MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / video / dm270fb.c
blob2b4fefc7ca7e65c517ef357b96dffee7e7afbc98
1 /*
2 * drivers/video/dm270fb.c
4 * Copyright (C) 2004 Chee Tim Loh <lohct@pacific.net.sg>
6 * Based on drivers/video/cyber2000fb.c
7 * Copyright (C) 1998-2002 Russell King
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
13 * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device
15 * Based on cyberfb.c.
17 * Note that we now use the new fbcon fix, var and cmap scheme. We do
18 * still have to check which console is the currently displayed one
19 * however, especially for the colourmap stuff.
21 * We also use the new hotplug PCI subsystem. I'm not sure if there
22 * are any such cards, but I'm erring on the side of caution. We don't
23 * want to go pop just because someone does have one.
25 * Note that this doesn't work fully in the case of multiple CyberPro
26 * cards with grabbers. We currently can only attach to the first
27 * CyberPro card found.
29 * When we're in truecolour mode, we power down the LUT RAM as a power
30 * saving feature. Also, when we enter any of the powersaving modes
31 * (except soft blanking) we power down the RAMDACs. This saves about
32 * 1W, which is roughly 8% of the power consumption of a NetWinder
33 * (which, incidentally, is about the same saving as a 2.5in hard disk
34 * entering standby mode.)
36 #include <linux/module.h>
37 #include <linux/kernel.h>
38 #include <linux/errno.h>
39 #include <linux/string.h>
40 #include <linux/page-flags.h>
41 #include <linux/mm.h>
42 #include <linux/tty.h>
43 #include <linux/slab.h>
44 #include <linux/delay.h>
45 #include <linux/fb.h>
46 #include <linux/init.h>
47 #include <linux/dm270-id.h>
49 #include <asm/io.h>
50 #include <asm/irq.h>
51 #include <asm/system.h>
52 #include <asm/uaccess.h>
54 #include "dm270fb.h"
56 /* -------------------- Global Variables ----------------------------------- */
58 static struct fb_info dm270fbinfo[DM270FB_NR_FB];
59 static char *dm270fb_options __initdata = NULL;
61 static struct dm270fb_cfg dm270fb_bootcfg = {
62 .noaccel = 1,
63 .nopan = 1,
64 .nowrap = 1,
65 .nohwcursor = 1,
66 .cmap_inverse = 0,
67 .cmap_static = 1,
68 .fontname = {'\0'},
69 .disp_type = DM270FB_DEFAULT_DISPTYPE, /* composite */
70 .vidout_std = DM270FB_DEFAULT_VIDFMT, /* NTSC */
73 static struct fb_var_screeninfo dm270fb_bootvar = {
74 .xres = DM270FB_DEFAULT_XRES, /* 640 */
75 .yres = DM270FB_DEFAULT_YRES, /* 480 */
76 .xres_virtual = DM270FB_DEFAULT_XRES,
77 .yres_virtual = DM270FB_DEFAULT_YRES,
78 .xoffset = 0,
79 .yoffset = 0,
80 .bits_per_pixel = DM270FB_DEFAULT_BPP, /* 8 */
81 .grayscale = 0,
82 /* for bpp <= 8, length of red = length of green = length of blue = bpp */
83 .red = {0, DM270FB_DEFAULT_BPP, 0},
84 .green = {0, DM270FB_DEFAULT_BPP, 0},
85 .blue = {0, DM270FB_DEFAULT_BPP, 0},
86 .transp = {0, 0, 0},
87 .nonstd = 0,
88 .activate = FB_ACTIVATE_NOW,
89 .height = -1,
90 .width = -1,
91 .accel_flags = 0,
92 .pixclock = DM270FB_DEFAULT_PIXCLOCK, /* 0 */
93 .left_margin = DM270FB_DEFAULT_LEFT_MARGIN, /* 0 */
94 .right_margin = DM270FB_DEFAULT_RIGHT_MARGIN, /* 0 */
95 .upper_margin = DM270FB_DEFAULT_UPPER_MARGIN, /* 0 */
96 .lower_margin = DM270FB_DEFAULT_LOWER_MARGIN, /* 0 */
97 .hsync_len = DM270FB_DEFAULT_HSYNC_LEN, /* 0 */
98 .vsync_len = DM270FB_DEFAULT_VSYNC_LEN, /* 0 */
99 .sync = DM270FB_DEFAULT_SYNC, /* csync */
100 .vmode = DM270FB_DEFAULT_VMODE, /* interlaced */
101 .rotate = 0,
104 /* -------------------- ROM Color Lookup Table ----------------------------- */
106 static u16 dm270fb_romclut_red[] = {
107 0x0000, 0xa400, 0x0000, 0x8600, 0x0000, 0x9e00, 0x0000, 0xc000,
108 0xb900, 0x9900, 0xfb00, 0x0800, 0x1000, 0x1800, 0x2100, 0x2900,
109 0x3100, 0x4a00, 0x5a00, 0x7300, 0x7b00, 0x9400, 0xa500, 0xbd00,
110 0x4c00, 0x7f00, 0x7700, 0x6700, 0xa500, 0x8d00, 0x8400, 0x8600,
111 0x8800, 0xae00, 0xa600, 0xa800, 0xc800, 0xf200, 0xae00, 0x8f00,
112 0xec00, 0xa600, 0x8d00, 0xdd00, 0x6400, 0xb700, 0xd700, 0x6700,
113 0xc500, 0xce00, 0xfb00, 0x5200, 0xa800, 0xff00, 0xca00, 0x7800,
114 0x7600, 0xd700, 0xe800, 0xff00, 0xff00, 0x6000, 0x5800, 0xff00,
115 0xff00, 0x6600, 0x2400, 0x6000, 0x5800, 0x3c00, 0x9800, 0x5e00,
116 0x5600, 0x9400, 0x8c00, 0x7b00, 0x3500, 0x6200, 0xea00, 0x4700,
117 0x8900, 0xdf00, 0x6800, 0xbf00, 0x9d00, 0xe400, 0xaf00, 0xdc00,
118 0xe500, 0xe800, 0xd900, 0xe100, 0xe900, 0xda00, 0xc000, 0x4f00,
119 0xef00, 0xac00, 0xe200, 0xeb00, 0xe300, 0xf500, 0xff00, 0xe600,
120 0x8000, 0x8900, 0x7600, 0x7600, 0x6300, 0x5100, 0x4500, 0x3d00,
121 0x3c00, 0x2a00, 0x4500, 0x0800, 0x1600, 0x0e00, 0x3600, 0x6d00,
122 0x1600, 0x0600, 0x2600, 0x0d00, 0x1700, 0x1f00, 0x1700, 0x0f00,
123 0x1100, 0x0100, 0x0200, 0x0000, 0x0000, 0x0500, 0x8100, 0x3f00,
124 0x2600, 0x1e00, 0x1500, 0x4c00, 0x2e00, 0x2900, 0x8f00, 0x0500,
125 0x6800, 0x5800, 0x1400, 0x0000, 0x0000, 0xa200, 0x6d00, 0x0000,
126 0x7e00, 0x7400, 0x6200, 0x6000, 0x0000, 0xaf00, 0x8e00, 0x4c00,
127 0x2b00, 0x1200, 0x0000, 0x0000, 0xe400, 0xc800, 0xb400, 0x9c00,
128 0x8b00, 0x1e00, 0x7000, 0x5100, 0x6000, 0x7600, 0x6500, 0x5d00,
129 0x3f00, 0x4400, 0x5800, 0x0000, 0x2500, 0x5700, 0x5500, 0x4400,
130 0x3600, 0x1200, 0x9300, 0x8300, 0x7200, 0x6200, 0x2800, 0x1a00,
131 0x0d00, 0x7400, 0x3200, 0x0600, 0x0000, 0x0000, 0x0000, 0xa700,
132 0x4400, 0x3c00, 0x2300, 0x2800, 0x2a00, 0xda00, 0x7700, 0x3900,
133 0x4300, 0x1e00, 0x3b00, 0x3200, 0x2a00, 0x0000, 0x0000, 0xa900,
134 0x8800, 0x6f00, 0x2d00, 0x2500, 0x0600, 0x0100, 0x5600, 0x4600,
135 0x4500, 0xac00, 0x9b00, 0x6a00, 0x6200, 0x5100, 0x5900, 0x4900,
136 0x4100, 0x6a00, 0x6200, 0x2000, 0x4800, 0x1700, 0x0f00, 0x4c00,
137 0x2300, 0x8a00, 0x5e00, 0x6700, 0x8a00, 0x0000, 0xff00, 0xa000,
138 0x8000, 0xfe00, 0x0000, 0xff00, 0x0000, 0xff00, 0x0000, 0xff00,
140 static u16 dm270fb_romclut_green[] = {
141 0x0000, 0x0000, 0x9a00, 0x8d00, 0x0000, 0x0000, 0x8d00, 0xc000,
142 0xe000, 0xca00, 0xfb00, 0x0800, 0x1000, 0x1800, 0x2100, 0x2900,
143 0x3100, 0x4a00, 0x5a00, 0x7300, 0x7b00, 0x9400, 0xa500, 0xbd00,
144 0x4000, 0x6900, 0x6100, 0x5000, 0x7800, 0x6000, 0x5700, 0x4d00,
145 0x4500, 0x5400, 0x4c00, 0x4200, 0x4100, 0x0000, 0x3000, 0x0700,
146 0x0a00, 0x4c00, 0x3300, 0x1d00, 0x0a00, 0x0c00, 0x0b00, 0x0100,
147 0x7500, 0x2f00, 0x2400, 0x0200, 0x2100, 0x1400, 0x6500, 0x1300,
148 0x1c00, 0x5c00, 0x4a00, 0x2e00, 0x2400, 0x1e00, 0x1400, 0x3800,
149 0x4000, 0x5b00, 0x1900, 0x4d00, 0x4500, 0x3400, 0x7b00, 0x5600,
150 0x4e00, 0x8200, 0x7b00, 0x6900, 0x2d00, 0x4f00, 0xd100, 0x3d00,
151 0x8000, 0xcf00, 0x5f00, 0xb100, 0x8d00, 0xc400, 0xa000, 0xbc00,
152 0xc000, 0xdb00, 0xca00, 0xd200, 0xd800, 0xc600, 0xaf00, 0x4800,
153 0xec00, 0xa500, 0xcc00, 0xd100, 0xc900, 0xd700, 0xe300, 0xe200,
154 0xd600, 0xd500, 0xd900, 0xd800, 0xd100, 0xc800, 0xcc00, 0xc400,
155 0xcc00, 0xc600, 0x9900, 0x3700, 0xbf00, 0xb700, 0x7e00, 0xc100,
156 0xbe00, 0xab00, 0x3300, 0x4b00, 0x8100, 0xba00, 0xb200, 0x7900,
157 0xa000, 0x2600, 0x8500, 0x2f00, 0x6800, 0x4000, 0x8d00, 0x4b00,
158 0x3200, 0x2a00, 0x2100, 0x6400, 0xa800, 0xba00, 0xc700, 0x9f00,
159 0xb500, 0xa500, 0x8d00, 0x8d00, 0x7d00, 0xce00, 0xa500, 0x7300,
160 0xb600, 0xb500, 0xa600, 0xac00, 0x7a00, 0xc600, 0xa500, 0x6300,
161 0x4200, 0x2900, 0x6200, 0x6b00, 0xef00, 0xdd00, 0xd400, 0xbd00,
162 0xab00, 0x2900, 0x9b00, 0x7100, 0x8b00, 0xab00, 0x9c00, 0x9200,
163 0x6a00, 0x7b00, 0xa400, 0x7100, 0x7100, 0x8300, 0x8a00, 0x7800,
164 0x6200, 0x6900, 0xb300, 0xa300, 0x9200, 0x8200, 0x4800, 0x4e00,
165 0x5800, 0x8b00, 0x4900, 0x4500, 0x4e00, 0x3500, 0x3e00, 0xbb00,
166 0x5800, 0x5000, 0x3700, 0x4700, 0x5f00, 0xe500, 0x8200, 0x5800,
167 0x5800, 0x2700, 0x5000, 0x4800, 0x4000, 0x1d00, 0x1d00, 0xb400,
168 0x9300, 0x7a00, 0x3800, 0x3000, 0x2400, 0x1400, 0x6100, 0x4f00,
169 0x4d00, 0xac00, 0x9a00, 0x6a00, 0x6200, 0x5100, 0x5800, 0x4900,
170 0x4100, 0x6900, 0x6100, 0x2000, 0x4700, 0x1600, 0x0f00, 0x3f00,
171 0x1600, 0x6600, 0x4800, 0x4f00, 0x6600, 0x0000, 0xfb00, 0x9e00,
172 0x8000, 0x0b00, 0xff00, 0xf900, 0x0600, 0x0000, 0xf400, 0xff00,
174 static u16 dm270fb_romclut_blue[] = {
175 0x0000, 0x0000, 0x0000, 0x0000, 0xd700, 0xb900, 0x9d00, 0xc000,
176 0xb300, 0xff00, 0xfb00, 0x0800, 0x1000, 0x1800, 0x2100, 0x2900,
177 0x3100, 0x4a00, 0x5a00, 0x7300, 0x7b00, 0x9400, 0xa500, 0xbd00,
178 0x4000, 0x6700, 0x5f00, 0x4e00, 0x7300, 0x5b00, 0x5200, 0x4800,
179 0x3e00, 0x4a00, 0x4200, 0x3900, 0x3200, 0x0000, 0x1600, 0x0000,
180 0x0000, 0x3500, 0x1c00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
181 0x6000, 0x0300, 0x0000, 0x0000, 0x0000, 0x0000, 0x3d00, 0x0000,
182 0x0000, 0x2400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
183 0x0000, 0x3c00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0a00,
184 0x0200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
185 0x0900, 0x0c00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
186 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
187 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0300,
188 0x1d00, 0x3800, 0x1100, 0x1f00, 0x0c00, 0x0600, 0x0000, 0x0000,
189 0x0000, 0x0000, 0x1c00, 0x0000, 0x0000, 0x0000, 0x1c00, 0x5300,
190 0x0000, 0x0000, 0x2500, 0x0400, 0x0700, 0x0800, 0x0000, 0x0000,
191 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0a00, 0x8d00, 0x4b00,
192 0x3200, 0x2a00, 0x2300, 0x7400, 0xff00, 0xff00, 0xf800, 0xff00,
193 0xff00, 0xf700, 0xff00, 0xff00, 0xff00, 0xff00, 0xe600, 0xff00,
194 0xf500, 0xff00, 0xf500, 0xff00, 0xff00, 0xe400, 0xc300, 0x8100,
195 0x6000, 0x4700, 0xff00, 0xff00, 0xfd00, 0xfe00, 0xff00, 0xec00,
196 0xdd00, 0x3700, 0xdb00, 0xa300, 0xcb00, 0xfb00, 0xeb00, 0xe200,
197 0xaa00, 0xca00, 0xff00, 0xff00, 0xef00, 0xd000, 0xe800, 0xd900,
198 0xaf00, 0xff00, 0xf200, 0xe200, 0xd100, 0xc100, 0x8700, 0xbd00,
199 0xe500, 0xb900, 0x7700, 0xd200, 0xff00, 0xc200, 0xe600, 0xea00,
200 0x8700, 0x7f00, 0x6600, 0x9400, 0xdb00, 0xff00, 0xa100, 0xa500,
201 0x9500, 0x4600, 0x8d00, 0x8500, 0x7d00, 0x7900, 0x9700, 0xd300,
202 0xb200, 0x9900, 0x5700, 0x4f00, 0x9000, 0x6200, 0x8d00, 0x7e00,
203 0x9900, 0xba00, 0xab00, 0x7800, 0x7000, 0x5f00, 0x6900, 0x5700,
204 0x4f00, 0x8500, 0x7d00, 0x2e00, 0x7300, 0x2700, 0x1d00, 0x4d00,
205 0x2400, 0x8000, 0x5300, 0x5b00, 0x7300, 0x0000, 0xe700, 0xa700,
206 0x8000, 0x0000, 0x0000, 0x0000, 0xfe00, 0xff00, 0xff00, 0xff00,
209 static struct fb_cmap dm270fb_romclut_cmap = {
210 .start = 0,
211 .len = 256,
212 .red = dm270fb_romclut_red,
213 .green = dm270fb_romclut_green,
214 .blue = dm270fb_romclut_blue,
215 .transp = NULL,
218 /* -------------------- Hardware specific routines ------------------------- */
221 * Initialise the DM270 hardware
223 static void __init
224 dm270fb_init_hw(struct fb_info *fbinfo)
226 struct dm270fb_par *dm270fbpar = (struct dm270fb_par *)fbinfo->par;
227 unsigned int bmpwin_addr;
228 unsigned int osdmode;
229 unsigned int vid01 = 0;
230 unsigned int vid02 = 0;
231 unsigned int basepx = 0;
232 unsigned int basepy = 0;
233 int ii;
235 if (!dm270fbpar->cfg.noinit) {
236 /* Disable VENC & DAC */
237 outw(0, DM270_VENC_VID01);
239 /* Disable clock to OSD, VENC & DAC. */
240 outw((inw(DM270_CLKC_MOD1) &
241 ~(DM270_CLKC_MOD1_COSD | DM270_CLKC_MOD1_CVENC |
242 DM270_CLKC_MOD1_CDAC)),
243 DM270_CLKC_MOD1);
245 /* Select MXI as VENC clock source, CLK_VENC as OSD clock source */
246 outw((inw(DM270_CLKC_CLKC) &
247 ~(DM270_CLKC_CLKC_CENS0 | DM270_CLKC_CLKC_CENS1 |
248 DM270_CLKC_CLKC_COSDS | DM270_CLKC_CLKC_CENIV)),
249 DM270_CLKC_CLKC);
251 /* Enable clock to OSD, VENC & DAC. */
252 outw((inw(DM270_CLKC_MOD1) |
253 (DM270_CLKC_MOD1_COSD | DM270_CLKC_MOD1_CVENC |
254 DM270_CLKC_MOD1_CDAC)),
255 DM270_CLKC_MOD1);
257 // Disable VENC & DAC
258 outw(0, DM270_VENC_VID01);
260 /* Initialize OSD and VENC */
261 bmpwin_addr = (fbinfo->fix.smem_start - CONFIG_DRAM_BASE) >> 5;
262 outw((bmpwin_addr >> 16), DM270_OSD_BMPWINADH); /* XXX potential contention between bmpwin0 & bmpwin1 */
263 outw((bmpwin_addr & 0xffff), dm270fbpar->regaddr.bmpwinadl);
265 osdmode = (DM270_OSD_OSDMODE_CS_CBCR |
266 DM270_OSD_OSDMODE_BCLUT_ROM |
267 DM270_OSD_OSDMODE_CABG_BLACK);
269 if (dm270fbpar->cfg.disp_type == DISP_TYPE_COMP) {
270 vid01 = (DM270_VENC_VID01_CRCUT_1_5MHZ |
271 DM270_VENC_VID01_SETUP_0 |
272 DM270_VENC_VID01_RGBFLT_OFF |
273 DM270_VENC_VID01_YFLT_OFF |
274 DM270_VENC_VID01_COUTEN_ENABLE |
275 DM270_VENC_VID01_BLANK_NORMAL);
277 vid02 = (DM270_VENC_VID02_SSMD_NTSCPAL |
278 DM270_VENC_VID02_SCMP_YES |
279 DM270_VENC_VID02_SYSW_DISABLE |
280 DM270_VENC_VID02_VSSW_CSYNC | /* XXX */
281 DM270_VENC_VID02_SYNE_ENABLE |
282 DM270_VENC_VID02_BREN_DISABLE |
283 DM270_VENC_VID02_BRPL_ACTIVELOW |
284 DM270_VENC_VID02_BRWDTH_0);
285 } else if (dm270fbpar->cfg.disp_type == DISP_TYPE_LCD ||
286 dm270fbpar->cfg.disp_type == DISP_TYPE_TFT ||
287 dm270fbpar->cfg.disp_type == DISP_TYPE_CRT) {
288 } else if (dm270fbpar->cfg.disp_type == DISP_TYPE_EPSON) {
289 } else if (dm270fbpar->cfg.disp_type == DISP_TYPE_CASIO) {
290 } else {
293 if (dm270fbpar->cfg.vidout_std == VID_FMT_NTSC) {
294 vid01 |= DM270_VENC_VID01_NTPLS_NTSC;
296 osdmode |= (DM270_OSD_OSDMODE_ORSZ_X1 |
297 DM270_OSD_OSDMODE_FSINV_NORMAL);
299 basepx = DM270FB_OSD_BASEPX_NTSC; /* 120 */
300 basepy = DM270FB_OSD_BASEPY_NTSC; /* 18 */
301 } else if (dm270fbpar->cfg.vidout_std == VID_FMT_PAL) {
302 vid01 |= DM270_VENC_VID01_NTPLS_PAL;
304 osdmode |= (DM270_OSD_OSDMODE_ORSZ_X6_5 |
305 DM270_OSD_OSDMODE_FSINV_INVERTED);
307 basepx = DM270FB_OSD_BASEPX_PAL; /* 144 */
308 basepy = DM270FB_OSD_BASEPY_PAL; /* 22 */
309 } else {
312 for (ii = 0; ii < 16; ii += 2) {
313 outw(((ii + 1) << 8) | ii,
314 dm270fbpar->regaddr.wbmp + ii);
317 outw(basepx, DM270_OSD_BASEPX);
318 outw(basepy, DM270_OSD_BASEPY);
319 outw(osdmode, DM270_OSD_OSDMODE);
320 outw(vid02, DM270_VENC_VID02);
321 outw(vid01, DM270_VENC_VID01);
322 } else {
323 bmpwin_addr = ((unsigned int)inw(DM270_OSD_BMPWINADH) << 16);
324 bmpwin_addr |= inw(dm270fbpar->regaddr.bmpwinadl);
325 fbinfo->fix.smem_start = (bmpwin_addr << 5) + CONFIG_DRAM_BASE;
326 fbinfo->screen_base = phys_to_virt(fbinfo->fix.smem_start);
327 DPRINTK("phys=0x%016lx virt=0x%08x len=%u\n",
328 fbinfo->fix.smem_start,
329 (unsigned int)fbinfo->screen_base,
330 fbinfo->fix.smem_len);
333 DPRINTK("OSDMODE=0x%04x BASEPX=0x%04x BASEPY=0x%04x\n",
334 inw(DM270_OSD_OSDMODE), inw(DM270_OSD_BASEPX),
335 inw(DM270_OSD_BASEPY));
336 DPRINTK("BMPWINADH=0x%04x BMPWINADL=0x%04x\n",
337 inw(DM270_OSD_BMPWINADH), inw(dm270fbpar->regaddr.bmpwinadl));
338 DPRINTK("VID01=0x%04x VID02=0x%04x\n",
339 inw(DM270_VENC_VID01), inw(DM270_VENC_VID02));
342 static void
343 dm270fb_blank_display(struct fb_info *fbinfo)
345 outw(inw(DM270_VENC_VID01) | DM270_VENC_VID01_BLANK, DM270_VENC_VID01);
346 DPRINTK("Blank: VID01=0x%04x\n", inw(DM270_VENC_VID01));
349 static void
350 dm270fb_unblank_display(struct fb_info *fbinfo)
352 outw(inw(DM270_VENC_VID01) & ~DM270_VENC_VID01_BLANK, DM270_VENC_VID01);
353 DPRINTK("Unblank: VID01=0x%04x\n", inw(DM270_VENC_VID01));
357 * FIXME: move LCD power stuff into dm270fb_dac_powerup()
358 * Also, I'm expecting that the backlight stuff should
359 * be handled differently.
361 static void
362 dm270fb_backlight_on(struct fb_info *fbinfo)
364 DPRINTK("Backlight on\n");
365 #ifdef CONFIG_BOARD_IMPLDM270VP4
366 outw(DM270_GIO_GIO06_BIT, DM270_GIO_BITSET0);
367 #endif
371 * FIXME: move LCD power stuff into dm270fb_dac_powerdown()
372 * Also, I'm expecting that the backlight stuff should
373 * be handled differently.
375 static void
376 dm270fb_backlight_off(struct fb_info *fbinfo)
378 DPRINTK("Backlight off\n");
379 #ifdef CONFIG_BOARD_IMPLDM270VP4
380 outw(DM270_GIO_GIO06_BIT, DM270_GIO_BITCLR0);
381 #endif
384 static void
385 dm270fb_dac_powerup(struct fb_info *fbinfo)
387 outw(inw(DM270_VENC_VID01) | DM270_VENC_VID01_DAPD, DM270_VENC_VID01);
388 DPRINTK("DAC poweron: VID01=0x%04x\n", inw(DM270_VENC_VID01));
391 static void
392 dm270fb_dac_powerdown(struct fb_info *fbinfo)
394 outw(inw(DM270_VENC_VID01) & ~DM270_VENC_VID01_DAPD, DM270_VENC_VID01);
395 DPRINTK("DAC poweroff: VID01=0x%04x\n", inw(DM270_VENC_VID01));
398 static void
399 dm270fb_osd_enable(struct fb_info *fbinfo)
401 struct dm270fb_par *dm270fbpar = (struct dm270fb_par *)fbinfo->par;
403 outw(inw(dm270fbpar->regaddr.bmpwinmd) | DM270_OSD_BMPWINMD_OACT,
404 dm270fbpar->regaddr.bmpwinmd);
406 DPRINTK("OSD enable: BMPWINMD=0x%04x\n",
407 inw(dm270fbpar->regaddr.bmpwinmd));
410 static void
411 dm270fb_osd_disable(struct fb_info *fbinfo)
413 struct dm270fb_par *dm270fbpar = (struct dm270fb_par *)fbinfo->par;
415 outw(inw(dm270fbpar->regaddr.bmpwinmd) & ~DM270_OSD_BMPWINMD_OACT,
416 dm270fbpar->regaddr.bmpwinmd);
418 DPRINTK("OSD disable: BMPWINMD=0x%04x\n",
419 inw(dm270fbpar->regaddr.bmpwinmd));
422 static void
423 dm270fb_venc_enable(struct fb_info *fbinfo)
425 outw(inw(DM270_VENC_VID01) | (DM270_VENC_VID01_DAOE |
426 DM270_VENC_VID01_VENC), DM270_VENC_VID01);
428 DPRINTK("VENC enable: VID01=0x%04x\n", inw(DM270_VENC_VID01));
431 static void
432 dm270fb_venc_disable(struct fb_info *fbinfo)
434 outw(inw(DM270_VENC_VID01) & ~(DM270_VENC_VID01_DAOE |
435 DM270_VENC_VID01_VENC), DM270_VENC_VID01);
437 DPRINTK("VENC disable: VID01=0x%04x\n", inw(DM270_VENC_VID01));
440 static int
441 dm270fb_set_palettereg(unsigned int regno, unsigned int red, unsigned int green,
442 unsigned int blue, unsigned int transp, struct fb_info *fbinfo)
444 unsigned int ccir601_y;
445 unsigned int ccir601_cb;
446 unsigned int ccir601_cr;
447 int too_long;
449 if (regno >= DM270FB_NR_PALETTE) {
450 WPRINTK("regno %u exceed %u CLUT entries\n",
451 regno, DM270FB_NR_PALETTE);
452 return -EINVAL;
456 * CCIR-601 YCbCr Color Space Conversion Equation
458 * Y = ( 77R + 150G + 29B)/256 Range: 16 ~ 235
459 * Cb = (-44R - 87G + 131B)/256 + 128 Range: 16 ~ 240
460 * Cr = (131R - 110G - 21B)/256 + 128 Range: 16 ~ 240
462 * R = Y + 1.371(Cr - 128)
463 * G = Y - 0.698(Cr - 128) - 0.336(Cb - 128)
464 * B = Y + 1.732(Cb - 128)
466 * where R, G and B are gamma-corrected values with a nominal range of 16 to 235
468 * Y = 0.257R + 0.504G + 0.098B + 16 Range: 16 ~ 235
469 * Cb = -0.148R - 0.291G + 0.439B + 128 Range: 16 ~ 240
470 * Cr = 0.439R - 0.368G - 0.071B + 128 Range: 16 ~ 240
472 * R = 1.164(Y - 16) + 1.596(Cr - 128)
473 * G = 1.164(Y - 16) - 0.813(Cr - 128) - 0.392(Cb - 128)
474 * B = 1.164(Y - 16) + 2.017(Cb - 128)
476 * where R, G and B are gamma-corrected values with a range of 0 to 255
479 ccir601_y = ((16843*red + 33030*green + 6423*blue)/65536 + 16) & 0xff;
480 ccir601_cb = ((-9699*red - 19071*green + 28770*blue)/65536 + 128) & 0xff;
481 ccir601_cr = ((28770*red - 24117*green - 4653*blue)/65536 + 128) & 0xff;
483 too_long = 100000;
484 while ((inw(DM270_OSD_MISCCTL) & DM270_OSD_MISCCTL_CPBSY) &&
485 (too_long-- > 0));
487 if (too_long <= 0) {
488 WPRINTK("timeout (MISCCTL=0x%04x)\n", inw(DM270_OSD_MISCCTL));
489 return -ETIMEDOUT;
492 outw((ccir601_y << 8) | ccir601_cb , DM270_OSD_CLUTRAMYCB);
494 #if 0
496 * XXX
497 * discrepancy between description and code in
498 * DM270 Techincal Reference Manual Ver 1.2 Sect 12.7.1.2 Pg 274
500 too_long = 100000;
501 while ((inw(DM270_OSD_MISCCTL) & DM270_OSD_MISCCTL_CPBSY) &&
502 (too_long-- > 0));
503 #endif
505 outw((ccir601_cr << 8) | (regno & 0xff), DM270_OSD_CLUTRAMCR);
506 return 0;
509 /* -------------------- Helper routines ------------------------- */
511 static void
512 dm270fb_display_powerup(struct fb_info *fbinfo)
514 DPRINTK("Display poweron\n");
515 dm270fb_dac_powerup(fbinfo);
516 dm270fb_backlight_on(fbinfo);
519 static void
520 dm270fb_display_powerdown(struct fb_info *fbinfo)
522 DPRINTK("Display poweroff\n");
523 dm270fb_backlight_off(fbinfo);
524 dm270fb_dac_powerdown(fbinfo);
527 static void
528 dm270fb_display_enable(struct fb_info *fbinfo)
530 DPRINTK("Display enable\n");
531 dm270fb_osd_enable(fbinfo);
532 dm270fb_venc_enable(fbinfo);
533 dm270fb_display_powerup(fbinfo);
536 static void
537 dm270fb_display_disable(struct fb_info *fbinfo)
539 DPRINTK("Display disable\n");
540 dm270fb_display_powerdown(fbinfo);
541 dm270fb_venc_disable(fbinfo);
542 dm270fb_osd_disable(fbinfo);
545 static unsigned int
546 dm270fb_calc_linelength(struct fb_info *fbinfo)
548 unsigned int linelength;
551 * Where width of data in SDRAM is not multiple of 32 bytes, padding
552 * must be done to make it multiple of 32 bytes
554 linelength = ((((fbinfo->var.xres_virtual * fbinfo->var.bits_per_pixel)
555 + 255) >> 8) << 5);
556 fbinfo->var.xres_virtual = (linelength << 3) /
557 fbinfo->var.bits_per_pixel;
558 return linelength;
562 * dm270fb_decode_var - Get the hardware video params out of 'var'.
563 * @info: frame buffer structure that represents a single frame buffer
564 * @regval: hardware register values obtained from 'var'
566 static int
567 dm270fb_decode_var(struct fb_info *fbinfo, struct dm270fb_regval *regval)
569 fbinfo->fix.line_length = dm270fb_calc_linelength(fbinfo);
570 regval->bmpwinofst = (fbinfo->fix.line_length >> 5);
571 regval->bmpwinxl = fbinfo->var.xres;
572 regval->bmpwinxp = fbinfo->var.xoffset;
574 regval->bmpwinmd = (DM270_OSD_BMPWINMD_CLUT_ROM |
575 DM270_OSD_BMPWINMD_OHZ_X1 |
576 DM270_OSD_BMPWINMD_OVZ_X1 |
577 DM270_OSD_BMPWINMD_BLND_0_8 |
578 DM270_OSD_BMPWINMD_TE_ENABLE);
580 regval->vid01 = 0;
581 if (fbinfo->var.vmode & FB_VMODE_INTERLACED) {
582 regval->vid01 |= DM270_VENC_VID01_SCMD_INTERLACE;
583 } else if (fbinfo->var.vmode & FB_VMODE_NONINTERLACED) {
584 regval->vid01 |= DM270_VENC_VID01_SCMD_NONINTERLACE;
587 regval->vid02 = 0;
588 if (fbinfo->var.sync & FB_SYNC_COMP_HIGH_ACT) {
589 regval->vid02 |= DM270_VENC_VID02_VSSW_CSYNC;
592 if (fbinfo->var.vmode & FB_VMODE_DOUBLE) {
593 regval->bmpwinyl = fbinfo->var.yres;
594 regval->bmpwinyp = fbinfo->var.yoffset;
595 regval->bmpwinmd |= DM270_OSD_BMPWINMD_OFF_FIELD;
596 } else {
597 regval->bmpwinyl = (fbinfo->var.yres >> 1);
598 regval->bmpwinyp = (fbinfo->var.yoffset >> 1);
599 regval->bmpwinmd |= DM270_OSD_BMPWINMD_OFF_FRAME;
602 switch (fbinfo->var.bits_per_pixel) {
603 case 1: regval->bmpwinmd |= DM270_OSD_BMPWINMD_BMW_1BPP; break;
604 case 2: regval->bmpwinmd |= DM270_OSD_BMPWINMD_BMW_2BPP; break;
605 case 4: regval->bmpwinmd |= DM270_OSD_BMPWINMD_BMW_4BPP; break;
606 case 8: regval->bmpwinmd |= DM270_OSD_BMPWINMD_BMW_8BPP; break;
607 default:
608 WPRINTK("depth %u bpp not supported???\n",
609 fbinfo->var.bits_per_pixel);
610 return -EINVAL;
613 return 0;
617 * dm270fb_map_graphics_memory - Allocates DRAM memory for frame buffer.
618 * @info: frame buffer structure that represents a single frame buffer
620 * This memory is remapped into a non-cached, non-buffered, memory region
621 * to allow pixel writes to occur without flushing the cache. Once this
622 * area is remapped, all virtual memory access to the graphics memory
623 * should occur at the new region.
625 static int __init
626 dm270fb_map_graphics_memory(struct fb_info *fbinfo)
628 unsigned long adrs;
629 unsigned long size;
632 * We reserve size of the framebuffer.
634 size = PAGE_ALIGN(fbinfo->fix.smem_len);
635 if (0 == size) {
636 WPRINTK("size=%u\n", fbinfo->fix.smem_len);
637 return -EINVAL;
639 if (size > (PAGE_SIZE << MAX_ORDER)) {
640 WPRINTK("size %u exceed %lu\n", fbinfo->fix.smem_len,
641 (PAGE_SIZE << MAX_ORDER));
642 return -EINVAL;
644 fbinfo->screen_base = (void *)__get_free_pages(GFP_KERNEL,
645 get_order(size));
646 if (NULL == fbinfo->screen_base) {
647 WPRINTK("alloc failed: virt=0x%08x size=%u "
648 "PAGESIZE=%lu MAX_ORDER=%u\n",
649 (unsigned int)fbinfo->screen_base, fbinfo->fix.smem_len,
650 PAGE_SIZE, MAX_ORDER);
651 return -ENOMEM;
653 fbinfo->fix.smem_len = size;
654 adrs = (unsigned long)fbinfo->screen_base;
655 while (size > 0) {
656 SetPageReserved(virt_to_page(adrs));
657 adrs += PAGE_SIZE;
658 size -= PAGE_SIZE;
660 fbinfo->fix.smem_start = virt_to_phys(fbinfo->screen_base);
661 DPRINTK("phys=0x%016lx virt=0x%08x len=%u\n", fbinfo->fix.smem_start,
662 (unsigned int)fbinfo->screen_base,
663 fbinfo->fix.smem_len);
664 memset(fbinfo->screen_base, 0, fbinfo->fix.smem_len);
665 return 0;
669 * dm270fb_unmap_graphics_memory - Frees DRAM memory of frame buffer.
670 * @info: frame buffer structure that represents a single frame buffer
672 static void
673 dm270fb_unmap_graphics_memory(struct fb_info *fbinfo)
675 unsigned long adrs;
676 unsigned long size;
678 DPRINTK("phys=0x%016lx virt=0x%08x len=%u\n",
679 fbinfo->fix.smem_start,
680 (unsigned int)fbinfo->screen_base,
681 fbinfo->fix.smem_len);
683 if (fbinfo->screen_base) {
684 size = fbinfo->fix.smem_len;
685 adrs = (unsigned long)fbinfo->screen_base;
686 while (size > 0) {
687 ClearPageReserved(virt_to_page(adrs));
688 adrs += PAGE_SIZE;
689 size -= PAGE_SIZE;
691 free_pages((unsigned long)fbinfo->screen_base, get_order(fbinfo->fix.smem_len));
692 fbinfo->fix.smem_len = 0;
693 fbinfo->fix.smem_start = 0;
694 fbinfo->screen_base = NULL;
699 * ===========================================================================
703 * dm270fb_check_var - Optional function. Validates a var passed in.
704 * @var: frame buffer variable screen structure
705 * @info: frame buffer structure that represents a single frame buffer
707 * Checks to see if the hardware supports the state requested by
708 * var passed in. This function does not alter the hardware state!!!
709 * This means the data stored in struct fb_info and struct dm270fb_par do
710 * not change. This includes the var inside of struct fb_info.
711 * Do NOT change these. This function can be called on its own if we
712 * intent to only test a mode and not actually set it. The stuff in
713 * modedb.c is a example of this. If the var passed in is slightly
714 * off by what the hardware can support then we alter the var PASSED in
715 * to what we can do. If the hardware doesn't support mode change
716 * a -EINVAL will be returned by the upper layers. You don't need to
717 * implement this function then. If you hardware doesn't support
718 * changing the resolution then this function is not needed. In this
719 * case the driver woudl just provide a var that represents the static
720 * state the screen is in.
722 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
724 * Suggestion: Round up in the following order: bits_per_pixel, xres,
725 * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
726 * bitfields, horizontal timing, vertical timing.
728 * Returns negative errno on error, or zero on success.
730 static int
731 dm270fb_check_var(struct fb_var_screeninfo *fbvar, struct fb_info *fbinfo)
733 switch (fbvar->bits_per_pixel) {
734 case 1:
735 case 2:
736 case 4:
737 case 8:
738 /* for bpp <= 8, length of red = length of green = length of blue = bpp */
739 fbvar->red.offset = 0;
740 fbvar->red.length = fbvar->bits_per_pixel;
741 fbvar->red.msb_right = 0;
743 fbvar->green.offset = 0;
744 fbvar->green.length = fbvar->bits_per_pixel;
745 fbvar->green.msb_right = 0;
747 fbvar->blue.offset = 0;
748 fbvar->blue.length = fbvar->bits_per_pixel;
749 fbvar->blue.msb_right = 0;
751 fbvar->transp.offset = 0;
752 fbvar->transp.length = 0;
753 fbvar->transp.msb_right = 0;
754 break;
755 default:
756 WPRINTK("unsupported depth: %u bpp\n", fbvar->bits_per_pixel);
757 return -EINVAL;
760 if (fbvar->xres < DM270FB_XRES_MIN) {
761 WPRINTK("width %u round up to %u\n",
762 fbvar->xres, DM270FB_XRES_MIN);
763 fbvar->xres = DM270FB_XRES_MIN;
765 if (fbvar->yres < DM270FB_YRES_MIN) {
766 WPRINTK("height %u round up to %u\n",
767 fbvar->yres, DM270FB_YRES_MIN);
768 fbvar->yres = DM270FB_YRES_MIN;
770 if (fbvar->xres > DM270FB_XRES_MAX) {
771 WPRINTK("width %u round down to %u\n",
772 fbvar->xres, DM270FB_XRES_MAX);
773 fbvar->xres = DM270FB_XRES_MAX;
775 if (fbvar->yres > DM270FB_YRES_MAX) {
776 WPRINTK("height %u round down to %u\n",
777 fbvar->yres, DM270FB_YRES_MAX);
778 fbvar->yres = DM270FB_YRES_MAX;
781 if (fbvar->xres_virtual < fbvar->xres) {
782 WPRINTK("virtual x resolution %u round up to "
783 "physical x resolution %u\n",
784 fbvar->xres_virtual, fbvar->xres);
785 fbvar->xres_virtual = fbvar->xres;
787 if (fbvar->yres_virtual < fbvar->yres) {
788 WPRINTK("virtual y resolution %u round up to "
789 "physical y resolution %u\n",
790 fbvar->yres_virtual, fbvar->yres);
791 fbvar->yres_virtual = fbvar->yres;
794 if (((fbvar->xres_virtual * fbvar->yres_virtual * fbvar->bits_per_pixel)
795 >> 3) > fbinfo->fix.smem_len) {
796 WPRINTK("insufficient memory for virtual screen (%u, %u, %u)\n",
797 fbvar->xres_virtual, fbvar->yres_virtual,
798 fbvar->bits_per_pixel);
799 return -ENOMEM;
802 fbvar->nonstd = 0;
803 fbvar->height = -1;
804 fbvar->width = -1;
805 return 0;
809 * dm270fb_set_par - Optional function. Alters the hardware state.
810 * @info: frame buffer structure that represents a single frame buffer
812 * Using the fb_var_screeninfo in fb_info we set the resolution of the
813 * this particular framebuffer. This function alters the par AND the
814 * fb_fix_screeninfo stored in fb_info. It doesn't alter var in
815 * fb_info since we are using that data. This means we depend on the
816 * data in var inside fb_info to be supported by the hardware.
817 * dm270fb_check_var is always called before dm270fb_set_par to ensure this.
818 * Again if you can't change the resolution you don't need this function.
820 * Configures OSD based on entries in var parameter. Settings are
821 * only written to the controller if changes were made.
823 static int
824 dm270fb_set_par(struct fb_info *fbinfo)
826 struct dm270fb_par *dm270fbpar = (struct dm270fb_par *)fbinfo->par;
827 struct dm270fb_regval regval;
828 int retval;
830 DPRINTK("Configuring TI TMS320DM270 OSD\n");
832 if ((retval = dm270fb_decode_var(fbinfo, &regval)))
833 return retval;
836 * XXX
837 * Only DM270_VENC_VID01_SCMD & DM270_VENC_VID02_VSSW are tracked.
838 * DM270_OSD_BMPWINMD_OACT is not tracked.
840 dm270fbpar->regval = regval; /* struct copy */
842 outw((inw(DM270_VENC_VID02) & ~(DM270_VENC_VID02_VSSW)) |
843 regval.vid02, DM270_VENC_VID02);
844 outw((inw(DM270_VENC_VID01) & ~(DM270_VENC_VID01_SCMD)) |
845 regval.vid01, DM270_VENC_VID01);
847 outw((inw(dm270fbpar->regaddr.bmpwinmd) & DM270_OSD_BMPWINMD_OACT) |
848 regval.bmpwinmd, dm270fbpar->regaddr.bmpwinmd);
849 outw(regval.bmpwinofst, dm270fbpar->regaddr.bmpwinofst);
850 outw(regval.bmpwinxl, dm270fbpar->regaddr.bmpwinxl);
851 outw(regval.bmpwinyl, dm270fbpar->regaddr.bmpwinyl);
852 outw(regval.bmpwinxp, dm270fbpar->regaddr.bmpwinxp);
853 outw(regval.bmpwinyp, dm270fbpar->regaddr.bmpwinyp);
855 DPRINTK("VID01=0x%04x VID02=0x%04x\n",
856 inw(DM270_VENC_VID01), inw(DM270_VENC_VID02));
857 DPRINTK("BMPWINMD=0x%04x BMPWINOFST=0x%04x\n",
858 inw(dm270fbpar->regaddr.bmpwinmd),
859 inw(dm270fbpar->regaddr.bmpwinofst));
860 DPRINTK("BMPWINXL=0x%04x BMPWINYL=0x%04x\n",
861 inw(dm270fbpar->regaddr.bmpwinxl),
862 inw(dm270fbpar->regaddr.bmpwinyl));
863 DPRINTK("BMPWINXP=0x%04x BMPWINYP=0x%04x\n",
864 inw(dm270fbpar->regaddr.bmpwinxp),
865 inw(dm270fbpar->regaddr.bmpwinyp));
866 return 0;
870 * dm270fb_setcolreg - Optional function. Sets a color register.
871 * @regno: Which register in the CLUT we are programming
872 * @red: The red value which can be up to 16 bits wide
873 * @green: The green value which can be up to 16 bits wide
874 * @blue: The blue value which can be up to 16 bits wide
875 * @transp: If supported the alpha value which can be up to 16 bits wide.
876 * @info: frame buffer info structure
878 * Set a single color register. The values supplied have a 16 bit
879 * magnitude which needs to be scaled in this function for the hardware.
880 * Things to take into consideration are how many color registers, if
881 * any, are supported with the current color visual. With truecolor mode
882 * no color palettes are supported. Here a psuedo palette is created
883 * which we store the value in pseudo_palette in struct fb_info. For
884 * pseudocolor mode we have a limited color palette. To deal with this
885 * we can program what color is displayed for a particular pixel value.
886 * DirectColor is similar in that we can program each color field. If
887 * we have a static colormap we don't need to implement this function.
889 * Returns negative errno on error, or zero on success.
891 static int
892 dm270fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
893 unsigned int blue, unsigned int transp, struct fb_info *fbinfo)
895 DPRINTK("regno=%u red=%u green=%u blue=%u transp=%u\n",
896 regno, red, green, blue, transp);
899 * If grayscale is true, we convert the RGB value to
900 * grayscale regardless of what visual we are using.
902 if (fbinfo->var.grayscale) {
903 /* gray = 0.30*R + 0.59*G + 0.11*B */
904 red = green = blue =
905 (19595 * red + 38470 * green + 7471 * blue) >> 16;
908 switch (fbinfo->fix.visual) {
909 case FB_VISUAL_PSEUDOCOLOR:
911 * Pseudocolour:
912 * 8 8
913 * pixel --/--+--/--> red lut --> red dac
914 * | 8
915 * +--/--> green lut --> green dac
916 * | 8
917 * +--/--> blue lut --> blue dac
919 if (regno >= fbinfo->cmap.len || regno >= DM270FB_NR_PALETTE) {
920 WPRINTK("regno %u exceed cmap length %u (max %u)\n",
921 regno, fbinfo->cmap.len,
922 DM270FB_NR_PALETTE);
923 return -EINVAL;
926 return dm270fb_set_palettereg(regno, red, green, blue,
927 transp, fbinfo);
928 default:
929 WPRINTK("invalid visual %u\n", fbinfo->fix.visual);
930 return -EINVAL;
933 return 0;
937 * dm270fb_blank - NOT a required function. Blanks the display.
938 * @blank: the blank mode we want.
939 * @info: frame buffer structure that represents a single frame buffer
941 * Blank the screen if blank != 0, else unblank. Return 0 if
942 * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
943 * video mode which doesn't support it. Implements VESA suspend
944 * and powerdown modes on hardware that supports disabling hsync/vsync:
945 * blank == 2: suspend vsync
946 * blank == 3: suspend hsync
947 * blank == 4: powerdown
949 * Returns negative errno on error, or zero on success.
952 * Formal definition of the VESA spec:
953 * On
954 * This refers to the state of the display when it is in full operation
955 * Stand-By
956 * This defines an optional operating state of minimal power reduction with
957 * the shortest recovery time
958 * Suspend
959 * This refers to a level of power management in which substantial power
960 * reduction is achieved by the display. The display can have a longer
961 * recovery time from this state than from the Stand-by state
962 * Off
963 * This indicates that the display is consuming the lowest level of power
964 * and is non-operational. Recovery from this state may optionally require
965 * the user to manually power on the monitor
967 * Now, the fbdev driver adds an additional state, (blank), where they
968 * turn off the video (maybe by colormap tricks), but don't mess with the
969 * video itself: think of it semantically between on and Stand-By.
971 * So here's what we should do in our fbdev blank routine:
973 * VESA_NO_BLANKING (mode 0) Video on, front/back light on
974 * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off
975 * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off
976 * VESA_POWERDOWN (mode 3) Video off, front/back light off
978 * This will match the matrox implementation.
980 static int
981 dm270fb_blank(int blank, struct fb_info *fbinfo)
983 DPRINTK("blank=%d\n", blank);
985 if (blank) {
986 dm270fb_blank_display(fbinfo);
987 } else {
988 dm270fb_unblank_display(fbinfo);
989 dm270fb_dac_powerup(fbinfo);
991 if (blank > 0) {
992 switch (blank - 1) {
993 case VESA_NO_BLANKING:
994 dm270fb_display_powerup(fbinfo);
995 break;
996 case VESA_VSYNC_SUSPEND:
997 case VESA_HSYNC_SUSPEND:
998 dm270fb_dac_powerdown(fbinfo);
999 break;
1000 case VESA_POWERDOWN:
1001 dm270fb_display_powerdown(fbinfo);
1002 break;
1003 default:
1004 WPRINTK("invalid VESA blanking level %d\n", blank);
1005 return -EINVAL;
1009 return 0;
1013 * dm270fb_pan_display - NOT a required function. Pans the display.
1014 * @var: frame buffer variable screen structure
1015 * @info: frame buffer structure that represents a single frame buffer
1017 * Pan (or wrap, depending on the `vmode' field) the display using the
1018 * `xoffset' and `yoffset' fields of the `var' structure.
1019 * If the values don't fit, return -EINVAL.
1021 * Returns negative errno on error, or zero on success.
1023 static int
1024 dm270fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1026 return -EINVAL;
1029 static int
1030 dm270fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
1031 unsigned long arg, struct fb_info *fbinfo)
1033 int ii;
1034 int jj;
1035 int retval = 0;
1037 switch (cmd) {
1038 #ifdef DM270FB_DEBUG
1039 case FBIOPUT_DM270_COLORIMG:
1040 DPRINTK("FBIOPUT_DM270_COLORIMG\n");
1041 for (ii = 0; ii < fbinfo->var.yres; ii++) {
1042 for (jj = 0; jj < fbinfo->var.xres; jj++) {
1043 *((unsigned char *)fbinfo->screen_base +
1044 ii*fbinfo->var.xres + jj) = arg;
1047 break;
1049 case FBCMD_DM270_PRINT_FBUF:
1050 DPRINTK("FBCMD_DM270_PRINT_FBUF\n");
1051 if (arg < 0 || arg >= fbinfo->var.yres) {
1052 WPRINTK("arg=%ld (%u)\n", arg, fbinfo->var.yres);
1053 return -EINVAL;
1055 for (ii = 0; ii < fbinfo->var.xres; ii++) {
1056 unsigned char *fbaddr =
1057 (unsigned char *)fbinfo->screen_base +
1058 arg*fbinfo->var.xres + ii;
1059 if (!(ii % 16)) {
1060 printk("\n%p: %02x ", fbaddr, *fbaddr);
1061 } else {
1062 printk("%02x ", *fbaddr);
1065 printk("\n");
1066 break;
1068 case FBCMD_DM270_PRINT_REG:
1069 DPRINTK("FBCMD_DM270_PRINT_REG\n");
1071 DPRINTK("Clock Controller\n" );
1072 DPRINTK("================\n" );
1073 DPRINTK("PLLA = 0x%08x\n", inw(DM270_CLKC_PLLA));
1074 DPRINTK("PLLB = 0x%08x\n", inw(DM270_CLKC_PLLB));
1075 DPRINTK("CLKC = 0x%08x\n", inw(DM270_CLKC_CLKC));
1076 DPRINTK("SEL = 0x%08x\n", inw(DM270_CLKC_SEL));
1077 DPRINTK("DIV = 0x%08x\n", inw(DM270_CLKC_DIV));
1078 DPRINTK("BYP = 0x%08x\n", inw(DM270_CLKC_BYP));
1079 DPRINTK("MMCCLK = 0x%08x\n", inw(DM270_CLKC_MMCCLK));
1080 DPRINTK("MOD0 = 0x%08x\n", inw(DM270_CLKC_MOD0));
1081 DPRINTK("MOD1 = 0x%08x\n", inw(DM270_CLKC_MOD1));
1082 DPRINTK("MOD2 = 0x%08x\n", inw(DM270_CLKC_MOD2));
1083 DPRINTK("LPCTL0 = 0x%08x\n", inw(DM270_CLKC_LPCTL0));
1084 DPRINTK("LPCTL1 = 0x%08x\n", inw(DM270_CLKC_LPCTL1));
1085 DPRINTK("OSEL = 0x%08x\n", inw(DM270_CLKC_OSEL));
1086 DPRINTK("O0DIV = 0x%08x\n", inw(DM270_CLKC_O0DIV));
1087 DPRINTK("O1DIV = 0x%08x\n", inw(DM270_CLKC_O1DIV));
1088 DPRINTK("O2DIV = 0x%08x\n", inw(DM270_CLKC_O2DIV));
1089 DPRINTK("PWM0C = 0x%08x\n", inw(DM270_CLKC_PWM0C));
1090 DPRINTK("PWM0H = 0x%08x\n", inw(DM270_CLKC_PWM0H));
1091 DPRINTK("PWM1C = 0x%08x\n", inw(DM270_CLKC_PWM1C));
1092 DPRINTK("PWM1H = 0x%08x\n", inw(DM270_CLKC_PWM1H));
1093 DPRINTK("\n");
1095 DPRINTK("OSD - On-Screen Display\n" );
1096 DPRINTK("=======================\n" );
1097 DPRINTK("OSDMODE = 0x%04x\n", inw(DM270_OSD_OSDMODE));
1098 DPRINTK("VIDWINMD = 0x%04x\n", inw(DM270_OSD_VIDWINMD));
1099 DPRINTK("BMPWIN0MD = 0x%04x\n", inw(DM270_OSD_BMPWIN0MD));
1100 DPRINTK("ATRMD = 0x%04x\n", inw(DM270_OSD_ATRMD));
1101 DPRINTK("RECTCUR = 0x%04x\n", inw(DM270_OSD_RECTCUR));
1102 DPRINTK("VIDWIN0OFST = 0x%04x\n", inw(DM270_OSD_VIDWIN0OFST));
1103 DPRINTK("VIDWIN1OFST = 0x%04x\n", inw(DM270_OSD_VIDWIN1OFST));
1104 DPRINTK("BMPWIN0OFST = 0x%04x\n", inw(DM270_OSD_BMPWIN0OFST));
1105 DPRINTK("BMPWIN1OFST = 0x%04x\n", inw(DM270_OSD_BMPWIN1OFST));
1106 DPRINTK("VIDWINADH = 0x%04x\n", inw(DM270_OSD_VIDWINADH));
1107 DPRINTK("VIDWIN0ADL = 0x%04x\n", inw(DM270_OSD_VIDWIN0ADL));
1108 DPRINTK("VIDWIN1ADL = 0x%04x\n", inw(DM270_OSD_VIDWIN1ADL));
1109 DPRINTK("BMPWINADH = 0x%04x\n", inw(DM270_OSD_BMPWINADH));
1110 DPRINTK("BMPWIN0ADL = 0x%04x\n", inw(DM270_OSD_BMPWIN0ADL));
1111 DPRINTK("BMPWIN1ADL = 0x%04x\n", inw(DM270_OSD_BMPWIN1ADL));
1112 DPRINTK("BASEPX = 0x%04x\n", inw(DM270_OSD_BASEPX));
1113 DPRINTK("BASEPY = 0x%04x\n", inw(DM270_OSD_BASEPY));
1114 DPRINTK("VIDWIN0XP = 0x%04x\n", inw(DM270_OSD_VIDWIN0XP));
1115 DPRINTK("VIDWIN0YP = 0x%04x\n", inw(DM270_OSD_VIDWIN0YP));
1116 DPRINTK("VIDWIN0XL = 0x%04x\n", inw(DM270_OSD_VIDWIN0XL));
1117 DPRINTK("VIDWIN0YL = 0x%04x\n", inw(DM270_OSD_VIDWIN0YL));
1118 DPRINTK("VIDWIN1XP = 0x%04x\n", inw(DM270_OSD_VIDWIN1XP));
1119 DPRINTK("VIDWIN1YP = 0x%04x\n", inw(DM270_OSD_VIDWIN1YP));
1120 DPRINTK("VIDWIN1XL = 0x%04x\n", inw(DM270_OSD_VIDWIN1XL));
1121 DPRINTK("VIDWIN1YL = 0x%04x\n", inw(DM270_OSD_VIDWIN1YL));
1122 DPRINTK("BMPWIN0XP = 0x%04x\n", inw(DM270_OSD_BMPWIN0XP));
1123 DPRINTK("BMPWIN0YP = 0x%04x\n", inw(DM270_OSD_BMPWIN0YP));
1124 DPRINTK("BMPWIN0XL = 0x%04x\n", inw(DM270_OSD_BMPWIN0XL));
1125 DPRINTK("BMPWIN0YL = 0x%04x\n", inw(DM270_OSD_BMPWIN0YL));
1126 DPRINTK("BMPWIN1XP = 0x%04x\n", inw(DM270_OSD_BMPWIN1XP));
1127 DPRINTK("BMPWIN1YP = 0x%04x\n", inw(DM270_OSD_BMPWIN1YP));
1128 DPRINTK("BMPWIN1XL = 0x%04x\n", inw(DM270_OSD_BMPWIN1XL));
1129 DPRINTK("BMPWIN1YL = 0x%04x\n", inw(DM270_OSD_BMPWIN1YL));
1130 DPRINTK("CURXP = 0x%04x\n", inw(DM270_OSD_CURXP));
1131 DPRINTK("CURYP = 0x%04x\n", inw(DM270_OSD_CURYP));
1132 DPRINTK("CURXL = 0x%04x\n", inw(DM270_OSD_CURXL));
1133 DPRINTK("CURYL = 0x%04x\n", inw(DM270_OSD_CURYL));
1134 DPRINTK("W0BMP01 = 0x%04x\n", inw(DM270_OSD_W0BMP01));
1135 DPRINTK("W0BMP23 = 0x%04x\n", inw(DM270_OSD_W0BMP23));
1136 DPRINTK("W0BMP45 = 0x%04x\n", inw(DM270_OSD_W0BMP45));
1137 DPRINTK("W0BMP67 = 0x%04x\n", inw(DM270_OSD_W0BMP67));
1138 DPRINTK("W0BMP89 = 0x%04x\n", inw(DM270_OSD_W0BMP89));
1139 DPRINTK("W0BMPAB = 0x%04x\n", inw(DM270_OSD_W0BMPAB));
1140 DPRINTK("W0BMPCD = 0x%04x\n", inw(DM270_OSD_W0BMPCD));
1141 DPRINTK("W0BMPEF = 0x%04x\n", inw(DM270_OSD_W0BMPEF));
1142 DPRINTK("W1BMP01 = 0x%04x\n", inw(DM270_OSD_W1BMP01));
1143 DPRINTK("W1BMP23 = 0x%04x\n", inw(DM270_OSD_W1BMP23));
1144 DPRINTK("W1BMP45 = 0x%04x\n", inw(DM270_OSD_W1BMP45));
1145 DPRINTK("W1BMP67 = 0x%04x\n", inw(DM270_OSD_W1BMP67));
1146 DPRINTK("W1BMP89 = 0x%04x\n", inw(DM270_OSD_W1BMP89));
1147 DPRINTK("W1BMPAB = 0x%04x\n", inw(DM270_OSD_W1BMPAB));
1148 DPRINTK("W1BMPCD = 0x%04x\n", inw(DM270_OSD_W1BMPCD));
1149 DPRINTK("W1BMPEF = 0x%04x\n", inw(DM270_OSD_W1BMPEF));
1150 DPRINTK("MISCCTL = 0x%04x\n", inw(DM270_OSD_MISCCTL));
1151 DPRINTK("CLUTRAMYCB = 0x%04x\n", inw(DM270_OSD_CLUTRAMYCB));
1152 DPRINTK("CLUTRAMCR = 0x%04x\n", inw(DM270_OSD_CLUTRAMCR));
1153 DPRINTK("PPVWIN0ADH = 0x%04x\n", inw(DM270_OSD_PPVWIN0ADH));
1154 DPRINTK("PPVWIN0ADL = 0x%04x\n", inw(DM270_OSD_PPVWIN0ADL));
1156 DPRINTK("Video Encoder\n" );
1157 DPRINTK("=============\n" );
1158 DPRINTK("VID01 = 0x%04x\n", inw(DM270_VENC_VID01));
1159 DPRINTK("VID02 = 0x%04x\n", inw(DM270_VENC_VID02));
1160 DPRINTK("DLCD1 = 0x%04x\n", inw(DM270_VENC_DLCD1));
1161 DPRINTK("DLCD2 = 0x%04x\n", inw(DM270_VENC_DLCD2));
1162 DPRINTK("DCLKPTN0E = 0x%04x\n", inw(DM270_VENC_DCLKPTN0E));
1163 DPRINTK("DCLKPTN1E = 0x%04x\n", inw(DM270_VENC_DCLKPTN1E));
1164 DPRINTK("DCLKPTN2E = 0x%04x\n", inw(DM270_VENC_DCLKPTN2E));
1165 DPRINTK("DCLKPTN3E = 0x%04x\n", inw(DM270_VENC_DCLKPTN3E));
1166 DPRINTK("DCLKPTN0O = 0x%04x\n", inw(DM270_VENC_DCLKPTN0O));
1167 DPRINTK("DCLKPTN1O = 0x%04x\n", inw(DM270_VENC_DCLKPTN1O));
1168 DPRINTK("DCLKPTN2O = 0x%04x\n", inw(DM270_VENC_DCLKPTN2O));
1169 DPRINTK("DCLKPTN3O = 0x%04x\n", inw(DM270_VENC_DCLKPTN3O));
1170 DPRINTK("DCLKSTPHE = 0x%04x\n", inw(DM270_VENC_DCLKSTPHE));
1171 DPRINTK("DCLKSTPHO = 0x%04x\n", inw(DM270_VENC_DCLKSTPHO));
1172 DPRINTK("DCLKVLDH = 0x%04x\n", inw(DM270_VENC_DCLKVLDH));
1173 DPRINTK("DCLKSTPV = 0x%04x\n", inw(DM270_VENC_DCLKSTPV));
1174 DPRINTK("DCLKVLDV = 0x%04x\n", inw(DM270_VENC_DCLKVLDV));
1175 DPRINTK("HVPWIDTH = 0x%04x\n", inw(DM270_VENC_HVPWIDTH));
1176 DPRINTK("HINTERVL = 0x%04x\n", inw(DM270_VENC_HINTERVL));
1177 DPRINTK("HSTART = 0x%04x\n", inw(DM270_VENC_HSTART));
1178 DPRINTK("HVALID = 0x%04x\n", inw(DM270_VENC_HVALID));
1179 DPRINTK("VINTERVL = 0x%04x\n", inw(DM270_VENC_VINTERVL));
1180 DPRINTK("VSTART = 0x%04x\n", inw(DM270_VENC_VSTART));
1181 DPRINTK("VVALID = 0x%04x\n", inw(DM270_VENC_VVALID));
1182 DPRINTK("HDELAY = 0x%04x\n", inw(DM270_VENC_HDELAY));
1183 DPRINTK("VDELAY = 0x%04x\n", inw(DM270_VENC_VDELAY));
1184 DPRINTK("CULLLINE = 0x%04x\n", inw(DM270_VENC_CULLLINE));
1185 DPRINTK("PWMCTRL = 0x%04x\n", inw(DM270_VENC_PWMCTRL));
1186 DPRINTK("PWMHPRD = 0x%04x\n", inw(DM270_VENC_PWMHPRD));
1187 DPRINTK("RGBLEVEL = 0x%04x\n", inw(DM270_VENC_RGBLEVEL));
1188 DPRINTK("ATR0 = 0x%04x\n", inw(DM270_VENC_ATR0));
1189 DPRINTK("ATR1 = 0x%04x\n", inw(DM270_VENC_ATR1));
1190 DPRINTK("ATR2 = 0x%04x\n", inw(DM270_VENC_ATR2));
1191 DPRINTK("REC656 = 0x%04x\n", inw(DM270_VENC_REC656));
1192 DPRINTK("EPSON_LCD = 0x%04x\n", inw(DM270_VENC_EPSON_LCD));
1193 DPRINTK("GCPDATA = 0x%04x\n", inw(DM270_VENC_GCPDATA));
1194 DPRINTK("CASIO = 0x%04x\n", inw(DM270_VENC_CASIO));
1195 DPRINTK("DOUTCTL = 0x%04x\n", inw(DM270_VENC_DOUTCTL));
1196 break;
1197 #endif
1199 default:
1200 WPRINTK("cmd=0x%08x\n", cmd);
1201 return -EINVAL;
1204 return retval;
1207 static struct fb_ops dm270fb_ops = {
1208 .owner = THIS_MODULE,
1209 .fb_check_var = dm270fb_check_var,
1210 .fb_set_par = dm270fb_set_par,
1211 .fb_setcolreg = dm270fb_setcolreg,
1212 .fb_blank = dm270fb_blank,
1213 .fb_pan_display = dm270fb_pan_display,
1214 .fb_fillrect = cfb_fillrect,
1215 .fb_copyarea = cfb_copyarea,
1216 .fb_imageblit = cfb_imageblit,
1217 .fb_cursor = soft_cursor,
1218 .fb_ioctl = dm270fb_ioctl,
1222 * ===========================================================================
1225 #if 0
1227 * These parameters give
1228 * 640x480, hsync 31.5kHz, vsync 60Hz
1230 static struct fb_videomode __devinitdata dm270fb_default_mode = {
1231 .refresh = 60,
1232 .xres = 640,
1233 .yres = 480,
1234 .pixclock = 39722,
1235 .left_margin = 56,
1236 .right_margin = 16,
1237 .upper_margin = 34,
1238 .lower_margin = 9,
1239 .hsync_len = 88,
1240 .vsync_len = 2,
1241 .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1242 .vmode = FB_VMODE_NONINTERLACED
1244 #endif
1247 * Parse dm270fb options.
1248 * Usage: video=dm270:<options>
1250 static int __init
1251 dm270fb_setup(char *options)
1253 char *this_opt;
1255 if (!options || !*options) {
1256 DPRINTK("options=%p\n", options);
1257 return 0;
1260 while ((this_opt = strsep(&options, ",")) != NULL) {
1261 if (!*this_opt)
1262 continue;
1264 if (!strncmp(this_opt, "noaccel", 7)) {
1265 dm270fb_bootcfg.noaccel = 1;
1266 } else if (!strncmp(this_opt, "nopan", 5)) {
1267 dm270fb_bootcfg.nopan = 1;
1268 } else if (!strncmp(this_opt, "nowrap", 6)) {
1269 dm270fb_bootcfg.nowrap = 1;
1270 } else if (!strncmp(this_opt, "nohwcursor", 10)) {
1271 dm270fb_bootcfg.nohwcursor = 1;
1272 } else if (!strncmp(this_opt, "noinit", 6)) {
1273 dm270fb_bootcfg.noinit = 1;
1274 } else if (!strncmp(this_opt, "romclut", 7)) {
1275 dm270fb_bootcfg.cmap_static = 1;
1276 } else if (!strncmp(this_opt, "vsync", 5)) {
1277 dm270fb_bootvar.sync &= ~FB_SYNC_COMP_HIGH_ACT;
1278 } else if (!strncmp(this_opt, "grayscale", 9)) {
1279 dm270fb_bootvar.grayscale = 1;
1280 } else if (!strncmp(this_opt, "doublescan", 10)) {
1281 dm270fb_bootvar.vmode |= FB_VMODE_DOUBLE;
1282 } else if (!strncmp(this_opt, "font:", 5)) {
1283 strncpy(dm270fb_bootcfg.fontname, this_opt+5,
1284 sizeof(dm270fb_bootcfg.fontname)-1);
1285 } else if (!strncmp(this_opt, "display:", 8)) {
1286 if (!strncmp(this_opt+8, "comp", 4))
1287 dm270fb_bootcfg.disp_type = DISP_TYPE_COMP;
1288 else if (!strncmp(this_opt+8, "lcd", 3))
1289 dm270fb_bootcfg.disp_type = DISP_TYPE_LCD;
1290 else if (!strncmp(this_opt+8, "tft", 3))
1291 dm270fb_bootcfg.disp_type = DISP_TYPE_TFT;
1292 else if (!strncmp(this_opt+8, "crt", 3))
1293 dm270fb_bootcfg.disp_type = DISP_TYPE_CRT;
1294 else if (!strncmp(this_opt+8, "epson", 5))
1295 dm270fb_bootcfg.disp_type = DISP_TYPE_EPSON;
1296 else if (!strncmp(this_opt+8, "casio", 5))
1297 dm270fb_bootcfg.disp_type = DISP_TYPE_CASIO;
1298 } else if (!strncmp(this_opt, "vidfmt:", 7)) {
1299 if (!strncmp(this_opt+7, "ntsc", 4))
1300 dm270fb_bootcfg.vidout_std = VID_FMT_NTSC;
1301 else if (!strncmp(this_opt+7, "pal", 3))
1302 dm270fb_bootcfg.vidout_std = VID_FMT_PAL;
1303 } else if (!strncmp(this_opt, "vidscan:", 8)) {
1304 if (!strncmp(this_opt+7, "interlace", 9))
1305 dm270fb_bootvar.vmode |= FB_VMODE_INTERLACED;
1306 else if (!strncmp(this_opt+7, "noninterlace", 12))
1307 dm270fb_bootvar.vmode &= ~FB_VMODE_INTERLACED;
1308 } else if (!strncmp(this_opt, "width:", 6)) {
1309 dm270fb_bootvar.xres = simple_strtoul(this_opt+6, NULL, 0);
1310 } else if (!strncmp(this_opt, "height:", 7)) {
1311 dm270fb_bootvar.yres = simple_strtoul(this_opt+7, NULL, 0);
1312 } else if (!strncmp(this_opt, "bpp:", 4)) {
1313 dm270fb_bootvar.bits_per_pixel = simple_strtoul(this_opt+4, NULL, 0);
1314 } else if (!strncmp(this_opt, "hswidth:", 8)) {
1315 dm270fb_bootvar.hsync_len = simple_strtoul(this_opt+8,
1316 NULL, 0);
1317 } else if (!strncmp(this_opt, "vswidth:", 8)) {
1318 dm270fb_bootvar.vsync_len = simple_strtoul(this_opt+8,
1319 NULL, 0);
1320 } else {
1321 dm270fb_bootcfg.mode_option = this_opt;
1325 return 0;
1328 static int __init
1329 dm270fb_init_fbinfo(struct fb_info *fbinfo, char *name)
1331 struct dm270fb_par *dm270fbpar;
1332 int maxlen;
1333 int retval = 0;
1335 if (!fbinfo) {
1336 WPRINTK("NULL\n");
1337 return -EINVAL;
1340 dm270fbpar = kmalloc(sizeof(struct dm270fb_par), GFP_KERNEL);
1341 if (!dm270fbpar) {
1342 WPRINTK("par alloc failed\n");
1343 return -ENOMEM;
1346 memset(dm270fbpar, 0, sizeof(struct dm270fb_par));
1347 memset(fbinfo, 0, sizeof(struct fb_info));
1349 /* copy boot options */
1350 dm270fbpar->cfg = dm270fb_bootcfg; /* struct copy */
1351 fbinfo->var = dm270fb_bootvar; /* struct copy */
1353 maxlen = sizeof(fbinfo->fix.id) - 1;
1354 strncpy(fbinfo->fix.id, name, maxlen); /* max length 15 */
1355 fbinfo->fix.id[maxlen] = 0;
1356 fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
1357 fbinfo->fix.type_aux = 0;
1358 fbinfo->fix.visual = (dm270fbpar->cfg.cmap_static) ?
1359 FB_VISUAL_STATIC_PSEUDOCOLOR : FB_VISUAL_PSEUDOCOLOR;
1360 fbinfo->fix.xpanstep = (dm270fbpar->cfg.nopan) ? 0 : 1;
1361 fbinfo->fix.ypanstep = (dm270fbpar->cfg.nopan) ? 0 : 1;
1362 fbinfo->fix.ywrapstep = (dm270fbpar->cfg.nowrap) ? 0 : 1;
1363 fbinfo->fix.line_length = dm270fb_calc_linelength(fbinfo);
1364 if (dm270fbpar->cfg.noaccel) {
1365 fbinfo->fix.accel = FB_ACCEL_NONE;
1366 } else {
1367 fbinfo->fix.accel = FB_ACCEL_DM270;
1370 /* initialize frame-buffer */
1371 fbinfo->fix.smem_len = (DM270FB_XRES_MAX * DM270FB_YRES_MAX *
1372 DM270FB_BPP_MAX) >> 3; /* frame-buffer size */
1374 if (!dm270fbpar->cfg.noinit) {
1375 if ((retval = dm270fb_map_graphics_memory(fbinfo))) {
1376 WPRINTK("frame buffer alloc failed\n");
1377 retval = -ENOMEM;
1378 goto ret_free_par;
1382 /* initialize register pointers */
1383 dm270fbpar->regaddr.bmpwinmd = DM270_OSD_BMPWIN0MD;
1384 dm270fbpar->regaddr.bmpwinofst = DM270_OSD_BMPWIN0OFST;
1385 dm270fbpar->regaddr.bmpwinadl = DM270_OSD_BMPWIN0ADL;
1386 dm270fbpar->regaddr.bmpwinxp = DM270_OSD_BMPWIN0XP;
1387 dm270fbpar->regaddr.bmpwinyp = DM270_OSD_BMPWIN0YP;
1388 dm270fbpar->regaddr.bmpwinxl = DM270_OSD_BMPWIN0XL;
1389 dm270fbpar->regaddr.bmpwinyl = DM270_OSD_BMPWIN0YL;
1390 dm270fbpar->regaddr.wbmp = DM270_OSD_W0BMP01;
1392 /* enable clock to VENC & OSD */
1393 fbinfo->par = dm270fbpar;
1394 dm270fb_init_hw(fbinfo);
1396 if (!dm270fbpar->cfg.noinit) {
1397 /* disable video encoder while initializing */
1398 dm270fb_display_disable(fbinfo);
1401 #if 0
1402 if (!dm270fbpar->cfg.nohwcursor)
1403 dm270fb_hwcursor_init(fbinfo);
1404 #endif
1406 fbinfo->node = -1;
1407 if (dm270fbpar->cfg.noaccel) {
1408 fbinfo->flags = FBINFO_DEFAULT;
1409 } else {
1410 fbinfo->flags = (FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN);
1412 fbinfo->fbops = &dm270fb_ops;
1413 fbinfo->currcon = -1;
1416 * If mode_option wasn't given at boot, assume all the boot
1417 * option timing parameters were specified individually, in
1418 * which case we do not need to call fb_find_mode as it has
1419 * already been copied from the boot options above.
1421 #if 0
1422 if (dm270fbpar->cfg.mode_option) {
1423 struct fb_videomode* modedb, *defmode;
1424 int dbsize = dm270fb_get_mode(fbinfo, DM270FB_DEFAULT_XRES, DM270FB_DEFAULT_YRES, &modedb, &defmode);
1426 /* first try the generic modedb */
1427 if (!fb_find_mode(&fbinfo->var, fbinfo, dm270fbpar->cfg.mode_option,
1428 NULL, 0, NULL, fbinfo->var.bits_per_pixel)) {
1429 WPRINTK("mode %s failed, trying dm270 modedb\n",
1430 dm270fbpar->cfg.mode_option);
1431 /* didn't work in generic modedb, try ours */
1432 if (!fb_find_mode(&fbinfo->var, fbinfo,
1433 dm270fbpar->cfg.mode_option, modedb, dbsize,
1434 defmode, fbinfo->var.bits_per_pixel)) {
1435 WPRINTK("mode %s failed dm270 modedb too, sorry\n",
1436 dm270fbpar->cfg.mode_option);
1437 retval = -ENXIO;
1438 goto ret_unmap_fbuf;
1442 fbinfo->var.xres_virtual = dm270fb_bootvar.xres_virtual ?
1443 dm270fb_bootvar.xres_virtual : fbinfo->var.xres;
1444 fbinfo->var.yres_virtual = dm270fb_bootvar.yres_virtual ?
1445 dm270fb_bootvar.yres_virtual : fbinfo->var.yres;
1447 #endif
1449 if ((retval = fb_alloc_cmap(&fbinfo->cmap, DM270FB_NR_PALETTE, 0))) {
1450 WPRINTK("error %d allocating cmap\n", retval);
1451 goto ret_unmap_fbuf;
1454 if (fbinfo->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
1455 fb_copy_cmap(&dm270fb_romclut_cmap, &fbinfo->cmap);
1458 return 0;
1460 ret_unmap_fbuf:
1461 if (!dm270fbpar->cfg.noinit) {
1462 dm270fb_unmap_graphics_memory(fbinfo);
1464 fbinfo->par = NULL;
1466 ret_free_par:
1467 kfree(dm270fbpar);
1468 return retval;
1471 static int __init
1472 dm270fb_init(void)
1474 struct dm270fb_par *dm270fbpar;
1475 int retval = -1;
1477 #ifndef MODULE
1478 if (fb_get_options("dm270fb", &dm270fb_options))
1479 return -ENODEV;
1480 #endif
1481 dm270fb_setup(dm270fb_options);
1483 if ((retval = dm270fb_init_fbinfo(&dm270fbinfo[0], DM270FB_NAME))) {
1484 printk(KERN_ERR "dm270fb: error %d initializing framebuffer\n",
1485 retval);
1486 goto ret_failed;
1489 dm270fbpar = (struct dm270fb_par *)dm270fbinfo[0].par;
1490 if (!dm270fbpar->cfg.noinit) {
1491 if ((retval = dm270fb_set_par(&dm270fbinfo[0]))) {
1492 printk(KERN_ERR "dm270fb: error %d initializing hardware\n",
1493 retval);
1494 goto ret_free_resource;
1496 dm270fb_display_enable(&dm270fbinfo[0]);
1499 if ((retval = register_framebuffer(&dm270fbinfo[0])) < 0) {
1500 printk(KERN_ERR "dm270fb: error %d registering framebuffer\n",
1501 retval);
1502 goto ret_free_resource;
1505 printk("fb%d: %s frame buffer device\n",
1506 dm270fbinfo[0].node, dm270fbinfo[0].fix.id);
1507 return 0;
1509 ret_free_resource:
1510 if (!dm270fbpar->cfg.noinit) {
1511 dm270fb_unmap_graphics_memory(&dm270fbinfo[0]);
1513 if (dm270fbinfo[0].par) {
1514 kfree(dm270fbinfo[0].par);
1515 dm270fbinfo[0].par = NULL;
1518 ret_failed:
1519 return retval;
1522 static void __exit
1523 dm270fb_exit(void)
1525 struct dm270fb_par *dm270fbpar = (struct dm270fb_par *)dm270fbinfo[0].par;
1526 int retval;
1528 if ((retval = unregister_framebuffer(&dm270fbinfo[0]))) {
1529 WPRINTK("error %d unregistering framebuffer\n", retval);
1531 fb_dealloc_cmap(&dm270fbinfo[0].cmap);
1532 if (!dm270fbpar->cfg.noinit) {
1533 dm270fb_unmap_graphics_memory(&dm270fbinfo[0]);
1535 if (dm270fbinfo[0].par) {
1536 kfree(dm270fbinfo[0].par);
1537 dm270fbinfo[0].par = NULL;
1541 module_init(dm270fb_init);
1542 module_exit(dm270fb_exit);
1544 MODULE_AUTHOR("Chee Tim Loh <lohct@pacific.net.sg>");
1545 MODULE_DESCRIPTION("TI TMS320DM270 on-chip OSD framebuffer driver");
1546 MODULE_LICENSE("GPL");
1547 MODULE_PARM(dm270fb_options, "s");
1548 MODULE_PARM_DESC(dm270fb_options, "Options to pass to dm270fb");