summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
authorNobuhiro Iwamatsu <iwamatsu@nigauri.org>2007-12-07 01:20:16 +0900
committerNobuhiro Iwamatsu <iwamatsu@nigauri.org>2007-12-07 01:20:16 +0900
commit521dcd30b9cc5b72cd27ae04104f19369251aa20 (patch)
treebc33710a3ae6f97f0dcae8f02fd6f3c91322d96d /drivers/video
parent260eea5676ca46903a335686cc020b29c4ca46fe (diff)
parent8d4f040a3c15036a6ea25a9c39e7d89fefa8440d (diff)
downloadu-boot-imx-521dcd30b9cc5b72cd27ae04104f19369251aa20.zip
u-boot-imx-521dcd30b9cc5b72cd27ae04104f19369251aa20.tar.gz
u-boot-imx-521dcd30b9cc5b72cd27ae04104f19369251aa20.tar.bz2
Merge git://www.denx.de/git/u-boot
Conflicts: drivers/Makefile
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Makefile53
-rw-r--r--drivers/video/ati_ids.h211
-rw-r--r--drivers/video/ati_radeon_fb.c488
-rw-r--r--drivers/video/ati_radeon_fb.h282
-rw-r--r--drivers/video/cfb_console.c1274
-rw-r--r--drivers/video/ct69000.c1286
-rw-r--r--drivers/video/sed13806.c310
-rw-r--r--drivers/video/sed156x.c566
-rw-r--r--drivers/video/sm501.c150
-rw-r--r--drivers/video/smiLynxEM.c858
-rw-r--r--drivers/video/videomodes.c208
-rw-r--r--drivers/video/videomodes.h88
12 files changed, 5774 insertions, 0 deletions
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
new file mode 100644
index 0000000..36611ec
--- /dev/null
+++ b/drivers/video/Makefile
@@ -0,0 +1,53 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)libvideo.a
+
+COBJS-y += ati_radeon_fb.o
+COBJS-y += cfb_console.o
+COBJS-y += ct69000.o
+COBJS-y += sed13806.o
+COBJS-y += sed156x.o
+COBJS-y += sm501.o
+COBJS-y += smiLynxEM.o
+COBJS-y += videomodes.o
+
+COBJS := $(COBJS-y)
+SRCS := $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(COBJS))
+
+all: $(LIB)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/video/ati_ids.h b/drivers/video/ati_ids.h
new file mode 100644
index 0000000..3e72a7d
--- /dev/null
+++ b/drivers/video/ati_ids.h
@@ -0,0 +1,211 @@
+/*
+ * ATI PCI IDs from XFree86, kept here to make sync'ing with
+ * XFree much simpler. Currently, this list is only used by
+ * radeonfb
+ */
+
+#define PCI_CHIP_RV380_3150 0x3150
+#define PCI_CHIP_RV380_3151 0x3151
+#define PCI_CHIP_RV380_3152 0x3152
+#define PCI_CHIP_RV380_3153 0x3153
+#define PCI_CHIP_RV380_3154 0x3154
+#define PCI_CHIP_RV380_3156 0x3156
+#define PCI_CHIP_RV380_3E50 0x3E50
+#define PCI_CHIP_RV380_3E51 0x3E51
+#define PCI_CHIP_RV380_3E52 0x3E52
+#define PCI_CHIP_RV380_3E53 0x3E53
+#define PCI_CHIP_RV380_3E54 0x3E54
+#define PCI_CHIP_RV380_3E56 0x3E56
+#define PCI_CHIP_RS100_4136 0x4136
+#define PCI_CHIP_RS200_4137 0x4137
+#define PCI_CHIP_R300_AD 0x4144
+#define PCI_CHIP_R300_AE 0x4145
+#define PCI_CHIP_R300_AF 0x4146
+#define PCI_CHIP_R300_AG 0x4147
+#define PCI_CHIP_R350_AH 0x4148
+#define PCI_CHIP_R350_AI 0x4149
+#define PCI_CHIP_R350_AJ 0x414A
+#define PCI_CHIP_R350_AK 0x414B
+#define PCI_CHIP_RV350_AP 0x4150
+#define PCI_CHIP_RV350_AQ 0x4151
+#define PCI_CHIP_RV360_AR 0x4152
+#define PCI_CHIP_RV350_AS 0x4153
+#define PCI_CHIP_RV350_AT 0x4154
+#define PCI_CHIP_RV350_AV 0x4156
+#define PCI_CHIP_MACH32 0x4158
+#define PCI_CHIP_RS250_4237 0x4237
+#define PCI_CHIP_R200_BB 0x4242
+#define PCI_CHIP_R200_BC 0x4243
+#define PCI_CHIP_RS100_4336 0x4336
+#define PCI_CHIP_RS200_4337 0x4337
+#define PCI_CHIP_MACH64CT 0x4354
+#define PCI_CHIP_MACH64CX 0x4358
+#define PCI_CHIP_RS250_4437 0x4437
+#define PCI_CHIP_MACH64ET 0x4554
+#define PCI_CHIP_MACH64GB 0x4742
+#define PCI_CHIP_MACH64GD 0x4744
+#define PCI_CHIP_MACH64GI 0x4749
+#define PCI_CHIP_MACH64GL 0x474C
+#define PCI_CHIP_MACH64GM 0x474D
+#define PCI_CHIP_MACH64GN 0x474E
+#define PCI_CHIP_MACH64GO 0x474F
+#define PCI_CHIP_MACH64GP 0x4750
+#define PCI_CHIP_MACH64GQ 0x4751
+#define PCI_CHIP_MACH64GR 0x4752
+#define PCI_CHIP_MACH64GS 0x4753
+#define PCI_CHIP_MACH64GT 0x4754
+#define PCI_CHIP_MACH64GU 0x4755
+#define PCI_CHIP_MACH64GV 0x4756
+#define PCI_CHIP_MACH64GW 0x4757
+#define PCI_CHIP_MACH64GX 0x4758
+#define PCI_CHIP_MACH64GY 0x4759
+#define PCI_CHIP_MACH64GZ 0x475A
+#define PCI_CHIP_RV250_Id 0x4964
+#define PCI_CHIP_RV250_Ie 0x4965
+#define PCI_CHIP_RV250_If 0x4966
+#define PCI_CHIP_RV250_Ig 0x4967
+#define PCI_CHIP_R420_JH 0x4A48
+#define PCI_CHIP_R420_JI 0x4A49
+#define PCI_CHIP_R420_JJ 0x4A4A
+#define PCI_CHIP_R420_JK 0x4A4B
+#define PCI_CHIP_R420_JL 0x4A4C
+#define PCI_CHIP_R420_JM 0x4A4D
+#define PCI_CHIP_R420_JN 0x4A4E
+#define PCI_CHIP_R420_JP 0x4A50
+#define PCI_CHIP_MACH64LB 0x4C42
+#define PCI_CHIP_MACH64LD 0x4C44
+#define PCI_CHIP_RAGE128LE 0x4C45
+#define PCI_CHIP_RAGE128LF 0x4C46
+#define PCI_CHIP_MACH64LG 0x4C47
+#define PCI_CHIP_MACH64LI 0x4C49
+#define PCI_CHIP_MACH64LM 0x4C4D
+#define PCI_CHIP_MACH64LN 0x4C4E
+#define PCI_CHIP_MACH64LP 0x4C50
+#define PCI_CHIP_MACH64LQ 0x4C51
+#define PCI_CHIP_MACH64LR 0x4C52
+#define PCI_CHIP_MACH64LS 0x4C53
+#define PCI_CHIP_MACH64LT 0x4C54
+#define PCI_CHIP_RADEON_LW 0x4C57
+#define PCI_CHIP_RADEON_LX 0x4C58
+#define PCI_CHIP_RADEON_LY 0x4C59
+#define PCI_CHIP_RADEON_LZ 0x4C5A
+#define PCI_CHIP_RV250_Ld 0x4C64
+#define PCI_CHIP_RV250_Le 0x4C65
+#define PCI_CHIP_RV250_Lf 0x4C66
+#define PCI_CHIP_RV250_Lg 0x4C67
+#define PCI_CHIP_RV250_Ln 0x4C6E
+#define PCI_CHIP_RAGE128MF 0x4D46
+#define PCI_CHIP_RAGE128ML 0x4D4C
+#define PCI_CHIP_R300_ND 0x4E44
+#define PCI_CHIP_R300_NE 0x4E45
+#define PCI_CHIP_R300_NF 0x4E46
+#define PCI_CHIP_R300_NG 0x4E47
+#define PCI_CHIP_R350_NH 0x4E48
+#define PCI_CHIP_R350_NI 0x4E49
+#define PCI_CHIP_R360_NJ 0x4E4A
+#define PCI_CHIP_R350_NK 0x4E4B
+#define PCI_CHIP_RV350_NP 0x4E50
+#define PCI_CHIP_RV350_NQ 0x4E51
+#define PCI_CHIP_RV350_NR 0x4E52
+#define PCI_CHIP_RV350_NS 0x4E53
+#define PCI_CHIP_RV350_NT 0x4E54
+#define PCI_CHIP_RV350_NV 0x4E56
+#define PCI_CHIP_RAGE128PA 0x5041
+#define PCI_CHIP_RAGE128PB 0x5042
+#define PCI_CHIP_RAGE128PC 0x5043
+#define PCI_CHIP_RAGE128PD 0x5044
+#define PCI_CHIP_RAGE128PE 0x5045
+#define PCI_CHIP_RAGE128PF 0x5046
+#define PCI_CHIP_RAGE128PG 0x5047
+#define PCI_CHIP_RAGE128PH 0x5048
+#define PCI_CHIP_RAGE128PI 0x5049
+#define PCI_CHIP_RAGE128PJ 0x504A
+#define PCI_CHIP_RAGE128PK 0x504B
+#define PCI_CHIP_RAGE128PL 0x504C
+#define PCI_CHIP_RAGE128PM 0x504D
+#define PCI_CHIP_RAGE128PN 0x504E
+#define PCI_CHIP_RAGE128PO 0x504F
+#define PCI_CHIP_RAGE128PP 0x5050
+#define PCI_CHIP_RAGE128PQ 0x5051
+#define PCI_CHIP_RAGE128PR 0x5052
+#define PCI_CHIP_RAGE128PS 0x5053
+#define PCI_CHIP_RAGE128PT 0x5054
+#define PCI_CHIP_RAGE128PU 0x5055
+#define PCI_CHIP_RAGE128PV 0x5056
+#define PCI_CHIP_RAGE128PW 0x5057
+#define PCI_CHIP_RAGE128PX 0x5058
+#define PCI_CHIP_RADEON_QD 0x5144
+#define PCI_CHIP_RADEON_QE 0x5145
+#define PCI_CHIP_RADEON_QF 0x5146
+#define PCI_CHIP_RADEON_QG 0x5147
+#define PCI_CHIP_R200_QH 0x5148
+#define PCI_CHIP_R200_QI 0x5149
+#define PCI_CHIP_R200_QJ 0x514A
+#define PCI_CHIP_R200_QK 0x514B
+#define PCI_CHIP_R200_QL 0x514C
+#define PCI_CHIP_R200_QM 0x514D
+#define PCI_CHIP_R200_QN 0x514E
+#define PCI_CHIP_R200_QO 0x514F
+#define PCI_CHIP_RV200_QW 0x5157
+#define PCI_CHIP_RV200_QX 0x5158
+#define PCI_CHIP_RV100_QY 0x5159
+#define PCI_CHIP_RV100_QZ 0x515A
+#define PCI_CHIP_RN50 0x515E
+#define PCI_CHIP_RAGE128RE 0x5245
+#define PCI_CHIP_RAGE128RF 0x5246
+#define PCI_CHIP_RAGE128RG 0x5247
+#define PCI_CHIP_RAGE128RK 0x524B
+#define PCI_CHIP_RAGE128RL 0x524C
+#define PCI_CHIP_RAGE128SE 0x5345
+#define PCI_CHIP_RAGE128SF 0x5346
+#define PCI_CHIP_RAGE128SG 0x5347
+#define PCI_CHIP_RAGE128SH 0x5348
+#define PCI_CHIP_RAGE128SK 0x534B
+#define PCI_CHIP_RAGE128SL 0x534C
+#define PCI_CHIP_RAGE128SM 0x534D
+#define PCI_CHIP_RAGE128SN 0x534E
+#define PCI_CHIP_RAGE128TF 0x5446
+#define PCI_CHIP_RAGE128TL 0x544C
+#define PCI_CHIP_RAGE128TR 0x5452
+#define PCI_CHIP_RAGE128TS 0x5453
+#define PCI_CHIP_RAGE128TT 0x5454
+#define PCI_CHIP_RAGE128TU 0x5455
+#define PCI_CHIP_RV370_5460 0x5460
+#define PCI_CHIP_RV370_5461 0x5461
+#define PCI_CHIP_RV370_5462 0x5462
+#define PCI_CHIP_RV370_5463 0x5463
+#define PCI_CHIP_RV370_5464 0x5464
+#define PCI_CHIP_RV370_5465 0x5465
+#define PCI_CHIP_RV370_5466 0x5466
+#define PCI_CHIP_RV370_5467 0x5467
+#define PCI_CHIP_R423_UH 0x5548
+#define PCI_CHIP_R423_UI 0x5549
+#define PCI_CHIP_R423_UJ 0x554A
+#define PCI_CHIP_R423_UK 0x554B
+#define PCI_CHIP_R423_UQ 0x5551
+#define PCI_CHIP_R423_UR 0x5552
+#define PCI_CHIP_R423_UT 0x5554
+#define PCI_CHIP_MACH64VT 0x5654
+#define PCI_CHIP_MACH64VU 0x5655
+#define PCI_CHIP_MACH64VV 0x5656
+#define PCI_CHIP_RS300_5834 0x5834
+#define PCI_CHIP_RS300_5835 0x5835
+#define PCI_CHIP_RS300_5836 0x5836
+#define PCI_CHIP_RS300_5837 0x5837
+#define PCI_CHIP_RV370_5B60 0x5B60
+#define PCI_CHIP_RV370_5B61 0x5B61
+#define PCI_CHIP_RV370_5B62 0x5B62
+#define PCI_CHIP_RV370_5B63 0x5B63
+#define PCI_CHIP_RV370_5B64 0x5B64
+#define PCI_CHIP_RV370_5B65 0x5B65
+#define PCI_CHIP_RV370_5B66 0x5B66
+#define PCI_CHIP_RV370_5B67 0x5B67
+#define PCI_CHIP_RV280_5960 0x5960
+#define PCI_CHIP_RV280_5961 0x5961
+#define PCI_CHIP_RV280_5962 0x5962
+#define PCI_CHIP_RV280_5964 0x5964
+#define PCI_CHIP_RV280_5C61 0x5C61
+#define PCI_CHIP_RV280_5C63 0x5C63
+#define PCI_CHIP_R423_5D57 0x5D57
+#define PCI_CHIP_RS350_7834 0x7834
+#define PCI_CHIP_RS350_7835 0x7835
diff --git a/drivers/video/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c
new file mode 100644
index 0000000..0bdaa1c
--- /dev/null
+++ b/drivers/video/ati_radeon_fb.c
@@ -0,0 +1,488 @@
+/*
+ * ATI Radeon Video card Framebuffer driver.
+ *
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ * Zhang Wei <wei.zhang@freescale.com>
+ * Jason Jin <jason.jin@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Some codes of this file is partly ported from Linux kernel
+ * ATI video framebuffer driver.
+ *
+ * Now the driver is tested on below ATI chips:
+ * 9200
+ * X300
+ * X700
+ *
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_ATI_RADEON_FB
+
+#include <command.h>
+#include <pci.h>
+#include <asm/processor.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <video_fb.h>
+
+#include <radeon.h>
+#include "ati_ids.h"
+#include "ati_radeon_fb.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DPRINT(x...) printf(x)
+#else
+#define DPRINT(x...) do{}while(0)
+#endif
+
+#ifndef min_t
+#define min_t(type,x,y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
+#endif
+
+#define MAX_MAPPED_VRAM (2048*2048*4)
+#define MIN_MAPPED_VRAM (1024*768*1)
+
+/*#define PCI_VENDOR_ID_ATI*/
+#define PCI_CHIP_RV280_5960 0x5960
+#define PCI_CHIP_RV280_5961 0x5961
+#define PCI_CHIP_RV280_5962 0x5962
+#define PCI_CHIP_RV280_5964 0x5964
+#define PCI_CHIP_RV370_5B60 0x5B60
+#define PCI_CHIP_RV380_5657 0x5657
+#define PCI_CHIP_R420_554d 0x554d
+
+static struct pci_device_id ati_radeon_pci_ids[] = {
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5960},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5961},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5962},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5964},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV370_5B60},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_RV380_5657},
+ {PCI_VENDOR_ID_ATI, PCI_CHIP_R420_554d},
+ {0, 0}
+};
+
+static u16 ati_radeon_id_family_table[][2] = {
+ {PCI_CHIP_RV280_5960, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV280_5961, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV280_5962, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV280_5964, CHIP_FAMILY_RV280},
+ {PCI_CHIP_RV370_5B60, CHIP_FAMILY_RV380},
+ {PCI_CHIP_RV380_5657, CHIP_FAMILY_RV380},
+ {PCI_CHIP_R420_554d, CHIP_FAMILY_R420},
+ {0, 0}
+};
+
+u16 get_radeon_id_family(u16 device)
+{
+ int i;
+ for (i=0; ati_radeon_id_family_table[0][i]; i+=2)
+ if (ati_radeon_id_family_table[0][i] == device)
+ return ati_radeon_id_family_table[0][i + 1];
+ return 0;
+}
+
+struct radeonfb_info *rinfo;
+
+static void radeon_identify_vram(struct radeonfb_info *rinfo)
+{
+ u32 tmp;
+
+ /* framebuffer size */
+ if ((rinfo->family == CHIP_FAMILY_RS100) ||
+ (rinfo->family == CHIP_FAMILY_RS200) ||
+ (rinfo->family == CHIP_FAMILY_RS300)) {
+ u32 tom = INREG(NB_TOM);
+ tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+
+ radeon_fifo_wait(6);
+ OUTREG(MC_FB_LOCATION, tom);
+ OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+ OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+ OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
+
+ /* This is supposed to fix the crtc2 noise problem. */
+ OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+ if ((rinfo->family == CHIP_FAMILY_RS100) ||
+ (rinfo->family == CHIP_FAMILY_RS200)) {
+ /* This is to workaround the asic bug for RMX, some versions
+ of BIOS dosen't have this register initialized correctly.
+ */
+ OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
+ ~CRTC_H_CUTOFF_ACTIVE_EN);
+ }
+ } else {
+ tmp = INREG(CONFIG_MEMSIZE);
+ }
+
+ /* mem size is bits [28:0], mask off the rest */
+ rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
+
+ /*
+ * Hack to get around some busted production M6's
+ * reporting no ram
+ */
+ if (rinfo->video_ram == 0) {
+ switch (rinfo->pdev.device) {
+ case PCI_CHIP_RADEON_LY:
+ case PCI_CHIP_RADEON_LZ:
+ rinfo->video_ram = 8192 * 1024;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Now try to identify VRAM type
+ */
+ if ((rinfo->family >= CHIP_FAMILY_R300) ||
+ (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
+ rinfo->vram_ddr = 1;
+ else
+ rinfo->vram_ddr = 0;
+
+ tmp = INREG(MEM_CNTL);
+ if (IS_R300_VARIANT(rinfo)) {
+ tmp &= R300_MEM_NUM_CHANNELS_MASK;
+ switch (tmp) {
+ case 0: rinfo->vram_width = 64; break;
+ case 1: rinfo->vram_width = 128; break;
+ case 2: rinfo->vram_width = 256; break;
+ default: rinfo->vram_width = 128; break;
+ }
+ } else if ((rinfo->family == CHIP_FAMILY_RV100) ||
+ (rinfo->family == CHIP_FAMILY_RS100) ||
+ (rinfo->family == CHIP_FAMILY_RS200)){
+ if (tmp & RV100_MEM_HALF_MODE)
+ rinfo->vram_width = 32;
+ else
+ rinfo->vram_width = 64;
+ } else {
+ if (tmp & MEM_NUM_CHANNELS_MASK)
+ rinfo->vram_width = 128;
+ else
+ rinfo->vram_width = 64;
+ }
+
+ /* This may not be correct, as some cards can have half of channel disabled
+ * ToDo: identify these cases
+ */
+
+ DPRINT("radeonfb: Found %ldk of %s %d bits wide videoram\n",
+ rinfo->video_ram / 1024,
+ rinfo->vram_ddr ? "DDR" : "SDRAM",
+ rinfo->vram_width);
+
+}
+
+static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
+{
+ int i;
+
+ radeon_fifo_wait(20);
+
+#if 0
+ /* Workaround from XFree */
+ if (rinfo->is_mobility) {
+ /* A temporal workaround for the occational blanking on certain laptop
+ * panels. This appears to related to the PLL divider registers
+ * (fail to lock?). It occurs even when all dividers are the same
+ * with their old settings. In this case we really don't need to
+ * fiddle with PLL registers. By doing this we can avoid the blanking
+ * problem with some panels.
+ */
+ if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
+ (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
+ (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
+ /* We still have to force a switch to selected PPLL div thanks to
+ * an XFree86 driver bug which will switch it away in some cases
+ * even when using UseFDev */
+ OUTREGP(CLOCK_CNTL_INDEX,
+ mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+ ~PPLL_DIV_SEL_MASK);
+ radeon_pll_errata_after_index(rinfo);
+ radeon_pll_errata_after_data(rinfo);
+ return;
+ }
+ }
+#endif
+ if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
+
+ /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
+ OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
+
+ /* Reset PPLL & enable atomic update */
+ OUTPLLP(PPLL_CNTL,
+ PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
+ ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ /* Switch to selected PPLL divider */
+ OUTREGP(CLOCK_CNTL_INDEX,
+ mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
+ ~PPLL_DIV_SEL_MASK);
+
+ /* Set PPLL ref. div */
+ if (rinfo->family == CHIP_FAMILY_R300 ||
+ rinfo->family == CHIP_FAMILY_RS300 ||
+ rinfo->family == CHIP_FAMILY_R350 ||
+ rinfo->family == CHIP_FAMILY_RV350) {
+ if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
+ /* When restoring console mode, use saved PPLL_REF_DIV
+ * setting.
+ */
+ OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
+ } else {
+ /* R300 uses ref_div_acc field as real ref divider */
+ OUTPLLP(PPLL_REF_DIV,
+ (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
+ ~R300_PPLL_REF_DIV_ACC_MASK);
+ }
+ } else
+ OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
+
+ /* Set PPLL divider 3 & post divider*/
+ OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
+ OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
+
+ /* Write update */
+ while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
+ ;
+ OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
+
+ /* Wait read update complete */
+ /* FIXME: Certain revisions of R300 can't recover here. Not sure of
+ the cause yet, but this workaround will mask the problem for now.
+ Other chips usually will pass at the very first test, so the
+ workaround shouldn't have any effect on them. */
+ for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
+ ;
+
+ OUTPLL(HTOTAL_CNTL, 0);
+
+ /* Clear reset & atomic update */
+ OUTPLLP(PPLL_CNTL, 0,
+ ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
+
+ /* We may want some locking ... oh well */
+ udelay(5000);
+
+ /* Switch back VCLK source to PPLL */
+ OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
+}
+
+typedef struct {
+ u16 reg;
+ u32 val;
+} reg_val;
+
+#if 0 /* unused ? -> scheduled for removal */
+/* these common regs are cleared before mode setting so they do not
+ * interfere with anything
+ */
+static reg_val common_regs[] = {
+ { OVR_CLR, 0 },
+ { OVR_WID_LEFT_RIGHT, 0 },
+ { OVR_WID_TOP_BOTTOM, 0 },
+ { OV0_SCALE_CNTL, 0 },
+ { SUBPIC_CNTL, 0 },
+ { VIPH_CONTROL, 0 },
+ { I2C_CNTL_1, 0 },
+ { GEN_INT_CNTL, 0 },
+ { CAP0_TRIG_CNTL, 0 },
+ { CAP1_TRIG_CNTL, 0 },
+};
+#endif /* 0 */
+
+void radeon_setmode(void)
+{
+ struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
+
+ mode->crtc_gen_cntl = 0x03000200;
+ mode->crtc_ext_cntl = 0x00008048;
+ mode->dac_cntl = 0xff002100;
+ mode->crtc_h_total_disp = 0x4f0063;
+ mode->crtc_h_sync_strt_wid = 0x8c02a2;
+ mode->crtc_v_total_disp = 0x01df020c;
+ mode->crtc_v_sync_strt_wid = 0x8201ea;
+ mode->crtc_pitch = 0x00500050;
+
+ OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
+ OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
+ ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
+ OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
+ OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
+ OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
+ OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
+ OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
+ OUTREG(CRTC_OFFSET, 0);
+ OUTREG(CRTC_OFFSET_CNTL, 0);
+ OUTREG(CRTC_PITCH, mode->crtc_pitch);
+
+ mode->clk_cntl_index = 0x300;
+ mode->ppll_ref_div = 0xc;
+ mode->ppll_div_3 = 0x00030059;
+
+ radeon_write_pll_regs(rinfo, mode);
+}
+
+#include "../bios_emulator/include/biosemu.h"
+extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
+
+int radeon_probe(struct radeonfb_info *rinfo)
+{
+ pci_dev_t pdev;
+ u16 did;
+
+ pdev = pci_find_devices(ati_radeon_pci_ids, 0);
+
+ if (pdev != -1) {
+ pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
+ printf("ATI Radeon video card (%04x, %04x) found @(%d:%d:%d)\n",
+ PCI_VENDOR_ID_ATI, did, (pdev >> 16) & 0xff,
+ (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
+
+ strcpy(rinfo->name, "ATI Radeon");
+ rinfo->pdev.vendor = PCI_VENDOR_ID_ATI;
+ rinfo->pdev.device = did;
+ rinfo->family = get_radeon_id_family(rinfo->pdev.device);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
+ &rinfo->fb_base_phys);
+ pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
+ &rinfo->mmio_base_phys);
+ rinfo->fb_base_phys &= 0xfffff000;
+ rinfo->mmio_base_phys &= ~0x04;
+
+ rinfo->mmio_base = (void *)rinfo->mmio_base_phys;
+ DPRINT("rinfo->mmio_base = 0x%x\n",rinfo->mmio_base);
+ rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
+ DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base);
+ /* PostBIOS with x86 emulater */
+ BootVideoCardBIOS(pdev, NULL, 0);
+
+ /*
+ * Check for errata
+ * (These will be added in the future for the chipfamily
+ * R300, RV200, RS200, RV100, RS100.)
+ */
+
+ /* Get VRAM size and type */
+ radeon_identify_vram(rinfo);
+
+ rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
+ rinfo->video_ram);
+ rinfo->fb_base = (void *)rinfo->fb_base_phys;
+
+ DPRINT("Radeon: framebuffer base phy address 0x%08x," \
+ "MMIO base phy address 0x%08x," \
+ "framebuffer local base 0x%08x.\n ",
+ rinfo->fb_base_phys, rinfo->mmio_base_phys,
+ rinfo->fb_local_base);
+
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+#define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */
+#define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */
+#define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */
+#define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */
+
+void *video_hw_init(void)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ int i;
+ u32 *vm;
+
+ rinfo = malloc(sizeof(struct radeonfb_info));
+
+ if(radeon_probe(rinfo)) {
+ printf("No radeon video card found!\n");
+ return NULL;
+ }
+
+ /* fill in Graphic device struct */
+ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", 640,
+ 480, 16, (1000 / 1000),
+ (2000 / 1000));
+ printf ("%s\n", pGD->modeIdent);
+
+ pGD->winSizeX = 640;
+ pGD->winSizeY = 480;
+ pGD->plnSizeX = 640;
+ pGD->plnSizeY = 480;
+
+ pGD->gdfBytesPP = 1;
+ pGD->gdfIndex = GDF__8BIT_INDEX;
+
+ pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
+ pGD->pciBase = rinfo->fb_base_phys;
+ pGD->frameAdrs = rinfo->fb_base_phys;
+ pGD->memSize = 64 * 1024 * 1024;
+
+ /* Cursor Start Address */
+ pGD->dprBase =
+ (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + rinfo->fb_base_phys;
+ if ((pGD->dprBase & 0x0fff) != 0) {
+ /* allign it */
+ pGD->dprBase &= 0xfffff000;
+ pGD->dprBase += 0x00001000;
+ }
+ DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
+ PATTERN_ADR);
+ pGD->vprBase = rinfo->fb_base_phys; /* Dummy */
+ pGD->cprBase = rinfo->fb_base_phys; /* Dummy */
+ /* set up Hardware */
+
+ /* Clear video memory */
+ i = pGD->memSize / 4;
+ vm = (unsigned int *) pGD->pciBase;
+ while (i--)
+ *vm++ = 0;
+ /*SetDrawingEngine (bits_per_pixel);*/
+
+ radeon_setmode();
+
+ return ((void *) pGD);
+}
+
+void video_set_lut (unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+ OUTREG(PALETTE_INDEX, index);
+ OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
+}
+#endif
diff --git a/drivers/video/ati_radeon_fb.h b/drivers/video/ati_radeon_fb.h
new file mode 100644
index 0000000..b5c4b8b
--- /dev/null
+++ b/drivers/video/ati_radeon_fb.h
@@ -0,0 +1,282 @@
+#ifndef __ATI_RADEON_FB_H
+#define __ATI_RADEON_FB_H
+
+/***************************************************************
+ * Most of the definitions here are adapted right from XFree86 *
+ ***************************************************************/
+
+/*
+ * Chip families. Must fit in the low 16 bits of a long word
+ */
+enum radeon_family {
+ CHIP_FAMILY_UNKNOW,
+ CHIP_FAMILY_LEGACY,
+ CHIP_FAMILY_RADEON,
+ CHIP_FAMILY_RV100,
+ CHIP_FAMILY_RS100, /* U1 (IGP320M) or A3 (IGP320)*/
+ CHIP_FAMILY_RV200,
+ CHIP_FAMILY_RS200, /* U2 (IGP330M/340M/350M) or A4 (IGP330/340/345/350),
+ RS250 (IGP 7000) */
+ CHIP_FAMILY_R200,
+ CHIP_FAMILY_RV250,
+ CHIP_FAMILY_RS300, /* Radeon 9000 IGP */
+ CHIP_FAMILY_RV280,
+ CHIP_FAMILY_R300,
+ CHIP_FAMILY_R350,
+ CHIP_FAMILY_RV350,
+ CHIP_FAMILY_RV380, /* RV370/RV380/M22/M24 */
+ CHIP_FAMILY_R420, /* R420/R423/M18 */
+ CHIP_FAMILY_LAST,
+};
+
+#define IS_RV100_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_RV100) || \
+ ((rinfo)->family == CHIP_FAMILY_RV200) || \
+ ((rinfo)->family == CHIP_FAMILY_RS100) || \
+ ((rinfo)->family == CHIP_FAMILY_RS200) || \
+ ((rinfo)->family == CHIP_FAMILY_RV250) || \
+ ((rinfo)->family == CHIP_FAMILY_RV280) || \
+ ((rinfo)->family == CHIP_FAMILY_RS300))
+
+#define IS_R300_VARIANT(rinfo) (((rinfo)->family == CHIP_FAMILY_R300) || \
+ ((rinfo)->family == CHIP_FAMILY_RV350) || \
+ ((rinfo)->family == CHIP_FAMILY_R350) || \
+ ((rinfo)->family == CHIP_FAMILY_RV380) || \
+ ((rinfo)->family == CHIP_FAMILY_R420))
+
+struct radeonfb_info {
+ char name[20];
+
+ struct pci_device_id pdev;
+ u16 family;
+
+ u32 fb_base_phys;
+ u32 mmio_base_phys;
+
+ void *mmio_base;
+ void *fb_base;
+
+ u32 video_ram;
+ u32 mapped_vram;
+ int vram_width;
+ int vram_ddr;
+
+ u32 fb_local_base;
+};
+
+#define INREG8(addr) readb((rinfo->mmio_base)+addr)
+#define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr)
+#define INREG16(addr) readw((rinfo->mmio_base)+addr)
+#define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr)
+#define INREG(addr) readl((rinfo->mmio_base)+addr)
+#define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr)
+
+static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr,
+ u32 val, u32 mask)
+{
+ unsigned int tmp;
+
+ tmp = INREG(addr);
+ tmp &= (mask);
+ tmp |= (val);
+ OUTREG(addr, tmp);
+}
+
+#define OUTREGP(addr,val,mask) _OUTREGP(rinfo, addr, val,mask)
+
+/*
+ * 2D Engine helper routines
+ */
+static inline void radeon_engine_flush (struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* initiate flush */
+ OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
+ ~RB2D_DC_FLUSH_ALL);
+
+ for (i=0; i < 2000000; i++) {
+ if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
+ return;
+ udelay(1);
+ }
+ printf("radeonfb: Flush Timeout !\n");
+}
+
+static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries)
+{
+ int i;
+
+ for (i=0; i<2000000; i++) {
+ if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
+ return;
+ udelay(1);
+ }
+ printf("radeonfb: FIFO Timeout !\n");
+}
+
+static inline void _radeon_engine_idle(struct radeonfb_info *rinfo)
+{
+ int i;
+
+ /* ensure FIFO is empty before waiting for idle */
+ _radeon_fifo_wait (rinfo, 64);
+
+ for (i=0; i<2000000; i++) {
+ if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) {
+ radeon_engine_flush (rinfo);
+ return;
+ }
+ udelay(1);
+ }
+ printf("radeonfb: Idle Timeout !\n");
+}
+
+#define radeon_engine_idle() _radeon_engine_idle(rinfo)
+#define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries)
+#define radeon_msleep(ms) _radeon_msleep(rinfo,ms)
+
+/*
+ * This structure contains the various registers manipulated by this
+ * driver for setting or restoring a mode. It's mostly copied from
+ * XFree's RADEONSaveRec structure. A few chip settings might still be
+ * tweaked without beeing reflected or saved in these registers though
+ */
+struct radeon_regs {
+ /* Common registers */
+ u32 ovr_clr;
+ u32 ovr_wid_left_right;
+ u32 ovr_wid_top_bottom;
+ u32 ov0_scale_cntl;
+ u32 mpp_tb_config;
+ u32 mpp_gp_config;
+ u32 subpic_cntl;
+ u32 viph_control;
+ u32 i2c_cntl_1;
+ u32 gen_int_cntl;
+ u32 cap0_trig_cntl;
+ u32 cap1_trig_cntl;
+ u32 bus_cntl;
+ u32 surface_cntl;
+ u32 bios_5_scratch;
+
+ /* Other registers to save for VT switches or driver load/unload */
+ u32 dp_datatype;
+ u32 rbbm_soft_reset;
+ u32 clock_cntl_index;
+ u32 amcgpio_en_reg;
+ u32 amcgpio_mask;
+
+ /* Surface/tiling registers */
+ u32 surf_lower_bound[8];
+ u32 surf_upper_bound[8];
+ u32 surf_info[8];
+
+ /* CRTC registers */
+ u32 crtc_gen_cntl;
+ u32 crtc_ext_cntl;
+ u32 dac_cntl;
+ u32 crtc_h_total_disp;
+ u32 crtc_h_sync_strt_wid;
+ u32 crtc_v_total_disp;
+ u32 crtc_v_sync_strt_wid;
+ u32 crtc_offset;
+ u32 crtc_offset_cntl;
+ u32 crtc_pitch;
+ u32 disp_merge_cntl;
+ u32 grph_buffer_cntl;
+ u32 crtc_more_cntl;
+
+ /* CRTC2 registers */
+ u32 crtc2_gen_cntl;
+ u32 dac2_cntl;
+ u32 disp_output_cntl;
+ u32 disp_hw_debug;
+ u32 disp2_merge_cntl;
+ u32 grph2_buffer_cntl;
+ u32 crtc2_h_total_disp;
+ u32 crtc2_h_sync_strt_wid;
+ u32 crtc2_v_total_disp;
+ u32 crtc2_v_sync_strt_wid;
+ u32 crtc2_offset;
+ u32 crtc2_offset_cntl;
+ u32 crtc2_pitch;
+
+ /* Flat panel regs */
+ u32 fp_crtc_h_total_disp;
+ u32 fp_crtc_v_total_disp;
+ u32 fp_gen_cntl;
+ u32 fp2_gen_cntl;
+ u32 fp_h_sync_strt_wid;
+ u32 fp2_h_sync_strt_wid;
+ u32 fp_horz_stretch;
+ u32 fp_panel_cntl;
+ u32 fp_v_sync_strt_wid;
+ u32 fp2_v_sync_strt_wid;
+ u32 fp_vert_stretch;
+ u32 lvds_gen_cntl;
+ u32 lvds_pll_cntl;
+ u32 tmds_crc;
+ u32 tmds_transmitter_cntl;
+
+ /* Computed values for PLL */
+ u32 dot_clock_freq;
+ int feedback_div;
+ int post_div;
+
+ /* PLL registers */
+ u32 ppll_div_3;
+ u32 ppll_ref_div;
+ u32 vclk_ecp_cntl;
+ u32 clk_cntl_index;
+
+ /* Computed values for PLL2 */
+ u32 dot_clock_freq_2;
+ int feedback_div_2;
+ int post_div_2;
+
+ /* PLL2 registers */
+ u32 p2pll_ref_div;
+ u32 p2pll_div_0;
+ u32 htotal_cntl2;
+
+ /* Palette */
+ int palette_valid;
+};
+
+static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
+{
+ u32 data;
+
+ OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
+ /* radeon_pll_errata_after_index(rinfo); */
+ data = INREG(CLOCK_CNTL_DATA);
+ /* radeon_pll_errata_after_data(rinfo); */
+ return data;
+}
+
+static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val)
+{
+
+ OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+ /* radeon_pll_errata_after_index(rinfo); */
+ OUTREG(CLOCK_CNTL_DATA, val);
+ /* radeon_pll_errata_after_data(rinfo); */
+}
+
+static inline void __OUTPLLP(struct radeonfb_info *rinfo, unsigned int index,
+ u32 val, u32 mask)
+{
+ unsigned int tmp;
+
+ tmp = __INPLL(rinfo, index);
+ tmp &= (mask);
+ tmp |= (val);
+ __OUTPLL(rinfo, index, tmp);
+}
+
+#define INPLL(addr) __INPLL(rinfo, addr)
+#define OUTPLL(index, val) __OUTPLL(rinfo, index, val)
+#define OUTPLLP(index, val, mask) __OUTPLLP(rinfo, index, val, mask)
+
+#endif
diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c
new file mode 100644
index 0000000..bcf8771
--- /dev/null
+++ b/drivers/video/cfb_console.c
@@ -0,0 +1,1274 @@
+/*
+ * (C) Copyright 2002 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * cfb_console.c
+ *
+ * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
+ *
+ * At the moment only the 8x16 font is tested and the font fore- and
+ * background color is limited to black/white/gray colors. The Linux
+ * logo can be placed in the upper left corner and additional board
+ * information strings (that normaly goes to serial port) can be drawed.
+ *
+ * The console driver can use the standard PC keyboard interface (i8042)
+ * for character input. Character output goes to a memory mapped video
+ * framebuffer with little or big-endian organisation.
+ * With environment setting 'console=serial' the console i/o can be
+ * forced to serial port.
+
+ The driver uses graphic specific defines/parameters/functions:
+
+ (for SMI LynxE graphic chip)
+
+ CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810
+ VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian
+ VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill
+ VIDEO_HW_BITBLT - graphic driver supports hardware bit blt
+
+ Console Parameters are set by graphic drivers global struct:
+
+ VIDEO_VISIBLE_COLS - x resolution
+ VIDEO_VISIBLE_ROWS - y resolution
+ VIDEO_PIXEL_SIZE - storage size in byte per pixel
+ VIDEO_DATA_FORMAT - graphical data format GDF
+ VIDEO_FB_ADRS - start of video memory
+
+ CONFIG_I8042_KBD - AT Keyboard driver for i8042
+ VIDEO_KBD_INIT_FCT - init function for keyboard
+ VIDEO_TSTC_FCT - keyboard_tstc function
+ VIDEO_GETC_FCT - keyboard_getc function
+
+ CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with delay
+ loop in VIDEO_TSTC_FCT (i8042)
+ CFG_CONSOLE_BLINK_COUNT - value for delay loop - blink rate
+ CONFIG_CONSOLE_TIME - display time/date in upper right corner,
+ needs CONFIG_CMD_DATE and CONFIG_CONSOLE_CURSOR
+ CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner
+ CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
+ CONFIG_CONSOLE_EXTRA_INFO - display additional board information strings
+ that normaly goes to serial port. This define
+ requires a board specific function:
+ video_drawstring (VIDEO_INFO_X,
+ VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
+ info);
+ that fills a info buffer at i=row.
+ s.a: board/eltec/bab7xx.
+CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be initialised
+ as an output only device. The Keyboard driver
+ will not be set-up. This may be used, if you
+ have none or more than one Keyboard devices
+ (USB Keyboard, AT Keyboard).
+
+CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last character. No
+ blinking is provided. Uses the macros CURSOR_SET
+ and CURSOR_OFF.
+CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the
+ graphic chip. Uses the macro CURSOR_SET.
+ ATTENTION: If booting an OS, the display driver
+ must disable the hardware register of the graphic
+ chip. Otherwise a blinking field is displayed
+*/
+
+#include <common.h>
+
+#ifdef CONFIG_CFB_CONSOLE
+
+#include <malloc.h>
+
+/*****************************************************************************/
+/* Console device defines with SMI graphic */
+/* Any other graphic must change this section */
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_SMI_LYNXEM
+
+#define VIDEO_FB_LITTLE_ENDIAN
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Defines for the CT69000 driver */
+/*****************************************************************************/
+#ifdef CONFIG_VIDEO_CT69000
+
+#define VIDEO_FB_LITTLE_ENDIAN
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Defines for the SED13806 driver */
+/*****************************************************************************/
+#ifdef CONFIG_VIDEO_SED13806
+
+#ifndef CONFIG_TOTAL5200
+#define VIDEO_FB_LITTLE_ENDIAN
+#endif
+#define VIDEO_HW_RECTFILL
+#define VIDEO_HW_BITBLT
+#endif
+
+/*****************************************************************************/
+/* Defines for the SED13806 driver */
+/*****************************************************************************/
+#ifdef CONFIG_VIDEO_SM501
+
+#ifdef CONFIG_HH405
+#define VIDEO_FB_LITTLE_ENDIAN
+#endif
+#endif
+
+/*****************************************************************************/
+/* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc */
+/*****************************************************************************/
+#include <video_fb.h>
+
+/*****************************************************************************/
+/* some Macros */
+/*****************************************************************************/
+#define VIDEO_VISIBLE_COLS (pGD->winSizeX)
+#define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
+#define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
+#define VIDEO_DATA_FORMAT (pGD->gdfIndex)
+#define VIDEO_FB_ADRS (pGD->frameAdrs)
+
+/*****************************************************************************/
+/* Console device defines with i8042 keyboard controller */
+/* Any other keyboard controller must change this section */
+/*****************************************************************************/
+
+#ifdef CONFIG_I8042_KBD
+#include <i8042.h>
+
+#define VIDEO_KBD_INIT_FCT i8042_kbd_init()
+#define VIDEO_TSTC_FCT i8042_tstc
+#define VIDEO_GETC_FCT i8042_getc
+#endif
+
+/*****************************************************************************/
+/* Console device */
+/*****************************************************************************/
+
+#include <version.h>
+#include <linux/types.h>
+#include <devices.h>
+#include <video_font.h>
+
+#if defined(CONFIG_CMD_DATE)
+#include <rtc.h>
+#endif
+
+#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
+#include <watchdog.h>
+#include <bmp_layout.h>
+#endif
+
+/*****************************************************************************/
+/* Cursor definition: */
+/* CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/i8042.c) to */
+/* let the cursor blink. Uses the macros CURSOR_OFF */
+/* and CURSOR_ON. */
+/* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No */
+/* blinking is provided. Uses the macros CURSOR_SET */
+/* and CURSOR_OFF. */
+/* CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the */
+/* graphic chip. Uses the macro CURSOR_SET. */
+/* ATTENTION: If booting an OS, the display driver */
+/* must disable the hardware register of the graphic */
+/* chip. Otherwise a blinking field is displayed */
+/*****************************************************************************/
+#if !defined(CONFIG_CONSOLE_CURSOR) && \
+ !defined(CONFIG_VIDEO_SW_CURSOR) && \
+ !defined(CONFIG_VIDEO_HW_CURSOR)
+/* no Cursor defined */
+#define CURSOR_ON
+#define CURSOR_OFF
+#define CURSOR_SET
+#endif
+
+#ifdef CONFIG_CONSOLE_CURSOR
+#ifdef CURSOR_ON
+#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+void console_cursor (int state);
+#define CURSOR_ON console_cursor(1);
+#define CURSOR_OFF console_cursor(0);
+#define CURSOR_SET
+#ifndef CONFIG_I8042_KBD
+#warning Cursor drawing on/off needs timer function s.a. drivers/i8042.c
+#endif
+#else
+#ifdef CONFIG_CONSOLE_TIME
+#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
+#endif
+#endif /* CONFIG_CONSOLE_CURSOR */
+
+#ifdef CONFIG_VIDEO_SW_CURSOR
+#ifdef CURSOR_ON
+#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+#define CURSOR_ON
+#define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\
+ console_row * VIDEO_FONT_HEIGHT, ' ');
+#define CURSOR_SET video_set_cursor();
+#endif /* CONFIG_VIDEO_SW_CURSOR */
+
+
+#ifdef CONFIG_VIDEO_HW_CURSOR
+#ifdef CURSOR_ON
+#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
+#endif
+#define CURSOR_ON
+#define CURSOR_OFF
+#define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
+ (console_row * VIDEO_FONT_HEIGHT) + VIDEO_LOGO_HEIGHT);
+#endif /* CONFIG_VIDEO_HW_CURSOR */
+
+#ifdef CONFIG_VIDEO_LOGO
+#ifdef CONFIG_VIDEO_BMP_LOGO
+#include <bmp_logo.h>
+#define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH
+#define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT
+#define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET
+#define VIDEO_LOGO_COLORS BMP_LOGO_COLORS
+
+#else /* CONFIG_VIDEO_BMP_LOGO */
+#define LINUX_LOGO_WIDTH 80
+#define LINUX_LOGO_HEIGHT 80
+#define LINUX_LOGO_COLORS 214
+#define LINUX_LOGO_LUT_OFFSET 0x20
+#define __initdata
+#include <linux_logo.h>
+#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
+#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
+#define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
+#define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
+#endif /* CONFIG_VIDEO_BMP_LOGO */
+#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
+#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
+#else /* CONFIG_VIDEO_LOGO */
+#define VIDEO_LOGO_WIDTH 0
+#define VIDEO_LOGO_HEIGHT 0
+#endif /* CONFIG_VIDEO_LOGO */
+
+#define VIDEO_COLS VIDEO_VISIBLE_COLS
+#define VIDEO_ROWS VIDEO_VISIBLE_ROWS
+#define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2)
+#define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE)
+#define VIDEO_BURST_LEN (VIDEO_COLS/8)
+
+#ifdef CONFIG_VIDEO_LOGO
+#define CONSOLE_ROWS ((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
+#else
+#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
+#endif
+
+#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
+#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
+#define CONSOLE_ROW_FIRST (video_console_address)
+#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
+#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
+#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+/* Macros */
+#ifdef VIDEO_FB_LITTLE_ENDIAN
+#define SWAP16(x) ((((x) & 0x00ff) << 8) | ( (x) >> 8))
+#define SWAP32(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
+ (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) )
+#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | (((x) & 0x0000ff00) >> 8)|\
+ (((x) & 0x00ff0000) << 8) | (((x) & 0xff000000) >> 8) )
+#else
+#define SWAP16(x) (x)
+#define SWAP32(x) (x)
+#define SHORTSWAP32(x) (x)
+#endif
+
+#if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE)
+#define PRINTD(x) printf(x)
+#else
+#define PRINTD(x)
+#endif
+
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+extern void video_get_info_str ( /* setup a board string: type, speed, etc. */
+ int line_number, /* location to place info string beside logo */
+ char *info /* buffer for info string */
+ );
+
+#endif
+
+/* Locals */
+static GraphicDevice *pGD; /* Pointer to Graphic array */
+
+static void *video_fb_address; /* frame buffer address */
+static void *video_console_address; /* console buffer start address */
+
+static int console_col = 0; /* cursor col */
+static int console_row = 0; /* cursor row */
+
+static u32 eorx, fgx, bgx; /* color pats */
+
+static const int video_font_draw_table8[] = {
+ 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
+ 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
+ 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
+ 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff };
+
+static const int video_font_draw_table15[] = {
+ 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff };
+
+static const int video_font_draw_table16[] = {
+ 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff };
+
+static const int video_font_draw_table24[16][3] = {
+ { 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00ffffff },
+ { 0x00000000, 0x0000ffff, 0xff000000 },
+ { 0x00000000, 0x0000ffff, 0xffffffff },
+ { 0x000000ff, 0xffff0000, 0x00000000 },
+ { 0x000000ff, 0xffff0000, 0x00ffffff },
+ { 0x000000ff, 0xffffffff, 0xff000000 },
+ { 0x000000ff, 0xffffffff, 0xffffffff },
+ { 0xffffff00, 0x00000000, 0x00000000 },
+ { 0xffffff00, 0x00000000, 0x00ffffff },
+ { 0xffffff00, 0x0000ffff, 0xff000000 },
+ { 0xffffff00, 0x0000ffff, 0xffffffff },
+ { 0xffffffff, 0xffff0000, 0x00000000 },
+ { 0xffffffff, 0xffff0000, 0x00ffffff },
+ { 0xffffffff, 0xffffffff, 0xff000000 },
+ { 0xffffffff, 0xffffffff, 0xffffffff } };
+
+static const int video_font_draw_table32[16][4] = {
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff },
+ { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 },
+ { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff },
+ { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 },
+ { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff },
+ { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 },
+ { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff },
+ { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff },
+ { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 },
+ { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff },
+ { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 },
+ { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff },
+ { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 },
+ { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } };
+
+
+int gunzip(void *, int, unsigned char *, unsigned long *);
+
+/******************************************************************************/
+
+static void video_drawchars (int xx, int yy, unsigned char *s, int count)
+{
+ u8 *cdat, *dest, *dest0;
+ int rows, offset, c;
+
+ offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
+ dest0 = video_fb_address + offset;
+
+ switch (VIDEO_DATA_FORMAT) {
+ case GDF__8BIT_INDEX:
+ case GDF__8BIT_332RGB:
+ while (count--) {
+ c = *s;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+ rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] = (video_font_draw_table8[bits >> 4] & eorx) ^ bgx;
+ ((u32 *) dest)[1] = (video_font_draw_table8[bits & 15] & eorx) ^ bgx;
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++;
+ }
+ break;
+
+ case GDF_15BIT_555RGB:
+ while (count--) {
+ c = *s;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+ rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 6] & eorx) ^ bgx);
+ ((u32 *) dest)[1] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 4 & 3] & eorx) ^ bgx);
+ ((u32 *) dest)[2] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 2 & 3] & eorx) ^ bgx);
+ ((u32 *) dest)[3] = SHORTSWAP32 ((video_font_draw_table15 [bits & 3] & eorx) ^ bgx);
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++;
+ }
+ break;
+
+ case GDF_16BIT_565RGB:
+ while (count--) {
+ c = *s;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+ rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 6] & eorx) ^ bgx);
+ ((u32 *) dest)[1] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 4 & 3] & eorx) ^ bgx);
+ ((u32 *) dest)[2] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 2 & 3] & eorx) ^ bgx);
+ ((u32 *) dest)[3] = SHORTSWAP32 ((video_font_draw_table16 [bits & 3] & eorx) ^ bgx);
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++;
+ }
+ break;
+
+ case GDF_32BIT_X888RGB:
+ while (count--) {
+ c = *s;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+ rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] = SWAP32 ((video_font_draw_table32 [bits >> 4][0] & eorx) ^ bgx);
+ ((u32 *) dest)[1] = SWAP32 ((video_font_draw_table32 [bits >> 4][1] & eorx) ^ bgx);
+ ((u32 *) dest)[2] = SWAP32 ((video_font_draw_table32 [bits >> 4][2] & eorx) ^ bgx);
+ ((u32 *) dest)[3] = SWAP32 ((video_font_draw_table32 [bits >> 4][3] & eorx) ^ bgx);
+ ((u32 *) dest)[4] = SWAP32 ((video_font_draw_table32 [bits & 15][0] & eorx) ^ bgx);
+ ((u32 *) dest)[5] = SWAP32 ((video_font_draw_table32 [bits & 15][1] & eorx) ^ bgx);
+ ((u32 *) dest)[6] = SWAP32 ((video_font_draw_table32 [bits & 15][2] & eorx) ^ bgx);
+ ((u32 *) dest)[7] = SWAP32 ((video_font_draw_table32 [bits & 15][3] & eorx) ^ bgx);
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++;
+ }
+ break;
+
+ case GDF_24BIT_888RGB:
+ while (count--) {
+ c = *s;
+ cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
+ for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
+ rows--;
+ dest += VIDEO_LINE_LEN) {
+ u8 bits = *cdat++;
+
+ ((u32 *) dest)[0] = (video_font_draw_table24[bits >> 4][0] & eorx) ^ bgx;
+ ((u32 *) dest)[1] = (video_font_draw_table24[bits >> 4][1] & eorx) ^ bgx;
+ ((u32 *) dest)[2] = (video_font_draw_table24[bits >> 4][2] & eorx) ^ bgx;
+ ((u32 *) dest)[3] = (video_font_draw_table24[bits & 15][0] & eorx) ^ bgx;
+ ((u32 *) dest)[4] = (video_font_draw_table24[bits & 15][1] & eorx) ^ bgx;
+ ((u32 *) dest)[5] = (video_font_draw_table24[bits & 15][2] & eorx) ^ bgx;
+ }
+ dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
+ s++;
+ }
+ break;
+ }
+}
+
+/*****************************************************************************/
+
+static inline void video_drawstring (int xx, int yy, unsigned char *s)
+{
+ video_drawchars (xx, yy, s, strlen ((char *)s));
+}
+
+/*****************************************************************************/
+
+static void video_putchar (int xx, int yy, unsigned char c)
+{
+ video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
+}
+
+/*****************************************************************************/
+#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
+static void video_set_cursor (void)
+{
+ /* swap drawing colors */
+ eorx = fgx;
+ fgx = bgx;
+ bgx = eorx;
+ eorx = fgx ^ bgx;
+ /* draw cursor */
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT,
+ ' ');
+ /* restore drawing colors */
+ eorx = fgx;
+ fgx = bgx;
+ bgx = eorx;
+ eorx = fgx ^ bgx;
+}
+#endif
+/*****************************************************************************/
+#ifdef CONFIG_CONSOLE_CURSOR
+void console_cursor (int state)
+{
+ static int last_state = 0;
+
+#ifdef CONFIG_CONSOLE_TIME
+ struct rtc_time tm;
+ char info[16];
+
+ /* time update only if cursor is on (faster scroll) */
+ if (state) {
+ rtc_get (&tm);
+
+ sprintf (info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
+ tm.tm_sec);
+ video_drawstring (VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
+ VIDEO_INFO_Y, (uchar *)info);
+
+ sprintf (info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
+ tm.tm_year);
+ video_drawstring (VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
+ VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT, (uchar *)info);
+ }
+#endif
+
+ if (state && (last_state != state)) {
+ video_set_cursor ();
+ }
+
+ if (!state && (last_state != state)) {
+ /* clear cursor */
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT,
+ ' ');
+ }
+
+ last_state = state;
+}
+#endif
+
+/*****************************************************************************/
+
+#ifndef VIDEO_HW_RECTFILL
+static void memsetl (int *p, int c, int v)
+{
+ while (c--)
+ *(p++) = v;
+}
+#endif
+
+/*****************************************************************************/
+
+#ifndef VIDEO_HW_BITBLT
+static void memcpyl (int *d, int *s, int c)
+{
+ while (c--)
+ *(d++) = *(s++);
+}
+#endif
+
+/*****************************************************************************/
+
+static void console_scrollup (void)
+{
+ /* copy up rows ignoring the first one */
+
+#ifdef VIDEO_HW_BITBLT
+ video_hw_bitblt (VIDEO_PIXEL_SIZE, /* bytes per pixel */
+ 0, /* source pos x */
+ VIDEO_LOGO_HEIGHT + VIDEO_FONT_HEIGHT, /* source pos y */
+ 0, /* dest pos x */
+ VIDEO_LOGO_HEIGHT, /* dest pos y */
+ VIDEO_VISIBLE_COLS, /* frame width */
+ VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT /* frame height */
+ );
+#else
+ memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
+ CONSOLE_SCROLL_SIZE >> 2);
+#endif
+
+ /* clear the last one */
+#ifdef VIDEO_HW_RECTFILL
+ video_hw_rectfill (VIDEO_PIXEL_SIZE, /* bytes per pixel */
+ 0, /* dest pos x */
+ VIDEO_VISIBLE_ROWS - VIDEO_FONT_HEIGHT, /* dest pos y */
+ VIDEO_VISIBLE_COLS, /* frame width */
+ VIDEO_FONT_HEIGHT, /* frame height */
+ CONSOLE_BG_COL /* fill color */
+ );
+#else
+ memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL);
+#endif
+}
+
+/*****************************************************************************/
+
+static void console_back (void)
+{
+ CURSOR_OFF console_col--;
+
+ if (console_col < 0) {
+ console_col = CONSOLE_COLS - 1;
+ console_row--;
+ if (console_row < 0)
+ console_row = 0;
+ }
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT,
+ ' ');
+}
+
+/*****************************************************************************/
+
+static void console_newline (void)
+{
+ CURSOR_OFF console_row++;
+ console_col = 0;
+
+ /* Check if we need to scroll the terminal */
+ if (console_row >= CONSOLE_ROWS) {
+ /* Scroll everything up */
+ console_scrollup ();
+
+ /* Decrement row number */
+ console_row--;
+ }
+}
+
+/*****************************************************************************/
+
+void video_putc (const char c)
+{
+ switch (c) {
+ case 13: /* ignore */
+ break;
+
+ case '\n': /* next line */
+ console_newline ();
+ break;
+
+ case 9: /* tab 8 */
+ CURSOR_OFF console_col |= 0x0008;
+ console_col &= ~0x0007;
+
+ if (console_col >= CONSOLE_COLS)
+ console_newline ();
+ break;
+
+ case 8: /* backspace */
+ console_back ();
+ break;
+
+ default: /* draw the char */
+ video_putchar (console_col * VIDEO_FONT_WIDTH,
+ console_row * VIDEO_FONT_HEIGHT,
+ c);
+ console_col++;
+
+ /* check for newline */
+ if (console_col >= CONSOLE_COLS)
+ console_newline ();
+ }
+CURSOR_SET}
+
+
+/*****************************************************************************/
+
+void video_puts (const char *s)
+{
+ int count = strlen (s);
+
+ while (count--)
+ video_putc (*s++);
+}
+
+/*****************************************************************************/
+
+#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
+
+#define FILL_8BIT_332RGB(r,g,b) { \
+ *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
+ fb ++; \
+}
+
+#define FILL_15BIT_555RGB(r,g,b) { \
+ *(unsigned short *)fb = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \
+ fb += 2; \
+}
+
+#define FILL_16BIT_565RGB(r,g,b) { \
+ *(unsigned short *)fb = SWAP16((unsigned short)((((r)>>3)<<11) | (((g)>>2)<<5) | ((b)>>3))); \
+ fb += 2; \
+}
+
+#define FILL_32BIT_X888RGB(r,g,b) { \
+ *(unsigned long *)fb = SWAP32((unsigned long)(((r<<16) | (g<<8) | b))); \
+ fb += 4; \
+}
+
+#ifdef VIDEO_FB_LITTLE_ENDIAN
+#define FILL_24BIT_888RGB(r,g,b) { \
+ fb[0] = b; \
+ fb[1] = g; \
+ fb[2] = r; \
+ fb += 3; \
+}
+#else
+#define FILL_24BIT_888RGB(r,g,b) { \
+ fb[0] = r; \
+ fb[1] = g; \
+ fb[2] = b; \
+ fb += 3; \
+}
+#endif
+
+
+/*
+ * Display the BMP file located at address bmp_image.
+ * Only uncompressed
+ */
+int video_display_bitmap (ulong bmp_image, int x, int y)
+{
+ ushort xcount, ycount;
+ uchar *fb;
+ bmp_image_t *bmp = (bmp_image_t *) bmp_image;
+ uchar *bmap;
+ ushort padded_line;
+ unsigned long width, height, bpp;
+ unsigned colors;
+ unsigned long compression;
+ bmp_color_table_entry_t cte;
+#ifdef CONFIG_VIDEO_BMP_GZIP
+ unsigned char *dst = NULL;
+ ulong len;
+#endif
+
+ WATCHDOG_RESET ();
+
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M'))) {
+
+#ifdef CONFIG_VIDEO_BMP_GZIP
+ /*
+ * Could be a gzipped bmp image, try to decrompress...
+ */
+ len = CFG_VIDEO_LOGO_MAX_SIZE;
+ dst = malloc(CFG_VIDEO_LOGO_MAX_SIZE);
+ if (dst == NULL) {
+ printf("Error: malloc in gunzip failed!\n");
+ return(1);
+ }
+ if (gunzip(dst, CFG_VIDEO_LOGO_MAX_SIZE, (uchar *)bmp_image, &len) != 0) {
+ printf ("Error: no valid bmp or bmp.gz image at %lx\n", bmp_image);
+ free(dst);
+ return 1;
+ }
+ if (len == CFG_VIDEO_LOGO_MAX_SIZE) {
+ printf("Image could be truncated (increase CFG_VIDEO_LOGO_MAX_SIZE)!\n");
+ }
+
+ /*
+ * Set addr to decompressed image
+ */
+ bmp = (bmp_image_t *)dst;
+
+ if (!((bmp->header.signature[0] == 'B') &&
+ (bmp->header.signature[1] == 'M'))) {
+ printf ("Error: no valid bmp.gz image at %lx\n", bmp_image);
+ return 1;
+ }
+#else
+ printf ("Error: no valid bmp image at %lx\n", bmp_image);
+ return 1;
+#endif /* CONFIG_VIDEO_BMP_GZIP */
+ }
+
+ width = le32_to_cpu (bmp->header.width);
+ height = le32_to_cpu (bmp->header.height);
+ bpp = le16_to_cpu (bmp->header.bit_count);
+ colors = le32_to_cpu (bmp->header.colors_used);
+ compression = le32_to_cpu (bmp->header.compression);
+
+ debug ("Display-bmp: %d x %d with %d colors\n",
+ width, height, colors);
+
+ if (compression != BMP_BI_RGB) {
+ printf ("Error: compression type %ld not supported\n",
+ compression);
+ return 1;
+ }
+
+ padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
+
+ if ((x + width) > VIDEO_VISIBLE_COLS)
+ width = VIDEO_VISIBLE_COLS - x;
+ if ((y + height) > VIDEO_VISIBLE_ROWS)
+ height = VIDEO_VISIBLE_ROWS - y;
+
+ bmap = (uchar *) bmp + le32_to_cpu (bmp->header.data_offset);
+ fb = (uchar *) (video_fb_address +
+ ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
+ x * VIDEO_PIXEL_SIZE);
+
+ /* We handle only 8bpp or 24 bpp bitmap */
+ switch (le16_to_cpu (bmp->header.bit_count)) {
+ case 8:
+ padded_line -= width;
+ if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
+ /* Copy colormap */
+ for (xcount = 0; xcount < colors; ++xcount) {
+ cte = bmp->color_table[xcount];
+ video_set_lut (xcount, cte.red, cte.green, cte.blue);
+ }
+ }
+ ycount = height;
+ switch (VIDEO_DATA_FORMAT) {
+ case GDF__8BIT_INDEX:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ *fb++ = *bmap++;
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF__8BIT_332RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ cte = bmp->color_table[*bmap++];
+ FILL_8BIT_332RGB (cte.red, cte.green, cte.blue);
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_15BIT_555RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ cte = bmp->color_table[*bmap++];
+ FILL_15BIT_555RGB (cte.red, cte.green, cte.blue);
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_16BIT_565RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ cte = bmp->color_table[*bmap++];
+ FILL_16BIT_565RGB (cte.red, cte.green, cte.blue);
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_32BIT_X888RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ cte = bmp->color_table[*bmap++];
+ FILL_32BIT_X888RGB (cte.red, cte.green, cte.blue);
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_24BIT_888RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ cte = bmp->color_table[*bmap++];
+ FILL_24BIT_888RGB (cte.red, cte.green, cte.blue);
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ }
+ break;
+ case 24:
+ padded_line -= 3 * width;
+ ycount = height;
+ switch (VIDEO_DATA_FORMAT) {
+ case GDF__8BIT_332RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ FILL_8BIT_332RGB (bmap[2], bmap[1], bmap[0]);
+ bmap += 3;
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_15BIT_555RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ FILL_15BIT_555RGB (bmap[2], bmap[1], bmap[0]);
+ bmap += 3;
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_16BIT_565RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ FILL_16BIT_565RGB (bmap[2], bmap[1], bmap[0]);
+ bmap += 3;
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_32BIT_X888RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ FILL_32BIT_X888RGB (bmap[2], bmap[1], bmap[0]);
+ bmap += 3;
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ case GDF_24BIT_888RGB:
+ while (ycount--) {
+ WATCHDOG_RESET ();
+ xcount = width;
+ while (xcount--) {
+ FILL_24BIT_888RGB (bmap[2], bmap[1], bmap[0]);
+ bmap += 3;
+ }
+ bmap += padded_line;
+ fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
+ }
+ break;
+ default:
+ printf ("Error: 24 bits/pixel bitmap incompatible with current video mode\n");
+ break;
+ }
+ break;
+ default:
+ printf ("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
+ le16_to_cpu (bmp->header.bit_count));
+ break;
+ }
+
+#ifdef CONFIG_VIDEO_BMP_GZIP
+ if (dst) {
+ free(dst);
+ }
+#endif
+
+ return (0);
+}
+#endif
+
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_LOGO
+void logo_plot (void *screen, int width, int x, int y)
+{
+
+ int xcount, i;
+ int skip = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
+ int ycount = VIDEO_LOGO_HEIGHT;
+ unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
+ unsigned char *source;
+ unsigned char *dest = (unsigned char *)screen + ((y * width * VIDEO_PIXEL_SIZE) + x);
+
+#ifdef CONFIG_VIDEO_BMP_LOGO
+ source = bmp_logo_bitmap;
+
+ /* Allocate temporary space for computing colormap */
+ logo_red = malloc (BMP_LOGO_COLORS);
+ logo_green = malloc (BMP_LOGO_COLORS);
+ logo_blue = malloc (BMP_LOGO_COLORS);
+ /* Compute color map */
+ for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
+ logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
+ logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
+ logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
+ }
+#else
+ source = linux_logo;
+ logo_red = linux_logo_red;
+ logo_green = linux_logo_green;
+ logo_blue = linux_logo_blue;
+#endif
+
+ if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
+ for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
+ video_set_lut (i + VIDEO_LOGO_LUT_OFFSET,
+ logo_red[i], logo_green[i], logo_blue[i]);
+ }
+ }
+
+ while (ycount--) {
+ xcount = VIDEO_LOGO_WIDTH;
+ while (xcount--) {
+ r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
+ g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
+ b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
+
+ switch (VIDEO_DATA_FORMAT) {
+ case GDF__8BIT_INDEX:
+ *dest = *source;
+ break;
+ case GDF__8BIT_332RGB:
+ *dest = ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
+ break;
+ case GDF_15BIT_555RGB:
+ *(unsigned short *) dest =
+ SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)));
+ break;
+ case GDF_16BIT_565RGB:
+ *(unsigned short *) dest =
+ SWAP16 ((unsigned short) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)));
+ break;
+ case GDF_32BIT_X888RGB:
+ *(unsigned long *) dest =
+ SWAP32 ((unsigned long) ((r << 16) | (g << 8) | b));
+ break;
+ case GDF_24BIT_888RGB:
+#ifdef VIDEO_FB_LITTLE_ENDIAN
+ dest[0] = b;
+ dest[1] = g;
+ dest[2] = r;
+#else
+ dest[0] = r;
+ dest[1] = g;
+ dest[2] = b;
+#endif
+ break;
+ }
+ source++;
+ dest += VIDEO_PIXEL_SIZE;
+ }
+ dest += skip;
+ }
+#ifdef CONFIG_VIDEO_BMP_LOGO
+ free (logo_red);
+ free (logo_green);
+ free (logo_blue);
+#endif
+}
+
+/*****************************************************************************/
+
+static void *video_logo (void)
+{
+ char info[128];
+ extern char version_string;
+
+#ifdef CONFIG_SPLASH_SCREEN
+ char *s;
+ ulong addr;
+
+ if ((s = getenv ("splashimage")) != NULL) {
+ addr = simple_strtoul (s, NULL, 16);
+
+ if (video_display_bitmap (addr, 0, 0) == 0) {
+ return ((void *) (video_fb_address));
+ }
+ }
+#endif /* CONFIG_SPLASH_SCREEN */
+
+ logo_plot (video_fb_address, VIDEO_COLS, 0, 0);
+
+ sprintf (info, " %s", &version_string);
+ video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *)info);
+
+#ifdef CONFIG_CONSOLE_EXTRA_INFO
+ {
+ int i, n = ((VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
+
+ for (i = 1; i < n; i++) {
+ video_get_info_str (i, info);
+ if (*info)
+ video_drawstring (VIDEO_INFO_X,
+ VIDEO_INFO_Y + i * VIDEO_FONT_HEIGHT,
+ (uchar *)info);
+ }
+ }
+#endif
+
+ return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN);
+}
+#endif
+
+
+/*****************************************************************************/
+
+static int video_init (void)
+{
+ unsigned char color8;
+
+ if ((pGD = video_hw_init ()) == NULL)
+ return -1;
+
+ video_fb_address = (void *) VIDEO_FB_ADRS;
+#ifdef CONFIG_VIDEO_HW_CURSOR
+ video_init_hw_cursor (VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
+#endif
+
+ /* Init drawing pats */
+ switch (VIDEO_DATA_FORMAT) {
+ case GDF__8BIT_INDEX:
+ video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
+ video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL);
+ fgx = 0x01010101;
+ bgx = 0x00000000;
+ break;
+ case GDF__8BIT_332RGB:
+ color8 = ((CONSOLE_FG_COL & 0xe0) |
+ ((CONSOLE_FG_COL >> 3) & 0x1c) | CONSOLE_FG_COL >> 6);
+ fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
+ color8 = ((CONSOLE_BG_COL & 0xe0) |
+ ((CONSOLE_BG_COL >> 3) & 0x1c) | CONSOLE_BG_COL >> 6);
+ bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
+ break;
+ case GDF_15BIT_555RGB:
+ fgx = (((CONSOLE_FG_COL >> 3) << 26) |
+ ((CONSOLE_FG_COL >> 3) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
+ ((CONSOLE_FG_COL >> 3) << 10) | ((CONSOLE_FG_COL >> 3) << 5) |
+ (CONSOLE_FG_COL >> 3));
+ bgx = (((CONSOLE_BG_COL >> 3) << 26) |
+ ((CONSOLE_BG_COL >> 3) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
+ ((CONSOLE_BG_COL >> 3) << 10) | ((CONSOLE_BG_COL >> 3) << 5) |
+ (CONSOLE_BG_COL >> 3));
+ break;
+ case GDF_16BIT_565RGB:
+ fgx = (((CONSOLE_FG_COL >> 3) << 27) |
+ ((CONSOLE_FG_COL >> 2) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
+ ((CONSOLE_FG_COL >> 3) << 11) | ((CONSOLE_FG_COL >> 2) << 5) |
+ (CONSOLE_FG_COL >> 3));
+ bgx = (((CONSOLE_BG_COL >> 3) << 27) |
+ ((CONSOLE_BG_COL >> 2) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
+ ((CONSOLE_BG_COL >> 3) << 11) | ((CONSOLE_BG_COL >> 2) << 5) |
+ (CONSOLE_BG_COL >> 3));
+ break;
+ case GDF_32BIT_X888RGB:
+ fgx = (CONSOLE_FG_COL << 16) | (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
+ bgx = (CONSOLE_BG_COL << 16) | (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
+ break;
+ case GDF_24BIT_888RGB:
+ fgx = (CONSOLE_FG_COL << 24) | (CONSOLE_FG_COL << 16) |
+ (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
+ bgx = (CONSOLE_BG_COL << 24) | (CONSOLE_BG_COL << 16) |
+ (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
+ break;
+ }
+ eorx = fgx ^ bgx;
+
+#ifdef CONFIG_VIDEO_LOGO
+ /* Plot the logo and get start point of console */
+ PRINTD ("Video: Drawing the logo ...\n");
+ video_console_address = video_logo ();
+#else
+ video_console_address = video_fb_address;
+#endif
+
+ /* Initialize the console */
+ console_col = 0;
+ console_row = 0;
+
+ return 0;
+}
+
+
+/*****************************************************************************/
+
+int drv_video_init (void)
+{
+ int skip_dev_init;
+ device_t console_dev;
+
+ skip_dev_init = 0;
+
+ /* Init video chip - returns with framebuffer cleared */
+ if (video_init () == -1)
+ skip_dev_init = 1;
+
+#ifdef CONFIG_VGA_AS_SINGLE_DEVICE
+ /* Devices VGA and Keyboard will be assigned seperately */
+ /* Init vga device */
+ if (!skip_dev_init) {
+ memset (&console_dev, 0, sizeof (console_dev));
+ strcpy (console_dev.name, "vga");
+ console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
+ console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+ console_dev.putc = video_putc; /* 'putc' function */
+ console_dev.puts = video_puts; /* 'puts' function */
+ console_dev.tstc = NULL; /* 'tstc' function */
+ console_dev.getc = NULL; /* 'getc' function */
+
+ if (device_register (&console_dev) == 0)
+ return 1;
+ }
+#else
+ PRINTD ("KBD: Keyboard init ...\n");
+ if (VIDEO_KBD_INIT_FCT == -1)
+ skip_dev_init = 1;
+
+ /* Init console device */
+ if (!skip_dev_init) {
+ memset (&console_dev, 0, sizeof (console_dev));
+ strcpy (console_dev.name, "vga");
+ console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
+ console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+ console_dev.putc = video_putc; /* 'putc' function */
+ console_dev.puts = video_puts; /* 'puts' function */
+ console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
+ console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
+
+ if (device_register (&console_dev) == 0)
+ return 1;
+ }
+#endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
+ /* No console dev available */
+ return 0;
+}
+#endif /* CONFIG_CFB_CONSOLE */
diff --git a/drivers/video/ct69000.c b/drivers/video/ct69000.c
new file mode 100644
index 0000000..29d82e4
--- /dev/null
+++ b/drivers/video/ct69000.c
@@ -0,0 +1,1286 @@
+/* ported from ctfb.c (linux kernel):
+ * Created in Jan - July 2000 by Thomas Höhenleitner <th@visuelle-maschinen.de>
+ *
+ * Ported to U-Boot:
+ * (C) Copyright 2002 Denis Peter, MPL AG Switzerland
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_VIDEO
+
+#include <pci.h>
+#include <video_fb.h>
+#include "videomodes.h"
+
+#ifdef CONFIG_VIDEO_CT69000
+
+/* debug */
+#undef VGA_DEBUG
+#undef VGA_DUMP_REG
+#ifdef VGA_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+/* Macros */
+#ifndef min
+#define min( a, b ) ( ( a ) < ( b ) ) ? ( a ) : ( b )
+#endif
+#ifndef max
+#define max( a, b ) ( ( a ) > ( b ) ) ? ( a ) : ( b )
+#endif
+#ifdef minmax
+#error "term minmax already used."
+#endif
+#define minmax( a, x, b ) max( ( a ), min( ( x ), ( b ) ) )
+#define N_ELTS( x ) ( sizeof( x ) / sizeof( x[ 0 ] ) )
+
+/* CT Register Offsets */
+#define CT_AR_O 0x3c0 /* Index and Data write port of the attribute Registers */
+#define CT_GR_O 0x3ce /* Index port of the Graphic Controller Registers */
+#define CT_SR_O 0x3c4 /* Index port of the Sequencer Controller */
+#define CT_CR_O 0x3d4 /* Index port of the CRT Controller */
+#define CT_XR_O 0x3d6 /* Extended Register index */
+#define CT_MSR_W_O 0x3c2 /* Misc. Output Register (write only) */
+#define CT_LUT_MASK_O 0x3c6 /* Color Palette Mask */
+#define CT_LUT_START_O 0x3c8 /* Color Palette Write Mode Index */
+#define CT_LUT_RGB_O 0x3c9 /* Color Palette Data Port */
+#define CT_STATUS_REG0_O 0x3c2 /* Status Register 0 (read only) */
+#define CT_STATUS_REG1_O 0x3da /* Input Status Register 1 (read only) */
+
+#define CT_FP_O 0x3d0 /* Index port of the Flat panel Registers */
+#define CT_MR_O 0x3d2 /* Index Port of the Multimedia Extension */
+
+/* defines for the memory mapped registers */
+#define BR00_o 0x400000 /* Source and Destination Span Register */
+#define BR01_o 0x400004 /* Pattern/Source Expansion Background Color & Transparency Key Register */
+#define BR02_o 0x400008 /* Pattern/Source Expansion Foreground Color Register */
+#define BR03_o 0x40000C /* Monochrome Source Control Register */
+#define BR04_o 0x400010 /* BitBLT Control Register */
+#define BR05_o 0x400014 /* Pattern Address Registe */
+#define BR06_o 0x400018 /* Source Address Register */
+#define BR07_o 0x40001C /* Destination Address Register */
+#define BR08_o 0x400020 /* Destination Width & Height Register */
+#define BR09_o 0x400024 /* Source Expansion Background Color & Transparency Key Register */
+#define BR0A_o 0x400028 /* Source Expansion Foreground Color Register */
+
+#define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */
+#define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */
+#define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */
+#define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */
+
+/* Some Mode definitions */
+#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define FB_SYNC_EXT 4 /* external sync */
+#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define FB_SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+#define FB_SYNC_ON_GREEN 32 /* sync on green */
+
+#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
+#define FB_VMODE_INTERLACED 1 /* interlaced */
+#define FB_VMODE_DOUBLE 2 /* double scan */
+#define FB_VMODE_MASK 255
+
+#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
+#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+#define text 0
+#define fntwidth 8
+
+/* table for VGA Initialization */
+typedef struct {
+ const unsigned char reg;
+ const unsigned char val;
+} CT_CFG_TABLE;
+
+/* this table provides some basic initialisations such as Memory Clock etc */
+static CT_CFG_TABLE xreg[] = {
+ {0x09, 0x01}, /* CRT Controller Extensions Enable */
+ {0x0A, 0x02}, /* Frame Buffer Mapping */
+ {0x0B, 0x01}, /* PCI Write Burst support */
+ {0x20, 0x00}, /* BitBLT Configuration */
+ {0x40, 0x03}, /* Memory Access Control */
+ {0x60, 0x00}, /* Video Pin Control */
+ {0x61, 0x00}, /* DPMS Synch control */
+ {0x62, 0x00}, /* GPIO Pin Control */
+ {0x63, 0xBD}, /* GPIO Pin Data */
+ {0x67, 0x00}, /* Pin Tri-State */
+ {0x80, 0x80}, /* Pixel Pipeline Config 0 register */
+ {0xA0, 0x00}, /* Cursor 1 Control Reg */
+ {0xA1, 0x00}, /* Cursor 1 Vertical Extension Reg */
+ {0xA2, 0x00}, /* Cursor 1 Base Address Low */
+ {0xA3, 0x00}, /* Cursor 1 Base Address High */
+ {0xA4, 0x00}, /* Cursor 1 X-Position Low */
+ {0xA5, 0x00}, /* Cursor 1 X-Position High */
+ {0xA6, 0x00}, /* Cursor 1 Y-Position Low */
+ {0xA7, 0x00}, /* Cursor 1 Y-Position High */
+ {0xA8, 0x00}, /* Cursor 2 Control Reg */
+ {0xA9, 0x00}, /* Cursor 2 Vertical Extension Reg */
+ {0xAA, 0x00}, /* Cursor 2 Base Address Low */
+ {0xAB, 0x00}, /* Cursor 2 Base Address High */
+ {0xAC, 0x00}, /* Cursor 2 X-Position Low */
+ {0xAD, 0x00}, /* Cursor 2 X-Position High */
+ {0xAE, 0x00}, /* Cursor 2 Y-Position Low */
+ {0xAF, 0x00}, /* Cursor 2 Y-Position High */
+ {0xC0, 0x7D}, /* Dot Clock 0 VCO M-Divisor */
+ {0xC1, 0x07}, /* Dot Clock 0 VCO N-Divisor */
+ {0xC3, 0x34}, /* Dot Clock 0 Divisor select */
+ {0xC4, 0x55}, /* Dot Clock 1 VCO M-Divisor */
+ {0xC5, 0x09}, /* Dot Clock 1 VCO N-Divisor */
+ {0xC7, 0x24}, /* Dot Clock 1 Divisor select */
+ {0xC8, 0x7D}, /* Dot Clock 2 VCO M-Divisor */
+ {0xC9, 0x07}, /* Dot Clock 2 VCO N-Divisor */
+ {0xCB, 0x34}, /* Dot Clock 2 Divisor select */
+ {0xCC, 0x38}, /* Memory Clock 0 VCO M-Divisor */
+ {0xCD, 0x03}, /* Memory Clock 0 VCO N-Divisor */
+ {0xCE, 0x90}, /* Memory Clock 0 Divisor select */
+ {0xCF, 0x06}, /* Clock Config */
+ {0xD0, 0x0F}, /* Power Down */
+ {0xD1, 0x01}, /* Power Down BitBLT */
+ {0xFF, 0xFF} /* end of table */
+};
+/* Clock Config:
+ * =============
+ *
+ * PD Registers:
+ * -------------
+ * Bit2 and Bit4..6 are used for the Loop Divisor and Post Divisor.
+ * They are encoded as follows:
+ *
+ * +---+--------------+
+ * | 2 | Loop Divisor |
+ * +---+--------------+
+ * | 1 | 1 |
+ * +---+--------------+
+ * | 0 | 4 |
+ * +---+--------------+
+ * Note: The Memory Clock does not have a Loop Divisor.
+ * +---+---+---+--------------+
+ * | 6 | 5 | 4 | Post Divisor |
+ * +---+---+---+--------------+
+ * | 0 | 0 | 0 | 1 |
+ * +---+---+---+--------------+
+ * | 0 | 0 | 1 | 2 |
+ * +---+---+---+--------------+
+ * | 0 | 1 | 0 | 4 |
+ * +---+---+---+--------------+
+ * | 0 | 1 | 1 | 8 |
+ * +---+---+---+--------------+
+ * | 1 | 0 | 0 | 16 |
+ * +---+---+---+--------------+
+ * | 1 | 0 | 1 | 32 |
+ * +---+---+---+--------------+
+ * | 1 | 1 | X | reserved |
+ * +---+---+---+--------------+
+ *
+ * All other bits are reserved in these registers.
+ *
+ * Clock VCO M Registers:
+ * ----------------------
+ * These Registers contain the M Value -2.
+ *
+ * Clock VCO N Registers:
+ * ----------------------
+ * These Registers contain the N Value -2.
+ *
+ * Formulas:
+ * ---------
+ * Fvco = (Fref * Loop Divisor * M/N), whereas 100MHz < Fvco < 220MHz
+ * Fout = Fvco / Post Divisor
+ *
+ * Dot Clk0 (default 25MHz):
+ * -------------------------
+ * Fvco = 14.318 * 127 / 9 = 202.045MHz
+ * Fout = 202.045MHz / 8 = 25.25MHz
+ * Post Divisor = 8
+ * Loop Divisor = 1
+ * XRC0 = (M - 2) = 125 = 0x7D
+ * XRC1 = (N - 2) = 7 = 0x07
+ * XRC3 = 0x34
+ *
+ * Dot Clk1 (default 28MHz):
+ * -------------------------
+ * Fvco = 14.318 * 87 / 11 = 113.24MHz
+ * Fout = 113.24MHz / 4 = 28.31MHz
+ * Post Divisor = 4
+ * Loop Divisor = 1
+ * XRC4 = (M - 2) = 85 = 0x55
+ * XRC5 = (N - 2) = 9 = 0x09
+ * XRC7 = 0x24
+ *
+ * Dot Clk2 (variable for extended modes set to 25MHz):
+ * ----------------------------------------------------
+ * Fvco = 14.318 * 127 / 9 = 202.045MHz
+ * Fout = 202.045MHz / 8 = 25.25MHz
+ * Post Divisor = 8
+ * Loop Divisor = 1
+ * XRC8 = (M - 2) = 125 = 0x7D
+ * XRC9 = (N - 2) = 7 = 0x07
+ * XRCB = 0x34
+ *
+ * Memory Clk for most modes >50MHz:
+ * ----------------------------------
+ * Fvco = 14.318 * 58 / 5 = 166MHz
+ * Fout = 166MHz / 2 = 83MHz
+ * Post Divisor = 2
+ * XRCC = (M - 2) = 57 = 0x38
+ * XRCD = (N - 2) = 3 = 0x03
+ * XRCE = 0x90
+ *
+ * Note Bit7 enables the clock source from the VCO
+ *
+ */
+
+/*******************************************************************
+ * Chips struct
+ *******************************************************************/
+struct ctfb_chips_properties {
+ int device_id; /* PCI Device ID */
+ unsigned long max_mem; /* memory for frame buffer */
+ int vld_set; /* value of VLD if bit2 in clock control is set */
+ int vld_not_set; /* value of VLD if bit2 in clock control is set */
+ int mn_diff; /* difference between M/N Value + mn_diff = M/N Register */
+ int mn_min; /* min value of M/N Value */
+ int mn_max; /* max value of M/N Value */
+ int vco_min; /* VCO Min in MHz */
+ int vco_max; /* VCO Max in MHz */
+};
+
+static const struct ctfb_chips_properties chips[] = {
+ {PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220},
+#ifdef CONFIG_USE_CPCIDVI
+ {PCI_DEVICE_ID_CT_69030, 0x400000, 1, 4, -2, 3, 257, 100, 220},
+#endif
+ {PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220}, /* NOT TESTED */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0} /* Terminator */
+};
+
+/*
+ * The Graphic Device
+ */
+GraphicDevice ctfb;
+
+/*******************************************************************************
+*
+* Low Level Routines
+*/
+
+/*******************************************************************************
+*
+* Read CT ISA register
+*/
+#ifdef VGA_DEBUG
+static unsigned char
+ctRead (unsigned short index)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ if (index == CT_AR_O)
+ /* synch the Flip Flop */
+ in8 (pGD->isaBase + CT_STATUS_REG1_O);
+
+ return (in8 (pGD->isaBase + index));
+}
+#endif
+/*******************************************************************************
+*
+* Write CT ISA register
+*/
+static void
+ctWrite (unsigned short index, unsigned char val)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+ out8 ((pGD->isaBase + index), val);
+}
+
+/*******************************************************************************
+*
+* Read CT ISA register indexed
+*/
+static unsigned char
+ctRead_i (unsigned short index, char reg)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ if (index == CT_AR_O)
+ /* synch the Flip Flop */
+ in8 (pGD->isaBase + CT_STATUS_REG1_O);
+ out8 ((pGD->isaBase + index), reg);
+ return (in8 (pGD->isaBase + index + 1));
+}
+
+/*******************************************************************************
+*
+* Write CT ISA register indexed
+*/
+static void
+ctWrite_i (unsigned short index, char reg, char val)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ if (index == CT_AR_O) {
+ /* synch the Flip Flop */
+ in8 (pGD->isaBase + CT_STATUS_REG1_O);
+ out8 ((pGD->isaBase + index), reg);
+ out8 ((pGD->isaBase + index), val);
+ } else {
+ out8 ((pGD->isaBase + index), reg);
+ out8 ((pGD->isaBase + index + 1), val);
+ }
+}
+
+/*******************************************************************************
+*
+* Write a table of CT ISA register
+*/
+static void
+ctLoadRegs (unsigned short index, CT_CFG_TABLE * regTab)
+{
+ while (regTab->reg != 0xFF) {
+ ctWrite_i (index, regTab->reg, regTab->val);
+ regTab++;
+ }
+}
+
+/*****************************************************************************/
+static void
+SetArRegs (void)
+{
+ int i, tmp;
+
+ for (i = 0; i < 0x10; i++)
+ ctWrite_i (CT_AR_O, i, i);
+ if (text)
+ tmp = 0x04;
+ else
+ tmp = 0x41;
+
+ ctWrite_i (CT_AR_O, 0x10, tmp); /* Mode Control Register */
+ ctWrite_i (CT_AR_O, 0x11, 0x00); /* Overscan Color Register */
+ ctWrite_i (CT_AR_O, 0x12, 0x0f); /* Memory Plane Enable Register */
+ if (fntwidth == 9)
+ tmp = 0x08;
+ else
+ tmp = 0x00;
+ ctWrite_i (CT_AR_O, 0x13, tmp); /* Horizontal Pixel Panning */
+ ctWrite_i (CT_AR_O, 0x14, 0x00); /* Color Select Register */
+ ctWrite (CT_AR_O, 0x20); /* enable video */
+}
+
+/*****************************************************************************/
+static void
+SetGrRegs (void)
+{ /* Set Graphics Mode */
+ int i;
+
+ for (i = 0; i < 0x05; i++)
+ ctWrite_i (CT_GR_O, i, 0);
+ if (text) {
+ ctWrite_i (CT_GR_O, 0x05, 0x10);
+ ctWrite_i (CT_GR_O, 0x06, 0x02);
+ } else {
+ ctWrite_i (CT_GR_O, 0x05, 0x40);
+ ctWrite_i (CT_GR_O, 0x06, 0x05);
+ }
+ ctWrite_i (CT_GR_O, 0x07, 0x0f);
+ ctWrite_i (CT_GR_O, 0x08, 0xff);
+}
+
+/*****************************************************************************/
+static void
+SetSrRegs (void)
+{
+ int tmp = 0;
+
+ ctWrite_i (CT_SR_O, 0x00, 0x00); /* reset */
+ /*rr( sr, 0x01, tmp );
+ if( fntwidth == 8 ) tmp |= 0x01; else tmp &= ~0x01;
+ wr( sr, 0x01, tmp ); */
+ if (fntwidth == 8)
+ ctWrite_i (CT_SR_O, 0x01, 0x01); /* Clocking Mode Register */
+ else
+ ctWrite_i (CT_SR_O, 0x01, 0x00); /* Clocking Mode Register */
+ ctWrite_i (CT_SR_O, 0x02, 0x0f); /* Enable CPU wr access to given memory plane */
+ ctWrite_i (CT_SR_O, 0x03, 0x00); /* Character Map Select Register */
+ if (text)
+ tmp = 0x02;
+ else
+ tmp = 0x0e;
+ ctWrite_i (CT_SR_O, 0x04, tmp); /* Enable CPU accesses to the rest of the 256KB
+ total VGA memory beyond the first 64KB and set
+ fb mapping mode. */
+ ctWrite_i (CT_SR_O, 0x00, 0x03); /* enable */
+}
+
+/*****************************************************************************/
+static void
+SetBitsPerPixelIntoXrRegs (int bpp)
+{
+ unsigned int n = (bpp >> 3), tmp; /* only for 15, 8, 16, 24 bpp */
+ static char md[4] = { 0x04, 0x02, 0x05, 0x06 }; /* DisplayColorMode */
+ static char off[4] = { ~0x20, ~0x30, ~0x20, ~0x10 }; /* mask */
+ static char on[4] = { 0x10, 0x00, 0x10, 0x20 }; /* mask */
+ if (bpp == 15)
+ n = 0;
+ tmp = ctRead_i (CT_XR_O, 0x20);
+ tmp &= off[n];
+ tmp |= on[n];
+ ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+ ctWrite_i (CT_XR_O, 0x81, md[n]);
+}
+
+/*****************************************************************************/
+static void
+SetCrRegs (struct ctfb_res_modes *var, int bits_per_pixel)
+{ /* he -le- ht|0 hd -ri- hs -h- he */
+ unsigned char cr[0x7a];
+ int i, tmp;
+ unsigned int hd, hs, he, ht, hbe; /* Horizontal. */
+ unsigned int vd, vs, ve, vt; /* vertical */
+ unsigned int bpp, wd, dblscan, interlaced, bcast, CrtHalfLine;
+ unsigned int CompSyncCharClkDelay, CompSyncPixelClkDelay;
+ unsigned int NTSC_PAL_HorizontalPulseWidth, BlDelayCtrl;
+ unsigned int HorizontalEqualizationPulses;
+ unsigned int HorizontalSerration1Start, HorizontalSerration2Start;
+
+ const int LineCompare = 0x3ff;
+ unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
+ unsigned int RAMDAC_BlankPedestalEnable = 0; /* 1=en-, 0=disable, see XR82 */
+
+ hd = (var->xres) / 8; /* HDisp. */
+ hs = (var->xres + var->right_margin) / 8; /* HsStrt */
+ he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
+ ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
+ hbe = ht - 1; /* HBlankEnable todo docu wants ht here, but it does not work */
+ /* ve -up- vt|0 vd -lo- vs -v- ve */
+ vd = var->yres; /* VDisplay */
+ vs = var->yres + var->lower_margin; /* VSyncStart */
+ ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
+ vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
+ bpp = bits_per_pixel;
+ dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
+ interlaced = var->vmode & FB_VMODE_INTERLACED;
+ bcast = var->sync & FB_SYNC_BROADCAST;
+ CrtHalfLine = bcast ? (hd >> 1) : 0;
+ BlDelayCtrl = bcast ? 1 : 0;
+ CompSyncCharClkDelay = 0; /* 2 bit */
+ CompSyncPixelClkDelay = 0; /* 3 bit */
+ if (bcast) {
+ NTSC_PAL_HorizontalPulseWidth = 7; /*( var->hsync_len >> 1 ) + 1 */
+ HorizontalEqualizationPulses = 0; /* inverse value */
+ HorizontalSerration1Start = 31; /* ( ht >> 1 ) */
+ HorizontalSerration2Start = 89; /* ( ht >> 1 ) */
+ } else {
+ NTSC_PAL_HorizontalPulseWidth = 0;
+ /* 4 bit: hsync pulse width = ( ( CR74[4:0] - CR74[5] )
+ * / 2 ) + 1 --> CR74[4:0] = 2*(hs-1) + CR74[5] */
+ HorizontalEqualizationPulses = 1; /* inverse value */
+ HorizontalSerration1Start = 0; /* ( ht >> 1 ) */
+ HorizontalSerration2Start = 0; /* ( ht >> 1 ) */
+ }
+
+ if (bpp == 15)
+ bpp = 16;
+ wd = var->xres * bpp / 64; /* double words per line */
+ if (interlaced) { /* we divide all vertical timings, exept vd */
+ vs >>= 1;
+ ve >>= 1;
+ vt >>= 1;
+ }
+ memset (cr, 0, sizeof (cr));
+ cr[0x00] = 0xff & (ht - 5);
+ cr[0x01] = hd - 1; /* soll:4f ist 59 */
+ cr[0x02] = hd;
+ cr[0x03] = (hbe & 0x1F) | 0x80; /* hd + ht - hd */
+ cr[0x04] = hs;
+ cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
+ cr[0x06] = (vt - 2) & 0xFF;
+ cr[0x30] = (vt - 2) >> 8;
+ cr[0x07] = ((vt & 0x100) >> 8)
+ | ((vd & 0x100) >> 7)
+ | ((vs & 0x100) >> 6)
+ | ((vs & 0x100) >> 5)
+ | ((LineCompare & 0x100) >> 4)
+ | ((vt & 0x200) >> 4)
+ | ((vd & 0x200) >> 3)
+ | ((vs & 0x200) >> 2);
+ cr[0x08] = 0x00;
+ cr[0x09] = (dblscan << 7)
+ | ((LineCompare & 0x200) >> 3)
+ | ((vs & 0x200) >> 4)
+ | (TextScanLines - 1);
+ cr[0x10] = vs & 0xff; /* VSyncPulseStart */
+ cr[0x32] = (vs & 0xf00) >> 8; /* VSyncPulseStart */
+ cr[0x11] = (ve & 0x0f); /* | 0x20; */
+ cr[0x12] = (vd - 1) & 0xff; /* LineCount */
+ cr[0x31] = ((vd - 1) & 0xf00) >> 8; /* LineCount */
+ cr[0x13] = wd & 0xff;
+ cr[0x41] = (wd & 0xf00) >> 8;
+ cr[0x15] = vs & 0xff;
+ cr[0x33] = (vs & 0xf00) >> 8;
+ cr[0x38] = (0x100 & (ht - 5)) >> 8;
+ cr[0x3C] = 0xc0 & hbe;
+ cr[0x16] = (vt - 1) & 0xff; /* vbe - docu wants vt here, */
+ cr[0x17] = 0xe3; /* but it does not work */
+ cr[0x18] = 0xff & LineCompare;
+ cr[0x22] = 0xff; /* todo? */
+ cr[0x70] = interlaced ? (0x80 | CrtHalfLine) : 0x00; /* check:0xa6 */
+ cr[0x71] = 0x80 | (RAMDAC_BlankPedestalEnable << 6)
+ | (BlDelayCtrl << 5)
+ | ((0x03 & CompSyncCharClkDelay) << 3)
+ | (0x07 & CompSyncPixelClkDelay); /* todo: see XR82 */
+ cr[0x72] = HorizontalSerration1Start;
+ cr[0x73] = HorizontalSerration2Start;
+ cr[0x74] = (HorizontalEqualizationPulses << 5)
+ | NTSC_PAL_HorizontalPulseWidth;
+ /* todo: ct69000 has also 0x75-79 */
+ /* now set the registers */
+ for (i = 0; i <= 0x0d; i++) { /*CR00 .. CR0D */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ for (i = 0x10; i <= 0x18; i++) { /*CR10 .. CR18 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ i = 0x22; /*CR22 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ for (i = 0x30; i <= 0x33; i++) { /*CR30 .. CR33 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ i = 0x38; /*CR38 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ i = 0x3C; /*CR3C */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ for (i = 0x40; i <= 0x41; i++) { /*CR40 .. CR41 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ for (i = 0x70; i <= 0x74; i++) { /*CR70 .. CR74 */
+ ctWrite_i (CT_CR_O, i, cr[i]);
+ }
+ tmp = ctRead_i (CT_CR_O, 0x40);
+ tmp &= 0x0f;
+ tmp |= 0x80;
+ ctWrite_i (CT_CR_O, 0x40, tmp); /* StartAddressEnable */
+}
+
+/* pixelclock control */
+
+/*****************************************************************************
+ We have a rational number p/q and need an m/n which is very close to p/q
+ but has m and n within mnmin and mnmax. We have no floating point in the
+ kernel. We can use long long without divide. And we have time to compute...
+******************************************************************************/
+static unsigned int
+FindBestPQFittingMN (unsigned int p, unsigned int q, unsigned int mnmin,
+ unsigned int mnmax, unsigned int *pm, unsigned int *pn)
+{
+ /* this code is not for general purpose usable but good for our number ranges */
+ unsigned int n = mnmin, m = 0;
+ long long int L = 0, P = p, Q = q, H = P >> 1;
+ long long int D = 0x7ffffffffffffffLL;
+ for (n = mnmin; n <= mnmax; n++) {
+ m = mnmin; /* p/q ~ m/n -> p*n ~ m*q -> p*n-x*q ~ 0 */
+ L = P * n - m * Q; /* n * vco - m * fref should be near 0 */
+ while (L > 0 && m < mnmax) {
+ L -= q; /* difference is greater as 0 subtract fref */
+ m++; /* and increment m */
+ }
+ /* difference is less or equal than 0 or m > maximum */
+ if (m > mnmax)
+ break; /* no solution: if we increase n we get the same situation */
+ /* L is <= 0 now */
+ if (-L > H && m > mnmin) { /* if difference > the half fref */
+ L += q; /* we take the situation before */
+ m--; /* because its closer to 0 */
+ }
+ L = (L < 0) ? -L : +L; /* absolute value */
+ if (D < L) /* if last difference was better take next n */
+ continue;
+ D = L;
+ *pm = m;
+ *pn = n; /* keep improved data */
+ if (D == 0)
+ break; /* best result we can get */
+ }
+ return (unsigned int) (0xffffffff & D);
+}
+
+/* that is the hardware < 69000 we have to manage
+ +---------+ +-------------------+ +----------------------+ +--+
+ | REFCLK |__|NTSC Divisor Select|__|FVCO Reference Divisor|__|÷N|__
+ | 14.3MHz | |(NTSCDS) (÷1, ÷5) | |Select (RDS) (÷1, ÷4) | | | |
+ +---------+ +-------------------+ +----------------------+ +--+ |
+ ___________________________________________________________________|
+ |
+ | fvco fout
+ | +--------+ +------------+ +-----+ +-------------------+ +----+
+ +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |--->
+ +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | |
+ | +--------+ +------------+ +-----+ | +-------------------+ +----+
+ | |
+ | +--+ +---------------+ |
+ |____|÷M|___|VCO Loop Divide|__________|
+ | | |(VLD)(÷4, ÷16) |
+ +--+ +---------------+
+****************************************************************************
+ that is the hardware >= 69000 we have to manage
+ +---------+ +--+
+ | REFCLK |__|÷N|__
+ | 14.3MHz | | | |
+ +---------+ +--+ |
+ __________________|
+ |
+ | fvco fout
+ | +--------+ +------------+ +-----+ +-------------------+ +----+
+ +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |--->
+ +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | |
+ | +--------+ +------------+ +-----+ | +-------------------+ +----+
+ | |
+ | +--+ +---------------+ |
+ |____|÷M|___|VCO Loop Divide|__________|
+ | | |(VLD)(÷1, ÷4) |
+ +--+ +---------------+
+
+
+*/
+
+#define VIDEO_FREF 14318180; /* Hz */
+/*****************************************************************************/
+static int
+ReadPixClckFromXrRegsBack (struct ctfb_chips_properties *param)
+{
+ unsigned int m, n, vld, pd, PD, fref, xr_cb, i, pixclock;
+ i = 0;
+ pixclock = -1;
+ fref = VIDEO_FREF;
+ m = ctRead_i (CT_XR_O, 0xc8);
+ n = ctRead_i (CT_XR_O, 0xc9);
+ m -= param->mn_diff;
+ n -= param->mn_diff;
+ xr_cb = ctRead_i (CT_XR_O, 0xcb);
+ PD = (0x70 & xr_cb) >> 4;
+ pd = 1;
+ for (i = 0; i < PD; i++) {
+ pd *= 2;
+ }
+ vld = (0x04 & xr_cb) ? param->vld_set : param->vld_not_set;
+ if (n * vld * m) {
+ unsigned long long p = 1000000000000LL * pd * n;
+ unsigned long long q = (long long) fref * vld * m;
+ while ((p > 0xffffffffLL) || (q > 0xffffffffLL)) {
+ p >>= 1; /* can't divide with long long so we scale down */
+ q >>= 1;
+ }
+ pixclock = (unsigned) p / (unsigned) q;
+ } else
+ printf ("Invalid data in xr regs.\n");
+ return pixclock;
+}
+
+/*****************************************************************************/
+static void
+FindAndSetPllParamIntoXrRegs (unsigned int pixelclock,
+ struct ctfb_chips_properties *param)
+{
+ unsigned int m, n, vld, pd, PD, fref, xr_cb;
+ unsigned int fvcomin, fvcomax, pclckmin, pclckmax, pclk;
+ unsigned int pfreq, fvco, new_pixclock;
+ unsigned int D,nback,mback;
+
+ fref = VIDEO_FREF;
+ pd = 1;
+ PD = 0;
+ fvcomin = param->vco_min;
+ fvcomax = param->vco_max; /* MHz */
+ pclckmin = 1000000 / fvcomax + 1; /* 4546 */
+ pclckmax = 32000000 / fvcomin - 1; /* 666665 */
+ pclk = minmax (pclckmin, pixelclock, pclckmax); /* ps pp */
+ pfreq = 250 * (4000000000U / pclk);
+ fvco = pfreq; /* Hz */
+ new_pixclock = 0;
+ while (fvco < fvcomin * 1000000) {
+ /* double VCO starting with the pixelclock frequency
+ * as long as it is lower than the minimal VCO frequency */
+ fvco *= 2;
+ pd *= 2;
+ PD++;
+ }
+ /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */
+ /* first try */
+ vld = param->vld_set;
+ D=FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n); /* rds = 1 */
+ mback=m;
+ nback=n;
+ /* second try */
+ vld = param->vld_not_set;
+ if(D<FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n)) { /* rds = 1 */
+ /* first try was better */
+ m=mback;
+ n=nback;
+ vld = param->vld_set;
+ }
+ m += param->mn_diff;
+ n += param->mn_diff;
+ PRINTF ("VCO %d, pd %d, m %d n %d vld %d \n", fvco, pd, m, n, vld);
+ xr_cb = ((0x7 & PD) << 4) | (vld == param->vld_set ? 0x04 : 0);
+ /* All four of the registers used for dot clock 2 (XRC8 - XRCB) must be
+ * written, and in order from XRC8 to XRCB, before the hardware will
+ * update the synthesizer s settings.
+ */
+ ctWrite_i (CT_XR_O, 0xc8, m);
+ ctWrite_i (CT_XR_O, 0xc9, n); /* xrca does not exist in CT69000 and CT69030 */
+ ctWrite_i (CT_XR_O, 0xca, 0); /* because of a hw bug I guess, but we write */
+ ctWrite_i (CT_XR_O, 0xcb, xr_cb); /* 0 to it for savety */
+ new_pixclock = ReadPixClckFromXrRegsBack (param);
+ PRINTF ("pixelclock.set = %d, pixelclock.real = %d \n",
+ pixelclock, new_pixclock);
+}
+
+/*****************************************************************************/
+static void
+SetMsrRegs (struct ctfb_res_modes *mode)
+{
+ unsigned char h_synch_high, v_synch_high;
+
+ h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
+ v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
+ ctWrite (CT_MSR_W_O, (h_synch_high | v_synch_high | 0x29));
+ /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
+ * Selects the upper 64KB page.Bit5=1
+ * CLK2 (left reserved in standard VGA) Bit3|2=1|0
+ * Disables CPU access to frame buffer. Bit1=0
+ * Sets the I/O address decode for ST01, FCR, and all CR registers
+ * to the 3Dx I/O address range (CGA emulation). Bit0=1
+ */
+}
+
+/************************************************************************************/
+#ifdef VGA_DUMP_REG
+
+static void
+ctDispRegs (unsigned short index, int from, int to)
+{
+ unsigned char status;
+ int i;
+
+ for (i = from; i < to; i++) {
+ status = ctRead_i (index, i);
+ printf ("%02X: is %02X\n", i, status);
+ }
+}
+
+void
+video_dump_reg (void)
+{
+ int i;
+
+ printf ("Extended Regs:\n");
+ ctDispRegs (CT_XR_O, 0, 0xC);
+ ctDispRegs (CT_XR_O, 0xe, 0xf);
+ ctDispRegs (CT_XR_O, 0x20, 0x21);
+ ctDispRegs (CT_XR_O, 0x40, 0x50);
+ ctDispRegs (CT_XR_O, 0x60, 0x64);
+ ctDispRegs (CT_XR_O, 0x67, 0x68);
+ ctDispRegs (CT_XR_O, 0x70, 0x72);
+ ctDispRegs (CT_XR_O, 0x80, 0x83);
+ ctDispRegs (CT_XR_O, 0xA0, 0xB0);
+ ctDispRegs (CT_XR_O, 0xC0, 0xD3);
+ printf ("Sequencer Regs:\n");
+ ctDispRegs (CT_SR_O, 0, 0x8);
+ printf ("Graphic Regs:\n");
+ ctDispRegs (CT_GR_O, 0, 0x9);
+ printf ("CRT Regs:\n");
+ ctDispRegs (CT_CR_O, 0, 0x19);
+ ctDispRegs (CT_CR_O, 0x22, 0x23);
+ ctDispRegs (CT_CR_O, 0x30, 0x34);
+ ctDispRegs (CT_CR_O, 0x38, 0x39);
+ ctDispRegs (CT_CR_O, 0x3C, 0x3D);
+ ctDispRegs (CT_CR_O, 0x40, 0x42);
+ ctDispRegs (CT_CR_O, 0x70, 0x80);
+ /* don't display the attributes */
+}
+
+#endif
+
+#ifdef CONFIG_VIDEO_HW_CURSOR
+/***************************************************************
+ * Set Hardware Cursor in Pixel
+ */
+void
+video_set_hw_cursor (int x, int y)
+{
+ int sig_x = 0, sig_y = 0;
+ if (x < 0) {
+ x *= -1;
+ sig_x = 1;
+ }
+ if (y < 0) {
+ y *= -1;
+ sig_y = 1;
+ }
+ ctWrite_i (CT_XR_O, 0xa4, x & 0xff);
+ ctWrite_i (CT_XR_O, 0xa5, (x >> 8) & 0x7);
+ ctWrite_i (CT_XR_O, 0xa6, y & 0xff);
+ ctWrite_i (CT_XR_O, 0xa7, (y >> 8) & 0x7);
+}
+
+/***************************************************************
+ * Init Hardware Cursor. To know the size of the Cursor,
+ * we have to know the Font size.
+ */
+void
+video_init_hw_cursor (int font_width, int font_height)
+{
+ unsigned char xr_80;
+ unsigned long *curs, pattern;
+ int i;
+ int cursor_start;
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+ cursor_start = pGD->dprBase;
+ xr_80 = ctRead_i (CT_XR_O, 0x80);
+ /* set start address */
+ ctWrite_i (CT_XR_O, 0xa2, (cursor_start >> 8) & 0xf0);
+ ctWrite_i (CT_XR_O, 0xa3, (cursor_start >> 16) & 0x3f);
+ /* set cursor shape */
+ curs = (unsigned long *) cursor_start;
+ i = 0;
+ while (i < 0x400) {
+ curs[i++] = 0xffffffff; /* AND mask */
+ curs[i++] = 0xffffffff; /* AND mask */
+ curs[i++] = 0; /* XOR mask */
+ curs[i++] = 0; /* XOR mask */
+ /* Transparent */
+ }
+ pattern = 0xffffffff >> font_width;
+ i = 0;
+ while (i < (font_height * 2)) {
+ curs[i++] = pattern; /* AND mask */
+ curs[i++] = pattern; /* AND mask */
+ curs[i++] = 0; /* XOR mask */
+ curs[i++] = 0; /* XOR mask */
+ /* Cursor Color 0 */
+ }
+ /* set blink rate */
+ ctWrite_i (CT_FP_O, 0x19, 0xf);
+
+ /* set cursors colors */
+ xr_80 = ctRead_i (CT_XR_O, 0x80);
+ xr_80 |= 0x1; /* alternate palette select */
+ ctWrite_i (CT_XR_O, 0x80, xr_80);
+ video_set_lut (4, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
+ /* position 4 is color 0 cursor 0 */
+ xr_80 &= 0xfe; /* normal palette select */
+ ctWrite_i (CT_XR_O, 0x80, xr_80);
+ /* cursor enable */
+ ctWrite_i (CT_XR_O, 0xa0, 0x91);
+ xr_80 |= 0x10; /* enable hwcursor */
+ ctWrite_i (CT_XR_O, 0x80, xr_80);
+ video_set_hw_cursor (0, 0);
+}
+#endif /* CONFIG_VIDEO_HW_CURSOR */
+
+/***************************************************************
+ * Wait for BitBlt ready
+ */
+static int
+video_wait_bitblt (unsigned long addr)
+{
+ unsigned long br04;
+ int i = 0;
+ br04 = in32r (addr);
+ while (br04 & 0x80000000) {
+ udelay (1);
+ br04 = in32r (addr);
+ if (i++ > 1000000) {
+ printf ("ERROR Timeout %lx\n", br04);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/***************************************************************
+ * Set up BitBlt Registrs
+ */
+static void
+SetDrawingEngine (int bits_per_pixel)
+{
+ unsigned long br04, br00;
+ unsigned char tmp;
+
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+
+ tmp = ctRead_i (CT_XR_O, 0x20); /* BitBLT Configuration */
+ tmp |= 0x02; /* reset BitBLT */
+ ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+ udelay (10);
+ tmp &= 0xfd; /* release reset BitBLT */
+ ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+
+ /* set pattern Address */
+ out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8);
+ br04 = 0;
+ if (bits_per_pixel == 1) {
+ br04 |= 0x00040000; /* monochome Pattern */
+ br04 |= 0x00001000; /* monochome source */
+ }
+ br00 = ((pGD->winSizeX * pGD->gdfBytesPP) << 16) + (pGD->winSizeX * pGD->gdfBytesPP); /* bytes per scanline */
+ out32r (pGD->pciBase + BR00_o, br00); /* */
+ out32r (pGD->pciBase + BR08_o, (10 << 16) + 10); /* dummy */
+ out32r (pGD->pciBase + BR04_o, br04); /* write all 0 */
+ out32r (pGD->pciBase + BR07_o, 0); /* destination */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+/****************************************************************************
+* supported Video Chips
+*/
+static struct pci_device_id supported[] = {
+ {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000},
+#ifdef CONFIG_USE_CPCIDVI
+ {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69030},
+#endif
+ {}
+};
+
+/*******************************************************************************
+*
+* Init video chip
+*/
+void *
+video_hw_init (void)
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ unsigned short device_id;
+ pci_dev_t devbusfn;
+ int videomode;
+ unsigned long t1, hsynch, vsynch;
+ unsigned int pci_mem_base, *vm;
+ int tmp, i, bits_per_pixel;
+ char *penv;
+ struct ctfb_res_modes *res_mode;
+ struct ctfb_res_modes var_mode;
+ struct ctfb_chips_properties *chips_param;
+ /* Search for video chip */
+
+ if ((devbusfn = pci_find_devices (supported, 0)) < 0) {
+#ifdef CONFIG_VIDEO_ONBOARD
+ printf ("Video: Controller not found !\n");
+#endif
+ return (NULL);
+ }
+
+ /* PCI setup */
+ pci_write_config_dword (devbusfn, PCI_COMMAND,
+ (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+ pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
+ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
+ pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
+
+ /* get chips params */
+ for (chips_param = (struct ctfb_chips_properties *) &chips[0];
+ chips_param->device_id != 0; chips_param++) {
+ if (chips_param->device_id == device_id)
+ break;
+ }
+ if (chips_param->device_id == 0) {
+#ifdef CONFIG_VIDEO_ONBOARD
+ printf ("Video: controller 0x%X not supported\n", device_id);
+#endif
+ return NULL;
+ }
+ /* supported Video controller found */
+ printf ("Video: ");
+
+ tmp = 0;
+ videomode = 0x301;
+ /* get video mode via environment */
+ if ((penv = getenv ("videomode")) != NULL) {
+ /* deceide if it is a string */
+ if (penv[0] <= '9') {
+ videomode = (int) simple_strtoul (penv, NULL, 16);
+ tmp = 1;
+ }
+ } else {
+ tmp = 1;
+ }
+ if (tmp) {
+ /* parameter are vesa modes */
+ /* search params */
+ for (i = 0; i < VESA_MODES_COUNT; i++) {
+ if (vesa_modes[i].vesanr == videomode)
+ break;
+ }
+ if (i == VESA_MODES_COUNT) {
+ printf ("no VESA Mode found, switching to mode 0x301 ");
+ i = 0;
+ }
+ res_mode =
+ (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
+ resindex];
+ bits_per_pixel = vesa_modes[i].bits_per_pixel;
+ } else {
+
+ res_mode = (struct ctfb_res_modes *) &var_mode;
+ bits_per_pixel = video_get_params (res_mode, penv);
+ }
+
+ /* calculate available color depth for controller memory */
+ if (bits_per_pixel == 15)
+ tmp = 2;
+ else
+ tmp = bits_per_pixel >> 3; /* /8 */
+ if (((chips_param->max_mem -
+ ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) {
+ tmp =
+ ((chips_param->max_mem -
+ ACCELMEMORY) / (res_mode->xres * res_mode->yres));
+ if (tmp == 0) {
+ printf
+ ("No matching videomode found .-> reduce resolution\n");
+ return NULL;
+ } else {
+ printf ("Switching back to %d Bits per Pixel ",
+ tmp << 3);
+ bits_per_pixel = tmp << 3;
+ }
+ }
+
+ /* calculate hsynch and vsynch freq (info only) */
+ t1 = (res_mode->left_margin + res_mode->xres +
+ res_mode->right_margin + res_mode->hsync_len) / 8;
+ t1 *= 8;
+ t1 *= res_mode->pixclock;
+ t1 /= 1000;
+ hsynch = 1000000000L / t1;
+ t1 *=
+ (res_mode->upper_margin + res_mode->yres +
+ res_mode->lower_margin + res_mode->vsync_len);
+ t1 /= 1000;
+ vsynch = 1000000000L / t1;
+
+ /* fill in Graphic device struct */
+ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
+ res_mode->yres, bits_per_pixel, (hsynch / 1000),
+ (vsynch / 1000));
+ printf ("%s\n", pGD->modeIdent);
+ pGD->winSizeX = res_mode->xres;
+ pGD->winSizeY = res_mode->yres;
+ pGD->plnSizeX = res_mode->xres;
+ pGD->plnSizeY = res_mode->yres;
+ switch (bits_per_pixel) {
+ case 8:
+ pGD->gdfBytesPP = 1;
+ pGD->gdfIndex = GDF__8BIT_INDEX;
+ break;
+ case 15:
+ pGD->gdfBytesPP = 2;
+ pGD->gdfIndex = GDF_15BIT_555RGB;
+ break;
+ case 16:
+ pGD->gdfBytesPP = 2;
+ pGD->gdfIndex = GDF_16BIT_565RGB;
+ break;
+ case 24:
+ pGD->gdfBytesPP = 3;
+ pGD->gdfIndex = GDF_24BIT_888RGB;
+ break;
+ }
+ pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
+ pGD->pciBase = pci_mem_base;
+ pGD->frameAdrs = pci_mem_base;
+ pGD->memSize = chips_param->max_mem;
+ /* Cursor Start Address */
+ pGD->dprBase =
+ (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base;
+ if ((pGD->dprBase & 0x0fff) != 0) {
+ /* allign it */
+ pGD->dprBase &= 0xfffff000;
+ pGD->dprBase += 0x00001000;
+ }
+ PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
+ PATTERN_ADR);
+ pGD->vprBase = pci_mem_base; /* Dummy */
+ pGD->cprBase = pci_mem_base; /* Dummy */
+ /* set up Hardware */
+
+#ifdef CONFIG_USE_CPCIDVI
+ if (device_id == PCI_DEVICE_ID_CT_69030) {
+ ctWrite (CT_MSR_W_O, 0x0b);
+ ctWrite (0x3cd, 0x13);
+ ctWrite_i (CT_FP_O, 0x02, 0x00);
+ ctWrite_i (CT_FP_O, 0x05, 0x00);
+ ctWrite_i (CT_FP_O, 0x06, 0x00);
+ ctWrite (0x3c2, 0x0b);
+ ctWrite_i (CT_FP_O, 0x02, 0x10);
+ ctWrite_i (CT_FP_O, 0x01, 0x09);
+ } else {
+ ctWrite (CT_MSR_W_O, 0x01);
+ }
+#else
+ ctWrite (CT_MSR_W_O, 0x01);
+#endif
+
+ /* set the extended Registers */
+ ctLoadRegs (CT_XR_O, xreg);
+ /* set atribute registers */
+ SetArRegs ();
+ /* set Graphics register */
+ SetGrRegs ();
+ /* set sequencer */
+ SetSrRegs ();
+
+ /* set msr */
+ SetMsrRegs (res_mode);
+
+ /* set CRT Registers */
+ SetCrRegs (res_mode, bits_per_pixel);
+ /* set color mode */
+ SetBitsPerPixelIntoXrRegs (bits_per_pixel);
+
+ /* set PLL */
+ FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param);
+
+ ctWrite_i (CT_SR_O, 0, 0x03); /* clear synchronous reset */
+ /* Clear video memory */
+ i = pGD->memSize / 4;
+ vm = (unsigned int *) pGD->pciBase;
+ while (i--)
+ *vm++ = 0;
+ SetDrawingEngine (bits_per_pixel);
+#ifdef VGA_DUMP_REG
+ video_dump_reg ();
+#endif
+
+ return ((void *) &ctfb);
+}
+
+ /*******************************************************************************
+*
+* Set a RGB color in the LUT (8 bit index)
+*/
+void
+video_set_lut (unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+
+ ctWrite (CT_LUT_MASK_O, 0xff);
+
+ ctWrite (CT_LUT_START_O, (char) index);
+
+ ctWrite (CT_LUT_RGB_O, r); /* red */
+ ctWrite (CT_LUT_RGB_O, g); /* green */
+ ctWrite (CT_LUT_RGB_O, b); /* blue */
+ udelay (1);
+ ctWrite (CT_LUT_MASK_O, 0xff);
+}
+
+/*******************************************************************************
+*
+* Drawing engine fill on screen region
+*/
+void
+video_hw_rectfill (unsigned int bpp, /* bytes per pixel */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y, /* frame height */
+ unsigned int color /* fill color */
+ )
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ unsigned long *p, br04;
+
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+
+ p = (unsigned long *) PATTERN_ADR;
+ dim_x *= bpp;
+ if (bpp == 3)
+ bpp++; /* 24Bit needs a 32bit pattern */
+ memset (p, color, (bpp * sizeof (unsigned char) * 8 * 8)); /* 8 x 8 pattern data */
+ out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP); /* destination */
+ br04 = in32r (pGD->pciBase + BR04_o) & 0xffffff00;
+ br04 |= 0xF0; /* write Pattern P -> D */
+ out32r (pGD->pciBase + BR04_o, br04); /* */
+ out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* starts the BITBlt */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+/*******************************************************************************
+*
+* Drawing engine bitblt with screen region
+*/
+void
+video_hw_bitblt (unsigned int bpp, /* bytes per pixel */
+ unsigned int src_x, /* source pos x */
+ unsigned int src_y, /* source pos y */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y /* frame height */
+ )
+{
+ GraphicDevice *pGD = (GraphicDevice *) & ctfb;
+ unsigned long br04;
+
+ br04 = in32r (pGD->pciBase + BR04_o);
+
+ /* to prevent data corruption due to overlap, we have to
+ * find out if, and how the frames overlaps */
+ if (src_x < dst_x) {
+ /* src is more left than dest
+ * the frame may overlap -> start from right to left */
+ br04 |= 0x00000100; /* set bit 8 */
+ src_x += dim_x;
+ dst_x += dim_x;
+ } else {
+ br04 &= 0xfffffeff; /* clear bit 8 left to right */
+ }
+ if (src_y < dst_y) {
+ /* src is higher than dst
+ * the frame may overlap => start from bottom */
+ br04 |= 0x00000200; /* set bit 9 */
+ src_y += dim_y;
+ dst_y += dim_y;
+ } else {
+ br04 &= 0xfffffdff; /* clear bit 9 top to bottom */
+ }
+ dim_x *= bpp;
+ out32r (pGD->pciBase + BR06_o, ((pGD->winSizeX * src_y) + src_x) * pGD->gdfBytesPP); /* source */
+ out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP); /* destination */
+ br04 &= 0xffffff00;
+ br04 |= 0x000000CC; /* S -> D */
+ out32r (pGD->pciBase + BR04_o, br04); /* */
+ out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* start the BITBlt */
+ video_wait_bitblt (pGD->pciBase + BR04_o);
+}
+
+#endif /* CONFIG_CT69000 */
+
+#endif /* CONFIG_VIDEO */
diff --git a/drivers/video/sed13806.c b/drivers/video/sed13806.c
new file mode 100644
index 0000000..6996ca8
--- /dev/null
+++ b/drivers/video/sed13806.c
@@ -0,0 +1,310 @@
+/*
+ * (C) Copyright 2002
+ * Stäubli Faverges - <www.staubli.com>
+ * Pierre AUBERT p.aubert@staubli.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/* Video support for Epson SED13806 chipset */
+
+#include <common.h>
+
+#ifdef CONFIG_VIDEO_SED13806
+
+#include <video_fb.h>
+#include <sed13806.h>
+
+#define readByte(ptrReg) \
+ *(volatile unsigned char *)(sed13806.isaBase + ptrReg)
+
+#define writeByte(ptrReg,value) \
+ *(volatile unsigned char *)(sed13806.isaBase + ptrReg) = value
+
+#ifdef CONFIG_TOTAL5200
+#define writeWord(ptrReg,value) \
+ (*(volatile unsigned short *)(sed13806.isaBase + ptrReg) = value)
+#else
+#define writeWord(ptrReg,value) \
+ (*(volatile unsigned short *)(sed13806.isaBase + ptrReg) = ((value >> 8 ) & 0xff) | ((value << 8) & 0xff00))
+#endif
+
+GraphicDevice sed13806;
+
+/*-----------------------------------------------------------------------------
+ * EpsonSetRegs --
+ *-----------------------------------------------------------------------------
+ */
+static void EpsonSetRegs (void)
+{
+ /* the content of the chipset register depends on the board (clocks, ...)*/
+ const S1D_REGS *preg = board_get_regs ();
+ while (preg -> Index) {
+ writeByte (preg -> Index, preg -> Value);
+ preg ++;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * video_hw_init --
+ *-----------------------------------------------------------------------------
+ */
+void *video_hw_init (void)
+{
+ unsigned int *vm, i;
+
+ memset (&sed13806, 0, sizeof (GraphicDevice));
+
+ /* Initialization of the access to the graphic chipset
+ Retreive base address of the chipset
+ (see board/RPXClassic/eccx.c) */
+ if ((sed13806.isaBase = board_video_init ()) == 0) {
+ return (NULL);
+ }
+
+ sed13806.frameAdrs = sed13806.isaBase + FRAME_BUFFER_OFFSET;
+ sed13806.winSizeX = board_get_width ();
+ sed13806.winSizeY = board_get_height ();
+
+#if defined(CONFIG_VIDEO_SED13806_8BPP)
+ sed13806.gdfIndex = GDF__8BIT_INDEX;
+ sed13806.gdfBytesPP = 1;
+
+#elif defined(CONFIG_VIDEO_SED13806_16BPP)
+ sed13806.gdfIndex = GDF_16BIT_565RGB;
+ sed13806.gdfBytesPP = 2;
+
+#else
+#error Unsupported SED13806 BPP
+#endif
+
+ sed13806.memSize = sed13806.winSizeX * sed13806.winSizeY * sed13806.gdfBytesPP;
+
+ /* Load SED registers */
+ EpsonSetRegs ();
+
+ /* (see board/RPXClassic/RPXClassic.c) */
+ board_validate_screen (sed13806.isaBase);
+
+ /* Clear video memory */
+ i = sed13806.memSize/4;
+ vm = (unsigned int *)sed13806.frameAdrs;
+ while(i--)
+ *vm++ = 0;
+
+
+ return (&sed13806);
+}
+/*-----------------------------------------------------------------------------
+ * Epson_wait_idle -- Wait for hardware to become idle
+ *-----------------------------------------------------------------------------
+ */
+static void Epson_wait_idle (void)
+{
+ while (readByte (BLT_CTRL0) & 0x80);
+
+ /* Read a word in the BitBLT memory area to shutdown the BitBLT engine */
+ *(volatile unsigned short *)(sed13806.isaBase + BLT_REG);
+}
+
+/*-----------------------------------------------------------------------------
+ * video_hw_bitblt --
+ *-----------------------------------------------------------------------------
+ */
+void video_hw_bitblt (
+ unsigned int bpp, /* bytes per pixel */
+ unsigned int src_x, /* source pos x */
+ unsigned int src_y, /* source pos y */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y /* frame height */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&sed13806;
+ unsigned long srcAddr, dstAddr;
+ unsigned int stride = bpp * pGD -> winSizeX;
+
+ srcAddr = (src_y * stride) + (src_x * bpp);
+ dstAddr = (dst_y * stride) + (dst_x * bpp);
+
+ Epson_wait_idle ();
+
+ writeByte(BLT_ROP,0x0C); /* source */
+ writeByte(BLT_OP,0x02);/* move blit in positive direction with ROP */
+ writeWord(BLT_MEM_OFF0, stride / 2);
+ if (pGD -> gdfIndex == GDF__8BIT_INDEX) {
+ writeByte(BLT_CTRL1,0x00);
+ }
+ else {
+ writeByte(BLT_CTRL1,0x01);
+ }
+
+ writeWord(BLT_WIDTH0,(dim_x - 1));
+ writeWord(BLT_HEIGHT0,(dim_y - 1));
+
+ /* set up blit registers */
+ writeByte(BLT_SRC_ADDR0,srcAddr);
+ writeByte(BLT_SRC_ADDR1,srcAddr>>8);
+ writeByte(BLT_SRC_ADDR2,srcAddr>>16);
+
+ writeByte(BLT_DST_ADDR0,dstAddr);
+ writeByte(BLT_DST_ADDR1,dstAddr>>8);
+ writeByte(BLT_DST_ADDR2,dstAddr>>16);
+
+ /* Engage the blt engine */
+ /* rectangular region for src and dst */
+ writeByte(BLT_CTRL0,0x80);
+
+ /* wait untill current blits finished */
+ Epson_wait_idle ();
+}
+/*-----------------------------------------------------------------------------
+ * video_hw_rectfill --
+ *-----------------------------------------------------------------------------
+ */
+void video_hw_rectfill (
+ unsigned int bpp, /* bytes per pixel */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y, /* frame height */
+ unsigned int color /* fill color */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&sed13806;
+ unsigned long dstAddr;
+ unsigned int stride = bpp * pGD -> winSizeX;
+
+ dstAddr = (dst_y * stride) + (dst_x * bpp);
+
+ Epson_wait_idle ();
+
+ /* set up blit registers */
+ writeByte(BLT_DST_ADDR0,dstAddr);
+ writeByte(BLT_DST_ADDR1,dstAddr>>8);
+ writeByte(BLT_DST_ADDR2,dstAddr>>16);
+
+ writeWord(BLT_WIDTH0,(dim_x - 1));
+ writeWord(BLT_HEIGHT0,(dim_y - 1));
+ writeWord(BLT_FGCOLOR0,color);
+
+ writeByte(BLT_OP,0x0C); /* solid fill */
+ writeWord(BLT_MEM_OFF0,stride / 2);
+
+ if (pGD -> gdfIndex == GDF__8BIT_INDEX) {
+ writeByte(BLT_CTRL1,0x00);
+ }
+ else {
+ writeByte(BLT_CTRL1,0x01);
+ }
+
+ /* Engage the blt engine */
+ /* rectangular region for src and dst */
+ writeByte(BLT_CTRL0,0x80);
+
+ /* wait untill current blits finished */
+ Epson_wait_idle ();
+}
+
+/*-----------------------------------------------------------------------------
+ * video_set_lut --
+ *-----------------------------------------------------------------------------
+ */
+void video_set_lut (
+ unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+ writeByte(REG_LUT_ADDR, index );
+ writeByte(REG_LUT_DATA, r);
+ writeByte(REG_LUT_DATA, g);
+ writeByte(REG_LUT_DATA, b);
+}
+#ifdef CONFIG_VIDEO_HW_CURSOR
+/*-----------------------------------------------------------------------------
+ * video_set_hw_cursor --
+ *-----------------------------------------------------------------------------
+ */
+void video_set_hw_cursor (int x, int y)
+{
+ writeByte (LCD_CURSOR_XL, (x & 0xff));
+ writeByte (LCD_CURSOR_XM, (x >> 8));
+ writeByte (LCD_CURSOR_YL, (y & 0xff));
+ writeByte (LCD_CURSOR_YM, (y >> 8));
+}
+
+/*-----------------------------------------------------------------------------
+ * video_init_hw_cursor --
+ *-----------------------------------------------------------------------------
+ */
+void video_init_hw_cursor (int font_width, int font_height)
+{
+ volatile unsigned char *ptr;
+ unsigned char pattern;
+ int i;
+
+
+ /* Init cursor content
+ Cursor size is 64x64 pixels
+ Start of the cursor memory depends on panel type (dual panel ...) */
+ if ((i = readByte (LCD_CURSOR_START)) == 0) {
+ ptr = (unsigned char *)(sed13806.frameAdrs + DEFAULT_VIDEO_MEMORY_SIZE - HWCURSORSIZE);
+ }
+ else {
+ ptr = (unsigned char *)(sed13806.frameAdrs + DEFAULT_VIDEO_MEMORY_SIZE - (i * 8192));
+ }
+
+ /* Fill the first line and the first empty line after cursor */
+ for (i = 0, pattern = 0; i < 64; i++) {
+ if (i < font_width) {
+ /* Invert background */
+ pattern |= 0x3;
+
+ }
+ else {
+ /* Background */
+ pattern |= 0x2;
+ }
+ if ((i & 3) == 3) {
+ *ptr = pattern;
+ *(ptr + font_height * 16) = 0xaa;
+ ptr ++;
+ pattern = 0;
+ }
+ pattern <<= 2;
+ }
+
+ /* Duplicate this line */
+ for (i = 1; i < font_height; i++) {
+ memcpy ((void *)ptr, (void *)(ptr - 16), 16);
+ ptr += 16;
+ }
+
+ for (; i < 64; i++) {
+ memcpy ((void *)(ptr + 16), (void *)ptr, 16);
+ ptr += 16;
+ }
+
+ /* Select cursor mode */
+ writeByte (LCD_CURSOR_CNTL, 1);
+}
+#endif
+#endif
diff --git a/drivers/video/sed156x.c b/drivers/video/sed156x.c
new file mode 100644
index 0000000..e9d5ed4
--- /dev/null
+++ b/drivers/video/sed156x.c
@@ -0,0 +1,566 @@
+/*
+ * (C) Copyright 2003
+ *
+ * Pantelis Antoniou <panto@intracom.gr>
+ * Intracom S.A.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <watchdog.h>
+
+#include <sed156x.h>
+
+#ifdef CONFIG_SED156X
+
+/* configure according to the selected display */
+#if defined(CONFIG_SED156X_PG12864Q)
+#define LCD_WIDTH 128
+#define LCD_HEIGHT 64
+#define LCD_LINES 64
+#define LCD_PAGES 9
+#define LCD_COLUMNS 132
+#else
+#error Unsupported SED156x configuration
+#endif
+
+/* include the font data */
+#include <video_font.h>
+
+#if VIDEO_FONT_WIDTH != 8 || VIDEO_FONT_HEIGHT != 16
+#error Expecting VIDEO_FONT_WIDTH == 8 && VIDEO_FONT_HEIGHT == 16
+#endif
+
+#define LCD_BYTE_WIDTH (LCD_WIDTH / 8)
+#define VIDEO_FONT_BYTE_WIDTH (VIDEO_FONT_WIDTH / 8)
+
+#define LCD_TEXT_WIDTH (LCD_WIDTH / VIDEO_FONT_WIDTH)
+#define LCD_TEXT_HEIGHT (LCD_HEIGHT / VIDEO_FONT_HEIGHT)
+
+#define LCD_BYTE_LINESZ (LCD_BYTE_WIDTH * VIDEO_FONT_HEIGHT)
+
+const int sed156x_text_width = LCD_TEXT_WIDTH;
+const int sed156x_text_height = LCD_TEXT_HEIGHT;
+
+/**************************************************************************************/
+
+#define SED156X_SPI_RXD() (SED156X_SPI_RXD_PORT & SED156X_SPI_RXD_MASK)
+
+#define SED156X_SPI_TXD(x) \
+ do { \
+ if (x) \
+ SED156X_SPI_TXD_PORT |= SED156X_SPI_TXD_MASK; \
+ else \
+ SED156X_SPI_TXD_PORT &= ~SED156X_SPI_TXD_MASK; \
+ } while(0)
+
+#define SED156X_SPI_CLK(x) \
+ do { \
+ if (x) \
+ SED156X_SPI_CLK_PORT |= SED156X_SPI_CLK_MASK; \
+ else \
+ SED156X_SPI_CLK_PORT &= ~SED156X_SPI_CLK_MASK; \
+ } while(0)
+
+#define SED156X_SPI_CLK_TOGGLE() (SED156X_SPI_CLK_PORT ^= SED156X_SPI_CLK_MASK)
+
+#define SED156X_SPI_BIT_DELAY() /* no delay */
+
+#define SED156X_CS(x) \
+ do { \
+ if (x) \
+ SED156X_CS_PORT |= SED156X_CS_MASK; \
+ else \
+ SED156X_CS_PORT &= ~SED156X_CS_MASK; \
+ } while(0)
+
+#define SED156X_A0(x) \
+ do { \
+ if (x) \
+ SED156X_A0_PORT |= SED156X_A0_MASK; \
+ else \
+ SED156X_A0_PORT &= ~SED156X_A0_MASK; \
+ } while(0)
+
+/**************************************************************************************/
+
+/*** LCD Commands ***/
+
+#define LCD_ON 0xAF /* Display ON */
+#define LCD_OFF 0xAE /* Display OFF */
+#define LCD_LADDR 0x40 /* Display start line set + (6-bit) address */
+#define LCD_PADDR 0xB0 /* Page address set + (4-bit) page */
+#define LCD_CADRH 0x10 /* Column address set upper + (4-bit) column hi */
+#define LCD_CADRL 0x00 /* Column address set lower + (4-bit) column lo */
+#define LCD_ADC_NRM 0xA0 /* ADC select Normal */
+#define LCD_ADC_REV 0xA1 /* ADC select Reverse */
+#define LCD_DSP_NRM 0xA6 /* LCD display Normal */
+#define LCD_DSP_REV 0xA7 /* LCD display Reverse */
+#define LCD_DPT_NRM 0xA4 /* Display all points Normal */
+#define LCD_DPT_ALL 0xA5 /* Display all points ON */
+#define LCD_BIAS9 0xA2 /* LCD bias set 1/9 */
+#define LCD_BIAS7 0xA3 /* LCD bias set 1/7 */
+#define LCD_CAINC 0xE0 /* Read/modify/write */
+#define LCD_CAEND 0xEE /* End */
+#define LCD_RESET 0xE2 /* Reset */
+#define LCD_C_NRM 0xC0 /* Common output mode select Normal direction */
+#define LCD_C_RVS 0xC8 /* Common output mode select Reverse direction */
+#define LCD_PWRMD 0x28 /* Power control set + (3-bit) mode */
+#define LCD_RESRT 0x20 /* V5 v. reg. int. resistor ratio set + (3-bit) ratio */
+#define LCD_EVSET 0x81 /* Electronic volume mode set + byte = (6-bit) volume */
+#define LCD_SIOFF 0xAC /* Static indicator OFF */
+#define LCD_SION 0xAD /* Static indicator ON + byte = (2-bit) mode */
+#define LCD_NOP 0xE3 /* NOP */
+#define LCD_TEST 0xF0 /* Test/Test mode reset (Note: *DO NOT USE*) */
+
+/*-------------------------------------------------------------------------------
+ Compound commands
+ -------------------------------------------------------------------------------
+ Command Description Commands
+ ---------- ------------------------ -------------------------------------
+ POWS_ON POWER SAVER ON command LCD_OFF, LCD_D_ALL
+ POWS_OFF POWER SAVER OFF command LCD_D_NRM
+ SLEEPON SLEEP mode LCD_SIOFF, POWS_ON
+ SLEEPOFF SLEEP mode cancel LCD_D_NRM, LCD_SION, LCD_SIS_???
+ STDBYON STAND BY mode LCD_SION, POWS_ON
+ STDBYOFF STAND BY mode cancel LCD_D_NRM
+ -------------------------------------------------------------------------------*/
+
+/*** LCD various parameters ***/
+#define LCD_PPB 8 /* Pixels per byte (display is B/W, 1 bit per pixel) */
+
+/*** LCD Status byte masks ***/
+#define LCD_S_BUSY 0x80 /* Status Read - BUSY mask */
+#define LCD_S_ADC 0x40 /* Status Read - ADC mask */
+#define LCD_S_ONOFF 0x20 /* Status Read - ON/OFF mask */
+#define LCD_S_RESET 0x10 /* Status Read - RESET mask */
+
+/*** LCD commands parameter masks ***/
+#define LCD_M_LADDR 0x3F /* Display start line (6-bit) address mask */
+#define LCD_M_PADDR 0x0F /* Page address (4-bit) page mask */
+#define LCD_M_CADRH 0x0F /* Column address upper (4-bit) column hi mask */
+#define LCD_M_CADRL 0x0F /* Column address lower (4-bit) column lo mask */
+#define LCD_M_PWRMD 0x07 /* Power control (3-bit) mode mask */
+#define LCD_M_RESRT 0x07 /* V5 v. reg. int. resistor ratio (3-bit) ratio mask */
+#define LCD_M_EVSET 0x3F /* Electronic volume mode byte (6-bit) volume mask */
+#define LCD_M_SION 0x03 /* Static indicator ON (2-bit) mode mask */
+
+/*** LCD Power control cirquits control masks ***/
+#define LCD_PWRBSTR 0x04 /* Power control mode - Booster cirquit ON */
+#define LCD_PWRVREG 0x02 /* Power control mode - Voltage regulator cirquit ON */
+#define LCD_PWRVFOL 0x01 /* Power control mode - Voltage follower cirquit ON */
+
+/*** LCD Static indicator states ***/
+#define LCD_SIS_OFF 0x00 /* Static indicator register set - OFF state */
+#define LCD_SIS_BL 0x01 /* Static indicator register set - 1s blink state */
+#define LCD_SIS_RBL 0x02 /* Static indicator register set - .5s rapid blink state */
+#define LCD_SIS_ON 0x03 /* Static indicator register set - constantly on state */
+
+/*** LCD functions special parameters (commands) ***/
+#define LCD_PREVP 0x80 /* Page number for moving to previous */
+#define LCD_NEXTP 0x81 /* or next page */
+#define LCD_ERR_P 0xFF /* Error in page number */
+
+/*** LCD initialization settings ***/
+#define LCD_BIAS LCD_BIAS9 /* Bias: 1/9 */
+#define LCD_ADCMODE LCD_ADC_NRM /* ADC mode: normal */
+#define LCD_COMDIR LCD_C_NRM /* Common output mode: normal */
+#define LCD_RRATIO 0 /* Resistor ratio: 0 */
+#define LCD_CNTRST 0x1C /* electronic volume: 1Ch */
+#define LCD_POWERM (LCD_PWRBSTR | LCD_PWRVREG | LCD_PWRVFOL) /* Power mode: All on */
+
+/**************************************************************************************/
+
+static inline unsigned int sed156x_transfer(unsigned int val)
+{
+ unsigned int rx;
+ int b;
+
+ rx = 0; b = 8;
+ while (--b >= 0) {
+ SED156X_SPI_TXD(val & 0x80);
+ val <<= 1;
+ SED156X_SPI_CLK_TOGGLE();
+ SED156X_SPI_BIT_DELAY();
+ rx <<= 1;
+ if (SED156X_SPI_RXD())
+ rx |= 1;
+ SED156X_SPI_CLK_TOGGLE();
+ SED156X_SPI_BIT_DELAY();
+ }
+
+ return rx;
+}
+
+unsigned int sed156x_data_transfer(unsigned int val)
+{
+ unsigned int rx;
+
+ SED156X_SPI_CLK(1);
+ SED156X_CS(0);
+ SED156X_A0(1);
+
+ rx = sed156x_transfer(val);
+
+ SED156X_CS(1);
+
+ return rx;
+}
+
+void sed156x_data_block_transfer(const u8 *p, int size)
+{
+ SED156X_SPI_CLK(1);
+ SED156X_CS(0);
+ SED156X_A0(1);
+
+ while (--size >= 0)
+ sed156x_transfer(*p++);
+
+ SED156X_CS(1);
+}
+
+unsigned int sed156x_cmd_transfer(unsigned int val)
+{
+ unsigned int rx;
+
+ SED156X_SPI_CLK(1);
+ SED156X_CS(0);
+ SED156X_A0(0);
+
+ rx = sed156x_transfer(val);
+
+ SED156X_CS(1);
+ SED156X_A0(1);
+
+ return rx;
+}
+
+/******************************************************************************/
+
+static u8 hw_screen[LCD_PAGES][LCD_COLUMNS];
+static u8 last_hw_screen[LCD_PAGES][LCD_COLUMNS];
+static u8 sw_screen[LCD_BYTE_WIDTH * LCD_HEIGHT];
+
+void sed156x_sync(void)
+{
+ int i, j, last_page;
+ u8 *d;
+ const u8 *s, *e, *b, *r;
+ u8 v0, v1, v2, v3, v4, v5, v6, v7;
+
+ /* copy and rotate sw_screen to hw_screen */
+ for (i = 0; i < LCD_HEIGHT / 8; i++) {
+
+ d = &hw_screen[i][0];
+ s = &sw_screen[LCD_BYTE_WIDTH * 8 * i + LCD_BYTE_WIDTH - 1];
+
+ for (j = 0; j < LCD_WIDTH / 8; j++) {
+
+ v0 = s[0 * LCD_BYTE_WIDTH];
+ v1 = s[1 * LCD_BYTE_WIDTH];
+ v2 = s[2 * LCD_BYTE_WIDTH];
+ v3 = s[3 * LCD_BYTE_WIDTH];
+ v4 = s[4 * LCD_BYTE_WIDTH];
+ v5 = s[5 * LCD_BYTE_WIDTH];
+ v6 = s[6 * LCD_BYTE_WIDTH];
+ v7 = s[7 * LCD_BYTE_WIDTH];
+
+ d[0] = ((v7 & 0x01) << 7) |
+ ((v6 & 0x01) << 6) |
+ ((v5 & 0x01) << 5) |
+ ((v4 & 0x01) << 4) |
+ ((v3 & 0x01) << 3) |
+ ((v2 & 0x01) << 2) |
+ ((v1 & 0x01) << 1) |
+ (v0 & 0x01) ;
+
+ d[1] = ((v7 & 0x02) << 6) |
+ ((v6 & 0x02) << 5) |
+ ((v5 & 0x02) << 4) |
+ ((v4 & 0x02) << 3) |
+ ((v3 & 0x02) << 2) |
+ ((v2 & 0x02) << 1) |
+ ((v1 & 0x02) << 0) |
+ ((v0 & 0x02) >> 1) ;
+
+ d[2] = ((v7 & 0x04) << 5) |
+ ((v6 & 0x04) << 4) |
+ ((v5 & 0x04) << 3) |
+ ((v4 & 0x04) << 2) |
+ ((v3 & 0x04) << 1) |
+ (v2 & 0x04) |
+ ((v1 & 0x04) >> 1) |
+ ((v0 & 0x04) >> 2) ;
+
+ d[3] = ((v7 & 0x08) << 4) |
+ ((v6 & 0x08) << 3) |
+ ((v5 & 0x08) << 2) |
+ ((v4 & 0x08) << 1) |
+ (v3 & 0x08) |
+ ((v2 & 0x08) >> 1) |
+ ((v1 & 0x08) >> 2) |
+ ((v0 & 0x08) >> 3) ;
+
+ d[4] = ((v7 & 0x10) << 3) |
+ ((v6 & 0x10) << 2) |
+ ((v5 & 0x10) << 1) |
+ (v4 & 0x10) |
+ ((v3 & 0x10) >> 1) |
+ ((v2 & 0x10) >> 2) |
+ ((v1 & 0x10) >> 3) |
+ ((v0 & 0x10) >> 4) ;
+
+ d[5] = ((v7 & 0x20) << 2) |
+ ((v6 & 0x20) << 1) |
+ (v5 & 0x20) |
+ ((v4 & 0x20) >> 1) |
+ ((v3 & 0x20) >> 2) |
+ ((v2 & 0x20) >> 3) |
+ ((v1 & 0x20) >> 4) |
+ ((v0 & 0x20) >> 5) ;
+
+ d[6] = ((v7 & 0x40) << 1) |
+ (v6 & 0x40) |
+ ((v5 & 0x40) >> 1) |
+ ((v4 & 0x40) >> 2) |
+ ((v3 & 0x40) >> 3) |
+ ((v2 & 0x40) >> 4) |
+ ((v1 & 0x40) >> 5) |
+ ((v0 & 0x40) >> 6) ;
+
+ d[7] = (v7 & 0x80) |
+ ((v6 & 0x80) >> 1) |
+ ((v5 & 0x80) >> 2) |
+ ((v4 & 0x80) >> 3) |
+ ((v3 & 0x80) >> 4) |
+ ((v2 & 0x80) >> 5) |
+ ((v1 & 0x80) >> 6) |
+ ((v0 & 0x80) >> 7) ;
+
+ d += 8;
+ s--;
+ }
+ }
+
+ /* and now output only the differences */
+ for (i = 0; i < LCD_PAGES; i++) {
+
+ b = &hw_screen[i][0];
+ e = &hw_screen[i][LCD_COLUMNS];
+
+ d = &last_hw_screen[i][0];
+ s = b;
+
+ last_page = -1;
+
+ /* update only the differences */
+ do {
+ while (s < e && *s == *d) {
+ s++;
+ d++;
+ }
+ if (s == e)
+ break;
+ r = s;
+ while (s < e && *s != *d)
+ *d++ = *s++;
+
+ j = r - b;
+
+ if (i != last_page) {
+ sed156x_cmd_transfer(LCD_PADDR | i);
+ last_page = i;
+ }
+
+ sed156x_cmd_transfer(LCD_CADRH | ((j >> 4) & 0x0F));
+ sed156x_cmd_transfer(LCD_CADRL | (j & 0x0F));
+ sed156x_data_block_transfer(r, s - r);
+
+ } while (s < e);
+ }
+
+/********
+ for (i = 0; i < LCD_PAGES; i++) {
+ sed156x_cmd_transfer(LCD_PADDR | i);
+ sed156x_cmd_transfer(LCD_CADRH | 0);
+ sed156x_cmd_transfer(LCD_CADRL | 0);
+ sed156x_data_block_transfer(&hw_screen[i][0], LCD_COLUMNS);
+ }
+ memcpy(last_hw_screen, hw_screen, sizeof(last_hw_screen));
+********/
+}
+
+void sed156x_clear(void)
+{
+ memset(sw_screen, 0, sizeof(sw_screen));
+}
+
+void sed156x_output_at(int x, int y, const char *str, int size)
+{
+ int i, j;
+ u8 *p;
+ const u8 *s;
+
+ if ((unsigned int)y >= LCD_TEXT_HEIGHT || (unsigned int)x >= LCD_TEXT_WIDTH)
+ return;
+
+ p = &sw_screen[y * VIDEO_FONT_HEIGHT * LCD_BYTE_WIDTH + x * VIDEO_FONT_BYTE_WIDTH];
+
+ while (--size >= 0) {
+
+ s = &video_fontdata[((int)*str++ & 0xff) * VIDEO_FONT_BYTE_WIDTH * VIDEO_FONT_HEIGHT];
+ for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+ for (j = 0; j < VIDEO_FONT_BYTE_WIDTH; j++)
+ *p++ = *s++;
+ p += LCD_BYTE_WIDTH - VIDEO_FONT_BYTE_WIDTH;
+ }
+ p -= (LCD_BYTE_LINESZ - VIDEO_FONT_BYTE_WIDTH);
+
+ if (x >= LCD_TEXT_WIDTH)
+ break;
+ x++;
+ }
+}
+
+void sed156x_reverse_at(int x, int y, int size)
+{
+ int i, j;
+ u8 *p;
+
+ if ((unsigned int)y >= LCD_TEXT_HEIGHT || (unsigned int)x >= LCD_TEXT_WIDTH)
+ return;
+
+ p = &sw_screen[y * VIDEO_FONT_HEIGHT * LCD_BYTE_WIDTH + x * VIDEO_FONT_BYTE_WIDTH];
+
+ while (--size >= 0) {
+
+ for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
+ for (j = 0; j < VIDEO_FONT_BYTE_WIDTH; j++, p++)
+ *p = ~*p;
+ p += LCD_BYTE_WIDTH - VIDEO_FONT_BYTE_WIDTH;
+ }
+ p -= (LCD_BYTE_LINESZ - VIDEO_FONT_BYTE_WIDTH);
+
+ if (x >= LCD_TEXT_WIDTH)
+ break;
+ x++;
+ }
+}
+
+void sed156x_scroll_line(void)
+{
+ memmove(&sw_screen[0],
+ &sw_screen[LCD_BYTE_LINESZ],
+ LCD_BYTE_WIDTH * (LCD_HEIGHT - VIDEO_FONT_HEIGHT));
+}
+
+void sed156x_scroll(int dx, int dy)
+{
+ u8 *p1 = NULL, *p2 = NULL, *p3 = NULL; /* pacify gcc */
+ int adx, ady, i, sz;
+
+ adx = dx > 0 ? dx : -dx;
+ ady = dy > 0 ? dy : -dy;
+
+ /* overscroll? erase everything */
+ if (adx >= LCD_TEXT_WIDTH || ady >= LCD_TEXT_HEIGHT) {
+ memset(sw_screen, 0, sizeof(sw_screen));
+ return;
+ }
+
+ sz = LCD_BYTE_LINESZ * ady;
+ if (dy > 0) {
+ p1 = &sw_screen[0];
+ p2 = &sw_screen[sz];
+ p3 = &sw_screen[LCD_BYTE_WIDTH * LCD_HEIGHT - sz];
+ } else if (dy < 0) {
+ p1 = &sw_screen[sz];
+ p2 = &sw_screen[0];
+ p3 = &sw_screen[0];
+ }
+
+ if (ady > 0) {
+ memmove(p1, p2, LCD_BYTE_WIDTH * LCD_HEIGHT - sz);
+ memset(p3, 0, sz);
+ }
+
+ sz = VIDEO_FONT_BYTE_WIDTH * adx;
+ if (dx > 0) {
+ p1 = &sw_screen[0];
+ p2 = &sw_screen[0] + sz;
+ p3 = &sw_screen[0] + LCD_BYTE_WIDTH - sz;
+ } else if (dx < 0) {
+ p1 = &sw_screen[0] + sz;
+ p2 = &sw_screen[0];
+ p3 = &sw_screen[0];
+ }
+
+ /* xscroll */
+ if (adx > 0) {
+ for (i = 0; i < LCD_HEIGHT; i++) {
+ memmove(p1, p2, LCD_BYTE_WIDTH - sz);
+ memset(p3, 0, sz);
+ p1 += LCD_BYTE_WIDTH;
+ p2 += LCD_BYTE_WIDTH;
+ p3 += LCD_BYTE_WIDTH;
+ }
+ }
+}
+
+void sed156x_init(void)
+{
+ int i;
+
+ SED156X_CS(1);
+ SED156X_A0(1);
+
+ /* Send initialization commands to the LCD */
+ sed156x_cmd_transfer(LCD_OFF); /* Turn display OFF */
+ sed156x_cmd_transfer(LCD_BIAS); /* set the LCD Bias, */
+ sed156x_cmd_transfer(LCD_ADCMODE); /* ADC mode, */
+ sed156x_cmd_transfer(LCD_COMDIR); /* common output mode, */
+ sed156x_cmd_transfer(LCD_RESRT | LCD_RRATIO); /* resistor ratio, */
+ sed156x_cmd_transfer(LCD_EVSET); /* electronic volume, */
+ sed156x_cmd_transfer(LCD_CNTRST);
+ sed156x_cmd_transfer(LCD_PWRMD | LCD_POWERM); /* and power mode */
+ sed156x_cmd_transfer(LCD_PADDR | 0); /* cursor home */
+ sed156x_cmd_transfer(LCD_CADRH | 0);
+ sed156x_cmd_transfer(LCD_CADRL | 0);
+ sed156x_cmd_transfer(LCD_LADDR | 0); /* and display start line */
+ sed156x_cmd_transfer(LCD_DSP_NRM); /* LCD display Normal */
+
+ /* clear everything */
+ memset(sw_screen, 0, sizeof(sw_screen));
+ memset(hw_screen, 0, sizeof(hw_screen));
+ memset(last_hw_screen, 0, sizeof(last_hw_screen));
+
+ for (i = 0; i < LCD_PAGES; i++) {
+ sed156x_cmd_transfer(LCD_PADDR | i);
+ sed156x_cmd_transfer(LCD_CADRH | 0);
+ sed156x_cmd_transfer(LCD_CADRL | 0);
+ sed156x_data_block_transfer(&hw_screen[i][0], LCD_COLUMNS);
+ }
+
+ sed156x_clear();
+ sed156x_sync();
+ sed156x_cmd_transfer(LCD_ON); /* Turn display ON */
+}
+
+#endif /* CONFIG_SED156X */
diff --git a/drivers/video/sm501.c b/drivers/video/sm501.c
new file mode 100644
index 0000000..23db02c
--- /dev/null
+++ b/drivers/video/sm501.c
@@ -0,0 +1,150 @@
+/*
+ * (C) Copyright 2002
+ * Stäubli Faverges - <www.staubli.com>
+ * Pierre AUBERT p.aubert@staubli.com
+ *
+ * (C) Copyright 2005
+ * Martin Krause TQ-Systems GmbH martin.krause@tqs.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Basic video support for SMI SM501 "Voyager" graphic controller
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_VIDEO_SM501
+
+#include <video_fb.h>
+#include <sm501.h>
+
+#define read8(ptrReg) \
+ *(volatile unsigned char *)(sm501.isaBase + ptrReg)
+
+#define write8(ptrReg,value) \
+ *(volatile unsigned char *)(sm501.isaBase + ptrReg) = value
+
+#define read16(ptrReg) \
+ (*(volatile unsigned short *)(sm501.isaBase + ptrReg))
+
+#define write16(ptrReg,value) \
+ (*(volatile unsigned short *)(sm501.isaBase + ptrReg) = value)
+
+#define read32(ptrReg) \
+ (*(volatile unsigned int *)(sm501.isaBase + ptrReg))
+
+#define write32(ptrReg, value) \
+ (*(volatile unsigned int *)(sm501.isaBase + ptrReg) = value)
+
+GraphicDevice sm501;
+
+/*-----------------------------------------------------------------------------
+ * SmiSetRegs --
+ *-----------------------------------------------------------------------------
+ */
+static void SmiSetRegs (void)
+{
+ /*
+ * The content of the chipset register depends on the board (clocks,
+ * ...)
+ */
+ const SMI_REGS *preg = board_get_regs ();
+ while (preg->Index) {
+ write32 (preg->Index, preg->Value);
+ /*
+ * Insert a delay between
+ */
+ udelay (1000);
+ preg ++;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ * video_hw_init --
+ *-----------------------------------------------------------------------------
+ */
+void *video_hw_init (void)
+{
+ unsigned int *vm, i;
+
+ memset (&sm501, 0, sizeof (GraphicDevice));
+
+ /*
+ * Initialization of the access to the graphic chipset Retreive base
+ * address of the chipset (see board/RPXClassic/eccx.c)
+ */
+ if ((sm501.isaBase = board_video_init ()) == 0) {
+ return (NULL);
+ }
+
+ if ((sm501.frameAdrs = board_video_get_fb ()) == 0) {
+ return (NULL);
+ }
+
+ sm501.winSizeX = board_get_width ();
+ sm501.winSizeY = board_get_height ();
+
+#if defined(CONFIG_VIDEO_SM501_8BPP)
+ sm501.gdfIndex = GDF__8BIT_INDEX;
+ sm501.gdfBytesPP = 1;
+
+#elif defined(CONFIG_VIDEO_SM501_16BPP)
+ sm501.gdfIndex = GDF_16BIT_565RGB;
+ sm501.gdfBytesPP = 2;
+
+#elif defined(CONFIG_VIDEO_SM501_32BPP)
+ sm501.gdfIndex = GDF_32BIT_X888RGB;
+ sm501.gdfBytesPP = 4;
+#else
+#error Unsupported SM501 BPP
+#endif
+
+ sm501.memSize = sm501.winSizeX * sm501.winSizeY * sm501.gdfBytesPP;
+
+ /* Load Smi registers */
+ SmiSetRegs ();
+
+ /* (see board/RPXClassic/RPXClassic.c) */
+ board_validate_screen (sm501.isaBase);
+
+ /* Clear video memory */
+ i = sm501.memSize/4;
+ vm = (unsigned int *)sm501.frameAdrs;
+ while(i--)
+ *vm++ = 0;
+
+ return (&sm501);
+}
+
+/*-----------------------------------------------------------------------------
+ * video_set_lut --
+ *-----------------------------------------------------------------------------
+ */
+void video_set_lut (
+ unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+}
+
+#endif /* CONFIG_VIDEO_SM501 */
diff --git a/drivers/video/smiLynxEM.c b/drivers/video/smiLynxEM.c
new file mode 100644
index 0000000..20f9beb
--- /dev/null
+++ b/drivers/video/smiLynxEM.c
@@ -0,0 +1,858 @@
+/*
+ * (C) Copyright 1997-2002 ELTEC Elektronik AG
+ * Frank Gottschling <fgottschling@eltec.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * smiLynxEM.c
+ *
+ * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator
+ *
+ * modification history
+ * --------------------
+ * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>.
+ *
+ * 18-03-2004 - Unify videomodes handling with the ct69000
+ * - The video output can be set via the variable "videoout"
+ * in the environment.
+ * videoout=1 output on LCD
+ * videoout=2 output on CRT (default value)
+ * <p.aubert@staubli.com>
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_VIDEO_SMI_LYNXEM)
+
+#include <pci.h>
+#include <video_fb.h>
+#include "videomodes.h"
+/*
+ * Export Graphic Device
+ */
+GraphicDevice smi;
+
+/*
+ * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external
+ */
+#define VIDEO_MEM_SIZE 0x400000
+
+
+/*
+ * ISA mapped regs
+ */
+#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */
+#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */
+#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */
+#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */
+#define SMI_ISR1 (pGD->isaBase + 0x03ca)
+#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */
+#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */
+#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */
+#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */
+#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */
+#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */
+#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/
+#define SMI_INDX_ATTR (pGD->isaBase + 0x03c0) /* attributes index reg */
+
+/*
+ * Video processor control
+ */
+typedef struct {
+ unsigned int control;
+ unsigned int colorKey;
+ unsigned int colorKeyMask;
+ unsigned int start;
+ unsigned short offset;
+ unsigned short width;
+ unsigned int fifoPrio;
+ unsigned int fifoERL;
+ unsigned int YUVtoRGB;
+} SmiVideoProc;
+
+/*
+ * Video window control
+ */
+typedef struct {
+ unsigned short top;
+ unsigned short left;
+ unsigned short bottom;
+ unsigned short right;
+ unsigned int srcStart;
+ unsigned short width;
+ unsigned short offset;
+ unsigned char hStretch;
+ unsigned char vStretch;
+} SmiVideoWin;
+
+/*
+ * Capture port control
+ */
+typedef struct {
+ unsigned int control;
+ unsigned short topClip;
+ unsigned short leftClip;
+ unsigned short srcHeight;
+ unsigned short srcWidth;
+ unsigned int srcBufStart1;
+ unsigned int srcBufStart2;
+ unsigned short srcOffset;
+ unsigned short fifoControl;
+} SmiCapturePort;
+
+
+/*
+ * Register values for common video modes
+ */
+static char SMI_SCR[] = {
+ /* all modes */
+ 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x15, 0x90,
+ 0x17, 0x20, 0x18, 0xb1, 0x19, 0x00,
+};
+static char SMI_EXT_CRT[] = {
+ 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00,
+ 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00,
+};
+static char SMI_ATTR [] = {
+ 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,
+ 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b,
+ 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x41, 0x11, 0x00,
+ 0x12, 0x0f, 0x13, 0x00, 0x14, 0x00,
+};
+static char SMI_GCR[18] = {
+ 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40,
+ 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff,
+};
+static char SMI_SEQR[] = {
+ 0x00, 0x00, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e, 0x00, 0x03,
+};
+static char SMI_PCR [] = {
+ 0x20, 0x04, 0x21, 0x30, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00,
+};
+static char SMI_MCR[] = {
+ 0x60, 0x01, 0x61, 0x00,
+#ifdef CONFIG_HMI1001
+ 0x62, 0x74, /* Memory type is not configured by pins on HMI1001 */
+#endif
+};
+
+static char SMI_HCR[] = {
+ 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00,
+ 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00,
+};
+
+
+/*******************************************************************************
+ *
+ * Write SMI ISA register
+ */
+static void smiWrite (unsigned short index, char reg, char val)
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ out8 ((pGD->isaBase + index), reg);
+ out8 ((pGD->isaBase + index + 1), val);
+}
+
+/*******************************************************************************
+ *
+ * Write a table of SMI ISA register
+ */
+static void smiLoadRegs (
+ unsigned int iReg,
+ unsigned int dReg,
+ char *regTab,
+ unsigned int tabSize
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register int i;
+
+ for (i=0; i<tabSize; i+=2) {
+ if (iReg == SMI_INDX_ATTR) {
+ /* Reset the Flip Flop */
+ in8 (SMI_ISR1);
+ out8 (iReg, regTab[i]);
+ out8 (iReg, regTab[i+1]);
+ } else {
+ out8 (iReg, regTab[i]);
+ out8 (dReg, regTab[i+1]);
+ }
+ }
+}
+
+/*******************************************************************************
+ *
+ * Init capture port registers
+ */
+static void smiInitCapturePort (void)
+{
+ SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 };
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP;
+
+ out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip));
+ out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth));
+ out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8);
+ out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8);
+ out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8);
+ out32r ((pGD->cprBase + 0x0018), pCP->fifoControl);
+ out32r ((pGD->cprBase + 0x0000), pCP->control);
+}
+
+
+/*******************************************************************************
+ *
+ * Init video processor registers
+ */
+static void smiInitVideoProcessor (void)
+{
+ SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed };
+ SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 };
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP;
+ register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW;
+
+ pVP->width = pGD->plnSizeX * pGD->gdfBytesPP;
+ pVP->control |= pGD->gdfIndex << 16;
+ pVWin->bottom = pGD->winSizeY - 1;
+ pVWin->right = pGD->winSizeX - 1;
+ pVWin->width = pVP->width;
+
+ /* color key */
+ out32r ((pGD->vprBase + 0x0004), pVP->colorKey);
+
+ /* color key mask */
+ out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask);
+
+ /* data src start adrs */
+ out32r ((pGD->vprBase + 0x000c), pVP->start / 8);
+
+ /* data width and offset */
+ out32r ((pGD->vprBase + 0x0010),
+ ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) |
+ (pGD->plnSizeX / 8 * pGD->gdfBytesPP));
+
+ /* video window 1 */
+ out32r ((pGD->vprBase + 0x0014),
+ ((pVWin->top << 16) | pVWin->left));
+
+ out32r ((pGD->vprBase + 0x0018),
+ ((pVWin->bottom << 16) | pVWin->right));
+
+ out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8);
+
+ out32r ((pGD->vprBase + 0x0020),
+ (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
+
+ out32r ((pGD->vprBase + 0x0024),
+ (((pVWin->hStretch) << 8) | pVWin->vStretch));
+
+ /* video window 2 */
+ out32r ((pGD->vprBase + 0x0028),
+ ((pVWin->top << 16) | pVWin->left));
+
+ out32r ((pGD->vprBase + 0x002c),
+ ((pVWin->bottom << 16) | pVWin->right));
+
+ out32r ((pGD->vprBase + 0x0030),
+ pVWin->srcStart / 8);
+
+ out32r ((pGD->vprBase + 0x0034),
+ (((pVWin->offset / 8) << 16) | (pVWin->width / 8)));
+
+ out32r ((pGD->vprBase + 0x0038),
+ (((pVWin->hStretch) << 8) | pVWin->vStretch));
+
+ /* fifo prio control */
+ out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio);
+
+ /* fifo empty request levell */
+ out32r ((pGD->vprBase + 0x0058), pVP->fifoERL);
+
+ /* conversion constant */
+ out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB);
+
+ /* vpr control word */
+ out32r ((pGD->vprBase + 0x0000), pVP->control);
+}
+
+/******************************************************************************
+ *
+ * Init drawing engine registers
+ */
+static void smiInitDrawingEngine (void)
+{
+ GraphicDevice *pGD = (GraphicDevice *)&smi;
+ unsigned int val;
+
+ /* don't start now */
+ out32r ((pGD->dprBase + 0x000c), 0x000f0000);
+
+ /* set rop2 to copypen */
+ val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c));
+ out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c));
+
+ /* set clip rect */
+ out32r ((pGD->dprBase + 0x002c), 0);
+ out32r ((pGD->dprBase + 0x0030),
+ ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP ));
+
+ /* src row pitch */
+ val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010)));
+ out32r ((pGD->dprBase + 0x0010),
+ (val | pGD->plnSizeX * pGD->gdfBytesPP));
+
+ /* dst row pitch */
+ val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010)));
+ out32r ((pGD->dprBase + 0x0010),
+ (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val));
+
+ /* window width src/dst */
+ out32r ((pGD->dprBase + 0x003c),
+ (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) |
+ (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)));
+ out16r ((pGD->dprBase + 0x001e), 0x0000);
+
+ /* src base adrs */
+ out32r ((pGD->dprBase + 0x0040),
+ (((pGD->frameAdrs/8) & 0x000fffff)));
+
+ /* dst base adrs */
+ out32r ((pGD->dprBase + 0x0044),
+ (((pGD->frameAdrs/8) & 0x000fffff)));
+
+ /* foreground color */
+ out32r ((pGD->dprBase + 0x0014), pGD->fg);
+
+ /* background color */
+ out32r ((pGD->dprBase + 0x0018), pGD->bg);
+
+ /* xcolor */
+ out32r ((pGD->dprBase + 0x0020), 0x00ffffff);
+
+ /* xcolor mask */
+ out32r ((pGD->dprBase + 0x0024), 0x00ffffff);
+
+ /* bit mask */
+ out32r ((pGD->dprBase + 0x0028), 0x00ffffff);
+
+ /* load mono pattern */
+ out32r ((pGD->dprBase + 0x0034), 0);
+ out32r ((pGD->dprBase + 0x0038), 0);
+}
+
+static struct pci_device_id supported[] = {
+ { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 },
+ { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 },
+ { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 },
+ { }
+};
+
+/*****************************************************************************/
+static void smiLoadMsr (struct ctfb_res_modes *mode)
+{
+ unsigned char h_synch_high, v_synch_high;
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */
+ v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */
+ out8 (SMI_MISC_REG, (h_synch_high | v_synch_high | 0x29));
+ /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01
+ * Selects the upper 64KB page.Bit5=1
+ * CLK2 (left reserved in standard VGA) Bit3|2=1|0
+ * Disables CPU access to frame buffer. Bit1=0
+ * Sets the I/O address decode for ST01, FCR, and all CR registers
+ * to the 3Dx I/O address range (CGA emulation). Bit0=1
+ */
+}
+/*****************************************************************************/
+static void smiLoadCrt (struct ctfb_res_modes *var, int bits_per_pixel)
+{
+ unsigned char cr[0x7a];
+ int i;
+ unsigned int hd, hs, he, ht, hbs, hbe; /* Horizontal. */
+ unsigned int vd, vs, ve, vt, vbs, vbe; /* vertical */
+ unsigned int bpp, wd, dblscan, interlaced;
+
+ const int LineCompare = 0x3ff;
+ unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ /* Horizontal */
+ hd = (var->xres) / 8; /* HDisp. */
+ hs = (var->xres + var->right_margin) / 8; /* HsStrt */
+ he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */
+ ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */
+ /* Blank */
+ hbs = hd;
+ hbe = 0; /* Blank end at 0 */
+
+ /* Vertical */
+ vd = var->yres; /* VDisplay */
+ vs = var->yres + var->lower_margin; /* VSyncStart */
+ ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */
+ vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */
+ vbs = vd;
+ vbe = 0;
+
+ bpp = bits_per_pixel;
+ dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
+ interlaced = var->vmode & FB_VMODE_INTERLACED;
+
+
+ if (bpp == 15)
+ bpp = 16;
+ wd = var->xres * bpp / 64; /* double words per line */
+ if (interlaced) { /* we divide all vertical timings, exept vd */
+ vs >>= 1;
+ vbs >>= 1;
+ ve >>= 1;
+ vt >>= 1;
+ }
+
+ memset (cr, 0, sizeof (cr));
+ cr[0x00] = ht - 5;
+ cr[0x01] = hd - 1;
+ cr[0x02] = hbs - 1;
+ cr[0x03] = (hbe & 0x1F);
+ cr[0x04] = hs;
+ cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
+
+ cr[0x06] = (vt - 2) & 0xFF;
+ cr[0x07] = (((vt - 2) & 0x100) >> 8)
+ | (((vd - 1) & 0x100) >> 7)
+ | ((vs & 0x100) >> 6)
+ | (((vbs - 1) & 0x100) >> 5)
+ | ((LineCompare & 0x100) >> 4)
+ | (((vt - 2) & 0x200) >> 4)
+ | (((vd - 1) & 0x200) >> 3)
+ | ((vs & 0x200) >> 2);
+
+ cr[0x30] = ((vt - 2) & 0x400) >> 7
+ | (((vd - 1) & 0x400) >> 8)
+ | (((vbs - 1) & 0x400) >> 9)
+ | ((vs & 0x400) >> 10)
+ | (interlaced) ? 0x80 : 0;
+
+
+ cr[0x08] = 0x00;
+ cr[0x09] = (dblscan << 7)
+ | ((LineCompare & 0x200) >> 3)
+ | (((vbs - 1) & 0x200) >> 4)
+ | (TextScanLines - 1);
+
+ cr[0x10] = vs & 0xff; /* VSyncPulseStart */
+ cr[0x11] = (ve & 0x0f);
+ cr[0x12] = (vd - 1) & 0xff; /* LineCount */
+ cr[0x13] = wd & 0xff;
+ cr[0x14] = 0x40;
+ cr[0x15] = (vbs - 1) & 0xff;
+ cr[0x16] = vbe & 0xff;
+ cr[0x17] = 0xe3; /* but it does not work */
+ cr[0x18] = 0xff & LineCompare;
+ cr[0x22] = 0x00; /* todo? */
+
+
+ /* now set the registers */
+ for (i = 0; i <= 0x18; i++) { /*CR00 .. CR18 */
+ smiWrite (SMI_INDX_D4, i, cr[i]);
+ }
+ i = 0x22; /*CR22 */
+ smiWrite (SMI_INDX_D4, i, cr[i]);
+ i = 0x30; /*CR30 */
+ smiWrite (SMI_INDX_D4, i, cr[i]);
+}
+
+/*****************************************************************************/
+#define REF_FREQ 14318180
+#define PMIN 1
+#define PMAX 255
+#define QMIN 1
+#define QMAX 63
+
+static unsigned int FindPQ (unsigned int freq, unsigned int *pp, unsigned int *pq)
+{
+ unsigned int n = QMIN, m = 0;
+ long long int L = 0, P = freq, Q = REF_FREQ, H = P >> 1;
+ long long int D = 0x7ffffffffffffffLL;
+
+ for (n = QMIN; n <= QMAX; n++) {
+ m = PMIN; /* p/q ~ freq/ref -> p*ref-freq*q ~ 0 */
+ L = P * n - m * Q;
+ while (L > 0 && m < PMAX) {
+ L -= REF_FREQ; /* difference is greater as 0 subtract fref */
+ m++; /* and increment m */
+ }
+ /* difference is less or equal than 0 or m > maximum */
+ if (m > PMAX)
+ break; /* no solution: if we increase n we get the same situation */
+ /* L is <= 0 now */
+ if (-L > H && m > PMIN) { /* if difference > the half fref */
+ L += REF_FREQ; /* we take the situation before */
+ m--; /* because its closer to 0 */
+ }
+ L = (L < 0) ? -L : +L; /* absolute value */
+ if (D < L) /* if last difference was better take next n */
+ continue;
+ D = L;
+ *pp = m;
+ *pq = n; /* keep improved data */
+ if (D == 0)
+ break; /* best result we can get */
+ }
+ return (unsigned int) (0xffffffff & D);
+}
+
+/*****************************************************************************/
+static void smiLoadCcr (struct ctfb_res_modes *var, unsigned short device_id)
+{
+ unsigned int p = 0;
+ unsigned int q = 0;
+ long long freq;
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ smiWrite (SMI_INDX_C4, 0x65, 0);
+ smiWrite (SMI_INDX_C4, 0x66, 0);
+ smiWrite (SMI_INDX_C4, 0x68, 0x50);
+ if (device_id == PCI_DEVICE_ID_SMI_810) {
+ smiWrite (SMI_INDX_C4, 0x69, 0x3);
+ } else {
+ smiWrite (SMI_INDX_C4, 0x69, 0x0);
+ }
+
+ /* Memory clock */
+ switch (device_id) {
+ case PCI_DEVICE_ID_SMI_710 :
+ smiWrite (SMI_INDX_C4, 0x6a, 0x75);
+ break;
+ case PCI_DEVICE_ID_SMI_712 :
+ smiWrite (SMI_INDX_C4, 0x6a, 0x80);
+ break;
+ default :
+ smiWrite (SMI_INDX_C4, 0x6a, 0x53);
+ break;
+ }
+ smiWrite (SMI_INDX_C4, 0x6b, 0x15);
+
+ /* VCLK */
+ freq = 1000000000000LL / var -> pixclock;
+
+ FindPQ ((unsigned int)freq, &p, &q);
+
+ smiWrite (SMI_INDX_C4, 0x6c, p);
+ smiWrite (SMI_INDX_C4, 0x6d, q);
+
+}
+
+/*******************************************************************************
+ *
+ * Init video chip with common Linux graphic modes (lilo)
+ */
+void *video_hw_init (void)
+{
+ GraphicDevice *pGD = (GraphicDevice *)&smi;
+ unsigned short device_id;
+ pci_dev_t devbusfn;
+ int videomode;
+ unsigned long t1, hsynch, vsynch;
+ unsigned int pci_mem_base, *vm;
+ char *penv;
+ int tmp, i, bits_per_pixel;
+ struct ctfb_res_modes *res_mode;
+ struct ctfb_res_modes var_mode;
+ unsigned char videoout;
+
+ /* Search for video chip */
+ printf("Video: ");
+
+ if ((devbusfn = pci_find_devices(supported, 0)) < 0)
+ {
+ printf ("Controller not found !\n");
+ return (NULL);
+ }
+
+ /* PCI setup */
+ pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
+ pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id);
+ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base);
+ pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base);
+
+ tmp = 0;
+
+ videomode = CFG_DEFAULT_VIDEO_MODE;
+ /* get video mode via environment */
+ if ((penv = getenv ("videomode")) != NULL) {
+ /* deceide if it is a string */
+ if (penv[0] <= '9') {
+ videomode = (int) simple_strtoul (penv, NULL, 16);
+ tmp = 1;
+ }
+ } else {
+ tmp = 1;
+ }
+ if (tmp) {
+ /* parameter are vesa modes */
+ /* search params */
+ for (i = 0; i < VESA_MODES_COUNT; i++) {
+ if (vesa_modes[i].vesanr == videomode)
+ break;
+ }
+ if (i == VESA_MODES_COUNT) {
+ printf ("no VESA Mode found, switching to mode 0x%x ", CFG_DEFAULT_VIDEO_MODE);
+ i = 0;
+ }
+ res_mode =
+ (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].
+ resindex];
+ bits_per_pixel = vesa_modes[i].bits_per_pixel;
+ } else {
+
+ res_mode = (struct ctfb_res_modes *) &var_mode;
+ bits_per_pixel = video_get_params (res_mode, penv);
+ }
+
+ /* calculate hsynch and vsynch freq (info only) */
+ t1 = (res_mode->left_margin + res_mode->xres +
+ res_mode->right_margin + res_mode->hsync_len) / 8;
+ t1 *= 8;
+ t1 *= res_mode->pixclock;
+ t1 /= 1000;
+ hsynch = 1000000000L / t1;
+ t1 *=
+ (res_mode->upper_margin + res_mode->yres +
+ res_mode->lower_margin + res_mode->vsync_len);
+ t1 /= 1000;
+ vsynch = 1000000000L / t1;
+
+ /* fill in Graphic device struct */
+ sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
+ res_mode->yres, bits_per_pixel, (hsynch / 1000),
+ (vsynch / 1000));
+ printf ("%s\n", pGD->modeIdent);
+ pGD->winSizeX = res_mode->xres;
+ pGD->winSizeY = res_mode->yres;
+ pGD->plnSizeX = res_mode->xres;
+ pGD->plnSizeY = res_mode->yres;
+ switch (bits_per_pixel) {
+ case 8:
+ pGD->gdfBytesPP = 1;
+ pGD->gdfIndex = GDF__8BIT_INDEX;
+ break;
+ case 15:
+ pGD->gdfBytesPP = 2;
+ pGD->gdfIndex = GDF_15BIT_555RGB;
+ break;
+ case 16:
+ pGD->gdfBytesPP = 2;
+ pGD->gdfIndex = GDF_16BIT_565RGB;
+ break;
+ case 24:
+ pGD->gdfBytesPP = 3;
+ pGD->gdfIndex = GDF_24BIT_888RGB;
+ break;
+ }
+
+ pGD->isaBase = CFG_ISA_IO;
+ pGD->pciBase = pci_mem_base;
+ pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000);
+ pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000);
+ pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000);
+ pGD->frameAdrs = pci_mem_base;
+ pGD->memSize = VIDEO_MEM_SIZE;
+
+ /* Set up hardware : select color mode,
+ set Register base to isa 3dx for 3?x regs*/
+ out8 (SMI_MISC_REG, 0x01);
+
+ /* Turn off display */
+ smiWrite (SMI_INDX_C4, 0x01, 0x20);
+
+ /* Unlock ext. crt regs */
+ out8 (SMI_LOCK_REG, 0x40);
+
+ /* Unlock crt regs 0-7 */
+ smiWrite (SMI_INDX_D4, 0x11, 0x0e);
+
+ /* Sytem Control Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SCR, sizeof(SMI_SCR));
+
+ /* extented CRT Register */
+ smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, SMI_EXT_CRT, sizeof(SMI_EXT_CRT));
+
+ /* Attributes controller registers */
+ smiLoadRegs (SMI_INDX_ATTR, SMI_INDX_ATTR, SMI_ATTR, sizeof(SMI_ATTR));
+
+ /* Graphics Controller Register */
+ smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, SMI_GCR, sizeof(SMI_GCR));
+
+ /* Sequencer Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_SEQR, sizeof(SMI_SEQR));
+
+ /* Power Control Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_PCR, sizeof(SMI_PCR));
+
+ /* Memory Control Register */
+ /* Register MSR62 is a power on configurable register. We don't */
+ /* modify it */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_MCR, sizeof(SMI_MCR));
+
+ /* Set misc output register */
+ smiLoadMsr (res_mode);
+
+ /* Set CRT and Clock control registers */
+ smiLoadCrt (res_mode, bits_per_pixel);
+
+ smiLoadCcr (res_mode, device_id);
+
+ /* Hardware Cusor Register */
+ smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, SMI_HCR, sizeof(SMI_HCR));
+
+ /* Enable Display */
+ videoout = 2; /* Default output is CRT */
+ if ((penv = getenv ("videoout")) != NULL) {
+ /* deceide if it is a string */
+ videoout = (int) simple_strtoul (penv, NULL, 16);
+ }
+ smiWrite (SMI_INDX_C4, 0x31, videoout);
+
+ /* Video processor default setup */
+ smiInitVideoProcessor ();
+
+ /* Capture port default setup */
+ smiInitCapturePort ();
+
+ /* Drawing engine default setup */
+ smiInitDrawingEngine ();
+
+ /* Turn on display */
+ smiWrite (0x3c4, 0x01, 0x01);
+
+ /* Clear video memory */
+ i = pGD->memSize/4;
+ vm = (unsigned int *)pGD->pciBase;
+ while(i--)
+ *vm++ = 0;
+ return ((void*)&smi);
+}
+
+/*******************************************************************************
+ *
+ * Drawing engine fill on screen region
+ */
+void video_hw_rectfill (
+ unsigned int bpp, /* bytes per pixel */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y, /* frame height */
+ unsigned int color /* fill color */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register unsigned int control;
+
+ dim_x *= bpp;
+
+ out32r ((pGD->dprBase + 0x0014), color);
+ out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
+ out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
+
+ control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c));
+
+ control |= 0x80010000;
+
+ out32r ((pGD->dprBase + 0x000c), control);
+
+ /* Wait for drawing processor */
+ do
+ {
+ out8 ((pGD->isaBase + 0x3c4), 0x16);
+ } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
+}
+
+/*******************************************************************************
+ *
+ * Drawing engine bitblt with screen region
+ */
+void video_hw_bitblt (
+ unsigned int bpp, /* bytes per pixel */
+ unsigned int src_x, /* source pos x */
+ unsigned int src_y, /* source pos y */
+ unsigned int dst_x, /* dest pos x */
+ unsigned int dst_y, /* dest pos y */
+ unsigned int dim_x, /* frame width */
+ unsigned int dim_y /* frame height */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+ register unsigned int control;
+
+ dim_x *= bpp;
+
+ if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x)))
+ {
+ out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1)));
+ out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1)));
+ control = 0x88000000;
+ } else {
+ out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y));
+ out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y));
+ control = 0x80000000;
+ }
+
+ out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y));
+ control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c)));
+ out32r ((pGD->dprBase + 0x000c), control);
+
+ /* Wait for drawing processor */
+ do
+ {
+ out8 ((pGD->isaBase + 0x3c4), 0x16);
+ } while (in8 (pGD->isaBase + 0x3c5) & 0x08);
+}
+
+/*******************************************************************************
+ *
+ * Set a RGB color in the LUT (8 bit index)
+ */
+void video_set_lut (
+ unsigned int index, /* color number */
+ unsigned char r, /* red */
+ unsigned char g, /* green */
+ unsigned char b /* blue */
+ )
+{
+ register GraphicDevice *pGD = (GraphicDevice *)&smi;
+
+ out8 (SMI_LUT_MASK, 0xff);
+
+ out8 (SMI_LUT_START, (char)index);
+
+ out8 (SMI_LUT_RGB, r>>2); /* red */
+ udelay (10);
+ out8 (SMI_LUT_RGB, g>>2); /* green */
+ udelay (10);
+ out8 (SMI_LUT_RGB, b>>2); /* blue */
+ udelay (10);
+}
+
+#endif /* CONFIG_VIDEO_SMI_LYNXEM */
diff --git a/drivers/video/videomodes.c b/drivers/video/videomodes.c
new file mode 100644
index 0000000..c81e5bc
--- /dev/null
+++ b/drivers/video/videomodes.c
@@ -0,0 +1,208 @@
+/*
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges , <p.aubert@staubli.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/************************************************************************
+ Get Parameters for the video mode:
+ The default video mode can be defined in CFG_DEFAULT_VIDEO_MODE.
+ If undefined, default video mode is set to 0x301
+ Parameters can be set via the variable "videomode" in the environment.
+ 2 diferent ways are possible:
+ "videomode=301" - 301 is a hexadecimal number describing the VESA
+ mode. Following modes are implemented:
+
+ Colors 640x480 800x600 1024x768 1152x864 1280x1024
+ --------+---------------------------------------------
+ 8 bits | 0x301 0x303 0x305 0x161 0x307
+ 15 bits | 0x310 0x313 0x316 0x162 0x319
+ 16 bits | 0x311 0x314 0x317 0x163 0x31A
+ 24 bits | 0x312 0x315 0x318 ? 0x31B
+ --------+---------------------------------------------
+ "videomode=bootargs"
+ - the parameters are parsed from the bootargs.
+ The format is "NAME:VALUE,NAME:VALUE" etc.
+ Ex.:
+ "bootargs=video=ctfb:x:800,y:600,depth:16,pclk:25000"
+ Parameters not included in the list will be taken from
+ the default mode, which is one of the following:
+ mode:0 640x480x24
+ mode:1 800x600x16
+ mode:2 1024x768x8
+ mode:3 960x720x24
+ mode:4 1152x864x16
+ mode:5 1280x1024x8
+
+ if "mode" is not provided within the parameter list,
+ mode:0 is assumed.
+ Following parameters are supported:
+ x xres = visible resolution horizontal
+ y yres = visible resolution vertical
+ pclk pixelclocks in pico sec
+ le left_marging time from sync to picture in pixelclocks
+ ri right_marging time from picture to sync in pixelclocks
+ up upper_margin time from sync to picture
+ lo lower_margin
+ hs hsync_len length of horizontal sync
+ vs vsync_len length of vertical sync
+ sync see FB_SYNC_*
+ vmode see FB_VMODE_*
+ depth Color depth in bits per pixel
+ All other parameters in the variable bootargs are ignored.
+ It is also possible to set the parameters direct in the
+ variable "videomode", or in another variable i.e.
+ "myvideo" and setting the variable "videomode=myvideo"..
+****************************************************************************/
+
+#include <common.h>
+#include "videomodes.h"
+
+const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
+ {0x301, RES_MODE_640x480, 8},
+ {0x310, RES_MODE_640x480, 15},
+ {0x311, RES_MODE_640x480, 16},
+ {0x312, RES_MODE_640x480, 24},
+ {0x303, RES_MODE_800x600, 8},
+ {0x313, RES_MODE_800x600, 15},
+ {0x314, RES_MODE_800x600, 16},
+ {0x315, RES_MODE_800x600, 24},
+ {0x305, RES_MODE_1024x768, 8},
+ {0x316, RES_MODE_1024x768, 15},
+ {0x317, RES_MODE_1024x768, 16},
+ {0x318, RES_MODE_1024x768, 24},
+ {0x161, RES_MODE_1152x864, 8},
+ {0x162, RES_MODE_1152x864, 15},
+ {0x163, RES_MODE_1152x864, 16},
+ {0x307, RES_MODE_1280x1024, 8},
+ {0x319, RES_MODE_1280x1024, 15},
+ {0x31A, RES_MODE_1280x1024, 16},
+ {0x31B, RES_MODE_1280x1024, 24},
+};
+const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
+ /* x y pixclk le ri up lo hs vs s vmode */
+ {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},
+ {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
+ {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},
+ {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},
+ {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},
+ {1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},
+};
+
+/************************************************************************
+ * Get Parameters for the video mode:
+ */
+/*********************************************************************
+ * returns the length to the next seperator
+ */
+static int
+video_get_param_len (char *start, char sep)
+{
+ int i = 0;
+ while ((*start != 0) && (*start != sep)) {
+ start++;
+ i++;
+ }
+ return i;
+}
+
+static int
+video_search_param (char *start, char *param)
+{
+ int len, totallen, i;
+ char *p = start;
+ len = strlen (param);
+ totallen = len + strlen (start);
+ for (i = 0; i < totallen; i++) {
+ if (strncmp (p++, param, len) == 0)
+ return (i);
+ }
+ return -1;
+}
+
+/***************************************************************
+ * Get parameter via the environment as it is done for the
+ * linux kernel i.e:
+ * video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000,
+ * le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0
+ *
+ * penv is a pointer to the environment, containing the string, or the name of
+ * another environment variable. It could even be the term "bootargs"
+ */
+
+#define GET_OPTION(name,var) \
+ if(strncmp(p,name,strlen(name))==0) { \
+ val_s=p+strlen(name); \
+ var=simple_strtoul(val_s, NULL, 10); \
+ }
+
+int video_get_params (struct ctfb_res_modes *pPar, char *penv)
+{
+ char *p, *s, *val_s;
+ int i = 0, t;
+ int bpp;
+ int mode;
+ /* first search for the environment containing the real param string */
+ s = penv;
+ if ((p = getenv (s)) != NULL) {
+ s = p;
+ }
+ /* in case of the bootargs line, we have to start
+ * after "video=ctfb:"
+ */
+ i = video_search_param (s, "video=ctfb:");
+ if (i >= 0) {
+ s += i;
+ s += strlen ("video=ctfb:");
+ }
+ /* search for mode as a default value */
+ p = s;
+ t = 0;
+ mode = 0; /* default */
+ while ((i = video_get_param_len (p, ',')) != 0) {
+ GET_OPTION ("mode:", mode)
+ p += i;
+ if (*p != 0)
+ p++; /* skip ',' */
+ }
+ if (mode >= RES_MODES_COUNT)
+ mode = 0;
+ *pPar = res_mode_init[mode]; /* copy default values */
+ bpp = 24 - ((mode % 3) * 8);
+ p = s; /* restart */
+ while ((i = video_get_param_len (p, ',')) != 0) {
+ GET_OPTION ("x:", pPar->xres)
+ GET_OPTION ("y:", pPar->yres)
+ GET_OPTION ("le:", pPar->left_margin)
+ GET_OPTION ("ri:", pPar->right_margin)
+ GET_OPTION ("up:", pPar->upper_margin)
+ GET_OPTION ("lo:", pPar->lower_margin)
+ GET_OPTION ("hs:", pPar->hsync_len)
+ GET_OPTION ("vs:", pPar->vsync_len)
+ GET_OPTION ("sync:", pPar->sync)
+ GET_OPTION ("vmode:", pPar->vmode)
+ GET_OPTION ("pclk:", pPar->pixclock)
+ GET_OPTION ("depth:", bpp)
+ p += i;
+ if (*p != 0)
+ p++; /* skip ',' */
+ }
+ return bpp;
+}
diff --git a/drivers/video/videomodes.h b/drivers/video/videomodes.h
new file mode 100644
index 0000000..e2dffe7
--- /dev/null
+++ b/drivers/video/videomodes.h
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2004
+ * Pierre Aubert, Staubli Faverges , <p.aubert@staubli.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#ifndef CFG_DEFAULT_VIDEO_MODE
+#define CFG_DEFAULT_VIDEO_MODE 0x301
+#endif
+
+/* Some mode definitions */
+#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define FB_SYNC_EXT 4 /* external sync */
+#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define FB_SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+#define FB_SYNC_ON_GREEN 32 /* sync on green */
+#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
+#define FB_VMODE_INTERLACED 1 /* interlaced */
+#define FB_VMODE_DOUBLE 2 /* double scan */
+#define FB_VMODE_MASK 255
+
+#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
+#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+
+/******************************************************************
+ * Resolution Struct
+ ******************************************************************/
+struct ctfb_res_modes {
+ int xres; /* visible resolution */
+ int yres;
+ /* Timing: All values in pixclocks, except pixclock (of course) */
+ int pixclock; /* pixel clock in ps (pico seconds) */
+ int left_margin; /* time from sync to picture */
+ int right_margin; /* time from picture to sync */
+ int upper_margin; /* time from sync to picture */
+ int lower_margin;
+ int hsync_len; /* length of horizontal sync */
+ int vsync_len; /* length of vertical sync */
+ int sync; /* see FB_SYNC_* */
+ int vmode; /* see FB_VMODE_* */
+};
+
+/******************************************************************
+ * Vesa Mode Struct
+ ******************************************************************/
+struct ctfb_vesa_modes {
+ int vesanr; /* Vesa number as in LILO (VESA Nr + 0x200} */
+ int resindex; /* index to resolution struct */
+ int bits_per_pixel; /* bpp */
+};
+
+#define RES_MODE_640x480 0
+#define RES_MODE_800x600 1
+#define RES_MODE_1024x768 2
+#define RES_MODE_960_720 3
+#define RES_MODE_1152x864 4
+#define RES_MODE_1280x1024 5
+#define RES_MODES_COUNT 6
+
+#define VESA_MODES_COUNT 19
+
+extern const struct ctfb_vesa_modes vesa_modes[];
+extern const struct ctfb_res_modes res_mode_init[];
+
+int video_get_params (struct ctfb_res_modes *pPar, char *penv);