aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/via
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-02-13 08:31:38 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-17 01:10:19 -0400
commitf7018c21350204c4cf628462f229d44d03545254 (patch)
tree408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/fbdev/via
parentc26ef3eb3c11274bad1b64498d0a134f85755250 (diff)
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related files, directories for backlight, console, linux logo, lots of fbdev device drivers, fbdev framework files. Make some order into the chaos by creating drivers/video/fbdev directory, and move all fbdev related files there. No functionality is changed, although I guess it is possible that some subtle Makefile build order related issue could be created by this patch. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Rob Clark <robdclark@gmail.com> Acked-by: Jingoo Han <jg1.han@samsung.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/fbdev/via')
-rw-r--r--drivers/video/fbdev/via/Makefile12
-rw-r--r--drivers/video/fbdev/via/accel.c547
-rw-r--r--drivers/video/fbdev/via/accel.h211
-rw-r--r--drivers/video/fbdev/via/chip.h176
-rw-r--r--drivers/video/fbdev/via/debug.h41
-rw-r--r--drivers/video/fbdev/via/dvi.c478
-rw-r--r--drivers/video/fbdev/via/dvi.h65
-rw-r--r--drivers/video/fbdev/via/global.c50
-rw-r--r--drivers/video/fbdev/via/global.h80
-rw-r--r--drivers/video/fbdev/via/hw.c2134
-rw-r--r--drivers/video/fbdev/via/hw.h676
-rw-r--r--drivers/video/fbdev/via/ioctl.c116
-rw-r--r--drivers/video/fbdev/via/ioctl.h203
-rw-r--r--drivers/video/fbdev/via/lcd.c1005
-rw-r--r--drivers/video/fbdev/via/lcd.h89
-rw-r--r--drivers/video/fbdev/via/share.h332
-rw-r--r--drivers/video/fbdev/via/tblDPASetting.c86
-rw-r--r--drivers/video/fbdev/via/tblDPASetting.h45
-rw-r--r--drivers/video/fbdev/via/via-core.c790
-rw-r--r--drivers/video/fbdev/via/via-gpio.c316
-rw-r--r--drivers/video/fbdev/via/via_aux.c88
-rw-r--r--drivers/video/fbdev/via/via_aux.h93
-rw-r--r--drivers/video/fbdev/via/via_aux_ch7301.c50
-rw-r--r--drivers/video/fbdev/via/via_aux_edid.c100
-rw-r--r--drivers/video/fbdev/via/via_aux_sii164.c54
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1621.c44
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1622.c50
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1625.c50
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1631.c46
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1632.c54
-rw-r--r--drivers/video/fbdev/via/via_aux_vt1636.c46
-rw-r--r--drivers/video/fbdev/via/via_clock.c368
-rw-r--r--drivers/video/fbdev/via/via_clock.h76
-rw-r--r--drivers/video/fbdev/via/via_i2c.c295
-rw-r--r--drivers/video/fbdev/via/via_modesetting.c230
-rw-r--r--drivers/video/fbdev/via/via_modesetting.h61
-rw-r--r--drivers/video/fbdev/via/via_utility.c242
-rw-r--r--drivers/video/fbdev/via/via_utility.h34
-rw-r--r--drivers/video/fbdev/via/viafbdev.c2176
-rw-r--r--drivers/video/fbdev/via/viafbdev.h110
-rw-r--r--drivers/video/fbdev/via/viamode.c383
-rw-r--r--drivers/video/fbdev/via/viamode.h63
-rw-r--r--drivers/video/fbdev/via/vt1636.c244
-rw-r--r--drivers/video/fbdev/via/vt1636.h44
44 files changed, 12453 insertions, 0 deletions
diff --git a/drivers/video/fbdev/via/Makefile b/drivers/video/fbdev/via/Makefile
new file mode 100644
index 000000000000..159f26e6adb5
--- /dev/null
+++ b/drivers/video/fbdev/via/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for the VIA framebuffer driver (for Linux Kernel 2.6)
3#
4
5obj-$(CONFIG_FB_VIA) += viafb.o
6
7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
9 via-core.o via-gpio.o via_modesetting.o via_clock.o \
10 via_aux.o via_aux_edid.o via_aux_vt1636.o via_aux_vt1632.o \
11 via_aux_vt1631.o via_aux_vt1625.o via_aux_vt1622.o via_aux_vt1621.o \
12 via_aux_sii164.o via_aux_ch7301.o
diff --git a/drivers/video/fbdev/via/accel.c b/drivers/video/fbdev/via/accel.c
new file mode 100644
index 000000000000..4b67b8e6030a
--- /dev/null
+++ b/drivers/video/fbdev/via/accel.c
@@ -0,0 +1,547 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/via-core.h>
22#include "global.h"
23
24/*
25 * Figure out an appropriate bytes-per-pixel setting.
26 */
27static int viafb_set_bpp(void __iomem *engine, u8 bpp)
28{
29 u32 gemode;
30
31 /* Preserve the reserved bits */
32 /* Lowest 2 bits to zero gives us no rotation */
33 gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
34 switch (bpp) {
35 case 8:
36 gemode |= VIA_GEM_8bpp;
37 break;
38 case 16:
39 gemode |= VIA_GEM_16bpp;
40 break;
41 case 32:
42 gemode |= VIA_GEM_32bpp;
43 break;
44 default:
45 printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
46 return -EINVAL;
47 }
48 writel(gemode, engine + VIA_REG_GEMODE);
49 return 0;
50}
51
52
53static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
54 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
55 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
56 u32 fg_color, u32 bg_color, u8 fill_rop)
57{
58 u32 ge_cmd = 0, tmp, i;
59 int ret;
60
61 if (!op || op > 3) {
62 printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op);
63 return -EINVAL;
64 }
65
66 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
67 if (src_x < dst_x) {
68 ge_cmd |= 0x00008000;
69 src_x += width - 1;
70 dst_x += width - 1;
71 }
72 if (src_y < dst_y) {
73 ge_cmd |= 0x00004000;
74 src_y += height - 1;
75 dst_y += height - 1;
76 }
77 }
78
79 if (op == VIA_BITBLT_FILL) {
80 switch (fill_rop) {
81 case 0x00: /* blackness */
82 case 0x5A: /* pattern inversion */
83 case 0xF0: /* pattern copy */
84 case 0xFF: /* whiteness */
85 break;
86 default:
87 printk(KERN_WARNING "hw_bitblt_1: Invalid fill rop: "
88 "%u\n", fill_rop);
89 return -EINVAL;
90 }
91 }
92
93 ret = viafb_set_bpp(engine, dst_bpp);
94 if (ret)
95 return ret;
96
97 if (op != VIA_BITBLT_FILL) {
98 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
99 || src_y & 0xFFFFF000) {
100 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
101 "x/y %d %d\n", src_x, src_y);
102 return -EINVAL;
103 }
104 tmp = src_x | (src_y << 16);
105 writel(tmp, engine + 0x08);
106 }
107
108 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
109 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination x/y "
110 "%d %d\n", dst_x, dst_y);
111 return -EINVAL;
112 }
113 tmp = dst_x | (dst_y << 16);
114 writel(tmp, engine + 0x0C);
115
116 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
117 printk(KERN_WARNING "hw_bitblt_1: Unsupported width/height "
118 "%d %d\n", width, height);
119 return -EINVAL;
120 }
121 tmp = (width - 1) | ((height - 1) << 16);
122 writel(tmp, engine + 0x10);
123
124 if (op != VIA_BITBLT_COLOR)
125 writel(fg_color, engine + 0x18);
126
127 if (op == VIA_BITBLT_MONO)
128 writel(bg_color, engine + 0x1C);
129
130 if (op != VIA_BITBLT_FILL) {
131 tmp = src_mem ? 0 : src_addr;
132 if (dst_addr & 0xE0000007) {
133 printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
134 "address %X\n", tmp);
135 return -EINVAL;
136 }
137 tmp >>= 3;
138 writel(tmp, engine + 0x30);
139 }
140
141 if (dst_addr & 0xE0000007) {
142 printk(KERN_WARNING "hw_bitblt_1: Unsupported destination "
143 "address %X\n", dst_addr);
144 return -EINVAL;
145 }
146 tmp = dst_addr >> 3;
147 writel(tmp, engine + 0x34);
148
149 if (op == VIA_BITBLT_FILL)
150 tmp = 0;
151 else
152 tmp = src_pitch;
153 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
154 printk(KERN_WARNING "hw_bitblt_1: Unsupported pitch %X %X\n",
155 tmp, dst_pitch);
156 return -EINVAL;
157 }
158 tmp = VIA_PITCH_ENABLE | (tmp >> 3) | (dst_pitch << (16 - 3));
159 writel(tmp, engine + 0x38);
160
161 if (op == VIA_BITBLT_FILL)
162 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
163 else {
164 ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
165 if (src_mem)
166 ge_cmd |= 0x00000040;
167 if (op == VIA_BITBLT_MONO)
168 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
169 else
170 ge_cmd |= 0x00000001;
171 }
172 writel(ge_cmd, engine);
173
174 if (op == VIA_BITBLT_FILL || !src_mem)
175 return 0;
176
177 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
178 3) >> 2;
179
180 for (i = 0; i < tmp; i++)
181 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
182
183 return 0;
184}
185
186static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
187 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
188 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
189 u32 fg_color, u32 bg_color, u8 fill_rop)
190{
191 u32 ge_cmd = 0, tmp, i;
192 int ret;
193
194 if (!op || op > 3) {
195 printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op);
196 return -EINVAL;
197 }
198
199 if (op != VIA_BITBLT_FILL && !src_mem && src_addr == dst_addr) {
200 if (src_x < dst_x) {
201 ge_cmd |= 0x00008000;
202 src_x += width - 1;
203 dst_x += width - 1;
204 }
205 if (src_y < dst_y) {
206 ge_cmd |= 0x00004000;
207 src_y += height - 1;
208 dst_y += height - 1;
209 }
210 }
211
212 if (op == VIA_BITBLT_FILL) {
213 switch (fill_rop) {
214 case 0x00: /* blackness */
215 case 0x5A: /* pattern inversion */
216 case 0xF0: /* pattern copy */
217 case 0xFF: /* whiteness */
218 break;
219 default:
220 printk(KERN_WARNING "hw_bitblt_2: Invalid fill rop: "
221 "%u\n", fill_rop);
222 return -EINVAL;
223 }
224 }
225
226 ret = viafb_set_bpp(engine, dst_bpp);
227 if (ret)
228 return ret;
229
230 if (op == VIA_BITBLT_FILL)
231 tmp = 0;
232 else
233 tmp = src_pitch;
234 if (tmp & 0xFFFFC007 || dst_pitch & 0xFFFFC007) {
235 printk(KERN_WARNING "hw_bitblt_2: Unsupported pitch %X %X\n",
236 tmp, dst_pitch);
237 return -EINVAL;
238 }
239 tmp = (tmp >> 3) | (dst_pitch << (16 - 3));
240 writel(tmp, engine + 0x08);
241
242 if ((width - 1) & 0xFFFFF000 || (height - 1) & 0xFFFFF000) {
243 printk(KERN_WARNING "hw_bitblt_2: Unsupported width/height "
244 "%d %d\n", width, height);
245 return -EINVAL;
246 }
247 tmp = (width - 1) | ((height - 1) << 16);
248 writel(tmp, engine + 0x0C);
249
250 if (dst_x & 0xFFFFF000 || dst_y & 0xFFFFF000) {
251 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination x/y "
252 "%d %d\n", dst_x, dst_y);
253 return -EINVAL;
254 }
255 tmp = dst_x | (dst_y << 16);
256 writel(tmp, engine + 0x10);
257
258 if (dst_addr & 0xE0000007) {
259 printk(KERN_WARNING "hw_bitblt_2: Unsupported destination "
260 "address %X\n", dst_addr);
261 return -EINVAL;
262 }
263 tmp = dst_addr >> 3;
264 writel(tmp, engine + 0x14);
265
266 if (op != VIA_BITBLT_FILL) {
267 if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000)
268 || src_y & 0xFFFFF000) {
269 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
270 "x/y %d %d\n", src_x, src_y);
271 return -EINVAL;
272 }
273 tmp = src_x | (src_y << 16);
274 writel(tmp, engine + 0x18);
275
276 tmp = src_mem ? 0 : src_addr;
277 if (dst_addr & 0xE0000007) {
278 printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
279 "address %X\n", tmp);
280 return -EINVAL;
281 }
282 tmp >>= 3;
283 writel(tmp, engine + 0x1C);
284 }
285
286 if (op == VIA_BITBLT_FILL) {
287 writel(fg_color, engine + 0x58);
288 } else if (op == VIA_BITBLT_MONO) {
289 writel(fg_color, engine + 0x4C);
290 writel(bg_color, engine + 0x50);
291 }
292
293 if (op == VIA_BITBLT_FILL)
294 ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
295 else {
296 ge_cmd |= 0xCC000000; /* ROP=SRCCOPY */
297 if (src_mem)
298 ge_cmd |= 0x00000040;
299 if (op == VIA_BITBLT_MONO)
300 ge_cmd |= 0x00000002 | 0x00000100 | 0x00020000;
301 else
302 ge_cmd |= 0x00000001;
303 }
304 writel(ge_cmd, engine);
305
306 if (op == VIA_BITBLT_FILL || !src_mem)
307 return 0;
308
309 tmp = (width * height * (op == VIA_BITBLT_MONO ? 1 : (dst_bpp >> 3)) +
310 3) >> 2;
311
312 for (i = 0; i < tmp; i++)
313 writel(src_mem[i], engine + VIA_MMIO_BLTBASE);
314
315 return 0;
316}
317
318int viafb_setup_engine(struct fb_info *info)
319{
320 struct viafb_par *viapar = info->par;
321 void __iomem *engine;
322 u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
323
324 engine = viapar->shared->vdev->engine_mmio;
325 if (!engine) {
326 printk(KERN_WARNING "viafb_init_accel: ioremap failed, "
327 "hardware acceleration disabled\n");
328 return -ENOMEM;
329 }
330
331 switch (chip_name) {
332 case UNICHROME_CLE266:
333 case UNICHROME_K400:
334 case UNICHROME_K800:
335 case UNICHROME_PM800:
336 case UNICHROME_CN700:
337 case UNICHROME_CX700:
338 case UNICHROME_CN750:
339 case UNICHROME_K8M890:
340 case UNICHROME_P4M890:
341 case UNICHROME_P4M900:
342 viapar->shared->hw_bitblt = hw_bitblt_1;
343 break;
344 case UNICHROME_VX800:
345 case UNICHROME_VX855:
346 case UNICHROME_VX900:
347 viapar->shared->hw_bitblt = hw_bitblt_2;
348 break;
349 default:
350 viapar->shared->hw_bitblt = NULL;
351 }
352
353 viapar->fbmem_free -= CURSOR_SIZE;
354 viapar->shared->cursor_vram_addr = viapar->fbmem_free;
355 viapar->fbmem_used += CURSOR_SIZE;
356
357 viapar->fbmem_free -= VQ_SIZE;
358 viapar->shared->vq_vram_addr = viapar->fbmem_free;
359 viapar->fbmem_used += VQ_SIZE;
360
361#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
362 /*
363 * Set aside a chunk of framebuffer memory for the camera
364 * driver. Someday this driver probably needs a proper allocator
365 * for fbmem; for now, we just have to do this before the
366 * framebuffer initializes itself.
367 *
368 * As for the size: the engine can handle three frames,
369 * 16 bits deep, up to VGA resolution.
370 */
371 viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2;
372 viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size;
373 viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size;
374 viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
375#endif
376
377 viafb_reset_engine(viapar);
378 return 0;
379}
380
381void viafb_reset_engine(struct viafb_par *viapar)
382{
383 void __iomem *engine = viapar->shared->vdev->engine_mmio;
384 int highest_reg, i;
385 u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
386 vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
387
388 /* Initialize registers to reset the 2D engine */
389 switch (viapar->shared->chip_info.twod_engine) {
390 case VIA_2D_ENG_M1:
391 highest_reg = 0x5c;
392 break;
393 default:
394 highest_reg = 0x40;
395 break;
396 }
397 for (i = 0; i <= highest_reg; i += 4)
398 writel(0x0, engine + i);
399
400 /* Init AGP and VQ regs */
401 switch (chip_name) {
402 case UNICHROME_K8M890:
403 case UNICHROME_P4M900:
404 case UNICHROME_VX800:
405 case UNICHROME_VX855:
406 case UNICHROME_VX900:
407 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
408 writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
409 writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
410 break;
411
412 default:
413 writel(0x00100000, engine + VIA_REG_TRANSET);
414 writel(0x00000000, engine + VIA_REG_TRANSPACE);
415 writel(0x00333004, engine + VIA_REG_TRANSPACE);
416 writel(0x60000000, engine + VIA_REG_TRANSPACE);
417 writel(0x61000000, engine + VIA_REG_TRANSPACE);
418 writel(0x62000000, engine + VIA_REG_TRANSPACE);
419 writel(0x63000000, engine + VIA_REG_TRANSPACE);
420 writel(0x64000000, engine + VIA_REG_TRANSPACE);
421 writel(0x7D000000, engine + VIA_REG_TRANSPACE);
422
423 writel(0xFE020000, engine + VIA_REG_TRANSET);
424 writel(0x00000000, engine + VIA_REG_TRANSPACE);
425 break;
426 }
427
428 /* Enable VQ */
429 vq_start_addr = viapar->shared->vq_vram_addr;
430 vq_end_addr = viapar->shared->vq_vram_addr + VQ_SIZE - 1;
431
432 vq_start_low = 0x50000000 | (vq_start_addr & 0xFFFFFF);
433 vq_end_low = 0x51000000 | (vq_end_addr & 0xFFFFFF);
434 vq_high = 0x52000000 | ((vq_start_addr & 0xFF000000) >> 24) |
435 ((vq_end_addr & 0xFF000000) >> 16);
436 vq_len = 0x53000000 | (VQ_SIZE >> 3);
437
438 switch (chip_name) {
439 case UNICHROME_K8M890:
440 case UNICHROME_P4M900:
441 case UNICHROME_VX800:
442 case UNICHROME_VX855:
443 case UNICHROME_VX900:
444 vq_start_low |= 0x20000000;
445 vq_end_low |= 0x20000000;
446 vq_high |= 0x20000000;
447 vq_len |= 0x20000000;
448
449 writel(0x00100000, engine + VIA_REG_CR_TRANSET);
450 writel(vq_high, engine + VIA_REG_CR_TRANSPACE);
451 writel(vq_start_low, engine + VIA_REG_CR_TRANSPACE);
452 writel(vq_end_low, engine + VIA_REG_CR_TRANSPACE);
453 writel(vq_len, engine + VIA_REG_CR_TRANSPACE);
454 writel(0x74301001, engine + VIA_REG_CR_TRANSPACE);
455 writel(0x00000000, engine + VIA_REG_CR_TRANSPACE);
456 break;
457 default:
458 writel(0x00FE0000, engine + VIA_REG_TRANSET);
459 writel(0x080003FE, engine + VIA_REG_TRANSPACE);
460 writel(0x0A00027C, engine + VIA_REG_TRANSPACE);
461 writel(0x0B000260, engine + VIA_REG_TRANSPACE);
462 writel(0x0C000274, engine + VIA_REG_TRANSPACE);
463 writel(0x0D000264, engine + VIA_REG_TRANSPACE);
464 writel(0x0E000000, engine + VIA_REG_TRANSPACE);
465 writel(0x0F000020, engine + VIA_REG_TRANSPACE);
466 writel(0x1000027E, engine + VIA_REG_TRANSPACE);
467 writel(0x110002FE, engine + VIA_REG_TRANSPACE);
468 writel(0x200F0060, engine + VIA_REG_TRANSPACE);
469
470 writel(0x00000006, engine + VIA_REG_TRANSPACE);
471 writel(0x40008C0F, engine + VIA_REG_TRANSPACE);
472 writel(0x44000000, engine + VIA_REG_TRANSPACE);
473 writel(0x45080C04, engine + VIA_REG_TRANSPACE);
474 writel(0x46800408, engine + VIA_REG_TRANSPACE);
475
476 writel(vq_high, engine + VIA_REG_TRANSPACE);
477 writel(vq_start_low, engine + VIA_REG_TRANSPACE);
478 writel(vq_end_low, engine + VIA_REG_TRANSPACE);
479 writel(vq_len, engine + VIA_REG_TRANSPACE);
480 break;
481 }
482
483 /* Set Cursor Image Base Address */
484 writel(viapar->shared->cursor_vram_addr, engine + VIA_REG_CURSOR_MODE);
485 writel(0x0, engine + VIA_REG_CURSOR_POS);
486 writel(0x0, engine + VIA_REG_CURSOR_ORG);
487 writel(0x0, engine + VIA_REG_CURSOR_BG);
488 writel(0x0, engine + VIA_REG_CURSOR_FG);
489 return;
490}
491
492void viafb_show_hw_cursor(struct fb_info *info, int Status)
493{
494 struct viafb_par *viapar = info->par;
495 u32 temp, iga_path = viapar->iga_path;
496
497 temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
498 switch (Status) {
499 case HW_Cursor_ON:
500 temp |= 0x1;
501 break;
502 case HW_Cursor_OFF:
503 temp &= 0xFFFFFFFE;
504 break;
505 }
506 switch (iga_path) {
507 case IGA2:
508 temp |= 0x80000000;
509 break;
510 case IGA1:
511 default:
512 temp &= 0x7FFFFFFF;
513 }
514 writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE);
515}
516
517void viafb_wait_engine_idle(struct fb_info *info)
518{
519 struct viafb_par *viapar = info->par;
520 int loop = 0;
521 u32 mask;
522 void __iomem *engine = viapar->shared->vdev->engine_mmio;
523
524 switch (viapar->shared->chip_info.twod_engine) {
525 case VIA_2D_ENG_H5:
526 case VIA_2D_ENG_M1:
527 mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 |
528 VIA_3D_ENG_BUSY_M1;
529 break;
530 default:
531 while (!(readl(engine + VIA_REG_STATUS) &
532 VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) {
533 loop++;
534 cpu_relax();
535 }
536 mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY;
537 break;
538 }
539
540 while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) {
541 loop++;
542 cpu_relax();
543 }
544
545 if (loop >= MAXLOOP)
546 printk(KERN_ERR "viafb_wait_engine_idle: not syncing\n");
547}
diff --git a/drivers/video/fbdev/via/accel.h b/drivers/video/fbdev/via/accel.h
new file mode 100644
index 000000000000..79d5e10cc835
--- /dev/null
+++ b/drivers/video/fbdev/via/accel.h
@@ -0,0 +1,211 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __ACCEL_H__
23#define __ACCEL_H__
24
25#define FB_ACCEL_VIA_UNICHROME 50
26
27/* MMIO Base Address Definition */
28#define MMIO_VGABASE 0x8000
29#define MMIO_CR_READ (MMIO_VGABASE + 0x3D4)
30#define MMIO_CR_WRITE (MMIO_VGABASE + 0x3D5)
31#define MMIO_SR_READ (MMIO_VGABASE + 0x3C4)
32#define MMIO_SR_WRITE (MMIO_VGABASE + 0x3C5)
33
34/* HW Cursor Status Define */
35#define HW_Cursor_ON 0
36#define HW_Cursor_OFF 1
37
38#define CURSOR_SIZE (8 * 1024)
39#define VQ_SIZE (256 * 1024)
40
41#define VIA_MMIO_BLTBASE 0x200000
42#define VIA_MMIO_BLTSIZE 0x200000
43
44/* Defines for 2D registers */
45#define VIA_REG_GECMD 0x000
46#define VIA_REG_GEMODE 0x004
47#define VIA_REG_SRCPOS 0x008
48#define VIA_REG_DSTPOS 0x00C
49/* width and height */
50#define VIA_REG_DIMENSION 0x010
51#define VIA_REG_PATADDR 0x014
52#define VIA_REG_FGCOLOR 0x018
53#define VIA_REG_BGCOLOR 0x01C
54/* top and left of clipping */
55#define VIA_REG_CLIPTL 0x020
56/* bottom and right of clipping */
57#define VIA_REG_CLIPBR 0x024
58#define VIA_REG_OFFSET 0x028
59/* color key control */
60#define VIA_REG_KEYCONTROL 0x02C
61#define VIA_REG_SRCBASE 0x030
62#define VIA_REG_DSTBASE 0x034
63/* pitch of src and dst */
64#define VIA_REG_PITCH 0x038
65#define VIA_REG_MONOPAT0 0x03C
66#define VIA_REG_MONOPAT1 0x040
67/* from 0x100 to 0x1ff */
68#define VIA_REG_COLORPAT 0x100
69
70/* defines for VIA 2D registers for vt3353/3409 (M1 engine)*/
71#define VIA_REG_GECMD_M1 0x000
72#define VIA_REG_GEMODE_M1 0x004
73#define VIA_REG_GESTATUS_M1 0x004 /* as same as VIA_REG_GEMODE */
74#define VIA_REG_PITCH_M1 0x008 /* pitch of src and dst */
75#define VIA_REG_DIMENSION_M1 0x00C /* width and height */
76#define VIA_REG_DSTPOS_M1 0x010
77#define VIA_REG_LINE_XY_M1 0x010
78#define VIA_REG_DSTBASE_M1 0x014
79#define VIA_REG_SRCPOS_M1 0x018
80#define VIA_REG_LINE_K1K2_M1 0x018
81#define VIA_REG_SRCBASE_M1 0x01C
82#define VIA_REG_PATADDR_M1 0x020
83#define VIA_REG_MONOPAT0_M1 0x024
84#define VIA_REG_MONOPAT1_M1 0x028
85#define VIA_REG_OFFSET_M1 0x02C
86#define VIA_REG_LINE_ERROR_M1 0x02C
87#define VIA_REG_CLIPTL_M1 0x040 /* top and left of clipping */
88#define VIA_REG_CLIPBR_M1 0x044 /* bottom and right of clipping */
89#define VIA_REG_KEYCONTROL_M1 0x048 /* color key control */
90#define VIA_REG_FGCOLOR_M1 0x04C
91#define VIA_REG_DSTCOLORKEY_M1 0x04C /* as same as VIA_REG_FG */
92#define VIA_REG_BGCOLOR_M1 0x050
93#define VIA_REG_SRCCOLORKEY_M1 0x050 /* as same as VIA_REG_BG */
94#define VIA_REG_MONOPATFGC_M1 0x058 /* Add BG color of Pattern. */
95#define VIA_REG_MONOPATBGC_M1 0x05C /* Add FG color of Pattern. */
96#define VIA_REG_COLORPAT_M1 0x100 /* from 0x100 to 0x1ff */
97
98/* VIA_REG_PITCH(0x38): Pitch Setting */
99#define VIA_PITCH_ENABLE 0x80000000
100
101/* defines for VIA HW cursor registers */
102#define VIA_REG_CURSOR_MODE 0x2D0
103#define VIA_REG_CURSOR_POS 0x2D4
104#define VIA_REG_CURSOR_ORG 0x2D8
105#define VIA_REG_CURSOR_BG 0x2DC
106#define VIA_REG_CURSOR_FG 0x2E0
107
108/* VIA_REG_GEMODE(0x04): GE mode */
109#define VIA_GEM_8bpp 0x00000000
110#define VIA_GEM_16bpp 0x00000100
111#define VIA_GEM_32bpp 0x00000300
112
113/* VIA_REG_GECMD(0x00): 2D Engine Command */
114#define VIA_GEC_NOOP 0x00000000
115#define VIA_GEC_BLT 0x00000001
116#define VIA_GEC_LINE 0x00000005
117
118/* Rotate Command */
119#define VIA_GEC_ROT 0x00000008
120
121#define VIA_GEC_SRC_XY 0x00000000
122#define VIA_GEC_SRC_LINEAR 0x00000010
123#define VIA_GEC_DST_XY 0x00000000
124#define VIA_GEC_DST_LINRAT 0x00000020
125
126#define VIA_GEC_SRC_FB 0x00000000
127#define VIA_GEC_SRC_SYS 0x00000040
128#define VIA_GEC_DST_FB 0x00000000
129#define VIA_GEC_DST_SYS 0x00000080
130
131/* source is mono */
132#define VIA_GEC_SRC_MONO 0x00000100
133/* pattern is mono */
134#define VIA_GEC_PAT_MONO 0x00000200
135/* mono src is opaque */
136#define VIA_GEC_MSRC_OPAQUE 0x00000000
137/* mono src is transparent */
138#define VIA_GEC_MSRC_TRANS 0x00000400
139/* pattern is in frame buffer */
140#define VIA_GEC_PAT_FB 0x00000000
141/* pattern is from reg setting */
142#define VIA_GEC_PAT_REG 0x00000800
143
144#define VIA_GEC_CLIP_DISABLE 0x00000000
145#define VIA_GEC_CLIP_ENABLE 0x00001000
146
147#define VIA_GEC_FIXCOLOR_PAT 0x00002000
148
149#define VIA_GEC_INCX 0x00000000
150#define VIA_GEC_DECY 0x00004000
151#define VIA_GEC_INCY 0x00000000
152#define VIA_GEC_DECX 0x00008000
153/* mono pattern is opaque */
154#define VIA_GEC_MPAT_OPAQUE 0x00000000
155/* mono pattern is transparent */
156#define VIA_GEC_MPAT_TRANS 0x00010000
157
158#define VIA_GEC_MONO_UNPACK 0x00000000
159#define VIA_GEC_MONO_PACK 0x00020000
160#define VIA_GEC_MONO_DWORD 0x00000000
161#define VIA_GEC_MONO_WORD 0x00040000
162#define VIA_GEC_MONO_BYTE 0x00080000
163
164#define VIA_GEC_LASTPIXEL_ON 0x00000000
165#define VIA_GEC_LASTPIXEL_OFF 0x00100000
166#define VIA_GEC_X_MAJOR 0x00000000
167#define VIA_GEC_Y_MAJOR 0x00200000
168#define VIA_GEC_QUICK_START 0x00800000
169
170/* defines for VIA 3D registers */
171#define VIA_REG_STATUS 0x400
172#define VIA_REG_CR_TRANSET 0x41C
173#define VIA_REG_CR_TRANSPACE 0x420
174#define VIA_REG_TRANSET 0x43C
175#define VIA_REG_TRANSPACE 0x440
176
177/* VIA_REG_STATUS(0x400): Engine Status */
178
179/* Command Regulator is busy */
180#define VIA_CMD_RGTR_BUSY 0x00000080
181/* 2D Engine is busy */
182#define VIA_2D_ENG_BUSY 0x00000002
183/* 3D Engine is busy */
184#define VIA_3D_ENG_BUSY 0x00000001
185/* Virtual Queue is busy */
186#define VIA_VR_QUEUE_BUSY 0x00020000
187
188/* VIA_REG_STATUS(0x400): Engine Status for H5 */
189#define VIA_CMD_RGTR_BUSY_H5 0x00000010 /* Command Regulator is busy */
190#define VIA_2D_ENG_BUSY_H5 0x00000002 /* 2D Engine is busy */
191#define VIA_3D_ENG_BUSY_H5 0x00001FE1 /* 3D Engine is busy */
192#define VIA_VR_QUEUE_BUSY_H5 0x00000004 /* Virtual Queue is busy */
193
194/* VIA_REG_STATUS(0x400): Engine Status for VT3353/3409 */
195#define VIA_CMD_RGTR_BUSY_M1 0x00000010 /* Command Regulator is busy */
196#define VIA_2D_ENG_BUSY_M1 0x00000002 /* 2D Engine is busy */
197#define VIA_3D_ENG_BUSY_M1 0x00001FE1 /* 3D Engine is busy */
198#define VIA_VR_QUEUE_BUSY_M1 0x00000004 /* Virtual Queue is busy */
199
200#define MAXLOOP 0xFFFFFF
201
202#define VIA_BITBLT_COLOR 1
203#define VIA_BITBLT_MONO 2
204#define VIA_BITBLT_FILL 3
205
206int viafb_setup_engine(struct fb_info *info);
207void viafb_reset_engine(struct viafb_par *viapar);
208void viafb_show_hw_cursor(struct fb_info *info, int Status);
209void viafb_wait_engine_idle(struct fb_info *info);
210
211#endif /* __ACCEL_H__ */
diff --git a/drivers/video/fbdev/via/chip.h b/drivers/video/fbdev/via/chip.h
new file mode 100644
index 000000000000..d32a5076c20f
--- /dev/null
+++ b/drivers/video/fbdev/via/chip.h
@@ -0,0 +1,176 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __CHIP_H__
22#define __CHIP_H__
23
24#include "global.h"
25
26/***************************************/
27/* Definition Graphic Chip Information */
28/***************************************/
29
30#define PCI_VIA_VENDOR_ID 0x1106
31
32/* Define VIA Graphic Chip Name */
33#define UNICHROME_CLE266 1
34#define UNICHROME_CLE266_DID 0x3122
35#define CLE266_REVISION_AX 0x0A
36#define CLE266_REVISION_CX 0x0C
37
38#define UNICHROME_K400 2
39#define UNICHROME_K400_DID 0x7205
40
41#define UNICHROME_K800 3
42#define UNICHROME_K800_DID 0x3108
43
44#define UNICHROME_PM800 4
45#define UNICHROME_PM800_DID 0x3118
46
47#define UNICHROME_CN700 5
48#define UNICHROME_CN700_DID 0x3344
49
50#define UNICHROME_CX700 6
51#define UNICHROME_CX700_DID 0x3157
52#define CX700_REVISION_700 0x0
53#define CX700_REVISION_700M 0x1
54#define CX700_REVISION_700M2 0x2
55
56#define UNICHROME_CN750 7
57#define UNICHROME_CN750_DID 0x3225
58
59#define UNICHROME_K8M890 8
60#define UNICHROME_K8M890_DID 0x3230
61
62#define UNICHROME_P4M890 9
63#define UNICHROME_P4M890_DID 0x3343
64
65#define UNICHROME_P4M900 10
66#define UNICHROME_P4M900_DID 0x3371
67
68#define UNICHROME_VX800 11
69#define UNICHROME_VX800_DID 0x1122
70
71#define UNICHROME_VX855 12
72#define UNICHROME_VX855_DID 0x5122
73
74#define UNICHROME_VX900 13
75#define UNICHROME_VX900_DID 0x7122
76
77/**************************************************/
78/* Definition TMDS Trasmitter Information */
79/**************************************************/
80
81/* Definition TMDS Trasmitter Index */
82#define NON_TMDS_TRANSMITTER 0x00
83#define VT1632_TMDS 0x01
84#define INTEGRATED_TMDS 0x42
85
86/* Definition TMDS Trasmitter I2C Slave Address */
87#define VT1632_TMDS_I2C_ADDR 0x10
88
89/**************************************************/
90/* Definition LVDS Trasmitter Information */
91/**************************************************/
92
93/* Definition LVDS Trasmitter Index */
94#define NON_LVDS_TRANSMITTER 0x00
95#define VT1631_LVDS 0x01
96#define VT1636_LVDS 0x0E
97#define INTEGRATED_LVDS 0x41
98
99/* Definition Digital Transmitter Mode */
100#define TX_DATA_12_BITS 0x01
101#define TX_DATA_24_BITS 0x02
102#define TX_DATA_DDR_MODE 0x04
103#define TX_DATA_SDR_MODE 0x08
104
105/* Definition LVDS Trasmitter I2C Slave Address */
106#define VT1631_LVDS_I2C_ADDR 0x70
107#define VT3271_LVDS_I2C_ADDR 0x80
108#define VT1636_LVDS_I2C_ADDR 0x80
109
110struct tmds_chip_information {
111 int tmds_chip_name;
112 int tmds_chip_slave_addr;
113 int output_interface;
114 int i2c_port;
115};
116
117struct lvds_chip_information {
118 int lvds_chip_name;
119 int lvds_chip_slave_addr;
120 int output_interface;
121 int i2c_port;
122};
123
124/* The type of 2D engine */
125enum via_2d_engine {
126 VIA_2D_ENG_H2,
127 VIA_2D_ENG_H5,
128 VIA_2D_ENG_M1,
129};
130
131struct chip_information {
132 int gfx_chip_name;
133 int gfx_chip_revision;
134 enum via_2d_engine twod_engine;
135 struct tmds_chip_information tmds_chip_info;
136 struct lvds_chip_information lvds_chip_info;
137 struct lvds_chip_information lvds_chip_info2;
138};
139
140struct tmds_setting_information {
141 int iga_path;
142 int h_active;
143 int v_active;
144 int max_pixel_clock;
145};
146
147struct lvds_setting_information {
148 int iga_path;
149 int lcd_panel_hres;
150 int lcd_panel_vres;
151 int display_method;
152 int device_lcd_dualedge;
153 int LCDDithering;
154 int lcd_mode;
155 u32 vclk; /*panel mode clock value */
156};
157
158struct GFX_DPA_SETTING {
159 int ClkRangeIndex;
160 u8 DVP0; /* CR96[3:0] */
161 u8 DVP0DataDri_S1; /* SR2A[5] */
162 u8 DVP0DataDri_S; /* SR1B[1] */
163 u8 DVP0ClockDri_S1; /* SR2A[4] */
164 u8 DVP0ClockDri_S; /* SR1E[2] */
165 u8 DVP1; /* CR9B[3:0] */
166 u8 DVP1Driving; /* SR65[3:0], Data and Clock driving */
167 u8 DFPHigh; /* CR97[3:0] */
168 u8 DFPLow; /* CR99[3:0] */
169
170};
171
172struct VT1636_DPA_SETTING {
173 u8 CLK_SEL_ST1;
174 u8 CLK_SEL_ST2;
175};
176#endif /* __CHIP_H__ */
diff --git a/drivers/video/fbdev/via/debug.h b/drivers/video/fbdev/via/debug.h
new file mode 100644
index 000000000000..86eacc2017f3
--- /dev/null
+++ b/drivers/video/fbdev/via/debug.h
@@ -0,0 +1,41 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __DEBUG_H__
22#define __DEBUG_H__
23
24#ifndef VIAFB_DEBUG
25#define VIAFB_DEBUG 0
26#endif
27
28#if VIAFB_DEBUG
29#define DEBUG_MSG(f, a...) printk(f, ## a)
30#else
31#define DEBUG_MSG(f, a...)
32#endif
33
34#define VIAFB_WARN 0
35#if VIAFB_WARN
36#define WARN_MSG(f, a...) printk(f, ## a)
37#else
38#define WARN_MSG(f, a...)
39#endif
40
41#endif /* __DEBUG_H__ */
diff --git a/drivers/video/fbdev/via/dvi.c b/drivers/video/fbdev/via/dvi.c
new file mode 100644
index 000000000000..7789553952d3
--- /dev/null
+++ b/drivers/video/fbdev/via/dvi.c
@@ -0,0 +1,478 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/via-core.h>
22#include <linux/via_i2c.h>
23#include "global.h"
24
25static void tmds_register_write(int index, u8 data);
26static int tmds_register_read(int index);
27static int tmds_register_read_bytes(int index, u8 *buff, int buff_len);
28static void dvi_get_panel_size_from_DDCv1(
29 struct tmds_chip_information *tmds_chip,
30 struct tmds_setting_information *tmds_setting);
31static int viafb_dvi_query_EDID(void);
32
33static inline bool check_tmds_chip(int device_id_subaddr, int device_id)
34{
35 return tmds_register_read(device_id_subaddr) == device_id;
36}
37
38void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
39 struct tmds_setting_information *tmds_setting)
40{
41 DEBUG_MSG(KERN_INFO "viafb_init_dvi_size()\n");
42
43 viafb_dvi_sense();
44 if (viafb_dvi_query_EDID() == 1)
45 dvi_get_panel_size_from_DDCv1(tmds_chip, tmds_setting);
46
47 return;
48}
49
50bool viafb_tmds_trasmitter_identify(void)
51{
52 unsigned char sr2a = 0, sr1e = 0, sr3e = 0;
53
54 /* Turn on ouputting pad */
55 switch (viaparinfo->chip_info->gfx_chip_name) {
56 case UNICHROME_K8M890:
57 /*=* DFP Low Pad on *=*/
58 sr2a = viafb_read_reg(VIASR, SR2A);
59 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
60 break;
61
62 case UNICHROME_P4M900:
63 case UNICHROME_P4M890:
64 /* DFP Low Pad on */
65 sr2a = viafb_read_reg(VIASR, SR2A);
66 viafb_write_reg_mask(SR2A, VIASR, 0x03, BIT0 + BIT1);
67 /* DVP0 Pad on */
68 sr1e = viafb_read_reg(VIASR, SR1E);
69 viafb_write_reg_mask(SR1E, VIASR, 0xC0, BIT6 + BIT7);
70 break;
71
72 default:
73 /* DVP0/DVP1 Pad on */
74 sr1e = viafb_read_reg(VIASR, SR1E);
75 viafb_write_reg_mask(SR1E, VIASR, 0xF0, BIT4 +
76 BIT5 + BIT6 + BIT7);
77 /* SR3E[1]Multi-function selection:
78 0 = Emulate I2C and DDC bus by GPIO2/3/4. */
79 sr3e = viafb_read_reg(VIASR, SR3E);
80 viafb_write_reg_mask(SR3E, VIASR, 0x0, BIT5);
81 break;
82 }
83
84 /* Check for VT1632: */
85 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS;
86 viaparinfo->chip_info->
87 tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
88 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31;
89 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
90 /*
91 * Currently only support 12bits,dual edge,add 24bits mode later
92 */
93 tmds_register_write(0x08, 0x3b);
94
95 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
96 DEBUG_MSG(KERN_INFO "\n %2d",
97 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
98 DEBUG_MSG(KERN_INFO "\n %2d",
99 viaparinfo->chip_info->tmds_chip_info.i2c_port);
100 return true;
101 } else {
102 viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C;
103 if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) {
104 tmds_register_write(0x08, 0x3b);
105 DEBUG_MSG(KERN_INFO "\n VT1632 TMDS ! \n");
106 DEBUG_MSG(KERN_INFO "\n %2d",
107 viaparinfo->chip_info->
108 tmds_chip_info.tmds_chip_name);
109 DEBUG_MSG(KERN_INFO "\n %2d",
110 viaparinfo->chip_info->
111 tmds_chip_info.i2c_port);
112 return true;
113 }
114 }
115
116 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = INTEGRATED_TMDS;
117
118 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) &&
119 ((viafb_display_hardware_layout == HW_LAYOUT_DVI_ONLY) ||
120 (viafb_display_hardware_layout == HW_LAYOUT_LCD_DVI))) {
121 DEBUG_MSG(KERN_INFO "\n Integrated TMDS ! \n");
122 return true;
123 }
124
125 switch (viaparinfo->chip_info->gfx_chip_name) {
126 case UNICHROME_K8M890:
127 viafb_write_reg(SR2A, VIASR, sr2a);
128 break;
129
130 case UNICHROME_P4M900:
131 case UNICHROME_P4M890:
132 viafb_write_reg(SR2A, VIASR, sr2a);
133 viafb_write_reg(SR1E, VIASR, sr1e);
134 break;
135
136 default:
137 viafb_write_reg(SR1E, VIASR, sr1e);
138 viafb_write_reg(SR3E, VIASR, sr3e);
139 break;
140 }
141
142 viaparinfo->chip_info->
143 tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER;
144 viaparinfo->chip_info->tmds_chip_info.
145 tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR;
146 return false;
147}
148
149static void tmds_register_write(int index, u8 data)
150{
151 viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
152 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
153 index, data);
154}
155
156static int tmds_register_read(int index)
157{
158 u8 data;
159
160 viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port,
161 (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
162 (u8) index, &data);
163 return data;
164}
165
166static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
167{
168 viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port,
169 (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr,
170 (u8) index, buff, buff_len);
171 return 0;
172}
173
174/* DVI Set Mode */
175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
176 u16 cxres, u16 cyres, int iga)
177{
178 struct fb_var_screeninfo dvi_var = *var;
179 const struct fb_videomode *rb_mode;
180 int maxPixelClock;
181
182 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
183 if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) {
184 rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60);
185 if (rb_mode)
186 viafb_fill_var_timing_info(&dvi_var, rb_mode);
187 }
188
189 viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);
190}
191
192/* Sense DVI Connector */
193int viafb_dvi_sense(void)
194{
195 u8 RegSR1E = 0, RegSR3E = 0, RegCR6B = 0, RegCR91 = 0,
196 RegCR93 = 0, RegCR9B = 0, data;
197 int ret = false;
198
199 DEBUG_MSG(KERN_INFO "viafb_dvi_sense!!\n");
200
201 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
202 /* DI1 Pad on */
203 RegSR1E = viafb_read_reg(VIASR, SR1E);
204 viafb_write_reg(SR1E, VIASR, RegSR1E | 0x30);
205
206 /* CR6B[0]VCK Input Selection: 1 = External clock. */
207 RegCR6B = viafb_read_reg(VIACR, CR6B);
208 viafb_write_reg(CR6B, VIACR, RegCR6B | 0x08);
209
210 /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
211 [0] Software Control Power Sequence */
212 RegCR91 = viafb_read_reg(VIACR, CR91);
213 viafb_write_reg(CR91, VIACR, 0x1D);
214
215 /* CR93[7] DI1 Data Source Selection: 1 = DSP2.
216 CR93[5] DI1 Clock Source: 1 = internal.
217 CR93[4] DI1 Clock Polarity.
218 CR93[3:1] DI1 Clock Adjust. CR93[0] DI1 enable */
219 RegCR93 = viafb_read_reg(VIACR, CR93);
220 viafb_write_reg(CR93, VIACR, 0x01);
221 } else {
222 /* DVP0/DVP1 Pad on */
223 RegSR1E = viafb_read_reg(VIASR, SR1E);
224 viafb_write_reg(SR1E, VIASR, RegSR1E | 0xF0);
225
226 /* SR3E[1]Multi-function selection:
227 0 = Emulate I2C and DDC bus by GPIO2/3/4. */
228 RegSR3E = viafb_read_reg(VIASR, SR3E);
229 viafb_write_reg(SR3E, VIASR, RegSR3E & (~0x20));
230
231 /* CR91[4] VDD On [3] Data On [2] VEE On [1] Back Light Off
232 [0] Software Control Power Sequence */
233 RegCR91 = viafb_read_reg(VIACR, CR91);
234 viafb_write_reg(CR91, VIACR, 0x1D);
235
236 /*CR9B[4] DVP1 Data Source Selection: 1 = From secondary
237 display.CR9B[2:0] DVP1 Clock Adjust */
238 RegCR9B = viafb_read_reg(VIACR, CR9B);
239 viafb_write_reg(CR9B, VIACR, 0x01);
240 }
241
242 data = (u8) tmds_register_read(0x09);
243 if (data & 0x04)
244 ret = true;
245
246 if (ret == false) {
247 if (viafb_dvi_query_EDID())
248 ret = true;
249 }
250
251 /* Restore status */
252 viafb_write_reg(SR1E, VIASR, RegSR1E);
253 viafb_write_reg(CR91, VIACR, RegCR91);
254 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
255 viafb_write_reg(CR6B, VIACR, RegCR6B);
256 viafb_write_reg(CR93, VIACR, RegCR93);
257 } else {
258 viafb_write_reg(SR3E, VIASR, RegSR3E);
259 viafb_write_reg(CR9B, VIACR, RegCR9B);
260 }
261
262 return ret;
263}
264
265/* Query Flat Panel's EDID Table Version Through DVI Connector */
266static int viafb_dvi_query_EDID(void)
267{
268 u8 data0, data1;
269 int restore;
270
271 DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n");
272
273 restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr;
274 viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0;
275
276 data0 = (u8) tmds_register_read(0x00);
277 data1 = (u8) tmds_register_read(0x01);
278 if ((data0 == 0) && (data1 == 0xFF)) {
279 viaparinfo->chip_info->
280 tmds_chip_info.tmds_chip_slave_addr = restore;
281 return EDID_VERSION_1; /* Found EDID1 Table */
282 }
283
284 return false;
285}
286
287/* Get Panel Size Using EDID1 Table */
288static void dvi_get_panel_size_from_DDCv1(
289 struct tmds_chip_information *tmds_chip,
290 struct tmds_setting_information *tmds_setting)
291{
292 int i, restore;
293 unsigned char EDID_DATA[18];
294
295 DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n");
296
297 restore = tmds_chip->tmds_chip_slave_addr;
298 tmds_chip->tmds_chip_slave_addr = 0xA0;
299 for (i = 0x25; i < 0x6D; i++) {
300 switch (i) {
301 case 0x36:
302 case 0x48:
303 case 0x5A:
304 case 0x6C:
305 tmds_register_read_bytes(i, EDID_DATA, 10);
306 if (!(EDID_DATA[0] || EDID_DATA[1])) {
307 /* The first two byte must be zero. */
308 if (EDID_DATA[3] == 0xFD) {
309 /* To get max pixel clock. */
310 tmds_setting->max_pixel_clock =
311 EDID_DATA[9] * 10;
312 }
313 }
314 break;
315
316 default:
317 break;
318 }
319 }
320
321 DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n",
322 tmds_setting->max_pixel_clock);
323 tmds_chip->tmds_chip_slave_addr = restore;
324}
325
326/* If Disable DVI, turn off pad */
327void viafb_dvi_disable(void)
328{
329 if (viaparinfo->chip_info->
330 tmds_chip_info.output_interface == INTERFACE_TMDS)
331 /* Turn off TMDS power. */
332 viafb_write_reg(CRD2, VIACR,
333 viafb_read_reg(VIACR, CRD2) | 0x08);
334}
335
336static void dvi_patch_skew_dvp0(void)
337{
338 /* Reset data driving first: */
339 viafb_write_reg_mask(SR1B, VIASR, 0, BIT1);
340 viafb_write_reg_mask(SR2A, VIASR, 0, BIT4);
341
342 switch (viaparinfo->chip_info->gfx_chip_name) {
343 case UNICHROME_P4M890:
344 {
345 if ((viaparinfo->tmds_setting_info->h_active == 1600) &&
346 (viaparinfo->tmds_setting_info->v_active ==
347 1200))
348 viafb_write_reg_mask(CR96, VIACR, 0x03,
349 BIT0 + BIT1 + BIT2);
350 else
351 viafb_write_reg_mask(CR96, VIACR, 0x07,
352 BIT0 + BIT1 + BIT2);
353 break;
354 }
355
356 case UNICHROME_P4M900:
357 {
358 viafb_write_reg_mask(CR96, VIACR, 0x07,
359 BIT0 + BIT1 + BIT2 + BIT3);
360 viafb_write_reg_mask(SR1B, VIASR, 0x02, BIT1);
361 viafb_write_reg_mask(SR2A, VIASR, 0x10, BIT4);
362 break;
363 }
364
365 default:
366 {
367 break;
368 }
369 }
370}
371
372static void dvi_patch_skew_dvp_low(void)
373{
374 switch (viaparinfo->chip_info->gfx_chip_name) {
375 case UNICHROME_K8M890:
376 {
377 viafb_write_reg_mask(CR99, VIACR, 0x03, BIT0 + BIT1);
378 break;
379 }
380
381 case UNICHROME_P4M900:
382 {
383 viafb_write_reg_mask(CR99, VIACR, 0x08,
384 BIT0 + BIT1 + BIT2 + BIT3);
385 break;
386 }
387
388 case UNICHROME_P4M890:
389 {
390 viafb_write_reg_mask(CR99, VIACR, 0x0F,
391 BIT0 + BIT1 + BIT2 + BIT3);
392 break;
393 }
394
395 default:
396 {
397 break;
398 }
399 }
400}
401
402/* If Enable DVI, turn off pad */
403void viafb_dvi_enable(void)
404{
405 u8 data;
406
407 switch (viaparinfo->chip_info->tmds_chip_info.output_interface) {
408 case INTERFACE_DVP0:
409 viafb_write_reg_mask(CR6B, VIACR, 0x01, BIT0);
410 viafb_write_reg_mask(CR6C, VIACR, 0x21, BIT0 + BIT5);
411 dvi_patch_skew_dvp0();
412 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
413 tmds_register_write(0x88, 0x3b);
414 else
415 /*clear CR91[5] to direct on display period
416 in the secondary diplay path */
417 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
418 break;
419
420 case INTERFACE_DVP1:
421 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
422 viafb_write_reg_mask(CR93, VIACR, 0x21, BIT0 + BIT5);
423
424 /*fix dvi cann't be enabled with MB VT5718C4 - Al Zhang */
425 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
426 tmds_register_write(0x88, 0x3b);
427 else
428 /*clear CR91[5] to direct on display period
429 in the secondary diplay path */
430 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
431
432 /*fix DVI cannot enable on EPIA-M board */
433 if (viafb_platform_epia_dvi == 1) {
434 viafb_write_reg_mask(CR91, VIACR, 0x1f, 0x1f);
435 viafb_write_reg_mask(CR88, VIACR, 0x00, BIT6 + BIT0);
436 if (viafb_bus_width == 24) {
437 if (viafb_device_lcd_dualedge == 1)
438 data = 0x3F;
439 else
440 data = 0x37;
441 viafb_i2c_writebyte(viaparinfo->chip_info->
442 tmds_chip_info.i2c_port,
443 viaparinfo->chip_info->
444 tmds_chip_info.tmds_chip_slave_addr,
445 0x08, data);
446 }
447 }
448 break;
449
450 case INTERFACE_DFP_HIGH:
451 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
452 via_write_reg_mask(VIACR, CR97, 0x03, 0x03);
453
454 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
455 break;
456
457 case INTERFACE_DFP_LOW:
458 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
459 break;
460
461 dvi_patch_skew_dvp_low();
462 via_write_reg_mask(VIACR, 0x91, 0x00, 0x20);
463 break;
464
465 case INTERFACE_TMDS:
466 /* Turn on Display period in the panel path. */
467 viafb_write_reg_mask(CR91, VIACR, 0, BIT7);
468
469 /* Turn on TMDS power. */
470 viafb_write_reg_mask(CRD2, VIACR, 0, BIT3);
471 break;
472 }
473
474 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
475 /* Disable LCD Scaling */
476 viafb_write_reg_mask(CR79, VIACR, 0x00, BIT0);
477 }
478}
diff --git a/drivers/video/fbdev/via/dvi.h b/drivers/video/fbdev/via/dvi.h
new file mode 100644
index 000000000000..4c6bfba57d11
--- /dev/null
+++ b/drivers/video/fbdev/via/dvi.h
@@ -0,0 +1,65 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __DVI_H__
23#define __DVI_H__
24
25/*Definition TMDS Device ID register*/
26#define VT1632_DEVICE_ID_REG 0x02
27#define VT1632_DEVICE_ID 0x92
28
29#define GET_DVI_SIZE_BY_SYSTEM_BIOS 0x01
30#define GET_DVI_SIZE_BY_VGA_BIOS 0x02
31#define GET_DVI_SZIE_BY_HW_STRAPPING 0x03
32
33/* Definition DVI Panel ID*/
34/* Resolution: 640x480, Channel: single, Dithering: Enable */
35#define DVI_PANEL_ID0_640X480 0x00
36/* Resolution: 800x600, Channel: single, Dithering: Enable */
37#define DVI_PANEL_ID1_800x600 0x01
38/* Resolution: 1024x768, Channel: single, Dithering: Enable */
39#define DVI_PANEL_ID1_1024x768 0x02
40/* Resolution: 1280x768, Channel: single, Dithering: Enable */
41#define DVI_PANEL_ID1_1280x768 0x03
42/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
43#define DVI_PANEL_ID1_1280x1024 0x04
44/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
45#define DVI_PANEL_ID1_1400x1050 0x05
46/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
47#define DVI_PANEL_ID1_1600x1200 0x06
48
49/* Define the version of EDID*/
50#define EDID_VERSION_1 1
51#define EDID_VERSION_2 2
52
53#define DEV_CONNECT_DVI 0x01
54#define DEV_CONNECT_HDMI 0x02
55
56int viafb_dvi_sense(void);
57void viafb_dvi_disable(void);
58void viafb_dvi_enable(void);
59bool viafb_tmds_trasmitter_identify(void);
60void viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
61 struct tmds_setting_information *tmds_setting);
62void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
63 u16 cxres, u16 cyres, int iga);
64
65#endif /* __DVI_H__ */
diff --git a/drivers/video/fbdev/via/global.c b/drivers/video/fbdev/via/global.c
new file mode 100644
index 000000000000..3102171c1674
--- /dev/null
+++ b/drivers/video/fbdev/via/global.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include "global.h"
22int viafb_platform_epia_dvi = STATE_OFF;
23int viafb_device_lcd_dualedge = STATE_OFF;
24int viafb_bus_width = 12;
25int viafb_display_hardware_layout = HW_LAYOUT_LCD_DVI;
26int viafb_DeviceStatus = CRT_Device;
27int viafb_hotplug;
28int viafb_refresh = 60;
29int viafb_refresh1 = 60;
30int viafb_lcd_dsp_method = LCD_EXPANDSION;
31int viafb_lcd_mode = LCD_OPENLDI;
32int viafb_CRT_ON = 1;
33int viafb_DVI_ON;
34int viafb_LCD_ON ;
35int viafb_LCD2_ON;
36int viafb_SAMM_ON;
37int viafb_dual_fb;
38unsigned int viafb_second_xres = 640;
39unsigned int viafb_second_yres = 480;
40int viafb_hotplug_Xres = 640;
41int viafb_hotplug_Yres = 480;
42int viafb_hotplug_bpp = 32;
43int viafb_hotplug_refresh = 60;
44int viafb_primary_dev = None_Device;
45int viafb_lcd_panel_id = LCD_PANEL_ID_MAXIMUM + 1;
46struct fb_info *viafbinfo;
47struct fb_info *viafbinfo1;
48struct viafb_par *viaparinfo;
49struct viafb_par *viaparinfo1;
50
diff --git a/drivers/video/fbdev/via/global.h b/drivers/video/fbdev/via/global.h
new file mode 100644
index 000000000000..275dbbbd6b81
--- /dev/null
+++ b/drivers/video/fbdev/via/global.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __GLOBAL_H__
23#define __GLOBAL_H__
24
25#include <linux/fb.h>
26#include <linux/delay.h>
27#include <linux/ioport.h>
28#include <linux/pci.h>
29#include <linux/io.h>
30#include <linux/uaccess.h>
31#include <linux/init.h>
32#include <linux/proc_fs.h>
33#include <linux/console.h>
34#include <linux/timer.h>
35
36#include "debug.h"
37
38#include "viafbdev.h"
39#include "chip.h"
40#include "accel.h"
41#include "share.h"
42#include "dvi.h"
43#include "viamode.h"
44#include "hw.h"
45
46#include "lcd.h"
47#include "ioctl.h"
48#include "via_utility.h"
49#include "vt1636.h"
50#include "tblDPASetting.h"
51
52/* External struct*/
53
54extern int viafb_platform_epia_dvi;
55extern int viafb_device_lcd_dualedge;
56extern int viafb_bus_width;
57extern int viafb_display_hardware_layout;
58extern struct offset offset_reg;
59extern struct viafb_par *viaparinfo;
60extern struct viafb_par *viaparinfo1;
61extern struct fb_info *viafbinfo;
62extern struct fb_info *viafbinfo1;
63extern int viafb_DeviceStatus;
64extern int viafb_refresh;
65extern int viafb_refresh1;
66extern int viafb_lcd_dsp_method;
67extern int viafb_lcd_mode;
68
69extern int viafb_CRT_ON;
70extern unsigned int viafb_second_xres;
71extern unsigned int viafb_second_yres;
72extern int viafb_hotplug_Xres;
73extern int viafb_hotplug_Yres;
74extern int viafb_hotplug_bpp;
75extern int viafb_hotplug_refresh;
76extern int viafb_primary_dev;
77
78extern int viafb_lcd_panel_id;
79
80#endif /* __GLOBAL_H__ */
diff --git a/drivers/video/fbdev/via/hw.c b/drivers/video/fbdev/via/hw.c
new file mode 100644
index 000000000000..22450908306c
--- /dev/null
+++ b/drivers/video/fbdev/via/hw.c
@@ -0,0 +1,2134 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/via-core.h>
23#include <asm/olpc.h>
24#include "global.h"
25#include "via_clock.h"
26
27static struct pll_limit cle266_pll_limits[] = {
28 {19, 19, 4, 0},
29 {26, 102, 5, 0},
30 {53, 112, 6, 0},
31 {41, 100, 7, 0},
32 {83, 108, 8, 0},
33 {87, 118, 9, 0},
34 {95, 115, 12, 0},
35 {108, 108, 13, 0},
36 {83, 83, 17, 0},
37 {67, 98, 20, 0},
38 {121, 121, 24, 0},
39 {99, 99, 29, 0},
40 {33, 33, 3, 1},
41 {15, 23, 4, 1},
42 {37, 121, 5, 1},
43 {82, 82, 6, 1},
44 {31, 84, 7, 1},
45 {83, 83, 8, 1},
46 {76, 127, 9, 1},
47 {33, 121, 4, 2},
48 {91, 118, 5, 2},
49 {83, 109, 6, 2},
50 {90, 90, 7, 2},
51 {93, 93, 2, 3},
52 {53, 53, 3, 3},
53 {73, 117, 4, 3},
54 {101, 127, 5, 3},
55 {99, 99, 7, 3}
56};
57
58static struct pll_limit k800_pll_limits[] = {
59 {22, 22, 2, 0},
60 {28, 28, 3, 0},
61 {81, 112, 3, 1},
62 {86, 166, 4, 1},
63 {109, 153, 5, 1},
64 {66, 116, 3, 2},
65 {93, 137, 4, 2},
66 {117, 208, 5, 2},
67 {30, 30, 2, 3},
68 {69, 125, 3, 3},
69 {89, 161, 4, 3},
70 {121, 208, 5, 3},
71 {66, 66, 2, 4},
72 {85, 85, 3, 4},
73 {141, 161, 4, 4},
74 {177, 177, 5, 4}
75};
76
77static struct pll_limit cx700_pll_limits[] = {
78 {98, 98, 3, 1},
79 {86, 86, 4, 1},
80 {109, 208, 5, 1},
81 {68, 68, 2, 2},
82 {95, 116, 3, 2},
83 {93, 166, 4, 2},
84 {110, 206, 5, 2},
85 {174, 174, 7, 2},
86 {82, 109, 3, 3},
87 {117, 161, 4, 3},
88 {112, 208, 5, 3},
89 {141, 202, 5, 4}
90};
91
92static struct pll_limit vx855_pll_limits[] = {
93 {86, 86, 4, 1},
94 {108, 208, 5, 1},
95 {110, 208, 5, 2},
96 {83, 112, 3, 3},
97 {103, 161, 4, 3},
98 {112, 209, 5, 3},
99 {142, 161, 4, 4},
100 {141, 176, 5, 4}
101};
102
103/* according to VIA Technologies these values are based on experiment */
104static struct io_reg scaling_parameters[] = {
105 {VIACR, CR7A, 0xFF, 0x01}, /* LCD Scaling Parameter 1 */
106 {VIACR, CR7B, 0xFF, 0x02}, /* LCD Scaling Parameter 2 */
107 {VIACR, CR7C, 0xFF, 0x03}, /* LCD Scaling Parameter 3 */
108 {VIACR, CR7D, 0xFF, 0x04}, /* LCD Scaling Parameter 4 */
109 {VIACR, CR7E, 0xFF, 0x07}, /* LCD Scaling Parameter 5 */
110 {VIACR, CR7F, 0xFF, 0x0A}, /* LCD Scaling Parameter 6 */
111 {VIACR, CR80, 0xFF, 0x0D}, /* LCD Scaling Parameter 7 */
112 {VIACR, CR81, 0xFF, 0x13}, /* LCD Scaling Parameter 8 */
113 {VIACR, CR82, 0xFF, 0x16}, /* LCD Scaling Parameter 9 */
114 {VIACR, CR83, 0xFF, 0x19}, /* LCD Scaling Parameter 10 */
115 {VIACR, CR84, 0xFF, 0x1C}, /* LCD Scaling Parameter 11 */
116 {VIACR, CR85, 0xFF, 0x1D}, /* LCD Scaling Parameter 12 */
117 {VIACR, CR86, 0xFF, 0x1E}, /* LCD Scaling Parameter 13 */
118 {VIACR, CR87, 0xFF, 0x1F}, /* LCD Scaling Parameter 14 */
119};
120
121static struct io_reg common_vga[] = {
122 {VIACR, CR07, 0x10, 0x10}, /* [0] vertical total (bit 8)
123 [1] vertical display end (bit 8)
124 [2] vertical retrace start (bit 8)
125 [3] start vertical blanking (bit 8)
126 [4] line compare (bit 8)
127 [5] vertical total (bit 9)
128 [6] vertical display end (bit 9)
129 [7] vertical retrace start (bit 9) */
130 {VIACR, CR08, 0xFF, 0x00}, /* [0-4] preset row scan
131 [5-6] byte panning */
132 {VIACR, CR09, 0xDF, 0x40}, /* [0-4] max scan line
133 [5] start vertical blanking (bit 9)
134 [6] line compare (bit 9)
135 [7] scan doubling */
136 {VIACR, CR0A, 0xFF, 0x1E}, /* [0-4] cursor start
137 [5] cursor disable */
138 {VIACR, CR0B, 0xFF, 0x00}, /* [0-4] cursor end
139 [5-6] cursor skew */
140 {VIACR, CR0E, 0xFF, 0x00}, /* [0-7] cursor location (high) */
141 {VIACR, CR0F, 0xFF, 0x00}, /* [0-7] cursor location (low) */
142 {VIACR, CR11, 0xF0, 0x80}, /* [0-3] vertical retrace end
143 [6] memory refresh bandwidth
144 [7] CRTC register protect enable */
145 {VIACR, CR14, 0xFF, 0x00}, /* [0-4] underline location
146 [5] divide memory address clock by 4
147 [6] double word addressing */
148 {VIACR, CR17, 0xFF, 0x63}, /* [0-1] mapping of display address 13-14
149 [2] divide scan line clock by 2
150 [3] divide memory address clock by 2
151 [5] address wrap
152 [6] byte mode select
153 [7] sync enable */
154 {VIACR, CR18, 0xFF, 0xFF}, /* [0-7] line compare */
155};
156
157static struct fifo_depth_select display_fifo_depth_reg = {
158 /* IGA1 FIFO Depth_Select */
159 {IGA1_FIFO_DEPTH_SELECT_REG_NUM, {{SR17, 0, 7} } },
160 /* IGA2 FIFO Depth_Select */
161 {IGA2_FIFO_DEPTH_SELECT_REG_NUM,
162 {{CR68, 4, 7}, {CR94, 7, 7}, {CR95, 7, 7} } }
163};
164
165static struct fifo_threshold_select fifo_threshold_select_reg = {
166 /* IGA1 FIFO Threshold Select */
167 {IGA1_FIFO_THRESHOLD_REG_NUM, {{SR16, 0, 5}, {SR16, 7, 7} } },
168 /* IGA2 FIFO Threshold Select */
169 {IGA2_FIFO_THRESHOLD_REG_NUM, {{CR68, 0, 3}, {CR95, 4, 6} } }
170};
171
172static struct fifo_high_threshold_select fifo_high_threshold_select_reg = {
173 /* IGA1 FIFO High Threshold Select */
174 {IGA1_FIFO_HIGH_THRESHOLD_REG_NUM, {{SR18, 0, 5}, {SR18, 7, 7} } },
175 /* IGA2 FIFO High Threshold Select */
176 {IGA2_FIFO_HIGH_THRESHOLD_REG_NUM, {{CR92, 0, 3}, {CR95, 0, 2} } }
177};
178
179static struct display_queue_expire_num display_queue_expire_num_reg = {
180 /* IGA1 Display Queue Expire Num */
181 {IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{SR22, 0, 4} } },
182 /* IGA2 Display Queue Expire Num */
183 {IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM, {{CR94, 0, 6} } }
184};
185
186/* Definition Fetch Count Registers*/
187static struct fetch_count fetch_count_reg = {
188 /* IGA1 Fetch Count Register */
189 {IGA1_FETCH_COUNT_REG_NUM, {{SR1C, 0, 7}, {SR1D, 0, 1} } },
190 /* IGA2 Fetch Count Register */
191 {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } }
192};
193
194static struct rgbLUT palLUT_table[] = {
195 /* {R,G,B} */
196 /* Index 0x00~0x03 */
197 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x2A}, {0x00, 0x2A, 0x00}, {0x00,
198 0x2A,
199 0x2A},
200 /* Index 0x04~0x07 */
201 {0x2A, 0x00, 0x00}, {0x2A, 0x00, 0x2A}, {0x2A, 0x15, 0x00}, {0x2A,
202 0x2A,
203 0x2A},
204 /* Index 0x08~0x0B */
205 {0x15, 0x15, 0x15}, {0x15, 0x15, 0x3F}, {0x15, 0x3F, 0x15}, {0x15,
206 0x3F,
207 0x3F},
208 /* Index 0x0C~0x0F */
209 {0x3F, 0x15, 0x15}, {0x3F, 0x15, 0x3F}, {0x3F, 0x3F, 0x15}, {0x3F,
210 0x3F,
211 0x3F},
212 /* Index 0x10~0x13 */
213 {0x00, 0x00, 0x00}, {0x05, 0x05, 0x05}, {0x08, 0x08, 0x08}, {0x0B,
214 0x0B,
215 0x0B},
216 /* Index 0x14~0x17 */
217 {0x0E, 0x0E, 0x0E}, {0x11, 0x11, 0x11}, {0x14, 0x14, 0x14}, {0x18,
218 0x18,
219 0x18},
220 /* Index 0x18~0x1B */
221 {0x1C, 0x1C, 0x1C}, {0x20, 0x20, 0x20}, {0x24, 0x24, 0x24}, {0x28,
222 0x28,
223 0x28},
224 /* Index 0x1C~0x1F */
225 {0x2D, 0x2D, 0x2D}, {0x32, 0x32, 0x32}, {0x38, 0x38, 0x38}, {0x3F,
226 0x3F,
227 0x3F},
228 /* Index 0x20~0x23 */
229 {0x00, 0x00, 0x3F}, {0x10, 0x00, 0x3F}, {0x1F, 0x00, 0x3F}, {0x2F,
230 0x00,
231 0x3F},
232 /* Index 0x24~0x27 */
233 {0x3F, 0x00, 0x3F}, {0x3F, 0x00, 0x2F}, {0x3F, 0x00, 0x1F}, {0x3F,
234 0x00,
235 0x10},
236 /* Index 0x28~0x2B */
237 {0x3F, 0x00, 0x00}, {0x3F, 0x10, 0x00}, {0x3F, 0x1F, 0x00}, {0x3F,
238 0x2F,
239 0x00},
240 /* Index 0x2C~0x2F */
241 {0x3F, 0x3F, 0x00}, {0x2F, 0x3F, 0x00}, {0x1F, 0x3F, 0x00}, {0x10,
242 0x3F,
243 0x00},
244 /* Index 0x30~0x33 */
245 {0x00, 0x3F, 0x00}, {0x00, 0x3F, 0x10}, {0x00, 0x3F, 0x1F}, {0x00,
246 0x3F,
247 0x2F},
248 /* Index 0x34~0x37 */
249 {0x00, 0x3F, 0x3F}, {0x00, 0x2F, 0x3F}, {0x00, 0x1F, 0x3F}, {0x00,
250 0x10,
251 0x3F},
252 /* Index 0x38~0x3B */
253 {0x1F, 0x1F, 0x3F}, {0x27, 0x1F, 0x3F}, {0x2F, 0x1F, 0x3F}, {0x37,
254 0x1F,
255 0x3F},
256 /* Index 0x3C~0x3F */
257 {0x3F, 0x1F, 0x3F}, {0x3F, 0x1F, 0x37}, {0x3F, 0x1F, 0x2F}, {0x3F,
258 0x1F,
259 0x27},
260 /* Index 0x40~0x43 */
261 {0x3F, 0x1F, 0x1F}, {0x3F, 0x27, 0x1F}, {0x3F, 0x2F, 0x1F}, {0x3F,
262 0x3F,
263 0x1F},
264 /* Index 0x44~0x47 */
265 {0x3F, 0x3F, 0x1F}, {0x37, 0x3F, 0x1F}, {0x2F, 0x3F, 0x1F}, {0x27,
266 0x3F,
267 0x1F},
268 /* Index 0x48~0x4B */
269 {0x1F, 0x3F, 0x1F}, {0x1F, 0x3F, 0x27}, {0x1F, 0x3F, 0x2F}, {0x1F,
270 0x3F,
271 0x37},
272 /* Index 0x4C~0x4F */
273 {0x1F, 0x3F, 0x3F}, {0x1F, 0x37, 0x3F}, {0x1F, 0x2F, 0x3F}, {0x1F,
274 0x27,
275 0x3F},
276 /* Index 0x50~0x53 */
277 {0x2D, 0x2D, 0x3F}, {0x31, 0x2D, 0x3F}, {0x36, 0x2D, 0x3F}, {0x3A,
278 0x2D,
279 0x3F},
280 /* Index 0x54~0x57 */
281 {0x3F, 0x2D, 0x3F}, {0x3F, 0x2D, 0x3A}, {0x3F, 0x2D, 0x36}, {0x3F,
282 0x2D,
283 0x31},
284 /* Index 0x58~0x5B */
285 {0x3F, 0x2D, 0x2D}, {0x3F, 0x31, 0x2D}, {0x3F, 0x36, 0x2D}, {0x3F,
286 0x3A,
287 0x2D},
288 /* Index 0x5C~0x5F */
289 {0x3F, 0x3F, 0x2D}, {0x3A, 0x3F, 0x2D}, {0x36, 0x3F, 0x2D}, {0x31,
290 0x3F,
291 0x2D},
292 /* Index 0x60~0x63 */
293 {0x2D, 0x3F, 0x2D}, {0x2D, 0x3F, 0x31}, {0x2D, 0x3F, 0x36}, {0x2D,
294 0x3F,
295 0x3A},
296 /* Index 0x64~0x67 */
297 {0x2D, 0x3F, 0x3F}, {0x2D, 0x3A, 0x3F}, {0x2D, 0x36, 0x3F}, {0x2D,
298 0x31,
299 0x3F},
300 /* Index 0x68~0x6B */
301 {0x00, 0x00, 0x1C}, {0x07, 0x00, 0x1C}, {0x0E, 0x00, 0x1C}, {0x15,
302 0x00,
303 0x1C},
304 /* Index 0x6C~0x6F */
305 {0x1C, 0x00, 0x1C}, {0x1C, 0x00, 0x15}, {0x1C, 0x00, 0x0E}, {0x1C,
306 0x00,
307 0x07},
308 /* Index 0x70~0x73 */
309 {0x1C, 0x00, 0x00}, {0x1C, 0x07, 0x00}, {0x1C, 0x0E, 0x00}, {0x1C,
310 0x15,
311 0x00},
312 /* Index 0x74~0x77 */
313 {0x1C, 0x1C, 0x00}, {0x15, 0x1C, 0x00}, {0x0E, 0x1C, 0x00}, {0x07,
314 0x1C,
315 0x00},
316 /* Index 0x78~0x7B */
317 {0x00, 0x1C, 0x00}, {0x00, 0x1C, 0x07}, {0x00, 0x1C, 0x0E}, {0x00,
318 0x1C,
319 0x15},
320 /* Index 0x7C~0x7F */
321 {0x00, 0x1C, 0x1C}, {0x00, 0x15, 0x1C}, {0x00, 0x0E, 0x1C}, {0x00,
322 0x07,
323 0x1C},
324 /* Index 0x80~0x83 */
325 {0x0E, 0x0E, 0x1C}, {0x11, 0x0E, 0x1C}, {0x15, 0x0E, 0x1C}, {0x18,
326 0x0E,
327 0x1C},
328 /* Index 0x84~0x87 */
329 {0x1C, 0x0E, 0x1C}, {0x1C, 0x0E, 0x18}, {0x1C, 0x0E, 0x15}, {0x1C,
330 0x0E,
331 0x11},
332 /* Index 0x88~0x8B */
333 {0x1C, 0x0E, 0x0E}, {0x1C, 0x11, 0x0E}, {0x1C, 0x15, 0x0E}, {0x1C,
334 0x18,
335 0x0E},
336 /* Index 0x8C~0x8F */
337 {0x1C, 0x1C, 0x0E}, {0x18, 0x1C, 0x0E}, {0x15, 0x1C, 0x0E}, {0x11,
338 0x1C,
339 0x0E},
340 /* Index 0x90~0x93 */
341 {0x0E, 0x1C, 0x0E}, {0x0E, 0x1C, 0x11}, {0x0E, 0x1C, 0x15}, {0x0E,
342 0x1C,
343 0x18},
344 /* Index 0x94~0x97 */
345 {0x0E, 0x1C, 0x1C}, {0x0E, 0x18, 0x1C}, {0x0E, 0x15, 0x1C}, {0x0E,
346 0x11,
347 0x1C},
348 /* Index 0x98~0x9B */
349 {0x14, 0x14, 0x1C}, {0x16, 0x14, 0x1C}, {0x18, 0x14, 0x1C}, {0x1A,
350 0x14,
351 0x1C},
352 /* Index 0x9C~0x9F */
353 {0x1C, 0x14, 0x1C}, {0x1C, 0x14, 0x1A}, {0x1C, 0x14, 0x18}, {0x1C,
354 0x14,
355 0x16},
356 /* Index 0xA0~0xA3 */
357 {0x1C, 0x14, 0x14}, {0x1C, 0x16, 0x14}, {0x1C, 0x18, 0x14}, {0x1C,
358 0x1A,
359 0x14},
360 /* Index 0xA4~0xA7 */
361 {0x1C, 0x1C, 0x14}, {0x1A, 0x1C, 0x14}, {0x18, 0x1C, 0x14}, {0x16,
362 0x1C,
363 0x14},
364 /* Index 0xA8~0xAB */
365 {0x14, 0x1C, 0x14}, {0x14, 0x1C, 0x16}, {0x14, 0x1C, 0x18}, {0x14,
366 0x1C,
367 0x1A},
368 /* Index 0xAC~0xAF */
369 {0x14, 0x1C, 0x1C}, {0x14, 0x1A, 0x1C}, {0x14, 0x18, 0x1C}, {0x14,
370 0x16,
371 0x1C},
372 /* Index 0xB0~0xB3 */
373 {0x00, 0x00, 0x10}, {0x04, 0x00, 0x10}, {0x08, 0x00, 0x10}, {0x0C,
374 0x00,
375 0x10},
376 /* Index 0xB4~0xB7 */
377 {0x10, 0x00, 0x10}, {0x10, 0x00, 0x0C}, {0x10, 0x00, 0x08}, {0x10,
378 0x00,
379 0x04},
380 /* Index 0xB8~0xBB */
381 {0x10, 0x00, 0x00}, {0x10, 0x04, 0x00}, {0x10, 0x08, 0x00}, {0x10,
382 0x0C,
383 0x00},
384 /* Index 0xBC~0xBF */
385 {0x10, 0x10, 0x00}, {0x0C, 0x10, 0x00}, {0x08, 0x10, 0x00}, {0x04,
386 0x10,
387 0x00},
388 /* Index 0xC0~0xC3 */
389 {0x00, 0x10, 0x00}, {0x00, 0x10, 0x04}, {0x00, 0x10, 0x08}, {0x00,
390 0x10,
391 0x0C},
392 /* Index 0xC4~0xC7 */
393 {0x00, 0x10, 0x10}, {0x00, 0x0C, 0x10}, {0x00, 0x08, 0x10}, {0x00,
394 0x04,
395 0x10},
396 /* Index 0xC8~0xCB */
397 {0x08, 0x08, 0x10}, {0x0A, 0x08, 0x10}, {0x0C, 0x08, 0x10}, {0x0E,
398 0x08,
399 0x10},
400 /* Index 0xCC~0xCF */
401 {0x10, 0x08, 0x10}, {0x10, 0x08, 0x0E}, {0x10, 0x08, 0x0C}, {0x10,
402 0x08,
403 0x0A},
404 /* Index 0xD0~0xD3 */
405 {0x10, 0x08, 0x08}, {0x10, 0x0A, 0x08}, {0x10, 0x0C, 0x08}, {0x10,
406 0x0E,
407 0x08},
408 /* Index 0xD4~0xD7 */
409 {0x10, 0x10, 0x08}, {0x0E, 0x10, 0x08}, {0x0C, 0x10, 0x08}, {0x0A,
410 0x10,
411 0x08},
412 /* Index 0xD8~0xDB */
413 {0x08, 0x10, 0x08}, {0x08, 0x10, 0x0A}, {0x08, 0x10, 0x0C}, {0x08,
414 0x10,
415 0x0E},
416 /* Index 0xDC~0xDF */
417 {0x08, 0x10, 0x10}, {0x08, 0x0E, 0x10}, {0x08, 0x0C, 0x10}, {0x08,
418 0x0A,
419 0x10},
420 /* Index 0xE0~0xE3 */
421 {0x0B, 0x0B, 0x10}, {0x0C, 0x0B, 0x10}, {0x0D, 0x0B, 0x10}, {0x0F,
422 0x0B,
423 0x10},
424 /* Index 0xE4~0xE7 */
425 {0x10, 0x0B, 0x10}, {0x10, 0x0B, 0x0F}, {0x10, 0x0B, 0x0D}, {0x10,
426 0x0B,
427 0x0C},
428 /* Index 0xE8~0xEB */
429 {0x10, 0x0B, 0x0B}, {0x10, 0x0C, 0x0B}, {0x10, 0x0D, 0x0B}, {0x10,
430 0x0F,
431 0x0B},
432 /* Index 0xEC~0xEF */
433 {0x10, 0x10, 0x0B}, {0x0F, 0x10, 0x0B}, {0x0D, 0x10, 0x0B}, {0x0C,
434 0x10,
435 0x0B},
436 /* Index 0xF0~0xF3 */
437 {0x0B, 0x10, 0x0B}, {0x0B, 0x10, 0x0C}, {0x0B, 0x10, 0x0D}, {0x0B,
438 0x10,
439 0x0F},
440 /* Index 0xF4~0xF7 */
441 {0x0B, 0x10, 0x10}, {0x0B, 0x0F, 0x10}, {0x0B, 0x0D, 0x10}, {0x0B,
442 0x0C,
443 0x10},
444 /* Index 0xF8~0xFB */
445 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
446 0x00,
447 0x00},
448 /* Index 0xFC~0xFF */
449 {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00,
450 0x00,
451 0x00}
452};
453
454static struct via_device_mapping device_mapping[] = {
455 {VIA_LDVP0, "LDVP0"},
456 {VIA_LDVP1, "LDVP1"},
457 {VIA_DVP0, "DVP0"},
458 {VIA_CRT, "CRT"},
459 {VIA_DVP1, "DVP1"},
460 {VIA_LVDS1, "LVDS1"},
461 {VIA_LVDS2, "LVDS2"}
462};
463
464/* structure with function pointers to support clock control */
465static struct via_clock clock;
466
467static void load_fix_bit_crtc_reg(void);
468static void init_gfx_chip_info(int chip_type);
469static void init_tmds_chip_info(void);
470static void init_lvds_chip_info(void);
471static void device_screen_off(void);
472static void device_screen_on(void);
473static void set_display_channel(void);
474static void device_off(void);
475static void device_on(void);
476static void enable_second_display_channel(void);
477static void disable_second_display_channel(void);
478
479void viafb_lock_crt(void)
480{
481 viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7);
482}
483
484void viafb_unlock_crt(void)
485{
486 viafb_write_reg_mask(CR11, VIACR, 0, BIT7);
487 viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
488}
489
490static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
491{
492 outb(index, LUT_INDEX_WRITE);
493 outb(r, LUT_DATA);
494 outb(g, LUT_DATA);
495 outb(b, LUT_DATA);
496}
497
498static u32 get_dvi_devices(int output_interface)
499{
500 switch (output_interface) {
501 case INTERFACE_DVP0:
502 return VIA_DVP0 | VIA_LDVP0;
503
504 case INTERFACE_DVP1:
505 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
506 return VIA_LDVP1;
507 else
508 return VIA_DVP1;
509
510 case INTERFACE_DFP_HIGH:
511 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
512 return 0;
513 else
514 return VIA_LVDS2 | VIA_DVP0;
515
516 case INTERFACE_DFP_LOW:
517 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
518 return 0;
519 else
520 return VIA_DVP1 | VIA_LVDS1;
521
522 case INTERFACE_TMDS:
523 return VIA_LVDS1;
524 }
525
526 return 0;
527}
528
529static u32 get_lcd_devices(int output_interface)
530{
531 switch (output_interface) {
532 case INTERFACE_DVP0:
533 return VIA_DVP0;
534
535 case INTERFACE_DVP1:
536 return VIA_DVP1;
537
538 case INTERFACE_DFP_HIGH:
539 return VIA_LVDS2 | VIA_DVP0;
540
541 case INTERFACE_DFP_LOW:
542 return VIA_LVDS1 | VIA_DVP1;
543
544 case INTERFACE_DFP:
545 return VIA_LVDS1 | VIA_LVDS2;
546
547 case INTERFACE_LVDS0:
548 case INTERFACE_LVDS0LVDS1:
549 return VIA_LVDS1;
550
551 case INTERFACE_LVDS1:
552 return VIA_LVDS2;
553 }
554
555 return 0;
556}
557
558/*Set IGA path for each device*/
559void viafb_set_iga_path(void)
560{
561 int crt_iga_path = 0;
562
563 if (viafb_SAMM_ON == 1) {
564 if (viafb_CRT_ON) {
565 if (viafb_primary_dev == CRT_Device)
566 crt_iga_path = IGA1;
567 else
568 crt_iga_path = IGA2;
569 }
570
571 if (viafb_DVI_ON) {
572 if (viafb_primary_dev == DVI_Device)
573 viaparinfo->tmds_setting_info->iga_path = IGA1;
574 else
575 viaparinfo->tmds_setting_info->iga_path = IGA2;
576 }
577
578 if (viafb_LCD_ON) {
579 if (viafb_primary_dev == LCD_Device) {
580 if (viafb_dual_fb &&
581 (viaparinfo->chip_info->gfx_chip_name ==
582 UNICHROME_CLE266)) {
583 viaparinfo->
584 lvds_setting_info->iga_path = IGA2;
585 crt_iga_path = IGA1;
586 viaparinfo->
587 tmds_setting_info->iga_path = IGA1;
588 } else
589 viaparinfo->
590 lvds_setting_info->iga_path = IGA1;
591 } else {
592 viaparinfo->lvds_setting_info->iga_path = IGA2;
593 }
594 }
595 if (viafb_LCD2_ON) {
596 if (LCD2_Device == viafb_primary_dev)
597 viaparinfo->lvds_setting_info2->iga_path = IGA1;
598 else
599 viaparinfo->lvds_setting_info2->iga_path = IGA2;
600 }
601 } else {
602 viafb_SAMM_ON = 0;
603
604 if (viafb_CRT_ON && viafb_LCD_ON) {
605 crt_iga_path = IGA1;
606 viaparinfo->lvds_setting_info->iga_path = IGA2;
607 } else if (viafb_CRT_ON && viafb_DVI_ON) {
608 crt_iga_path = IGA1;
609 viaparinfo->tmds_setting_info->iga_path = IGA2;
610 } else if (viafb_LCD_ON && viafb_DVI_ON) {
611 viaparinfo->tmds_setting_info->iga_path = IGA1;
612 viaparinfo->lvds_setting_info->iga_path = IGA2;
613 } else if (viafb_LCD_ON && viafb_LCD2_ON) {
614 viaparinfo->lvds_setting_info->iga_path = IGA2;
615 viaparinfo->lvds_setting_info2->iga_path = IGA2;
616 } else if (viafb_CRT_ON) {
617 crt_iga_path = IGA1;
618 } else if (viafb_LCD_ON) {
619 viaparinfo->lvds_setting_info->iga_path = IGA2;
620 } else if (viafb_DVI_ON) {
621 viaparinfo->tmds_setting_info->iga_path = IGA1;
622 }
623 }
624
625 viaparinfo->shared->iga1_devices = 0;
626 viaparinfo->shared->iga2_devices = 0;
627 if (viafb_CRT_ON) {
628 if (crt_iga_path == IGA1)
629 viaparinfo->shared->iga1_devices |= VIA_CRT;
630 else
631 viaparinfo->shared->iga2_devices |= VIA_CRT;
632 }
633
634 if (viafb_DVI_ON) {
635 if (viaparinfo->tmds_setting_info->iga_path == IGA1)
636 viaparinfo->shared->iga1_devices |= get_dvi_devices(
637 viaparinfo->chip_info->
638 tmds_chip_info.output_interface);
639 else
640 viaparinfo->shared->iga2_devices |= get_dvi_devices(
641 viaparinfo->chip_info->
642 tmds_chip_info.output_interface);
643 }
644
645 if (viafb_LCD_ON) {
646 if (viaparinfo->lvds_setting_info->iga_path == IGA1)
647 viaparinfo->shared->iga1_devices |= get_lcd_devices(
648 viaparinfo->chip_info->
649 lvds_chip_info.output_interface);
650 else
651 viaparinfo->shared->iga2_devices |= get_lcd_devices(
652 viaparinfo->chip_info->
653 lvds_chip_info.output_interface);
654 }
655
656 if (viafb_LCD2_ON) {
657 if (viaparinfo->lvds_setting_info2->iga_path == IGA1)
658 viaparinfo->shared->iga1_devices |= get_lcd_devices(
659 viaparinfo->chip_info->
660 lvds_chip_info2.output_interface);
661 else
662 viaparinfo->shared->iga2_devices |= get_lcd_devices(
663 viaparinfo->chip_info->
664 lvds_chip_info2.output_interface);
665 }
666
667 /* looks like the OLPC has its display wired to DVP1 and LVDS2 */
668 if (machine_is_olpc())
669 viaparinfo->shared->iga2_devices = VIA_DVP1 | VIA_LVDS2;
670}
671
672static void set_color_register(u8 index, u8 red, u8 green, u8 blue)
673{
674 outb(0xFF, 0x3C6); /* bit mask of palette */
675 outb(index, 0x3C8);
676 outb(red, 0x3C9);
677 outb(green, 0x3C9);
678 outb(blue, 0x3C9);
679}
680
681void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue)
682{
683 viafb_write_reg_mask(0x1A, VIASR, 0x00, 0x01);
684 set_color_register(index, red, green, blue);
685}
686
687void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue)
688{
689 viafb_write_reg_mask(0x1A, VIASR, 0x01, 0x01);
690 set_color_register(index, red, green, blue);
691}
692
693static void set_source_common(u8 index, u8 offset, u8 iga)
694{
695 u8 value, mask = 1 << offset;
696
697 switch (iga) {
698 case IGA1:
699 value = 0x00;
700 break;
701 case IGA2:
702 value = mask;
703 break;
704 default:
705 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
706 return;
707 }
708
709 via_write_reg_mask(VIACR, index, value, mask);
710}
711
712static void set_crt_source(u8 iga)
713{
714 u8 value;
715
716 switch (iga) {
717 case IGA1:
718 value = 0x00;
719 break;
720 case IGA2:
721 value = 0x40;
722 break;
723 default:
724 printk(KERN_WARNING "viafb: Unsupported source: %d\n", iga);
725 return;
726 }
727
728 via_write_reg_mask(VIASR, 0x16, value, 0x40);
729}
730
731static inline void set_ldvp0_source(u8 iga)
732{
733 set_source_common(0x6C, 7, iga);
734}
735
736static inline void set_ldvp1_source(u8 iga)
737{
738 set_source_common(0x93, 7, iga);
739}
740
741static inline void set_dvp0_source(u8 iga)
742{
743 set_source_common(0x96, 4, iga);
744}
745
746static inline void set_dvp1_source(u8 iga)
747{
748 set_source_common(0x9B, 4, iga);
749}
750
751static inline void set_lvds1_source(u8 iga)
752{
753 set_source_common(0x99, 4, iga);
754}
755
756static inline void set_lvds2_source(u8 iga)
757{
758 set_source_common(0x97, 4, iga);
759}
760
761void via_set_source(u32 devices, u8 iga)
762{
763 if (devices & VIA_LDVP0)
764 set_ldvp0_source(iga);
765 if (devices & VIA_LDVP1)
766 set_ldvp1_source(iga);
767 if (devices & VIA_DVP0)
768 set_dvp0_source(iga);
769 if (devices & VIA_CRT)
770 set_crt_source(iga);
771 if (devices & VIA_DVP1)
772 set_dvp1_source(iga);
773 if (devices & VIA_LVDS1)
774 set_lvds1_source(iga);
775 if (devices & VIA_LVDS2)
776 set_lvds2_source(iga);
777}
778
779static void set_crt_state(u8 state)
780{
781 u8 value;
782
783 switch (state) {
784 case VIA_STATE_ON:
785 value = 0x00;
786 break;
787 case VIA_STATE_STANDBY:
788 value = 0x10;
789 break;
790 case VIA_STATE_SUSPEND:
791 value = 0x20;
792 break;
793 case VIA_STATE_OFF:
794 value = 0x30;
795 break;
796 default:
797 return;
798 }
799
800 via_write_reg_mask(VIACR, 0x36, value, 0x30);
801}
802
803static void set_dvp0_state(u8 state)
804{
805 u8 value;
806
807 switch (state) {
808 case VIA_STATE_ON:
809 value = 0xC0;
810 break;
811 case VIA_STATE_OFF:
812 value = 0x00;
813 break;
814 default:
815 return;
816 }
817
818 via_write_reg_mask(VIASR, 0x1E, value, 0xC0);
819}
820
821static void set_dvp1_state(u8 state)
822{
823 u8 value;
824
825 switch (state) {
826 case VIA_STATE_ON:
827 value = 0x30;
828 break;
829 case VIA_STATE_OFF:
830 value = 0x00;
831 break;
832 default:
833 return;
834 }
835
836 via_write_reg_mask(VIASR, 0x1E, value, 0x30);
837}
838
839static void set_lvds1_state(u8 state)
840{
841 u8 value;
842
843 switch (state) {
844 case VIA_STATE_ON:
845 value = 0x03;
846 break;
847 case VIA_STATE_OFF:
848 value = 0x00;
849 break;
850 default:
851 return;
852 }
853
854 via_write_reg_mask(VIASR, 0x2A, value, 0x03);
855}
856
857static void set_lvds2_state(u8 state)
858{
859 u8 value;
860
861 switch (state) {
862 case VIA_STATE_ON:
863 value = 0x0C;
864 break;
865 case VIA_STATE_OFF:
866 value = 0x00;
867 break;
868 default:
869 return;
870 }
871
872 via_write_reg_mask(VIASR, 0x2A, value, 0x0C);
873}
874
875void via_set_state(u32 devices, u8 state)
876{
877 /*
878 TODO: Can we enable/disable these devices? How?
879 if (devices & VIA_LDVP0)
880 if (devices & VIA_LDVP1)
881 */
882 if (devices & VIA_DVP0)
883 set_dvp0_state(state);
884 if (devices & VIA_CRT)
885 set_crt_state(state);
886 if (devices & VIA_DVP1)
887 set_dvp1_state(state);
888 if (devices & VIA_LVDS1)
889 set_lvds1_state(state);
890 if (devices & VIA_LVDS2)
891 set_lvds2_state(state);
892}
893
894void via_set_sync_polarity(u32 devices, u8 polarity)
895{
896 if (polarity & ~(VIA_HSYNC_NEGATIVE | VIA_VSYNC_NEGATIVE)) {
897 printk(KERN_WARNING "viafb: Unsupported polarity: %d\n",
898 polarity);
899 return;
900 }
901
902 if (devices & VIA_CRT)
903 via_write_misc_reg_mask(polarity << 6, 0xC0);
904 if (devices & VIA_DVP1)
905 via_write_reg_mask(VIACR, 0x9B, polarity << 5, 0x60);
906 if (devices & VIA_LVDS1)
907 via_write_reg_mask(VIACR, 0x99, polarity << 5, 0x60);
908 if (devices & VIA_LVDS2)
909 via_write_reg_mask(VIACR, 0x97, polarity << 5, 0x60);
910}
911
912u32 via_parse_odev(char *input, char **end)
913{
914 char *ptr = input;
915 u32 odev = 0;
916 bool next = true;
917 int i, len;
918
919 while (next) {
920 next = false;
921 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
922 len = strlen(device_mapping[i].name);
923 if (!strncmp(ptr, device_mapping[i].name, len)) {
924 odev |= device_mapping[i].device;
925 ptr += len;
926 if (*ptr == ',') {
927 ptr++;
928 next = true;
929 }
930 }
931 }
932 }
933
934 *end = ptr;
935 return odev;
936}
937
938void via_odev_to_seq(struct seq_file *m, u32 odev)
939{
940 int i, count = 0;
941
942 for (i = 0; i < ARRAY_SIZE(device_mapping); i++) {
943 if (odev & device_mapping[i].device) {
944 if (count > 0)
945 seq_putc(m, ',');
946
947 seq_puts(m, device_mapping[i].name);
948 count++;
949 }
950 }
951
952 seq_putc(m, '\n');
953}
954
955static void load_fix_bit_crtc_reg(void)
956{
957 viafb_unlock_crt();
958
959 /* always set to 1 */
960 viafb_write_reg_mask(CR03, VIACR, 0x80, BIT7);
961 /* line compare should set all bits = 1 (extend modes) */
962 viafb_write_reg_mask(CR35, VIACR, 0x10, BIT4);
963 /* line compare should set all bits = 1 (extend modes) */
964 viafb_write_reg_mask(CR33, VIACR, 0x06, BIT0 + BIT1 + BIT2);
965 /*viafb_write_reg_mask(CR32, VIACR, 0x01, BIT0); */
966
967 viafb_lock_crt();
968
969 /* If K8M800, enable Prefetch Mode. */
970 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
971 || (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890))
972 viafb_write_reg_mask(CR33, VIACR, 0x08, BIT3);
973 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)
974 && (viaparinfo->chip_info->gfx_chip_revision == CLE266_REVISION_AX))
975 viafb_write_reg_mask(SR1A, VIASR, 0x02, BIT1);
976
977}
978
979void viafb_load_reg(int timing_value, int viafb_load_reg_num,
980 struct io_register *reg,
981 int io_type)
982{
983 int reg_mask;
984 int bit_num = 0;
985 int data;
986 int i, j;
987 int shift_next_reg;
988 int start_index, end_index, cr_index;
989 u16 get_bit;
990
991 for (i = 0; i < viafb_load_reg_num; i++) {
992 reg_mask = 0;
993 data = 0;
994 start_index = reg[i].start_bit;
995 end_index = reg[i].end_bit;
996 cr_index = reg[i].io_addr;
997
998 shift_next_reg = bit_num;
999 for (j = start_index; j <= end_index; j++) {
1000 /*if (bit_num==8) timing_value = timing_value >>8; */
1001 reg_mask = reg_mask | (BIT0 << j);
1002 get_bit = (timing_value & (BIT0 << bit_num));
1003 data =
1004 data | ((get_bit >> shift_next_reg) << start_index);
1005 bit_num++;
1006 }
1007 if (io_type == VIACR)
1008 viafb_write_reg_mask(cr_index, VIACR, data, reg_mask);
1009 else
1010 viafb_write_reg_mask(cr_index, VIASR, data, reg_mask);
1011 }
1012
1013}
1014
1015/* Write Registers */
1016void viafb_write_regx(struct io_reg RegTable[], int ItemNum)
1017{
1018 int i;
1019
1020 /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */
1021
1022 for (i = 0; i < ItemNum; i++)
1023 via_write_reg_mask(RegTable[i].port, RegTable[i].index,
1024 RegTable[i].value, RegTable[i].mask);
1025}
1026
1027void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga)
1028{
1029 int reg_value;
1030 int viafb_load_reg_num;
1031 struct io_register *reg = NULL;
1032
1033 switch (set_iga) {
1034 case IGA1:
1035 reg_value = IGA1_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1036 viafb_load_reg_num = fetch_count_reg.
1037 iga1_fetch_count_reg.reg_num;
1038 reg = fetch_count_reg.iga1_fetch_count_reg.reg;
1039 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1040 break;
1041 case IGA2:
1042 reg_value = IGA2_FETCH_COUNT_FORMULA(h_addr, bpp_byte);
1043 viafb_load_reg_num = fetch_count_reg.
1044 iga2_fetch_count_reg.reg_num;
1045 reg = fetch_count_reg.iga2_fetch_count_reg.reg;
1046 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1047 break;
1048 }
1049
1050}
1051
1052void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active)
1053{
1054 int reg_value;
1055 int viafb_load_reg_num;
1056 struct io_register *reg = NULL;
1057 int iga1_fifo_max_depth = 0, iga1_fifo_threshold =
1058 0, iga1_fifo_high_threshold = 0, iga1_display_queue_expire_num = 0;
1059 int iga2_fifo_max_depth = 0, iga2_fifo_threshold =
1060 0, iga2_fifo_high_threshold = 0, iga2_display_queue_expire_num = 0;
1061
1062 if (set_iga == IGA1) {
1063 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1064 iga1_fifo_max_depth = K800_IGA1_FIFO_MAX_DEPTH;
1065 iga1_fifo_threshold = K800_IGA1_FIFO_THRESHOLD;
1066 iga1_fifo_high_threshold =
1067 K800_IGA1_FIFO_HIGH_THRESHOLD;
1068 /* If resolution > 1280x1024, expire length = 64, else
1069 expire length = 128 */
1070 if ((hor_active > 1280) && (ver_active > 1024))
1071 iga1_display_queue_expire_num = 16;
1072 else
1073 iga1_display_queue_expire_num =
1074 K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1075
1076 }
1077
1078 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1079 iga1_fifo_max_depth = P880_IGA1_FIFO_MAX_DEPTH;
1080 iga1_fifo_threshold = P880_IGA1_FIFO_THRESHOLD;
1081 iga1_fifo_high_threshold =
1082 P880_IGA1_FIFO_HIGH_THRESHOLD;
1083 iga1_display_queue_expire_num =
1084 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1085
1086 /* If resolution > 1280x1024, expire length = 64, else
1087 expire length = 128 */
1088 if ((hor_active > 1280) && (ver_active > 1024))
1089 iga1_display_queue_expire_num = 16;
1090 else
1091 iga1_display_queue_expire_num =
1092 P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1093 }
1094
1095 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1096 iga1_fifo_max_depth = CN700_IGA1_FIFO_MAX_DEPTH;
1097 iga1_fifo_threshold = CN700_IGA1_FIFO_THRESHOLD;
1098 iga1_fifo_high_threshold =
1099 CN700_IGA1_FIFO_HIGH_THRESHOLD;
1100
1101 /* If resolution > 1280x1024, expire length = 64,
1102 else expire length = 128 */
1103 if ((hor_active > 1280) && (ver_active > 1024))
1104 iga1_display_queue_expire_num = 16;
1105 else
1106 iga1_display_queue_expire_num =
1107 CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1108 }
1109
1110 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1111 iga1_fifo_max_depth = CX700_IGA1_FIFO_MAX_DEPTH;
1112 iga1_fifo_threshold = CX700_IGA1_FIFO_THRESHOLD;
1113 iga1_fifo_high_threshold =
1114 CX700_IGA1_FIFO_HIGH_THRESHOLD;
1115 iga1_display_queue_expire_num =
1116 CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1117 }
1118
1119 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1120 iga1_fifo_max_depth = K8M890_IGA1_FIFO_MAX_DEPTH;
1121 iga1_fifo_threshold = K8M890_IGA1_FIFO_THRESHOLD;
1122 iga1_fifo_high_threshold =
1123 K8M890_IGA1_FIFO_HIGH_THRESHOLD;
1124 iga1_display_queue_expire_num =
1125 K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1126 }
1127
1128 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1129 iga1_fifo_max_depth = P4M890_IGA1_FIFO_MAX_DEPTH;
1130 iga1_fifo_threshold = P4M890_IGA1_FIFO_THRESHOLD;
1131 iga1_fifo_high_threshold =
1132 P4M890_IGA1_FIFO_HIGH_THRESHOLD;
1133 iga1_display_queue_expire_num =
1134 P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1135 }
1136
1137 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1138 iga1_fifo_max_depth = P4M900_IGA1_FIFO_MAX_DEPTH;
1139 iga1_fifo_threshold = P4M900_IGA1_FIFO_THRESHOLD;
1140 iga1_fifo_high_threshold =
1141 P4M900_IGA1_FIFO_HIGH_THRESHOLD;
1142 iga1_display_queue_expire_num =
1143 P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1144 }
1145
1146 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1147 iga1_fifo_max_depth = VX800_IGA1_FIFO_MAX_DEPTH;
1148 iga1_fifo_threshold = VX800_IGA1_FIFO_THRESHOLD;
1149 iga1_fifo_high_threshold =
1150 VX800_IGA1_FIFO_HIGH_THRESHOLD;
1151 iga1_display_queue_expire_num =
1152 VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1153 }
1154
1155 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1156 iga1_fifo_max_depth = VX855_IGA1_FIFO_MAX_DEPTH;
1157 iga1_fifo_threshold = VX855_IGA1_FIFO_THRESHOLD;
1158 iga1_fifo_high_threshold =
1159 VX855_IGA1_FIFO_HIGH_THRESHOLD;
1160 iga1_display_queue_expire_num =
1161 VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1162 }
1163
1164 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1165 iga1_fifo_max_depth = VX900_IGA1_FIFO_MAX_DEPTH;
1166 iga1_fifo_threshold = VX900_IGA1_FIFO_THRESHOLD;
1167 iga1_fifo_high_threshold =
1168 VX900_IGA1_FIFO_HIGH_THRESHOLD;
1169 iga1_display_queue_expire_num =
1170 VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM;
1171 }
1172
1173 /* Set Display FIFO Depath Select */
1174 reg_value = IGA1_FIFO_DEPTH_SELECT_FORMULA(iga1_fifo_max_depth);
1175 viafb_load_reg_num =
1176 display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg_num;
1177 reg = display_fifo_depth_reg.iga1_fifo_depth_select_reg.reg;
1178 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1179
1180 /* Set Display FIFO Threshold Select */
1181 reg_value = IGA1_FIFO_THRESHOLD_FORMULA(iga1_fifo_threshold);
1182 viafb_load_reg_num =
1183 fifo_threshold_select_reg.
1184 iga1_fifo_threshold_select_reg.reg_num;
1185 reg =
1186 fifo_threshold_select_reg.
1187 iga1_fifo_threshold_select_reg.reg;
1188 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1189
1190 /* Set FIFO High Threshold Select */
1191 reg_value =
1192 IGA1_FIFO_HIGH_THRESHOLD_FORMULA(iga1_fifo_high_threshold);
1193 viafb_load_reg_num =
1194 fifo_high_threshold_select_reg.
1195 iga1_fifo_high_threshold_select_reg.reg_num;
1196 reg =
1197 fifo_high_threshold_select_reg.
1198 iga1_fifo_high_threshold_select_reg.reg;
1199 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1200
1201 /* Set Display Queue Expire Num */
1202 reg_value =
1203 IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1204 (iga1_display_queue_expire_num);
1205 viafb_load_reg_num =
1206 display_queue_expire_num_reg.
1207 iga1_display_queue_expire_num_reg.reg_num;
1208 reg =
1209 display_queue_expire_num_reg.
1210 iga1_display_queue_expire_num_reg.reg;
1211 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIASR);
1212
1213 } else {
1214 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1215 iga2_fifo_max_depth = K800_IGA2_FIFO_MAX_DEPTH;
1216 iga2_fifo_threshold = K800_IGA2_FIFO_THRESHOLD;
1217 iga2_fifo_high_threshold =
1218 K800_IGA2_FIFO_HIGH_THRESHOLD;
1219
1220 /* If resolution > 1280x1024, expire length = 64,
1221 else expire length = 128 */
1222 if ((hor_active > 1280) && (ver_active > 1024))
1223 iga2_display_queue_expire_num = 16;
1224 else
1225 iga2_display_queue_expire_num =
1226 K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1227 }
1228
1229 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_PM800) {
1230 iga2_fifo_max_depth = P880_IGA2_FIFO_MAX_DEPTH;
1231 iga2_fifo_threshold = P880_IGA2_FIFO_THRESHOLD;
1232 iga2_fifo_high_threshold =
1233 P880_IGA2_FIFO_HIGH_THRESHOLD;
1234
1235 /* If resolution > 1280x1024, expire length = 64,
1236 else expire length = 128 */
1237 if ((hor_active > 1280) && (ver_active > 1024))
1238 iga2_display_queue_expire_num = 16;
1239 else
1240 iga2_display_queue_expire_num =
1241 P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1242 }
1243
1244 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CN700) {
1245 iga2_fifo_max_depth = CN700_IGA2_FIFO_MAX_DEPTH;
1246 iga2_fifo_threshold = CN700_IGA2_FIFO_THRESHOLD;
1247 iga2_fifo_high_threshold =
1248 CN700_IGA2_FIFO_HIGH_THRESHOLD;
1249
1250 /* If resolution > 1280x1024, expire length = 64,
1251 else expire length = 128 */
1252 if ((hor_active > 1280) && (ver_active > 1024))
1253 iga2_display_queue_expire_num = 16;
1254 else
1255 iga2_display_queue_expire_num =
1256 CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1257 }
1258
1259 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1260 iga2_fifo_max_depth = CX700_IGA2_FIFO_MAX_DEPTH;
1261 iga2_fifo_threshold = CX700_IGA2_FIFO_THRESHOLD;
1262 iga2_fifo_high_threshold =
1263 CX700_IGA2_FIFO_HIGH_THRESHOLD;
1264 iga2_display_queue_expire_num =
1265 CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1266 }
1267
1268 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K8M890) {
1269 iga2_fifo_max_depth = K8M890_IGA2_FIFO_MAX_DEPTH;
1270 iga2_fifo_threshold = K8M890_IGA2_FIFO_THRESHOLD;
1271 iga2_fifo_high_threshold =
1272 K8M890_IGA2_FIFO_HIGH_THRESHOLD;
1273 iga2_display_queue_expire_num =
1274 K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1275 }
1276
1277 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M890) {
1278 iga2_fifo_max_depth = P4M890_IGA2_FIFO_MAX_DEPTH;
1279 iga2_fifo_threshold = P4M890_IGA2_FIFO_THRESHOLD;
1280 iga2_fifo_high_threshold =
1281 P4M890_IGA2_FIFO_HIGH_THRESHOLD;
1282 iga2_display_queue_expire_num =
1283 P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1284 }
1285
1286 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_P4M900) {
1287 iga2_fifo_max_depth = P4M900_IGA2_FIFO_MAX_DEPTH;
1288 iga2_fifo_threshold = P4M900_IGA2_FIFO_THRESHOLD;
1289 iga2_fifo_high_threshold =
1290 P4M900_IGA2_FIFO_HIGH_THRESHOLD;
1291 iga2_display_queue_expire_num =
1292 P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1293 }
1294
1295 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX800) {
1296 iga2_fifo_max_depth = VX800_IGA2_FIFO_MAX_DEPTH;
1297 iga2_fifo_threshold = VX800_IGA2_FIFO_THRESHOLD;
1298 iga2_fifo_high_threshold =
1299 VX800_IGA2_FIFO_HIGH_THRESHOLD;
1300 iga2_display_queue_expire_num =
1301 VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1302 }
1303
1304 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX855) {
1305 iga2_fifo_max_depth = VX855_IGA2_FIFO_MAX_DEPTH;
1306 iga2_fifo_threshold = VX855_IGA2_FIFO_THRESHOLD;
1307 iga2_fifo_high_threshold =
1308 VX855_IGA2_FIFO_HIGH_THRESHOLD;
1309 iga2_display_queue_expire_num =
1310 VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1311 }
1312
1313 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_VX900) {
1314 iga2_fifo_max_depth = VX900_IGA2_FIFO_MAX_DEPTH;
1315 iga2_fifo_threshold = VX900_IGA2_FIFO_THRESHOLD;
1316 iga2_fifo_high_threshold =
1317 VX900_IGA2_FIFO_HIGH_THRESHOLD;
1318 iga2_display_queue_expire_num =
1319 VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM;
1320 }
1321
1322 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800) {
1323 /* Set Display FIFO Depath Select */
1324 reg_value =
1325 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth)
1326 - 1;
1327 /* Patch LCD in IGA2 case */
1328 viafb_load_reg_num =
1329 display_fifo_depth_reg.
1330 iga2_fifo_depth_select_reg.reg_num;
1331 reg =
1332 display_fifo_depth_reg.
1333 iga2_fifo_depth_select_reg.reg;
1334 viafb_load_reg(reg_value,
1335 viafb_load_reg_num, reg, VIACR);
1336 } else {
1337
1338 /* Set Display FIFO Depath Select */
1339 reg_value =
1340 IGA2_FIFO_DEPTH_SELECT_FORMULA(iga2_fifo_max_depth);
1341 viafb_load_reg_num =
1342 display_fifo_depth_reg.
1343 iga2_fifo_depth_select_reg.reg_num;
1344 reg =
1345 display_fifo_depth_reg.
1346 iga2_fifo_depth_select_reg.reg;
1347 viafb_load_reg(reg_value,
1348 viafb_load_reg_num, reg, VIACR);
1349 }
1350
1351 /* Set Display FIFO Threshold Select */
1352 reg_value = IGA2_FIFO_THRESHOLD_FORMULA(iga2_fifo_threshold);
1353 viafb_load_reg_num =
1354 fifo_threshold_select_reg.
1355 iga2_fifo_threshold_select_reg.reg_num;
1356 reg =
1357 fifo_threshold_select_reg.
1358 iga2_fifo_threshold_select_reg.reg;
1359 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1360
1361 /* Set FIFO High Threshold Select */
1362 reg_value =
1363 IGA2_FIFO_HIGH_THRESHOLD_FORMULA(iga2_fifo_high_threshold);
1364 viafb_load_reg_num =
1365 fifo_high_threshold_select_reg.
1366 iga2_fifo_high_threshold_select_reg.reg_num;
1367 reg =
1368 fifo_high_threshold_select_reg.
1369 iga2_fifo_high_threshold_select_reg.reg;
1370 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1371
1372 /* Set Display Queue Expire Num */
1373 reg_value =
1374 IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA
1375 (iga2_display_queue_expire_num);
1376 viafb_load_reg_num =
1377 display_queue_expire_num_reg.
1378 iga2_display_queue_expire_num_reg.reg_num;
1379 reg =
1380 display_queue_expire_num_reg.
1381 iga2_display_queue_expire_num_reg.reg;
1382 viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR);
1383
1384 }
1385
1386}
1387
1388static struct via_pll_config get_pll_config(struct pll_limit *limits, int size,
1389 int clk)
1390{
1391 struct via_pll_config cur, up, down, best = {0, 1, 0};
1392 const u32 f0 = 14318180; /* X1 frequency */
1393 int i, f;
1394
1395 for (i = 0; i < size; i++) {
1396 cur.rshift = limits[i].rshift;
1397 cur.divisor = limits[i].divisor;
1398 cur.multiplier = clk / ((f0 / cur.divisor)>>cur.rshift);
1399 f = abs(get_pll_output_frequency(f0, cur) - clk);
1400 up = down = cur;
1401 up.multiplier++;
1402 down.multiplier--;
1403 if (abs(get_pll_output_frequency(f0, up) - clk) < f)
1404 cur = up;
1405 else if (abs(get_pll_output_frequency(f0, down) - clk) < f)
1406 cur = down;
1407
1408 if (cur.multiplier < limits[i].multiplier_min)
1409 cur.multiplier = limits[i].multiplier_min;
1410 else if (cur.multiplier > limits[i].multiplier_max)
1411 cur.multiplier = limits[i].multiplier_max;
1412
1413 f = abs(get_pll_output_frequency(f0, cur) - clk);
1414 if (f < abs(get_pll_output_frequency(f0, best) - clk))
1415 best = cur;
1416 }
1417
1418 return best;
1419}
1420
1421static struct via_pll_config get_best_pll_config(int clk)
1422{
1423 struct via_pll_config config;
1424
1425 switch (viaparinfo->chip_info->gfx_chip_name) {
1426 case UNICHROME_CLE266:
1427 case UNICHROME_K400:
1428 config = get_pll_config(cle266_pll_limits,
1429 ARRAY_SIZE(cle266_pll_limits), clk);
1430 break;
1431 case UNICHROME_K800:
1432 case UNICHROME_PM800:
1433 case UNICHROME_CN700:
1434 config = get_pll_config(k800_pll_limits,
1435 ARRAY_SIZE(k800_pll_limits), clk);
1436 break;
1437 case UNICHROME_CX700:
1438 case UNICHROME_CN750:
1439 case UNICHROME_K8M890:
1440 case UNICHROME_P4M890:
1441 case UNICHROME_P4M900:
1442 case UNICHROME_VX800:
1443 config = get_pll_config(cx700_pll_limits,
1444 ARRAY_SIZE(cx700_pll_limits), clk);
1445 break;
1446 case UNICHROME_VX855:
1447 case UNICHROME_VX900:
1448 config = get_pll_config(vx855_pll_limits,
1449 ARRAY_SIZE(vx855_pll_limits), clk);
1450 break;
1451 }
1452
1453 return config;
1454}
1455
1456/* Set VCLK*/
1457void viafb_set_vclock(u32 clk, int set_iga)
1458{
1459 struct via_pll_config config = get_best_pll_config(clk);
1460
1461 if (set_iga == IGA1)
1462 clock.set_primary_pll(config);
1463 if (set_iga == IGA2)
1464 clock.set_secondary_pll(config);
1465
1466 /* Fire! */
1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
1468}
1469
1470struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
1471 u16 cxres, u16 cyres)
1472{
1473 struct via_display_timing timing;
1474 u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
1475
1476 timing.hor_addr = cxres;
1477 timing.hor_sync_start = timing.hor_addr + var->right_margin + dx;
1478 timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
1479 timing.hor_total = timing.hor_sync_end + var->left_margin + dx;
1480 timing.hor_blank_start = timing.hor_addr + dx;
1481 timing.hor_blank_end = timing.hor_total - dx;
1482 timing.ver_addr = cyres;
1483 timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy;
1484 timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
1485 timing.ver_total = timing.ver_sync_end + var->upper_margin + dy;
1486 timing.ver_blank_start = timing.ver_addr + dy;
1487 timing.ver_blank_end = timing.ver_total - dy;
1488 return timing;
1489}
1490
1491void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
1492 u16 cxres, u16 cyres, int iga)
1493{
1494 struct via_display_timing crt_reg = var_to_timing(var,
1495 cxres ? cxres : var->xres, cyres ? cyres : var->yres);
1496
1497 if (iga == IGA1)
1498 via_set_primary_timing(&crt_reg);
1499 else if (iga == IGA2)
1500 via_set_secondary_timing(&crt_reg);
1501
1502 viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga);
1503 if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266
1504 && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)
1505 viafb_load_FIFO_reg(iga, var->xres, var->yres);
1506
1507 viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga);
1508}
1509
1510void viafb_init_chip_info(int chip_type)
1511{
1512 via_clock_init(&clock, chip_type);
1513 init_gfx_chip_info(chip_type);
1514 init_tmds_chip_info();
1515 init_lvds_chip_info();
1516
1517 /*Set IGA path for each device */
1518 viafb_set_iga_path();
1519
1520 viaparinfo->lvds_setting_info->display_method = viafb_lcd_dsp_method;
1521 viaparinfo->lvds_setting_info->lcd_mode = viafb_lcd_mode;
1522 viaparinfo->lvds_setting_info2->display_method =
1523 viaparinfo->lvds_setting_info->display_method;
1524 viaparinfo->lvds_setting_info2->lcd_mode =
1525 viaparinfo->lvds_setting_info->lcd_mode;
1526}
1527
1528void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
1529{
1530 if (flag == 0) {
1531 viaparinfo->tmds_setting_info->h_active = hres;
1532 viaparinfo->tmds_setting_info->v_active = vres;
1533 } else {
1534
1535 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
1536 viaparinfo->tmds_setting_info->h_active = hres;
1537 viaparinfo->tmds_setting_info->v_active = vres;
1538 }
1539
1540 }
1541}
1542
1543static void init_gfx_chip_info(int chip_type)
1544{
1545 u8 tmp;
1546
1547 viaparinfo->chip_info->gfx_chip_name = chip_type;
1548
1549 /* Check revision of CLE266 Chip */
1550 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
1551 /* CR4F only define in CLE266.CX chip */
1552 tmp = viafb_read_reg(VIACR, CR4F);
1553 viafb_write_reg(CR4F, VIACR, 0x55);
1554 if (viafb_read_reg(VIACR, CR4F) != 0x55)
1555 viaparinfo->chip_info->gfx_chip_revision =
1556 CLE266_REVISION_AX;
1557 else
1558 viaparinfo->chip_info->gfx_chip_revision =
1559 CLE266_REVISION_CX;
1560 /* restore orignal CR4F value */
1561 viafb_write_reg(CR4F, VIACR, tmp);
1562 }
1563
1564 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
1565 tmp = viafb_read_reg(VIASR, SR43);
1566 DEBUG_MSG(KERN_INFO "SR43:%X\n", tmp);
1567 if (tmp & 0x02) {
1568 viaparinfo->chip_info->gfx_chip_revision =
1569 CX700_REVISION_700M2;
1570 } else if (tmp & 0x40) {
1571 viaparinfo->chip_info->gfx_chip_revision =
1572 CX700_REVISION_700M;
1573 } else {
1574 viaparinfo->chip_info->gfx_chip_revision =
1575 CX700_REVISION_700;
1576 }
1577 }
1578
1579 /* Determine which 2D engine we have */
1580 switch (viaparinfo->chip_info->gfx_chip_name) {
1581 case UNICHROME_VX800:
1582 case UNICHROME_VX855:
1583 case UNICHROME_VX900:
1584 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1;
1585 break;
1586 case UNICHROME_K8M890:
1587 case UNICHROME_P4M900:
1588 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5;
1589 break;
1590 default:
1591 viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2;
1592 break;
1593 }
1594}
1595
1596static void init_tmds_chip_info(void)
1597{
1598 viafb_tmds_trasmitter_identify();
1599
1600 if (INTERFACE_NONE == viaparinfo->chip_info->tmds_chip_info.
1601 output_interface) {
1602 switch (viaparinfo->chip_info->gfx_chip_name) {
1603 case UNICHROME_CX700:
1604 {
1605 /* we should check support by hardware layout.*/
1606 if ((viafb_display_hardware_layout ==
1607 HW_LAYOUT_DVI_ONLY)
1608 || (viafb_display_hardware_layout ==
1609 HW_LAYOUT_LCD_DVI)) {
1610 viaparinfo->chip_info->tmds_chip_info.
1611 output_interface = INTERFACE_TMDS;
1612 } else {
1613 viaparinfo->chip_info->tmds_chip_info.
1614 output_interface =
1615 INTERFACE_NONE;
1616 }
1617 break;
1618 }
1619 case UNICHROME_K8M890:
1620 case UNICHROME_P4M900:
1621 case UNICHROME_P4M890:
1622 /* TMDS on PCIE, we set DFPLOW as default. */
1623 viaparinfo->chip_info->tmds_chip_info.output_interface =
1624 INTERFACE_DFP_LOW;
1625 break;
1626 default:
1627 {
1628 /* set DVP1 default for DVI */
1629 viaparinfo->chip_info->tmds_chip_info
1630 .output_interface = INTERFACE_DVP1;
1631 }
1632 }
1633 }
1634
1635 DEBUG_MSG(KERN_INFO "TMDS Chip = %d\n",
1636 viaparinfo->chip_info->tmds_chip_info.tmds_chip_name);
1637 viafb_init_dvi_size(&viaparinfo->shared->chip_info.tmds_chip_info,
1638 &viaparinfo->shared->tmds_setting_info);
1639}
1640
1641static void init_lvds_chip_info(void)
1642{
1643 viafb_lvds_trasmitter_identify();
1644 viafb_init_lcd_size();
1645 viafb_init_lvds_output_interface(&viaparinfo->chip_info->lvds_chip_info,
1646 viaparinfo->lvds_setting_info);
1647 if (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1648 viafb_init_lvds_output_interface(&viaparinfo->chip_info->
1649 lvds_chip_info2, viaparinfo->lvds_setting_info2);
1650 }
1651 /*If CX700,two singel LCD, we need to reassign
1652 LCD interface to different LVDS port */
1653 if ((UNICHROME_CX700 == viaparinfo->chip_info->gfx_chip_name)
1654 && (HW_LAYOUT_LCD1_LCD2 == viafb_display_hardware_layout)) {
1655 if ((INTEGRATED_LVDS == viaparinfo->chip_info->lvds_chip_info.
1656 lvds_chip_name) && (INTEGRATED_LVDS ==
1657 viaparinfo->chip_info->
1658 lvds_chip_info2.lvds_chip_name)) {
1659 viaparinfo->chip_info->lvds_chip_info.output_interface =
1660 INTERFACE_LVDS0;
1661 viaparinfo->chip_info->lvds_chip_info2.
1662 output_interface =
1663 INTERFACE_LVDS1;
1664 }
1665 }
1666
1667 DEBUG_MSG(KERN_INFO "LVDS Chip = %d\n",
1668 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
1669 DEBUG_MSG(KERN_INFO "LVDS1 output_interface = %d\n",
1670 viaparinfo->chip_info->lvds_chip_info.output_interface);
1671 DEBUG_MSG(KERN_INFO "LVDS2 output_interface = %d\n",
1672 viaparinfo->chip_info->lvds_chip_info.output_interface);
1673}
1674
1675void viafb_init_dac(int set_iga)
1676{
1677 int i;
1678 u8 tmp;
1679
1680 if (set_iga == IGA1) {
1681 /* access Primary Display's LUT */
1682 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
1683 /* turn off LCK */
1684 viafb_write_reg_mask(SR1B, VIASR, 0x00, BIT7 + BIT6);
1685 for (i = 0; i < 256; i++) {
1686 write_dac_reg(i, palLUT_table[i].red,
1687 palLUT_table[i].green,
1688 palLUT_table[i].blue);
1689 }
1690 /* turn on LCK */
1691 viafb_write_reg_mask(SR1B, VIASR, 0xC0, BIT7 + BIT6);
1692 } else {
1693 tmp = viafb_read_reg(VIACR, CR6A);
1694 /* access Secondary Display's LUT */
1695 viafb_write_reg_mask(CR6A, VIACR, 0x40, BIT6);
1696 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
1697 for (i = 0; i < 256; i++) {
1698 write_dac_reg(i, palLUT_table[i].red,
1699 palLUT_table[i].green,
1700 palLUT_table[i].blue);
1701 }
1702 /* set IGA1 DAC for default */
1703 viafb_write_reg_mask(SR1A, VIASR, 0x00, BIT0);
1704 viafb_write_reg(CR6A, VIACR, tmp);
1705 }
1706}
1707
1708static void device_screen_off(void)
1709{
1710 /* turn off CRT screen (IGA1) */
1711 viafb_write_reg_mask(SR01, VIASR, 0x20, BIT5);
1712}
1713
1714static void device_screen_on(void)
1715{
1716 /* turn on CRT screen (IGA1) */
1717 viafb_write_reg_mask(SR01, VIASR, 0x00, BIT5);
1718}
1719
1720static void set_display_channel(void)
1721{
1722 /*If viafb_LCD2_ON, on cx700, internal lvds's information
1723 is keeped on lvds_setting_info2 */
1724 if (viafb_LCD2_ON &&
1725 viaparinfo->lvds_setting_info2->device_lcd_dualedge) {
1726 /* For dual channel LCD: */
1727 /* Set to Dual LVDS channel. */
1728 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
1729 } else if (viafb_LCD_ON && viafb_DVI_ON) {
1730 /* For LCD+DFP: */
1731 /* Set to LVDS1 + TMDS channel. */
1732 viafb_write_reg_mask(CRD2, VIACR, 0x10, BIT4 + BIT5);
1733 } else if (viafb_DVI_ON) {
1734 /* Set to single TMDS channel. */
1735 viafb_write_reg_mask(CRD2, VIACR, 0x30, BIT4 + BIT5);
1736 } else if (viafb_LCD_ON) {
1737 if (viaparinfo->lvds_setting_info->device_lcd_dualedge) {
1738 /* For dual channel LCD: */
1739 /* Set to Dual LVDS channel. */
1740 viafb_write_reg_mask(CRD2, VIACR, 0x20, BIT4 + BIT5);
1741 } else {
1742 /* Set to LVDS0 + LVDS1 channel. */
1743 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT4 + BIT5);
1744 }
1745 }
1746}
1747
1748static u8 get_sync(struct fb_var_screeninfo *var)
1749{
1750 u8 polarity = 0;
1751
1752 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
1753 polarity |= VIA_HSYNC_NEGATIVE;
1754 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
1755 polarity |= VIA_VSYNC_NEGATIVE;
1756 return polarity;
1757}
1758
1759static void hw_init(void)
1760{
1761 int i;
1762
1763 inb(VIAStatus);
1764 outb(0x00, VIAAR);
1765
1766 /* Write Common Setting for Video Mode */
1767 viafb_write_regx(common_vga, ARRAY_SIZE(common_vga));
1768 switch (viaparinfo->chip_info->gfx_chip_name) {
1769 case UNICHROME_CLE266:
1770 viafb_write_regx(CLE266_ModeXregs, NUM_TOTAL_CLE266_ModeXregs);
1771 break;
1772
1773 case UNICHROME_K400:
1774 viafb_write_regx(KM400_ModeXregs, NUM_TOTAL_KM400_ModeXregs);
1775 break;
1776
1777 case UNICHROME_K800:
1778 case UNICHROME_PM800:
1779 viafb_write_regx(CN400_ModeXregs, NUM_TOTAL_CN400_ModeXregs);
1780 break;
1781
1782 case UNICHROME_CN700:
1783 case UNICHROME_K8M890:
1784 case UNICHROME_P4M890:
1785 case UNICHROME_P4M900:
1786 viafb_write_regx(CN700_ModeXregs, NUM_TOTAL_CN700_ModeXregs);
1787 break;
1788
1789 case UNICHROME_CX700:
1790 case UNICHROME_VX800:
1791 viafb_write_regx(CX700_ModeXregs, NUM_TOTAL_CX700_ModeXregs);
1792 break;
1793
1794 case UNICHROME_VX855:
1795 case UNICHROME_VX900:
1796 viafb_write_regx(VX855_ModeXregs, NUM_TOTAL_VX855_ModeXregs);
1797 break;
1798 }
1799
1800 /* magic required on VX900 for correct modesetting on IGA1 */
1801 via_write_reg_mask(VIACR, 0x45, 0x00, 0x01);
1802
1803 /* probably this should go to the scaling code one day */
1804 via_write_reg_mask(VIACR, 0xFD, 0, 0x80); /* VX900 hw scale on IGA2 */
1805 viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
1806
1807 /* Fill VPIT Parameters */
1808 /* Write Misc Register */
1809 outb(VPIT.Misc, VIA_MISC_REG_WRITE);
1810
1811 /* Write Sequencer */
1812 for (i = 1; i <= StdSR; i++)
1813 via_write_reg(VIASR, i, VPIT.SR[i - 1]);
1814
1815 viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2);
1816
1817 /* Write Graphic Controller */
1818 for (i = 0; i < StdGR; i++)
1819 via_write_reg(VIAGR, i, VPIT.GR[i]);
1820
1821 /* Write Attribute Controller */
1822 for (i = 0; i < StdAR; i++) {
1823 inb(VIAStatus);
1824 outb(i, VIAAR);
1825 outb(VPIT.AR[i], VIAAR);
1826 }
1827
1828 inb(VIAStatus);
1829 outb(0x20, VIAAR);
1830
1831 load_fix_bit_crtc_reg();
1832}
1833
1834int viafb_setmode(void)
1835{
1836 int j, cxres = 0, cyres = 0;
1837 int port;
1838 u32 devices = viaparinfo->shared->iga1_devices
1839 | viaparinfo->shared->iga2_devices;
1840 u8 value, index, mask;
1841 struct fb_var_screeninfo var2;
1842
1843 device_screen_off();
1844 device_off();
1845 via_set_state(devices, VIA_STATE_OFF);
1846
1847 hw_init();
1848
1849 /* Update Patch Register */
1850
1851 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266
1852 || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400)
1853 && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) {
1854 for (j = 0; j < res_patch_table[0].table_length; j++) {
1855 index = res_patch_table[0].io_reg_table[j].index;
1856 port = res_patch_table[0].io_reg_table[j].port;
1857 value = res_patch_table[0].io_reg_table[j].value;
1858 mask = res_patch_table[0].io_reg_table[j].mask;
1859 viafb_write_reg_mask(index, port, value, mask);
1860 }
1861 }
1862
1863 via_set_primary_pitch(viafbinfo->fix.line_length);
1864 via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length
1865 : viafbinfo->fix.line_length);
1866 via_set_primary_color_depth(viaparinfo->depth);
1867 via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth
1868 : viaparinfo->depth);
1869 via_set_source(viaparinfo->shared->iga1_devices, IGA1);
1870 via_set_source(viaparinfo->shared->iga2_devices, IGA2);
1871 if (viaparinfo->shared->iga2_devices)
1872 enable_second_display_channel();
1873 else
1874 disable_second_display_channel();
1875
1876 /* Update Refresh Rate Setting */
1877
1878 /* Clear On Screen */
1879
1880 if (viafb_dual_fb) {
1881 var2 = viafbinfo1->var;
1882 } else if (viafb_SAMM_ON) {
1883 viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
1884 viafb_second_xres, viafb_second_yres, viafb_refresh1));
1885 cxres = viafbinfo->var.xres;
1886 cyres = viafbinfo->var.yres;
1887 var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
1888 }
1889
1890 /* CRT set mode */
1891 if (viafb_CRT_ON) {
1892 if (viaparinfo->shared->iga2_devices & VIA_CRT
1893 && viafb_SAMM_ON)
1894 viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2);
1895 else
1896 viafb_fill_crtc_timing(&viafbinfo->var, 0, 0,
1897 (viaparinfo->shared->iga1_devices & VIA_CRT)
1898 ? IGA1 : IGA2);
1899
1900 /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode
1901 to 8 alignment (1368),there is several pixels (2 pixels)
1902 on right side of screen. */
1903 if (viafbinfo->var.xres % 8) {
1904 viafb_unlock_crt();
1905 viafb_write_reg(CR02, VIACR,
1906 viafb_read_reg(VIACR, CR02) - 1);
1907 viafb_lock_crt();
1908 }
1909 }
1910
1911 if (viafb_DVI_ON) {
1912 if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
1913 && viafb_SAMM_ON)
1914 viafb_dvi_set_mode(&var2, cxres, cyres, IGA2);
1915 else
1916 viafb_dvi_set_mode(&viafbinfo->var, 0, 0,
1917 viaparinfo->tmds_setting_info->iga_path);
1918 }
1919
1920 if (viafb_LCD_ON) {
1921 if (viafb_SAMM_ON &&
1922 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
1923 viafb_lcd_set_mode(&var2, cxres, cyres,
1924 viaparinfo->lvds_setting_info,
1925 &viaparinfo->chip_info->lvds_chip_info);
1926 } else {
1927 /* IGA1 doesn't have LCD scaling, so set it center. */
1928 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
1929 viaparinfo->lvds_setting_info->display_method =
1930 LCD_CENTERING;
1931 }
1932 viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1933 viaparinfo->lvds_setting_info,
1934 &viaparinfo->chip_info->lvds_chip_info);
1935 }
1936 }
1937 if (viafb_LCD2_ON) {
1938 if (viafb_SAMM_ON &&
1939 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
1940 viafb_lcd_set_mode(&var2, cxres, cyres,
1941 viaparinfo->lvds_setting_info2,
1942 &viaparinfo->chip_info->lvds_chip_info2);
1943 } else {
1944 /* IGA1 doesn't have LCD scaling, so set it center. */
1945 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
1946 viaparinfo->lvds_setting_info2->display_method =
1947 LCD_CENTERING;
1948 }
1949 viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1950 viaparinfo->lvds_setting_info2,
1951 &viaparinfo->chip_info->lvds_chip_info2);
1952 }
1953 }
1954
1955 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
1956 && (viafb_LCD_ON || viafb_DVI_ON))
1957 set_display_channel();
1958
1959 /* If set mode normally, save resolution information for hot-plug . */
1960 if (!viafb_hotplug) {
1961 viafb_hotplug_Xres = viafbinfo->var.xres;
1962 viafb_hotplug_Yres = viafbinfo->var.yres;
1963 viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel;
1964 viafb_hotplug_refresh = viafb_refresh;
1965
1966 if (viafb_DVI_ON)
1967 viafb_DeviceStatus = DVI_Device;
1968 else
1969 viafb_DeviceStatus = CRT_Device;
1970 }
1971 device_on();
1972 if (!viafb_SAMM_ON)
1973 via_set_sync_polarity(devices, get_sync(&viafbinfo->var));
1974 else {
1975 via_set_sync_polarity(viaparinfo->shared->iga1_devices,
1976 get_sync(&viafbinfo->var));
1977 via_set_sync_polarity(viaparinfo->shared->iga2_devices,
1978 get_sync(&var2));
1979 }
1980
1981 clock.set_engine_pll_state(VIA_STATE_ON);
1982 clock.set_primary_clock_source(VIA_CLKSRC_X1, true);
1983 clock.set_secondary_clock_source(VIA_CLKSRC_X1, true);
1984
1985#ifdef CONFIG_FB_VIA_X_COMPATIBILITY
1986 clock.set_primary_pll_state(VIA_STATE_ON);
1987 clock.set_primary_clock_state(VIA_STATE_ON);
1988 clock.set_secondary_pll_state(VIA_STATE_ON);
1989 clock.set_secondary_clock_state(VIA_STATE_ON);
1990#else
1991 if (viaparinfo->shared->iga1_devices) {
1992 clock.set_primary_pll_state(VIA_STATE_ON);
1993 clock.set_primary_clock_state(VIA_STATE_ON);
1994 } else {
1995 clock.set_primary_pll_state(VIA_STATE_OFF);
1996 clock.set_primary_clock_state(VIA_STATE_OFF);
1997 }
1998
1999 if (viaparinfo->shared->iga2_devices) {
2000 clock.set_secondary_pll_state(VIA_STATE_ON);
2001 clock.set_secondary_clock_state(VIA_STATE_ON);
2002 } else {
2003 clock.set_secondary_pll_state(VIA_STATE_OFF);
2004 clock.set_secondary_clock_state(VIA_STATE_OFF);
2005 }
2006#endif /*CONFIG_FB_VIA_X_COMPATIBILITY*/
2007
2008 via_set_state(devices, VIA_STATE_ON);
2009 device_screen_on();
2010 return 1;
2011}
2012
2013int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2014{
2015 const struct fb_videomode *best;
2016
2017 best = viafb_get_best_mode(hres, vres, long_refresh);
2018 if (!best)
2019 return 60;
2020
2021 if (abs(best->refresh - long_refresh) > 3) {
2022 if (hres == 1200 && vres == 900)
2023 return 49; /* OLPC DCON only supports 50 Hz */
2024 else
2025 return 60;
2026 }
2027
2028 return best->refresh;
2029}
2030
2031static void device_off(void)
2032{
2033 viafb_dvi_disable();
2034 viafb_lcd_disable();
2035}
2036
2037static void device_on(void)
2038{
2039 if (viafb_DVI_ON == 1)
2040 viafb_dvi_enable();
2041 if (viafb_LCD_ON == 1)
2042 viafb_lcd_enable();
2043}
2044
2045static void enable_second_display_channel(void)
2046{
2047 /* to enable second display channel. */
2048 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2049 viafb_write_reg_mask(CR6A, VIACR, BIT7, BIT7);
2050 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2051}
2052
2053static void disable_second_display_channel(void)
2054{
2055 /* to disable second display channel. */
2056 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT6);
2057 viafb_write_reg_mask(CR6A, VIACR, 0x00, BIT7);
2058 viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6);
2059}
2060
2061void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2062 *p_gfx_dpa_setting)
2063{
2064 switch (output_interface) {
2065 case INTERFACE_DVP0:
2066 {
2067 /* DVP0 Clock Polarity and Adjust: */
2068 viafb_write_reg_mask(CR96, VIACR,
2069 p_gfx_dpa_setting->DVP0, 0x0F);
2070
2071 /* DVP0 Clock and Data Pads Driving: */
2072 viafb_write_reg_mask(SR1E, VIASR,
2073 p_gfx_dpa_setting->DVP0ClockDri_S, BIT2);
2074 viafb_write_reg_mask(SR2A, VIASR,
2075 p_gfx_dpa_setting->DVP0ClockDri_S1,
2076 BIT4);
2077 viafb_write_reg_mask(SR1B, VIASR,
2078 p_gfx_dpa_setting->DVP0DataDri_S, BIT1);
2079 viafb_write_reg_mask(SR2A, VIASR,
2080 p_gfx_dpa_setting->DVP0DataDri_S1, BIT5);
2081 break;
2082 }
2083
2084 case INTERFACE_DVP1:
2085 {
2086 /* DVP1 Clock Polarity and Adjust: */
2087 viafb_write_reg_mask(CR9B, VIACR,
2088 p_gfx_dpa_setting->DVP1, 0x0F);
2089
2090 /* DVP1 Clock and Data Pads Driving: */
2091 viafb_write_reg_mask(SR65, VIASR,
2092 p_gfx_dpa_setting->DVP1Driving, 0x0F);
2093 break;
2094 }
2095
2096 case INTERFACE_DFP_HIGH:
2097 {
2098 viafb_write_reg_mask(CR97, VIACR,
2099 p_gfx_dpa_setting->DFPHigh, 0x0F);
2100 break;
2101 }
2102
2103 case INTERFACE_DFP_LOW:
2104 {
2105 viafb_write_reg_mask(CR99, VIACR,
2106 p_gfx_dpa_setting->DFPLow, 0x0F);
2107 break;
2108 }
2109
2110 case INTERFACE_DFP:
2111 {
2112 viafb_write_reg_mask(CR97, VIACR,
2113 p_gfx_dpa_setting->DFPHigh, 0x0F);
2114 viafb_write_reg_mask(CR99, VIACR,
2115 p_gfx_dpa_setting->DFPLow, 0x0F);
2116 break;
2117 }
2118 }
2119}
2120
2121void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
2122 const struct fb_videomode *mode)
2123{
2124 var->pixclock = mode->pixclock;
2125 var->xres = mode->xres;
2126 var->yres = mode->yres;
2127 var->left_margin = mode->left_margin;
2128 var->right_margin = mode->right_margin;
2129 var->hsync_len = mode->hsync_len;
2130 var->upper_margin = mode->upper_margin;
2131 var->lower_margin = mode->lower_margin;
2132 var->vsync_len = mode->vsync_len;
2133 var->sync = mode->sync;
2134}
diff --git a/drivers/video/fbdev/via/hw.h b/drivers/video/fbdev/via/hw.h
new file mode 100644
index 000000000000..3be073c58b03
--- /dev/null
+++ b/drivers/video/fbdev/via/hw.h
@@ -0,0 +1,676 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __HW_H__
23#define __HW_H__
24
25#include <linux/seq_file.h>
26
27#include "viamode.h"
28#include "global.h"
29#include "via_modesetting.h"
30
31#define viafb_read_reg(p, i) via_read_reg(p, i)
32#define viafb_write_reg(i, p, d) via_write_reg(p, i, d)
33#define viafb_write_reg_mask(i, p, d, m) via_write_reg_mask(p, i, d, m)
34
35/* VIA output devices */
36#define VIA_LDVP0 0x00000001
37#define VIA_LDVP1 0x00000002
38#define VIA_DVP0 0x00000004
39#define VIA_CRT 0x00000010
40#define VIA_DVP1 0x00000020
41#define VIA_LVDS1 0x00000040
42#define VIA_LVDS2 0x00000080
43
44/* VIA output device power states */
45#define VIA_STATE_ON 0
46#define VIA_STATE_STANDBY 1
47#define VIA_STATE_SUSPEND 2
48#define VIA_STATE_OFF 3
49
50/* VIA output device sync polarity */
51#define VIA_HSYNC_NEGATIVE 0x01
52#define VIA_VSYNC_NEGATIVE 0x02
53
54/**********************************************************/
55/* Definition IGA2 Design Method of CRTC Shadow Registers */
56/**********************************************************/
57#define IGA2_HOR_TOTAL_SHADOW_FORMULA(x) ((x/8)-5)
58#define IGA2_HOR_BLANK_END_SHADOW_FORMULA(x, y) (((x+y)/8)-1)
59#define IGA2_VER_TOTAL_SHADOW_FORMULA(x) ((x)-2)
60#define IGA2_VER_ADDR_SHADOW_FORMULA(x) ((x)-1)
61#define IGA2_VER_BLANK_START_SHADOW_FORMULA(x) ((x)-1)
62#define IGA2_VER_BLANK_END_SHADOW_FORMULA(x, y) ((x+y)-1)
63#define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x)
64#define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y)
65
66/* Define Register Number for IGA2 Shadow CRTC Timing */
67
68/* location: {CR6D,0,7},{CR71,3,3} */
69#define IGA2_SHADOW_HOR_TOTAL_REG_NUM 2
70/* location: {CR6E,0,7} */
71#define IGA2_SHADOW_HOR_BLANK_END_REG_NUM 1
72/* location: {CR6F,0,7},{CR71,0,2} */
73#define IGA2_SHADOW_VER_TOTAL_REG_NUM 2
74/* location: {CR70,0,7},{CR71,4,6} */
75#define IGA2_SHADOW_VER_ADDR_REG_NUM 2
76/* location: {CR72,0,7},{CR74,4,6} */
77#define IGA2_SHADOW_VER_BLANK_START_REG_NUM 2
78/* location: {CR73,0,7},{CR74,0,2} */
79#define IGA2_SHADOW_VER_BLANK_END_REG_NUM 2
80/* location: {CR75,0,7},{CR76,4,6} */
81#define IGA2_SHADOW_VER_SYNC_START_REG_NUM 2
82/* location: {CR76,0,3} */
83#define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1
84
85/* Define Fetch Count Register*/
86
87/* location: {SR1C,0,7},{SR1D,0,1} */
88#define IGA1_FETCH_COUNT_REG_NUM 2
89/* 16 bytes alignment. */
90#define IGA1_FETCH_COUNT_ALIGN_BYTE 16
91/* x: H resolution, y: color depth */
92#define IGA1_FETCH_COUNT_PATCH_VALUE 4
93#define IGA1_FETCH_COUNT_FORMULA(x, y) \
94 (((x*y)/IGA1_FETCH_COUNT_ALIGN_BYTE) + IGA1_FETCH_COUNT_PATCH_VALUE)
95
96/* location: {CR65,0,7},{CR67,2,3} */
97#define IGA2_FETCH_COUNT_REG_NUM 2
98#define IGA2_FETCH_COUNT_ALIGN_BYTE 16
99#define IGA2_FETCH_COUNT_PATCH_VALUE 0
100#define IGA2_FETCH_COUNT_FORMULA(x, y) \
101 (((x*y)/IGA2_FETCH_COUNT_ALIGN_BYTE) + IGA2_FETCH_COUNT_PATCH_VALUE)
102
103/* Staring Address*/
104
105/* location: {CR0C,0,7},{CR0D,0,7},{CR34,0,7},{CR48,0,1} */
106#define IGA1_STARTING_ADDR_REG_NUM 4
107/* location: {CR62,1,7},{CR63,0,7},{CR64,0,7} */
108#define IGA2_STARTING_ADDR_REG_NUM 3
109
110/* Define Display OFFSET*/
111/* These value are by HW suggested value*/
112/* location: {SR17,0,7} */
113#define K800_IGA1_FIFO_MAX_DEPTH 384
114/* location: {SR16,0,5},{SR16,7,7} */
115#define K800_IGA1_FIFO_THRESHOLD 328
116/* location: {SR18,0,5},{SR18,7,7} */
117#define K800_IGA1_FIFO_HIGH_THRESHOLD 296
118/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
119 /* because HW only 5 bits */
120#define K800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
121
122/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
123#define K800_IGA2_FIFO_MAX_DEPTH 384
124/* location: {CR68,0,3},{CR95,4,6} */
125#define K800_IGA2_FIFO_THRESHOLD 328
126/* location: {CR92,0,3},{CR95,0,2} */
127#define K800_IGA2_FIFO_HIGH_THRESHOLD 296
128/* location: {CR94,0,6} */
129#define K800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
130
131/* location: {SR17,0,7} */
132#define P880_IGA1_FIFO_MAX_DEPTH 192
133/* location: {SR16,0,5},{SR16,7,7} */
134#define P880_IGA1_FIFO_THRESHOLD 128
135/* location: {SR18,0,5},{SR18,7,7} */
136#define P880_IGA1_FIFO_HIGH_THRESHOLD 64
137/* location: {SR22,0,4}. (128/4) =64, K800 must be set zero, */
138 /* because HW only 5 bits */
139#define P880_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
140
141/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
142#define P880_IGA2_FIFO_MAX_DEPTH 96
143/* location: {CR68,0,3},{CR95,4,6} */
144#define P880_IGA2_FIFO_THRESHOLD 64
145/* location: {CR92,0,3},{CR95,0,2} */
146#define P880_IGA2_FIFO_HIGH_THRESHOLD 32
147/* location: {CR94,0,6} */
148#define P880_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
149
150/* VT3314 chipset*/
151
152/* location: {SR17,0,7} */
153#define CN700_IGA1_FIFO_MAX_DEPTH 96
154/* location: {SR16,0,5},{SR16,7,7} */
155#define CN700_IGA1_FIFO_THRESHOLD 80
156/* location: {SR18,0,5},{SR18,7,7} */
157#define CN700_IGA1_FIFO_HIGH_THRESHOLD 64
158/* location: {SR22,0,4}. (128/4) =64, P800 must be set zero,
159 because HW only 5 bits */
160#define CN700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 0
161/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
162#define CN700_IGA2_FIFO_MAX_DEPTH 96
163/* location: {CR68,0,3},{CR95,4,6} */
164#define CN700_IGA2_FIFO_THRESHOLD 80
165/* location: {CR92,0,3},{CR95,0,2} */
166#define CN700_IGA2_FIFO_HIGH_THRESHOLD 32
167/* location: {CR94,0,6} */
168#define CN700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
169
170/* For VT3324, these values are suggested by HW */
171/* location: {SR17,0,7} */
172#define CX700_IGA1_FIFO_MAX_DEPTH 192
173/* location: {SR16,0,5},{SR16,7,7} */
174#define CX700_IGA1_FIFO_THRESHOLD 128
175/* location: {SR18,0,5},{SR18,7,7} */
176#define CX700_IGA1_FIFO_HIGH_THRESHOLD 128
177/* location: {SR22,0,4} */
178#define CX700_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
179
180/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
181#define CX700_IGA2_FIFO_MAX_DEPTH 96
182/* location: {CR68,0,3},{CR95,4,6} */
183#define CX700_IGA2_FIFO_THRESHOLD 64
184/* location: {CR92,0,3},{CR95,0,2} */
185#define CX700_IGA2_FIFO_HIGH_THRESHOLD 32
186/* location: {CR94,0,6} */
187#define CX700_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
188
189/* VT3336 chipset*/
190/* location: {SR17,0,7} */
191#define K8M890_IGA1_FIFO_MAX_DEPTH 360
192/* location: {SR16,0,5},{SR16,7,7} */
193#define K8M890_IGA1_FIFO_THRESHOLD 328
194/* location: {SR18,0,5},{SR18,7,7} */
195#define K8M890_IGA1_FIFO_HIGH_THRESHOLD 296
196/* location: {SR22,0,4}. */
197#define K8M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 124
198
199/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
200#define K8M890_IGA2_FIFO_MAX_DEPTH 360
201/* location: {CR68,0,3},{CR95,4,6} */
202#define K8M890_IGA2_FIFO_THRESHOLD 328
203/* location: {CR92,0,3},{CR95,0,2} */
204#define K8M890_IGA2_FIFO_HIGH_THRESHOLD 296
205/* location: {CR94,0,6} */
206#define K8M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 124
207
208/* VT3327 chipset*/
209/* location: {SR17,0,7} */
210#define P4M890_IGA1_FIFO_MAX_DEPTH 96
211/* location: {SR16,0,5},{SR16,7,7} */
212#define P4M890_IGA1_FIFO_THRESHOLD 76
213/* location: {SR18,0,5},{SR18,7,7} */
214#define P4M890_IGA1_FIFO_HIGH_THRESHOLD 64
215/* location: {SR22,0,4}. (32/4) =8 */
216#define P4M890_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
217/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
218#define P4M890_IGA2_FIFO_MAX_DEPTH 96
219/* location: {CR68,0,3},{CR95,4,6} */
220#define P4M890_IGA2_FIFO_THRESHOLD 76
221/* location: {CR92,0,3},{CR95,0,2} */
222#define P4M890_IGA2_FIFO_HIGH_THRESHOLD 64
223/* location: {CR94,0,6} */
224#define P4M890_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
225
226/* VT3364 chipset*/
227/* location: {SR17,0,7} */
228#define P4M900_IGA1_FIFO_MAX_DEPTH 96
229/* location: {SR16,0,5},{SR16,7,7} */
230#define P4M900_IGA1_FIFO_THRESHOLD 76
231/* location: {SR18,0,5},{SR18,7,7} */
232#define P4M900_IGA1_FIFO_HIGH_THRESHOLD 76
233/* location: {SR22,0,4}. */
234#define P4M900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 32
235/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
236#define P4M900_IGA2_FIFO_MAX_DEPTH 96
237/* location: {CR68,0,3},{CR95,4,6} */
238#define P4M900_IGA2_FIFO_THRESHOLD 76
239/* location: {CR92,0,3},{CR95,0,2} */
240#define P4M900_IGA2_FIFO_HIGH_THRESHOLD 76
241/* location: {CR94,0,6} */
242#define P4M900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 32
243
244/* For VT3353, these values are suggested by HW */
245/* location: {SR17,0,7} */
246#define VX800_IGA1_FIFO_MAX_DEPTH 192
247/* location: {SR16,0,5},{SR16,7,7} */
248#define VX800_IGA1_FIFO_THRESHOLD 152
249/* location: {SR18,0,5},{SR18,7,7} */
250#define VX800_IGA1_FIFO_HIGH_THRESHOLD 152
251/* location: {SR22,0,4} */
252#define VX800_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 64
253/* location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
254#define VX800_IGA2_FIFO_MAX_DEPTH 96
255/* location: {CR68,0,3},{CR95,4,6} */
256#define VX800_IGA2_FIFO_THRESHOLD 64
257/* location: {CR92,0,3},{CR95,0,2} */
258#define VX800_IGA2_FIFO_HIGH_THRESHOLD 32
259/* location: {CR94,0,6} */
260#define VX800_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 128
261
262/* For VT3409 */
263#define VX855_IGA1_FIFO_MAX_DEPTH 400
264#define VX855_IGA1_FIFO_THRESHOLD 320
265#define VX855_IGA1_FIFO_HIGH_THRESHOLD 320
266#define VX855_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 160
267
268#define VX855_IGA2_FIFO_MAX_DEPTH 200
269#define VX855_IGA2_FIFO_THRESHOLD 160
270#define VX855_IGA2_FIFO_HIGH_THRESHOLD 160
271#define VX855_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320
272
273/* For VT3410 */
274#define VX900_IGA1_FIFO_MAX_DEPTH 400
275#define VX900_IGA1_FIFO_THRESHOLD 320
276#define VX900_IGA1_FIFO_HIGH_THRESHOLD 320
277#define VX900_IGA1_DISPLAY_QUEUE_EXPIRE_NUM 160
278
279#define VX900_IGA2_FIFO_MAX_DEPTH 192
280#define VX900_IGA2_FIFO_THRESHOLD 160
281#define VX900_IGA2_FIFO_HIGH_THRESHOLD 160
282#define VX900_IGA2_DISPLAY_QUEUE_EXPIRE_NUM 320
283
284#define IGA1_FIFO_DEPTH_SELECT_REG_NUM 1
285#define IGA1_FIFO_THRESHOLD_REG_NUM 2
286#define IGA1_FIFO_HIGH_THRESHOLD_REG_NUM 2
287#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
288
289#define IGA2_FIFO_DEPTH_SELECT_REG_NUM 3
290#define IGA2_FIFO_THRESHOLD_REG_NUM 2
291#define IGA2_FIFO_HIGH_THRESHOLD_REG_NUM 2
292#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM 1
293
294#define IGA1_FIFO_DEPTH_SELECT_FORMULA(x) ((x/2)-1)
295#define IGA1_FIFO_THRESHOLD_FORMULA(x) (x/4)
296#define IGA1_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
297#define IGA1_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
298#define IGA2_FIFO_DEPTH_SELECT_FORMULA(x) (((x/2)/4)-1)
299#define IGA2_FIFO_THRESHOLD_FORMULA(x) (x/4)
300#define IGA2_DISPLAY_QUEUE_EXPIRE_NUM_FORMULA(x) (x/4)
301#define IGA2_FIFO_HIGH_THRESHOLD_FORMULA(x) (x/4)
302
303/************************************************************************/
304/* LCD Timing */
305/************************************************************************/
306
307/* 500 ms = 500000 us */
308#define LCD_POWER_SEQ_TD0 500000
309/* 50 ms = 50000 us */
310#define LCD_POWER_SEQ_TD1 50000
311/* 0 us */
312#define LCD_POWER_SEQ_TD2 0
313/* 210 ms = 210000 us */
314#define LCD_POWER_SEQ_TD3 210000
315/* 2^10 * (1/14.31818M) = 71.475 us (K400.revA) */
316#define CLE266_POWER_SEQ_UNIT 71
317/* 2^11 * (1/14.31818M) = 142.95 us (K400.revB) */
318#define K800_POWER_SEQ_UNIT 142
319/* 2^13 * (1/14.31818M) = 572.1 us */
320#define P880_POWER_SEQ_UNIT 572
321
322#define CLE266_POWER_SEQ_FORMULA(x) ((x)/CLE266_POWER_SEQ_UNIT)
323#define K800_POWER_SEQ_FORMULA(x) ((x)/K800_POWER_SEQ_UNIT)
324#define P880_POWER_SEQ_FORMULA(x) ((x)/P880_POWER_SEQ_UNIT)
325
326/* location: {CR8B,0,7},{CR8F,0,3} */
327#define LCD_POWER_SEQ_TD0_REG_NUM 2
328/* location: {CR8C,0,7},{CR8F,4,7} */
329#define LCD_POWER_SEQ_TD1_REG_NUM 2
330/* location: {CR8D,0,7},{CR90,0,3} */
331#define LCD_POWER_SEQ_TD2_REG_NUM 2
332/* location: {CR8E,0,7},{CR90,4,7} */
333#define LCD_POWER_SEQ_TD3_REG_NUM 2
334
335/* LCD Scaling factor*/
336/* x: indicate setting horizontal size*/
337/* y: indicate panel horizontal size*/
338
339/* Horizontal scaling factor 10 bits (2^10) */
340#define CLE266_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
341/* Vertical scaling factor 10 bits (2^10) */
342#define CLE266_LCD_VER_SCF_FORMULA(x, y) (((x-1)*1024)/(y-1))
343/* Horizontal scaling factor 10 bits (2^12) */
344#define K800_LCD_HOR_SCF_FORMULA(x, y) (((x-1)*4096)/(y-1))
345/* Vertical scaling factor 10 bits (2^11) */
346#define K800_LCD_VER_SCF_FORMULA(x, y) (((x-1)*2048)/(y-1))
347
348/* location: {CR9F,0,1},{CR77,0,7},{CR79,4,5} */
349#define LCD_HOR_SCALING_FACTOR_REG_NUM 3
350/* location: {CR79,3,3},{CR78,0,7},{CR79,6,7} */
351#define LCD_VER_SCALING_FACTOR_REG_NUM 3
352/* location: {CR77,0,7},{CR79,4,5} */
353#define LCD_HOR_SCALING_FACTOR_REG_NUM_CLE 2
354/* location: {CR78,0,7},{CR79,6,7} */
355#define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2
356
357struct io_register {
358 u8 io_addr;
359 u8 start_bit;
360 u8 end_bit;
361};
362
363/*****************************************************
364** Define IGA2 Shadow Display Timing ****
365*****************************************************/
366
367/* IGA2 Shadow Horizontal Total */
368struct iga2_shadow_hor_total {
369 int reg_num;
370 struct io_register reg[IGA2_SHADOW_HOR_TOTAL_REG_NUM];
371};
372
373/* IGA2 Shadow Horizontal Blank End */
374struct iga2_shadow_hor_blank_end {
375 int reg_num;
376 struct io_register reg[IGA2_SHADOW_HOR_BLANK_END_REG_NUM];
377};
378
379/* IGA2 Shadow Vertical Total */
380struct iga2_shadow_ver_total {
381 int reg_num;
382 struct io_register reg[IGA2_SHADOW_VER_TOTAL_REG_NUM];
383};
384
385/* IGA2 Shadow Vertical Addressable Video */
386struct iga2_shadow_ver_addr {
387 int reg_num;
388 struct io_register reg[IGA2_SHADOW_VER_ADDR_REG_NUM];
389};
390
391/* IGA2 Shadow Vertical Blank Start */
392struct iga2_shadow_ver_blank_start {
393 int reg_num;
394 struct io_register reg[IGA2_SHADOW_VER_BLANK_START_REG_NUM];
395};
396
397/* IGA2 Shadow Vertical Blank End */
398struct iga2_shadow_ver_blank_end {
399 int reg_num;
400 struct io_register reg[IGA2_SHADOW_VER_BLANK_END_REG_NUM];
401};
402
403/* IGA2 Shadow Vertical Sync Start */
404struct iga2_shadow_ver_sync_start {
405 int reg_num;
406 struct io_register reg[IGA2_SHADOW_VER_SYNC_START_REG_NUM];
407};
408
409/* IGA2 Shadow Vertical Sync End */
410struct iga2_shadow_ver_sync_end {
411 int reg_num;
412 struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM];
413};
414
415/* IGA1 Fetch Count Register */
416struct iga1_fetch_count {
417 int reg_num;
418 struct io_register reg[IGA1_FETCH_COUNT_REG_NUM];
419};
420
421/* IGA2 Fetch Count Register */
422struct iga2_fetch_count {
423 int reg_num;
424 struct io_register reg[IGA2_FETCH_COUNT_REG_NUM];
425};
426
427struct fetch_count {
428 struct iga1_fetch_count iga1_fetch_count_reg;
429 struct iga2_fetch_count iga2_fetch_count_reg;
430};
431
432/* Starting Address Register */
433struct iga1_starting_addr {
434 int reg_num;
435 struct io_register reg[IGA1_STARTING_ADDR_REG_NUM];
436};
437
438struct iga2_starting_addr {
439 int reg_num;
440 struct io_register reg[IGA2_STARTING_ADDR_REG_NUM];
441};
442
443struct starting_addr {
444 struct iga1_starting_addr iga1_starting_addr_reg;
445 struct iga2_starting_addr iga2_starting_addr_reg;
446};
447
448/* LCD Power Sequence Timer */
449struct lcd_pwd_seq_td0 {
450 int reg_num;
451 struct io_register reg[LCD_POWER_SEQ_TD0_REG_NUM];
452};
453
454struct lcd_pwd_seq_td1 {
455 int reg_num;
456 struct io_register reg[LCD_POWER_SEQ_TD1_REG_NUM];
457};
458
459struct lcd_pwd_seq_td2 {
460 int reg_num;
461 struct io_register reg[LCD_POWER_SEQ_TD2_REG_NUM];
462};
463
464struct lcd_pwd_seq_td3 {
465 int reg_num;
466 struct io_register reg[LCD_POWER_SEQ_TD3_REG_NUM];
467};
468
469struct _lcd_pwd_seq_timer {
470 struct lcd_pwd_seq_td0 td0;
471 struct lcd_pwd_seq_td1 td1;
472 struct lcd_pwd_seq_td2 td2;
473 struct lcd_pwd_seq_td3 td3;
474};
475
476/* LCD Scaling Factor */
477struct _lcd_hor_scaling_factor {
478 int reg_num;
479 struct io_register reg[LCD_HOR_SCALING_FACTOR_REG_NUM];
480};
481
482struct _lcd_ver_scaling_factor {
483 int reg_num;
484 struct io_register reg[LCD_VER_SCALING_FACTOR_REG_NUM];
485};
486
487struct _lcd_scaling_factor {
488 struct _lcd_hor_scaling_factor lcd_hor_scaling_factor;
489 struct _lcd_ver_scaling_factor lcd_ver_scaling_factor;
490};
491
492struct pll_limit {
493 u16 multiplier_min;
494 u16 multiplier_max;
495 u8 divisor;
496 u8 rshift;
497};
498
499struct rgbLUT {
500 u8 red;
501 u8 green;
502 u8 blue;
503};
504
505struct lcd_pwd_seq_timer {
506 u16 td0;
507 u16 td1;
508 u16 td2;
509 u16 td3;
510};
511
512/* Display FIFO Relation Registers*/
513struct iga1_fifo_depth_select {
514 int reg_num;
515 struct io_register reg[IGA1_FIFO_DEPTH_SELECT_REG_NUM];
516};
517
518struct iga1_fifo_threshold_select {
519 int reg_num;
520 struct io_register reg[IGA1_FIFO_THRESHOLD_REG_NUM];
521};
522
523struct iga1_fifo_high_threshold_select {
524 int reg_num;
525 struct io_register reg[IGA1_FIFO_HIGH_THRESHOLD_REG_NUM];
526};
527
528struct iga1_display_queue_expire_num {
529 int reg_num;
530 struct io_register reg[IGA1_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
531};
532
533struct iga2_fifo_depth_select {
534 int reg_num;
535 struct io_register reg[IGA2_FIFO_DEPTH_SELECT_REG_NUM];
536};
537
538struct iga2_fifo_threshold_select {
539 int reg_num;
540 struct io_register reg[IGA2_FIFO_THRESHOLD_REG_NUM];
541};
542
543struct iga2_fifo_high_threshold_select {
544 int reg_num;
545 struct io_register reg[IGA2_FIFO_HIGH_THRESHOLD_REG_NUM];
546};
547
548struct iga2_display_queue_expire_num {
549 int reg_num;
550 struct io_register reg[IGA2_DISPLAY_QUEUE_EXPIRE_NUM_REG_NUM];
551};
552
553struct fifo_depth_select {
554 struct iga1_fifo_depth_select iga1_fifo_depth_select_reg;
555 struct iga2_fifo_depth_select iga2_fifo_depth_select_reg;
556};
557
558struct fifo_threshold_select {
559 struct iga1_fifo_threshold_select iga1_fifo_threshold_select_reg;
560 struct iga2_fifo_threshold_select iga2_fifo_threshold_select_reg;
561};
562
563struct fifo_high_threshold_select {
564 struct iga1_fifo_high_threshold_select
565 iga1_fifo_high_threshold_select_reg;
566 struct iga2_fifo_high_threshold_select
567 iga2_fifo_high_threshold_select_reg;
568};
569
570struct display_queue_expire_num {
571 struct iga1_display_queue_expire_num
572 iga1_display_queue_expire_num_reg;
573 struct iga2_display_queue_expire_num
574 iga2_display_queue_expire_num_reg;
575};
576
577struct iga2_shadow_crtc_timing {
578 struct iga2_shadow_hor_total hor_total_shadow;
579 struct iga2_shadow_hor_blank_end hor_blank_end_shadow;
580 struct iga2_shadow_ver_total ver_total_shadow;
581 struct iga2_shadow_ver_addr ver_addr_shadow;
582 struct iga2_shadow_ver_blank_start ver_blank_start_shadow;
583 struct iga2_shadow_ver_blank_end ver_blank_end_shadow;
584 struct iga2_shadow_ver_sync_start ver_sync_start_shadow;
585 struct iga2_shadow_ver_sync_end ver_sync_end_shadow;
586};
587
588/* device ID */
589#define CLE266_FUNCTION3 0x3123
590#define KM400_FUNCTION3 0x3205
591#define CN400_FUNCTION2 0x2259
592#define CN400_FUNCTION3 0x3259
593/* support VT3314 chipset */
594#define CN700_FUNCTION2 0x2314
595#define CN700_FUNCTION3 0x3208
596/* VT3324 chipset */
597#define CX700_FUNCTION2 0x2324
598#define CX700_FUNCTION3 0x3324
599/* VT3204 chipset*/
600#define KM800_FUNCTION3 0x3204
601/* VT3336 chipset*/
602#define KM890_FUNCTION3 0x3336
603/* VT3327 chipset*/
604#define P4M890_FUNCTION3 0x3327
605/* VT3293 chipset*/
606#define CN750_FUNCTION3 0x3208
607/* VT3364 chipset*/
608#define P4M900_FUNCTION3 0x3364
609/* VT3353 chipset*/
610#define VX800_FUNCTION3 0x3353
611/* VT3409 chipset*/
612#define VX855_FUNCTION3 0x3409
613/* VT3410 chipset*/
614#define VX900_FUNCTION3 0x3410
615
616struct IODATA {
617 u8 Index;
618 u8 Mask;
619 u8 Data;
620};
621
622struct pci_device_id_info {
623 u32 vendor;
624 u32 device;
625 u32 chip_index;
626};
627
628struct via_device_mapping {
629 u32 device;
630 const char *name;
631};
632
633extern int viafb_SAMM_ON;
634extern int viafb_dual_fb;
635extern int viafb_LCD2_ON;
636extern int viafb_LCD_ON;
637extern int viafb_DVI_ON;
638extern int viafb_hotplug;
639
640struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
641 u16 cxres, u16 cyres);
642void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
643 u16 cxres, u16 cyres, int iga);
644void viafb_set_vclock(u32 CLK, int set_iga);
645void viafb_load_reg(int timing_value, int viafb_load_reg_num,
646 struct io_register *reg,
647 int io_type);
648void via_set_source(u32 devices, u8 iga);
649void via_set_state(u32 devices, u8 state);
650void via_set_sync_polarity(u32 devices, u8 polarity);
651u32 via_parse_odev(char *input, char **end);
652void via_odev_to_seq(struct seq_file *m, u32 odev);
653void init_ad9389(void);
654/* Access I/O Function */
655void viafb_lock_crt(void);
656void viafb_unlock_crt(void);
657void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga);
658void viafb_write_regx(struct io_reg RegTable[], int ItemNum);
659void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
660void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
661 *p_gfx_dpa_setting);
662
663int viafb_setmode(void);
664void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
665 const struct fb_videomode *mode);
666void viafb_init_chip_info(int chip_type);
667void viafb_init_dac(int set_iga);
668int viafb_get_refresh(int hres, int vres, u32 float_refresh);
669void viafb_update_device_setting(int hres, int vres, int bpp, int flag);
670
671void viafb_set_iga_path(void);
672void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
673void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
674void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len);
675
676#endif /* __HW_H__ */
diff --git a/drivers/video/fbdev/via/ioctl.c b/drivers/video/fbdev/via/ioctl.c
new file mode 100644
index 000000000000..ea1c51428823
--- /dev/null
+++ b/drivers/video/fbdev/via/ioctl.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24int viafb_ioctl_get_viafb_info(u_long arg)
25{
26 struct viafb_ioctl_info viainfo;
27
28 memset(&viainfo, 0, sizeof(struct viafb_ioctl_info));
29
30 viainfo.viafb_id = VIAID;
31 viainfo.vendor_id = PCI_VIA_VENDOR_ID;
32
33 switch (viaparinfo->chip_info->gfx_chip_name) {
34 case UNICHROME_CLE266:
35 viainfo.device_id = UNICHROME_CLE266_DID;
36 break;
37
38 case UNICHROME_K400:
39 viainfo.device_id = UNICHROME_K400_DID;
40 break;
41
42 case UNICHROME_K800:
43 viainfo.device_id = UNICHROME_K800_DID;
44 break;
45
46 case UNICHROME_PM800:
47 viainfo.device_id = UNICHROME_PM800_DID;
48 break;
49
50 case UNICHROME_CN700:
51 viainfo.device_id = UNICHROME_CN700_DID;
52 break;
53
54 case UNICHROME_CX700:
55 viainfo.device_id = UNICHROME_CX700_DID;
56 break;
57
58 case UNICHROME_K8M890:
59 viainfo.device_id = UNICHROME_K8M890_DID;
60 break;
61
62 case UNICHROME_P4M890:
63 viainfo.device_id = UNICHROME_P4M890_DID;
64 break;
65
66 case UNICHROME_P4M900:
67 viainfo.device_id = UNICHROME_P4M900_DID;
68 break;
69 }
70
71 viainfo.version = VERSION_MAJOR;
72 viainfo.revision = VERSION_MINOR;
73
74 if (copy_to_user((void __user *)arg, &viainfo, sizeof(viainfo)))
75 return -EFAULT;
76
77 return 0;
78}
79
80/* Hot-Plug Priority: DVI > CRT*/
81int viafb_ioctl_hotplug(int hres, int vres, int bpp)
82{
83 int DVIsense, status = 0;
84 DEBUG_MSG(KERN_INFO "viafb_ioctl_hotplug!!\n");
85
86 if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name !=
87 NON_TMDS_TRANSMITTER) {
88 DVIsense = viafb_dvi_sense();
89
90 if (DVIsense) {
91 DEBUG_MSG(KERN_INFO "DVI Attached...\n");
92 if (viafb_DeviceStatus != DVI_Device) {
93 viafb_DVI_ON = 1;
94 viafb_CRT_ON = 0;
95 viafb_LCD_ON = 0;
96 viafb_DeviceStatus = DVI_Device;
97 viafb_set_iga_path();
98 return viafb_DeviceStatus;
99 }
100 status = 1;
101 } else
102 DEBUG_MSG(KERN_INFO "DVI De-attached...\n");
103 }
104
105 if ((viafb_DeviceStatus != CRT_Device) && (status == 0)) {
106 viafb_CRT_ON = 1;
107 viafb_DVI_ON = 0;
108 viafb_LCD_ON = 0;
109
110 viafb_DeviceStatus = CRT_Device;
111 viafb_set_iga_path();
112 return viafb_DeviceStatus;
113 }
114
115 return 0;
116}
diff --git a/drivers/video/fbdev/via/ioctl.h b/drivers/video/fbdev/via/ioctl.h
new file mode 100644
index 000000000000..6010d10b59e8
--- /dev/null
+++ b/drivers/video/fbdev/via/ioctl.h
@@ -0,0 +1,203 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __IOCTL_H__
23#define __IOCTL_H__
24
25#ifndef __user
26#define __user
27#endif
28
29/* VIAFB IOCTL definition */
30#define VIAFB_GET_INFO_SIZE 0x56494101 /* 'VIA\01' */
31#define VIAFB_GET_INFO 0x56494102 /* 'VIA\02' */
32#define VIAFB_HOTPLUG 0x56494103 /* 'VIA\03' */
33#define VIAFB_SET_HOTPLUG_FLAG 0x56494104 /* 'VIA\04' */
34#define VIAFB_GET_RESOLUTION 0x56494105 /* 'VIA\05' */
35#define VIAFB_GET_SAMM_INFO 0x56494107 /* 'VIA\07' */
36#define VIAFB_TURN_ON_OUTPUT_DEVICE 0x56494108 /* 'VIA\08' */
37#define VIAFB_TURN_OFF_OUTPUT_DEVICE 0x56494109 /* 'VIA\09' */
38#define VIAFB_GET_DEVICE 0x5649410B
39#define VIAFB_GET_DRIVER_VERSION 0x56494112 /* 'VIA\12' */
40#define VIAFB_GET_CHIP_INFO 0x56494113 /* 'VIA\13' */
41#define VIAFB_GET_DEVICE_INFO 0x56494115
42
43#define VIAFB_GET_DEVICE_SUPPORT 0x56494118
44#define VIAFB_GET_DEVICE_CONNECT 0x56494119
45#define VIAFB_GET_PANEL_SUPPORT_EXPAND 0x5649411A
46#define VIAFB_GET_DRIVER_NAME 0x56494122
47#define VIAFB_GET_DEVICE_SUPPORT_STATE 0x56494123
48#define VIAFB_GET_GAMMA_LUT 0x56494124
49#define VIAFB_SET_GAMMA_LUT 0x56494125
50#define VIAFB_GET_GAMMA_SUPPORT_STATE 0x56494126
51#define VIAFB_SYNC_SURFACE 0x56494130
52#define VIAFB_GET_DRIVER_CAPS 0x56494131
53#define VIAFB_GET_IGA_SCALING_INFO 0x56494132
54#define VIAFB_GET_PANEL_MAX_SIZE 0x56494133
55#define VIAFB_GET_PANEL_MAX_POSITION 0x56494134
56#define VIAFB_SET_PANEL_SIZE 0x56494135
57#define VIAFB_SET_PANEL_POSITION 0x56494136
58#define VIAFB_GET_PANEL_POSITION 0x56494137
59#define VIAFB_GET_PANEL_SIZE 0x56494138
60
61#define None_Device 0x00
62#define CRT_Device 0x01
63#define LCD_Device 0x02
64#define DVI_Device 0x08
65#define CRT2_Device 0x10
66#define LCD2_Device 0x40
67
68#define OP_LCD_CENTERING 0x01
69#define OP_LCD_PANEL_ID 0x02
70#define OP_LCD_MODE 0x03
71
72/*SAMM operation flag*/
73#define OP_SAMM 0x80
74
75#define LCD_PANEL_ID_MAXIMUM 23
76
77#define STATE_ON 0x1
78#define STATE_OFF 0x0
79#define STATE_DEFAULT 0xFFFF
80
81#define MAX_ACTIVE_DEV_NUM 2
82
83struct device_t {
84 unsigned short crt:1;
85 unsigned short dvi:1;
86 unsigned short lcd:1;
87 unsigned short samm:1;
88 unsigned short lcd_dsp_cent:1;
89 unsigned char lcd_mode:1;
90 unsigned short epia_dvi:1;
91 unsigned short lcd_dual_edge:1;
92 unsigned short lcd2:1;
93
94 unsigned short primary_dev;
95 unsigned char lcd_panel_id;
96 unsigned short xres, yres;
97 unsigned short xres1, yres1;
98 unsigned short refresh;
99 unsigned short bpp;
100 unsigned short refresh1;
101 unsigned short bpp1;
102 unsigned short sequence;
103 unsigned short bus_width;
104};
105
106struct viafb_ioctl_info {
107 u32 viafb_id; /* for identifying viafb */
108#define VIAID 0x56494146 /* Identify myself with 'VIAF' */
109 u16 vendor_id;
110 u16 device_id;
111 u8 version;
112 u8 revision;
113 u8 reserved[246]; /* for future use */
114};
115
116struct viafb_ioctl_mode {
117 u32 xres;
118 u32 yres;
119 u32 refresh;
120 u32 bpp;
121 u32 xres_sec;
122 u32 yres_sec;
123 u32 virtual_xres_sec;
124 u32 virtual_yres_sec;
125 u32 refresh_sec;
126 u32 bpp_sec;
127};
128struct viafb_ioctl_samm {
129 u32 samm_status;
130 u32 size_prim;
131 u32 size_sec;
132 u32 mem_base;
133 u32 offset_sec;
134};
135
136struct viafb_driver_version {
137 int iMajorNum;
138 int iKernelNum;
139 int iOSNum;
140 int iMinorNum;
141};
142
143struct viafb_ioctl_lcd_attribute {
144 unsigned int panel_id;
145 unsigned int display_center;
146 unsigned int lcd_mode;
147};
148
149struct viafb_ioctl_setting {
150 /* Enable or disable active devices */
151 unsigned short device_flag;
152 /* Indicate which device should be turn on or turn off. */
153 unsigned short device_status;
154 unsigned int reserved;
155 /* Indicate which LCD's attribute can be changed. */
156 unsigned short lcd_operation_flag;
157 /* 1: SAMM ON 0: SAMM OFF */
158 unsigned short samm_status;
159 /* horizontal resolution of first device */
160 unsigned short first_dev_hor_res;
161 /* vertical resolution of first device */
162 unsigned short first_dev_ver_res;
163 /* horizontal resolution of second device */
164 unsigned short second_dev_hor_res;
165 /* vertical resolution of second device */
166 unsigned short second_dev_ver_res;
167 /* refresh rate of first device */
168 unsigned short first_dev_refresh;
169 /* bpp of first device */
170 unsigned short first_dev_bpp;
171 /* refresh rate of second device */
172 unsigned short second_dev_refresh;
173 /* bpp of second device */
174 unsigned short second_dev_bpp;
175 /* Indicate which device are primary display device. */
176 unsigned int primary_device;
177 unsigned int struct_reserved[35];
178 struct viafb_ioctl_lcd_attribute lcd_attributes;
179};
180
181struct _UTFunctionCaps {
182 unsigned int dw3DScalingState;
183 unsigned int reserved[31];
184};
185
186struct _POSITIONVALUE {
187 unsigned int dwX;
188 unsigned int dwY;
189};
190
191struct _panel_size_pos_info {
192 unsigned int device_type;
193 int x;
194 int y;
195};
196
197extern int viafb_LCD_ON;
198extern int viafb_DVI_ON;
199
200int viafb_ioctl_get_viafb_info(u_long arg);
201int viafb_ioctl_hotplug(int hres, int vres, int bpp);
202
203#endif /* __IOCTL_H__ */
diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c
new file mode 100644
index 000000000000..5d21ff436ec8
--- /dev/null
+++ b/drivers/video/fbdev/via/lcd.c
@@ -0,0 +1,1005 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#include <linux/via-core.h>
22#include <linux/via_i2c.h>
23#include "global.h"
24
25#define viafb_compact_res(x, y) (((x)<<16)|(y))
26
27/* CLE266 Software Power Sequence */
28/* {Mask}, {Data}, {Delay} */
29static const int PowerSequenceOn[3][3] = {
30 {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06}, {0x19, 0x1FE, 0x01}
31};
32static const int PowerSequenceOff[3][3] = {
33 {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00}, {0xD2, 0x19, 0x01}
34};
35
36static struct _lcd_scaling_factor lcd_scaling_factor = {
37 /* LCD Horizontal Scaling Factor Register */
38 {LCD_HOR_SCALING_FACTOR_REG_NUM,
39 {{CR9F, 0, 1}, {CR77, 0, 7}, {CR79, 4, 5} } },
40 /* LCD Vertical Scaling Factor Register */
41 {LCD_VER_SCALING_FACTOR_REG_NUM,
42 {{CR79, 3, 3}, {CR78, 0, 7}, {CR79, 6, 7} } }
43};
44static struct _lcd_scaling_factor lcd_scaling_factor_CLE = {
45 /* LCD Horizontal Scaling Factor Register */
46 {LCD_HOR_SCALING_FACTOR_REG_NUM_CLE, {{CR77, 0, 7}, {CR79, 4, 5} } },
47 /* LCD Vertical Scaling Factor Register */
48 {LCD_VER_SCALING_FACTOR_REG_NUM_CLE, {{CR78, 0, 7}, {CR79, 6, 7} } }
49};
50
51static bool lvds_identify_integratedlvds(void);
52static void fp_id_to_vindex(int panel_id);
53static int lvds_register_read(int index);
54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
55 int panel_vres);
56static void lcd_patch_skew_dvp0(struct lvds_setting_information
57 *plvds_setting_info,
58 struct lvds_chip_information *plvds_chip_info);
59static void lcd_patch_skew_dvp1(struct lvds_setting_information
60 *plvds_setting_info,
61 struct lvds_chip_information *plvds_chip_info);
62static void lcd_patch_skew(struct lvds_setting_information
63 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
64
65static void integrated_lvds_disable(struct lvds_setting_information
66 *plvds_setting_info,
67 struct lvds_chip_information *plvds_chip_info);
68static void integrated_lvds_enable(struct lvds_setting_information
69 *plvds_setting_info,
70 struct lvds_chip_information *plvds_chip_info);
71static void lcd_powersequence_off(void);
72static void lcd_powersequence_on(void);
73static void fill_lcd_format(void);
74static void check_diport_of_integrated_lvds(
75 struct lvds_chip_information *plvds_chip_info,
76 struct lvds_setting_information
77 *plvds_setting_info);
78
79static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
80{
81 return lvds_register_read(device_id_subaddr) == device_id;
82}
83
84void viafb_init_lcd_size(void)
85{
86 DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
87
88 fp_id_to_vindex(viafb_lcd_panel_id);
89 viaparinfo->lvds_setting_info2->lcd_panel_hres =
90 viaparinfo->lvds_setting_info->lcd_panel_hres;
91 viaparinfo->lvds_setting_info2->lcd_panel_vres =
92 viaparinfo->lvds_setting_info->lcd_panel_vres;
93 viaparinfo->lvds_setting_info2->device_lcd_dualedge =
94 viaparinfo->lvds_setting_info->device_lcd_dualedge;
95 viaparinfo->lvds_setting_info2->LCDDithering =
96 viaparinfo->lvds_setting_info->LCDDithering;
97}
98
99static bool lvds_identify_integratedlvds(void)
100{
101 if (viafb_display_hardware_layout == HW_LAYOUT_LCD_EXTERNAL_LCD2) {
102 /* Two dual channel LCD (Internal LVDS + External LVDS): */
103 /* If we have an external LVDS, such as VT1636, we should
104 have its chip ID already. */
105 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
106 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
107 INTEGRATED_LVDS;
108 DEBUG_MSG(KERN_INFO "Support two dual channel LVDS! "
109 "(Internal LVDS + External LVDS)\n");
110 } else {
111 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
112 INTEGRATED_LVDS;
113 DEBUG_MSG(KERN_INFO "Not found external LVDS, "
114 "so can't support two dual channel LVDS!\n");
115 }
116 } else if (viafb_display_hardware_layout == HW_LAYOUT_LCD1_LCD2) {
117 /* Two single channel LCD (Internal LVDS + Internal LVDS): */
118 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
119 INTEGRATED_LVDS;
120 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name =
121 INTEGRATED_LVDS;
122 DEBUG_MSG(KERN_INFO "Support two single channel LVDS! "
123 "(Internal LVDS + Internal LVDS)\n");
124 } else if (viafb_display_hardware_layout != HW_LAYOUT_DVI_ONLY) {
125 /* If we have found external LVDS, just use it,
126 otherwise, we will use internal LVDS as default. */
127 if (!viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
128 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
129 INTEGRATED_LVDS;
130 DEBUG_MSG(KERN_INFO "Found Integrated LVDS!\n");
131 }
132 } else {
133 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
134 NON_LVDS_TRANSMITTER;
135 DEBUG_MSG(KERN_INFO "Do not support LVDS!\n");
136 return false;
137 }
138
139 return true;
140}
141
142bool viafb_lvds_trasmitter_identify(void)
143{
144 if (viafb_lvds_identify_vt1636(VIA_PORT_31)) {
145 viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31;
146 DEBUG_MSG(KERN_INFO
147 "Found VIA VT1636 LVDS on port i2c 0x31\n");
148 } else {
149 if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) {
150 viaparinfo->chip_info->lvds_chip_info.i2c_port =
151 VIA_PORT_2C;
152 DEBUG_MSG(KERN_INFO
153 "Found VIA VT1636 LVDS on port gpio 0x2c\n");
154 }
155 }
156
157 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700)
158 lvds_identify_integratedlvds();
159
160 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
161 return true;
162 /* Check for VT1631: */
163 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS;
164 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
165 VT1631_LVDS_I2C_ADDR;
166
167 if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) {
168 DEBUG_MSG(KERN_INFO "\n VT1631 LVDS ! \n");
169 DEBUG_MSG(KERN_INFO "\n %2d",
170 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
171 DEBUG_MSG(KERN_INFO "\n %2d",
172 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name);
173 return true;
174 }
175
176 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
177 NON_LVDS_TRANSMITTER;
178 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
179 VT1631_LVDS_I2C_ADDR;
180 return false;
181}
182
183static void fp_id_to_vindex(int panel_id)
184{
185 DEBUG_MSG(KERN_INFO "fp_get_panel_id()\n");
186
187 if (panel_id > LCD_PANEL_ID_MAXIMUM)
188 viafb_lcd_panel_id = panel_id =
189 viafb_read_reg(VIACR, CR3F) & 0x0F;
190
191 switch (panel_id) {
192 case 0x0:
193 viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
194 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
195 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
196 viaparinfo->lvds_setting_info->LCDDithering = 1;
197 break;
198 case 0x1:
199 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
200 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
201 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
202 viaparinfo->lvds_setting_info->LCDDithering = 1;
203 break;
204 case 0x2:
205 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
206 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
207 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
208 viaparinfo->lvds_setting_info->LCDDithering = 1;
209 break;
210 case 0x3:
211 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
212 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
213 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
214 viaparinfo->lvds_setting_info->LCDDithering = 1;
215 break;
216 case 0x4:
217 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
218 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
219 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
220 viaparinfo->lvds_setting_info->LCDDithering = 1;
221 break;
222 case 0x5:
223 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
224 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
225 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
226 viaparinfo->lvds_setting_info->LCDDithering = 1;
227 break;
228 case 0x6:
229 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
230 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
231 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
232 viaparinfo->lvds_setting_info->LCDDithering = 1;
233 break;
234 case 0x8:
235 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
236 viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
237 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
238 viaparinfo->lvds_setting_info->LCDDithering = 1;
239 break;
240 case 0x9:
241 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
242 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
243 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
244 viaparinfo->lvds_setting_info->LCDDithering = 1;
245 break;
246 case 0xA:
247 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
248 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
249 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
250 viaparinfo->lvds_setting_info->LCDDithering = 0;
251 break;
252 case 0xB:
253 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
254 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
255 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
256 viaparinfo->lvds_setting_info->LCDDithering = 0;
257 break;
258 case 0xC:
259 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
260 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
261 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
262 viaparinfo->lvds_setting_info->LCDDithering = 0;
263 break;
264 case 0xD:
265 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
266 viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
267 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
268 viaparinfo->lvds_setting_info->LCDDithering = 0;
269 break;
270 case 0xE:
271 viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
272 viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
273 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
274 viaparinfo->lvds_setting_info->LCDDithering = 0;
275 break;
276 case 0xF:
277 viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
278 viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
279 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
280 viaparinfo->lvds_setting_info->LCDDithering = 0;
281 break;
282 case 0x10:
283 viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
284 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
285 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
286 viaparinfo->lvds_setting_info->LCDDithering = 0;
287 break;
288 case 0x11:
289 viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
290 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
291 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
292 viaparinfo->lvds_setting_info->LCDDithering = 1;
293 break;
294 case 0x12:
295 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
296 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
297 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
298 viaparinfo->lvds_setting_info->LCDDithering = 1;
299 break;
300 case 0x13:
301 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
302 viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
303 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
304 viaparinfo->lvds_setting_info->LCDDithering = 1;
305 break;
306 case 0x14:
307 viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
308 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
309 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
310 viaparinfo->lvds_setting_info->LCDDithering = 0;
311 break;
312 case 0x15:
313 viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
314 viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
315 viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
316 viaparinfo->lvds_setting_info->LCDDithering = 0;
317 break;
318 case 0x16:
319 viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
320 viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
321 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
322 viaparinfo->lvds_setting_info->LCDDithering = 1;
323 break;
324 case 0x17:
325 /* OLPC XO-1.5 panel */
326 viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
327 viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
328 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
329 viaparinfo->lvds_setting_info->LCDDithering = 0;
330 break;
331 default:
332 viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
333 viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
334 viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
335 viaparinfo->lvds_setting_info->LCDDithering = 1;
336 }
337}
338
339static int lvds_register_read(int index)
340{
341 u8 data;
342
343 viafb_i2c_readbyte(VIA_PORT_2C,
344 (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr,
345 (u8) index, &data);
346 return data;
347}
348
349static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
350 int panel_vres)
351{
352 int reg_value = 0;
353 int viafb_load_reg_num;
354 struct io_register *reg = NULL;
355
356 DEBUG_MSG(KERN_INFO "load_lcd_scaling()!!\n");
357
358 /* LCD Scaling Enable */
359 viafb_write_reg_mask(CR79, VIACR, 0x07, BIT0 + BIT1 + BIT2);
360
361 /* Check if expansion for horizontal */
362 if (set_hres < panel_hres) {
363 /* Load Horizontal Scaling Factor */
364 switch (viaparinfo->chip_info->gfx_chip_name) {
365 case UNICHROME_CLE266:
366 case UNICHROME_K400:
367 reg_value =
368 CLE266_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
369 viafb_load_reg_num =
370 lcd_scaling_factor_CLE.lcd_hor_scaling_factor.
371 reg_num;
372 reg = lcd_scaling_factor_CLE.lcd_hor_scaling_factor.reg;
373 viafb_load_reg(reg_value,
374 viafb_load_reg_num, reg, VIACR);
375 break;
376 case UNICHROME_K800:
377 case UNICHROME_PM800:
378 case UNICHROME_CN700:
379 case UNICHROME_CX700:
380 case UNICHROME_K8M890:
381 case UNICHROME_P4M890:
382 case UNICHROME_P4M900:
383 case UNICHROME_CN750:
384 case UNICHROME_VX800:
385 case UNICHROME_VX855:
386 case UNICHROME_VX900:
387 reg_value =
388 K800_LCD_HOR_SCF_FORMULA(set_hres, panel_hres);
389 /* Horizontal scaling enabled */
390 viafb_write_reg_mask(CRA2, VIACR, 0xC0, BIT7 + BIT6);
391 viafb_load_reg_num =
392 lcd_scaling_factor.lcd_hor_scaling_factor.reg_num;
393 reg = lcd_scaling_factor.lcd_hor_scaling_factor.reg;
394 viafb_load_reg(reg_value,
395 viafb_load_reg_num, reg, VIACR);
396 break;
397 }
398
399 DEBUG_MSG(KERN_INFO "Horizontal Scaling value = %d", reg_value);
400 } else {
401 /* Horizontal scaling disabled */
402 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT7);
403 }
404
405 /* Check if expansion for vertical */
406 if (set_vres < panel_vres) {
407 /* Load Vertical Scaling Factor */
408 switch (viaparinfo->chip_info->gfx_chip_name) {
409 case UNICHROME_CLE266:
410 case UNICHROME_K400:
411 reg_value =
412 CLE266_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
413 viafb_load_reg_num =
414 lcd_scaling_factor_CLE.lcd_ver_scaling_factor.
415 reg_num;
416 reg = lcd_scaling_factor_CLE.lcd_ver_scaling_factor.reg;
417 viafb_load_reg(reg_value,
418 viafb_load_reg_num, reg, VIACR);
419 break;
420 case UNICHROME_K800:
421 case UNICHROME_PM800:
422 case UNICHROME_CN700:
423 case UNICHROME_CX700:
424 case UNICHROME_K8M890:
425 case UNICHROME_P4M890:
426 case UNICHROME_P4M900:
427 case UNICHROME_CN750:
428 case UNICHROME_VX800:
429 case UNICHROME_VX855:
430 case UNICHROME_VX900:
431 reg_value =
432 K800_LCD_VER_SCF_FORMULA(set_vres, panel_vres);
433 /* Vertical scaling enabled */
434 viafb_write_reg_mask(CRA2, VIACR, 0x08, BIT3);
435 viafb_load_reg_num =
436 lcd_scaling_factor.lcd_ver_scaling_factor.reg_num;
437 reg = lcd_scaling_factor.lcd_ver_scaling_factor.reg;
438 viafb_load_reg(reg_value,
439 viafb_load_reg_num, reg, VIACR);
440 break;
441 }
442
443 DEBUG_MSG(KERN_INFO "Vertical Scaling value = %d", reg_value);
444 } else {
445 /* Vertical scaling disabled */
446 viafb_write_reg_mask(CRA2, VIACR, 0x00, BIT3);
447 }
448}
449
450static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
451{
452 unsigned char cr13, cr35, cr65, cr66, cr67;
453 unsigned long dwScreenPitch = 0;
454 unsigned long dwPitch;
455
456 dwPitch = hres * (bpp >> 3);
457 if (dwPitch & 0x1F) {
458 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
459 if (iga_path == IGA2) {
460 if (bpp > 8) {
461 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
462 viafb_write_reg(CR66, VIACR, cr66);
463 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
464 cr67 |=
465 (unsigned
466 char)((dwScreenPitch & 0x300) >> 8);
467 viafb_write_reg(CR67, VIACR, cr67);
468 }
469
470 /* Fetch Count */
471 cr67 = viafb_read_reg(VIACR, CR67) & 0xF3;
472 cr67 |= (unsigned char)((dwScreenPitch & 0x600) >> 7);
473 viafb_write_reg(CR67, VIACR, cr67);
474 cr65 = (unsigned char)((dwScreenPitch >> 1) & 0xFF);
475 cr65 += 2;
476 viafb_write_reg(CR65, VIACR, cr65);
477 } else {
478 if (bpp > 8) {
479 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
480 viafb_write_reg(CR13, VIACR, cr13);
481 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
482 cr35 |=
483 (unsigned
484 char)((dwScreenPitch & 0x700) >> 3);
485 viafb_write_reg(CR35, VIACR, cr35);
486 }
487 }
488 }
489}
490static void lcd_patch_skew_dvp0(struct lvds_setting_information
491 *plvds_setting_info,
492 struct lvds_chip_information *plvds_chip_info)
493{
494 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
495 switch (viaparinfo->chip_info->gfx_chip_name) {
496 case UNICHROME_P4M900:
497 viafb_vt1636_patch_skew_on_vt3364(plvds_setting_info,
498 plvds_chip_info);
499 break;
500 case UNICHROME_P4M890:
501 viafb_vt1636_patch_skew_on_vt3327(plvds_setting_info,
502 plvds_chip_info);
503 break;
504 }
505 }
506}
507static void lcd_patch_skew_dvp1(struct lvds_setting_information
508 *plvds_setting_info,
509 struct lvds_chip_information *plvds_chip_info)
510{
511 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) {
512 switch (viaparinfo->chip_info->gfx_chip_name) {
513 case UNICHROME_CX700:
514 viafb_vt1636_patch_skew_on_vt3324(plvds_setting_info,
515 plvds_chip_info);
516 break;
517 }
518 }
519}
520static void lcd_patch_skew(struct lvds_setting_information
521 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
522{
523 DEBUG_MSG(KERN_INFO "lcd_patch_skew\n");
524 switch (plvds_chip_info->output_interface) {
525 case INTERFACE_DVP0:
526 lcd_patch_skew_dvp0(plvds_setting_info, plvds_chip_info);
527 break;
528 case INTERFACE_DVP1:
529 lcd_patch_skew_dvp1(plvds_setting_info, plvds_chip_info);
530 break;
531 case INTERFACE_DFP_LOW:
532 if (UNICHROME_P4M900 == viaparinfo->chip_info->gfx_chip_name) {
533 viafb_write_reg_mask(CR99, VIACR, 0x08,
534 BIT0 + BIT1 + BIT2 + BIT3);
535 }
536 break;
537 }
538}
539
540/* LCD Set Mode */
541void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
542 u16 cyres, struct lvds_setting_information *plvds_setting_info,
543 struct lvds_chip_information *plvds_chip_info)
544{
545 int set_iga = plvds_setting_info->iga_path;
546 int mode_bpp = var->bits_per_pixel;
547 int set_hres = cxres ? cxres : var->xres;
548 int set_vres = cyres ? cyres : var->yres;
549 int panel_hres = plvds_setting_info->lcd_panel_hres;
550 int panel_vres = plvds_setting_info->lcd_panel_vres;
551 u32 clock;
552 struct via_display_timing timing;
553 struct fb_var_screeninfo panel_var;
554 const struct fb_videomode *mode_crt_table, *panel_crt_table;
555
556 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
557 /* Get mode table */
558 mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
559 /* Get panel table Pointer */
560 panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
561 viafb_fill_var_timing_info(&panel_var, panel_crt_table);
562 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
563 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
564 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
565 clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
566 plvds_setting_info->vclk = clock;
567
568 if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
569 && plvds_setting_info->display_method == LCD_EXPANDSION) {
570 timing = var_to_timing(&panel_var, panel_hres, panel_vres);
571 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
572 } else {
573 timing = var_to_timing(&panel_var, set_hres, set_vres);
574 if (set_iga == IGA2)
575 /* disable scaling */
576 via_write_reg_mask(VIACR, 0x79, 0x00,
577 BIT0 + BIT1 + BIT2);
578 }
579
580 if (set_iga == IGA1)
581 via_set_primary_timing(&timing);
582 else if (set_iga == IGA2)
583 via_set_secondary_timing(&timing);
584
585 /* Fetch count for IGA2 only */
586 viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga);
587
588 if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266)
589 && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
590 viafb_load_FIFO_reg(set_iga, set_hres, set_vres);
591
592 fill_lcd_format();
593 viafb_set_vclock(clock, set_iga);
594 lcd_patch_skew(plvds_setting_info, plvds_chip_info);
595
596 /* If K8M800, enable LCD Prefetch Mode. */
597 if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_K800)
598 || (UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name))
599 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
600
601 /* Patch for non 32bit alignment mode */
602 via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
603 var->bits_per_pixel);
604}
605
606static void integrated_lvds_disable(struct lvds_setting_information
607 *plvds_setting_info,
608 struct lvds_chip_information *plvds_chip_info)
609{
610 bool turn_off_first_powersequence = false;
611 bool turn_off_second_powersequence = false;
612 if (INTERFACE_LVDS0LVDS1 == plvds_chip_info->output_interface)
613 turn_off_first_powersequence = true;
614 if (INTERFACE_LVDS0 == plvds_chip_info->output_interface)
615 turn_off_first_powersequence = true;
616 if (INTERFACE_LVDS1 == plvds_chip_info->output_interface)
617 turn_off_second_powersequence = true;
618 if (turn_off_second_powersequence) {
619 /* Use second power sequence control: */
620
621 /* Turn off power sequence. */
622 viafb_write_reg_mask(CRD4, VIACR, 0, BIT1);
623
624 /* Turn off back light. */
625 viafb_write_reg_mask(CRD3, VIACR, 0xC0, BIT6 + BIT7);
626 }
627 if (turn_off_first_powersequence) {
628 /* Use first power sequence control: */
629
630 /* Turn off power sequence. */
631 viafb_write_reg_mask(CR6A, VIACR, 0, BIT3);
632
633 /* Turn off back light. */
634 viafb_write_reg_mask(CR91, VIACR, 0xC0, BIT6 + BIT7);
635 }
636
637 /* Power off LVDS channel. */
638 switch (plvds_chip_info->output_interface) {
639 case INTERFACE_LVDS0:
640 {
641 viafb_write_reg_mask(CRD2, VIACR, 0x80, BIT7);
642 break;
643 }
644
645 case INTERFACE_LVDS1:
646 {
647 viafb_write_reg_mask(CRD2, VIACR, 0x40, BIT6);
648 break;
649 }
650
651 case INTERFACE_LVDS0LVDS1:
652 {
653 viafb_write_reg_mask(CRD2, VIACR, 0xC0, BIT6 + BIT7);
654 break;
655 }
656 }
657}
658
659static void integrated_lvds_enable(struct lvds_setting_information
660 *plvds_setting_info,
661 struct lvds_chip_information *plvds_chip_info)
662{
663 DEBUG_MSG(KERN_INFO "integrated_lvds_enable, out_interface:%d\n",
664 plvds_chip_info->output_interface);
665 if (plvds_setting_info->lcd_mode == LCD_SPWG)
666 viafb_write_reg_mask(CRD2, VIACR, 0x00, BIT0 + BIT1);
667 else
668 viafb_write_reg_mask(CRD2, VIACR, 0x03, BIT0 + BIT1);
669
670 switch (plvds_chip_info->output_interface) {
671 case INTERFACE_LVDS0LVDS1:
672 case INTERFACE_LVDS0:
673 /* Use first power sequence control: */
674 /* Use hardware control power sequence. */
675 viafb_write_reg_mask(CR91, VIACR, 0, BIT0);
676 /* Turn on back light. */
677 viafb_write_reg_mask(CR91, VIACR, 0, BIT6 + BIT7);
678 /* Turn on hardware power sequence. */
679 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
680 break;
681 case INTERFACE_LVDS1:
682 /* Use second power sequence control: */
683 /* Use hardware control power sequence. */
684 viafb_write_reg_mask(CRD3, VIACR, 0, BIT0);
685 /* Turn on back light. */
686 viafb_write_reg_mask(CRD3, VIACR, 0, BIT6 + BIT7);
687 /* Turn on hardware power sequence. */
688 viafb_write_reg_mask(CRD4, VIACR, 0x02, BIT1);
689 break;
690 }
691
692 /* Power on LVDS channel. */
693 switch (plvds_chip_info->output_interface) {
694 case INTERFACE_LVDS0:
695 {
696 viafb_write_reg_mask(CRD2, VIACR, 0, BIT7);
697 break;
698 }
699
700 case INTERFACE_LVDS1:
701 {
702 viafb_write_reg_mask(CRD2, VIACR, 0, BIT6);
703 break;
704 }
705
706 case INTERFACE_LVDS0LVDS1:
707 {
708 viafb_write_reg_mask(CRD2, VIACR, 0, BIT6 + BIT7);
709 break;
710 }
711 }
712}
713
714void viafb_lcd_disable(void)
715{
716
717 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
718 lcd_powersequence_off();
719 /* DI1 pad off */
720 viafb_write_reg_mask(SR1E, VIASR, 0x00, 0x30);
721 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
722 if (viafb_LCD2_ON
723 && (INTEGRATED_LVDS ==
724 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
725 integrated_lvds_disable(viaparinfo->lvds_setting_info,
726 &viaparinfo->chip_info->lvds_chip_info2);
727 if (INTEGRATED_LVDS ==
728 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
729 integrated_lvds_disable(viaparinfo->lvds_setting_info,
730 &viaparinfo->chip_info->lvds_chip_info);
731 if (VT1636_LVDS == viaparinfo->chip_info->
732 lvds_chip_info.lvds_chip_name)
733 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
734 &viaparinfo->chip_info->lvds_chip_info);
735 } else if (VT1636_LVDS ==
736 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
737 viafb_disable_lvds_vt1636(viaparinfo->lvds_setting_info,
738 &viaparinfo->chip_info->lvds_chip_info);
739 } else {
740 /* Backlight off */
741 viafb_write_reg_mask(SR3D, VIASR, 0x00, 0x20);
742 /* 24 bit DI data paht off */
743 viafb_write_reg_mask(CR91, VIACR, 0x80, 0x80);
744 }
745
746 /* Disable expansion bit */
747 viafb_write_reg_mask(CR79, VIACR, 0x00, 0x01);
748 /* Simultaneout disabled */
749 viafb_write_reg_mask(CR6B, VIACR, 0x00, 0x08);
750}
751
752static void set_lcd_output_path(int set_iga, int output_interface)
753{
754 switch (output_interface) {
755 case INTERFACE_DFP:
756 if ((UNICHROME_K8M890 == viaparinfo->chip_info->gfx_chip_name)
757 || (UNICHROME_P4M890 ==
758 viaparinfo->chip_info->gfx_chip_name))
759 viafb_write_reg_mask(CR97, VIACR, 0x84,
760 BIT7 + BIT2 + BIT1 + BIT0);
761 case INTERFACE_DVP0:
762 case INTERFACE_DVP1:
763 case INTERFACE_DFP_HIGH:
764 case INTERFACE_DFP_LOW:
765 if (set_iga == IGA2)
766 viafb_write_reg(CR91, VIACR, 0x00);
767 break;
768 }
769}
770
771void viafb_lcd_enable(void)
772{
773 viafb_write_reg_mask(CR6B, VIACR, 0x00, BIT3);
774 viafb_write_reg_mask(CR6A, VIACR, 0x08, BIT3);
775 set_lcd_output_path(viaparinfo->lvds_setting_info->iga_path,
776 viaparinfo->chip_info->lvds_chip_info.output_interface);
777 if (viafb_LCD2_ON)
778 set_lcd_output_path(viaparinfo->lvds_setting_info2->iga_path,
779 viaparinfo->chip_info->
780 lvds_chip_info2.output_interface);
781
782 if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) {
783 /* DI1 pad on */
784 viafb_write_reg_mask(SR1E, VIASR, 0x30, 0x30);
785 lcd_powersequence_on();
786 } else if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CX700) {
787 if (viafb_LCD2_ON && (INTEGRATED_LVDS ==
788 viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name))
789 integrated_lvds_enable(viaparinfo->lvds_setting_info2, \
790 &viaparinfo->chip_info->lvds_chip_info2);
791 if (INTEGRATED_LVDS ==
792 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name)
793 integrated_lvds_enable(viaparinfo->lvds_setting_info,
794 &viaparinfo->chip_info->lvds_chip_info);
795 if (VT1636_LVDS == viaparinfo->chip_info->
796 lvds_chip_info.lvds_chip_name)
797 viafb_enable_lvds_vt1636(viaparinfo->
798 lvds_setting_info, &viaparinfo->chip_info->
799 lvds_chip_info);
800 } else if (VT1636_LVDS ==
801 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
802 viafb_enable_lvds_vt1636(viaparinfo->lvds_setting_info,
803 &viaparinfo->chip_info->lvds_chip_info);
804 } else {
805 /* Backlight on */
806 viafb_write_reg_mask(SR3D, VIASR, 0x20, 0x20);
807 /* 24 bit DI data paht on */
808 viafb_write_reg_mask(CR91, VIACR, 0x00, 0x80);
809 /* LCD enabled */
810 viafb_write_reg_mask(CR6A, VIACR, 0x48, 0x48);
811 }
812}
813
814static void lcd_powersequence_off(void)
815{
816 int i, mask, data;
817
818 /* Software control power sequence */
819 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
820
821 for (i = 0; i < 3; i++) {
822 mask = PowerSequenceOff[0][i];
823 data = PowerSequenceOff[1][i] & mask;
824 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
825 udelay(PowerSequenceOff[2][i]);
826 }
827
828 /* Disable LCD */
829 viafb_write_reg_mask(CR6A, VIACR, 0x00, 0x08);
830}
831
832static void lcd_powersequence_on(void)
833{
834 int i, mask, data;
835
836 /* Software control power sequence */
837 viafb_write_reg_mask(CR91, VIACR, 0x11, 0x11);
838
839 /* Enable LCD */
840 viafb_write_reg_mask(CR6A, VIACR, 0x08, 0x08);
841
842 for (i = 0; i < 3; i++) {
843 mask = PowerSequenceOn[0][i];
844 data = PowerSequenceOn[1][i] & mask;
845 viafb_write_reg_mask(CR91, VIACR, (u8) data, (u8) mask);
846 udelay(PowerSequenceOn[2][i]);
847 }
848
849 udelay(1);
850}
851
852static void fill_lcd_format(void)
853{
854 u8 bdithering = 0, bdual = 0;
855
856 if (viaparinfo->lvds_setting_info->device_lcd_dualedge)
857 bdual = BIT4;
858 if (viaparinfo->lvds_setting_info->LCDDithering)
859 bdithering = BIT0;
860 /* Dual & Dithering */
861 viafb_write_reg_mask(CR88, VIACR, (bdithering | bdual), BIT4 + BIT0);
862}
863
864static void check_diport_of_integrated_lvds(
865 struct lvds_chip_information *plvds_chip_info,
866 struct lvds_setting_information
867 *plvds_setting_info)
868{
869 /* Determine LCD DI Port by hardware layout. */
870 switch (viafb_display_hardware_layout) {
871 case HW_LAYOUT_LCD_ONLY:
872 {
873 if (plvds_setting_info->device_lcd_dualedge) {
874 plvds_chip_info->output_interface =
875 INTERFACE_LVDS0LVDS1;
876 } else {
877 plvds_chip_info->output_interface =
878 INTERFACE_LVDS0;
879 }
880
881 break;
882 }
883
884 case HW_LAYOUT_DVI_ONLY:
885 {
886 plvds_chip_info->output_interface = INTERFACE_NONE;
887 break;
888 }
889
890 case HW_LAYOUT_LCD1_LCD2:
891 case HW_LAYOUT_LCD_EXTERNAL_LCD2:
892 {
893 plvds_chip_info->output_interface =
894 INTERFACE_LVDS0LVDS1;
895 break;
896 }
897
898 case HW_LAYOUT_LCD_DVI:
899 {
900 plvds_chip_info->output_interface = INTERFACE_LVDS1;
901 break;
902 }
903
904 default:
905 {
906 plvds_chip_info->output_interface = INTERFACE_LVDS1;
907 break;
908 }
909 }
910
911 DEBUG_MSG(KERN_INFO
912 "Display Hardware Layout: 0x%x, LCD DI Port: 0x%x\n",
913 viafb_display_hardware_layout,
914 plvds_chip_info->output_interface);
915}
916
917void viafb_init_lvds_output_interface(struct lvds_chip_information
918 *plvds_chip_info,
919 struct lvds_setting_information
920 *plvds_setting_info)
921{
922 if (INTERFACE_NONE != plvds_chip_info->output_interface) {
923 /*Do nothing, lcd port is specified by module parameter */
924 return;
925 }
926
927 switch (plvds_chip_info->lvds_chip_name) {
928
929 case VT1636_LVDS:
930 switch (viaparinfo->chip_info->gfx_chip_name) {
931 case UNICHROME_CX700:
932 plvds_chip_info->output_interface = INTERFACE_DVP1;
933 break;
934 case UNICHROME_CN700:
935 plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
936 break;
937 default:
938 plvds_chip_info->output_interface = INTERFACE_DVP0;
939 break;
940 }
941 break;
942
943 case INTEGRATED_LVDS:
944 check_diport_of_integrated_lvds(plvds_chip_info,
945 plvds_setting_info);
946 break;
947
948 default:
949 switch (viaparinfo->chip_info->gfx_chip_name) {
950 case UNICHROME_K8M890:
951 case UNICHROME_P4M900:
952 case UNICHROME_P4M890:
953 plvds_chip_info->output_interface = INTERFACE_DFP_LOW;
954 break;
955 default:
956 plvds_chip_info->output_interface = INTERFACE_DFP;
957 break;
958 }
959 break;
960 }
961}
962
963bool viafb_lcd_get_mobile_state(bool *mobile)
964{
965 unsigned char __iomem *romptr, *tableptr, *biosptr;
966 u8 core_base;
967 /* Rom address */
968 const u32 romaddr = 0x000C0000;
969 u16 start_pattern;
970
971 biosptr = ioremap(romaddr, 0x10000);
972 start_pattern = readw(biosptr);
973
974 /* Compare pattern */
975 if (start_pattern == 0xAA55) {
976 /* Get the start of Table */
977 /* 0x1B means BIOS offset position */
978 romptr = biosptr + 0x1B;
979 tableptr = biosptr + readw(romptr);
980
981 /* Get the start of biosver structure */
982 /* 18 means BIOS version position. */
983 romptr = tableptr + 18;
984 romptr = biosptr + readw(romptr);
985
986 /* The offset should be 44, but the
987 actual image is less three char. */
988 /* pRom += 44; */
989 romptr += 41;
990
991 core_base = readb(romptr);
992
993 if (core_base & 0x8)
994 *mobile = false;
995 else
996 *mobile = true;
997 /* release memory */
998 iounmap(biosptr);
999
1000 return true;
1001 } else {
1002 iounmap(biosptr);
1003 return false;
1004 }
1005}
diff --git a/drivers/video/fbdev/via/lcd.h b/drivers/video/fbdev/via/lcd.h
new file mode 100644
index 000000000000..5c988a063ad5
--- /dev/null
+++ b/drivers/video/fbdev/via/lcd.h
@@ -0,0 +1,89 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __LCD_H__
22#define __LCD_H__
23
24/*Definition TMDS Device ID register*/
25#define VT1631_DEVICE_ID_REG 0x02
26#define VT1631_DEVICE_ID 0x92
27
28#define VT3271_DEVICE_ID_REG 0x02
29#define VT3271_DEVICE_ID 0x71
30
31/* Definition DVI Panel ID*/
32/* Resolution: 640x480, Channel: single, Dithering: Enable */
33#define LCD_PANEL_ID0_640X480 0x00
34/* Resolution: 800x600, Channel: single, Dithering: Enable */
35#define LCD_PANEL_ID1_800X600 0x01
36/* Resolution: 1024x768, Channel: single, Dithering: Enable */
37#define LCD_PANEL_ID2_1024X768 0x02
38/* Resolution: 1280x768, Channel: single, Dithering: Enable */
39#define LCD_PANEL_ID3_1280X768 0x03
40/* Resolution: 1280x1024, Channel: dual, Dithering: Enable */
41#define LCD_PANEL_ID4_1280X1024 0x04
42/* Resolution: 1400x1050, Channel: dual, Dithering: Enable */
43#define LCD_PANEL_ID5_1400X1050 0x05
44/* Resolution: 1600x1200, Channel: dual, Dithering: Enable */
45#define LCD_PANEL_ID6_1600X1200 0x06
46/* Resolution: 1366x768, Channel: single, Dithering: Disable */
47#define LCD_PANEL_ID7_1366X768 0x07
48/* Resolution: 1024x600, Channel: single, Dithering: Enable*/
49#define LCD_PANEL_ID8_1024X600 0x08
50/* Resolution: 1280x800, Channel: single, Dithering: Enable*/
51#define LCD_PANEL_ID9_1280X800 0x09
52/* Resolution: 800x480, Channel: single, Dithering: Enable*/
53#define LCD_PANEL_IDA_800X480 0x0A
54/* Resolution: 1360x768, Channel: single, Dithering: Disable*/
55#define LCD_PANEL_IDB_1360X768 0x0B
56/* Resolution: 480x640, Channel: single, Dithering: Enable */
57#define LCD_PANEL_IDC_480X640 0x0C
58/* Resolution: 1200x900, Channel: single, Dithering: Disable */
59#define LCD_PANEL_IDD_1200X900 0x0D
60
61
62extern int viafb_LCD2_ON;
63extern int viafb_LCD_ON;
64extern int viafb_DVI_ON;
65
66void viafb_disable_lvds_vt1636(struct lvds_setting_information
67 *plvds_setting_info,
68 struct lvds_chip_information *plvds_chip_info);
69void viafb_enable_lvds_vt1636(struct lvds_setting_information
70 *plvds_setting_info,
71 struct lvds_chip_information *plvds_chip_info);
72void viafb_lcd_disable(void);
73void viafb_lcd_enable(void);
74void viafb_init_lcd_size(void);
75void viafb_init_lvds_output_interface(struct lvds_chip_information
76 *plvds_chip_info,
77 struct lvds_setting_information
78 *plvds_setting_info);
79void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
80 u16 cyres, struct lvds_setting_information *plvds_setting_info,
81 struct lvds_chip_information *plvds_chip_info);
82bool viafb_lvds_trasmitter_identify(void);
83void viafb_init_lvds_output_interface(struct lvds_chip_information
84 *plvds_chip_info,
85 struct lvds_setting_information
86 *plvds_setting_info);
87bool viafb_lcd_get_mobile_state(bool *mobile);
88
89#endif /* __LCD_H__ */
diff --git a/drivers/video/fbdev/via/share.h b/drivers/video/fbdev/via/share.h
new file mode 100644
index 000000000000..65c65c611e0a
--- /dev/null
+++ b/drivers/video/fbdev/via/share.h
@@ -0,0 +1,332 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __SHARE_H__
23#define __SHARE_H__
24
25#include "via_modesetting.h"
26
27/* Define Bit Field */
28#define BIT0 0x01
29#define BIT1 0x02
30#define BIT2 0x04
31#define BIT3 0x08
32#define BIT4 0x10
33#define BIT5 0x20
34#define BIT6 0x40
35#define BIT7 0x80
36
37/* Video Memory Size */
38#define VIDEO_MEMORY_SIZE_16M 0x1000000
39
40/*
41 * Lengths of the VPIT structure arrays.
42 */
43#define StdCR 0x19
44#define StdSR 0x04
45#define StdGR 0x09
46#define StdAR 0x14
47
48#define PatchCR 11
49
50/* Display path */
51#define IGA1 1
52#define IGA2 2
53
54/* Define Color Depth */
55#define MODE_8BPP 1
56#define MODE_16BPP 2
57#define MODE_32BPP 4
58
59#define GR20 0x20
60#define GR21 0x21
61#define GR22 0x22
62
63/* Sequencer Registers */
64#define SR01 0x01
65#define SR10 0x10
66#define SR12 0x12
67#define SR15 0x15
68#define SR16 0x16
69#define SR17 0x17
70#define SR18 0x18
71#define SR1B 0x1B
72#define SR1A 0x1A
73#define SR1C 0x1C
74#define SR1D 0x1D
75#define SR1E 0x1E
76#define SR1F 0x1F
77#define SR20 0x20
78#define SR21 0x21
79#define SR22 0x22
80#define SR2A 0x2A
81#define SR2D 0x2D
82#define SR2E 0x2E
83
84#define SR30 0x30
85#define SR39 0x39
86#define SR3D 0x3D
87#define SR3E 0x3E
88#define SR3F 0x3F
89#define SR40 0x40
90#define SR43 0x43
91#define SR44 0x44
92#define SR45 0x45
93#define SR46 0x46
94#define SR47 0x47
95#define SR48 0x48
96#define SR49 0x49
97#define SR4A 0x4A
98#define SR4B 0x4B
99#define SR4C 0x4C
100#define SR52 0x52
101#define SR57 0x57
102#define SR58 0x58
103#define SR59 0x59
104#define SR5D 0x5D
105#define SR5E 0x5E
106#define SR65 0x65
107
108/* CRT Controller Registers */
109#define CR00 0x00
110#define CR01 0x01
111#define CR02 0x02
112#define CR03 0x03
113#define CR04 0x04
114#define CR05 0x05
115#define CR06 0x06
116#define CR07 0x07
117#define CR08 0x08
118#define CR09 0x09
119#define CR0A 0x0A
120#define CR0B 0x0B
121#define CR0C 0x0C
122#define CR0D 0x0D
123#define CR0E 0x0E
124#define CR0F 0x0F
125#define CR10 0x10
126#define CR11 0x11
127#define CR12 0x12
128#define CR13 0x13
129#define CR14 0x14
130#define CR15 0x15
131#define CR16 0x16
132#define CR17 0x17
133#define CR18 0x18
134
135/* Extend CRT Controller Registers */
136#define CR30 0x30
137#define CR31 0x31
138#define CR32 0x32
139#define CR33 0x33
140#define CR34 0x34
141#define CR35 0x35
142#define CR36 0x36
143#define CR37 0x37
144#define CR38 0x38
145#define CR39 0x39
146#define CR3A 0x3A
147#define CR3B 0x3B
148#define CR3C 0x3C
149#define CR3D 0x3D
150#define CR3E 0x3E
151#define CR3F 0x3F
152#define CR40 0x40
153#define CR41 0x41
154#define CR42 0x42
155#define CR43 0x43
156#define CR44 0x44
157#define CR45 0x45
158#define CR46 0x46
159#define CR47 0x47
160#define CR48 0x48
161#define CR49 0x49
162#define CR4A 0x4A
163#define CR4B 0x4B
164#define CR4C 0x4C
165#define CR4D 0x4D
166#define CR4E 0x4E
167#define CR4F 0x4F
168#define CR50 0x50
169#define CR51 0x51
170#define CR52 0x52
171#define CR53 0x53
172#define CR54 0x54
173#define CR55 0x55
174#define CR56 0x56
175#define CR57 0x57
176#define CR58 0x58
177#define CR59 0x59
178#define CR5A 0x5A
179#define CR5B 0x5B
180#define CR5C 0x5C
181#define CR5D 0x5D
182#define CR5E 0x5E
183#define CR5F 0x5F
184#define CR60 0x60
185#define CR61 0x61
186#define CR62 0x62
187#define CR63 0x63
188#define CR64 0x64
189#define CR65 0x65
190#define CR66 0x66
191#define CR67 0x67
192#define CR68 0x68
193#define CR69 0x69
194#define CR6A 0x6A
195#define CR6B 0x6B
196#define CR6C 0x6C
197#define CR6D 0x6D
198#define CR6E 0x6E
199#define CR6F 0x6F
200#define CR70 0x70
201#define CR71 0x71
202#define CR72 0x72
203#define CR73 0x73
204#define CR74 0x74
205#define CR75 0x75
206#define CR76 0x76
207#define CR77 0x77
208#define CR78 0x78
209#define CR79 0x79
210#define CR7A 0x7A
211#define CR7B 0x7B
212#define CR7C 0x7C
213#define CR7D 0x7D
214#define CR7E 0x7E
215#define CR7F 0x7F
216#define CR80 0x80
217#define CR81 0x81
218#define CR82 0x82
219#define CR83 0x83
220#define CR84 0x84
221#define CR85 0x85
222#define CR86 0x86
223#define CR87 0x87
224#define CR88 0x88
225#define CR89 0x89
226#define CR8A 0x8A
227#define CR8B 0x8B
228#define CR8C 0x8C
229#define CR8D 0x8D
230#define CR8E 0x8E
231#define CR8F 0x8F
232#define CR90 0x90
233#define CR91 0x91
234#define CR92 0x92
235#define CR93 0x93
236#define CR94 0x94
237#define CR95 0x95
238#define CR96 0x96
239#define CR97 0x97
240#define CR98 0x98
241#define CR99 0x99
242#define CR9A 0x9A
243#define CR9B 0x9B
244#define CR9C 0x9C
245#define CR9D 0x9D
246#define CR9E 0x9E
247#define CR9F 0x9F
248#define CRA0 0xA0
249#define CRA1 0xA1
250#define CRA2 0xA2
251#define CRA3 0xA3
252#define CRD2 0xD2
253#define CRD3 0xD3
254#define CRD4 0xD4
255
256/* LUT Table*/
257#define LUT_DATA 0x3C9 /* DACDATA */
258#define LUT_INDEX_READ 0x3C7 /* DACRX */
259#define LUT_INDEX_WRITE 0x3C8 /* DACWX */
260#define DACMASK 0x3C6
261
262/* Definition Device */
263#define DEVICE_CRT 0x01
264#define DEVICE_DVI 0x03
265#define DEVICE_LCD 0x04
266
267/* Device output interface */
268#define INTERFACE_NONE 0x00
269#define INTERFACE_ANALOG_RGB 0x01
270#define INTERFACE_DVP0 0x02
271#define INTERFACE_DVP1 0x03
272#define INTERFACE_DFP_HIGH 0x04
273#define INTERFACE_DFP_LOW 0x05
274#define INTERFACE_DFP 0x06
275#define INTERFACE_LVDS0 0x07
276#define INTERFACE_LVDS1 0x08
277#define INTERFACE_LVDS0LVDS1 0x09
278#define INTERFACE_TMDS 0x0A
279
280#define HW_LAYOUT_LCD_ONLY 0x01
281#define HW_LAYOUT_DVI_ONLY 0x02
282#define HW_LAYOUT_LCD_DVI 0x03
283#define HW_LAYOUT_LCD1_LCD2 0x04
284#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
285
286/* Definition CRTC Timing Index */
287#define H_TOTAL_INDEX 0
288#define H_ADDR_INDEX 1
289#define H_BLANK_START_INDEX 2
290#define H_BLANK_END_INDEX 3
291#define H_SYNC_START_INDEX 4
292#define H_SYNC_END_INDEX 5
293#define V_TOTAL_INDEX 6
294#define V_ADDR_INDEX 7
295#define V_BLANK_START_INDEX 8
296#define V_BLANK_END_INDEX 9
297#define V_SYNC_START_INDEX 10
298#define V_SYNC_END_INDEX 11
299#define H_TOTAL_SHADOW_INDEX 12
300#define H_BLANK_END_SHADOW_INDEX 13
301#define V_TOTAL_SHADOW_INDEX 14
302#define V_ADDR_SHADOW_INDEX 15
303#define V_BLANK_SATRT_SHADOW_INDEX 16
304#define V_BLANK_END_SHADOW_INDEX 17
305#define V_SYNC_SATRT_SHADOW_INDEX 18
306#define V_SYNC_END_SHADOW_INDEX 19
307
308/* LCD display method
309*/
310#define LCD_EXPANDSION 0x00
311#define LCD_CENTERING 0x01
312
313/* LCD mode
314*/
315#define LCD_OPENLDI 0x00
316#define LCD_SPWG 0x01
317
318struct crt_mode_table {
319 int refresh_rate;
320 int h_sync_polarity;
321 int v_sync_polarity;
322 struct via_display_timing crtc;
323};
324
325struct io_reg {
326 int port;
327 u8 index;
328 u8 mask;
329 u8 value;
330};
331
332#endif /* __SHARE_H__ */
diff --git a/drivers/video/fbdev/via/tblDPASetting.c b/drivers/video/fbdev/via/tblDPASetting.c
new file mode 100644
index 000000000000..73bb554e7c1e
--- /dev/null
+++ b/drivers/video/fbdev/via/tblDPASetting.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include "global.h"
23
24struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
25/* ClkRange, DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
26 DVP1Driving, DFPHigh, DFPLow */
27/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
28 SR65, CR97, CR99 */
29 /* LCK/VCK < 30000000 will use this value */
30 {DPA_CLK_RANGE_30M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
31 0x00},
32 /* 30000000 < LCK/VCK < 50000000 will use this value */
33 {DPA_CLK_RANGE_30_50M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
34 0x00},
35 /* 50000000 < LCK/VCK < 70000000 will use this value */
36 {DPA_CLK_RANGE_50_70M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
37 0x00},
38 /* 70000000 < LCK/VCK < 100000000 will use this value */
39 {DPA_CLK_RANGE_70_100M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
40 0x00},
41 /* 100000000 < LCK/VCK < 15000000 will use this value */
42 {DPA_CLK_RANGE_100_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
43 0x00},
44 /* 15000000 < LCK/VCK will use this value */
45 {DPA_CLK_RANGE_150M, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x00,
46 0x00},
47};
48
49struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
50/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
51 DVP1Driving, DFPHigh, DFPLow */
52/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
53 SR65, CR97, CR99 */
54/* LCK/VCK < 30000000 will use this value */
55{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
56/* 30000000 < LCK/VCK < 50000000 will use this value */
57{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
58/* 50000000 < LCK/VCK < 70000000 will use this value */
59{DPA_CLK_RANGE_50_70M, 0x06, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x01},
60/* 70000000 < LCK/VCK < 100000000 will use this value */
61{DPA_CLK_RANGE_70_100M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x08, 0x03},
62/* 100000000 < LCK/VCK < 15000000 will use this value */
63{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x02},
64/* 15000000 < LCK/VCK will use this value */
65{DPA_CLK_RANGE_150M, 0x00, 0x20, 0x00, 0x10, 0x00, 0x03, 0x00, 0x0D, 0x03},
66};
67
68/* For VT3364: */
69struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[] = {
70/* ClkRange,DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
71 DVP1Driving, DFPHigh, DFPLow */
72/* CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2], CR9B,
73 SR65, CR97, CR99 */
74/* LCK/VCK < 30000000 will use this value */
75{DPA_CLK_RANGE_30M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
76/* 30000000 < LCK/VCK < 50000000 will use this value */
77{DPA_CLK_RANGE_30_50M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
78/* 50000000 < LCK/VCK < 70000000 will use this value */
79{DPA_CLK_RANGE_50_70M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
80/* 70000000 < LCK/VCK < 100000000 will use this value */
81{DPA_CLK_RANGE_70_100M, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
82/* 100000000 < LCK/VCK < 15000000 will use this value */
83{DPA_CLK_RANGE_100_150M, 0x03, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x08},
84/* 15000000 < LCK/VCK will use this value */
85{DPA_CLK_RANGE_150M, 0x01, 0x00, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x08},
86};
diff --git a/drivers/video/fbdev/via/tblDPASetting.h b/drivers/video/fbdev/via/tblDPASetting.h
new file mode 100644
index 000000000000..6db61519cb5d
--- /dev/null
+++ b/drivers/video/fbdev/via/tblDPASetting.h
@@ -0,0 +1,45 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef _TBLDPASETTING_H_
23#define _TBLDPASETTING_H_
24#include "global.h"
25
26#define DPA_CLK_30M 30000000
27#define DPA_CLK_50M 50000000
28#define DPA_CLK_70M 70000000
29#define DPA_CLK_100M 100000000
30#define DPA_CLK_150M 150000000
31
32enum DPA_RANGE {
33 DPA_CLK_RANGE_30M,
34 DPA_CLK_RANGE_30_50M,
35 DPA_CLK_RANGE_50_70M,
36 DPA_CLK_RANGE_70_100M,
37 DPA_CLK_RANGE_100_150M,
38 DPA_CLK_RANGE_150M
39};
40
41extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
42extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
43extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
44
45#endif
diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c
new file mode 100644
index 000000000000..6e274825fb31
--- /dev/null
+++ b/drivers/video/fbdev/via/via-core.c
@@ -0,0 +1,790 @@
1/*
2 * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
5 */
6
7/*
8 * Core code for the Via multifunction framebuffer device.
9 */
10#include <linux/via-core.h>
11#include <linux/via_i2c.h>
12#include <linux/via-gpio.h>
13#include "global.h"
14
15#include <linux/module.h>
16#include <linux/interrupt.h>
17#include <linux/platform_device.h>
18#include <linux/list.h>
19#include <linux/pm.h>
20#include <asm/olpc.h>
21
22/*
23 * The default port config.
24 */
25static struct via_port_cfg adap_configs[] = {
26 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
27 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
28 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
29 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
30 [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
31 { 0, 0, 0, 0 }
32};
33
34/*
35 * The OLPC XO-1.5 puts the camera power and reset lines onto
36 * GPIO 2C.
37 */
38static struct via_port_cfg olpc_adap_configs[] = {
39 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
40 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
41 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
42 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
43 [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
44 { 0, 0, 0, 0 }
45};
46
47/*
48 * We currently only support one viafb device (will there ever be
49 * more than one?), so just declare it globally here.
50 */
51static struct viafb_dev global_dev;
52
53
54/*
55 * Basic register access; spinlock required.
56 */
57static inline void viafb_mmio_write(int reg, u32 v)
58{
59 iowrite32(v, global_dev.engine_mmio + reg);
60}
61
62static inline int viafb_mmio_read(int reg)
63{
64 return ioread32(global_dev.engine_mmio + reg);
65}
66
67/* ---------------------------------------------------------------------- */
68/*
69 * Interrupt management. We have a single IRQ line for a lot of
70 * different functions, so we need to share it. The design here
71 * is that we don't want to reimplement the shared IRQ code here;
72 * we also want to avoid having contention for a single handler thread.
73 * So each subdev driver which needs interrupts just requests
74 * them directly from the kernel. We just have what's needed for
75 * overall access to the interrupt control register.
76 */
77
78/*
79 * Which interrupts are enabled now?
80 */
81static u32 viafb_enabled_ints;
82
83static void viafb_int_init(void)
84{
85 viafb_enabled_ints = 0;
86
87 viafb_mmio_write(VDE_INTERRUPT, 0);
88}
89
90/*
91 * Allow subdevs to ask for specific interrupts to be enabled. These
92 * functions must be called with reg_lock held
93 */
94void viafb_irq_enable(u32 mask)
95{
96 viafb_enabled_ints |= mask;
97 viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE);
98}
99EXPORT_SYMBOL_GPL(viafb_irq_enable);
100
101void viafb_irq_disable(u32 mask)
102{
103 viafb_enabled_ints &= ~mask;
104 if (viafb_enabled_ints == 0)
105 viafb_mmio_write(VDE_INTERRUPT, 0); /* Disable entirely */
106 else
107 viafb_mmio_write(VDE_INTERRUPT,
108 viafb_enabled_ints | VDE_I_ENABLE);
109}
110EXPORT_SYMBOL_GPL(viafb_irq_disable);
111
112/* ---------------------------------------------------------------------- */
113/*
114 * Currently, the camera driver is the only user of the DMA code, so we
115 * only compile it in if the camera driver is being built. Chances are,
116 * most viafb systems will not need to have this extra code for a while.
117 * As soon as another user comes long, the ifdef can be removed.
118 */
119#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
120/*
121 * Access to the DMA engine. This currently provides what the camera
122 * driver needs (i.e. outgoing only) but is easily expandable if need
123 * be.
124 */
125
126/*
127 * There are four DMA channels in the vx855. For now, we only
128 * use one of them, though. Most of the time, the DMA channel
129 * will be idle, so we keep the IRQ handler unregistered except
130 * when some subsystem has indicated an interest.
131 */
132static int viafb_dma_users;
133static DECLARE_COMPLETION(viafb_dma_completion);
134/*
135 * This mutex protects viafb_dma_users and our global interrupt
136 * registration state; it also serializes access to the DMA
137 * engine.
138 */
139static DEFINE_MUTEX(viafb_dma_lock);
140
141/*
142 * The VX855 DMA descriptor (used for s/g transfers) looks
143 * like this.
144 */
145struct viafb_vx855_dma_descr {
146 u32 addr_low; /* Low part of phys addr */
147 u32 addr_high; /* High 12 bits of addr */
148 u32 fb_offset; /* Offset into FB memory */
149 u32 seg_size; /* Size, 16-byte units */
150 u32 tile_mode; /* "tile mode" setting */
151 u32 next_desc_low; /* Next descriptor addr */
152 u32 next_desc_high;
153 u32 pad; /* Fill out to 64 bytes */
154};
155
156/*
157 * Flags added to the "next descriptor low" pointers
158 */
159#define VIAFB_DMA_MAGIC 0x01 /* ??? Just has to be there */
160#define VIAFB_DMA_FINAL_SEGMENT 0x02 /* Final segment */
161
162/*
163 * The completion IRQ handler.
164 */
165static irqreturn_t viafb_dma_irq(int irq, void *data)
166{
167 int csr;
168 irqreturn_t ret = IRQ_NONE;
169
170 spin_lock(&global_dev.reg_lock);
171 csr = viafb_mmio_read(VDMA_CSR0);
172 if (csr & VDMA_C_DONE) {
173 viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
174 complete(&viafb_dma_completion);
175 ret = IRQ_HANDLED;
176 }
177 spin_unlock(&global_dev.reg_lock);
178 return ret;
179}
180
181/*
182 * Indicate a need for DMA functionality.
183 */
184int viafb_request_dma(void)
185{
186 int ret = 0;
187
188 /*
189 * Only VX855 is supported currently.
190 */
191 if (global_dev.chip_type != UNICHROME_VX855)
192 return -ENODEV;
193 /*
194 * Note the new user and set up our interrupt handler
195 * if need be.
196 */
197 mutex_lock(&viafb_dma_lock);
198 viafb_dma_users++;
199 if (viafb_dma_users == 1) {
200 ret = request_irq(global_dev.pdev->irq, viafb_dma_irq,
201 IRQF_SHARED, "via-dma", &viafb_dma_users);
202 if (ret)
203 viafb_dma_users--;
204 else
205 viafb_irq_enable(VDE_I_DMA0TDEN);
206 }
207 mutex_unlock(&viafb_dma_lock);
208 return ret;
209}
210EXPORT_SYMBOL_GPL(viafb_request_dma);
211
212void viafb_release_dma(void)
213{
214 mutex_lock(&viafb_dma_lock);
215 viafb_dma_users--;
216 if (viafb_dma_users == 0) {
217 viafb_irq_disable(VDE_I_DMA0TDEN);
218 free_irq(global_dev.pdev->irq, &viafb_dma_users);
219 }
220 mutex_unlock(&viafb_dma_lock);
221}
222EXPORT_SYMBOL_GPL(viafb_release_dma);
223
224
225#if 0
226/*
227 * Copy a single buffer from FB memory, synchronously. This code works
228 * but is not currently used.
229 */
230void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len)
231{
232 unsigned long flags;
233 int csr;
234
235 mutex_lock(&viafb_dma_lock);
236 init_completion(&viafb_dma_completion);
237 /*
238 * Program the controller.
239 */
240 spin_lock_irqsave(&global_dev.reg_lock, flags);
241 viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
242 /* Enable ints; must happen after CSR0 write! */
243 viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE);
244 viafb_mmio_write(VDMA_MARL0, (int) (paddr & 0xfffffff0));
245 viafb_mmio_write(VDMA_MARH0, (int) ((paddr >> 28) & 0xfff));
246 /* Data sheet suggests DAR0 should be <<4, but it lies */
247 viafb_mmio_write(VDMA_DAR0, offset);
248 viafb_mmio_write(VDMA_DQWCR0, len >> 4);
249 viafb_mmio_write(VDMA_TMR0, 0);
250 viafb_mmio_write(VDMA_DPRL0, 0);
251 viafb_mmio_write(VDMA_DPRH0, 0);
252 viafb_mmio_write(VDMA_PMR0, 0);
253 csr = viafb_mmio_read(VDMA_CSR0);
254 viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
255 spin_unlock_irqrestore(&global_dev.reg_lock, flags);
256 /*
257 * Now we just wait until the interrupt handler says
258 * we're done.
259 */
260 wait_for_completion_interruptible(&viafb_dma_completion);
261 viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
262 mutex_unlock(&viafb_dma_lock);
263}
264EXPORT_SYMBOL_GPL(viafb_dma_copy_out);
265#endif
266
267/*
268 * Do a scatter/gather DMA copy from FB memory. You must have done
269 * a successful call to viafb_request_dma() first.
270 */
271int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
272{
273 struct viafb_vx855_dma_descr *descr;
274 void *descrpages;
275 dma_addr_t descr_handle;
276 unsigned long flags;
277 int i;
278 struct scatterlist *sgentry;
279 dma_addr_t nextdesc;
280
281 /*
282 * Get a place to put the descriptors.
283 */
284 descrpages = dma_alloc_coherent(&global_dev.pdev->dev,
285 nsg*sizeof(struct viafb_vx855_dma_descr),
286 &descr_handle, GFP_KERNEL);
287 if (descrpages == NULL) {
288 dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n");
289 return -ENOMEM;
290 }
291 mutex_lock(&viafb_dma_lock);
292 /*
293 * Fill them in.
294 */
295 descr = descrpages;
296 nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr);
297 for_each_sg(sg, sgentry, nsg, i) {
298 dma_addr_t paddr = sg_dma_address(sgentry);
299 descr->addr_low = paddr & 0xfffffff0;
300 descr->addr_high = ((u64) paddr >> 32) & 0x0fff;
301 descr->fb_offset = offset;
302 descr->seg_size = sg_dma_len(sgentry) >> 4;
303 descr->tile_mode = 0;
304 descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC;
305 descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff;
306 descr->pad = 0xffffffff; /* VIA driver does this */
307 offset += sg_dma_len(sgentry);
308 nextdesc += sizeof(struct viafb_vx855_dma_descr);
309 descr++;
310 }
311 descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC;
312 /*
313 * Program the engine.
314 */
315 spin_lock_irqsave(&global_dev.reg_lock, flags);
316 init_completion(&viafb_dma_completion);
317 viafb_mmio_write(VDMA_DQWCR0, 0);
318 viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
319 viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN);
320 viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC);
321 viafb_mmio_write(VDMA_DPRH0,
322 (((u64)descr_handle >> 32) & 0x0fff) | 0xf0000);
323 (void) viafb_mmio_read(VDMA_CSR0);
324 viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
325 spin_unlock_irqrestore(&global_dev.reg_lock, flags);
326 /*
327 * Now we just wait until the interrupt handler says
328 * we're done. Except that, actually, we need to wait a little
329 * longer: the interrupts seem to jump the gun a little and we
330 * get corrupted frames sometimes.
331 */
332 wait_for_completion_timeout(&viafb_dma_completion, 1);
333 msleep(1);
334 if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0)
335 printk(KERN_ERR "VIA DMA timeout!\n");
336 /*
337 * Clean up and we're done.
338 */
339 viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
340 viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */
341 mutex_unlock(&viafb_dma_lock);
342 dma_free_coherent(&global_dev.pdev->dev,
343 nsg*sizeof(struct viafb_vx855_dma_descr), descrpages,
344 descr_handle);
345 return 0;
346}
347EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
348#endif /* CONFIG_VIDEO_VIA_CAMERA */
349
350/* ---------------------------------------------------------------------- */
351/*
352 * Figure out how big our framebuffer memory is. Kind of ugly,
353 * but evidently we can't trust the information found in the
354 * fbdev configuration area.
355 */
356static u16 via_function3[] = {
357 CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
358 CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
359 P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
360};
361
362/* Get the BIOS-configured framebuffer size from PCI configuration space
363 * of function 3 in the respective chipset */
364static int viafb_get_fb_size_from_pci(int chip_type)
365{
366 int i;
367 u8 offset = 0;
368 u32 FBSize;
369 u32 VideoMemSize;
370
371 /* search for the "FUNCTION3" device in this chipset */
372 for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
373 struct pci_dev *pdev;
374
375 pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
376 NULL);
377 if (!pdev)
378 continue;
379
380 DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
381
382 switch (pdev->device) {
383 case CLE266_FUNCTION3:
384 case KM400_FUNCTION3:
385 offset = 0xE0;
386 break;
387 case CN400_FUNCTION3:
388 case CN700_FUNCTION3:
389 case CX700_FUNCTION3:
390 case KM800_FUNCTION3:
391 case KM890_FUNCTION3:
392 case P4M890_FUNCTION3:
393 case P4M900_FUNCTION3:
394 case VX800_FUNCTION3:
395 case VX855_FUNCTION3:
396 case VX900_FUNCTION3:
397 /*case CN750_FUNCTION3: */
398 offset = 0xA0;
399 break;
400 }
401
402 if (!offset)
403 break;
404
405 pci_read_config_dword(pdev, offset, &FBSize);
406 pci_dev_put(pdev);
407 }
408
409 if (!offset) {
410 printk(KERN_ERR "cannot determine framebuffer size\n");
411 return -EIO;
412 }
413
414 FBSize = FBSize & 0x00007000;
415 DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
416
417 if (chip_type < UNICHROME_CX700) {
418 switch (FBSize) {
419 case 0x00004000:
420 VideoMemSize = (16 << 20); /*16M */
421 break;
422
423 case 0x00005000:
424 VideoMemSize = (32 << 20); /*32M */
425 break;
426
427 case 0x00006000:
428 VideoMemSize = (64 << 20); /*64M */
429 break;
430
431 default:
432 VideoMemSize = (32 << 20); /*32M */
433 break;
434 }
435 } else {
436 switch (FBSize) {
437 case 0x00001000:
438 VideoMemSize = (8 << 20); /*8M */
439 break;
440
441 case 0x00002000:
442 VideoMemSize = (16 << 20); /*16M */
443 break;
444
445 case 0x00003000:
446 VideoMemSize = (32 << 20); /*32M */
447 break;
448
449 case 0x00004000:
450 VideoMemSize = (64 << 20); /*64M */
451 break;
452
453 case 0x00005000:
454 VideoMemSize = (128 << 20); /*128M */
455 break;
456
457 case 0x00006000:
458 VideoMemSize = (256 << 20); /*256M */
459 break;
460
461 case 0x00007000: /* Only on VX855/875 */
462 VideoMemSize = (512 << 20); /*512M */
463 break;
464
465 default:
466 VideoMemSize = (32 << 20); /*32M */
467 break;
468 }
469 }
470
471 return VideoMemSize;
472}
473
474
475/*
476 * Figure out and map our MMIO regions.
477 */
478static int via_pci_setup_mmio(struct viafb_dev *vdev)
479{
480 int ret;
481 /*
482 * Hook up to the device registers. Note that we soldier
483 * on if it fails; the framebuffer can operate (without
484 * acceleration) without this region.
485 */
486 vdev->engine_start = pci_resource_start(vdev->pdev, 1);
487 vdev->engine_len = pci_resource_len(vdev->pdev, 1);
488 vdev->engine_mmio = ioremap_nocache(vdev->engine_start,
489 vdev->engine_len);
490 if (vdev->engine_mmio == NULL)
491 dev_err(&vdev->pdev->dev,
492 "Unable to map engine MMIO; operation will be "
493 "slow and crippled.\n");
494 /*
495 * Map in framebuffer memory. For now, failure here is
496 * fatal. Unfortunately, in the absence of significant
497 * vmalloc space, failure here is also entirely plausible.
498 * Eventually we want to move away from mapping this
499 * entire region.
500 */
501 if (vdev->chip_type == UNICHROME_VX900)
502 vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
503 else
504 vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
505 ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
506 if (ret < 0)
507 goto out_unmap;
508
509 /* try to map less memory on failure, 8 MB should be still enough */
510 for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
511 vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
512 if (vdev->fbmem)
513 break;
514 }
515
516 if (vdev->fbmem == NULL) {
517 ret = -ENOMEM;
518 goto out_unmap;
519 }
520 return 0;
521out_unmap:
522 iounmap(vdev->engine_mmio);
523 return ret;
524}
525
526static void via_pci_teardown_mmio(struct viafb_dev *vdev)
527{
528 iounmap(vdev->fbmem);
529 iounmap(vdev->engine_mmio);
530}
531
532/*
533 * Create our subsidiary devices.
534 */
535static struct viafb_subdev_info {
536 char *name;
537 struct platform_device *platdev;
538} viafb_subdevs[] = {
539 {
540 .name = "viafb-gpio",
541 },
542 {
543 .name = "viafb-i2c",
544 },
545#if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
546 {
547 .name = "viafb-camera",
548 },
549#endif
550};
551#define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
552
553static int via_create_subdev(struct viafb_dev *vdev,
554 struct viafb_subdev_info *info)
555{
556 int ret;
557
558 info->platdev = platform_device_alloc(info->name, -1);
559 if (!info->platdev) {
560 dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
561 info->name);
562 return -ENOMEM;
563 }
564 info->platdev->dev.parent = &vdev->pdev->dev;
565 info->platdev->dev.platform_data = vdev;
566 ret = platform_device_add(info->platdev);
567 if (ret) {
568 dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
569 info->name);
570 platform_device_put(info->platdev);
571 info->platdev = NULL;
572 }
573 return ret;
574}
575
576static int via_setup_subdevs(struct viafb_dev *vdev)
577{
578 int i;
579
580 /*
581 * Ignore return values. Even if some of the devices
582 * fail to be created, we'll still be able to use some
583 * of the rest.
584 */
585 for (i = 0; i < N_SUBDEVS; i++)
586 via_create_subdev(vdev, viafb_subdevs + i);
587 return 0;
588}
589
590static void via_teardown_subdevs(void)
591{
592 int i;
593
594 for (i = 0; i < N_SUBDEVS; i++)
595 if (viafb_subdevs[i].platdev) {
596 viafb_subdevs[i].platdev->dev.platform_data = NULL;
597 platform_device_unregister(viafb_subdevs[i].platdev);
598 }
599}
600
601/*
602 * Power management functions
603 */
604#ifdef CONFIG_PM
605static LIST_HEAD(viafb_pm_hooks);
606static DEFINE_MUTEX(viafb_pm_hooks_lock);
607
608void viafb_pm_register(struct viafb_pm_hooks *hooks)
609{
610 INIT_LIST_HEAD(&hooks->list);
611
612 mutex_lock(&viafb_pm_hooks_lock);
613 list_add_tail(&hooks->list, &viafb_pm_hooks);
614 mutex_unlock(&viafb_pm_hooks_lock);
615}
616EXPORT_SYMBOL_GPL(viafb_pm_register);
617
618void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
619{
620 mutex_lock(&viafb_pm_hooks_lock);
621 list_del(&hooks->list);
622 mutex_unlock(&viafb_pm_hooks_lock);
623}
624EXPORT_SYMBOL_GPL(viafb_pm_unregister);
625
626static int via_suspend(struct pci_dev *pdev, pm_message_t state)
627{
628 struct viafb_pm_hooks *hooks;
629
630 if (state.event != PM_EVENT_SUSPEND)
631 return 0;
632 /*
633 * "I've occasionally hit a few drivers that caused suspend
634 * failures, and each and every time it was a driver bug, and
635 * the right thing to do was to just ignore the error and suspend
636 * anyway - returning an error code and trying to undo the suspend
637 * is not what anybody ever really wants, even if our model
638 *_allows_ for it."
639 * -- Linus Torvalds, Dec. 7, 2009
640 */
641 mutex_lock(&viafb_pm_hooks_lock);
642 list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
643 hooks->suspend(hooks->private);
644 mutex_unlock(&viafb_pm_hooks_lock);
645
646 pci_save_state(pdev);
647 pci_disable_device(pdev);
648 pci_set_power_state(pdev, pci_choose_state(pdev, state));
649 return 0;
650}
651
652static int via_resume(struct pci_dev *pdev)
653{
654 struct viafb_pm_hooks *hooks;
655
656 /* Get the bus side powered up */
657 pci_set_power_state(pdev, PCI_D0);
658 pci_restore_state(pdev);
659 if (pci_enable_device(pdev))
660 return 0;
661
662 pci_set_master(pdev);
663
664 /* Now bring back any subdevs */
665 mutex_lock(&viafb_pm_hooks_lock);
666 list_for_each_entry(hooks, &viafb_pm_hooks, list)
667 hooks->resume(hooks->private);
668 mutex_unlock(&viafb_pm_hooks_lock);
669
670 return 0;
671}
672#endif /* CONFIG_PM */
673
674static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
675{
676 int ret;
677
678 ret = pci_enable_device(pdev);
679 if (ret)
680 return ret;
681
682 /*
683 * Global device initialization.
684 */
685 memset(&global_dev, 0, sizeof(global_dev));
686 global_dev.pdev = pdev;
687 global_dev.chip_type = ent->driver_data;
688 global_dev.port_cfg = adap_configs;
689 if (machine_is_olpc())
690 global_dev.port_cfg = olpc_adap_configs;
691
692 spin_lock_init(&global_dev.reg_lock);
693 ret = via_pci_setup_mmio(&global_dev);
694 if (ret)
695 goto out_disable;
696 /*
697 * Set up interrupts and create our subdevices. Continue even if
698 * some things fail.
699 */
700 viafb_int_init();
701 via_setup_subdevs(&global_dev);
702 /*
703 * Set up the framebuffer device
704 */
705 ret = via_fb_pci_probe(&global_dev);
706 if (ret)
707 goto out_subdevs;
708 return 0;
709
710out_subdevs:
711 via_teardown_subdevs();
712 via_pci_teardown_mmio(&global_dev);
713out_disable:
714 pci_disable_device(pdev);
715 return ret;
716}
717
718static void via_pci_remove(struct pci_dev *pdev)
719{
720 via_teardown_subdevs();
721 via_fb_pci_remove(pdev);
722 via_pci_teardown_mmio(&global_dev);
723 pci_disable_device(pdev);
724}
725
726
727static struct pci_device_id via_pci_table[] = {
728 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
729 .driver_data = UNICHROME_CLE266 },
730 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
731 .driver_data = UNICHROME_K400 },
732 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
733 .driver_data = UNICHROME_K800 },
734 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
735 .driver_data = UNICHROME_PM800 },
736 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN700_DID),
737 .driver_data = UNICHROME_CN700 },
738 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
739 .driver_data = UNICHROME_CX700 },
740 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
741 .driver_data = UNICHROME_CN750 },
742 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
743 .driver_data = UNICHROME_K8M890 },
744 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
745 .driver_data = UNICHROME_P4M890 },
746 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
747 .driver_data = UNICHROME_P4M900 },
748 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
749 .driver_data = UNICHROME_VX800 },
750 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
751 .driver_data = UNICHROME_VX855 },
752 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
753 .driver_data = UNICHROME_VX900 },
754 { }
755};
756MODULE_DEVICE_TABLE(pci, via_pci_table);
757
758static struct pci_driver via_driver = {
759 .name = "viafb",
760 .id_table = via_pci_table,
761 .probe = via_pci_probe,
762 .remove = via_pci_remove,
763#ifdef CONFIG_PM
764 .suspend = via_suspend,
765 .resume = via_resume,
766#endif
767};
768
769static int __init via_core_init(void)
770{
771 int ret;
772
773 ret = viafb_init();
774 if (ret)
775 return ret;
776 viafb_i2c_init();
777 viafb_gpio_init();
778 return pci_register_driver(&via_driver);
779}
780
781static void __exit via_core_exit(void)
782{
783 pci_unregister_driver(&via_driver);
784 viafb_gpio_exit();
785 viafb_i2c_exit();
786 viafb_exit();
787}
788
789module_init(via_core_init);
790module_exit(via_core_exit);
diff --git a/drivers/video/fbdev/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c
new file mode 100644
index 000000000000..e408679081ab
--- /dev/null
+++ b/drivers/video/fbdev/via/via-gpio.c
@@ -0,0 +1,316 @@
1/*
2 * Support for viafb GPIO ports.
3 *
4 * Copyright 2009 Jonathan Corbet <corbet@lwn.net>
5 * Distributable under version 2 of the GNU General Public License.
6 */
7
8#include <linux/spinlock.h>
9#include <linux/gpio.h>
10#include <linux/platform_device.h>
11#include <linux/via-core.h>
12#include <linux/via-gpio.h>
13#include <linux/export.h>
14
15/*
16 * The ports we know about. Note that the port-25 gpios are not
17 * mentioned in the datasheet.
18 */
19
20struct viafb_gpio {
21 char *vg_name; /* Data sheet name */
22 u16 vg_io_port;
23 u8 vg_port_index;
24 int vg_mask_shift;
25};
26
27static struct viafb_gpio viafb_all_gpios[] = {
28 {
29 .vg_name = "VGPIO0", /* Guess - not in datasheet */
30 .vg_io_port = VIASR,
31 .vg_port_index = 0x25,
32 .vg_mask_shift = 1
33 },
34 {
35 .vg_name = "VGPIO1",
36 .vg_io_port = VIASR,
37 .vg_port_index = 0x25,
38 .vg_mask_shift = 0
39 },
40 {
41 .vg_name = "VGPIO2", /* aka DISPCLKI0 */
42 .vg_io_port = VIASR,
43 .vg_port_index = 0x2c,
44 .vg_mask_shift = 1
45 },
46 {
47 .vg_name = "VGPIO3", /* aka DISPCLKO0 */
48 .vg_io_port = VIASR,
49 .vg_port_index = 0x2c,
50 .vg_mask_shift = 0
51 },
52 {
53 .vg_name = "VGPIO4", /* DISPCLKI1 */
54 .vg_io_port = VIASR,
55 .vg_port_index = 0x3d,
56 .vg_mask_shift = 1
57 },
58 {
59 .vg_name = "VGPIO5", /* DISPCLKO1 */
60 .vg_io_port = VIASR,
61 .vg_port_index = 0x3d,
62 .vg_mask_shift = 0
63 },
64};
65
66#define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios)
67
68/*
69 * This structure controls the active GPIOs, which may be a subset
70 * of those which are known.
71 */
72
73struct viafb_gpio_cfg {
74 struct gpio_chip gpio_chip;
75 struct viafb_dev *vdev;
76 struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS];
77 const char *gpio_names[VIAFB_NUM_GPIOS];
78};
79
80/*
81 * GPIO access functions
82 */
83static void via_gpio_set(struct gpio_chip *chip, unsigned int nr,
84 int value)
85{
86 struct viafb_gpio_cfg *cfg = container_of(chip,
87 struct viafb_gpio_cfg,
88 gpio_chip);
89 u8 reg;
90 struct viafb_gpio *gpio;
91 unsigned long flags;
92
93 spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
94 gpio = cfg->active_gpios[nr];
95 reg = via_read_reg(VIASR, gpio->vg_port_index);
96 reg |= 0x40 << gpio->vg_mask_shift; /* output enable */
97 if (value)
98 reg |= 0x10 << gpio->vg_mask_shift;
99 else
100 reg &= ~(0x10 << gpio->vg_mask_shift);
101 via_write_reg(VIASR, gpio->vg_port_index, reg);
102 spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
103}
104
105static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr,
106 int value)
107{
108 via_gpio_set(chip, nr, value);
109 return 0;
110}
111
112/*
113 * Set the input direction. I'm not sure this is right; we should
114 * be able to do input without disabling output.
115 */
116static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr)
117{
118 struct viafb_gpio_cfg *cfg = container_of(chip,
119 struct viafb_gpio_cfg,
120 gpio_chip);
121 struct viafb_gpio *gpio;
122 unsigned long flags;
123
124 spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
125 gpio = cfg->active_gpios[nr];
126 via_write_reg_mask(VIASR, gpio->vg_port_index, 0,
127 0x40 << gpio->vg_mask_shift);
128 spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
129 return 0;
130}
131
132static int via_gpio_get(struct gpio_chip *chip, unsigned int nr)
133{
134 struct viafb_gpio_cfg *cfg = container_of(chip,
135 struct viafb_gpio_cfg,
136 gpio_chip);
137 u8 reg;
138 struct viafb_gpio *gpio;
139 unsigned long flags;
140
141 spin_lock_irqsave(&cfg->vdev->reg_lock, flags);
142 gpio = cfg->active_gpios[nr];
143 reg = via_read_reg(VIASR, gpio->vg_port_index);
144 spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags);
145 return reg & (0x04 << gpio->vg_mask_shift);
146}
147
148
149static struct viafb_gpio_cfg viafb_gpio_config = {
150 .gpio_chip = {
151 .label = "VIAFB onboard GPIO",
152 .owner = THIS_MODULE,
153 .direction_output = via_gpio_dir_out,
154 .set = via_gpio_set,
155 .direction_input = via_gpio_dir_input,
156 .get = via_gpio_get,
157 .base = -1,
158 .ngpio = 0,
159 .can_sleep = 0
160 }
161};
162
163/*
164 * Manage the software enable bit.
165 */
166static void viafb_gpio_enable(struct viafb_gpio *gpio)
167{
168 via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02);
169}
170
171static void viafb_gpio_disable(struct viafb_gpio *gpio)
172{
173 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02);
174}
175
176#ifdef CONFIG_PM
177
178static int viafb_gpio_suspend(void *private)
179{
180 return 0;
181}
182
183static int viafb_gpio_resume(void *private)
184{
185 int i;
186
187 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
188 viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
189 return 0;
190}
191
192static struct viafb_pm_hooks viafb_gpio_pm_hooks = {
193 .suspend = viafb_gpio_suspend,
194 .resume = viafb_gpio_resume
195};
196#endif /* CONFIG_PM */
197
198/*
199 * Look up a specific gpio and return the number it was assigned.
200 */
201int viafb_gpio_lookup(const char *name)
202{
203 int i;
204
205 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++)
206 if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name))
207 return viafb_gpio_config.gpio_chip.base + i;
208 return -1;
209}
210EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
211
212/*
213 * Platform device stuff.
214 */
215static int viafb_gpio_probe(struct platform_device *platdev)
216{
217 struct viafb_dev *vdev = platdev->dev.platform_data;
218 struct via_port_cfg *port_cfg = vdev->port_cfg;
219 int i, ngpio = 0, ret;
220 struct viafb_gpio *gpio;
221 unsigned long flags;
222
223 /*
224 * Set up entries for all GPIOs which have been configured to
225 * operate as such (as opposed to as i2c ports).
226 */
227 for (i = 0; i < VIAFB_NUM_PORTS; i++) {
228 if (port_cfg[i].mode != VIA_MODE_GPIO)
229 continue;
230 for (gpio = viafb_all_gpios;
231 gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++)
232 if (gpio->vg_port_index == port_cfg[i].ioport_index) {
233 viafb_gpio_config.active_gpios[ngpio] = gpio;
234 viafb_gpio_config.gpio_names[ngpio] =
235 gpio->vg_name;
236 ngpio++;
237 }
238 }
239 viafb_gpio_config.gpio_chip.ngpio = ngpio;
240 viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names;
241 viafb_gpio_config.vdev = vdev;
242 if (ngpio == 0) {
243 printk(KERN_INFO "viafb: no GPIOs configured\n");
244 return 0;
245 }
246 /*
247 * Enable the ports. They come in pairs, with a single
248 * enable bit for both.
249 */
250 spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
251 for (i = 0; i < ngpio; i += 2)
252 viafb_gpio_enable(viafb_gpio_config.active_gpios[i]);
253 spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
254 /*
255 * Get registered.
256 */
257 viafb_gpio_config.gpio_chip.base = -1; /* Dynamic */
258 ret = gpiochip_add(&viafb_gpio_config.gpio_chip);
259 if (ret) {
260 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret);
261 viafb_gpio_config.gpio_chip.ngpio = 0;
262 }
263#ifdef CONFIG_PM
264 viafb_pm_register(&viafb_gpio_pm_hooks);
265#endif
266 return ret;
267}
268
269
270static int viafb_gpio_remove(struct platform_device *platdev)
271{
272 unsigned long flags;
273 int ret = 0, i;
274
275#ifdef CONFIG_PM
276 viafb_pm_unregister(&viafb_gpio_pm_hooks);
277#endif
278
279 /*
280 * Get unregistered.
281 */
282 if (viafb_gpio_config.gpio_chip.ngpio > 0) {
283 ret = gpiochip_remove(&viafb_gpio_config.gpio_chip);
284 if (ret) { /* Somebody still using it? */
285 printk(KERN_ERR "Viafb: GPIO remove failed\n");
286 return ret;
287 }
288 }
289 /*
290 * Disable the ports.
291 */
292 spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags);
293 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2)
294 viafb_gpio_disable(viafb_gpio_config.active_gpios[i]);
295 viafb_gpio_config.gpio_chip.ngpio = 0;
296 spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags);
297 return ret;
298}
299
300static struct platform_driver via_gpio_driver = {
301 .driver = {
302 .name = "viafb-gpio",
303 },
304 .probe = viafb_gpio_probe,
305 .remove = viafb_gpio_remove,
306};
307
308int viafb_gpio_init(void)
309{
310 return platform_driver_register(&via_gpio_driver);
311}
312
313void viafb_gpio_exit(void)
314{
315 platform_driver_unregister(&via_gpio_driver);
316}
diff --git a/drivers/video/fbdev/via/via_aux.c b/drivers/video/fbdev/via/via_aux.c
new file mode 100644
index 000000000000..4a0a55cdac3d
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux.c
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * infrastructure for devices connected via I2C
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap)
29{
30 struct via_aux_bus *bus;
31
32 if (!adap)
33 return NULL;
34
35 bus = kmalloc(sizeof(*bus), GFP_KERNEL);
36 if (!bus)
37 return NULL;
38
39 bus->adap = adap;
40 INIT_LIST_HEAD(&bus->drivers);
41
42 via_aux_edid_probe(bus);
43 via_aux_vt1636_probe(bus);
44 via_aux_vt1632_probe(bus);
45 via_aux_vt1631_probe(bus);
46 via_aux_vt1625_probe(bus);
47 via_aux_vt1622_probe(bus);
48 via_aux_vt1621_probe(bus);
49 via_aux_sii164_probe(bus);
50 via_aux_ch7301_probe(bus);
51
52 return bus;
53}
54
55void via_aux_free(struct via_aux_bus *bus)
56{
57 struct via_aux_drv *pos, *n;
58
59 if (!bus)
60 return;
61
62 list_for_each_entry_safe(pos, n, &bus->drivers, chain) {
63 if (pos->cleanup)
64 pos->cleanup(pos);
65
66 list_del(&pos->chain);
67 kfree(pos->data);
68 kfree(pos);
69 }
70
71 kfree(bus);
72}
73
74const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus)
75{
76 struct via_aux_drv *pos;
77 const struct fb_videomode *mode = NULL;
78
79 if (!bus)
80 return NULL;
81
82 list_for_each_entry(pos, &bus->drivers, chain) {
83 if (pos->get_preferred_mode)
84 mode = pos->get_preferred_mode(pos);
85 }
86
87 return mode;
88}
diff --git a/drivers/video/fbdev/via/via_aux.h b/drivers/video/fbdev/via/via_aux.h
new file mode 100644
index 000000000000..a8de3f038cea
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux.h
@@ -0,0 +1,93 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * infrastructure for devices connected via I2C
22 */
23
24#ifndef __VIA_AUX_H__
25#define __VIA_AUX_H__
26
27
28#include <linux/list.h>
29#include <linux/i2c.h>
30#include <linux/fb.h>
31
32
33struct via_aux_bus {
34 struct i2c_adapter *adap; /* the I2C device to access the bus */
35 struct list_head drivers; /* drivers for devices on this bus */
36};
37
38struct via_aux_drv {
39 struct list_head chain; /* chain to support multiple drivers */
40
41 struct via_aux_bus *bus; /* the I2C bus used */
42 u8 addr; /* the I2C slave address */
43
44 const char *name; /* human readable name of the driver */
45 void *data; /* private data of this driver */
46
47 void (*cleanup)(struct via_aux_drv *drv);
48 const struct fb_videomode* (*get_preferred_mode)
49 (struct via_aux_drv *drv);
50};
51
52
53struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap);
54void via_aux_free(struct via_aux_bus *bus);
55const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus);
56
57
58static inline bool via_aux_add(struct via_aux_drv *drv)
59{
60 struct via_aux_drv *data = kmalloc(sizeof(*data), GFP_KERNEL);
61
62 if (!data)
63 return false;
64
65 *data = *drv;
66 list_add_tail(&data->chain, &data->bus->drivers);
67 return true;
68}
69
70static inline bool via_aux_read(struct via_aux_drv *drv, u8 start, u8 *buf,
71 u8 len)
72{
73 struct i2c_msg msg[2] = {
74 {.addr = drv->addr, .flags = 0, .len = 1, .buf = &start},
75 {.addr = drv->addr, .flags = I2C_M_RD, .len = len, .buf = buf} };
76
77 return i2c_transfer(drv->bus->adap, msg, 2) == 2;
78}
79
80
81/* probe functions of existing drivers - should only be called in via_aux.c */
82void via_aux_ch7301_probe(struct via_aux_bus *bus);
83void via_aux_edid_probe(struct via_aux_bus *bus);
84void via_aux_sii164_probe(struct via_aux_bus *bus);
85void via_aux_vt1636_probe(struct via_aux_bus *bus);
86void via_aux_vt1632_probe(struct via_aux_bus *bus);
87void via_aux_vt1631_probe(struct via_aux_bus *bus);
88void via_aux_vt1625_probe(struct via_aux_bus *bus);
89void via_aux_vt1622_probe(struct via_aux_bus *bus);
90void via_aux_vt1621_probe(struct via_aux_bus *bus);
91
92
93#endif /* __VIA_AUX_H__ */
diff --git a/drivers/video/fbdev/via/via_aux_ch7301.c b/drivers/video/fbdev/via/via_aux_ch7301.c
new file mode 100644
index 000000000000..1cbe5037a6b0
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_ch7301.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for Chrontel CH7301 DVI Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "CH7301 DVI Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x4B, &tmp, 1) || tmp != 0x17)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_ch7301_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x75);
49 probe(bus, 0x76);
50}
diff --git a/drivers/video/fbdev/via/via_aux_edid.c b/drivers/video/fbdev/via/via_aux_edid.c
new file mode 100644
index 000000000000..754d4509033f
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_edid.c
@@ -0,0 +1,100 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * generic EDID driver
22 */
23
24#include <linux/slab.h>
25#include <linux/fb.h>
26#include "via_aux.h"
27#include "../edid.h"
28
29
30static const char *name = "EDID";
31
32
33static void query_edid(struct via_aux_drv *drv)
34{
35 struct fb_monspecs *spec = drv->data;
36 unsigned char edid[EDID_LENGTH];
37 bool valid = false;
38
39 if (spec) {
40 fb_destroy_modedb(spec->modedb);
41 } else {
42 spec = kmalloc(sizeof(*spec), GFP_KERNEL);
43 if (!spec)
44 return;
45 }
46
47 spec->version = spec->revision = 0;
48 if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
49 fb_edid_to_monspecs(edid, spec);
50 valid = spec->version || spec->revision;
51 }
52
53 if (!valid) {
54 kfree(spec);
55 spec = NULL;
56 } else
57 printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);
58
59 drv->data = spec;
60}
61
62static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)
63{
64 struct fb_monspecs *spec = drv->data;
65 int i;
66
67 if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
68 return NULL;
69
70 for (i = 0; i < spec->modedb_len; i++) {
71 if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
72 spec->modedb[i].flag & FB_MODE_IS_DETAILED)
73 return &spec->modedb[i];
74 }
75
76 return NULL;
77}
78
79static void cleanup(struct via_aux_drv *drv)
80{
81 struct fb_monspecs *spec = drv->data;
82
83 if (spec)
84 fb_destroy_modedb(spec->modedb);
85}
86
87void via_aux_edid_probe(struct via_aux_bus *bus)
88{
89 struct via_aux_drv drv = {
90 .bus = bus,
91 .addr = 0x50,
92 .name = name,
93 .cleanup = cleanup,
94 .get_preferred_mode = get_preferred_mode};
95
96 query_edid(&drv);
97
98 /* as EDID devices can be connected/disconnected just add the driver */
99 via_aux_add(&drv);
100}
diff --git a/drivers/video/fbdev/via/via_aux_sii164.c b/drivers/video/fbdev/via/via_aux_sii164.c
new file mode 100644
index 000000000000..ca1b35f033b1
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_sii164.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for Silicon Image SiI 164 PanelLink Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "SiI 164 PanelLink Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
45 via_aux_add(&drv);
46}
47
48void via_aux_sii164_probe(struct via_aux_bus *bus)
49{
50 u8 i;
51
52 for (i = 0x38; i <= 0x3F; i++)
53 probe(bus, i);
54}
diff --git a/drivers/video/fbdev/via/via_aux_vt1621.c b/drivers/video/fbdev/via/via_aux_vt1621.c
new file mode 100644
index 000000000000..38eca8479898
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1621.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1621(M) TV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1621(M) TV Encoder";
29
30
31void via_aux_vt1621_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x20,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x02)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s\n", name);
43 via_aux_add(&drv);
44}
diff --git a/drivers/video/fbdev/via/via_aux_vt1622.c b/drivers/video/fbdev/via/via_aux_vt1622.c
new file mode 100644
index 000000000000..8c79c68ba683
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1622.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1622(M) Digital TV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1622(M) Digital TV Encoder";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x03)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_vt1622_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x20);
49 probe(bus, 0x21);
50}
diff --git a/drivers/video/fbdev/via/via_aux_vt1625.c b/drivers/video/fbdev/via/via_aux_vt1625.c
new file mode 100644
index 000000000000..03eb30165d36
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1625.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1625(M) HDTV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1625(M) HDTV Encoder";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x50)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_vt1625_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x20);
49 probe(bus, 0x21);
50}
diff --git a/drivers/video/fbdev/via/via_aux_vt1631.c b/drivers/video/fbdev/via/via_aux_vt1631.c
new file mode 100644
index 000000000000..06e742f1f723
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1631.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1631 LVDS Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1631 LVDS Transmitter";
29
30
31void via_aux_vt1631_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x38,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s\n", name);
45 via_aux_add(&drv);
46}
diff --git a/drivers/video/fbdev/via/via_aux_vt1632.c b/drivers/video/fbdev/via/via_aux_vt1632.c
new file mode 100644
index 000000000000..d24f4cd97401
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1632.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1632 DVI Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1632 DVI Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
45 via_aux_add(&drv);
46}
47
48void via_aux_vt1632_probe(struct via_aux_bus *bus)
49{
50 u8 i;
51
52 for (i = 0x08; i <= 0x0F; i++)
53 probe(bus, i);
54}
diff --git a/drivers/video/fbdev/via/via_aux_vt1636.c b/drivers/video/fbdev/via/via_aux_vt1636.c
new file mode 100644
index 000000000000..9e015c101d4d
--- /dev/null
+++ b/drivers/video/fbdev/via/via_aux_vt1636.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1636 LVDS Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1636 LVDS Transmitter";
29
30
31void via_aux_vt1636_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x40,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s\n", name);
45 via_aux_add(&drv);
46}
diff --git a/drivers/video/fbdev/via/via_clock.c b/drivers/video/fbdev/via/via_clock.c
new file mode 100644
index 000000000000..db1e39277e32
--- /dev/null
+++ b/drivers/video/fbdev/via/via_clock.c
@@ -0,0 +1,368 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * either version 2, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
13 * the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE.See the GNU General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22/*
23 * clock and PLL management functions
24 */
25
26#include <linux/kernel.h>
27#include <linux/via-core.h>
28#include <asm/olpc.h>
29#include "via_clock.h"
30#include "global.h"
31#include "debug.h"
32
33const char *via_slap = "Please slap VIA Technologies to motivate them "
34 "releasing full documentation for your platform!\n";
35
36static inline u32 cle266_encode_pll(struct via_pll_config pll)
37{
38 return (pll.multiplier << 8)
39 | (pll.rshift << 6)
40 | pll.divisor;
41}
42
43static inline u32 k800_encode_pll(struct via_pll_config pll)
44{
45 return ((pll.divisor - 2) << 16)
46 | (pll.rshift << 10)
47 | (pll.multiplier - 2);
48}
49
50static inline u32 vx855_encode_pll(struct via_pll_config pll)
51{
52 return (pll.divisor << 16)
53 | (pll.rshift << 10)
54 | pll.multiplier;
55}
56
57static inline void cle266_set_primary_pll_encoded(u32 data)
58{
59 via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
60 via_write_reg(VIASR, 0x46, data & 0xFF);
61 via_write_reg(VIASR, 0x47, (data >> 8) & 0xFF);
62 via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
63}
64
65static inline void k800_set_primary_pll_encoded(u32 data)
66{
67 via_write_reg_mask(VIASR, 0x40, 0x02, 0x02); /* enable reset */
68 via_write_reg(VIASR, 0x44, data & 0xFF);
69 via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
70 via_write_reg(VIASR, 0x46, (data >> 16) & 0xFF);
71 via_write_reg_mask(VIASR, 0x40, 0x00, 0x02); /* disable reset */
72}
73
74static inline void cle266_set_secondary_pll_encoded(u32 data)
75{
76 via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
77 via_write_reg(VIASR, 0x44, data & 0xFF);
78 via_write_reg(VIASR, 0x45, (data >> 8) & 0xFF);
79 via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
80}
81
82static inline void k800_set_secondary_pll_encoded(u32 data)
83{
84 via_write_reg_mask(VIASR, 0x40, 0x04, 0x04); /* enable reset */
85 via_write_reg(VIASR, 0x4A, data & 0xFF);
86 via_write_reg(VIASR, 0x4B, (data >> 8) & 0xFF);
87 via_write_reg(VIASR, 0x4C, (data >> 16) & 0xFF);
88 via_write_reg_mask(VIASR, 0x40, 0x00, 0x04); /* disable reset */
89}
90
91static inline void set_engine_pll_encoded(u32 data)
92{
93 via_write_reg_mask(VIASR, 0x40, 0x01, 0x01); /* enable reset */
94 via_write_reg(VIASR, 0x47, data & 0xFF);
95 via_write_reg(VIASR, 0x48, (data >> 8) & 0xFF);
96 via_write_reg(VIASR, 0x49, (data >> 16) & 0xFF);
97 via_write_reg_mask(VIASR, 0x40, 0x00, 0x01); /* disable reset */
98}
99
100static void cle266_set_primary_pll(struct via_pll_config config)
101{
102 cle266_set_primary_pll_encoded(cle266_encode_pll(config));
103}
104
105static void k800_set_primary_pll(struct via_pll_config config)
106{
107 k800_set_primary_pll_encoded(k800_encode_pll(config));
108}
109
110static void vx855_set_primary_pll(struct via_pll_config config)
111{
112 k800_set_primary_pll_encoded(vx855_encode_pll(config));
113}
114
115static void cle266_set_secondary_pll(struct via_pll_config config)
116{
117 cle266_set_secondary_pll_encoded(cle266_encode_pll(config));
118}
119
120static void k800_set_secondary_pll(struct via_pll_config config)
121{
122 k800_set_secondary_pll_encoded(k800_encode_pll(config));
123}
124
125static void vx855_set_secondary_pll(struct via_pll_config config)
126{
127 k800_set_secondary_pll_encoded(vx855_encode_pll(config));
128}
129
130static void k800_set_engine_pll(struct via_pll_config config)
131{
132 set_engine_pll_encoded(k800_encode_pll(config));
133}
134
135static void vx855_set_engine_pll(struct via_pll_config config)
136{
137 set_engine_pll_encoded(vx855_encode_pll(config));
138}
139
140static void set_primary_pll_state(u8 state)
141{
142 u8 value;
143
144 switch (state) {
145 case VIA_STATE_ON:
146 value = 0x20;
147 break;
148 case VIA_STATE_OFF:
149 value = 0x00;
150 break;
151 default:
152 return;
153 }
154
155 via_write_reg_mask(VIASR, 0x2D, value, 0x30);
156}
157
158static void set_secondary_pll_state(u8 state)
159{
160 u8 value;
161
162 switch (state) {
163 case VIA_STATE_ON:
164 value = 0x08;
165 break;
166 case VIA_STATE_OFF:
167 value = 0x00;
168 break;
169 default:
170 return;
171 }
172
173 via_write_reg_mask(VIASR, 0x2D, value, 0x0C);
174}
175
176static void set_engine_pll_state(u8 state)
177{
178 u8 value;
179
180 switch (state) {
181 case VIA_STATE_ON:
182 value = 0x02;
183 break;
184 case VIA_STATE_OFF:
185 value = 0x00;
186 break;
187 default:
188 return;
189 }
190
191 via_write_reg_mask(VIASR, 0x2D, value, 0x03);
192}
193
194static void set_primary_clock_state(u8 state)
195{
196 u8 value;
197
198 switch (state) {
199 case VIA_STATE_ON:
200 value = 0x20;
201 break;
202 case VIA_STATE_OFF:
203 value = 0x00;
204 break;
205 default:
206 return;
207 }
208
209 via_write_reg_mask(VIASR, 0x1B, value, 0x30);
210}
211
212static void set_secondary_clock_state(u8 state)
213{
214 u8 value;
215
216 switch (state) {
217 case VIA_STATE_ON:
218 value = 0x80;
219 break;
220 case VIA_STATE_OFF:
221 value = 0x00;
222 break;
223 default:
224 return;
225 }
226
227 via_write_reg_mask(VIASR, 0x1B, value, 0xC0);
228}
229
230static inline u8 set_clock_source_common(enum via_clksrc source, bool use_pll)
231{
232 u8 data = 0;
233
234 switch (source) {
235 case VIA_CLKSRC_X1:
236 data = 0x00;
237 break;
238 case VIA_CLKSRC_TVX1:
239 data = 0x02;
240 break;
241 case VIA_CLKSRC_TVPLL:
242 data = 0x04; /* 0x06 should be the same */
243 break;
244 case VIA_CLKSRC_DVP1TVCLKR:
245 data = 0x0A;
246 break;
247 case VIA_CLKSRC_CAP0:
248 data = 0xC;
249 break;
250 case VIA_CLKSRC_CAP1:
251 data = 0x0E;
252 break;
253 }
254
255 if (!use_pll)
256 data |= 1;
257
258 return data;
259}
260
261static void set_primary_clock_source(enum via_clksrc source, bool use_pll)
262{
263 u8 data = set_clock_source_common(source, use_pll) << 4;
264 via_write_reg_mask(VIACR, 0x6C, data, 0xF0);
265}
266
267static void set_secondary_clock_source(enum via_clksrc source, bool use_pll)
268{
269 u8 data = set_clock_source_common(source, use_pll);
270 via_write_reg_mask(VIACR, 0x6C, data, 0x0F);
271}
272
273static void dummy_set_clock_state(u8 state)
274{
275 printk(KERN_INFO "Using undocumented set clock state.\n%s", via_slap);
276}
277
278static void dummy_set_clock_source(enum via_clksrc source, bool use_pll)
279{
280 printk(KERN_INFO "Using undocumented set clock source.\n%s", via_slap);
281}
282
283static void dummy_set_pll_state(u8 state)
284{
285 printk(KERN_INFO "Using undocumented set PLL state.\n%s", via_slap);
286}
287
288static void dummy_set_pll(struct via_pll_config config)
289{
290 printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
291}
292
293static void noop_set_clock_state(u8 state)
294{
295}
296
297void via_clock_init(struct via_clock *clock, int gfx_chip)
298{
299 switch (gfx_chip) {
300 case UNICHROME_CLE266:
301 case UNICHROME_K400:
302 clock->set_primary_clock_state = dummy_set_clock_state;
303 clock->set_primary_clock_source = dummy_set_clock_source;
304 clock->set_primary_pll_state = dummy_set_pll_state;
305 clock->set_primary_pll = cle266_set_primary_pll;
306
307 clock->set_secondary_clock_state = dummy_set_clock_state;
308 clock->set_secondary_clock_source = dummy_set_clock_source;
309 clock->set_secondary_pll_state = dummy_set_pll_state;
310 clock->set_secondary_pll = cle266_set_secondary_pll;
311
312 clock->set_engine_pll_state = dummy_set_pll_state;
313 clock->set_engine_pll = dummy_set_pll;
314 break;
315 case UNICHROME_K800:
316 case UNICHROME_PM800:
317 case UNICHROME_CN700:
318 case UNICHROME_CX700:
319 case UNICHROME_CN750:
320 case UNICHROME_K8M890:
321 case UNICHROME_P4M890:
322 case UNICHROME_P4M900:
323 case UNICHROME_VX800:
324 clock->set_primary_clock_state = set_primary_clock_state;
325 clock->set_primary_clock_source = set_primary_clock_source;
326 clock->set_primary_pll_state = set_primary_pll_state;
327 clock->set_primary_pll = k800_set_primary_pll;
328
329 clock->set_secondary_clock_state = set_secondary_clock_state;
330 clock->set_secondary_clock_source = set_secondary_clock_source;
331 clock->set_secondary_pll_state = set_secondary_pll_state;
332 clock->set_secondary_pll = k800_set_secondary_pll;
333
334 clock->set_engine_pll_state = set_engine_pll_state;
335 clock->set_engine_pll = k800_set_engine_pll;
336 break;
337 case UNICHROME_VX855:
338 case UNICHROME_VX900:
339 clock->set_primary_clock_state = set_primary_clock_state;
340 clock->set_primary_clock_source = set_primary_clock_source;
341 clock->set_primary_pll_state = set_primary_pll_state;
342 clock->set_primary_pll = vx855_set_primary_pll;
343
344 clock->set_secondary_clock_state = set_secondary_clock_state;
345 clock->set_secondary_clock_source = set_secondary_clock_source;
346 clock->set_secondary_pll_state = set_secondary_pll_state;
347 clock->set_secondary_pll = vx855_set_secondary_pll;
348
349 clock->set_engine_pll_state = set_engine_pll_state;
350 clock->set_engine_pll = vx855_set_engine_pll;
351 break;
352
353 }
354
355 if (machine_is_olpc()) {
356 /* The OLPC XO-1.5 cannot suspend/resume reliably if the
357 * IGA1/IGA2 clocks are set as on or off (memory rot
358 * occasionally happens during suspend under such
359 * configurations).
360 *
361 * The only known stable scenario is to leave this bits as-is,
362 * which in their default states are documented to enable the
363 * clock only when it is needed.
364 */
365 clock->set_primary_clock_state = noop_set_clock_state;
366 clock->set_secondary_clock_state = noop_set_clock_state;
367 }
368}
diff --git a/drivers/video/fbdev/via/via_clock.h b/drivers/video/fbdev/via/via_clock.h
new file mode 100644
index 000000000000..88714ae0d157
--- /dev/null
+++ b/drivers/video/fbdev/via/via_clock.h
@@ -0,0 +1,76 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * either version 2, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
13 * the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE.See the GNU General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22/*
23 * clock and PLL management functions
24 */
25
26#ifndef __VIA_CLOCK_H__
27#define __VIA_CLOCK_H__
28
29#include <linux/types.h>
30
31enum via_clksrc {
32 VIA_CLKSRC_X1 = 0,
33 VIA_CLKSRC_TVX1,
34 VIA_CLKSRC_TVPLL,
35 VIA_CLKSRC_DVP1TVCLKR,
36 VIA_CLKSRC_CAP0,
37 VIA_CLKSRC_CAP1,
38};
39
40struct via_pll_config {
41 u16 multiplier;
42 u8 divisor;
43 u8 rshift;
44};
45
46struct via_clock {
47 void (*set_primary_clock_state)(u8 state);
48 void (*set_primary_clock_source)(enum via_clksrc src, bool use_pll);
49 void (*set_primary_pll_state)(u8 state);
50 void (*set_primary_pll)(struct via_pll_config config);
51
52 void (*set_secondary_clock_state)(u8 state);
53 void (*set_secondary_clock_source)(enum via_clksrc src, bool use_pll);
54 void (*set_secondary_pll_state)(u8 state);
55 void (*set_secondary_pll)(struct via_pll_config config);
56
57 void (*set_engine_pll_state)(u8 state);
58 void (*set_engine_pll)(struct via_pll_config config);
59};
60
61
62static inline u32 get_pll_internal_frequency(u32 ref_freq,
63 struct via_pll_config pll)
64{
65 return ref_freq / pll.divisor * pll.multiplier;
66}
67
68static inline u32 get_pll_output_frequency(u32 ref_freq,
69 struct via_pll_config pll)
70{
71 return get_pll_internal_frequency(ref_freq, pll) >> pll.rshift;
72}
73
74void via_clock_init(struct via_clock *clock, int gfx_chip);
75
76#endif /* __VIA_CLOCK_H__ */
diff --git a/drivers/video/fbdev/via/via_i2c.c b/drivers/video/fbdev/via/via_i2c.c
new file mode 100644
index 000000000000..dd53058bbbb7
--- /dev/null
+++ b/drivers/video/fbdev/via/via_i2c.c
@@ -0,0 +1,295 @@
1/*
2 * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/platform_device.h>
23#include <linux/delay.h>
24#include <linux/spinlock.h>
25#include <linux/module.h>
26#include <linux/via-core.h>
27#include <linux/via_i2c.h>
28
29/*
30 * There can only be one set of these, so there's no point in having
31 * them be dynamically allocated...
32 */
33#define VIAFB_NUM_I2C 5
34static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
35static struct viafb_dev *i2c_vdev; /* Passed in from core */
36
37static void via_i2c_setscl(void *data, int state)
38{
39 u8 val;
40 struct via_port_cfg *adap_data = data;
41 unsigned long flags;
42
43 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
44 val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
45 if (state)
46 val |= 0x20;
47 else
48 val &= ~0x20;
49 switch (adap_data->type) {
50 case VIA_PORT_I2C:
51 val |= 0x01;
52 break;
53 case VIA_PORT_GPIO:
54 val |= 0x82;
55 break;
56 default:
57 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
58 }
59 via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
60 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
61}
62
63static int via_i2c_getscl(void *data)
64{
65 struct via_port_cfg *adap_data = data;
66 unsigned long flags;
67 int ret = 0;
68
69 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
70 if (adap_data->type == VIA_PORT_GPIO)
71 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
72 0, 0x80);
73 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
74 ret = 1;
75 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
76 return ret;
77}
78
79static int via_i2c_getsda(void *data)
80{
81 struct via_port_cfg *adap_data = data;
82 unsigned long flags;
83 int ret = 0;
84
85 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
86 if (adap_data->type == VIA_PORT_GPIO)
87 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
88 0, 0x40);
89 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
90 ret = 1;
91 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
92 return ret;
93}
94
95static void via_i2c_setsda(void *data, int state)
96{
97 u8 val;
98 struct via_port_cfg *adap_data = data;
99 unsigned long flags;
100
101 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
102 val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0;
103 if (state)
104 val |= 0x10;
105 else
106 val &= ~0x10;
107 switch (adap_data->type) {
108 case VIA_PORT_I2C:
109 val |= 0x01;
110 break;
111 case VIA_PORT_GPIO:
112 val |= 0x42;
113 break;
114 default:
115 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
116 }
117 via_write_reg(adap_data->io_port, adap_data->ioport_index, val);
118 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
119}
120
121int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata)
122{
123 int ret;
124 u8 mm1[] = {0x00};
125 struct i2c_msg msgs[2];
126
127 if (!via_i2c_par[adap].is_active)
128 return -ENODEV;
129 *pdata = 0;
130 msgs[0].flags = 0;
131 msgs[1].flags = I2C_M_RD;
132 msgs[0].addr = msgs[1].addr = slave_addr / 2;
133 mm1[0] = index;
134 msgs[0].len = 1; msgs[1].len = 1;
135 msgs[0].buf = mm1; msgs[1].buf = pdata;
136 ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
137 if (ret == 2)
138 ret = 0;
139 else if (ret >= 0)
140 ret = -EIO;
141
142 return ret;
143}
144
145int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data)
146{
147 int ret;
148 u8 msg[2] = { index, data };
149 struct i2c_msg msgs;
150
151 if (!via_i2c_par[adap].is_active)
152 return -ENODEV;
153 msgs.flags = 0;
154 msgs.addr = slave_addr / 2;
155 msgs.len = 2;
156 msgs.buf = msg;
157 ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1);
158 if (ret == 1)
159 ret = 0;
160 else if (ret >= 0)
161 ret = -EIO;
162
163 return ret;
164}
165
166int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len)
167{
168 int ret;
169 u8 mm1[] = {0x00};
170 struct i2c_msg msgs[2];
171
172 if (!via_i2c_par[adap].is_active)
173 return -ENODEV;
174 msgs[0].flags = 0;
175 msgs[1].flags = I2C_M_RD;
176 msgs[0].addr = msgs[1].addr = slave_addr / 2;
177 mm1[0] = index;
178 msgs[0].len = 1; msgs[1].len = buff_len;
179 msgs[0].buf = mm1; msgs[1].buf = buff;
180 ret = i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2);
181 if (ret == 2)
182 ret = 0;
183 else if (ret >= 0)
184 ret = -EIO;
185
186 return ret;
187}
188
189/*
190 * Allow other viafb subdevices to look up a specific adapter
191 * by port name.
192 */
193struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which)
194{
195 struct via_i2c_stuff *stuff = &via_i2c_par[which];
196
197 return &stuff->adapter;
198}
199EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter);
200
201
202static int create_i2c_bus(struct i2c_adapter *adapter,
203 struct i2c_algo_bit_data *algo,
204 struct via_port_cfg *adap_cfg,
205 struct pci_dev *pdev)
206{
207 algo->setsda = via_i2c_setsda;
208 algo->setscl = via_i2c_setscl;
209 algo->getsda = via_i2c_getsda;
210 algo->getscl = via_i2c_getscl;
211 algo->udelay = 10;
212 algo->timeout = 2;
213 algo->data = adap_cfg;
214
215 sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
216 adap_cfg->ioport_index);
217 adapter->owner = THIS_MODULE;
218 adapter->class = I2C_CLASS_DDC;
219 adapter->algo_data = algo;
220 if (pdev)
221 adapter->dev.parent = &pdev->dev;
222 else
223 adapter->dev.parent = NULL;
224 /* i2c_set_adapdata(adapter, adap_cfg); */
225
226 /* Raise SCL and SDA */
227 via_i2c_setsda(adap_cfg, 1);
228 via_i2c_setscl(adap_cfg, 1);
229 udelay(20);
230
231 return i2c_bit_add_bus(adapter);
232}
233
234static int viafb_i2c_probe(struct platform_device *platdev)
235{
236 int i, ret;
237 struct via_port_cfg *configs;
238
239 i2c_vdev = platdev->dev.platform_data;
240 configs = i2c_vdev->port_cfg;
241
242 for (i = 0; i < VIAFB_NUM_PORTS; i++) {
243 struct via_port_cfg *adap_cfg = configs++;
244 struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
245
246 i2c_stuff->is_active = 0;
247 if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C)
248 continue;
249 ret = create_i2c_bus(&i2c_stuff->adapter,
250 &i2c_stuff->algo, adap_cfg,
251 NULL); /* FIXME: PCIDEV */
252 if (ret < 0) {
253 printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n",
254 i, ret);
255 continue; /* Still try to make the rest */
256 }
257 i2c_stuff->is_active = 1;
258 }
259
260 return 0;
261}
262
263static int viafb_i2c_remove(struct platform_device *platdev)
264{
265 int i;
266
267 for (i = 0; i < VIAFB_NUM_PORTS; i++) {
268 struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i];
269 /*
270 * Only remove those entries in the array that we've
271 * actually used (and thus initialized algo_data)
272 */
273 if (i2c_stuff->is_active)
274 i2c_del_adapter(&i2c_stuff->adapter);
275 }
276 return 0;
277}
278
279static struct platform_driver via_i2c_driver = {
280 .driver = {
281 .name = "viafb-i2c",
282 },
283 .probe = viafb_i2c_probe,
284 .remove = viafb_i2c_remove,
285};
286
287int viafb_i2c_init(void)
288{
289 return platform_driver_register(&via_i2c_driver);
290}
291
292void viafb_i2c_exit(void)
293{
294 platform_driver_unregister(&via_i2c_driver);
295}
diff --git a/drivers/video/fbdev/via/via_modesetting.c b/drivers/video/fbdev/via/via_modesetting.c
new file mode 100644
index 000000000000..0b414b09b9b4
--- /dev/null
+++ b/drivers/video/fbdev/via/via_modesetting.c
@@ -0,0 +1,230 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * either version 2, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
13 * the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE.See the GNU General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22/*
23 * basic modesetting functions
24 */
25
26#include <linux/kernel.h>
27#include <linux/via-core.h>
28#include "via_modesetting.h"
29#include "share.h"
30#include "debug.h"
31
32
33void via_set_primary_timing(const struct via_display_timing *timing)
34{
35 struct via_display_timing raw;
36
37 raw.hor_total = timing->hor_total / 8 - 5;
38 raw.hor_addr = timing->hor_addr / 8 - 1;
39 raw.hor_blank_start = timing->hor_blank_start / 8 - 1;
40 raw.hor_blank_end = timing->hor_blank_end / 8 - 1;
41 raw.hor_sync_start = timing->hor_sync_start / 8;
42 raw.hor_sync_end = timing->hor_sync_end / 8;
43 raw.ver_total = timing->ver_total - 2;
44 raw.ver_addr = timing->ver_addr - 1;
45 raw.ver_blank_start = timing->ver_blank_start - 1;
46 raw.ver_blank_end = timing->ver_blank_end - 1;
47 raw.ver_sync_start = timing->ver_sync_start - 1;
48 raw.ver_sync_end = timing->ver_sync_end - 1;
49
50 /* unlock timing registers */
51 via_write_reg_mask(VIACR, 0x11, 0x00, 0x80);
52
53 via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF);
54 via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF);
55 via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF);
56 via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F);
57 via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF);
58 via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F)
59 | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F);
60 via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF);
61 via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01)
62 | (raw.ver_addr >> (8 - 1) & 0x02)
63 | (raw.ver_sync_start >> (8 - 2) & 0x04)
64 | (raw.ver_blank_start >> (8 - 3) & 0x08)
65 | (raw.ver_total >> (9 - 5) & 0x20)
66 | (raw.ver_addr >> (9 - 6) & 0x40)
67 | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF);
68 via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20,
69 0x20);
70 via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF);
71 via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F);
72 via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF);
73 via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF);
74 via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF);
75 via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10)
76 | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30);
77 via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01)
78 | (raw.ver_sync_start >> (10 - 1) & 0x02)
79 | (raw.ver_addr >> (10 - 2) & 0x04)
80 | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F);
81 via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08);
82
83 /* lock timing registers */
84 via_write_reg_mask(VIACR, 0x11, 0x80, 0x80);
85
86 /* reset timing control */
87 via_write_reg_mask(VIACR, 0x17, 0x00, 0x80);
88 via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
89}
90
91void via_set_secondary_timing(const struct via_display_timing *timing)
92{
93 struct via_display_timing raw;
94
95 raw.hor_total = timing->hor_total - 1;
96 raw.hor_addr = timing->hor_addr - 1;
97 raw.hor_blank_start = timing->hor_blank_start - 1;
98 raw.hor_blank_end = timing->hor_blank_end - 1;
99 raw.hor_sync_start = timing->hor_sync_start - 1;
100 raw.hor_sync_end = timing->hor_sync_end - 1;
101 raw.ver_total = timing->ver_total - 1;
102 raw.ver_addr = timing->ver_addr - 1;
103 raw.ver_blank_start = timing->ver_blank_start - 1;
104 raw.ver_blank_end = timing->ver_blank_end - 1;
105 raw.ver_sync_start = timing->ver_sync_start - 1;
106 raw.ver_sync_end = timing->ver_sync_end - 1;
107
108 via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF);
109 via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF);
110 via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF);
111 via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF);
112 via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07)
113 | (raw.hor_blank_end >> (8 - 3) & 0x38)
114 | (raw.hor_sync_start >> (8 - 6) & 0xC0));
115 via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F)
116 | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F);
117 via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF);
118 via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF);
119 via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF);
120 via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF);
121 via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF);
122 via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF);
123 via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07)
124 | (raw.ver_blank_end >> (8 - 3) & 0x38)
125 | (raw.hor_sync_end >> (8 - 6) & 0x40)
126 | (raw.hor_sync_start >> (10 - 7) & 0x80));
127 via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07)
128 | (raw.ver_addr >> (8 - 3) & 0x38)
129 | (raw.hor_blank_end >> (11 - 6) & 0x40)
130 | (raw.hor_sync_start >> (11 - 7) & 0x80));
131 via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF);
132 via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F)
133 | (raw.ver_sync_start >> (8 - 5) & 0xE0));
134}
135
136void via_set_primary_address(u32 addr)
137{
138 DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr);
139 via_write_reg(VIACR, 0x0D, addr & 0xFF);
140 via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF);
141 via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF);
142 via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F);
143}
144
145void via_set_secondary_address(u32 addr)
146{
147 DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr);
148 /* secondary display supports only quadword aligned memory */
149 via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE);
150 via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF);
151 via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF);
152 via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07);
153}
154
155void via_set_primary_pitch(u32 pitch)
156{
157 DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch);
158 /* spec does not say that first adapter skips 3 bits but old
159 * code did it and seems to be reasonable in analogy to 2nd adapter
160 */
161 pitch = pitch >> 3;
162 via_write_reg(VIACR, 0x13, pitch & 0xFF);
163 via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0);
164}
165
166void via_set_secondary_pitch(u32 pitch)
167{
168 DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch);
169 pitch = pitch >> 3;
170 via_write_reg(VIACR, 0x66, pitch & 0xFF);
171 via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03);
172 via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80);
173}
174
175void via_set_primary_color_depth(u8 depth)
176{
177 u8 value;
178
179 DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth);
180 switch (depth) {
181 case 8:
182 value = 0x00;
183 break;
184 case 15:
185 value = 0x04;
186 break;
187 case 16:
188 value = 0x14;
189 break;
190 case 24:
191 value = 0x0C;
192 break;
193 case 30:
194 value = 0x08;
195 break;
196 default:
197 printk(KERN_WARNING "via_set_primary_color_depth: "
198 "Unsupported depth: %d\n", depth);
199 return;
200 }
201
202 via_write_reg_mask(VIASR, 0x15, value, 0x1C);
203}
204
205void via_set_secondary_color_depth(u8 depth)
206{
207 u8 value;
208
209 DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth);
210 switch (depth) {
211 case 8:
212 value = 0x00;
213 break;
214 case 16:
215 value = 0x40;
216 break;
217 case 24:
218 value = 0xC0;
219 break;
220 case 30:
221 value = 0x80;
222 break;
223 default:
224 printk(KERN_WARNING "via_set_secondary_color_depth: "
225 "Unsupported depth: %d\n", depth);
226 return;
227 }
228
229 via_write_reg_mask(VIACR, 0x67, value, 0xC0);
230}
diff --git a/drivers/video/fbdev/via/via_modesetting.h b/drivers/video/fbdev/via/via_modesetting.h
new file mode 100644
index 000000000000..f6a6503da3b3
--- /dev/null
+++ b/drivers/video/fbdev/via/via_modesetting.h
@@ -0,0 +1,61 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License as published by the Free Software Foundation;
9 * either version 2, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
13 * the implied warranty of MERCHANTABILITY or FITNESS FOR
14 * A PARTICULAR PURPOSE.See the GNU General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22/*
23 * basic modesetting functions
24 */
25
26#ifndef __VIA_MODESETTING_H__
27#define __VIA_MODESETTING_H__
28
29#include <linux/types.h>
30
31
32#define VIA_PITCH_SIZE (1<<3)
33#define VIA_PITCH_MAX 0x3FF8
34
35
36struct via_display_timing {
37 u16 hor_total;
38 u16 hor_addr;
39 u16 hor_blank_start;
40 u16 hor_blank_end;
41 u16 hor_sync_start;
42 u16 hor_sync_end;
43 u16 ver_total;
44 u16 ver_addr;
45 u16 ver_blank_start;
46 u16 ver_blank_end;
47 u16 ver_sync_start;
48 u16 ver_sync_end;
49};
50
51
52void via_set_primary_timing(const struct via_display_timing *timing);
53void via_set_secondary_timing(const struct via_display_timing *timing);
54void via_set_primary_address(u32 addr);
55void via_set_secondary_address(u32 addr);
56void via_set_primary_pitch(u32 pitch);
57void via_set_secondary_pitch(u32 pitch);
58void via_set_primary_color_depth(u8 depth);
59void via_set_secondary_color_depth(u8 depth);
60
61#endif /* __VIA_MODESETTING_H__ */
diff --git a/drivers/video/fbdev/via/via_utility.c b/drivers/video/fbdev/via/via_utility.c
new file mode 100644
index 000000000000..35458a5eadc8
--- /dev/null
+++ b/drivers/video/fbdev/via/via_utility.c
@@ -0,0 +1,242 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/via-core.h>
23#include "global.h"
24
25void viafb_get_device_support_state(u32 *support_state)
26{
27 *support_state = CRT_Device;
28
29 if (viaparinfo->chip_info->tmds_chip_info.tmds_chip_name == VT1632_TMDS)
30 *support_state |= DVI_Device;
31
32 if (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name == VT1631_LVDS)
33 *support_state |= LCD_Device;
34}
35
36void viafb_get_device_connect_state(u32 *connect_state)
37{
38 bool mobile = false;
39
40 *connect_state = CRT_Device;
41
42 if (viafb_dvi_sense())
43 *connect_state |= DVI_Device;
44
45 viafb_lcd_get_mobile_state(&mobile);
46 if (mobile)
47 *connect_state |= LCD_Device;
48}
49
50bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres)
51{
52 unsigned int support_state = 0;
53
54 switch (viafb_lcd_panel_id) {
55 case LCD_PANEL_ID0_640X480:
56 if ((xres < 640) && (yres < 480))
57 support_state = true;
58 break;
59
60 case LCD_PANEL_ID1_800X600:
61 if ((xres < 800) && (yres < 600))
62 support_state = true;
63 break;
64
65 case LCD_PANEL_ID2_1024X768:
66 if ((xres < 1024) && (yres < 768))
67 support_state = true;
68 break;
69
70 case LCD_PANEL_ID3_1280X768:
71 if ((xres < 1280) && (yres < 768))
72 support_state = true;
73 break;
74
75 case LCD_PANEL_ID4_1280X1024:
76 if ((xres < 1280) && (yres < 1024))
77 support_state = true;
78 break;
79
80 case LCD_PANEL_ID5_1400X1050:
81 if ((xres < 1400) && (yres < 1050))
82 support_state = true;
83 break;
84
85 case LCD_PANEL_ID6_1600X1200:
86 if ((xres < 1600) && (yres < 1200))
87 support_state = true;
88 break;
89
90 case LCD_PANEL_ID7_1366X768:
91 if ((xres < 1366) && (yres < 768))
92 support_state = true;
93 break;
94
95 case LCD_PANEL_ID8_1024X600:
96 if ((xres < 1024) && (yres < 600))
97 support_state = true;
98 break;
99
100 case LCD_PANEL_ID9_1280X800:
101 if ((xres < 1280) && (yres < 800))
102 support_state = true;
103 break;
104
105 case LCD_PANEL_IDA_800X480:
106 if ((xres < 800) && (yres < 480))
107 support_state = true;
108 break;
109
110 case LCD_PANEL_IDB_1360X768:
111 if ((xres < 1360) && (yres < 768))
112 support_state = true;
113 break;
114
115 case LCD_PANEL_IDC_480X640:
116 if ((xres < 480) && (yres < 640))
117 support_state = true;
118 break;
119
120 default:
121 support_state = false;
122 break;
123 }
124
125 return support_state;
126}
127
128/*====================================================================*/
129/* Gamma Function Implementation*/
130/*====================================================================*/
131
132void viafb_set_gamma_table(int bpp, unsigned int *gamma_table)
133{
134 int i, sr1a;
135 int active_device_amount = 0;
136 int device_status = viafb_DeviceStatus;
137
138 for (i = 0; i < sizeof(viafb_DeviceStatus) * 8; i++) {
139 if (device_status & 1)
140 active_device_amount++;
141 device_status >>= 1;
142 }
143
144 /* 8 bpp mode can't adjust gamma */
145 if (bpp == 8)
146 return ;
147
148 /* Enable Gamma */
149 switch (viaparinfo->chip_info->gfx_chip_name) {
150 case UNICHROME_CLE266:
151 case UNICHROME_K400:
152 viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
153 break;
154
155 case UNICHROME_K800:
156 case UNICHROME_PM800:
157 case UNICHROME_CN700:
158 case UNICHROME_CX700:
159 case UNICHROME_K8M890:
160 case UNICHROME_P4M890:
161 case UNICHROME_P4M900:
162 viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
163 break;
164 }
165 sr1a = (unsigned int)viafb_read_reg(VIASR, SR1A);
166 viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
167
168 /* Fill IGA1 Gamma Table */
169 outb(0, LUT_INDEX_WRITE);
170 for (i = 0; i < 256; i++) {
171 outb(gamma_table[i] >> 16, LUT_DATA);
172 outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
173 outb(gamma_table[i] & 0xFF, LUT_DATA);
174 }
175
176 /* If adjust Gamma value in SAMM, fill IGA1,
177 IGA2 Gamma table simultaneous. */
178 /* Switch to IGA2 Gamma Table */
179 if ((active_device_amount > 1) &&
180 !((viaparinfo->chip_info->gfx_chip_name ==
181 UNICHROME_CLE266) &&
182 (viaparinfo->chip_info->gfx_chip_revision < 15))) {
183 viafb_write_reg_mask(SR1A, VIASR, 0x01, BIT0);
184 viafb_write_reg_mask(CR6A, VIACR, 0x02, BIT1);
185
186 /* Fill IGA2 Gamma Table */
187 outb(0, LUT_INDEX_WRITE);
188 for (i = 0; i < 256; i++) {
189 outb(gamma_table[i] >> 16, LUT_DATA);
190 outb(gamma_table[i] >> 8 & 0xFF, LUT_DATA);
191 outb(gamma_table[i] & 0xFF, LUT_DATA);
192 }
193 }
194 viafb_write_reg(SR1A, VIASR, sr1a);
195}
196
197void viafb_get_gamma_table(unsigned int *gamma_table)
198{
199 unsigned char color_r, color_g, color_b;
200 unsigned char sr1a = 0;
201 int i;
202
203 /* Enable Gamma */
204 switch (viaparinfo->chip_info->gfx_chip_name) {
205 case UNICHROME_CLE266:
206 case UNICHROME_K400:
207 viafb_write_reg_mask(SR16, VIASR, 0x80, BIT7);
208 break;
209
210 case UNICHROME_K800:
211 case UNICHROME_PM800:
212 case UNICHROME_CN700:
213 case UNICHROME_CX700:
214 case UNICHROME_K8M890:
215 case UNICHROME_P4M890:
216 case UNICHROME_P4M900:
217 viafb_write_reg_mask(CR33, VIACR, 0x80, BIT7);
218 break;
219 }
220 sr1a = viafb_read_reg(VIASR, SR1A);
221 viafb_write_reg_mask(SR1A, VIASR, 0x0, BIT0);
222
223 /* Reading gamma table to get color value */
224 outb(0, LUT_INDEX_READ);
225 for (i = 0; i < 256; i++) {
226 color_r = inb(LUT_DATA);
227 color_g = inb(LUT_DATA);
228 color_b = inb(LUT_DATA);
229 gamma_table[i] =
230 ((((u32) color_r) << 16) |
231 (((u16) color_g) << 8)) | color_b;
232 }
233 viafb_write_reg(SR1A, VIASR, sr1a);
234}
235
236void viafb_get_gamma_support_state(int bpp, unsigned int *support_state)
237{
238 if (bpp == 8)
239 *support_state = None_Device;
240 else
241 *support_state = CRT_Device | DVI_Device | LCD_Device;
242}
diff --git a/drivers/video/fbdev/via/via_utility.h b/drivers/video/fbdev/via/via_utility.h
new file mode 100644
index 000000000000..f23be1708c14
--- /dev/null
+++ b/drivers/video/fbdev/via/via_utility.h
@@ -0,0 +1,34 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21#ifndef __VIAUTILITY_H__
22#define __VIAUTILITY_H__
23
24/* These functions are used to get information about device's state */
25void viafb_get_device_support_state(u32 *support_state);
26void viafb_get_device_connect_state(u32 *connect_state);
27bool viafb_lcd_get_support_expand_state(u32 xres, u32 yres);
28
29/* These function are used to access gamma table */
30void viafb_set_gamma_table(int bpp, unsigned int *gamma_table);
31void viafb_get_gamma_table(unsigned int *gamma_table);
32void viafb_get_gamma_support_state(int bpp, unsigned int *support_state);
33
34#endif /* __VIAUTILITY_H__ */
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
new file mode 100644
index 000000000000..325c43c6ff97
--- /dev/null
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -0,0 +1,2176 @@
1/*
2 * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/module.h>
23#include <linux/seq_file.h>
24#include <linux/slab.h>
25#include <linux/stat.h>
26#include <linux/via-core.h>
27#include <linux/via_i2c.h>
28#include <asm/olpc.h>
29
30#define _MASTER_FILE
31#include "global.h"
32
33static char *viafb_name = "Via";
34static u32 pseudo_pal[17];
35
36/* video mode */
37static char *viafb_mode;
38static char *viafb_mode1;
39static int viafb_bpp = 32;
40static int viafb_bpp1 = 32;
41
42static unsigned int viafb_second_offset;
43static int viafb_second_size;
44
45static int viafb_accel = 1;
46
47/* Added for specifying active devices.*/
48static char *viafb_active_dev;
49
50/*Added for specify lcd output port*/
51static char *viafb_lcd_port = "";
52static char *viafb_dvi_port = "";
53
54static void retrieve_device_setting(struct viafb_ioctl_setting
55 *setting_info);
56static int viafb_pan_display(struct fb_var_screeninfo *var,
57 struct fb_info *info);
58
59static struct fb_ops viafb_ops;
60
61/* supported output devices on each IGP
62 * only CX700, VX800, VX855, VX900 were documented
63 * VIA_CRT should be everywhere
64 * VIA_6C can be onle pre-CX700 (probably only on CLE266) as 6C is used for PLL
65 * source selection on CX700 and later
66 * K400 seems to support VIA_96, VIA_DVP1, VIA_LVDS{1,2} as in viamode.c
67 */
68static const u32 supported_odev_map[] = {
69 [UNICHROME_CLE266] = VIA_CRT | VIA_LDVP0 | VIA_LDVP1,
70 [UNICHROME_K400] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
71 | VIA_LVDS2,
72 [UNICHROME_K800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
73 | VIA_LVDS2,
74 [UNICHROME_PM800] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
75 | VIA_LVDS2,
76 [UNICHROME_CN700] = VIA_CRT | VIA_DVP0 | VIA_DVP1 | VIA_LVDS1
77 | VIA_LVDS2,
78 [UNICHROME_CX700] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
79 [UNICHROME_CN750] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
80 [UNICHROME_K8M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
81 [UNICHROME_P4M890] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
82 [UNICHROME_P4M900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
83 [UNICHROME_VX800] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
84 [UNICHROME_VX855] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
85 [UNICHROME_VX900] = VIA_CRT | VIA_DVP1 | VIA_LVDS1 | VIA_LVDS2,
86};
87
88static void viafb_fill_var_color_info(struct fb_var_screeninfo *var, u8 depth)
89{
90 var->grayscale = 0;
91 var->red.msb_right = 0;
92 var->green.msb_right = 0;
93 var->blue.msb_right = 0;
94 var->transp.offset = 0;
95 var->transp.length = 0;
96 var->transp.msb_right = 0;
97 var->nonstd = 0;
98 switch (depth) {
99 case 8:
100 var->bits_per_pixel = 8;
101 var->red.offset = 0;
102 var->green.offset = 0;
103 var->blue.offset = 0;
104 var->red.length = 8;
105 var->green.length = 8;
106 var->blue.length = 8;
107 break;
108 case 15:
109 var->bits_per_pixel = 16;
110 var->red.offset = 10;
111 var->green.offset = 5;
112 var->blue.offset = 0;
113 var->red.length = 5;
114 var->green.length = 5;
115 var->blue.length = 5;
116 break;
117 case 16:
118 var->bits_per_pixel = 16;
119 var->red.offset = 11;
120 var->green.offset = 5;
121 var->blue.offset = 0;
122 var->red.length = 5;
123 var->green.length = 6;
124 var->blue.length = 5;
125 break;
126 case 24:
127 var->bits_per_pixel = 32;
128 var->red.offset = 16;
129 var->green.offset = 8;
130 var->blue.offset = 0;
131 var->red.length = 8;
132 var->green.length = 8;
133 var->blue.length = 8;
134 break;
135 case 30:
136 var->bits_per_pixel = 32;
137 var->red.offset = 20;
138 var->green.offset = 10;
139 var->blue.offset = 0;
140 var->red.length = 10;
141 var->green.length = 10;
142 var->blue.length = 10;
143 break;
144 }
145}
146
147static void viafb_update_fix(struct fb_info *info)
148{
149 u32 bpp = info->var.bits_per_pixel;
150
151 info->fix.visual =
152 bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
153 info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8,
154 VIA_PITCH_SIZE);
155}
156
157static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix,
158 struct viafb_par *viaparinfo)
159{
160 memset(fix, 0, sizeof(struct fb_fix_screeninfo));
161 strcpy(fix->id, viafb_name);
162
163 fix->smem_start = viaparinfo->fbmem;
164 fix->smem_len = viaparinfo->fbmem_free;
165
166 fix->type = FB_TYPE_PACKED_PIXELS;
167 fix->type_aux = 0;
168 fix->visual = FB_VISUAL_TRUECOLOR;
169
170 fix->xpanstep = fix->ywrapstep = 0;
171 fix->ypanstep = 1;
172
173 /* Just tell the accel name */
174 viafbinfo->fix.accel = FB_ACCEL_VIA_UNICHROME;
175}
176static int viafb_open(struct fb_info *info, int user)
177{
178 DEBUG_MSG(KERN_INFO "viafb_open!\n");
179 return 0;
180}
181
182static int viafb_release(struct fb_info *info, int user)
183{
184 DEBUG_MSG(KERN_INFO "viafb_release!\n");
185 return 0;
186}
187
188static inline int get_var_refresh(struct fb_var_screeninfo *var)
189{
190 u32 htotal, vtotal;
191
192 htotal = var->left_margin + var->xres + var->right_margin
193 + var->hsync_len;
194 vtotal = var->upper_margin + var->yres + var->lower_margin
195 + var->vsync_len;
196 return PICOS2KHZ(var->pixclock) * 1000 / (htotal * vtotal);
197}
198
199static int viafb_check_var(struct fb_var_screeninfo *var,
200 struct fb_info *info)
201{
202 int depth, refresh;
203 struct viafb_par *ppar = info->par;
204 u32 line;
205
206 DEBUG_MSG(KERN_INFO "viafb_check_var!\n");
207 /* Sanity check */
208 /* HW neither support interlacte nor double-scaned mode */
209 if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE)
210 return -EINVAL;
211
212 /* the refresh rate is not important here, as we only want to know
213 * whether the resolution exists
214 */
215 if (!viafb_get_best_mode(var->xres, var->yres, 60)) {
216 DEBUG_MSG(KERN_INFO
217 "viafb: Mode %dx%dx%d not supported!!\n",
218 var->xres, var->yres, var->bits_per_pixel);
219 return -EINVAL;
220 }
221
222 depth = fb_get_color_depth(var, &info->fix);
223 if (!depth)
224 depth = var->bits_per_pixel;
225
226 if (depth < 0 || depth > 32)
227 return -EINVAL;
228 else if (!depth)
229 depth = 24;
230 else if (depth == 15 && viafb_dual_fb && ppar->iga_path == IGA1)
231 depth = 15;
232 else if (depth == 30)
233 depth = 30;
234 else if (depth <= 8)
235 depth = 8;
236 else if (depth <= 16)
237 depth = 16;
238 else
239 depth = 24;
240
241 viafb_fill_var_color_info(var, depth);
242 if (var->xres_virtual < var->xres)
243 var->xres_virtual = var->xres;
244
245 line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8,
246 VIA_PITCH_SIZE);
247 if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize)
248 return -EINVAL;
249
250 /* Based on var passed in to calculate the refresh,
251 * because our driver use some modes special.
252 */
253 refresh = viafb_get_refresh(var->xres, var->yres,
254 get_var_refresh(var));
255
256 /* Adjust var according to our driver's own table */
257 viafb_fill_var_timing_info(var,
258 viafb_get_best_mode(var->xres, var->yres, refresh));
259 if (var->accel_flags & FB_ACCELF_TEXT &&
260 !ppar->shared->vdev->engine_mmio)
261 var->accel_flags = 0;
262
263 return 0;
264}
265
266static int viafb_set_par(struct fb_info *info)
267{
268 struct viafb_par *viapar = info->par;
269 int refresh;
270 DEBUG_MSG(KERN_INFO "viafb_set_par!\n");
271
272 viafb_update_fix(info);
273 viapar->depth = fb_get_color_depth(&info->var, &info->fix);
274 viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres,
275 viafbinfo->var.bits_per_pixel, 0);
276
277 if (viafb_dual_fb) {
278 viafb_update_device_setting(viafbinfo1->var.xres,
279 viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel,
280 1);
281 } else if (viafb_SAMM_ON == 1) {
282 DEBUG_MSG(KERN_INFO
283 "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n",
284 viafb_second_xres, viafb_second_yres, viafb_bpp1);
285
286 viafb_update_device_setting(viafb_second_xres,
287 viafb_second_yres, viafb_bpp1, 1);
288 }
289
290 refresh = get_var_refresh(&info->var);
291 if (viafb_dual_fb && viapar->iga_path == IGA2) {
292 viafb_bpp1 = info->var.bits_per_pixel;
293 viafb_refresh1 = refresh;
294 } else {
295 viafb_bpp = info->var.bits_per_pixel;
296 viafb_refresh = refresh;
297 }
298
299 if (info->var.accel_flags & FB_ACCELF_TEXT)
300 info->flags &= ~FBINFO_HWACCEL_DISABLED;
301 else
302 info->flags |= FBINFO_HWACCEL_DISABLED;
303 viafb_setmode();
304 viafb_pan_display(&info->var, info);
305
306 return 0;
307}
308
309/* Set one color register */
310static int viafb_setcolreg(unsigned regno, unsigned red, unsigned green,
311unsigned blue, unsigned transp, struct fb_info *info)
312{
313 struct viafb_par *viapar = info->par;
314 u32 r, g, b;
315
316 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
317 if (regno > 255)
318 return -EINVAL;
319
320 if (!viafb_dual_fb || viapar->iga_path == IGA1)
321 viafb_set_primary_color_register(regno, red >> 8,
322 green >> 8, blue >> 8);
323
324 if (!viafb_dual_fb || viapar->iga_path == IGA2)
325 viafb_set_secondary_color_register(regno, red >> 8,
326 green >> 8, blue >> 8);
327 } else {
328 if (regno > 15)
329 return -EINVAL;
330
331 r = (red >> (16 - info->var.red.length))
332 << info->var.red.offset;
333 b = (blue >> (16 - info->var.blue.length))
334 << info->var.blue.offset;
335 g = (green >> (16 - info->var.green.length))
336 << info->var.green.offset;
337 ((u32 *) info->pseudo_palette)[regno] = r | g | b;
338 }
339
340 return 0;
341}
342
343static int viafb_pan_display(struct fb_var_screeninfo *var,
344 struct fb_info *info)
345{
346 struct viafb_par *viapar = info->par;
347 u32 vram_addr = viapar->vram_addr
348 + var->yoffset * info->fix.line_length
349 + var->xoffset * info->var.bits_per_pixel / 8;
350
351 DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr);
352 if (!viafb_dual_fb) {
353 via_set_primary_address(vram_addr);
354 via_set_secondary_address(vram_addr);
355 } else if (viapar->iga_path == IGA1)
356 via_set_primary_address(vram_addr);
357 else
358 via_set_secondary_address(vram_addr);
359
360 return 0;
361}
362
363static int viafb_blank(int blank_mode, struct fb_info *info)
364{
365 DEBUG_MSG(KERN_INFO "viafb_blank!\n");
366 /* clear DPMS setting */
367
368 switch (blank_mode) {
369 case FB_BLANK_UNBLANK:
370 /* Screen: On, HSync: On, VSync: On */
371 /* control CRT monitor power management */
372 via_set_state(VIA_CRT, VIA_STATE_ON);
373 break;
374 case FB_BLANK_HSYNC_SUSPEND:
375 /* Screen: Off, HSync: Off, VSync: On */
376 /* control CRT monitor power management */
377 via_set_state(VIA_CRT, VIA_STATE_STANDBY);
378 break;
379 case FB_BLANK_VSYNC_SUSPEND:
380 /* Screen: Off, HSync: On, VSync: Off */
381 /* control CRT monitor power management */
382 via_set_state(VIA_CRT, VIA_STATE_SUSPEND);
383 break;
384 case FB_BLANK_POWERDOWN:
385 /* Screen: Off, HSync: Off, VSync: Off */
386 /* control CRT monitor power management */
387 via_set_state(VIA_CRT, VIA_STATE_OFF);
388 break;
389 }
390
391 return 0;
392}
393
394static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
395{
396 union {
397 struct viafb_ioctl_mode viamode;
398 struct viafb_ioctl_samm viasamm;
399 struct viafb_driver_version driver_version;
400 struct fb_var_screeninfo sec_var;
401 struct _panel_size_pos_info panel_pos_size_para;
402 struct viafb_ioctl_setting viafb_setting;
403 struct device_t active_dev;
404 } u;
405 u32 state_info = 0;
406 u32 *viafb_gamma_table;
407 char driver_name[] = "viafb";
408
409 u32 __user *argp = (u32 __user *) arg;
410 u32 gpu32;
411
412 DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd);
413 printk(KERN_WARNING "viafb_ioctl: Please avoid this interface as it is unstable and might change or vanish at any time!\n");
414 memset(&u, 0, sizeof(u));
415
416 switch (cmd) {
417 case VIAFB_GET_CHIP_INFO:
418 if (copy_to_user(argp, viaparinfo->chip_info,
419 sizeof(struct chip_information)))
420 return -EFAULT;
421 break;
422 case VIAFB_GET_INFO_SIZE:
423 return put_user((u32)sizeof(struct viafb_ioctl_info), argp);
424 case VIAFB_GET_INFO:
425 return viafb_ioctl_get_viafb_info(arg);
426 case VIAFB_HOTPLUG:
427 return put_user(viafb_ioctl_hotplug(info->var.xres,
428 info->var.yres,
429 info->var.bits_per_pixel), argp);
430 case VIAFB_SET_HOTPLUG_FLAG:
431 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
432 return -EFAULT;
433 viafb_hotplug = (gpu32) ? 1 : 0;
434 break;
435 case VIAFB_GET_RESOLUTION:
436 u.viamode.xres = (u32) viafb_hotplug_Xres;
437 u.viamode.yres = (u32) viafb_hotplug_Yres;
438 u.viamode.refresh = (u32) viafb_hotplug_refresh;
439 u.viamode.bpp = (u32) viafb_hotplug_bpp;
440 if (viafb_SAMM_ON == 1) {
441 u.viamode.xres_sec = viafb_second_xres;
442 u.viamode.yres_sec = viafb_second_yres;
443 u.viamode.virtual_xres_sec = viafb_dual_fb ? viafbinfo1->var.xres_virtual : viafbinfo->var.xres_virtual;
444 u.viamode.virtual_yres_sec = viafb_dual_fb ? viafbinfo1->var.yres_virtual : viafbinfo->var.yres_virtual;
445 u.viamode.refresh_sec = viafb_refresh1;
446 u.viamode.bpp_sec = viafb_bpp1;
447 } else {
448 u.viamode.xres_sec = 0;
449 u.viamode.yres_sec = 0;
450 u.viamode.virtual_xres_sec = 0;
451 u.viamode.virtual_yres_sec = 0;
452 u.viamode.refresh_sec = 0;
453 u.viamode.bpp_sec = 0;
454 }
455 if (copy_to_user(argp, &u.viamode, sizeof(u.viamode)))
456 return -EFAULT;
457 break;
458 case VIAFB_GET_SAMM_INFO:
459 u.viasamm.samm_status = viafb_SAMM_ON;
460
461 if (viafb_SAMM_ON == 1) {
462 if (viafb_dual_fb) {
463 u.viasamm.size_prim = viaparinfo->fbmem_free;
464 u.viasamm.size_sec = viaparinfo1->fbmem_free;
465 } else {
466 if (viafb_second_size) {
467 u.viasamm.size_prim =
468 viaparinfo->fbmem_free -
469 viafb_second_size * 1024 * 1024;
470 u.viasamm.size_sec =
471 viafb_second_size * 1024 * 1024;
472 } else {
473 u.viasamm.size_prim =
474 viaparinfo->fbmem_free >> 1;
475 u.viasamm.size_sec =
476 (viaparinfo->fbmem_free >> 1);
477 }
478 }
479 u.viasamm.mem_base = viaparinfo->fbmem;
480 u.viasamm.offset_sec = viafb_second_offset;
481 } else {
482 u.viasamm.size_prim =
483 viaparinfo->memsize - viaparinfo->fbmem_used;
484 u.viasamm.size_sec = 0;
485 u.viasamm.mem_base = viaparinfo->fbmem;
486 u.viasamm.offset_sec = 0;
487 }
488
489 if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm)))
490 return -EFAULT;
491
492 break;
493 case VIAFB_TURN_ON_OUTPUT_DEVICE:
494 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
495 return -EFAULT;
496 if (gpu32 & CRT_Device)
497 via_set_state(VIA_CRT, VIA_STATE_ON);
498 if (gpu32 & DVI_Device)
499 viafb_dvi_enable();
500 if (gpu32 & LCD_Device)
501 viafb_lcd_enable();
502 break;
503 case VIAFB_TURN_OFF_OUTPUT_DEVICE:
504 if (copy_from_user(&gpu32, argp, sizeof(gpu32)))
505 return -EFAULT;
506 if (gpu32 & CRT_Device)
507 via_set_state(VIA_CRT, VIA_STATE_OFF);
508 if (gpu32 & DVI_Device)
509 viafb_dvi_disable();
510 if (gpu32 & LCD_Device)
511 viafb_lcd_disable();
512 break;
513 case VIAFB_GET_DEVICE:
514 u.active_dev.crt = viafb_CRT_ON;
515 u.active_dev.dvi = viafb_DVI_ON;
516 u.active_dev.lcd = viafb_LCD_ON;
517 u.active_dev.samm = viafb_SAMM_ON;
518 u.active_dev.primary_dev = viafb_primary_dev;
519
520 u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method;
521 u.active_dev.lcd_panel_id = viafb_lcd_panel_id;
522 u.active_dev.lcd_mode = viafb_lcd_mode;
523
524 u.active_dev.xres = viafb_hotplug_Xres;
525 u.active_dev.yres = viafb_hotplug_Yres;
526
527 u.active_dev.xres1 = viafb_second_xres;
528 u.active_dev.yres1 = viafb_second_yres;
529
530 u.active_dev.bpp = viafb_bpp;
531 u.active_dev.bpp1 = viafb_bpp1;
532 u.active_dev.refresh = viafb_refresh;
533 u.active_dev.refresh1 = viafb_refresh1;
534
535 u.active_dev.epia_dvi = viafb_platform_epia_dvi;
536 u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge;
537 u.active_dev.bus_width = viafb_bus_width;
538
539 if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev)))
540 return -EFAULT;
541 break;
542
543 case VIAFB_GET_DRIVER_VERSION:
544 u.driver_version.iMajorNum = VERSION_MAJOR;
545 u.driver_version.iKernelNum = VERSION_KERNEL;
546 u.driver_version.iOSNum = VERSION_OS;
547 u.driver_version.iMinorNum = VERSION_MINOR;
548
549 if (copy_to_user(argp, &u.driver_version,
550 sizeof(u.driver_version)))
551 return -EFAULT;
552
553 break;
554
555 case VIAFB_GET_DEVICE_INFO:
556
557 retrieve_device_setting(&u.viafb_setting);
558
559 if (copy_to_user(argp, &u.viafb_setting,
560 sizeof(u.viafb_setting)))
561 return -EFAULT;
562
563 break;
564
565 case VIAFB_GET_DEVICE_SUPPORT:
566 viafb_get_device_support_state(&state_info);
567 if (put_user(state_info, argp))
568 return -EFAULT;
569 break;
570
571 case VIAFB_GET_DEVICE_CONNECT:
572 viafb_get_device_connect_state(&state_info);
573 if (put_user(state_info, argp))
574 return -EFAULT;
575 break;
576
577 case VIAFB_GET_PANEL_SUPPORT_EXPAND:
578 state_info =
579 viafb_lcd_get_support_expand_state(info->var.xres,
580 info->var.yres);
581 if (put_user(state_info, argp))
582 return -EFAULT;
583 break;
584
585 case VIAFB_GET_DRIVER_NAME:
586 if (copy_to_user(argp, driver_name, sizeof(driver_name)))
587 return -EFAULT;
588 break;
589
590 case VIAFB_SET_GAMMA_LUT:
591 viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32));
592 if (IS_ERR(viafb_gamma_table))
593 return PTR_ERR(viafb_gamma_table);
594 viafb_set_gamma_table(viafb_bpp, viafb_gamma_table);
595 kfree(viafb_gamma_table);
596 break;
597
598 case VIAFB_GET_GAMMA_LUT:
599 viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
600 if (!viafb_gamma_table)
601 return -ENOMEM;
602 viafb_get_gamma_table(viafb_gamma_table);
603 if (copy_to_user(argp, viafb_gamma_table,
604 256 * sizeof(u32))) {
605 kfree(viafb_gamma_table);
606 return -EFAULT;
607 }
608 kfree(viafb_gamma_table);
609 break;
610
611 case VIAFB_GET_GAMMA_SUPPORT_STATE:
612 viafb_get_gamma_support_state(viafb_bpp, &state_info);
613 if (put_user(state_info, argp))
614 return -EFAULT;
615 break;
616 case VIAFB_SYNC_SURFACE:
617 DEBUG_MSG(KERN_INFO "lobo VIAFB_SYNC_SURFACE\n");
618 break;
619 case VIAFB_GET_DRIVER_CAPS:
620 break;
621
622 case VIAFB_GET_PANEL_MAX_SIZE:
623 if (copy_from_user(&u.panel_pos_size_para, argp,
624 sizeof(u.panel_pos_size_para)))
625 return -EFAULT;
626 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
627 if (copy_to_user(argp, &u.panel_pos_size_para,
628 sizeof(u.panel_pos_size_para)))
629 return -EFAULT;
630 break;
631 case VIAFB_GET_PANEL_MAX_POSITION:
632 if (copy_from_user(&u.panel_pos_size_para, argp,
633 sizeof(u.panel_pos_size_para)))
634 return -EFAULT;
635 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
636 if (copy_to_user(argp, &u.panel_pos_size_para,
637 sizeof(u.panel_pos_size_para)))
638 return -EFAULT;
639 break;
640
641 case VIAFB_GET_PANEL_POSITION:
642 if (copy_from_user(&u.panel_pos_size_para, argp,
643 sizeof(u.panel_pos_size_para)))
644 return -EFAULT;
645 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
646 if (copy_to_user(argp, &u.panel_pos_size_para,
647 sizeof(u.panel_pos_size_para)))
648 return -EFAULT;
649 break;
650 case VIAFB_GET_PANEL_SIZE:
651 if (copy_from_user(&u.panel_pos_size_para, argp,
652 sizeof(u.panel_pos_size_para)))
653 return -EFAULT;
654 u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0;
655 if (copy_to_user(argp, &u.panel_pos_size_para,
656 sizeof(u.panel_pos_size_para)))
657 return -EFAULT;
658 break;
659
660 case VIAFB_SET_PANEL_POSITION:
661 if (copy_from_user(&u.panel_pos_size_para, argp,
662 sizeof(u.panel_pos_size_para)))
663 return -EFAULT;
664 break;
665 case VIAFB_SET_PANEL_SIZE:
666 if (copy_from_user(&u.panel_pos_size_para, argp,
667 sizeof(u.panel_pos_size_para)))
668 return -EFAULT;
669 break;
670
671 default:
672 return -EINVAL;
673 }
674
675 return 0;
676}
677
678static void viafb_fillrect(struct fb_info *info,
679 const struct fb_fillrect *rect)
680{
681 struct viafb_par *viapar = info->par;
682 struct viafb_shared *shared = viapar->shared;
683 u32 fg_color;
684 u8 rop;
685
686 if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
687 cfb_fillrect(info, rect);
688 return;
689 }
690
691 if (!rect->width || !rect->height)
692 return;
693
694 if (info->fix.visual == FB_VISUAL_TRUECOLOR)
695 fg_color = ((u32 *)info->pseudo_palette)[rect->color];
696 else
697 fg_color = rect->color;
698
699 if (rect->rop == ROP_XOR)
700 rop = 0x5A;
701 else
702 rop = 0xF0;
703
704 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n");
705 if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL,
706 rect->width, rect->height, info->var.bits_per_pixel,
707 viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy,
708 NULL, 0, 0, 0, 0, fg_color, 0, rop))
709 cfb_fillrect(info, rect);
710}
711
712static void viafb_copyarea(struct fb_info *info,
713 const struct fb_copyarea *area)
714{
715 struct viafb_par *viapar = info->par;
716 struct viafb_shared *shared = viapar->shared;
717
718 if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt) {
719 cfb_copyarea(info, area);
720 return;
721 }
722
723 if (!area->width || !area->height)
724 return;
725
726 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n");
727 if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR,
728 area->width, area->height, info->var.bits_per_pixel,
729 viapar->vram_addr, info->fix.line_length, area->dx, area->dy,
730 NULL, viapar->vram_addr, info->fix.line_length,
731 area->sx, area->sy, 0, 0, 0))
732 cfb_copyarea(info, area);
733}
734
735static void viafb_imageblit(struct fb_info *info,
736 const struct fb_image *image)
737{
738 struct viafb_par *viapar = info->par;
739 struct viafb_shared *shared = viapar->shared;
740 u32 fg_color = 0, bg_color = 0;
741 u8 op;
742
743 if (info->flags & FBINFO_HWACCEL_DISABLED || !shared->hw_bitblt ||
744 (image->depth != 1 && image->depth != viapar->depth)) {
745 cfb_imageblit(info, image);
746 return;
747 }
748
749 if (image->depth == 1) {
750 op = VIA_BITBLT_MONO;
751 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
752 fg_color =
753 ((u32 *)info->pseudo_palette)[image->fg_color];
754 bg_color =
755 ((u32 *)info->pseudo_palette)[image->bg_color];
756 } else {
757 fg_color = image->fg_color;
758 bg_color = image->bg_color;
759 }
760 } else
761 op = VIA_BITBLT_COLOR;
762
763 DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n");
764 if (shared->hw_bitblt(shared->vdev->engine_mmio, op,
765 image->width, image->height, info->var.bits_per_pixel,
766 viapar->vram_addr, info->fix.line_length, image->dx, image->dy,
767 (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0))
768 cfb_imageblit(info, image);
769}
770
771static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
772{
773 struct viafb_par *viapar = info->par;
774 void __iomem *engine = viapar->shared->vdev->engine_mmio;
775 u32 temp, xx, yy, bg_color = 0, fg_color = 0,
776 chip_name = viapar->shared->chip_info.gfx_chip_name;
777 int i, j = 0, cur_size = 64;
778
779 if (info->flags & FBINFO_HWACCEL_DISABLED || info != viafbinfo)
780 return -ENODEV;
781
782 /* LCD ouput does not support hw cursors (at least on VN896) */
783 if ((chip_name == UNICHROME_CLE266 && viapar->iga_path == IGA2) ||
784 viafb_LCD_ON)
785 return -ENODEV;
786
787 viafb_show_hw_cursor(info, HW_Cursor_OFF);
788
789 if (cursor->set & FB_CUR_SETHOT) {
790 temp = (cursor->hot.x << 16) + cursor->hot.y;
791 writel(temp, engine + VIA_REG_CURSOR_ORG);
792 }
793
794 if (cursor->set & FB_CUR_SETPOS) {
795 yy = cursor->image.dy - info->var.yoffset;
796 xx = cursor->image.dx - info->var.xoffset;
797 temp = yy & 0xFFFF;
798 temp |= (xx << 16);
799 writel(temp, engine + VIA_REG_CURSOR_POS);
800 }
801
802 if (cursor->image.width <= 32 && cursor->image.height <= 32)
803 cur_size = 32;
804 else if (cursor->image.width <= 64 && cursor->image.height <= 64)
805 cur_size = 64;
806 else {
807 printk(KERN_WARNING "viafb_cursor: The cursor is too large "
808 "%dx%d", cursor->image.width, cursor->image.height);
809 return -ENXIO;
810 }
811
812 if (cursor->set & FB_CUR_SETSIZE) {
813 temp = readl(engine + VIA_REG_CURSOR_MODE);
814 if (cur_size == 32)
815 temp |= 0x2;
816 else
817 temp &= ~0x2;
818
819 writel(temp, engine + VIA_REG_CURSOR_MODE);
820 }
821
822 if (cursor->set & FB_CUR_SETCMAP) {
823 fg_color = cursor->image.fg_color;
824 bg_color = cursor->image.bg_color;
825 if (chip_name == UNICHROME_CX700 ||
826 chip_name == UNICHROME_VX800 ||
827 chip_name == UNICHROME_VX855 ||
828 chip_name == UNICHROME_VX900) {
829 fg_color =
830 ((info->cmap.red[fg_color] & 0xFFC0) << 14) |
831 ((info->cmap.green[fg_color] & 0xFFC0) << 4) |
832 ((info->cmap.blue[fg_color] & 0xFFC0) >> 6);
833 bg_color =
834 ((info->cmap.red[bg_color] & 0xFFC0) << 14) |
835 ((info->cmap.green[bg_color] & 0xFFC0) << 4) |
836 ((info->cmap.blue[bg_color] & 0xFFC0) >> 6);
837 } else {
838 fg_color =
839 ((info->cmap.red[fg_color] & 0xFF00) << 8) |
840 (info->cmap.green[fg_color] & 0xFF00) |
841 ((info->cmap.blue[fg_color] & 0xFF00) >> 8);
842 bg_color =
843 ((info->cmap.red[bg_color] & 0xFF00) << 8) |
844 (info->cmap.green[bg_color] & 0xFF00) |
845 ((info->cmap.blue[bg_color] & 0xFF00) >> 8);
846 }
847
848 writel(bg_color, engine + VIA_REG_CURSOR_BG);
849 writel(fg_color, engine + VIA_REG_CURSOR_FG);
850 }
851
852 if (cursor->set & FB_CUR_SETSHAPE) {
853 struct {
854 u8 data[CURSOR_SIZE];
855 u32 bak[CURSOR_SIZE / 4];
856 } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC);
857 int size = ((cursor->image.width + 7) >> 3) *
858 cursor->image.height;
859
860 if (!cr_data)
861 return -ENOMEM;
862
863 if (cur_size == 32) {
864 for (i = 0; i < (CURSOR_SIZE / 4); i++) {
865 cr_data->bak[i] = 0x0;
866 cr_data->bak[i + 1] = 0xFFFFFFFF;
867 i += 1;
868 }
869 } else {
870 for (i = 0; i < (CURSOR_SIZE / 4); i++) {
871 cr_data->bak[i] = 0x0;
872 cr_data->bak[i + 1] = 0x0;
873 cr_data->bak[i + 2] = 0xFFFFFFFF;
874 cr_data->bak[i + 3] = 0xFFFFFFFF;
875 i += 3;
876 }
877 }
878
879 switch (cursor->rop) {
880 case ROP_XOR:
881 for (i = 0; i < size; i++)
882 cr_data->data[i] = cursor->mask[i];
883 break;
884 case ROP_COPY:
885
886 for (i = 0; i < size; i++)
887 cr_data->data[i] = cursor->mask[i];
888 break;
889 default:
890 break;
891 }
892
893 if (cur_size == 32) {
894 for (i = 0; i < size; i++) {
895 cr_data->bak[j] = (u32) cr_data->data[i];
896 cr_data->bak[j + 1] = ~cr_data->bak[j];
897 j += 2;
898 }
899 } else {
900 for (i = 0; i < size; i++) {
901 cr_data->bak[j] = (u32) cr_data->data[i];
902 cr_data->bak[j + 1] = 0x0;
903 cr_data->bak[j + 2] = ~cr_data->bak[j];
904 cr_data->bak[j + 3] = ~cr_data->bak[j + 1];
905 j += 4;
906 }
907 }
908
909 memcpy_toio(viafbinfo->screen_base + viapar->shared->
910 cursor_vram_addr, cr_data->bak, CURSOR_SIZE);
911 kfree(cr_data);
912 }
913
914 if (cursor->enable)
915 viafb_show_hw_cursor(info, HW_Cursor_ON);
916
917 return 0;
918}
919
920static int viafb_sync(struct fb_info *info)
921{
922 if (!(info->flags & FBINFO_HWACCEL_DISABLED))
923 viafb_wait_engine_idle(info);
924 return 0;
925}
926
927static int get_primary_device(void)
928{
929 int primary_device = 0;
930 /* Rule: device on iga1 path are the primary device. */
931 if (viafb_SAMM_ON) {
932 if (viafb_CRT_ON) {
933 if (viaparinfo->shared->iga1_devices & VIA_CRT) {
934 DEBUG_MSG(KERN_INFO "CRT IGA Path:%d\n", IGA1);
935 primary_device = CRT_Device;
936 }
937 }
938 if (viafb_DVI_ON) {
939 if (viaparinfo->tmds_setting_info->iga_path == IGA1) {
940 DEBUG_MSG(KERN_INFO "DVI IGA Path:%d\n",
941 viaparinfo->
942 tmds_setting_info->iga_path);
943 primary_device = DVI_Device;
944 }
945 }
946 if (viafb_LCD_ON) {
947 if (viaparinfo->lvds_setting_info->iga_path == IGA1) {
948 DEBUG_MSG(KERN_INFO "LCD IGA Path:%d\n",
949 viaparinfo->
950 lvds_setting_info->iga_path);
951 primary_device = LCD_Device;
952 }
953 }
954 if (viafb_LCD2_ON) {
955 if (viaparinfo->lvds_setting_info2->iga_path == IGA1) {
956 DEBUG_MSG(KERN_INFO "LCD2 IGA Path:%d\n",
957 viaparinfo->
958 lvds_setting_info2->iga_path);
959 primary_device = LCD2_Device;
960 }
961 }
962 }
963 return primary_device;
964}
965
966static void retrieve_device_setting(struct viafb_ioctl_setting
967 *setting_info)
968{
969
970 /* get device status */
971 if (viafb_CRT_ON == 1)
972 setting_info->device_status = CRT_Device;
973 if (viafb_DVI_ON == 1)
974 setting_info->device_status |= DVI_Device;
975 if (viafb_LCD_ON == 1)
976 setting_info->device_status |= LCD_Device;
977 if (viafb_LCD2_ON == 1)
978 setting_info->device_status |= LCD2_Device;
979
980 setting_info->samm_status = viafb_SAMM_ON;
981 setting_info->primary_device = get_primary_device();
982
983 setting_info->first_dev_bpp = viafb_bpp;
984 setting_info->second_dev_bpp = viafb_bpp1;
985
986 setting_info->first_dev_refresh = viafb_refresh;
987 setting_info->second_dev_refresh = viafb_refresh1;
988
989 setting_info->first_dev_hor_res = viafb_hotplug_Xres;
990 setting_info->first_dev_ver_res = viafb_hotplug_Yres;
991 setting_info->second_dev_hor_res = viafb_second_xres;
992 setting_info->second_dev_ver_res = viafb_second_yres;
993
994 /* Get lcd attributes */
995 setting_info->lcd_attributes.display_center = viafb_lcd_dsp_method;
996 setting_info->lcd_attributes.panel_id = viafb_lcd_panel_id;
997 setting_info->lcd_attributes.lcd_mode = viafb_lcd_mode;
998}
999
1000static int __init parse_active_dev(void)
1001{
1002 viafb_CRT_ON = STATE_OFF;
1003 viafb_DVI_ON = STATE_OFF;
1004 viafb_LCD_ON = STATE_OFF;
1005 viafb_LCD2_ON = STATE_OFF;
1006 /* 1. Modify the active status of devices. */
1007 /* 2. Keep the order of devices, so we can set corresponding
1008 IGA path to devices in SAMM case. */
1009 /* Note: The previous of active_dev is primary device,
1010 and the following is secondary device. */
1011 if (!viafb_active_dev) {
1012 if (machine_is_olpc()) { /* LCD only */
1013 viafb_LCD_ON = STATE_ON;
1014 viafb_SAMM_ON = STATE_OFF;
1015 } else {
1016 viafb_CRT_ON = STATE_ON;
1017 viafb_SAMM_ON = STATE_OFF;
1018 }
1019 } else if (!strcmp(viafb_active_dev, "CRT+DVI")) {
1020 /* CRT+DVI */
1021 viafb_CRT_ON = STATE_ON;
1022 viafb_DVI_ON = STATE_ON;
1023 viafb_primary_dev = CRT_Device;
1024 } else if (!strcmp(viafb_active_dev, "DVI+CRT")) {
1025 /* DVI+CRT */
1026 viafb_CRT_ON = STATE_ON;
1027 viafb_DVI_ON = STATE_ON;
1028 viafb_primary_dev = DVI_Device;
1029 } else if (!strcmp(viafb_active_dev, "CRT+LCD")) {
1030 /* CRT+LCD */
1031 viafb_CRT_ON = STATE_ON;
1032 viafb_LCD_ON = STATE_ON;
1033 viafb_primary_dev = CRT_Device;
1034 } else if (!strcmp(viafb_active_dev, "LCD+CRT")) {
1035 /* LCD+CRT */
1036 viafb_CRT_ON = STATE_ON;
1037 viafb_LCD_ON = STATE_ON;
1038 viafb_primary_dev = LCD_Device;
1039 } else if (!strcmp(viafb_active_dev, "DVI+LCD")) {
1040 /* DVI+LCD */
1041 viafb_DVI_ON = STATE_ON;
1042 viafb_LCD_ON = STATE_ON;
1043 viafb_primary_dev = DVI_Device;
1044 } else if (!strcmp(viafb_active_dev, "LCD+DVI")) {
1045 /* LCD+DVI */
1046 viafb_DVI_ON = STATE_ON;
1047 viafb_LCD_ON = STATE_ON;
1048 viafb_primary_dev = LCD_Device;
1049 } else if (!strcmp(viafb_active_dev, "LCD+LCD2")) {
1050 viafb_LCD_ON = STATE_ON;
1051 viafb_LCD2_ON = STATE_ON;
1052 viafb_primary_dev = LCD_Device;
1053 } else if (!strcmp(viafb_active_dev, "LCD2+LCD")) {
1054 viafb_LCD_ON = STATE_ON;
1055 viafb_LCD2_ON = STATE_ON;
1056 viafb_primary_dev = LCD2_Device;
1057 } else if (!strcmp(viafb_active_dev, "CRT")) {
1058 /* CRT only */
1059 viafb_CRT_ON = STATE_ON;
1060 viafb_SAMM_ON = STATE_OFF;
1061 } else if (!strcmp(viafb_active_dev, "DVI")) {
1062 /* DVI only */
1063 viafb_DVI_ON = STATE_ON;
1064 viafb_SAMM_ON = STATE_OFF;
1065 } else if (!strcmp(viafb_active_dev, "LCD")) {
1066 /* LCD only */
1067 viafb_LCD_ON = STATE_ON;
1068 viafb_SAMM_ON = STATE_OFF;
1069 } else
1070 return -EINVAL;
1071
1072 return 0;
1073}
1074
1075static int parse_port(char *opt_str, int *output_interface)
1076{
1077 if (!strncmp(opt_str, "DVP0", 4))
1078 *output_interface = INTERFACE_DVP0;
1079 else if (!strncmp(opt_str, "DVP1", 4))
1080 *output_interface = INTERFACE_DVP1;
1081 else if (!strncmp(opt_str, "DFP_HIGHLOW", 11))
1082 *output_interface = INTERFACE_DFP;
1083 else if (!strncmp(opt_str, "DFP_HIGH", 8))
1084 *output_interface = INTERFACE_DFP_HIGH;
1085 else if (!strncmp(opt_str, "DFP_LOW", 7))
1086 *output_interface = INTERFACE_DFP_LOW;
1087 else
1088 *output_interface = INTERFACE_NONE;
1089 return 0;
1090}
1091
1092static void parse_lcd_port(void)
1093{
1094 parse_port(viafb_lcd_port, &viaparinfo->chip_info->lvds_chip_info.
1095 output_interface);
1096 /*Initialize to avoid unexpected behavior */
1097 viaparinfo->chip_info->lvds_chip_info2.output_interface =
1098 INTERFACE_NONE;
1099
1100 DEBUG_MSG(KERN_INFO "parse_lcd_port: viafb_lcd_port:%s,interface:%d\n",
1101 viafb_lcd_port, viaparinfo->chip_info->lvds_chip_info.
1102 output_interface);
1103}
1104
1105static void parse_dvi_port(void)
1106{
1107 parse_port(viafb_dvi_port, &viaparinfo->chip_info->tmds_chip_info.
1108 output_interface);
1109
1110 DEBUG_MSG(KERN_INFO "parse_dvi_port: viafb_dvi_port:%s,interface:%d\n",
1111 viafb_dvi_port, viaparinfo->chip_info->tmds_chip_info.
1112 output_interface);
1113}
1114
1115#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1116
1117/*
1118 * The proc filesystem read/write function, a simple proc implement to
1119 * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1,
1120 * DVP1Driving, DFPHigh, DFPLow CR96, SR2A[5], SR1B[1], SR2A[4], SR1E[2],
1121 * CR9B, SR65, CR97, CR99
1122 */
1123static int viafb_dvp0_proc_show(struct seq_file *m, void *v)
1124{
1125 u8 dvp0_data_dri = 0, dvp0_clk_dri = 0, dvp0 = 0;
1126 dvp0_data_dri =
1127 (viafb_read_reg(VIASR, SR2A) & BIT5) >> 4 |
1128 (viafb_read_reg(VIASR, SR1B) & BIT1) >> 1;
1129 dvp0_clk_dri =
1130 (viafb_read_reg(VIASR, SR2A) & BIT4) >> 3 |
1131 (viafb_read_reg(VIASR, SR1E) & BIT2) >> 2;
1132 dvp0 = viafb_read_reg(VIACR, CR96) & 0x0f;
1133 seq_printf(m, "%x %x %x\n", dvp0, dvp0_data_dri, dvp0_clk_dri);
1134 return 0;
1135}
1136
1137static int viafb_dvp0_proc_open(struct inode *inode, struct file *file)
1138{
1139 return single_open(file, viafb_dvp0_proc_show, NULL);
1140}
1141
1142static ssize_t viafb_dvp0_proc_write(struct file *file,
1143 const char __user *buffer, size_t count, loff_t *pos)
1144{
1145 char buf[20], *value, *pbuf;
1146 u8 reg_val = 0;
1147 unsigned long length, i;
1148 if (count < 1)
1149 return -EINVAL;
1150 length = count > 20 ? 20 : count;
1151 if (copy_from_user(&buf[0], buffer, length))
1152 return -EFAULT;
1153 buf[length - 1] = '\0'; /*Ensure end string */
1154 pbuf = &buf[0];
1155 for (i = 0; i < 3; i++) {
1156 value = strsep(&pbuf, " ");
1157 if (value != NULL) {
1158 if (kstrtou8(value, 0, &reg_val) < 0)
1159 return -EINVAL;
1160 DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i,
1161 reg_val);
1162 switch (i) {
1163 case 0:
1164 viafb_write_reg_mask(CR96, VIACR,
1165 reg_val, 0x0f);
1166 break;
1167 case 1:
1168 viafb_write_reg_mask(SR2A, VIASR,
1169 reg_val << 4, BIT5);
1170 viafb_write_reg_mask(SR1B, VIASR,
1171 reg_val << 1, BIT1);
1172 break;
1173 case 2:
1174 viafb_write_reg_mask(SR2A, VIASR,
1175 reg_val << 3, BIT4);
1176 viafb_write_reg_mask(SR1E, VIASR,
1177 reg_val << 2, BIT2);
1178 break;
1179 default:
1180 break;
1181 }
1182 } else {
1183 break;
1184 }
1185 }
1186 return count;
1187}
1188
1189static const struct file_operations viafb_dvp0_proc_fops = {
1190 .owner = THIS_MODULE,
1191 .open = viafb_dvp0_proc_open,
1192 .read = seq_read,
1193 .llseek = seq_lseek,
1194 .release = single_release,
1195 .write = viafb_dvp0_proc_write,
1196};
1197
1198static int viafb_dvp1_proc_show(struct seq_file *m, void *v)
1199{
1200 u8 dvp1 = 0, dvp1_data_dri = 0, dvp1_clk_dri = 0;
1201 dvp1 = viafb_read_reg(VIACR, CR9B) & 0x0f;
1202 dvp1_data_dri = (viafb_read_reg(VIASR, SR65) & 0x0c) >> 2;
1203 dvp1_clk_dri = viafb_read_reg(VIASR, SR65) & 0x03;
1204 seq_printf(m, "%x %x %x\n", dvp1, dvp1_data_dri, dvp1_clk_dri);
1205 return 0;
1206}
1207
1208static int viafb_dvp1_proc_open(struct inode *inode, struct file *file)
1209{
1210 return single_open(file, viafb_dvp1_proc_show, NULL);
1211}
1212
1213static ssize_t viafb_dvp1_proc_write(struct file *file,
1214 const char __user *buffer, size_t count, loff_t *pos)
1215{
1216 char buf[20], *value, *pbuf;
1217 u8 reg_val = 0;
1218 unsigned long length, i;
1219 if (count < 1)
1220 return -EINVAL;
1221 length = count > 20 ? 20 : count;
1222 if (copy_from_user(&buf[0], buffer, length))
1223 return -EFAULT;
1224 buf[length - 1] = '\0'; /*Ensure end string */
1225 pbuf = &buf[0];
1226 for (i = 0; i < 3; i++) {
1227 value = strsep(&pbuf, " ");
1228 if (value != NULL) {
1229 if (kstrtou8(value, 0, &reg_val) < 0)
1230 return -EINVAL;
1231 switch (i) {
1232 case 0:
1233 viafb_write_reg_mask(CR9B, VIACR,
1234 reg_val, 0x0f);
1235 break;
1236 case 1:
1237 viafb_write_reg_mask(SR65, VIASR,
1238 reg_val << 2, 0x0c);
1239 break;
1240 case 2:
1241 viafb_write_reg_mask(SR65, VIASR,
1242 reg_val, 0x03);
1243 break;
1244 default:
1245 break;
1246 }
1247 } else {
1248 break;
1249 }
1250 }
1251 return count;
1252}
1253
1254static const struct file_operations viafb_dvp1_proc_fops = {
1255 .owner = THIS_MODULE,
1256 .open = viafb_dvp1_proc_open,
1257 .read = seq_read,
1258 .llseek = seq_lseek,
1259 .release = single_release,
1260 .write = viafb_dvp1_proc_write,
1261};
1262
1263static int viafb_dfph_proc_show(struct seq_file *m, void *v)
1264{
1265 u8 dfp_high = 0;
1266 dfp_high = viafb_read_reg(VIACR, CR97) & 0x0f;
1267 seq_printf(m, "%x\n", dfp_high);
1268 return 0;
1269}
1270
1271static int viafb_dfph_proc_open(struct inode *inode, struct file *file)
1272{
1273 return single_open(file, viafb_dfph_proc_show, NULL);
1274}
1275
1276static ssize_t viafb_dfph_proc_write(struct file *file,
1277 const char __user *buffer, size_t count, loff_t *pos)
1278{
1279 int err;
1280 u8 reg_val;
1281 err = kstrtou8_from_user(buffer, count, 0, &reg_val);
1282 if (err)
1283 return err;
1284
1285 viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
1286 return count;
1287}
1288
1289static const struct file_operations viafb_dfph_proc_fops = {
1290 .owner = THIS_MODULE,
1291 .open = viafb_dfph_proc_open,
1292 .read = seq_read,
1293 .llseek = seq_lseek,
1294 .release = single_release,
1295 .write = viafb_dfph_proc_write,
1296};
1297
1298static int viafb_dfpl_proc_show(struct seq_file *m, void *v)
1299{
1300 u8 dfp_low = 0;
1301 dfp_low = viafb_read_reg(VIACR, CR99) & 0x0f;
1302 seq_printf(m, "%x\n", dfp_low);
1303 return 0;
1304}
1305
1306static int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
1307{
1308 return single_open(file, viafb_dfpl_proc_show, NULL);
1309}
1310
1311static ssize_t viafb_dfpl_proc_write(struct file *file,
1312 const char __user *buffer, size_t count, loff_t *pos)
1313{
1314 int err;
1315 u8 reg_val;
1316 err = kstrtou8_from_user(buffer, count, 0, &reg_val);
1317 if (err)
1318 return err;
1319
1320 viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
1321 return count;
1322}
1323
1324static const struct file_operations viafb_dfpl_proc_fops = {
1325 .owner = THIS_MODULE,
1326 .open = viafb_dfpl_proc_open,
1327 .read = seq_read,
1328 .llseek = seq_lseek,
1329 .release = single_release,
1330 .write = viafb_dfpl_proc_write,
1331};
1332
1333static int viafb_vt1636_proc_show(struct seq_file *m, void *v)
1334{
1335 u8 vt1636_08 = 0, vt1636_09 = 0;
1336 switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1337 case VT1636_LVDS:
1338 vt1636_08 =
1339 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1340 &viaparinfo->chip_info->lvds_chip_info, 0x08) & 0x0f;
1341 vt1636_09 =
1342 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info,
1343 &viaparinfo->chip_info->lvds_chip_info, 0x09) & 0x1f;
1344 seq_printf(m, "%x %x\n", vt1636_08, vt1636_09);
1345 break;
1346 default:
1347 break;
1348 }
1349 switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1350 case VT1636_LVDS:
1351 vt1636_08 =
1352 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1353 &viaparinfo->chip_info->lvds_chip_info2, 0x08) & 0x0f;
1354 vt1636_09 =
1355 viafb_gpio_i2c_read_lvds(viaparinfo->lvds_setting_info2,
1356 &viaparinfo->chip_info->lvds_chip_info2, 0x09) & 0x1f;
1357 seq_printf(m, " %x %x\n", vt1636_08, vt1636_09);
1358 break;
1359 default:
1360 break;
1361 }
1362 return 0;
1363}
1364
1365static int viafb_vt1636_proc_open(struct inode *inode, struct file *file)
1366{
1367 return single_open(file, viafb_vt1636_proc_show, NULL);
1368}
1369
1370static ssize_t viafb_vt1636_proc_write(struct file *file,
1371 const char __user *buffer, size_t count, loff_t *pos)
1372{
1373 char buf[30], *value, *pbuf;
1374 struct IODATA reg_val;
1375 unsigned long length, i;
1376 if (count < 1)
1377 return -EINVAL;
1378 length = count > 30 ? 30 : count;
1379 if (copy_from_user(&buf[0], buffer, length))
1380 return -EFAULT;
1381 buf[length - 1] = '\0'; /*Ensure end string */
1382 pbuf = &buf[0];
1383 switch (viaparinfo->chip_info->lvds_chip_info.lvds_chip_name) {
1384 case VT1636_LVDS:
1385 for (i = 0; i < 2; i++) {
1386 value = strsep(&pbuf, " ");
1387 if (value != NULL) {
1388 if (kstrtou8(value, 0, &reg_val.Data) < 0)
1389 return -EINVAL;
1390 switch (i) {
1391 case 0:
1392 reg_val.Index = 0x08;
1393 reg_val.Mask = 0x0f;
1394 viafb_gpio_i2c_write_mask_lvds
1395 (viaparinfo->lvds_setting_info,
1396 &viaparinfo->
1397 chip_info->lvds_chip_info,
1398 reg_val);
1399 break;
1400 case 1:
1401 reg_val.Index = 0x09;
1402 reg_val.Mask = 0x1f;
1403 viafb_gpio_i2c_write_mask_lvds
1404 (viaparinfo->lvds_setting_info,
1405 &viaparinfo->
1406 chip_info->lvds_chip_info,
1407 reg_val);
1408 break;
1409 default:
1410 break;
1411 }
1412 } else {
1413 break;
1414 }
1415 }
1416 break;
1417 default:
1418 break;
1419 }
1420 switch (viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) {
1421 case VT1636_LVDS:
1422 for (i = 0; i < 2; i++) {
1423 value = strsep(&pbuf, " ");
1424 if (value != NULL) {
1425 if (kstrtou8(value, 0, &reg_val.Data) < 0)
1426 return -EINVAL;
1427 switch (i) {
1428 case 0:
1429 reg_val.Index = 0x08;
1430 reg_val.Mask = 0x0f;
1431 viafb_gpio_i2c_write_mask_lvds
1432 (viaparinfo->lvds_setting_info2,
1433 &viaparinfo->
1434 chip_info->lvds_chip_info2,
1435 reg_val);
1436 break;
1437 case 1:
1438 reg_val.Index = 0x09;
1439 reg_val.Mask = 0x1f;
1440 viafb_gpio_i2c_write_mask_lvds
1441 (viaparinfo->lvds_setting_info2,
1442 &viaparinfo->
1443 chip_info->lvds_chip_info2,
1444 reg_val);
1445 break;
1446 default:
1447 break;
1448 }
1449 } else {
1450 break;
1451 }
1452 }
1453 break;
1454 default:
1455 break;
1456 }
1457 return count;
1458}
1459
1460static const struct file_operations viafb_vt1636_proc_fops = {
1461 .owner = THIS_MODULE,
1462 .open = viafb_vt1636_proc_open,
1463 .read = seq_read,
1464 .llseek = seq_lseek,
1465 .release = single_release,
1466 .write = viafb_vt1636_proc_write,
1467};
1468
1469#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1470
1471static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
1472{
1473 via_odev_to_seq(m, supported_odev_map[
1474 viaparinfo->shared->chip_info.gfx_chip_name]);
1475 return 0;
1476}
1477
1478static int viafb_sup_odev_proc_open(struct inode *inode, struct file *file)
1479{
1480 return single_open(file, viafb_sup_odev_proc_show, NULL);
1481}
1482
1483static const struct file_operations viafb_sup_odev_proc_fops = {
1484 .owner = THIS_MODULE,
1485 .open = viafb_sup_odev_proc_open,
1486 .read = seq_read,
1487 .llseek = seq_lseek,
1488 .release = single_release,
1489};
1490
1491static ssize_t odev_update(const char __user *buffer, size_t count, u32 *odev)
1492{
1493 char buf[64], *ptr = buf;
1494 u32 devices;
1495 bool add, sub;
1496
1497 if (count < 1 || count > 63)
1498 return -EINVAL;
1499 if (copy_from_user(&buf[0], buffer, count))
1500 return -EFAULT;
1501 buf[count] = '\0';
1502 add = buf[0] == '+';
1503 sub = buf[0] == '-';
1504 if (add || sub)
1505 ptr++;
1506 devices = via_parse_odev(ptr, &ptr);
1507 if (*ptr == '\n')
1508 ptr++;
1509 if (*ptr != 0)
1510 return -EINVAL;
1511 if (add)
1512 *odev |= devices;
1513 else if (sub)
1514 *odev &= ~devices;
1515 else
1516 *odev = devices;
1517 return count;
1518}
1519
1520static int viafb_iga1_odev_proc_show(struct seq_file *m, void *v)
1521{
1522 via_odev_to_seq(m, viaparinfo->shared->iga1_devices);
1523 return 0;
1524}
1525
1526static int viafb_iga1_odev_proc_open(struct inode *inode, struct file *file)
1527{
1528 return single_open(file, viafb_iga1_odev_proc_show, NULL);
1529}
1530
1531static ssize_t viafb_iga1_odev_proc_write(struct file *file,
1532 const char __user *buffer, size_t count, loff_t *pos)
1533{
1534 u32 dev_on, dev_off, dev_old, dev_new;
1535 ssize_t res;
1536
1537 dev_old = dev_new = viaparinfo->shared->iga1_devices;
1538 res = odev_update(buffer, count, &dev_new);
1539 if (res != count)
1540 return res;
1541 dev_off = dev_old & ~dev_new;
1542 dev_on = dev_new & ~dev_old;
1543 viaparinfo->shared->iga1_devices = dev_new;
1544 viaparinfo->shared->iga2_devices &= ~dev_new;
1545 via_set_state(dev_off, VIA_STATE_OFF);
1546 via_set_source(dev_new, IGA1);
1547 via_set_state(dev_on, VIA_STATE_ON);
1548 return res;
1549}
1550
1551static const struct file_operations viafb_iga1_odev_proc_fops = {
1552 .owner = THIS_MODULE,
1553 .open = viafb_iga1_odev_proc_open,
1554 .read = seq_read,
1555 .llseek = seq_lseek,
1556 .release = single_release,
1557 .write = viafb_iga1_odev_proc_write,
1558};
1559
1560static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
1561{
1562 via_odev_to_seq(m, viaparinfo->shared->iga2_devices);
1563 return 0;
1564}
1565
1566static int viafb_iga2_odev_proc_open(struct inode *inode, struct file *file)
1567{
1568 return single_open(file, viafb_iga2_odev_proc_show, NULL);
1569}
1570
1571static ssize_t viafb_iga2_odev_proc_write(struct file *file,
1572 const char __user *buffer, size_t count, loff_t *pos)
1573{
1574 u32 dev_on, dev_off, dev_old, dev_new;
1575 ssize_t res;
1576
1577 dev_old = dev_new = viaparinfo->shared->iga2_devices;
1578 res = odev_update(buffer, count, &dev_new);
1579 if (res != count)
1580 return res;
1581 dev_off = dev_old & ~dev_new;
1582 dev_on = dev_new & ~dev_old;
1583 viaparinfo->shared->iga2_devices = dev_new;
1584 viaparinfo->shared->iga1_devices &= ~dev_new;
1585 via_set_state(dev_off, VIA_STATE_OFF);
1586 via_set_source(dev_new, IGA2);
1587 via_set_state(dev_on, VIA_STATE_ON);
1588 return res;
1589}
1590
1591static const struct file_operations viafb_iga2_odev_proc_fops = {
1592 .owner = THIS_MODULE,
1593 .open = viafb_iga2_odev_proc_open,
1594 .read = seq_read,
1595 .llseek = seq_lseek,
1596 .release = single_release,
1597 .write = viafb_iga2_odev_proc_write,
1598};
1599
1600#define IS_VT1636(lvds_chip) ((lvds_chip).lvds_chip_name == VT1636_LVDS)
1601static void viafb_init_proc(struct viafb_shared *shared)
1602{
1603 struct proc_dir_entry *iga1_entry, *iga2_entry,
1604 *viafb_entry = proc_mkdir("viafb", NULL);
1605
1606 shared->proc_entry = viafb_entry;
1607 if (viafb_entry) {
1608#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1609 proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
1610 proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
1611 proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
1612 proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
1613 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1614 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1615 proc_create("vt1636", 0, viafb_entry,
1616 &viafb_vt1636_proc_fops);
1617#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1618
1619 proc_create("supported_output_devices", 0, viafb_entry,
1620 &viafb_sup_odev_proc_fops);
1621 iga1_entry = proc_mkdir("iga1", viafb_entry);
1622 shared->iga1_proc_entry = iga1_entry;
1623 proc_create("output_devices", 0, iga1_entry,
1624 &viafb_iga1_odev_proc_fops);
1625 iga2_entry = proc_mkdir("iga2", viafb_entry);
1626 shared->iga2_proc_entry = iga2_entry;
1627 proc_create("output_devices", 0, iga2_entry,
1628 &viafb_iga2_odev_proc_fops);
1629 }
1630}
1631static void viafb_remove_proc(struct viafb_shared *shared)
1632{
1633 struct proc_dir_entry *viafb_entry = shared->proc_entry,
1634 *iga1_entry = shared->iga1_proc_entry,
1635 *iga2_entry = shared->iga2_proc_entry;
1636
1637 if (!viafb_entry)
1638 return;
1639
1640 remove_proc_entry("output_devices", iga2_entry);
1641 remove_proc_entry("iga2", viafb_entry);
1642 remove_proc_entry("output_devices", iga1_entry);
1643 remove_proc_entry("iga1", viafb_entry);
1644 remove_proc_entry("supported_output_devices", viafb_entry);
1645
1646#ifdef CONFIG_FB_VIA_DIRECT_PROCFS
1647 remove_proc_entry("dvp0", viafb_entry);/* parent dir */
1648 remove_proc_entry("dvp1", viafb_entry);
1649 remove_proc_entry("dfph", viafb_entry);
1650 remove_proc_entry("dfpl", viafb_entry);
1651 if (IS_VT1636(shared->chip_info.lvds_chip_info)
1652 || IS_VT1636(shared->chip_info.lvds_chip_info2))
1653 remove_proc_entry("vt1636", viafb_entry);
1654#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
1655
1656 remove_proc_entry("viafb", NULL);
1657}
1658#undef IS_VT1636
1659
1660static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres)
1661{
1662 const struct fb_videomode *mode = NULL;
1663 char *ptr;
1664
1665 if (!str) {
1666 if (devices == VIA_CRT)
1667 mode = via_aux_get_preferred_mode(
1668 viaparinfo->shared->i2c_26);
1669 else if (devices == VIA_DVP1)
1670 mode = via_aux_get_preferred_mode(
1671 viaparinfo->shared->i2c_31);
1672
1673 if (mode) {
1674 *xres = mode->xres;
1675 *yres = mode->yres;
1676 } else if (machine_is_olpc()) {
1677 *xres = 1200;
1678 *yres = 900;
1679 } else {
1680 *xres = 640;
1681 *yres = 480;
1682 }
1683 return 0;
1684 }
1685
1686 *xres = simple_strtoul(str, &ptr, 10);
1687 if (ptr[0] != 'x')
1688 return -EINVAL;
1689
1690 *yres = simple_strtoul(&ptr[1], &ptr, 10);
1691 if (ptr[0])
1692 return -EINVAL;
1693
1694 return 0;
1695}
1696
1697
1698#ifdef CONFIG_PM
1699static int viafb_suspend(void *unused)
1700{
1701 console_lock();
1702 fb_set_suspend(viafbinfo, 1);
1703 viafb_sync(viafbinfo);
1704 console_unlock();
1705
1706 return 0;
1707}
1708
1709static int viafb_resume(void *unused)
1710{
1711 console_lock();
1712 if (viaparinfo->shared->vdev->engine_mmio)
1713 viafb_reset_engine(viaparinfo);
1714 viafb_set_par(viafbinfo);
1715 if (viafb_dual_fb)
1716 viafb_set_par(viafbinfo1);
1717 fb_set_suspend(viafbinfo, 0);
1718
1719 console_unlock();
1720 return 0;
1721}
1722
1723static struct viafb_pm_hooks viafb_fb_pm_hooks = {
1724 .suspend = viafb_suspend,
1725 .resume = viafb_resume
1726};
1727
1728#endif
1729
1730static void i2c_bus_probe(struct viafb_shared *shared)
1731{
1732 /* should be always CRT */
1733 printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
1734 shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26));
1735
1736 /* seems to be usually DVP1 */
1737 printk(KERN_INFO "viafb: Probing I2C bus 0x31\n");
1738 shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31));
1739
1740 /* FIXME: what is this? */
1741 if (!machine_is_olpc()) {
1742 printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n");
1743 shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C));
1744 }
1745
1746 printk(KERN_INFO "viafb: Finished I2C bus probing");
1747}
1748
1749static void i2c_bus_free(struct viafb_shared *shared)
1750{
1751 via_aux_free(shared->i2c_26);
1752 via_aux_free(shared->i2c_31);
1753 via_aux_free(shared->i2c_2C);
1754}
1755
1756int via_fb_pci_probe(struct viafb_dev *vdev)
1757{
1758 u32 default_xres, default_yres;
1759 struct fb_var_screeninfo default_var;
1760 int rc;
1761 u32 viafb_par_length;
1762
1763 DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n");
1764 memset(&default_var, 0, sizeof(default_var));
1765 viafb_par_length = ALIGN(sizeof(struct viafb_par), BITS_PER_LONG/8);
1766
1767 /* Allocate fb_info and ***_par here, also including some other needed
1768 * variables
1769 */
1770 viafbinfo = framebuffer_alloc(viafb_par_length +
1771 ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8),
1772 &vdev->pdev->dev);
1773 if (!viafbinfo) {
1774 printk(KERN_ERR"Could not allocate memory for viafb_info.\n");
1775 return -ENOMEM;
1776 }
1777
1778 viaparinfo = (struct viafb_par *)viafbinfo->par;
1779 viaparinfo->shared = viafbinfo->par + viafb_par_length;
1780 viaparinfo->shared->vdev = vdev;
1781 viaparinfo->vram_addr = 0;
1782 viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info;
1783 viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info;
1784 viaparinfo->lvds_setting_info2 =
1785 &viaparinfo->shared->lvds_setting_info2;
1786 viaparinfo->chip_info = &viaparinfo->shared->chip_info;
1787
1788 i2c_bus_probe(viaparinfo->shared);
1789 if (viafb_dual_fb)
1790 viafb_SAMM_ON = 1;
1791 parse_lcd_port();
1792 parse_dvi_port();
1793
1794 viafb_init_chip_info(vdev->chip_type);
1795 /*
1796 * The framebuffer will have been successfully mapped by
1797 * the core (or we'd not be here), but we still need to
1798 * set up our own accounting.
1799 */
1800 viaparinfo->fbmem = vdev->fbmem_start;
1801 viaparinfo->memsize = vdev->fbmem_len;
1802 viaparinfo->fbmem_free = viaparinfo->memsize;
1803 viaparinfo->fbmem_used = 0;
1804 viafbinfo->screen_base = vdev->fbmem;
1805
1806 viafbinfo->fix.mmio_start = vdev->engine_start;
1807 viafbinfo->fix.mmio_len = vdev->engine_len;
1808 viafbinfo->node = 0;
1809 viafbinfo->fbops = &viafb_ops;
1810 viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1811
1812 viafbinfo->pseudo_palette = pseudo_pal;
1813 if (viafb_accel && !viafb_setup_engine(viafbinfo)) {
1814 viafbinfo->flags |= FBINFO_HWACCEL_COPYAREA |
1815 FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
1816 default_var.accel_flags = FB_ACCELF_TEXT;
1817 } else {
1818 viafbinfo->flags |= FBINFO_HWACCEL_DISABLED;
1819 default_var.accel_flags = 0;
1820 }
1821
1822 if (viafb_second_size && (viafb_second_size < 8)) {
1823 viafb_second_offset = viaparinfo->fbmem_free -
1824 viafb_second_size * 1024 * 1024;
1825 } else {
1826 viafb_second_size = 8;
1827 viafb_second_offset = viaparinfo->fbmem_free -
1828 viafb_second_size * 1024 * 1024;
1829 }
1830
1831 parse_mode(viafb_mode, viaparinfo->shared->iga1_devices,
1832 &default_xres, &default_yres);
1833 if (viafb_SAMM_ON == 1)
1834 parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices,
1835 &viafb_second_xres, &viafb_second_yres);
1836
1837 default_var.xres = default_xres;
1838 default_var.yres = default_yres;
1839 default_var.xres_virtual = default_xres;
1840 default_var.yres_virtual = default_yres;
1841 default_var.bits_per_pixel = viafb_bpp;
1842 viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
1843 default_var.xres, default_var.yres, viafb_refresh));
1844 viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo);
1845 viafbinfo->var = default_var;
1846
1847 if (viafb_dual_fb) {
1848 viafbinfo1 = framebuffer_alloc(viafb_par_length,
1849 &vdev->pdev->dev);
1850 if (!viafbinfo1) {
1851 printk(KERN_ERR
1852 "allocate the second framebuffer struct error\n");
1853 rc = -ENOMEM;
1854 goto out_fb_release;
1855 }
1856 viaparinfo1 = viafbinfo1->par;
1857 memcpy(viaparinfo1, viaparinfo, viafb_par_length);
1858 viaparinfo1->vram_addr = viafb_second_offset;
1859 viaparinfo1->memsize = viaparinfo->memsize -
1860 viafb_second_offset;
1861 viaparinfo->memsize = viafb_second_offset;
1862 viaparinfo1->fbmem = viaparinfo->fbmem + viafb_second_offset;
1863
1864 viaparinfo1->fbmem_used = viaparinfo->fbmem_used;
1865 viaparinfo1->fbmem_free = viaparinfo1->memsize -
1866 viaparinfo1->fbmem_used;
1867 viaparinfo->fbmem_free = viaparinfo->memsize;
1868 viaparinfo->fbmem_used = 0;
1869
1870 viaparinfo->iga_path = IGA1;
1871 viaparinfo1->iga_path = IGA2;
1872 memcpy(viafbinfo1, viafbinfo, sizeof(struct fb_info));
1873 viafbinfo1->par = viaparinfo1;
1874 viafbinfo1->screen_base = viafbinfo->screen_base +
1875 viafb_second_offset;
1876
1877 default_var.xres = viafb_second_xres;
1878 default_var.yres = viafb_second_yres;
1879 default_var.xres_virtual = viafb_second_xres;
1880 default_var.yres_virtual = viafb_second_yres;
1881 default_var.bits_per_pixel = viafb_bpp1;
1882 viafb_fill_var_timing_info(&default_var, viafb_get_best_mode(
1883 default_var.xres, default_var.yres, viafb_refresh1));
1884
1885 viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1);
1886 viafb_check_var(&default_var, viafbinfo1);
1887 viafbinfo1->var = default_var;
1888 viafb_update_fix(viafbinfo1);
1889 viaparinfo1->depth = fb_get_color_depth(&viafbinfo1->var,
1890 &viafbinfo1->fix);
1891 }
1892
1893 viafb_check_var(&viafbinfo->var, viafbinfo);
1894 viafb_update_fix(viafbinfo);
1895 viaparinfo->depth = fb_get_color_depth(&viafbinfo->var,
1896 &viafbinfo->fix);
1897 default_var.activate = FB_ACTIVATE_NOW;
1898 rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0);
1899 if (rc)
1900 goto out_fb1_release;
1901
1902 if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
1903 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) {
1904 rc = register_framebuffer(viafbinfo1);
1905 if (rc)
1906 goto out_dealloc_cmap;
1907 }
1908 rc = register_framebuffer(viafbinfo);
1909 if (rc)
1910 goto out_fb1_unreg_lcd_cle266;
1911
1912 if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device)
1913 || (viaparinfo->chip_info->gfx_chip_name !=
1914 UNICHROME_CLE266))) {
1915 rc = register_framebuffer(viafbinfo1);
1916 if (rc)
1917 goto out_fb_unreg;
1918 }
1919 DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n",
1920 viafbinfo->node, viafbinfo->fix.id, default_var.xres,
1921 default_var.yres, default_var.bits_per_pixel);
1922
1923 viafb_init_proc(viaparinfo->shared);
1924 viafb_init_dac(IGA2);
1925
1926#ifdef CONFIG_PM
1927 viafb_pm_register(&viafb_fb_pm_hooks);
1928#endif
1929 return 0;
1930
1931out_fb_unreg:
1932 unregister_framebuffer(viafbinfo);
1933out_fb1_unreg_lcd_cle266:
1934 if (viafb_dual_fb && (viafb_primary_dev == LCD_Device)
1935 && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266))
1936 unregister_framebuffer(viafbinfo1);
1937out_dealloc_cmap:
1938 fb_dealloc_cmap(&viafbinfo->cmap);
1939out_fb1_release:
1940 if (viafbinfo1)
1941 framebuffer_release(viafbinfo1);
1942out_fb_release:
1943 i2c_bus_free(viaparinfo->shared);
1944 framebuffer_release(viafbinfo);
1945 return rc;
1946}
1947
1948void via_fb_pci_remove(struct pci_dev *pdev)
1949{
1950 DEBUG_MSG(KERN_INFO "via_pci_remove!\n");
1951 fb_dealloc_cmap(&viafbinfo->cmap);
1952 unregister_framebuffer(viafbinfo);
1953 if (viafb_dual_fb)
1954 unregister_framebuffer(viafbinfo1);
1955 viafb_remove_proc(viaparinfo->shared);
1956 i2c_bus_free(viaparinfo->shared);
1957 framebuffer_release(viafbinfo);
1958 if (viafb_dual_fb)
1959 framebuffer_release(viafbinfo1);
1960}
1961
1962#ifndef MODULE
1963static int __init viafb_setup(void)
1964{
1965 char *this_opt;
1966 char *options;
1967
1968 DEBUG_MSG(KERN_INFO "viafb_setup!\n");
1969
1970 if (fb_get_options("viafb", &options))
1971 return -ENODEV;
1972
1973 if (!options || !*options)
1974 return 0;
1975
1976 while ((this_opt = strsep(&options, ",")) != NULL) {
1977 if (!*this_opt)
1978 continue;
1979
1980 if (!strncmp(this_opt, "viafb_mode1=", 12)) {
1981 viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL);
1982 } else if (!strncmp(this_opt, "viafb_mode=", 11)) {
1983 viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL);
1984 } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) {
1985 if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0)
1986 return -EINVAL;
1987 } else if (!strncmp(this_opt, "viafb_bpp=", 10)) {
1988 if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0)
1989 return -EINVAL;
1990 } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) {
1991 if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0)
1992 return -EINVAL;
1993 } else if (!strncmp(this_opt, "viafb_refresh=", 14)) {
1994 if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0)
1995 return -EINVAL;
1996 } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) {
1997 if (kstrtoint(this_opt + 21, 0,
1998 &viafb_lcd_dsp_method) < 0)
1999 return -EINVAL;
2000 } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) {
2001 if (kstrtoint(this_opt + 19, 0,
2002 &viafb_lcd_panel_id) < 0)
2003 return -EINVAL;
2004 } else if (!strncmp(this_opt, "viafb_accel=", 12)) {
2005 if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0)
2006 return -EINVAL;
2007 } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) {
2008 if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0)
2009 return -EINVAL;
2010 } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) {
2011 viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL);
2012 } else if (!strncmp(this_opt,
2013 "viafb_display_hardware_layout=", 30)) {
2014 if (kstrtoint(this_opt + 30, 0,
2015 &viafb_display_hardware_layout) < 0)
2016 return -EINVAL;
2017 } else if (!strncmp(this_opt, "viafb_second_size=", 18)) {
2018 if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0)
2019 return -EINVAL;
2020 } else if (!strncmp(this_opt,
2021 "viafb_platform_epia_dvi=", 24)) {
2022 if (kstrtoint(this_opt + 24, 0,
2023 &viafb_platform_epia_dvi) < 0)
2024 return -EINVAL;
2025 } else if (!strncmp(this_opt,
2026 "viafb_device_lcd_dualedge=", 26)) {
2027 if (kstrtoint(this_opt + 26, 0,
2028 &viafb_device_lcd_dualedge) < 0)
2029 return -EINVAL;
2030 } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) {
2031 if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0)
2032 return -EINVAL;
2033 } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) {
2034 if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0)
2035 return -EINVAL;
2036 } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) {
2037 viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL);
2038 } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) {
2039 viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL);
2040 }
2041 }
2042 return 0;
2043}
2044#endif
2045
2046/*
2047 * These are called out of via-core for now.
2048 */
2049int __init viafb_init(void)
2050{
2051 u32 dummy_x, dummy_y;
2052 int r = 0;
2053
2054 if (machine_is_olpc())
2055 /* Apply XO-1.5-specific configuration. */
2056 viafb_lcd_panel_id = 23;
2057
2058#ifndef MODULE
2059 r = viafb_setup();
2060 if (r < 0)
2061 return r;
2062#endif
2063 if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y)
2064 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
2065 || parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y)
2066 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
2067 || viafb_bpp < 0 || viafb_bpp > 32
2068 || viafb_bpp1 < 0 || viafb_bpp1 > 32
2069 || parse_active_dev())
2070 return -EINVAL;
2071
2072 printk(KERN_INFO
2073 "VIA Graphics Integration Chipset framebuffer %d.%d initializing\n",
2074 VERSION_MAJOR, VERSION_MINOR);
2075 return r;
2076}
2077
2078void __exit viafb_exit(void)
2079{
2080 DEBUG_MSG(KERN_INFO "viafb_exit!\n");
2081}
2082
2083static struct fb_ops viafb_ops = {
2084 .owner = THIS_MODULE,
2085 .fb_open = viafb_open,
2086 .fb_release = viafb_release,
2087 .fb_check_var = viafb_check_var,
2088 .fb_set_par = viafb_set_par,
2089 .fb_setcolreg = viafb_setcolreg,
2090 .fb_pan_display = viafb_pan_display,
2091 .fb_blank = viafb_blank,
2092 .fb_fillrect = viafb_fillrect,
2093 .fb_copyarea = viafb_copyarea,
2094 .fb_imageblit = viafb_imageblit,
2095 .fb_cursor = viafb_cursor,
2096 .fb_ioctl = viafb_ioctl,
2097 .fb_sync = viafb_sync,
2098};
2099
2100
2101#ifdef MODULE
2102module_param(viafb_mode, charp, S_IRUSR);
2103MODULE_PARM_DESC(viafb_mode, "Set resolution (default=640x480)");
2104
2105module_param(viafb_mode1, charp, S_IRUSR);
2106MODULE_PARM_DESC(viafb_mode1, "Set resolution (default=640x480)");
2107
2108module_param(viafb_bpp, int, S_IRUSR);
2109MODULE_PARM_DESC(viafb_bpp, "Set color depth (default=32bpp)");
2110
2111module_param(viafb_bpp1, int, S_IRUSR);
2112MODULE_PARM_DESC(viafb_bpp1, "Set color depth (default=32bpp)");
2113
2114module_param(viafb_refresh, int, S_IRUSR);
2115MODULE_PARM_DESC(viafb_refresh,
2116 "Set CRT viafb_refresh rate (default = 60)");
2117
2118module_param(viafb_refresh1, int, S_IRUSR);
2119MODULE_PARM_DESC(viafb_refresh1,
2120 "Set CRT refresh rate (default = 60)");
2121
2122module_param(viafb_lcd_panel_id, int, S_IRUSR);
2123MODULE_PARM_DESC(viafb_lcd_panel_id,
2124 "Set Flat Panel type(Default=1024x768)");
2125
2126module_param(viafb_lcd_dsp_method, int, S_IRUSR);
2127MODULE_PARM_DESC(viafb_lcd_dsp_method,
2128 "Set Flat Panel display scaling method.(Default=Expandsion)");
2129
2130module_param(viafb_SAMM_ON, int, S_IRUSR);
2131MODULE_PARM_DESC(viafb_SAMM_ON,
2132 "Turn on/off flag of SAMM(Default=OFF)");
2133
2134module_param(viafb_accel, int, S_IRUSR);
2135MODULE_PARM_DESC(viafb_accel,
2136 "Set 2D Hardware Acceleration: 0 = OFF, 1 = ON (default)");
2137
2138module_param(viafb_active_dev, charp, S_IRUSR);
2139MODULE_PARM_DESC(viafb_active_dev, "Specify active devices.");
2140
2141module_param(viafb_display_hardware_layout, int, S_IRUSR);
2142MODULE_PARM_DESC(viafb_display_hardware_layout,
2143 "Display Hardware Layout (LCD Only, DVI Only...,etc)");
2144
2145module_param(viafb_second_size, int, S_IRUSR);
2146MODULE_PARM_DESC(viafb_second_size,
2147 "Set secondary device memory size");
2148
2149module_param(viafb_dual_fb, int, S_IRUSR);
2150MODULE_PARM_DESC(viafb_dual_fb,
2151 "Turn on/off flag of dual framebuffer devices.(Default = OFF)");
2152
2153module_param(viafb_platform_epia_dvi, int, S_IRUSR);
2154MODULE_PARM_DESC(viafb_platform_epia_dvi,
2155 "Turn on/off flag of DVI devices on EPIA board.(Default = OFF)");
2156
2157module_param(viafb_device_lcd_dualedge, int, S_IRUSR);
2158MODULE_PARM_DESC(viafb_device_lcd_dualedge,
2159 "Turn on/off flag of dual edge panel.(Default = OFF)");
2160
2161module_param(viafb_bus_width, int, S_IRUSR);
2162MODULE_PARM_DESC(viafb_bus_width,
2163 "Set bus width of panel.(Default = 12)");
2164
2165module_param(viafb_lcd_mode, int, S_IRUSR);
2166MODULE_PARM_DESC(viafb_lcd_mode,
2167 "Set Flat Panel mode(Default=OPENLDI)");
2168
2169module_param(viafb_lcd_port, charp, S_IRUSR);
2170MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port.");
2171
2172module_param(viafb_dvi_port, charp, S_IRUSR);
2173MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port.");
2174
2175MODULE_LICENSE("GPL");
2176#endif
diff --git a/drivers/video/fbdev/via/viafbdev.h b/drivers/video/fbdev/via/viafbdev.h
new file mode 100644
index 000000000000..f6b2ddf56e94
--- /dev/null
+++ b/drivers/video/fbdev/via/viafbdev.h
@@ -0,0 +1,110 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __VIAFBDEV_H__
23#define __VIAFBDEV_H__
24
25#include <linux/proc_fs.h>
26#include <linux/fb.h>
27#include <linux/spinlock.h>
28
29#include "via_aux.h"
30#include "ioctl.h"
31#include "share.h"
32#include "chip.h"
33#include "hw.h"
34
35#define VERSION_MAJOR 2
36#define VERSION_KERNEL 6 /* For kernel 2.6 */
37
38#define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */
39#define VERSION_MINOR 4
40
41#define VIAFB_NUM_I2C 5
42
43struct viafb_shared {
44 u32 iga1_devices;
45 u32 iga2_devices;
46
47 struct proc_dir_entry *proc_entry; /*viafb proc entry */
48 struct proc_dir_entry *iga1_proc_entry;
49 struct proc_dir_entry *iga2_proc_entry;
50 struct viafb_dev *vdev; /* Global dev info */
51
52 /* I2C busses that may have auxiliary devices */
53 struct via_aux_bus *i2c_26;
54 struct via_aux_bus *i2c_31;
55 struct via_aux_bus *i2c_2C;
56
57 /* All the information will be needed to set engine */
58 struct tmds_setting_information tmds_setting_info;
59 struct lvds_setting_information lvds_setting_info;
60 struct lvds_setting_information lvds_setting_info2;
61 struct chip_information chip_info;
62
63 /* hardware acceleration stuff */
64 u32 cursor_vram_addr;
65 u32 vq_vram_addr; /* virtual queue address in video ram */
66 int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height,
67 u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y,
68 u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y,
69 u32 fg_color, u32 bg_color, u8 fill_rop);
70};
71
72struct viafb_par {
73 u8 depth;
74 u32 vram_addr;
75
76 unsigned int fbmem; /*framebuffer physical memory address */
77 unsigned int memsize; /*size of fbmem */
78 u32 fbmem_free; /* Free FB memory */
79 u32 fbmem_used; /* Use FB memory size */
80 u32 iga_path;
81
82 struct viafb_shared *shared;
83
84 /* All the information will be needed to set engine */
85 /* depreciated, use the ones in shared directly */
86 struct tmds_setting_information *tmds_setting_info;
87 struct lvds_setting_information *lvds_setting_info;
88 struct lvds_setting_information *lvds_setting_info2;
89 struct chip_information *chip_info;
90};
91
92extern int viafb_SAMM_ON;
93extern int viafb_dual_fb;
94extern int viafb_LCD2_ON;
95extern int viafb_LCD_ON;
96extern int viafb_DVI_ON;
97extern int viafb_hotplug;
98
99u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
100 *plvds_setting_info, struct lvds_chip_information
101 *plvds_chip_info, u8 index);
102void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
103 *plvds_setting_info, struct lvds_chip_information
104 *plvds_chip_info, struct IODATA io_data);
105int via_fb_pci_probe(struct viafb_dev *vdev);
106void via_fb_pci_remove(struct pci_dev *pdev);
107/* Temporary */
108int viafb_init(void);
109void viafb_exit(void);
110#endif /* __VIAFBDEV_H__ */
diff --git a/drivers/video/fbdev/via/viamode.c b/drivers/video/fbdev/via/viamode.c
new file mode 100644
index 000000000000..0666ab01cf4a
--- /dev/null
+++ b/drivers/video/fbdev/via/viamode.c
@@ -0,0 +1,383 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/via-core.h>
23#include "global.h"
24
25struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
26{VIASR, SR15, 0x02, 0x02},
27{VIASR, SR16, 0xBF, 0x08},
28{VIASR, SR17, 0xFF, 0x1F},
29{VIASR, SR18, 0xFF, 0x4E},
30{VIASR, SR1A, 0xFB, 0x08},
31{VIASR, SR1E, 0x0F, 0x01},
32{VIASR, SR2A, 0xFF, 0x00},
33{VIACR, CR32, 0xFF, 0x00},
34{VIACR, CR33, 0xFF, 0x00},
35{VIACR, CR35, 0xFF, 0x00},
36{VIACR, CR36, 0x08, 0x00},
37{VIACR, CR69, 0xFF, 0x00},
38{VIACR, CR6A, 0xFF, 0x40},
39{VIACR, CR6B, 0xFF, 0x00},
40{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
41{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
42{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
43{VIACR, CR8B, 0xFF, 0x69}, /* LCD Power Sequence Control 0 */
44{VIACR, CR8C, 0xFF, 0x57}, /* LCD Power Sequence Control 1 */
45{VIACR, CR8D, 0xFF, 0x00}, /* LCD Power Sequence Control 2 */
46{VIACR, CR8E, 0xFF, 0x7B}, /* LCD Power Sequence Control 3 */
47{VIACR, CR8F, 0xFF, 0x03}, /* LCD Power Sequence Control 4 */
48{VIACR, CR90, 0xFF, 0x30}, /* LCD Power Sequence Control 5 */
49{VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
50{VIACR, CR96, 0xFF, 0x00},
51{VIACR, CR97, 0xFF, 0x00},
52{VIACR, CR99, 0xFF, 0x00},
53{VIACR, CR9B, 0xFF, 0x00}
54};
55
56/* Video Mode Table for VT3314 chipset*/
57/* Common Setting for Video Mode */
58struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
59{VIASR, SR15, 0x02, 0x02},
60{VIASR, SR16, 0xBF, 0x08},
61{VIASR, SR17, 0xFF, 0x1F},
62{VIASR, SR18, 0xFF, 0x4E},
63{VIASR, SR1A, 0xFB, 0x82},
64{VIASR, SR1B, 0xFF, 0xF0},
65{VIASR, SR1F, 0xFF, 0x00},
66{VIASR, SR1E, 0xFF, 0x01},
67{VIASR, SR22, 0xFF, 0x1F},
68{VIASR, SR2A, 0x0F, 0x00},
69{VIASR, SR2E, 0xFF, 0xFF},
70{VIASR, SR3F, 0xFF, 0xFF},
71{VIASR, SR40, 0xF7, 0x00},
72{VIASR, CR30, 0xFF, 0x04},
73{VIACR, CR32, 0xFF, 0x00},
74{VIACR, CR33, 0x7F, 0x00},
75{VIACR, CR35, 0xFF, 0x00},
76{VIACR, CR36, 0xFF, 0x31},
77{VIACR, CR41, 0xFF, 0x80},
78{VIACR, CR42, 0xFF, 0x00},
79{VIACR, CR55, 0x80, 0x00},
80{VIACR, CR5D, 0x80, 0x00}, /*Horizontal Retrace Start bit[11] should be 0*/
81{VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
82{VIACR, CR69, 0xFF, 0x00},
83{VIACR, CR6A, 0xFD, 0x40},
84{VIACR, CR6B, 0xFF, 0x00},
85{VIACR, CR77, 0xFF, 0x00}, /* LCD scaling Factor */
86{VIACR, CR78, 0xFF, 0x00}, /* LCD scaling Factor */
87{VIACR, CR79, 0xFF, 0x00}, /* LCD scaling Factor */
88{VIACR, CR9F, 0x03, 0x00}, /* LCD scaling Factor */
89{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
90{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
91{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
92{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
93{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
94{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
95{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
96{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
97{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
98{VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
99{VIACR, CR96, 0xFF, 0x00},
100{VIACR, CR97, 0xFF, 0x00},
101{VIACR, CR99, 0xFF, 0x00},
102{VIACR, CR9B, 0xFF, 0x00},
103{VIACR, CR9D, 0xFF, 0x80},
104{VIACR, CR9E, 0xFF, 0x80}
105};
106
107struct io_reg KM400_ModeXregs[] = {
108 {VIASR, SR10, 0xFF, 0x01}, /* Unlock Register */
109 {VIASR, SR16, 0xFF, 0x08}, /* Display FIFO threshold Control */
110 {VIASR, SR17, 0xFF, 0x1F}, /* Display FIFO Control */
111 {VIASR, SR18, 0xFF, 0x4E}, /* GFX PREQ threshold */
112 {VIASR, SR1A, 0xFF, 0x0a}, /* GFX PREQ threshold */
113 {VIASR, SR1F, 0xFF, 0x00}, /* Memory Control 0 */
114 {VIASR, SR1B, 0xFF, 0xF0}, /* Power Management Control 0 */
115 {VIASR, SR1E, 0xFF, 0x01}, /* Power Management Control */
116 {VIASR, SR20, 0xFF, 0x00}, /* Sequencer Arbiter Control 0 */
117 {VIASR, SR21, 0xFF, 0x00}, /* Sequencer Arbiter Control 1 */
118 {VIASR, SR22, 0xFF, 0x1F}, /* Display Arbiter Control 1 */
119 {VIASR, SR2A, 0xFF, 0x00}, /* Power Management Control 5 */
120 {VIASR, SR2D, 0xFF, 0xFF}, /* Power Management Control 1 */
121 {VIASR, SR2E, 0xFF, 0xFF}, /* Power Management Control 2 */
122 {VIACR, CR33, 0xFF, 0x00},
123 {VIACR, CR55, 0x80, 0x00},
124 {VIACR, CR5D, 0x80, 0x00},
125 {VIACR, CR36, 0xFF, 0x01}, /* Power Mangement 3 */
126 {VIACR, CR68, 0xFF, 0x67}, /* Default FIFO For IGA2 */
127 {VIACR, CR6A, 0x20, 0x20}, /* Extended FIFO On */
128 {VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
129 {VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
130 {VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
131 {VIACR, CR8B, 0xFF, 0x2D}, /* LCD Power Sequence Control 0 */
132 {VIACR, CR8C, 0xFF, 0x2D}, /* LCD Power Sequence Control 1 */
133 {VIACR, CR8D, 0xFF, 0xC8}, /* LCD Power Sequence Control 2 */
134 {VIACR, CR8E, 0xFF, 0x36}, /* LCD Power Sequence Control 3 */
135 {VIACR, CR8F, 0xFF, 0x00}, /* LCD Power Sequence Control 4 */
136 {VIACR, CR90, 0xFF, 0x10}, /* LCD Power Sequence Control 5 */
137 {VIACR, CR91, 0xFF, 0xA0}, /* 24/12 bit LVDS Data off */
138 {VIACR, CR96, 0xFF, 0x03}, /* DVP0 ; DVP0 Clock Skew */
139 {VIACR, CR97, 0xFF, 0x03}, /* DFP high ; DFPH Clock Skew */
140 {VIACR, CR99, 0xFF, 0x03}, /* DFP low ; DFPL Clock Skew*/
141 {VIACR, CR9B, 0xFF, 0x07} /* DVI on DVP1 ; DVP1 Clock Skew*/
142};
143
144/* For VT3324: Common Setting for Video Mode */
145struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
146{VIASR, SR15, 0x02, 0x02},
147{VIASR, SR16, 0xBF, 0x08},
148{VIASR, SR17, 0xFF, 0x1F},
149{VIASR, SR18, 0xFF, 0x4E},
150{VIASR, SR1A, 0xFB, 0x08},
151{VIASR, SR1B, 0xFF, 0xF0},
152{VIASR, SR1E, 0xFF, 0x01},
153{VIASR, SR2A, 0xFF, 0x00},
154{VIASR, SR2D, 0xC0, 0xC0}, /* delayed E3_ECK */
155{VIACR, CR32, 0xFF, 0x00},
156{VIACR, CR33, 0xFF, 0x00},
157{VIACR, CR35, 0xFF, 0x00},
158{VIACR, CR36, 0x08, 0x00},
159{VIACR, CR47, 0xC8, 0x00}, /* Clear VCK Plus. */
160{VIACR, CR69, 0xFF, 0x00},
161{VIACR, CR6A, 0xFF, 0x40},
162{VIACR, CR6B, 0xFF, 0x00},
163{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
164{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
165{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
166{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
167{VIACR, CR8B, 0xFF, 0x5D}, /* LCD Power Sequence Control 0 */
168{VIACR, CR8C, 0xFF, 0x2B}, /* LCD Power Sequence Control 1 */
169{VIACR, CR8D, 0xFF, 0x6F}, /* LCD Power Sequence Control 2 */
170{VIACR, CR8E, 0xFF, 0x2B}, /* LCD Power Sequence Control 3 */
171{VIACR, CR8F, 0xFF, 0x01}, /* LCD Power Sequence Control 4 */
172{VIACR, CR90, 0xFF, 0x01}, /* LCD Power Sequence Control 5 */
173{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
174{VIACR, CR96, 0xFF, 0x00},
175{VIACR, CR97, 0xFF, 0x00},
176{VIACR, CR99, 0xFF, 0x00},
177{VIACR, CR9B, 0xFF, 0x00}
178};
179
180struct io_reg VX855_ModeXregs[] = {
181{VIASR, SR10, 0xFF, 0x01},
182{VIASR, SR15, 0x02, 0x02},
183{VIASR, SR16, 0xBF, 0x08},
184{VIASR, SR17, 0xFF, 0x1F},
185{VIASR, SR18, 0xFF, 0x4E},
186{VIASR, SR1A, 0xFB, 0x08},
187{VIASR, SR1B, 0xFF, 0xF0},
188{VIASR, SR1E, 0x07, 0x01},
189{VIASR, SR2A, 0xF0, 0x00},
190{VIASR, SR58, 0xFF, 0x00},
191{VIASR, SR59, 0xFF, 0x00},
192{VIASR, SR2D, 0xC0, 0xC0}, /* delayed E3_ECK */
193{VIACR, CR32, 0xFF, 0x00},
194{VIACR, CR33, 0x7F, 0x00},
195{VIACR, CR35, 0xFF, 0x00},
196{VIACR, CR36, 0x08, 0x00},
197{VIACR, CR69, 0xFF, 0x00},
198{VIACR, CR6A, 0xFD, 0x60},
199{VIACR, CR6B, 0xFF, 0x00},
200{VIACR, CR88, 0xFF, 0x40}, /* LCD Panel Type */
201{VIACR, CR89, 0xFF, 0x00}, /* LCD Timing Control 0 */
202{VIACR, CR8A, 0xFF, 0x88}, /* LCD Timing Control 1 */
203{VIACR, CRD4, 0xFF, 0x81}, /* Second power sequence control */
204{VIACR, CR91, 0xFF, 0x80}, /* 24/12 bit LVDS Data off */
205{VIACR, CR96, 0xFF, 0x00},
206{VIACR, CR97, 0xFF, 0x00},
207{VIACR, CR99, 0xFF, 0x00},
208{VIACR, CR9B, 0xFF, 0x00},
209{VIACR, CRD2, 0xFF, 0xFF} /* TMDS/LVDS control register. */
210};
211
212/* Video Mode Table */
213/* Common Setting for Video Mode */
214struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
215{VIASR, SR2A, 0x0F, 0x00},
216{VIASR, SR15, 0x02, 0x02},
217{VIASR, SR16, 0xBF, 0x08},
218{VIASR, SR17, 0xFF, 0x1F},
219{VIASR, SR18, 0xFF, 0x4E},
220{VIASR, SR1A, 0xFB, 0x08},
221
222{VIACR, CR32, 0xFF, 0x00},
223{VIACR, CR35, 0xFF, 0x00},
224{VIACR, CR36, 0x08, 0x00},
225{VIACR, CR6A, 0xFF, 0x80},
226{VIACR, CR6A, 0xFF, 0xC0},
227
228{VIACR, CR55, 0x80, 0x00},
229{VIACR, CR5D, 0x80, 0x00},
230
231{VIAGR, GR20, 0xFF, 0x00},
232{VIAGR, GR21, 0xFF, 0x00},
233{VIAGR, GR22, 0xFF, 0x00},
234
235};
236
237/* Mode:1024X768 */
238struct io_reg PM1024x768[] = { {VIASR, 0x16, 0xBF, 0x0C},
239{VIASR, 0x18, 0xFF, 0x4C}
240};
241
242struct patch_table res_patch_table[] = {
243 {ARRAY_SIZE(PM1024x768), PM1024x768}
244};
245
246/* struct VPITTable {
247 unsigned char Misc;
248 unsigned char SR[StdSR];
249 unsigned char CR[StdCR];
250 unsigned char GR[StdGR];
251 unsigned char AR[StdAR];
252 };*/
253
254struct VPITTable VPIT = {
255 /* Msic */
256 0xC7,
257 /* Sequencer */
258 {0x01, 0x0F, 0x00, 0x0E},
259 /* Graphic Controller */
260 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},
261 /* Attribute Controller */
262 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
263 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
264 0x01, 0x00, 0x0F, 0x00}
265};
266
267/********************/
268/* Mode Table */
269/********************/
270
271static const struct fb_videomode viafb_modes[] = {
272 {NULL, 60, 480, 640, 40285, 72, 24, 19, 1, 48, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
273 {NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, 0, 0},
274 {NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0, 0},
275 {NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, 0, 0, 0},
276 {NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
277 {NULL, 120, 640, 480, 19081, 104, 40, 31, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
278 {NULL, 60, 720, 480, 37426, 88, 16, 13, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
279 {NULL, 60, 720, 576, 30611, 96, 24, 17, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
280 {NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
281 {NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
282 {NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
283 {NULL, 100, 800, 600, 14667, 136, 48, 32, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
284 {NULL, 120, 800, 600, 11911, 144, 56, 39, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
285 {NULL, 60, 800, 480, 33602, 96, 24, 10, 3, 72, 7, FB_SYNC_VERT_HIGH_ACT, 0, 0},
286 {NULL, 60, 848, 480, 31565, 104, 24, 12, 3, 80, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
287 {NULL, 60, 856, 480, 31517, 104, 16, 13, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
288 {NULL, 60, 1024, 512, 24218, 136, 32, 15, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
289 {NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
290 {NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, 0, 0, 0},
291 {NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
292 {NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
293 {NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
294 {NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
295 {NULL, 60, 1280, 768, 12478, 200, 64, 23, 1, 136, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
296 {NULL, 50, 1280, 768, 15342, 184, 56, 19, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
297 {NULL, 60, 960, 600, 21964, 128, 32, 15, 3, 96, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
298 {NULL, 60, 1000, 600, 20803, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
299 {NULL, 60, 1024, 576, 21278, 144, 40, 17, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
300 {NULL, 60, 1088, 612, 18825, 152, 48, 16, 3, 104, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
301 {NULL, 60, 1152, 720, 14974, 168, 56, 19, 3, 112, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
302 {NULL, 60, 1200, 720, 14248, 184, 56, 22, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
303 {NULL, 49, 1200, 900, 17703, 21, 11, 1, 1, 32, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
304 {NULL, 60, 1280, 600, 16259, 184, 56, 18, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
305 {NULL, 60, 1280, 800, 11938, 200, 72, 22, 3, 128, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
306 {NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
307 {NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
308 {NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
309 {NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
310 {NULL, 60, 1360, 768, 11759, 208, 72, 22, 3, 136, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
311 {NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
312 {NULL, 50, 1368, 768, 14301, 200, 56, 19, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
313 {NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
314 {NULL, 60, 1440, 900, 9372, 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
315 {NULL, 75, 1440, 900, 7311, 248, 96, 33, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
316 {NULL, 60, 1440, 1040, 7993, 248, 96, 33, 1, 152, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
317 {NULL, 60, 1600, 900, 8449, 256, 88, 26, 3, 168, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
318 {NULL, 60, 1600, 1024, 7333, 272, 104, 32, 1, 168, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
319 {NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
320 {NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
321 {NULL, 60, 1680, 1050, 6832, 280, 104, 30, 3, 176, 6, 0, 0, 0},
322 {NULL, 75, 1680, 1050, 5339, 296, 120, 40, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
323 {NULL, 60, 1792, 1344, 4883, 328, 128, 46, 1, 200, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
324 {NULL, 60, 1856, 1392, 4581, 352, 96, 43, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
325 {NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
326 {NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
327 {NULL, 60, 2048, 1536, 3738, 376, 152, 49, 3, 224, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
328 {NULL, 60, 1280, 720, 13484, 216, 112, 20, 5, 40, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
329 {NULL, 50, 1280, 720, 16538, 176, 48, 17, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
330 {NULL, 60, 1920, 1080, 5776, 328, 128, 32, 3, 200, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
331 {NULL, 60, 1920, 1200, 5164, 336, 136, 36, 3, 200, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
332 {NULL, 60, 1400, 1050, 8210, 232, 88, 32, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
333 {NULL, 75, 1400, 1050, 6398, 248, 104, 42, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0} };
334
335static const struct fb_videomode viafb_rb_modes[] = {
336 {NULL, 60, 1360, 768, 13879, 80, 48, 14, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
337 {NULL, 60, 1440, 900, 11249, 80, 48, 17, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
338 {NULL, 60, 1400, 1050, 9892, 80, 48, 23, 3, 32, 4, FB_SYNC_HOR_HIGH_ACT, 0, 0},
339 {NULL, 60, 1600, 900, 10226, 80, 48, 18, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
340 {NULL, 60, 1680, 1050, 8387, 80, 48, 21, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
341 {NULL, 60, 1920, 1080, 7212, 80, 48, 23, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
342 {NULL, 60, 1920, 1200, 6488, 80, 48, 26, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0} };
343
344int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
345int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
346int NUM_TOTAL_KM400_ModeXregs = ARRAY_SIZE(KM400_ModeXregs);
347int NUM_TOTAL_CX700_ModeXregs = ARRAY_SIZE(CX700_ModeXregs);
348int NUM_TOTAL_VX855_ModeXregs = ARRAY_SIZE(VX855_ModeXregs);
349int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
350int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
351
352
353static const struct fb_videomode *get_best_mode(
354 const struct fb_videomode *modes, int n,
355 int hres, int vres, int refresh)
356{
357 const struct fb_videomode *best = NULL;
358 int i;
359
360 for (i = 0; i < n; i++) {
361 if (modes[i].xres != hres || modes[i].yres != vres)
362 continue;
363
364 if (!best || abs(modes[i].refresh - refresh) <
365 abs(best->refresh - refresh))
366 best = &modes[i];
367 }
368
369 return best;
370}
371
372const struct fb_videomode *viafb_get_best_mode(int hres, int vres, int refresh)
373{
374 return get_best_mode(viafb_modes, ARRAY_SIZE(viafb_modes),
375 hres, vres, refresh);
376}
377
378const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
379 int refresh)
380{
381 return get_best_mode(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes),
382 hres, vres, refresh);
383}
diff --git a/drivers/video/fbdev/via/viamode.h b/drivers/video/fbdev/via/viamode.h
new file mode 100644
index 000000000000..dd19106698e7
--- /dev/null
+++ b/drivers/video/fbdev/via/viamode.h
@@ -0,0 +1,63 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef __VIAMODE_H__
23#define __VIAMODE_H__
24
25#include "global.h"
26
27struct VPITTable {
28 unsigned char Misc;
29 unsigned char SR[StdSR];
30 unsigned char GR[StdGR];
31 unsigned char AR[StdAR];
32};
33
34struct patch_table {
35 int table_length;
36 struct io_reg *io_reg_table;
37};
38
39extern int NUM_TOTAL_CN400_ModeXregs;
40extern int NUM_TOTAL_CN700_ModeXregs;
41extern int NUM_TOTAL_KM400_ModeXregs;
42extern int NUM_TOTAL_CX700_ModeXregs;
43extern int NUM_TOTAL_VX855_ModeXregs;
44extern int NUM_TOTAL_CLE266_ModeXregs;
45extern int NUM_TOTAL_PATCH_MODE;
46
47extern struct io_reg CN400_ModeXregs[];
48extern struct io_reg CN700_ModeXregs[];
49extern struct io_reg KM400_ModeXregs[];
50extern struct io_reg CX700_ModeXregs[];
51extern struct io_reg VX800_ModeXregs[];
52extern struct io_reg VX855_ModeXregs[];
53extern struct io_reg CLE266_ModeXregs[];
54extern struct io_reg PM1024x768[];
55extern struct patch_table res_patch_table[];
56extern struct VPITTable VPIT;
57
58const struct fb_videomode *viafb_get_best_mode(int hres, int vres,
59 int refresh);
60const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
61 int refresh);
62
63#endif /* __VIAMODE_H__ */
diff --git a/drivers/video/fbdev/via/vt1636.c b/drivers/video/fbdev/via/vt1636.c
new file mode 100644
index 000000000000..ee2903b472cf
--- /dev/null
+++ b/drivers/video/fbdev/via/vt1636.c
@@ -0,0 +1,244 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#include <linux/via-core.h>
23#include <linux/via_i2c.h>
24#include "global.h"
25
26static const struct IODATA common_init_data[] = {
27/* Index, Mask, Value */
28 /* Set panel power sequence timing */
29 {0x10, 0xC0, 0x00},
30 /* T1: VDD on - Data on. Each increment is 1 ms. (50ms = 031h) */
31 {0x0B, 0xFF, 0x40},
32 /* T2: Data on - Backlight on. Each increment is 2 ms. (210ms = 068h) */
33 {0x0C, 0xFF, 0x31},
34 /* T3: Backlight off -Data off. Each increment is 2 ms. (210ms = 068h)*/
35 {0x0D, 0xFF, 0x31},
36 /* T4: Data off - VDD off. Each increment is 1 ms. (50ms = 031h) */
37 {0x0E, 0xFF, 0x68},
38 /* T5: VDD off - VDD on. Each increment is 100 ms. (500ms = 04h) */
39 {0x0F, 0xFF, 0x68},
40 /* LVDS output power up */
41 {0x09, 0xA0, 0xA0},
42 /* turn on back light */
43 {0x10, 0x33, 0x13}
44};
45
46/* Index, Mask, Value */
47static const struct IODATA dual_channel_enable_data = {0x08, 0xF0, 0xE0};
48static const struct IODATA single_channel_enable_data = {0x08, 0xF0, 0x00};
49static const struct IODATA dithering_enable_data = {0x0A, 0x70, 0x50};
50static const struct IODATA dithering_disable_data = {0x0A, 0x70, 0x00};
51static const struct IODATA vdd_on_data = {0x10, 0x20, 0x20};
52static const struct IODATA vdd_off_data = {0x10, 0x20, 0x00};
53
54u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
55 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
56 u8 index)
57{
58 u8 data;
59
60 viafb_i2c_readbyte(plvds_chip_info->i2c_port,
61 plvds_chip_info->lvds_chip_slave_addr, index, &data);
62 return data;
63}
64
65void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information
66 *plvds_setting_info, struct lvds_chip_information
67 *plvds_chip_info, struct IODATA io_data)
68{
69 int index, data;
70
71 index = io_data.Index;
72 data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info,
73 index);
74 data = (data & (~io_data.Mask)) | io_data.Data;
75
76 viafb_i2c_writebyte(plvds_chip_info->i2c_port,
77 plvds_chip_info->lvds_chip_slave_addr, index, data);
78}
79
80void viafb_init_lvds_vt1636(struct lvds_setting_information
81 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info)
82{
83 int reg_num, i;
84
85 /* Common settings: */
86 reg_num = ARRAY_SIZE(common_init_data);
87 for (i = 0; i < reg_num; i++)
88 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
89 plvds_chip_info, common_init_data[i]);
90
91 /* Input Data Mode Select */
92 if (plvds_setting_info->device_lcd_dualedge)
93 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
94 plvds_chip_info, dual_channel_enable_data);
95 else
96 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
97 plvds_chip_info, single_channel_enable_data);
98
99 if (plvds_setting_info->LCDDithering)
100 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
101 plvds_chip_info, dithering_enable_data);
102 else
103 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
104 plvds_chip_info, dithering_disable_data);
105}
106
107void viafb_enable_lvds_vt1636(struct lvds_setting_information
108 *plvds_setting_info,
109 struct lvds_chip_information *plvds_chip_info)
110{
111 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
112 vdd_on_data);
113}
114
115void viafb_disable_lvds_vt1636(struct lvds_setting_information
116 *plvds_setting_info,
117 struct lvds_chip_information *plvds_chip_info)
118{
119 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
120 vdd_off_data);
121}
122
123bool viafb_lvds_identify_vt1636(u8 i2c_adapter)
124{
125 u8 Buffer[2];
126
127 DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n");
128
129 /* Sense VT1636 LVDS Transmiter */
130 viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr =
131 VT1636_LVDS_I2C_ADDR;
132
133 /* Check vendor ID first: */
134 if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR,
135 0x00, &Buffer[0]))
136 return false;
137 viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]);
138
139 if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11)))
140 return false;
141
142 /* Check Chip ID: */
143 viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]);
144 viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]);
145 if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) {
146 viaparinfo->chip_info->lvds_chip_info.lvds_chip_name =
147 VT1636_LVDS;
148 return true;
149 }
150
151 return false;
152}
153
154static int get_clk_range_index(u32 Clk)
155{
156 if (Clk < DPA_CLK_30M)
157 return DPA_CLK_RANGE_30M;
158 else if (Clk < DPA_CLK_50M)
159 return DPA_CLK_RANGE_30_50M;
160 else if (Clk < DPA_CLK_70M)
161 return DPA_CLK_RANGE_50_70M;
162 else if (Clk < DPA_CLK_100M)
163 return DPA_CLK_RANGE_70_100M;
164 else if (Clk < DPA_CLK_150M)
165 return DPA_CLK_RANGE_100_150M;
166 else
167 return DPA_CLK_RANGE_150M;
168}
169
170static void set_dpa_vt1636(struct lvds_setting_information
171 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
172 struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
173{
174 struct IODATA io_data;
175
176 io_data.Index = 0x09;
177 io_data.Mask = 0x1F;
178 io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST1;
179 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info,
180 plvds_chip_info, io_data);
181
182 io_data.Index = 0x08;
183 io_data.Mask = 0x0F;
184 io_data.Data = p_vt1636_dpa_setting->CLK_SEL_ST2;
185 viafb_gpio_i2c_write_mask_lvds(plvds_setting_info, plvds_chip_info,
186 io_data);
187}
188
189void viafb_vt1636_patch_skew_on_vt3324(
190 struct lvds_setting_information *plvds_setting_info,
191 struct lvds_chip_information *plvds_chip_info)
192{
193 struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
194 *pdpa;
195 int index;
196
197 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
198
199 /* Graphics DPA settings: */
200 index = get_clk_range_index(plvds_setting_info->vclk);
201 viafb_set_dpa_gfx(plvds_chip_info->output_interface,
202 &GFX_DPA_SETTING_TBL_VT3324[index]);
203
204 /* LVDS Transmitter DPA settings: */
205 if (plvds_setting_info->lcd_panel_hres == 1600 &&
206 plvds_setting_info->lcd_panel_vres == 1200)
207 pdpa = &dpa_16x12;
208 else
209 pdpa = &dpa;
210
211 set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
212}
213
214void viafb_vt1636_patch_skew_on_vt3327(
215 struct lvds_setting_information *plvds_setting_info,
216 struct lvds_chip_information *plvds_chip_info)
217{
218 struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
219 int index;
220
221 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
222
223 /* Graphics DPA settings: */
224 index = get_clk_range_index(plvds_setting_info->vclk);
225 viafb_set_dpa_gfx(plvds_chip_info->output_interface,
226 &GFX_DPA_SETTING_TBL_VT3327[index]);
227
228 /* LVDS Transmitter DPA settings: */
229 set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
230}
231
232void viafb_vt1636_patch_skew_on_vt3364(
233 struct lvds_setting_information *plvds_setting_info,
234 struct lvds_chip_information *plvds_chip_info)
235{
236 int index;
237
238 DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3364.\n");
239
240 /* Graphics DPA settings: */
241 index = get_clk_range_index(plvds_setting_info->vclk);
242 viafb_set_dpa_gfx(plvds_chip_info->output_interface,
243 &GFX_DPA_SETTING_TBL_VT3364[index]);
244}
diff --git a/drivers/video/fbdev/via/vt1636.h b/drivers/video/fbdev/via/vt1636.h
new file mode 100644
index 000000000000..4c1314e57468
--- /dev/null
+++ b/drivers/video/fbdev/via/vt1636.h
@@ -0,0 +1,44 @@
1/*
2 * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved.
4
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public
7 * License as published by the Free Software Foundation;
8 * either version 2, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
12 * the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE.See the GNU General Public License
14 * for more details.
15
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22#ifndef _VT1636_H_
23#define _VT1636_H_
24#include "chip.h"
25bool viafb_lvds_identify_vt1636(u8 i2c_adapter);
26void viafb_init_lvds_vt1636(struct lvds_setting_information
27 *plvds_setting_info, struct lvds_chip_information *plvds_chip_info);
28void viafb_enable_lvds_vt1636(struct lvds_setting_information
29 *plvds_setting_info,
30 struct lvds_chip_information *plvds_chip_info);
31void viafb_disable_lvds_vt1636(struct lvds_setting_information
32 *plvds_setting_info,
33 struct lvds_chip_information *plvds_chip_info);
34void viafb_vt1636_patch_skew_on_vt3324(
35 struct lvds_setting_information *plvds_setting_info,
36 struct lvds_chip_information *plvds_chip_info);
37void viafb_vt1636_patch_skew_on_vt3327(
38 struct lvds_setting_information *plvds_setting_info,
39 struct lvds_chip_information *plvds_chip_info);
40void viafb_vt1636_patch_skew_on_vt3364(
41 struct lvds_setting_information *plvds_setting_info,
42 struct lvds_chip_information *plvds_chip_info);
43
44#endif