diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 16:34:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-20 16:34:17 -0400 |
commit | 7c6d87ac843bfbc5a7669736882a0e88c217a820 (patch) | |
tree | b757687fcc7493a322c5c27aa141c87668900234 /drivers/video/via | |
parent | a0fe3cc5d36a5f5b4f60abfe1a4b1caf4a5cce5a (diff) | |
parent | ec66841e495b9ab4f92bdf91efe8cf56e1471fbd (diff) |
Merge branch 'viafb-next' of git://git.lwn.net/linux-2.6
* 'viafb-next' of git://git.lwn.net/linux-2.6: (35 commits)
viafb: move some include files to include/linux
viafb: Eliminate some global.h references
viafb: get rid of i2c debug cruft
viafb: fold via_io.h into via-core.h
viafb: Fix initialization error paths
viafb: Do not remove gpiochip under spinlock
viafb: make procfs entries optional
viafb: fix proc entry removal
viafb: improve misc register handling
viafb: replace inb/outb
viafb: move some modesetting functions to a seperate file
viafb: unify modesetting functions
viafb: Reserve framebuffer memory for the upcoming camera driver
viafb: Add a simple VX855 DMA engine driver
viafb: Add a simple interrupt management infrastructure
via: Rationalize vt1636 detection
viafb: Introduce viafb_find_i2c_adapter()
via: Do not attempt I/O on inactive I2C adapters
viafb: Turn GPIO and i2c into proper platform devices
viafb: Convert GPIO and i2c to the new indexed port ops
...
Diffstat (limited to 'drivers/video/via')
-rw-r--r-- | drivers/video/via/Makefile | 4 | ||||
-rw-r--r-- | drivers/video/via/accel.c | 137 | ||||
-rw-r--r-- | drivers/video/via/accel.h | 40 | ||||
-rw-r--r-- | drivers/video/via/chip.h | 8 | ||||
-rw-r--r-- | drivers/video/via/dvi.c | 37 | ||||
-rw-r--r-- | drivers/video/via/global.h | 1 | ||||
-rw-r--r-- | drivers/video/via/hw.c | 307 | ||||
-rw-r--r-- | drivers/video/via/hw.h | 20 | ||||
-rw-r--r-- | drivers/video/via/ioctl.h | 2 | ||||
-rw-r--r-- | drivers/video/via/lcd.c | 31 | ||||
-rw-r--r-- | drivers/video/via/lcd.h | 2 | ||||
-rw-r--r-- | drivers/video/via/share.h | 20 | ||||
-rw-r--r-- | drivers/video/via/via-core.c | 668 | ||||
-rw-r--r-- | drivers/video/via/via-gpio.c | 285 | ||||
-rw-r--r-- | drivers/video/via/via_i2c.c | 232 | ||||
-rw-r--r-- | drivers/video/via/via_modesetting.c | 126 | ||||
-rw-r--r-- | drivers/video/via/via_modesetting.h (renamed from drivers/video/via/via_i2c.h) | 42 | ||||
-rw-r--r-- | drivers/video/via/via_utility.c | 1 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.c | 181 | ||||
-rw-r--r-- | drivers/video/via/viafbdev.h | 14 | ||||
-rw-r--r-- | drivers/video/via/viamode.c | 15 | ||||
-rw-r--r-- | drivers/video/via/vt1636.c | 34 | ||||
-rw-r--r-- | drivers/video/via/vt1636.h | 2 |
23 files changed, 1625 insertions, 584 deletions
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index eeed238ad6a2..d496adb0f832 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile | |||
@@ -4,4 +4,6 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_FB_VIA) += viafb.o | 5 | obj-$(CONFIG_FB_VIA) += viafb.o |
6 | 6 | ||
7 | viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o | 7 | viafb-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 tbl1636.o \ | ||
9 | via-core.o via-gpio.o via_modesetting.o | ||
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index d5077dfa9e00..e44893ea590d 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c | |||
@@ -18,14 +18,45 @@ | |||
18 | * Foundation, Inc., | 18 | * Foundation, Inc., |
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | #include <linux/via-core.h> | ||
21 | #include "global.h" | 22 | #include "global.h" |
22 | 23 | ||
24 | /* | ||
25 | * Figure out an appropriate bytes-per-pixel setting. | ||
26 | */ | ||
27 | static 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 | |||
23 | static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, | 53 | static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, |
24 | u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, | 54 | u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, |
25 | u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, | 55 | u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, |
26 | u32 fg_color, u32 bg_color, u8 fill_rop) | 56 | u32 fg_color, u32 bg_color, u8 fill_rop) |
27 | { | 57 | { |
28 | u32 ge_cmd = 0, tmp, i; | 58 | u32 ge_cmd = 0, tmp, i; |
59 | int ret; | ||
29 | 60 | ||
30 | if (!op || op > 3) { | 61 | if (!op || op > 3) { |
31 | printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); | 62 | printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); |
@@ -59,22 +90,9 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, | |||
59 | } | 90 | } |
60 | } | 91 | } |
61 | 92 | ||
62 | switch (dst_bpp) { | 93 | ret = viafb_set_bpp(engine, dst_bpp); |
63 | case 8: | 94 | if (ret) |
64 | tmp = 0x00000000; | 95 | return ret; |
65 | break; | ||
66 | case 16: | ||
67 | tmp = 0x00000100; | ||
68 | break; | ||
69 | case 32: | ||
70 | tmp = 0x00000300; | ||
71 | break; | ||
72 | default: | ||
73 | printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n", | ||
74 | dst_bpp); | ||
75 | return -EINVAL; | ||
76 | } | ||
77 | writel(tmp, engine + 0x04); | ||
78 | 96 | ||
79 | if (op != VIA_BITBLT_FILL) { | 97 | if (op != VIA_BITBLT_FILL) { |
80 | if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) | 98 | if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) |
@@ -171,6 +189,7 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, | |||
171 | u32 fg_color, u32 bg_color, u8 fill_rop) | 189 | u32 fg_color, u32 bg_color, u8 fill_rop) |
172 | { | 190 | { |
173 | u32 ge_cmd = 0, tmp, i; | 191 | u32 ge_cmd = 0, tmp, i; |
192 | int ret; | ||
174 | 193 | ||
175 | if (!op || op > 3) { | 194 | if (!op || op > 3) { |
176 | printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); | 195 | printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); |
@@ -204,22 +223,9 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, | |||
204 | } | 223 | } |
205 | } | 224 | } |
206 | 225 | ||
207 | switch (dst_bpp) { | 226 | ret = viafb_set_bpp(engine, dst_bpp); |
208 | case 8: | 227 | if (ret) |
209 | tmp = 0x00000000; | 228 | return ret; |
210 | break; | ||
211 | case 16: | ||
212 | tmp = 0x00000100; | ||
213 | break; | ||
214 | case 32: | ||
215 | tmp = 0x00000300; | ||
216 | break; | ||
217 | default: | ||
218 | printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n", | ||
219 | dst_bpp); | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | writel(tmp, engine + 0x04); | ||
223 | 229 | ||
224 | if (op == VIA_BITBLT_FILL) | 230 | if (op == VIA_BITBLT_FILL) |
225 | tmp = 0; | 231 | tmp = 0; |
@@ -312,17 +318,29 @@ int viafb_init_engine(struct fb_info *info) | |||
312 | { | 318 | { |
313 | struct viafb_par *viapar = info->par; | 319 | struct viafb_par *viapar = info->par; |
314 | void __iomem *engine; | 320 | void __iomem *engine; |
321 | int highest_reg, i; | ||
315 | u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, | 322 | u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, |
316 | vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; | 323 | vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; |
317 | 324 | ||
318 | engine = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); | 325 | engine = viapar->shared->vdev->engine_mmio; |
319 | viapar->shared->engine_mmio = engine; | ||
320 | if (!engine) { | 326 | if (!engine) { |
321 | printk(KERN_WARNING "viafb_init_accel: ioremap failed, " | 327 | printk(KERN_WARNING "viafb_init_accel: ioremap failed, " |
322 | "hardware acceleration disabled\n"); | 328 | "hardware acceleration disabled\n"); |
323 | return -ENOMEM; | 329 | return -ENOMEM; |
324 | } | 330 | } |
325 | 331 | ||
332 | /* Initialize registers to reset the 2D engine */ | ||
333 | switch (viapar->shared->chip_info.twod_engine) { | ||
334 | case VIA_2D_ENG_M1: | ||
335 | highest_reg = 0x5c; | ||
336 | break; | ||
337 | default: | ||
338 | highest_reg = 0x40; | ||
339 | break; | ||
340 | } | ||
341 | for (i = 0; i <= highest_reg; i += 4) | ||
342 | writel(0x0, engine + i); | ||
343 | |||
326 | switch (chip_name) { | 344 | switch (chip_name) { |
327 | case UNICHROME_CLE266: | 345 | case UNICHROME_CLE266: |
328 | case UNICHROME_K400: | 346 | case UNICHROME_K400: |
@@ -352,13 +370,28 @@ int viafb_init_engine(struct fb_info *info) | |||
352 | viapar->shared->vq_vram_addr = viapar->fbmem_free; | 370 | viapar->shared->vq_vram_addr = viapar->fbmem_free; |
353 | viapar->fbmem_used += VQ_SIZE; | 371 | viapar->fbmem_used += VQ_SIZE; |
354 | 372 | ||
355 | /* Init 2D engine reg to reset 2D engine */ | 373 | #if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) |
356 | writel(0x0, engine + VIA_REG_KEYCONTROL); | 374 | /* |
375 | * Set aside a chunk of framebuffer memory for the camera | ||
376 | * driver. Someday this driver probably needs a proper allocator | ||
377 | * for fbmem; for now, we just have to do this before the | ||
378 | * framebuffer initializes itself. | ||
379 | * | ||
380 | * As for the size: the engine can handle three frames, | ||
381 | * 16 bits deep, up to VGA resolution. | ||
382 | */ | ||
383 | viapar->shared->vdev->camera_fbmem_size = 3*VGA_HEIGHT*VGA_WIDTH*2; | ||
384 | viapar->fbmem_free -= viapar->shared->vdev->camera_fbmem_size; | ||
385 | viapar->fbmem_used += viapar->shared->vdev->camera_fbmem_size; | ||
386 | viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free; | ||
387 | #endif | ||
357 | 388 | ||
358 | /* Init AGP and VQ regs */ | 389 | /* Init AGP and VQ regs */ |
359 | switch (chip_name) { | 390 | switch (chip_name) { |
360 | case UNICHROME_K8M890: | 391 | case UNICHROME_K8M890: |
361 | case UNICHROME_P4M900: | 392 | case UNICHROME_P4M900: |
393 | case UNICHROME_VX800: | ||
394 | case UNICHROME_VX855: | ||
362 | writel(0x00100000, engine + VIA_REG_CR_TRANSET); | 395 | writel(0x00100000, engine + VIA_REG_CR_TRANSET); |
363 | writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); | 396 | writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE); |
364 | writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); | 397 | writel(0x02000000, engine + VIA_REG_CR_TRANSPACE); |
@@ -393,6 +426,8 @@ int viafb_init_engine(struct fb_info *info) | |||
393 | switch (chip_name) { | 426 | switch (chip_name) { |
394 | case UNICHROME_K8M890: | 427 | case UNICHROME_K8M890: |
395 | case UNICHROME_P4M900: | 428 | case UNICHROME_P4M900: |
429 | case UNICHROME_VX800: | ||
430 | case UNICHROME_VX855: | ||
396 | vq_start_low |= 0x20000000; | 431 | vq_start_low |= 0x20000000; |
397 | vq_end_low |= 0x20000000; | 432 | vq_end_low |= 0x20000000; |
398 | vq_high |= 0x20000000; | 433 | vq_high |= 0x20000000; |
@@ -446,7 +481,7 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) | |||
446 | struct viafb_par *viapar = info->par; | 481 | struct viafb_par *viapar = info->par; |
447 | u32 temp, iga_path = viapar->iga_path; | 482 | u32 temp, iga_path = viapar->iga_path; |
448 | 483 | ||
449 | temp = readl(viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE); | 484 | temp = readl(viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE); |
450 | switch (Status) { | 485 | switch (Status) { |
451 | case HW_Cursor_ON: | 486 | case HW_Cursor_ON: |
452 | temp |= 0x1; | 487 | temp |= 0x1; |
@@ -463,23 +498,33 @@ void viafb_show_hw_cursor(struct fb_info *info, int Status) | |||
463 | default: | 498 | default: |
464 | temp &= 0x7FFFFFFF; | 499 | temp &= 0x7FFFFFFF; |
465 | } | 500 | } |
466 | writel(temp, viapar->shared->engine_mmio + VIA_REG_CURSOR_MODE); | 501 | writel(temp, viapar->shared->vdev->engine_mmio + VIA_REG_CURSOR_MODE); |
467 | } | 502 | } |
468 | 503 | ||
469 | void viafb_wait_engine_idle(struct fb_info *info) | 504 | void viafb_wait_engine_idle(struct fb_info *info) |
470 | { | 505 | { |
471 | struct viafb_par *viapar = info->par; | 506 | struct viafb_par *viapar = info->par; |
472 | int loop = 0; | 507 | int loop = 0; |
473 | 508 | u32 mask; | |
474 | while (!(readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & | 509 | void __iomem *engine = viapar->shared->vdev->engine_mmio; |
475 | VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { | 510 | |
476 | loop++; | 511 | switch (viapar->shared->chip_info.twod_engine) { |
477 | cpu_relax(); | 512 | case VIA_2D_ENG_H5: |
513 | case VIA_2D_ENG_M1: | ||
514 | mask = VIA_CMD_RGTR_BUSY_M1 | VIA_2D_ENG_BUSY_M1 | | ||
515 | VIA_3D_ENG_BUSY_M1; | ||
516 | break; | ||
517 | default: | ||
518 | while (!(readl(engine + VIA_REG_STATUS) & | ||
519 | VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { | ||
520 | loop++; | ||
521 | cpu_relax(); | ||
522 | } | ||
523 | mask = VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY; | ||
524 | break; | ||
478 | } | 525 | } |
479 | 526 | ||
480 | while ((readl(viapar->shared->engine_mmio + VIA_REG_STATUS) & | 527 | while ((readl(engine + VIA_REG_STATUS) & mask) && (loop < MAXLOOP)) { |
481 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && | ||
482 | (loop < MAXLOOP)) { | ||
483 | loop++; | 528 | loop++; |
484 | cpu_relax(); | 529 | cpu_relax(); |
485 | } | 530 | } |
diff --git a/drivers/video/via/accel.h b/drivers/video/via/accel.h index 615c84ad0f01..2c122d292365 100644 --- a/drivers/video/via/accel.h +++ b/drivers/video/via/accel.h | |||
@@ -67,6 +67,34 @@ | |||
67 | /* from 0x100 to 0x1ff */ | 67 | /* from 0x100 to 0x1ff */ |
68 | #define VIA_REG_COLORPAT 0x100 | 68 | #define VIA_REG_COLORPAT 0x100 |
69 | 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 | |||
70 | /* VIA_REG_PITCH(0x38): Pitch Setting */ | 98 | /* VIA_REG_PITCH(0x38): Pitch Setting */ |
71 | #define VIA_PITCH_ENABLE 0x80000000 | 99 | #define VIA_PITCH_ENABLE 0x80000000 |
72 | 100 | ||
@@ -157,6 +185,18 @@ | |||
157 | /* Virtual Queue is busy */ | 185 | /* Virtual Queue is busy */ |
158 | #define VIA_VR_QUEUE_BUSY 0x00020000 | 186 | #define VIA_VR_QUEUE_BUSY 0x00020000 |
159 | 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 | |||
160 | #define MAXLOOP 0xFFFFFF | 200 | #define MAXLOOP 0xFFFFFF |
161 | 201 | ||
162 | #define VIA_BITBLT_COLOR 1 | 202 | #define VIA_BITBLT_COLOR 1 |
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h index 8c06bd3c0b4d..d9b6e06e0700 100644 --- a/drivers/video/via/chip.h +++ b/drivers/video/via/chip.h | |||
@@ -121,9 +121,17 @@ struct lvds_chip_information { | |||
121 | int i2c_port; | 121 | int i2c_port; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | /* The type of 2D engine */ | ||
125 | enum via_2d_engine { | ||
126 | VIA_2D_ENG_H2, | ||
127 | VIA_2D_ENG_H5, | ||
128 | VIA_2D_ENG_M1, | ||
129 | }; | ||
130 | |||
124 | struct chip_information { | 131 | struct chip_information { |
125 | int gfx_chip_name; | 132 | int gfx_chip_name; |
126 | int gfx_chip_revision; | 133 | int gfx_chip_revision; |
134 | enum via_2d_engine twod_engine; | ||
127 | struct tmds_chip_information tmds_chip_info; | 135 | struct tmds_chip_information tmds_chip_info; |
128 | struct lvds_chip_information lvds_chip_info; | 136 | struct lvds_chip_information lvds_chip_info; |
129 | struct lvds_chip_information lvds_chip_info2; | 137 | struct lvds_chip_information lvds_chip_info2; |
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index abe59b8c7a05..39b040bb3817 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c | |||
@@ -18,6 +18,8 @@ | |||
18 | * Foundation, Inc., | 18 | * Foundation, Inc., |
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | #include <linux/via-core.h> | ||
22 | #include <linux/via_i2c.h> | ||
21 | #include "global.h" | 23 | #include "global.h" |
22 | 24 | ||
23 | static void tmds_register_write(int index, u8 data); | 25 | static void tmds_register_write(int index, u8 data); |
@@ -96,7 +98,7 @@ int viafb_tmds_trasmitter_identify(void) | |||
96 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; | 98 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; |
97 | viaparinfo->chip_info-> | 99 | viaparinfo->chip_info-> |
98 | tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; | 100 | tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; |
99 | viaparinfo->chip_info->tmds_chip_info.i2c_port = I2CPORTINDEX; | 101 | viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31; |
100 | if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { | 102 | if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) != FAIL) { |
101 | /* | 103 | /* |
102 | * Currently only support 12bits,dual edge,add 24bits mode later | 104 | * Currently only support 12bits,dual edge,add 24bits mode later |
@@ -110,7 +112,7 @@ int viafb_tmds_trasmitter_identify(void) | |||
110 | viaparinfo->chip_info->tmds_chip_info.i2c_port); | 112 | viaparinfo->chip_info->tmds_chip_info.i2c_port); |
111 | return OK; | 113 | return OK; |
112 | } else { | 114 | } else { |
113 | viaparinfo->chip_info->tmds_chip_info.i2c_port = GPIOPORTINDEX; | 115 | viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_2C; |
114 | if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) | 116 | if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID) |
115 | != FAIL) { | 117 | != FAIL) { |
116 | tmds_register_write(0x08, 0x3b); | 118 | tmds_register_write(0x08, 0x3b); |
@@ -160,32 +162,26 @@ int viafb_tmds_trasmitter_identify(void) | |||
160 | 162 | ||
161 | static void tmds_register_write(int index, u8 data) | 163 | static void tmds_register_write(int index, u8 data) |
162 | { | 164 | { |
163 | viaparinfo->shared->i2c_stuff.i2c_port = | 165 | viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, |
164 | viaparinfo->chip_info->tmds_chip_info.i2c_port; | 166 | viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, |
165 | 167 | index, data); | |
166 | viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info. | ||
167 | tmds_chip_slave_addr, index, | ||
168 | data); | ||
169 | } | 168 | } |
170 | 169 | ||
171 | static int tmds_register_read(int index) | 170 | static int tmds_register_read(int index) |
172 | { | 171 | { |
173 | u8 data; | 172 | u8 data; |
174 | 173 | ||
175 | viaparinfo->shared->i2c_stuff.i2c_port = | 174 | viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, |
176 | viaparinfo->chip_info->tmds_chip_info.i2c_port; | 175 | (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, |
177 | viafb_i2c_readbyte((u8) viaparinfo->chip_info-> | 176 | (u8) index, &data); |
178 | tmds_chip_info.tmds_chip_slave_addr, | ||
179 | (u8) index, &data); | ||
180 | return data; | 177 | return data; |
181 | } | 178 | } |
182 | 179 | ||
183 | static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) | 180 | static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) |
184 | { | 181 | { |
185 | viaparinfo->shared->i2c_stuff.i2c_port = | 182 | viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port, |
186 | viaparinfo->chip_info->tmds_chip_info.i2c_port; | 183 | (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, |
187 | viafb_i2c_readbytes((u8) viaparinfo->chip_info->tmds_chip_info. | 184 | (u8) index, buff, buff_len); |
188 | tmds_chip_slave_addr, (u8) index, buff, buff_len); | ||
189 | return 0; | 185 | return 0; |
190 | } | 186 | } |
191 | 187 | ||
@@ -541,9 +537,10 @@ void viafb_dvi_enable(void) | |||
541 | else | 537 | else |
542 | data = 0x37; | 538 | data = 0x37; |
543 | viafb_i2c_writebyte(viaparinfo->chip_info-> | 539 | viafb_i2c_writebyte(viaparinfo->chip_info-> |
544 | tmds_chip_info. | 540 | tmds_chip_info.i2c_port, |
545 | tmds_chip_slave_addr, | 541 | viaparinfo->chip_info-> |
546 | 0x08, data); | 542 | tmds_chip_info.tmds_chip_slave_addr, |
543 | 0x08, data); | ||
547 | } | 544 | } |
548 | } | 545 | } |
549 | } | 546 | } |
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index 8d95d5fd1388..28221a062dda 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h | |||
@@ -41,7 +41,6 @@ | |||
41 | #include "share.h" | 41 | #include "share.h" |
42 | #include "dvi.h" | 42 | #include "dvi.h" |
43 | #include "viamode.h" | 43 | #include "viamode.h" |
44 | #include "via_i2c.h" | ||
45 | #include "hw.h" | 44 | #include "hw.h" |
46 | 45 | ||
47 | #include "lcd.h" | 46 | #include "lcd.h" |
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index f2583b1b527f..b996803ae2c1 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/via-core.h> | ||
22 | #include "global.h" | 23 | #include "global.h" |
23 | 24 | ||
24 | static struct pll_map pll_value[] = { | 25 | static struct pll_map pll_value[] = { |
@@ -62,6 +63,7 @@ static struct pll_map pll_value[] = { | |||
62 | CX700_52_977M, VX855_52_977M}, | 63 | CX700_52_977M, VX855_52_977M}, |
63 | {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, | 64 | {CLK_56_250M, CLE266_PLL_56_250M, K800_PLL_56_250M, |
64 | CX700_56_250M, VX855_56_250M}, | 65 | CX700_56_250M, VX855_56_250M}, |
66 | {CLK_57_275M, 0, 0, 0, VX855_57_275M}, | ||
65 | {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, | 67 | {CLK_60_466M, CLE266_PLL_60_466M, K800_PLL_60_466M, |
66 | CX700_60_466M, VX855_60_466M}, | 68 | CX700_60_466M, VX855_60_466M}, |
67 | {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, | 69 | {CLK_61_500M, CLE266_PLL_61_500M, K800_PLL_61_500M, |
@@ -525,8 +527,7 @@ static void dvi_patch_skew_dvp_low(void); | |||
525 | static void set_dvi_output_path(int set_iga, int output_interface); | 527 | static void set_dvi_output_path(int set_iga, int output_interface); |
526 | static void set_lcd_output_path(int set_iga, int output_interface); | 528 | static void set_lcd_output_path(int set_iga, int output_interface); |
527 | static void load_fix_bit_crtc_reg(void); | 529 | static void load_fix_bit_crtc_reg(void); |
528 | static void init_gfx_chip_info(struct pci_dev *pdev, | 530 | static void init_gfx_chip_info(int chip_type); |
529 | const struct pci_device_id *pdi); | ||
530 | static void init_tmds_chip_info(void); | 531 | static void init_tmds_chip_info(void); |
531 | static void init_lvds_chip_info(void); | 532 | static void init_lvds_chip_info(void); |
532 | static void device_screen_off(void); | 533 | static void device_screen_off(void); |
@@ -537,18 +538,6 @@ static void device_on(void); | |||
537 | static void enable_second_display_channel(void); | 538 | static void enable_second_display_channel(void); |
538 | static void disable_second_display_channel(void); | 539 | static void disable_second_display_channel(void); |
539 | 540 | ||
540 | void viafb_write_reg(u8 index, u16 io_port, u8 data) | ||
541 | { | ||
542 | outb(index, io_port); | ||
543 | outb(data, io_port + 1); | ||
544 | /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, data); */ | ||
545 | } | ||
546 | u8 viafb_read_reg(int io_port, u8 index) | ||
547 | { | ||
548 | outb(index, io_port); | ||
549 | return inb(io_port + 1); | ||
550 | } | ||
551 | |||
552 | void viafb_lock_crt(void) | 541 | void viafb_lock_crt(void) |
553 | { | 542 | { |
554 | viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7); | 543 | viafb_write_reg_mask(CR11, VIACR, BIT7, BIT7); |
@@ -560,16 +549,6 @@ void viafb_unlock_crt(void) | |||
560 | viafb_write_reg_mask(CR47, VIACR, 0, BIT0); | 549 | viafb_write_reg_mask(CR47, VIACR, 0, BIT0); |
561 | } | 550 | } |
562 | 551 | ||
563 | void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask) | ||
564 | { | ||
565 | u8 tmp; | ||
566 | |||
567 | outb(index, io_port); | ||
568 | tmp = inb(io_port + 1); | ||
569 | outb((data & mask) | (tmp & (~mask)), io_port + 1); | ||
570 | /*DEBUG_MSG(KERN_INFO "\nIndex=%2d Value=%2d", index, tmp); */ | ||
571 | } | ||
572 | |||
573 | void write_dac_reg(u8 index, u8 r, u8 g, u8 b) | 552 | void write_dac_reg(u8 index, u8 r, u8 g, u8 b) |
574 | { | 553 | { |
575 | outb(index, LUT_INDEX_WRITE); | 554 | outb(index, LUT_INDEX_WRITE); |
@@ -646,102 +625,6 @@ void viafb_set_iga_path(void) | |||
646 | } | 625 | } |
647 | } | 626 | } |
648 | 627 | ||
649 | void viafb_set_primary_address(u32 addr) | ||
650 | { | ||
651 | DEBUG_MSG(KERN_DEBUG "viafb_set_primary_address(0x%08X)\n", addr); | ||
652 | viafb_write_reg(CR0D, VIACR, addr & 0xFF); | ||
653 | viafb_write_reg(CR0C, VIACR, (addr >> 8) & 0xFF); | ||
654 | viafb_write_reg(CR34, VIACR, (addr >> 16) & 0xFF); | ||
655 | viafb_write_reg_mask(CR48, VIACR, (addr >> 24) & 0x1F, 0x1F); | ||
656 | } | ||
657 | |||
658 | void viafb_set_secondary_address(u32 addr) | ||
659 | { | ||
660 | DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_address(0x%08X)\n", addr); | ||
661 | /* secondary display supports only quadword aligned memory */ | ||
662 | viafb_write_reg_mask(CR62, VIACR, (addr >> 2) & 0xFE, 0xFE); | ||
663 | viafb_write_reg(CR63, VIACR, (addr >> 10) & 0xFF); | ||
664 | viafb_write_reg(CR64, VIACR, (addr >> 18) & 0xFF); | ||
665 | viafb_write_reg_mask(CRA3, VIACR, (addr >> 26) & 0x07, 0x07); | ||
666 | } | ||
667 | |||
668 | void viafb_set_primary_pitch(u32 pitch) | ||
669 | { | ||
670 | DEBUG_MSG(KERN_DEBUG "viafb_set_primary_pitch(0x%08X)\n", pitch); | ||
671 | /* spec does not say that first adapter skips 3 bits but old | ||
672 | * code did it and seems to be reasonable in analogy to 2nd adapter | ||
673 | */ | ||
674 | pitch = pitch >> 3; | ||
675 | viafb_write_reg(0x13, VIACR, pitch & 0xFF); | ||
676 | viafb_write_reg_mask(0x35, VIACR, (pitch >> (8 - 5)) & 0xE0, 0xE0); | ||
677 | } | ||
678 | |||
679 | void viafb_set_secondary_pitch(u32 pitch) | ||
680 | { | ||
681 | DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_pitch(0x%08X)\n", pitch); | ||
682 | pitch = pitch >> 3; | ||
683 | viafb_write_reg(0x66, VIACR, pitch & 0xFF); | ||
684 | viafb_write_reg_mask(0x67, VIACR, (pitch >> 8) & 0x03, 0x03); | ||
685 | viafb_write_reg_mask(0x71, VIACR, (pitch >> (10 - 7)) & 0x80, 0x80); | ||
686 | } | ||
687 | |||
688 | void viafb_set_primary_color_depth(u8 depth) | ||
689 | { | ||
690 | u8 value; | ||
691 | |||
692 | DEBUG_MSG(KERN_DEBUG "viafb_set_primary_color_depth(%d)\n", depth); | ||
693 | switch (depth) { | ||
694 | case 8: | ||
695 | value = 0x00; | ||
696 | break; | ||
697 | case 15: | ||
698 | value = 0x04; | ||
699 | break; | ||
700 | case 16: | ||
701 | value = 0x14; | ||
702 | break; | ||
703 | case 24: | ||
704 | value = 0x0C; | ||
705 | break; | ||
706 | case 30: | ||
707 | value = 0x08; | ||
708 | break; | ||
709 | default: | ||
710 | printk(KERN_WARNING "viafb_set_primary_color_depth: " | ||
711 | "Unsupported depth: %d\n", depth); | ||
712 | return; | ||
713 | } | ||
714 | |||
715 | viafb_write_reg_mask(0x15, VIASR, value, 0x1C); | ||
716 | } | ||
717 | |||
718 | void viafb_set_secondary_color_depth(u8 depth) | ||
719 | { | ||
720 | u8 value; | ||
721 | |||
722 | DEBUG_MSG(KERN_DEBUG "viafb_set_secondary_color_depth(%d)\n", depth); | ||
723 | switch (depth) { | ||
724 | case 8: | ||
725 | value = 0x00; | ||
726 | break; | ||
727 | case 16: | ||
728 | value = 0x40; | ||
729 | break; | ||
730 | case 24: | ||
731 | value = 0xC0; | ||
732 | break; | ||
733 | case 30: | ||
734 | value = 0x80; | ||
735 | break; | ||
736 | default: | ||
737 | printk(KERN_WARNING "viafb_set_secondary_color_depth: " | ||
738 | "Unsupported depth: %d\n", depth); | ||
739 | return; | ||
740 | } | ||
741 | |||
742 | viafb_write_reg_mask(0x67, VIACR, value, 0xC0); | ||
743 | } | ||
744 | |||
745 | static void set_color_register(u8 index, u8 red, u8 green, u8 blue) | 628 | static void set_color_register(u8 index, u8 red, u8 green, u8 blue) |
746 | { | 629 | { |
747 | outb(0xFF, 0x3C6); /* bit mask of palette */ | 630 | outb(0xFF, 0x3C6); /* bit mask of palette */ |
@@ -1126,16 +1009,12 @@ void viafb_load_reg(int timing_value, int viafb_load_reg_num, | |||
1126 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum) | 1009 | void viafb_write_regx(struct io_reg RegTable[], int ItemNum) |
1127 | { | 1010 | { |
1128 | int i; | 1011 | int i; |
1129 | unsigned char RegTemp; | ||
1130 | 1012 | ||
1131 | /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */ | 1013 | /*DEBUG_MSG(KERN_INFO "Table Size : %x!!\n",ItemNum ); */ |
1132 | 1014 | ||
1133 | for (i = 0; i < ItemNum; i++) { | 1015 | for (i = 0; i < ItemNum; i++) |
1134 | outb(RegTable[i].index, RegTable[i].port); | 1016 | via_write_reg_mask(RegTable[i].port, RegTable[i].index, |
1135 | RegTemp = inb(RegTable[i].port + 1); | 1017 | RegTable[i].value, RegTable[i].mask); |
1136 | RegTemp = (RegTemp & (~RegTable[i].mask)) | RegTable[i].value; | ||
1137 | outb(RegTemp, RegTable[i].port + 1); | ||
1138 | } | ||
1139 | } | 1018 | } |
1140 | 1019 | ||
1141 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) | 1020 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) |
@@ -1516,8 +1395,6 @@ u32 viafb_get_clk_value(int clk) | |||
1516 | /* Set VCLK*/ | 1395 | /* Set VCLK*/ |
1517 | void viafb_set_vclock(u32 CLK, int set_iga) | 1396 | void viafb_set_vclock(u32 CLK, int set_iga) |
1518 | { | 1397 | { |
1519 | unsigned char RegTemp; | ||
1520 | |||
1521 | /* H.W. Reset : ON */ | 1398 | /* H.W. Reset : ON */ |
1522 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | 1399 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); |
1523 | 1400 | ||
@@ -1590,8 +1467,7 @@ void viafb_set_vclock(u32 CLK, int set_iga) | |||
1590 | } | 1467 | } |
1591 | 1468 | ||
1592 | /* Fire! */ | 1469 | /* Fire! */ |
1593 | RegTemp = inb(VIARMisc); | 1470 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ |
1594 | outb(RegTemp | (BIT2 + BIT3), VIAWMisc); | ||
1595 | } | 1471 | } |
1596 | 1472 | ||
1597 | void viafb_load_crtc_timing(struct display_timing device_timing, | 1473 | void viafb_load_crtc_timing(struct display_timing device_timing, |
@@ -1835,6 +1711,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | |||
1835 | int index = 0; | 1711 | int index = 0; |
1836 | int h_addr, v_addr; | 1712 | int h_addr, v_addr; |
1837 | u32 pll_D_N; | 1713 | u32 pll_D_N; |
1714 | u8 polarity = 0; | ||
1838 | 1715 | ||
1839 | for (i = 0; i < video_mode->mode_array; i++) { | 1716 | for (i = 0; i < video_mode->mode_array; i++) { |
1840 | index = i; | 1717 | index = i; |
@@ -1863,20 +1740,11 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | |||
1863 | v_addr = crt_reg.ver_addr; | 1740 | v_addr = crt_reg.ver_addr; |
1864 | 1741 | ||
1865 | /* update polarity for CRT timing */ | 1742 | /* update polarity for CRT timing */ |
1866 | if (crt_table[index].h_sync_polarity == NEGATIVE) { | 1743 | if (crt_table[index].h_sync_polarity == NEGATIVE) |
1867 | if (crt_table[index].v_sync_polarity == NEGATIVE) | 1744 | polarity |= BIT6; |
1868 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | | 1745 | if (crt_table[index].v_sync_polarity == NEGATIVE) |
1869 | (BIT6 + BIT7), VIAWMisc); | 1746 | polarity |= BIT7; |
1870 | else | 1747 | via_write_misc_reg_mask(polarity, BIT6 | BIT7); |
1871 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT6), | ||
1872 | VIAWMisc); | ||
1873 | } else { | ||
1874 | if (crt_table[index].v_sync_polarity == NEGATIVE) | ||
1875 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))) | (BIT7), | ||
1876 | VIAWMisc); | ||
1877 | else | ||
1878 | outb((inb(VIARMisc) & (~(BIT6 + BIT7))), VIAWMisc); | ||
1879 | } | ||
1880 | 1748 | ||
1881 | if (set_iga == IGA1) { | 1749 | if (set_iga == IGA1) { |
1882 | viafb_unlock_crt(); | 1750 | viafb_unlock_crt(); |
@@ -1910,10 +1778,9 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | |||
1910 | 1778 | ||
1911 | } | 1779 | } |
1912 | 1780 | ||
1913 | void viafb_init_chip_info(struct pci_dev *pdev, | 1781 | void viafb_init_chip_info(int chip_type) |
1914 | const struct pci_device_id *pdi) | ||
1915 | { | 1782 | { |
1916 | init_gfx_chip_info(pdev, pdi); | 1783 | init_gfx_chip_info(chip_type); |
1917 | init_tmds_chip_info(); | 1784 | init_tmds_chip_info(); |
1918 | init_lvds_chip_info(); | 1785 | init_lvds_chip_info(); |
1919 | 1786 | ||
@@ -1980,12 +1847,11 @@ void viafb_update_device_setting(int hres, int vres, | |||
1980 | } | 1847 | } |
1981 | } | 1848 | } |
1982 | 1849 | ||
1983 | static void init_gfx_chip_info(struct pci_dev *pdev, | 1850 | static void init_gfx_chip_info(int chip_type) |
1984 | const struct pci_device_id *pdi) | ||
1985 | { | 1851 | { |
1986 | u8 tmp; | 1852 | u8 tmp; |
1987 | 1853 | ||
1988 | viaparinfo->chip_info->gfx_chip_name = pdi->driver_data; | 1854 | viaparinfo->chip_info->gfx_chip_name = chip_type; |
1989 | 1855 | ||
1990 | /* Check revision of CLE266 Chip */ | 1856 | /* Check revision of CLE266 Chip */ |
1991 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { | 1857 | if (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266) { |
@@ -2016,6 +1882,21 @@ static void init_gfx_chip_info(struct pci_dev *pdev, | |||
2016 | CX700_REVISION_700; | 1882 | CX700_REVISION_700; |
2017 | } | 1883 | } |
2018 | } | 1884 | } |
1885 | |||
1886 | /* Determine which 2D engine we have */ | ||
1887 | switch (viaparinfo->chip_info->gfx_chip_name) { | ||
1888 | case UNICHROME_VX800: | ||
1889 | case UNICHROME_VX855: | ||
1890 | viaparinfo->chip_info->twod_engine = VIA_2D_ENG_M1; | ||
1891 | break; | ||
1892 | case UNICHROME_K8M890: | ||
1893 | case UNICHROME_P4M900: | ||
1894 | viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H5; | ||
1895 | break; | ||
1896 | default: | ||
1897 | viaparinfo->chip_info->twod_engine = VIA_2D_ENG_H2; | ||
1898 | break; | ||
1899 | } | ||
2019 | } | 1900 | } |
2020 | 1901 | ||
2021 | static void init_tmds_chip_info(void) | 1902 | static void init_tmds_chip_info(void) |
@@ -2232,13 +2113,11 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2232 | 2113 | ||
2233 | /* Fill VPIT Parameters */ | 2114 | /* Fill VPIT Parameters */ |
2234 | /* Write Misc Register */ | 2115 | /* Write Misc Register */ |
2235 | outb(VPIT.Misc, VIAWMisc); | 2116 | outb(VPIT.Misc, VIA_MISC_REG_WRITE); |
2236 | 2117 | ||
2237 | /* Write Sequencer */ | 2118 | /* Write Sequencer */ |
2238 | for (i = 1; i <= StdSR; i++) { | 2119 | for (i = 1; i <= StdSR; i++) |
2239 | outb(i, VIASR); | 2120 | via_write_reg(VIASR, i, VPIT.SR[i - 1]); |
2240 | outb(VPIT.SR[i - 1], VIASR + 1); | ||
2241 | } | ||
2242 | 2121 | ||
2243 | viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); | 2122 | viafb_write_reg_mask(0x15, VIASR, 0xA2, 0xA2); |
2244 | viafb_set_iga_path(); | 2123 | viafb_set_iga_path(); |
@@ -2247,10 +2126,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2247 | viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1); | 2126 | viafb_fill_crtc_timing(crt_timing, vmode_tbl, video_bpp / 8, IGA1); |
2248 | 2127 | ||
2249 | /* Write Graphic Controller */ | 2128 | /* Write Graphic Controller */ |
2250 | for (i = 0; i < StdGR; i++) { | 2129 | for (i = 0; i < StdGR; i++) |
2251 | outb(i, VIAGR); | 2130 | via_write_reg(VIAGR, i, VPIT.GR[i]); |
2252 | outb(VPIT.GR[i], VIAGR + 1); | ||
2253 | } | ||
2254 | 2131 | ||
2255 | /* Write Attribute Controller */ | 2132 | /* Write Attribute Controller */ |
2256 | for (i = 0; i < StdAR; i++) { | 2133 | for (i = 0; i < StdAR; i++) { |
@@ -2277,11 +2154,11 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
2277 | } | 2154 | } |
2278 | } | 2155 | } |
2279 | 2156 | ||
2280 | viafb_set_primary_pitch(viafbinfo->fix.line_length); | 2157 | via_set_primary_pitch(viafbinfo->fix.line_length); |
2281 | viafb_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length | 2158 | via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length |
2282 | : viafbinfo->fix.line_length); | 2159 | : viafbinfo->fix.line_length); |
2283 | viafb_set_primary_color_depth(viaparinfo->depth); | 2160 | via_set_primary_color_depth(viaparinfo->depth); |
2284 | viafb_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth | 2161 | via_set_secondary_color_depth(viafb_dual_fb ? viaparinfo1->depth |
2285 | : viaparinfo->depth); | 2162 | : viaparinfo->depth); |
2286 | /* Update Refresh Rate Setting */ | 2163 | /* Update Refresh Rate Setting */ |
2287 | 2164 | ||
@@ -2473,108 +2350,6 @@ static void disable_second_display_channel(void) | |||
2473 | viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); | 2350 | viafb_write_reg_mask(CR6A, VIACR, BIT6, BIT6); |
2474 | } | 2351 | } |
2475 | 2352 | ||
2476 | int viafb_get_fb_size_from_pci(void) | ||
2477 | { | ||
2478 | unsigned long configid, deviceid, FBSize = 0; | ||
2479 | int VideoMemSize; | ||
2480 | int DeviceFound = false; | ||
2481 | |||
2482 | for (configid = 0x80000000; configid < 0x80010800; configid += 0x100) { | ||
2483 | outl(configid, (unsigned long)0xCF8); | ||
2484 | deviceid = (inl((unsigned long)0xCFC) >> 16) & 0xffff; | ||
2485 | |||
2486 | switch (deviceid) { | ||
2487 | case CLE266: | ||
2488 | case KM400: | ||
2489 | outl(configid + 0xE0, (unsigned long)0xCF8); | ||
2490 | FBSize = inl((unsigned long)0xCFC); | ||
2491 | DeviceFound = true; /* Found device id */ | ||
2492 | break; | ||
2493 | |||
2494 | case CN400_FUNCTION3: | ||
2495 | case CN700_FUNCTION3: | ||
2496 | case CX700_FUNCTION3: | ||
2497 | case KM800_FUNCTION3: | ||
2498 | case KM890_FUNCTION3: | ||
2499 | case P4M890_FUNCTION3: | ||
2500 | case P4M900_FUNCTION3: | ||
2501 | case VX800_FUNCTION3: | ||
2502 | case VX855_FUNCTION3: | ||
2503 | /*case CN750_FUNCTION3: */ | ||
2504 | outl(configid + 0xA0, (unsigned long)0xCF8); | ||
2505 | FBSize = inl((unsigned long)0xCFC); | ||
2506 | DeviceFound = true; /* Found device id */ | ||
2507 | break; | ||
2508 | |||
2509 | default: | ||
2510 | break; | ||
2511 | } | ||
2512 | |||
2513 | if (DeviceFound) | ||
2514 | break; | ||
2515 | } | ||
2516 | |||
2517 | DEBUG_MSG(KERN_INFO "Device ID = %lx\n", deviceid); | ||
2518 | |||
2519 | FBSize = FBSize & 0x00007000; | ||
2520 | DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); | ||
2521 | |||
2522 | if (viaparinfo->chip_info->gfx_chip_name < UNICHROME_CX700) { | ||
2523 | switch (FBSize) { | ||
2524 | case 0x00004000: | ||
2525 | VideoMemSize = (16 << 20); /*16M */ | ||
2526 | break; | ||
2527 | |||
2528 | case 0x00005000: | ||
2529 | VideoMemSize = (32 << 20); /*32M */ | ||
2530 | break; | ||
2531 | |||
2532 | case 0x00006000: | ||
2533 | VideoMemSize = (64 << 20); /*64M */ | ||
2534 | break; | ||
2535 | |||
2536 | default: | ||
2537 | VideoMemSize = (32 << 20); /*32M */ | ||
2538 | break; | ||
2539 | } | ||
2540 | } else { | ||
2541 | switch (FBSize) { | ||
2542 | case 0x00001000: | ||
2543 | VideoMemSize = (8 << 20); /*8M */ | ||
2544 | break; | ||
2545 | |||
2546 | case 0x00002000: | ||
2547 | VideoMemSize = (16 << 20); /*16M */ | ||
2548 | break; | ||
2549 | |||
2550 | case 0x00003000: | ||
2551 | VideoMemSize = (32 << 20); /*32M */ | ||
2552 | break; | ||
2553 | |||
2554 | case 0x00004000: | ||
2555 | VideoMemSize = (64 << 20); /*64M */ | ||
2556 | break; | ||
2557 | |||
2558 | case 0x00005000: | ||
2559 | VideoMemSize = (128 << 20); /*128M */ | ||
2560 | break; | ||
2561 | |||
2562 | case 0x00006000: | ||
2563 | VideoMemSize = (256 << 20); /*256M */ | ||
2564 | break; | ||
2565 | |||
2566 | case 0x00007000: /* Only on VX855/875 */ | ||
2567 | VideoMemSize = (512 << 20); /*512M */ | ||
2568 | break; | ||
2569 | |||
2570 | default: | ||
2571 | VideoMemSize = (32 << 20); /*32M */ | ||
2572 | break; | ||
2573 | } | ||
2574 | } | ||
2575 | |||
2576 | return VideoMemSize; | ||
2577 | } | ||
2578 | 2353 | ||
2579 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | 2354 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ |
2580 | *p_gfx_dpa_setting) | 2355 | *p_gfx_dpa_setting) |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index 12ef32d334cb..a109de379816 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
@@ -24,6 +24,11 @@ | |||
24 | 24 | ||
25 | #include "viamode.h" | 25 | #include "viamode.h" |
26 | #include "global.h" | 26 | #include "global.h" |
27 | #include "via_modesetting.h" | ||
28 | |||
29 | #define viafb_read_reg(p, i) via_read_reg(p, i) | ||
30 | #define viafb_write_reg(i, p, d) via_write_reg(p, i, d) | ||
31 | #define viafb_write_reg_mask(i, p, d, m) via_write_reg_mask(p, i, d, m) | ||
27 | 32 | ||
28 | /*************************************************** | 33 | /*************************************************** |
29 | * Definition IGA1 Design Method of CRTC Registers * | 34 | * Definition IGA1 Design Method of CRTC Registers * |
@@ -823,8 +828,8 @@ struct iga2_crtc_timing { | |||
823 | }; | 828 | }; |
824 | 829 | ||
825 | /* device ID */ | 830 | /* device ID */ |
826 | #define CLE266 0x3123 | 831 | #define CLE266_FUNCTION3 0x3123 |
827 | #define KM400 0x3205 | 832 | #define KM400_FUNCTION3 0x3205 |
828 | #define CN400_FUNCTION2 0x2259 | 833 | #define CN400_FUNCTION2 0x2259 |
829 | #define CN400_FUNCTION3 0x3259 | 834 | #define CN400_FUNCTION3 0x3259 |
830 | /* support VT3314 chipset */ | 835 | /* support VT3314 chipset */ |
@@ -870,7 +875,6 @@ extern int viafb_LCD_ON; | |||
870 | extern int viafb_DVI_ON; | 875 | extern int viafb_DVI_ON; |
871 | extern int viafb_hotplug; | 876 | extern int viafb_hotplug; |
872 | 877 | ||
873 | void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask); | ||
874 | void viafb_set_output_path(int device, int set_iga, | 878 | void viafb_set_output_path(int device, int set_iga, |
875 | int output_interface); | 879 | int output_interface); |
876 | 880 | ||
@@ -885,8 +889,6 @@ void viafb_crt_disable(void); | |||
885 | void viafb_crt_enable(void); | 889 | void viafb_crt_enable(void); |
886 | void init_ad9389(void); | 890 | void init_ad9389(void); |
887 | /* Access I/O Function */ | 891 | /* Access I/O Function */ |
888 | void viafb_write_reg(u8 index, u16 io_port, u8 data); | ||
889 | u8 viafb_read_reg(int io_port, u8 index); | ||
890 | void viafb_lock_crt(void); | 892 | void viafb_lock_crt(void); |
891 | void viafb_unlock_crt(void); | 893 | void viafb_unlock_crt(void); |
892 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); | 894 | void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); |
@@ -900,20 +902,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
900 | struct VideoModeTable *vmode_tbl1, int video_bpp1); | 902 | struct VideoModeTable *vmode_tbl1, int video_bpp1); |
901 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 903 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, |
902 | struct VideoModeTable *vmode_tbl); | 904 | struct VideoModeTable *vmode_tbl); |
903 | void viafb_init_chip_info(struct pci_dev *pdev, | 905 | void viafb_init_chip_info(int chip_type); |
904 | const struct pci_device_id *pdi); | ||
905 | void viafb_init_dac(int set_iga); | 906 | void viafb_init_dac(int set_iga); |
906 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); | 907 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); |
907 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); | 908 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); |
908 | void viafb_update_device_setting(int hres, int vres, int bpp, | 909 | void viafb_update_device_setting(int hres, int vres, int bpp, |
909 | int vmode_refresh, int flag); | 910 | int vmode_refresh, int flag); |
910 | 911 | ||
911 | int viafb_get_fb_size_from_pci(void); | ||
912 | void viafb_set_iga_path(void); | 912 | void viafb_set_iga_path(void); |
913 | void viafb_set_primary_address(u32 addr); | ||
914 | void viafb_set_secondary_address(u32 addr); | ||
915 | void viafb_set_primary_pitch(u32 pitch); | ||
916 | void viafb_set_secondary_pitch(u32 pitch); | ||
917 | void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); | 913 | void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); |
918 | void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); | 914 | void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); |
919 | void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); | 915 | void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); |
diff --git a/drivers/video/via/ioctl.h b/drivers/video/via/ioctl.h index de899807eade..c430fa23008a 100644 --- a/drivers/video/via/ioctl.h +++ b/drivers/video/via/ioctl.h | |||
@@ -75,7 +75,7 @@ | |||
75 | /*SAMM operation flag*/ | 75 | /*SAMM operation flag*/ |
76 | #define OP_SAMM 0x80 | 76 | #define OP_SAMM 0x80 |
77 | 77 | ||
78 | #define LCD_PANEL_ID_MAXIMUM 22 | 78 | #define LCD_PANEL_ID_MAXIMUM 23 |
79 | 79 | ||
80 | #define STATE_ON 0x1 | 80 | #define STATE_ON 0x1 |
81 | #define STATE_OFF 0x0 | 81 | #define STATE_OFF 0x0 |
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 1b1ccdc2d83d..2ab0f156439a 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c | |||
@@ -18,7 +18,8 @@ | |||
18 | * Foundation, Inc., | 18 | * Foundation, Inc., |
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | #include <linux/via-core.h> | |
22 | #include <linux/via_i2c.h> | ||
22 | #include "global.h" | 23 | #include "global.h" |
23 | #include "lcdtbl.h" | 24 | #include "lcdtbl.h" |
24 | 25 | ||
@@ -172,18 +173,16 @@ static bool lvds_identify_integratedlvds(void) | |||
172 | 173 | ||
173 | int viafb_lvds_trasmitter_identify(void) | 174 | int viafb_lvds_trasmitter_identify(void) |
174 | { | 175 | { |
175 | viaparinfo->shared->i2c_stuff.i2c_port = I2CPORTINDEX; | 176 | if (viafb_lvds_identify_vt1636(VIA_PORT_31)) { |
176 | if (viafb_lvds_identify_vt1636()) { | 177 | viaparinfo->chip_info->lvds_chip_info.i2c_port = VIA_PORT_31; |
177 | viaparinfo->chip_info->lvds_chip_info.i2c_port = I2CPORTINDEX; | ||
178 | DEBUG_MSG(KERN_INFO | 178 | DEBUG_MSG(KERN_INFO |
179 | "Found VIA VT1636 LVDS on port i2c 0x31 \n"); | 179 | "Found VIA VT1636 LVDS on port i2c 0x31\n"); |
180 | } else { | 180 | } else { |
181 | viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX; | 181 | if (viafb_lvds_identify_vt1636(VIA_PORT_2C)) { |
182 | if (viafb_lvds_identify_vt1636()) { | ||
183 | viaparinfo->chip_info->lvds_chip_info.i2c_port = | 182 | viaparinfo->chip_info->lvds_chip_info.i2c_port = |
184 | GPIOPORTINDEX; | 183 | VIA_PORT_2C; |
185 | DEBUG_MSG(KERN_INFO | 184 | DEBUG_MSG(KERN_INFO |
186 | "Found VIA VT1636 LVDS on port gpio 0x2c \n"); | 185 | "Found VIA VT1636 LVDS on port gpio 0x2c\n"); |
187 | } | 186 | } |
188 | } | 187 | } |
189 | 188 | ||
@@ -398,6 +397,15 @@ static void fp_id_to_vindex(int panel_id) | |||
398 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | 397 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; |
399 | viaparinfo->lvds_setting_info->LCDDithering = 1; | 398 | viaparinfo->lvds_setting_info->LCDDithering = 1; |
400 | break; | 399 | break; |
400 | case 0x17: | ||
401 | /* OLPC XO-1.5 panel */ | ||
402 | viaparinfo->lvds_setting_info->lcd_panel_hres = 1200; | ||
403 | viaparinfo->lvds_setting_info->lcd_panel_vres = 900; | ||
404 | viaparinfo->lvds_setting_info->lcd_panel_id = | ||
405 | LCD_PANEL_IDD_1200X900; | ||
406 | viaparinfo->lvds_setting_info->device_lcd_dualedge = 0; | ||
407 | viaparinfo->lvds_setting_info->LCDDithering = 0; | ||
408 | break; | ||
401 | default: | 409 | default: |
402 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; | 410 | viaparinfo->lvds_setting_info->lcd_panel_hres = 800; |
403 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; | 411 | viaparinfo->lvds_setting_info->lcd_panel_vres = 600; |
@@ -412,9 +420,8 @@ static int lvds_register_read(int index) | |||
412 | { | 420 | { |
413 | u8 data; | 421 | u8 data; |
414 | 422 | ||
415 | viaparinfo->shared->i2c_stuff.i2c_port = GPIOPORTINDEX; | 423 | viafb_i2c_readbyte(VIA_PORT_2C, |
416 | viafb_i2c_readbyte((u8) viaparinfo->chip_info-> | 424 | (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, |
417 | lvds_chip_info.lvds_chip_slave_addr, | ||
418 | (u8) index, &data); | 425 | (u8) index, &data); |
419 | return data; | 426 | return data; |
420 | } | 427 | } |
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h index 071f47cf5be1..9762ec62b495 100644 --- a/drivers/video/via/lcd.h +++ b/drivers/video/via/lcd.h | |||
@@ -60,6 +60,8 @@ | |||
60 | #define LCD_PANEL_IDB_1360X768 0x0B | 60 | #define LCD_PANEL_IDB_1360X768 0x0B |
61 | /* Resolution: 480x640, Channel: single, Dithering: Enable */ | 61 | /* Resolution: 480x640, Channel: single, Dithering: Enable */ |
62 | #define LCD_PANEL_IDC_480X640 0x0C | 62 | #define LCD_PANEL_IDC_480X640 0x0C |
63 | /* Resolution: 1200x900, Channel: single, Dithering: Disable */ | ||
64 | #define LCD_PANEL_IDD_1200X900 0x0D | ||
63 | 65 | ||
64 | 66 | ||
65 | extern int viafb_LCD2_ON; | 67 | extern int viafb_LCD2_ON; |
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index d55aaa7b912c..7f0de7f006ad 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h | |||
@@ -43,16 +43,9 @@ | |||
43 | /* Video Memory Size */ | 43 | /* Video Memory Size */ |
44 | #define VIDEO_MEMORY_SIZE_16M 0x1000000 | 44 | #define VIDEO_MEMORY_SIZE_16M 0x1000000 |
45 | 45 | ||
46 | /* standard VGA IO port | 46 | /* |
47 | */ | 47 | * Lengths of the VPIT structure arrays. |
48 | #define VIARMisc 0x3CC | 48 | */ |
49 | #define VIAWMisc 0x3C2 | ||
50 | #define VIAStatus 0x3DA | ||
51 | #define VIACR 0x3D4 | ||
52 | #define VIASR 0x3C4 | ||
53 | #define VIAGR 0x3CE | ||
54 | #define VIAAR 0x3C0 | ||
55 | |||
56 | #define StdCR 0x19 | 49 | #define StdCR 0x19 |
57 | #define StdSR 0x04 | 50 | #define StdSR 0x04 |
58 | #define StdGR 0x09 | 51 | #define StdGR 0x09 |
@@ -570,6 +563,10 @@ | |||
570 | #define M1200X720_R60_HSP NEGATIVE | 563 | #define M1200X720_R60_HSP NEGATIVE |
571 | #define M1200X720_R60_VSP POSITIVE | 564 | #define M1200X720_R60_VSP POSITIVE |
572 | 565 | ||
566 | /* 1200x900@60 Sync Polarity (DCON) */ | ||
567 | #define M1200X900_R60_HSP NEGATIVE | ||
568 | #define M1200X900_R60_VSP NEGATIVE | ||
569 | |||
573 | /* 1280x600@60 Sync Polarity (GTF Mode) */ | 570 | /* 1280x600@60 Sync Polarity (GTF Mode) */ |
574 | #define M1280x600_R60_HSP NEGATIVE | 571 | #define M1280x600_R60_HSP NEGATIVE |
575 | #define M1280x600_R60_VSP POSITIVE | 572 | #define M1280x600_R60_VSP POSITIVE |
@@ -651,6 +648,7 @@ | |||
651 | #define CLK_52_406M 52406000 | 648 | #define CLK_52_406M 52406000 |
652 | #define CLK_52_977M 52977000 | 649 | #define CLK_52_977M 52977000 |
653 | #define CLK_56_250M 56250000 | 650 | #define CLK_56_250M 56250000 |
651 | #define CLK_57_275M 57275000 | ||
654 | #define CLK_60_466M 60466000 | 652 | #define CLK_60_466M 60466000 |
655 | #define CLK_61_500M 61500000 | 653 | #define CLK_61_500M 61500000 |
656 | #define CLK_65_000M 65000000 | 654 | #define CLK_65_000M 65000000 |
@@ -939,6 +937,7 @@ | |||
939 | #define VX855_52_406M 0x00580C03 | 937 | #define VX855_52_406M 0x00580C03 |
940 | #define VX855_52_977M 0x00940C05 | 938 | #define VX855_52_977M 0x00940C05 |
941 | #define VX855_56_250M 0x009D0C05 | 939 | #define VX855_56_250M 0x009D0C05 |
940 | #define VX855_57_275M 0x009D8C85 /* Used by XO panel */ | ||
942 | #define VX855_60_466M 0x00A90C05 | 941 | #define VX855_60_466M 0x00A90C05 |
943 | #define VX855_61_500M 0x00AC0C05 | 942 | #define VX855_61_500M 0x00AC0C05 |
944 | #define VX855_65_000M 0x006D0C03 | 943 | #define VX855_65_000M 0x006D0C03 |
@@ -1065,6 +1064,7 @@ | |||
1065 | #define RES_1600X1200_60HZ_PIXCLOCK 6172 | 1064 | #define RES_1600X1200_60HZ_PIXCLOCK 6172 |
1066 | #define RES_1600X1200_75HZ_PIXCLOCK 4938 | 1065 | #define RES_1600X1200_75HZ_PIXCLOCK 4938 |
1067 | #define RES_1280X720_60HZ_PIXCLOCK 13426 | 1066 | #define RES_1280X720_60HZ_PIXCLOCK 13426 |
1067 | #define RES_1200X900_60HZ_PIXCLOCK 17459 | ||
1068 | #define RES_1920X1080_60HZ_PIXCLOCK 5787 | 1068 | #define RES_1920X1080_60HZ_PIXCLOCK 5787 |
1069 | #define RES_1400X1050_60HZ_PIXCLOCK 8214 | 1069 | #define RES_1400X1050_60HZ_PIXCLOCK 8214 |
1070 | #define RES_1400X1050_75HZ_PIXCLOCK 6410 | 1070 | #define RES_1400X1050_75HZ_PIXCLOCK 6410 |
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c new file mode 100644 index 000000000000..e8cfe8392110 --- /dev/null +++ b/drivers/video/via/via-core.c | |||
@@ -0,0 +1,668 @@ | |||
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 | |||
19 | /* | ||
20 | * The default port config. | ||
21 | */ | ||
22 | static struct via_port_cfg adap_configs[] = { | ||
23 | [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_OFF, VIASR, 0x26 }, | ||
24 | [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, | ||
25 | [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, | ||
26 | [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c }, | ||
27 | [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d }, | ||
28 | { 0, 0, 0, 0 } | ||
29 | }; | ||
30 | |||
31 | /* | ||
32 | * We currently only support one viafb device (will there ever be | ||
33 | * more than one?), so just declare it globally here. | ||
34 | */ | ||
35 | static struct viafb_dev global_dev; | ||
36 | |||
37 | |||
38 | /* | ||
39 | * Basic register access; spinlock required. | ||
40 | */ | ||
41 | static inline void viafb_mmio_write(int reg, u32 v) | ||
42 | { | ||
43 | iowrite32(v, global_dev.engine_mmio + reg); | ||
44 | } | ||
45 | |||
46 | static inline int viafb_mmio_read(int reg) | ||
47 | { | ||
48 | return ioread32(global_dev.engine_mmio + reg); | ||
49 | } | ||
50 | |||
51 | /* ---------------------------------------------------------------------- */ | ||
52 | /* | ||
53 | * Interrupt management. We have a single IRQ line for a lot of | ||
54 | * different functions, so we need to share it. The design here | ||
55 | * is that we don't want to reimplement the shared IRQ code here; | ||
56 | * we also want to avoid having contention for a single handler thread. | ||
57 | * So each subdev driver which needs interrupts just requests | ||
58 | * them directly from the kernel. We just have what's needed for | ||
59 | * overall access to the interrupt control register. | ||
60 | */ | ||
61 | |||
62 | /* | ||
63 | * Which interrupts are enabled now? | ||
64 | */ | ||
65 | static u32 viafb_enabled_ints; | ||
66 | |||
67 | static void viafb_int_init(void) | ||
68 | { | ||
69 | viafb_enabled_ints = 0; | ||
70 | |||
71 | viafb_mmio_write(VDE_INTERRUPT, 0); | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | * Allow subdevs to ask for specific interrupts to be enabled. These | ||
76 | * functions must be called with reg_lock held | ||
77 | */ | ||
78 | void viafb_irq_enable(u32 mask) | ||
79 | { | ||
80 | viafb_enabled_ints |= mask; | ||
81 | viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE); | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(viafb_irq_enable); | ||
84 | |||
85 | void viafb_irq_disable(u32 mask) | ||
86 | { | ||
87 | viafb_enabled_ints &= ~mask; | ||
88 | if (viafb_enabled_ints == 0) | ||
89 | viafb_mmio_write(VDE_INTERRUPT, 0); /* Disable entirely */ | ||
90 | else | ||
91 | viafb_mmio_write(VDE_INTERRUPT, | ||
92 | viafb_enabled_ints | VDE_I_ENABLE); | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(viafb_irq_disable); | ||
95 | |||
96 | /* ---------------------------------------------------------------------- */ | ||
97 | /* | ||
98 | * Access to the DMA engine. This currently provides what the camera | ||
99 | * driver needs (i.e. outgoing only) but is easily expandable if need | ||
100 | * be. | ||
101 | */ | ||
102 | |||
103 | /* | ||
104 | * There are four DMA channels in the vx855. For now, we only | ||
105 | * use one of them, though. Most of the time, the DMA channel | ||
106 | * will be idle, so we keep the IRQ handler unregistered except | ||
107 | * when some subsystem has indicated an interest. | ||
108 | */ | ||
109 | static int viafb_dma_users; | ||
110 | static DECLARE_COMPLETION(viafb_dma_completion); | ||
111 | /* | ||
112 | * This mutex protects viafb_dma_users and our global interrupt | ||
113 | * registration state; it also serializes access to the DMA | ||
114 | * engine. | ||
115 | */ | ||
116 | static DEFINE_MUTEX(viafb_dma_lock); | ||
117 | |||
118 | /* | ||
119 | * The VX855 DMA descriptor (used for s/g transfers) looks | ||
120 | * like this. | ||
121 | */ | ||
122 | struct viafb_vx855_dma_descr { | ||
123 | u32 addr_low; /* Low part of phys addr */ | ||
124 | u32 addr_high; /* High 12 bits of addr */ | ||
125 | u32 fb_offset; /* Offset into FB memory */ | ||
126 | u32 seg_size; /* Size, 16-byte units */ | ||
127 | u32 tile_mode; /* "tile mode" setting */ | ||
128 | u32 next_desc_low; /* Next descriptor addr */ | ||
129 | u32 next_desc_high; | ||
130 | u32 pad; /* Fill out to 64 bytes */ | ||
131 | }; | ||
132 | |||
133 | /* | ||
134 | * Flags added to the "next descriptor low" pointers | ||
135 | */ | ||
136 | #define VIAFB_DMA_MAGIC 0x01 /* ??? Just has to be there */ | ||
137 | #define VIAFB_DMA_FINAL_SEGMENT 0x02 /* Final segment */ | ||
138 | |||
139 | /* | ||
140 | * The completion IRQ handler. | ||
141 | */ | ||
142 | static irqreturn_t viafb_dma_irq(int irq, void *data) | ||
143 | { | ||
144 | int csr; | ||
145 | irqreturn_t ret = IRQ_NONE; | ||
146 | |||
147 | spin_lock(&global_dev.reg_lock); | ||
148 | csr = viafb_mmio_read(VDMA_CSR0); | ||
149 | if (csr & VDMA_C_DONE) { | ||
150 | viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE); | ||
151 | complete(&viafb_dma_completion); | ||
152 | ret = IRQ_HANDLED; | ||
153 | } | ||
154 | spin_unlock(&global_dev.reg_lock); | ||
155 | return ret; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Indicate a need for DMA functionality. | ||
160 | */ | ||
161 | int viafb_request_dma(void) | ||
162 | { | ||
163 | int ret = 0; | ||
164 | |||
165 | /* | ||
166 | * Only VX855 is supported currently. | ||
167 | */ | ||
168 | if (global_dev.chip_type != UNICHROME_VX855) | ||
169 | return -ENODEV; | ||
170 | /* | ||
171 | * Note the new user and set up our interrupt handler | ||
172 | * if need be. | ||
173 | */ | ||
174 | mutex_lock(&viafb_dma_lock); | ||
175 | viafb_dma_users++; | ||
176 | if (viafb_dma_users == 1) { | ||
177 | ret = request_irq(global_dev.pdev->irq, viafb_dma_irq, | ||
178 | IRQF_SHARED, "via-dma", &viafb_dma_users); | ||
179 | if (ret) | ||
180 | viafb_dma_users--; | ||
181 | else | ||
182 | viafb_irq_enable(VDE_I_DMA0TDEN); | ||
183 | } | ||
184 | mutex_unlock(&viafb_dma_lock); | ||
185 | return ret; | ||
186 | } | ||
187 | EXPORT_SYMBOL_GPL(viafb_request_dma); | ||
188 | |||
189 | void viafb_release_dma(void) | ||
190 | { | ||
191 | mutex_lock(&viafb_dma_lock); | ||
192 | viafb_dma_users--; | ||
193 | if (viafb_dma_users == 0) { | ||
194 | viafb_irq_disable(VDE_I_DMA0TDEN); | ||
195 | free_irq(global_dev.pdev->irq, &viafb_dma_users); | ||
196 | } | ||
197 | mutex_unlock(&viafb_dma_lock); | ||
198 | } | ||
199 | EXPORT_SYMBOL_GPL(viafb_release_dma); | ||
200 | |||
201 | |||
202 | #if 0 | ||
203 | /* | ||
204 | * Copy a single buffer from FB memory, synchronously. This code works | ||
205 | * but is not currently used. | ||
206 | */ | ||
207 | void viafb_dma_copy_out(unsigned int offset, dma_addr_t paddr, int len) | ||
208 | { | ||
209 | unsigned long flags; | ||
210 | int csr; | ||
211 | |||
212 | mutex_lock(&viafb_dma_lock); | ||
213 | init_completion(&viafb_dma_completion); | ||
214 | /* | ||
215 | * Program the controller. | ||
216 | */ | ||
217 | spin_lock_irqsave(&global_dev.reg_lock, flags); | ||
218 | viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE); | ||
219 | /* Enable ints; must happen after CSR0 write! */ | ||
220 | viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE); | ||
221 | viafb_mmio_write(VDMA_MARL0, (int) (paddr & 0xfffffff0)); | ||
222 | viafb_mmio_write(VDMA_MARH0, (int) ((paddr >> 28) & 0xfff)); | ||
223 | /* Data sheet suggests DAR0 should be <<4, but it lies */ | ||
224 | viafb_mmio_write(VDMA_DAR0, offset); | ||
225 | viafb_mmio_write(VDMA_DQWCR0, len >> 4); | ||
226 | viafb_mmio_write(VDMA_TMR0, 0); | ||
227 | viafb_mmio_write(VDMA_DPRL0, 0); | ||
228 | viafb_mmio_write(VDMA_DPRH0, 0); | ||
229 | viafb_mmio_write(VDMA_PMR0, 0); | ||
230 | csr = viafb_mmio_read(VDMA_CSR0); | ||
231 | viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START); | ||
232 | spin_unlock_irqrestore(&global_dev.reg_lock, flags); | ||
233 | /* | ||
234 | * Now we just wait until the interrupt handler says | ||
235 | * we're done. | ||
236 | */ | ||
237 | wait_for_completion_interruptible(&viafb_dma_completion); | ||
238 | viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */ | ||
239 | mutex_unlock(&viafb_dma_lock); | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(viafb_dma_copy_out); | ||
242 | #endif | ||
243 | |||
244 | /* | ||
245 | * Do a scatter/gather DMA copy from FB memory. You must have done | ||
246 | * a successful call to viafb_request_dma() first. | ||
247 | */ | ||
248 | int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg) | ||
249 | { | ||
250 | struct viafb_vx855_dma_descr *descr; | ||
251 | void *descrpages; | ||
252 | dma_addr_t descr_handle; | ||
253 | unsigned long flags; | ||
254 | int i; | ||
255 | struct scatterlist *sgentry; | ||
256 | dma_addr_t nextdesc; | ||
257 | |||
258 | /* | ||
259 | * Get a place to put the descriptors. | ||
260 | */ | ||
261 | descrpages = dma_alloc_coherent(&global_dev.pdev->dev, | ||
262 | nsg*sizeof(struct viafb_vx855_dma_descr), | ||
263 | &descr_handle, GFP_KERNEL); | ||
264 | if (descrpages == NULL) { | ||
265 | dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n"); | ||
266 | return -ENOMEM; | ||
267 | } | ||
268 | mutex_lock(&viafb_dma_lock); | ||
269 | /* | ||
270 | * Fill them in. | ||
271 | */ | ||
272 | descr = descrpages; | ||
273 | nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr); | ||
274 | for_each_sg(sg, sgentry, nsg, i) { | ||
275 | dma_addr_t paddr = sg_dma_address(sgentry); | ||
276 | descr->addr_low = paddr & 0xfffffff0; | ||
277 | descr->addr_high = ((u64) paddr >> 32) & 0x0fff; | ||
278 | descr->fb_offset = offset; | ||
279 | descr->seg_size = sg_dma_len(sgentry) >> 4; | ||
280 | descr->tile_mode = 0; | ||
281 | descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC; | ||
282 | descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff; | ||
283 | descr->pad = 0xffffffff; /* VIA driver does this */ | ||
284 | offset += sg_dma_len(sgentry); | ||
285 | nextdesc += sizeof(struct viafb_vx855_dma_descr); | ||
286 | descr++; | ||
287 | } | ||
288 | descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC; | ||
289 | /* | ||
290 | * Program the engine. | ||
291 | */ | ||
292 | spin_lock_irqsave(&global_dev.reg_lock, flags); | ||
293 | init_completion(&viafb_dma_completion); | ||
294 | viafb_mmio_write(VDMA_DQWCR0, 0); | ||
295 | viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE); | ||
296 | viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN); | ||
297 | viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC); | ||
298 | viafb_mmio_write(VDMA_DPRH0, | ||
299 | (((u64)descr_handle >> 32) & 0x0fff) | 0xf0000); | ||
300 | (void) viafb_mmio_read(VDMA_CSR0); | ||
301 | viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START); | ||
302 | spin_unlock_irqrestore(&global_dev.reg_lock, flags); | ||
303 | /* | ||
304 | * Now we just wait until the interrupt handler says | ||
305 | * we're done. Except that, actually, we need to wait a little | ||
306 | * longer: the interrupts seem to jump the gun a little and we | ||
307 | * get corrupted frames sometimes. | ||
308 | */ | ||
309 | wait_for_completion_timeout(&viafb_dma_completion, 1); | ||
310 | msleep(1); | ||
311 | if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0) | ||
312 | printk(KERN_ERR "VIA DMA timeout!\n"); | ||
313 | /* | ||
314 | * Clean up and we're done. | ||
315 | */ | ||
316 | viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE); | ||
317 | viafb_mmio_write(VDMA_MR0, 0); /* Reset int enable */ | ||
318 | mutex_unlock(&viafb_dma_lock); | ||
319 | dma_free_coherent(&global_dev.pdev->dev, | ||
320 | nsg*sizeof(struct viafb_vx855_dma_descr), descrpages, | ||
321 | descr_handle); | ||
322 | return 0; | ||
323 | } | ||
324 | EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg); | ||
325 | |||
326 | |||
327 | /* ---------------------------------------------------------------------- */ | ||
328 | /* | ||
329 | * Figure out how big our framebuffer memory is. Kind of ugly, | ||
330 | * but evidently we can't trust the information found in the | ||
331 | * fbdev configuration area. | ||
332 | */ | ||
333 | static u16 via_function3[] = { | ||
334 | CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3, | ||
335 | CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3, | ||
336 | P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, | ||
337 | }; | ||
338 | |||
339 | /* Get the BIOS-configured framebuffer size from PCI configuration space | ||
340 | * of function 3 in the respective chipset */ | ||
341 | static int viafb_get_fb_size_from_pci(int chip_type) | ||
342 | { | ||
343 | int i; | ||
344 | u8 offset = 0; | ||
345 | u32 FBSize; | ||
346 | u32 VideoMemSize; | ||
347 | |||
348 | /* search for the "FUNCTION3" device in this chipset */ | ||
349 | for (i = 0; i < ARRAY_SIZE(via_function3); i++) { | ||
350 | struct pci_dev *pdev; | ||
351 | |||
352 | pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i], | ||
353 | NULL); | ||
354 | if (!pdev) | ||
355 | continue; | ||
356 | |||
357 | DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device); | ||
358 | |||
359 | switch (pdev->device) { | ||
360 | case CLE266_FUNCTION3: | ||
361 | case KM400_FUNCTION3: | ||
362 | offset = 0xE0; | ||
363 | break; | ||
364 | case CN400_FUNCTION3: | ||
365 | case CN700_FUNCTION3: | ||
366 | case CX700_FUNCTION3: | ||
367 | case KM800_FUNCTION3: | ||
368 | case KM890_FUNCTION3: | ||
369 | case P4M890_FUNCTION3: | ||
370 | case P4M900_FUNCTION3: | ||
371 | case VX800_FUNCTION3: | ||
372 | case VX855_FUNCTION3: | ||
373 | /*case CN750_FUNCTION3: */ | ||
374 | offset = 0xA0; | ||
375 | break; | ||
376 | } | ||
377 | |||
378 | if (!offset) | ||
379 | break; | ||
380 | |||
381 | pci_read_config_dword(pdev, offset, &FBSize); | ||
382 | pci_dev_put(pdev); | ||
383 | } | ||
384 | |||
385 | if (!offset) { | ||
386 | printk(KERN_ERR "cannot determine framebuffer size\n"); | ||
387 | return -EIO; | ||
388 | } | ||
389 | |||
390 | FBSize = FBSize & 0x00007000; | ||
391 | DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize); | ||
392 | |||
393 | if (chip_type < UNICHROME_CX700) { | ||
394 | switch (FBSize) { | ||
395 | case 0x00004000: | ||
396 | VideoMemSize = (16 << 20); /*16M */ | ||
397 | break; | ||
398 | |||
399 | case 0x00005000: | ||
400 | VideoMemSize = (32 << 20); /*32M */ | ||
401 | break; | ||
402 | |||
403 | case 0x00006000: | ||
404 | VideoMemSize = (64 << 20); /*64M */ | ||
405 | break; | ||
406 | |||
407 | default: | ||
408 | VideoMemSize = (32 << 20); /*32M */ | ||
409 | break; | ||
410 | } | ||
411 | } else { | ||
412 | switch (FBSize) { | ||
413 | case 0x00001000: | ||
414 | VideoMemSize = (8 << 20); /*8M */ | ||
415 | break; | ||
416 | |||
417 | case 0x00002000: | ||
418 | VideoMemSize = (16 << 20); /*16M */ | ||
419 | break; | ||
420 | |||
421 | case 0x00003000: | ||
422 | VideoMemSize = (32 << 20); /*32M */ | ||
423 | break; | ||
424 | |||
425 | case 0x00004000: | ||
426 | VideoMemSize = (64 << 20); /*64M */ | ||
427 | break; | ||
428 | |||
429 | case 0x00005000: | ||
430 | VideoMemSize = (128 << 20); /*128M */ | ||
431 | break; | ||
432 | |||
433 | case 0x00006000: | ||
434 | VideoMemSize = (256 << 20); /*256M */ | ||
435 | break; | ||
436 | |||
437 | case 0x00007000: /* Only on VX855/875 */ | ||
438 | VideoMemSize = (512 << 20); /*512M */ | ||
439 | break; | ||
440 | |||
441 | default: | ||
442 | VideoMemSize = (32 << 20); /*32M */ | ||
443 | break; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | return VideoMemSize; | ||
448 | } | ||
449 | |||
450 | |||
451 | /* | ||
452 | * Figure out and map our MMIO regions. | ||
453 | */ | ||
454 | static int __devinit via_pci_setup_mmio(struct viafb_dev *vdev) | ||
455 | { | ||
456 | int ret; | ||
457 | /* | ||
458 | * Hook up to the device registers. Note that we soldier | ||
459 | * on if it fails; the framebuffer can operate (without | ||
460 | * acceleration) without this region. | ||
461 | */ | ||
462 | vdev->engine_start = pci_resource_start(vdev->pdev, 1); | ||
463 | vdev->engine_len = pci_resource_len(vdev->pdev, 1); | ||
464 | vdev->engine_mmio = ioremap_nocache(vdev->engine_start, | ||
465 | vdev->engine_len); | ||
466 | if (vdev->engine_mmio == NULL) | ||
467 | dev_err(&vdev->pdev->dev, | ||
468 | "Unable to map engine MMIO; operation will be " | ||
469 | "slow and crippled.\n"); | ||
470 | /* | ||
471 | * Map in framebuffer memory. For now, failure here is | ||
472 | * fatal. Unfortunately, in the absence of significant | ||
473 | * vmalloc space, failure here is also entirely plausible. | ||
474 | * Eventually we want to move away from mapping this | ||
475 | * entire region. | ||
476 | */ | ||
477 | vdev->fbmem_start = pci_resource_start(vdev->pdev, 0); | ||
478 | ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type); | ||
479 | if (ret < 0) | ||
480 | goto out_unmap; | ||
481 | vdev->fbmem = ioremap_nocache(vdev->fbmem_start, vdev->fbmem_len); | ||
482 | if (vdev->fbmem == NULL) { | ||
483 | ret = -ENOMEM; | ||
484 | goto out_unmap; | ||
485 | } | ||
486 | return 0; | ||
487 | out_unmap: | ||
488 | iounmap(vdev->engine_mmio); | ||
489 | return ret; | ||
490 | } | ||
491 | |||
492 | static void __devexit via_pci_teardown_mmio(struct viafb_dev *vdev) | ||
493 | { | ||
494 | iounmap(vdev->fbmem); | ||
495 | iounmap(vdev->engine_mmio); | ||
496 | } | ||
497 | |||
498 | /* | ||
499 | * Create our subsidiary devices. | ||
500 | */ | ||
501 | static struct viafb_subdev_info { | ||
502 | char *name; | ||
503 | struct platform_device *platdev; | ||
504 | } viafb_subdevs[] = { | ||
505 | { | ||
506 | .name = "viafb-gpio", | ||
507 | }, | ||
508 | { | ||
509 | .name = "viafb-i2c", | ||
510 | } | ||
511 | }; | ||
512 | #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs) | ||
513 | |||
514 | static int __devinit via_create_subdev(struct viafb_dev *vdev, | ||
515 | struct viafb_subdev_info *info) | ||
516 | { | ||
517 | int ret; | ||
518 | |||
519 | info->platdev = platform_device_alloc(info->name, -1); | ||
520 | if (!info->platdev) { | ||
521 | dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n", | ||
522 | info->name); | ||
523 | return -ENOMEM; | ||
524 | } | ||
525 | info->platdev->dev.parent = &vdev->pdev->dev; | ||
526 | info->platdev->dev.platform_data = vdev; | ||
527 | ret = platform_device_add(info->platdev); | ||
528 | if (ret) { | ||
529 | dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n", | ||
530 | info->name); | ||
531 | platform_device_put(info->platdev); | ||
532 | info->platdev = NULL; | ||
533 | } | ||
534 | return ret; | ||
535 | } | ||
536 | |||
537 | static int __devinit via_setup_subdevs(struct viafb_dev *vdev) | ||
538 | { | ||
539 | int i; | ||
540 | |||
541 | /* | ||
542 | * Ignore return values. Even if some of the devices | ||
543 | * fail to be created, we'll still be able to use some | ||
544 | * of the rest. | ||
545 | */ | ||
546 | for (i = 0; i < N_SUBDEVS; i++) | ||
547 | via_create_subdev(vdev, viafb_subdevs + i); | ||
548 | return 0; | ||
549 | } | ||
550 | |||
551 | static void __devexit via_teardown_subdevs(void) | ||
552 | { | ||
553 | int i; | ||
554 | |||
555 | for (i = 0; i < N_SUBDEVS; i++) | ||
556 | if (viafb_subdevs[i].platdev) { | ||
557 | viafb_subdevs[i].platdev->dev.platform_data = NULL; | ||
558 | platform_device_unregister(viafb_subdevs[i].platdev); | ||
559 | } | ||
560 | } | ||
561 | |||
562 | |||
563 | static int __devinit via_pci_probe(struct pci_dev *pdev, | ||
564 | const struct pci_device_id *ent) | ||
565 | { | ||
566 | int ret; | ||
567 | |||
568 | ret = pci_enable_device(pdev); | ||
569 | if (ret) | ||
570 | return ret; | ||
571 | /* | ||
572 | * Global device initialization. | ||
573 | */ | ||
574 | memset(&global_dev, 0, sizeof(global_dev)); | ||
575 | global_dev.pdev = pdev; | ||
576 | global_dev.chip_type = ent->driver_data; | ||
577 | global_dev.port_cfg = adap_configs; | ||
578 | spin_lock_init(&global_dev.reg_lock); | ||
579 | ret = via_pci_setup_mmio(&global_dev); | ||
580 | if (ret) | ||
581 | goto out_disable; | ||
582 | /* | ||
583 | * Set up interrupts and create our subdevices. Continue even if | ||
584 | * some things fail. | ||
585 | */ | ||
586 | viafb_int_init(); | ||
587 | via_setup_subdevs(&global_dev); | ||
588 | /* | ||
589 | * Set up the framebuffer device | ||
590 | */ | ||
591 | ret = via_fb_pci_probe(&global_dev); | ||
592 | if (ret) | ||
593 | goto out_subdevs; | ||
594 | return 0; | ||
595 | |||
596 | out_subdevs: | ||
597 | via_teardown_subdevs(); | ||
598 | via_pci_teardown_mmio(&global_dev); | ||
599 | out_disable: | ||
600 | pci_disable_device(pdev); | ||
601 | return ret; | ||
602 | } | ||
603 | |||
604 | static void __devexit via_pci_remove(struct pci_dev *pdev) | ||
605 | { | ||
606 | via_teardown_subdevs(); | ||
607 | via_fb_pci_remove(pdev); | ||
608 | via_pci_teardown_mmio(&global_dev); | ||
609 | pci_disable_device(pdev); | ||
610 | } | ||
611 | |||
612 | |||
613 | static struct pci_device_id via_pci_table[] __devinitdata = { | ||
614 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), | ||
615 | .driver_data = UNICHROME_CLE266 }, | ||
616 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), | ||
617 | .driver_data = UNICHROME_PM800 }, | ||
618 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), | ||
619 | .driver_data = UNICHROME_K400 }, | ||
620 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), | ||
621 | .driver_data = UNICHROME_K800 }, | ||
622 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), | ||
623 | .driver_data = UNICHROME_CN700 }, | ||
624 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), | ||
625 | .driver_data = UNICHROME_K8M890 }, | ||
626 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), | ||
627 | .driver_data = UNICHROME_CX700 }, | ||
628 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), | ||
629 | .driver_data = UNICHROME_P4M900 }, | ||
630 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), | ||
631 | .driver_data = UNICHROME_CN750 }, | ||
632 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), | ||
633 | .driver_data = UNICHROME_VX800 }, | ||
634 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), | ||
635 | .driver_data = UNICHROME_VX855 }, | ||
636 | { } | ||
637 | }; | ||
638 | MODULE_DEVICE_TABLE(pci, via_pci_table); | ||
639 | |||
640 | static struct pci_driver via_driver = { | ||
641 | .name = "viafb", | ||
642 | .id_table = via_pci_table, | ||
643 | .probe = via_pci_probe, | ||
644 | .remove = __devexit_p(via_pci_remove), | ||
645 | }; | ||
646 | |||
647 | static int __init via_core_init(void) | ||
648 | { | ||
649 | int ret; | ||
650 | |||
651 | ret = viafb_init(); | ||
652 | if (ret) | ||
653 | return ret; | ||
654 | viafb_i2c_init(); | ||
655 | viafb_gpio_init(); | ||
656 | return pci_register_driver(&via_driver); | ||
657 | } | ||
658 | |||
659 | static void __exit via_core_exit(void) | ||
660 | { | ||
661 | pci_unregister_driver(&via_driver); | ||
662 | viafb_gpio_exit(); | ||
663 | viafb_i2c_exit(); | ||
664 | viafb_exit(); | ||
665 | } | ||
666 | |||
667 | module_init(via_core_init); | ||
668 | module_exit(via_core_exit); | ||
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c new file mode 100644 index 000000000000..595516aea691 --- /dev/null +++ b/drivers/video/via/via-gpio.c | |||
@@ -0,0 +1,285 @@ | |||
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 | |||
14 | /* | ||
15 | * The ports we know about. Note that the port-25 gpios are not | ||
16 | * mentioned in the datasheet. | ||
17 | */ | ||
18 | |||
19 | struct viafb_gpio { | ||
20 | char *vg_name; /* Data sheet name */ | ||
21 | u16 vg_io_port; | ||
22 | u8 vg_port_index; | ||
23 | int vg_mask_shift; | ||
24 | }; | ||
25 | |||
26 | static struct viafb_gpio viafb_all_gpios[] = { | ||
27 | { | ||
28 | .vg_name = "VGPIO0", /* Guess - not in datasheet */ | ||
29 | .vg_io_port = VIASR, | ||
30 | .vg_port_index = 0x25, | ||
31 | .vg_mask_shift = 1 | ||
32 | }, | ||
33 | { | ||
34 | .vg_name = "VGPIO1", | ||
35 | .vg_io_port = VIASR, | ||
36 | .vg_port_index = 0x25, | ||
37 | .vg_mask_shift = 0 | ||
38 | }, | ||
39 | { | ||
40 | .vg_name = "VGPIO2", /* aka DISPCLKI0 */ | ||
41 | .vg_io_port = VIASR, | ||
42 | .vg_port_index = 0x2c, | ||
43 | .vg_mask_shift = 1 | ||
44 | }, | ||
45 | { | ||
46 | .vg_name = "VGPIO3", /* aka DISPCLKO0 */ | ||
47 | .vg_io_port = VIASR, | ||
48 | .vg_port_index = 0x2c, | ||
49 | .vg_mask_shift = 0 | ||
50 | }, | ||
51 | { | ||
52 | .vg_name = "VGPIO4", /* DISPCLKI1 */ | ||
53 | .vg_io_port = VIASR, | ||
54 | .vg_port_index = 0x3d, | ||
55 | .vg_mask_shift = 1 | ||
56 | }, | ||
57 | { | ||
58 | .vg_name = "VGPIO5", /* DISPCLKO1 */ | ||
59 | .vg_io_port = VIASR, | ||
60 | .vg_port_index = 0x3d, | ||
61 | .vg_mask_shift = 0 | ||
62 | }, | ||
63 | }; | ||
64 | |||
65 | #define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios) | ||
66 | |||
67 | /* | ||
68 | * This structure controls the active GPIOs, which may be a subset | ||
69 | * of those which are known. | ||
70 | */ | ||
71 | |||
72 | struct viafb_gpio_cfg { | ||
73 | struct gpio_chip gpio_chip; | ||
74 | struct viafb_dev *vdev; | ||
75 | struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS]; | ||
76 | char *gpio_names[VIAFB_NUM_GPIOS]; | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | * GPIO access functions | ||
81 | */ | ||
82 | static void via_gpio_set(struct gpio_chip *chip, unsigned int nr, | ||
83 | int value) | ||
84 | { | ||
85 | struct viafb_gpio_cfg *cfg = container_of(chip, | ||
86 | struct viafb_gpio_cfg, | ||
87 | gpio_chip); | ||
88 | u8 reg; | ||
89 | struct viafb_gpio *gpio; | ||
90 | unsigned long flags; | ||
91 | |||
92 | spin_lock_irqsave(&cfg->vdev->reg_lock, flags); | ||
93 | gpio = cfg->active_gpios[nr]; | ||
94 | reg = via_read_reg(VIASR, gpio->vg_port_index); | ||
95 | reg |= 0x40 << gpio->vg_mask_shift; /* output enable */ | ||
96 | if (value) | ||
97 | reg |= 0x10 << gpio->vg_mask_shift; | ||
98 | else | ||
99 | reg &= ~(0x10 << gpio->vg_mask_shift); | ||
100 | via_write_reg(VIASR, gpio->vg_port_index, reg); | ||
101 | spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); | ||
102 | } | ||
103 | |||
104 | static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr, | ||
105 | int value) | ||
106 | { | ||
107 | via_gpio_set(chip, nr, value); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | /* | ||
112 | * Set the input direction. I'm not sure this is right; we should | ||
113 | * be able to do input without disabling output. | ||
114 | */ | ||
115 | static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr) | ||
116 | { | ||
117 | struct viafb_gpio_cfg *cfg = container_of(chip, | ||
118 | struct viafb_gpio_cfg, | ||
119 | gpio_chip); | ||
120 | struct viafb_gpio *gpio; | ||
121 | unsigned long flags; | ||
122 | |||
123 | spin_lock_irqsave(&cfg->vdev->reg_lock, flags); | ||
124 | gpio = cfg->active_gpios[nr]; | ||
125 | via_write_reg_mask(VIASR, gpio->vg_port_index, 0, | ||
126 | 0x40 << gpio->vg_mask_shift); | ||
127 | spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int via_gpio_get(struct gpio_chip *chip, unsigned int nr) | ||
132 | { | ||
133 | struct viafb_gpio_cfg *cfg = container_of(chip, | ||
134 | struct viafb_gpio_cfg, | ||
135 | gpio_chip); | ||
136 | u8 reg; | ||
137 | struct viafb_gpio *gpio; | ||
138 | unsigned long flags; | ||
139 | |||
140 | spin_lock_irqsave(&cfg->vdev->reg_lock, flags); | ||
141 | gpio = cfg->active_gpios[nr]; | ||
142 | reg = via_read_reg(VIASR, gpio->vg_port_index); | ||
143 | spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); | ||
144 | return reg & (0x04 << gpio->vg_mask_shift); | ||
145 | } | ||
146 | |||
147 | |||
148 | static struct viafb_gpio_cfg gpio_config = { | ||
149 | .gpio_chip = { | ||
150 | .label = "VIAFB onboard GPIO", | ||
151 | .owner = THIS_MODULE, | ||
152 | .direction_output = via_gpio_dir_out, | ||
153 | .set = via_gpio_set, | ||
154 | .direction_input = via_gpio_dir_input, | ||
155 | .get = via_gpio_get, | ||
156 | .base = -1, | ||
157 | .ngpio = 0, | ||
158 | .can_sleep = 0 | ||
159 | } | ||
160 | }; | ||
161 | |||
162 | /* | ||
163 | * Manage the software enable bit. | ||
164 | */ | ||
165 | static void viafb_gpio_enable(struct viafb_gpio *gpio) | ||
166 | { | ||
167 | via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02); | ||
168 | } | ||
169 | |||
170 | static void viafb_gpio_disable(struct viafb_gpio *gpio) | ||
171 | { | ||
172 | via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Look up a specific gpio and return the number it was assigned. | ||
177 | */ | ||
178 | int viafb_gpio_lookup(const char *name) | ||
179 | { | ||
180 | int i; | ||
181 | |||
182 | for (i = 0; i < gpio_config.gpio_chip.ngpio; i++) | ||
183 | if (!strcmp(name, gpio_config.active_gpios[i]->vg_name)) | ||
184 | return gpio_config.gpio_chip.base + i; | ||
185 | return -1; | ||
186 | } | ||
187 | EXPORT_SYMBOL_GPL(viafb_gpio_lookup); | ||
188 | |||
189 | /* | ||
190 | * Platform device stuff. | ||
191 | */ | ||
192 | static __devinit int viafb_gpio_probe(struct platform_device *platdev) | ||
193 | { | ||
194 | struct viafb_dev *vdev = platdev->dev.platform_data; | ||
195 | struct via_port_cfg *port_cfg = vdev->port_cfg; | ||
196 | int i, ngpio = 0, ret; | ||
197 | struct viafb_gpio *gpio; | ||
198 | unsigned long flags; | ||
199 | |||
200 | /* | ||
201 | * Set up entries for all GPIOs which have been configured to | ||
202 | * operate as such (as opposed to as i2c ports). | ||
203 | */ | ||
204 | for (i = 0; i < VIAFB_NUM_PORTS; i++) { | ||
205 | if (port_cfg[i].mode != VIA_MODE_GPIO) | ||
206 | continue; | ||
207 | for (gpio = viafb_all_gpios; | ||
208 | gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++) | ||
209 | if (gpio->vg_port_index == port_cfg[i].ioport_index) { | ||
210 | gpio_config.active_gpios[ngpio] = gpio; | ||
211 | gpio_config.gpio_names[ngpio] = gpio->vg_name; | ||
212 | ngpio++; | ||
213 | } | ||
214 | } | ||
215 | gpio_config.gpio_chip.ngpio = ngpio; | ||
216 | gpio_config.gpio_chip.names = gpio_config.gpio_names; | ||
217 | gpio_config.vdev = vdev; | ||
218 | if (ngpio == 0) { | ||
219 | printk(KERN_INFO "viafb: no GPIOs configured\n"); | ||
220 | return 0; | ||
221 | } | ||
222 | /* | ||
223 | * Enable the ports. They come in pairs, with a single | ||
224 | * enable bit for both. | ||
225 | */ | ||
226 | spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); | ||
227 | for (i = 0; i < ngpio; i += 2) | ||
228 | viafb_gpio_enable(gpio_config.active_gpios[i]); | ||
229 | spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); | ||
230 | /* | ||
231 | * Get registered. | ||
232 | */ | ||
233 | gpio_config.gpio_chip.base = -1; /* Dynamic */ | ||
234 | ret = gpiochip_add(&gpio_config.gpio_chip); | ||
235 | if (ret) { | ||
236 | printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); | ||
237 | gpio_config.gpio_chip.ngpio = 0; | ||
238 | } | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | |||
243 | static int viafb_gpio_remove(struct platform_device *platdev) | ||
244 | { | ||
245 | unsigned long flags; | ||
246 | int ret = 0, i; | ||
247 | |||
248 | /* | ||
249 | * Get unregistered. | ||
250 | */ | ||
251 | if (gpio_config.gpio_chip.ngpio > 0) { | ||
252 | ret = gpiochip_remove(&gpio_config.gpio_chip); | ||
253 | if (ret) { /* Somebody still using it? */ | ||
254 | printk(KERN_ERR "Viafb: GPIO remove failed\n"); | ||
255 | return ret; | ||
256 | } | ||
257 | } | ||
258 | /* | ||
259 | * Disable the ports. | ||
260 | */ | ||
261 | spin_lock_irqsave(&gpio_config.vdev->reg_lock, flags); | ||
262 | for (i = 0; i < gpio_config.gpio_chip.ngpio; i += 2) | ||
263 | viafb_gpio_disable(gpio_config.active_gpios[i]); | ||
264 | gpio_config.gpio_chip.ngpio = 0; | ||
265 | spin_unlock_irqrestore(&gpio_config.vdev->reg_lock, flags); | ||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static struct platform_driver via_gpio_driver = { | ||
270 | .driver = { | ||
271 | .name = "viafb-gpio", | ||
272 | }, | ||
273 | .probe = viafb_gpio_probe, | ||
274 | .remove = viafb_gpio_remove, | ||
275 | }; | ||
276 | |||
277 | int viafb_gpio_init(void) | ||
278 | { | ||
279 | return platform_driver_register(&via_gpio_driver); | ||
280 | } | ||
281 | |||
282 | void viafb_gpio_exit(void) | ||
283 | { | ||
284 | platform_driver_unregister(&via_gpio_driver); | ||
285 | } | ||
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c index 15543e968248..da9e4ca94b17 100644 --- a/drivers/video/via/via_i2c.c +++ b/drivers/video/via/via_i2c.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | 2 | * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. |
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | 3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. |
4 | 4 | ||
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -19,77 +19,106 @@ | |||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include "global.h" | 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 | ||
34 | static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C]; | ||
35 | struct viafb_dev *i2c_vdev; /* Passed in from core */ | ||
23 | 36 | ||
24 | static void via_i2c_setscl(void *data, int state) | 37 | static void via_i2c_setscl(void *data, int state) |
25 | { | 38 | { |
26 | u8 val; | 39 | u8 val; |
27 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | 40 | struct via_port_cfg *adap_data = data; |
41 | unsigned long flags; | ||
28 | 42 | ||
29 | val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0; | 43 | spin_lock_irqsave(&i2c_vdev->reg_lock, flags); |
44 | val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; | ||
30 | if (state) | 45 | if (state) |
31 | val |= 0x20; | 46 | val |= 0x20; |
32 | else | 47 | else |
33 | val &= ~0x20; | 48 | val &= ~0x20; |
34 | switch (via_i2c_chan->i2c_port) { | 49 | switch (adap_data->type) { |
35 | case I2CPORTINDEX: | 50 | case VIA_PORT_I2C: |
36 | val |= 0x01; | 51 | val |= 0x01; |
37 | break; | 52 | break; |
38 | case GPIOPORTINDEX: | 53 | case VIA_PORT_GPIO: |
39 | val |= 0x80; | 54 | val |= 0x80; |
40 | break; | 55 | break; |
41 | default: | 56 | default: |
42 | DEBUG_MSG("via_i2c: specify wrong i2c port.\n"); | 57 | printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); |
43 | } | 58 | } |
44 | viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val); | 59 | via_write_reg(adap_data->io_port, adap_data->ioport_index, val); |
60 | spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); | ||
45 | } | 61 | } |
46 | 62 | ||
47 | static int via_i2c_getscl(void *data) | 63 | static int via_i2c_getscl(void *data) |
48 | { | 64 | { |
49 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | 65 | struct via_port_cfg *adap_data = data; |
66 | unsigned long flags; | ||
67 | int ret = 0; | ||
50 | 68 | ||
51 | if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x08) | 69 | spin_lock_irqsave(&i2c_vdev->reg_lock, flags); |
52 | return 1; | 70 | if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) |
53 | return 0; | 71 | ret = 1; |
72 | spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); | ||
73 | return ret; | ||
54 | } | 74 | } |
55 | 75 | ||
56 | static int via_i2c_getsda(void *data) | 76 | static int via_i2c_getsda(void *data) |
57 | { | 77 | { |
58 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | 78 | struct via_port_cfg *adap_data = data; |
79 | unsigned long flags; | ||
80 | int ret = 0; | ||
59 | 81 | ||
60 | if (viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0x04) | 82 | spin_lock_irqsave(&i2c_vdev->reg_lock, flags); |
61 | return 1; | 83 | if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) |
62 | return 0; | 84 | ret = 1; |
85 | spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); | ||
86 | return ret; | ||
63 | } | 87 | } |
64 | 88 | ||
65 | static void via_i2c_setsda(void *data, int state) | 89 | static void via_i2c_setsda(void *data, int state) |
66 | { | 90 | { |
67 | u8 val; | 91 | u8 val; |
68 | struct via_i2c_stuff *via_i2c_chan = (struct via_i2c_stuff *)data; | 92 | struct via_port_cfg *adap_data = data; |
93 | unsigned long flags; | ||
69 | 94 | ||
70 | val = viafb_read_reg(VIASR, via_i2c_chan->i2c_port) & 0xF0; | 95 | spin_lock_irqsave(&i2c_vdev->reg_lock, flags); |
96 | val = via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0xF0; | ||
71 | if (state) | 97 | if (state) |
72 | val |= 0x10; | 98 | val |= 0x10; |
73 | else | 99 | else |
74 | val &= ~0x10; | 100 | val &= ~0x10; |
75 | switch (via_i2c_chan->i2c_port) { | 101 | switch (adap_data->type) { |
76 | case I2CPORTINDEX: | 102 | case VIA_PORT_I2C: |
77 | val |= 0x01; | 103 | val |= 0x01; |
78 | break; | 104 | break; |
79 | case GPIOPORTINDEX: | 105 | case VIA_PORT_GPIO: |
80 | val |= 0x40; | 106 | val |= 0x40; |
81 | break; | 107 | break; |
82 | default: | 108 | default: |
83 | DEBUG_MSG("via_i2c: specify wrong i2c port.\n"); | 109 | printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); |
84 | } | 110 | } |
85 | viafb_write_reg(via_i2c_chan->i2c_port, VIASR, val); | 111 | via_write_reg(adap_data->io_port, adap_data->ioport_index, val); |
112 | spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); | ||
86 | } | 113 | } |
87 | 114 | ||
88 | int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) | 115 | int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) |
89 | { | 116 | { |
90 | u8 mm1[] = {0x00}; | 117 | u8 mm1[] = {0x00}; |
91 | struct i2c_msg msgs[2]; | 118 | struct i2c_msg msgs[2]; |
92 | 119 | ||
120 | if (!via_i2c_par[adap].is_active) | ||
121 | return -ENODEV; | ||
93 | *pdata = 0; | 122 | *pdata = 0; |
94 | msgs[0].flags = 0; | 123 | msgs[0].flags = 0; |
95 | msgs[1].flags = I2C_M_RD; | 124 | msgs[1].flags = I2C_M_RD; |
@@ -97,81 +126,144 @@ int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) | |||
97 | mm1[0] = index; | 126 | mm1[0] = index; |
98 | msgs[0].len = 1; msgs[1].len = 1; | 127 | msgs[0].len = 1; msgs[1].len = 1; |
99 | msgs[0].buf = mm1; msgs[1].buf = pdata; | 128 | msgs[0].buf = mm1; msgs[1].buf = pdata; |
100 | i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2); | 129 | return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); |
101 | |||
102 | return 0; | ||
103 | } | 130 | } |
104 | 131 | ||
105 | int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data) | 132 | int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) |
106 | { | 133 | { |
107 | u8 msg[2] = { index, data }; | 134 | u8 msg[2] = { index, data }; |
108 | struct i2c_msg msgs; | 135 | struct i2c_msg msgs; |
109 | 136 | ||
137 | if (!via_i2c_par[adap].is_active) | ||
138 | return -ENODEV; | ||
110 | msgs.flags = 0; | 139 | msgs.flags = 0; |
111 | msgs.addr = slave_addr / 2; | 140 | msgs.addr = slave_addr / 2; |
112 | msgs.len = 2; | 141 | msgs.len = 2; |
113 | msgs.buf = msg; | 142 | msgs.buf = msg; |
114 | return i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, &msgs, 1); | 143 | return i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); |
115 | } | 144 | } |
116 | 145 | ||
117 | int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) | 146 | int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) |
118 | { | 147 | { |
119 | u8 mm1[] = {0x00}; | 148 | u8 mm1[] = {0x00}; |
120 | struct i2c_msg msgs[2]; | 149 | struct i2c_msg msgs[2]; |
121 | 150 | ||
151 | if (!via_i2c_par[adap].is_active) | ||
152 | return -ENODEV; | ||
122 | msgs[0].flags = 0; | 153 | msgs[0].flags = 0; |
123 | msgs[1].flags = I2C_M_RD; | 154 | msgs[1].flags = I2C_M_RD; |
124 | msgs[0].addr = msgs[1].addr = slave_addr / 2; | 155 | msgs[0].addr = msgs[1].addr = slave_addr / 2; |
125 | mm1[0] = index; | 156 | mm1[0] = index; |
126 | msgs[0].len = 1; msgs[1].len = buff_len; | 157 | msgs[0].len = 1; msgs[1].len = buff_len; |
127 | msgs[0].buf = mm1; msgs[1].buf = buff; | 158 | msgs[0].buf = mm1; msgs[1].buf = buff; |
128 | i2c_transfer(&viaparinfo->shared->i2c_stuff.adapter, msgs, 2); | 159 | return i2c_transfer(&via_i2c_par[adap].adapter, msgs, 2); |
129 | return 0; | ||
130 | } | 160 | } |
131 | 161 | ||
132 | int viafb_create_i2c_bus(void *viapar) | 162 | /* |
163 | * Allow other viafb subdevices to look up a specific adapter | ||
164 | * by port name. | ||
165 | */ | ||
166 | struct i2c_adapter *viafb_find_i2c_adapter(enum viafb_i2c_adap which) | ||
133 | { | 167 | { |
134 | int ret; | 168 | struct via_i2c_stuff *stuff = &via_i2c_par[which]; |
135 | struct via_i2c_stuff *i2c_stuff = | ||
136 | &((struct viafb_par *)viapar)->shared->i2c_stuff; | ||
137 | |||
138 | strcpy(i2c_stuff->adapter.name, "via_i2c"); | ||
139 | i2c_stuff->i2c_port = 0x0; | ||
140 | i2c_stuff->adapter.owner = THIS_MODULE; | ||
141 | i2c_stuff->adapter.id = 0x01FFFF; | ||
142 | i2c_stuff->adapter.class = 0; | ||
143 | i2c_stuff->adapter.algo_data = &i2c_stuff->algo; | ||
144 | i2c_stuff->adapter.dev.parent = NULL; | ||
145 | i2c_stuff->algo.setsda = via_i2c_setsda; | ||
146 | i2c_stuff->algo.setscl = via_i2c_setscl; | ||
147 | i2c_stuff->algo.getsda = via_i2c_getsda; | ||
148 | i2c_stuff->algo.getscl = via_i2c_getscl; | ||
149 | i2c_stuff->algo.udelay = 40; | ||
150 | i2c_stuff->algo.timeout = 20; | ||
151 | i2c_stuff->algo.data = i2c_stuff; | ||
152 | |||
153 | i2c_set_adapdata(&i2c_stuff->adapter, i2c_stuff); | ||
154 | 169 | ||
155 | /* Raise SCL and SDA */ | 170 | return &stuff->adapter; |
156 | i2c_stuff->i2c_port = I2CPORTINDEX; | 171 | } |
157 | via_i2c_setsda(i2c_stuff, 1); | 172 | EXPORT_SYMBOL_GPL(viafb_find_i2c_adapter); |
158 | via_i2c_setscl(i2c_stuff, 1); | ||
159 | 173 | ||
160 | i2c_stuff->i2c_port = GPIOPORTINDEX; | ||
161 | via_i2c_setsda(i2c_stuff, 1); | ||
162 | via_i2c_setscl(i2c_stuff, 1); | ||
163 | udelay(20); | ||
164 | 174 | ||
165 | ret = i2c_bit_add_bus(&i2c_stuff->adapter); | 175 | static int create_i2c_bus(struct i2c_adapter *adapter, |
166 | if (ret == 0) | 176 | struct i2c_algo_bit_data *algo, |
167 | DEBUG_MSG("I2C bus %s registered.\n", i2c_stuff->adapter.name); | 177 | struct via_port_cfg *adap_cfg, |
178 | struct pci_dev *pdev) | ||
179 | { | ||
180 | algo->setsda = via_i2c_setsda; | ||
181 | algo->setscl = via_i2c_setscl; | ||
182 | algo->getsda = via_i2c_getsda; | ||
183 | algo->getscl = via_i2c_getscl; | ||
184 | algo->udelay = 40; | ||
185 | algo->timeout = 20; | ||
186 | algo->data = adap_cfg; | ||
187 | |||
188 | sprintf(adapter->name, "viafb i2c io_port idx 0x%02x", | ||
189 | adap_cfg->ioport_index); | ||
190 | adapter->owner = THIS_MODULE; | ||
191 | adapter->id = 0x01FFFF; | ||
192 | adapter->class = I2C_CLASS_DDC; | ||
193 | adapter->algo_data = algo; | ||
194 | if (pdev) | ||
195 | adapter->dev.parent = &pdev->dev; | ||
168 | else | 196 | else |
169 | DEBUG_MSG("Failed to register I2C bus %s.\n", | 197 | adapter->dev.parent = NULL; |
170 | i2c_stuff->adapter.name); | 198 | /* i2c_set_adapdata(adapter, adap_cfg); */ |
171 | return ret; | 199 | |
200 | /* Raise SCL and SDA */ | ||
201 | via_i2c_setsda(adap_cfg, 1); | ||
202 | via_i2c_setscl(adap_cfg, 1); | ||
203 | udelay(20); | ||
204 | |||
205 | return i2c_bit_add_bus(adapter); | ||
206 | } | ||
207 | |||
208 | static int viafb_i2c_probe(struct platform_device *platdev) | ||
209 | { | ||
210 | int i, ret; | ||
211 | struct via_port_cfg *configs; | ||
212 | |||
213 | i2c_vdev = platdev->dev.platform_data; | ||
214 | configs = i2c_vdev->port_cfg; | ||
215 | |||
216 | for (i = 0; i < VIAFB_NUM_PORTS; i++) { | ||
217 | struct via_port_cfg *adap_cfg = configs++; | ||
218 | struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; | ||
219 | |||
220 | i2c_stuff->is_active = 0; | ||
221 | if (adap_cfg->type == 0 || adap_cfg->mode != VIA_MODE_I2C) | ||
222 | continue; | ||
223 | ret = create_i2c_bus(&i2c_stuff->adapter, | ||
224 | &i2c_stuff->algo, adap_cfg, | ||
225 | NULL); /* FIXME: PCIDEV */ | ||
226 | if (ret < 0) { | ||
227 | printk(KERN_ERR "viafb: cannot create i2c bus %u:%d\n", | ||
228 | i, ret); | ||
229 | continue; /* Still try to make the rest */ | ||
230 | } | ||
231 | i2c_stuff->is_active = 1; | ||
232 | } | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int viafb_i2c_remove(struct platform_device *platdev) | ||
238 | { | ||
239 | int i; | ||
240 | |||
241 | for (i = 0; i < VIAFB_NUM_PORTS; i++) { | ||
242 | struct via_i2c_stuff *i2c_stuff = &via_i2c_par[i]; | ||
243 | /* | ||
244 | * Only remove those entries in the array that we've | ||
245 | * actually used (and thus initialized algo_data) | ||
246 | */ | ||
247 | if (i2c_stuff->is_active) | ||
248 | i2c_del_adapter(&i2c_stuff->adapter); | ||
249 | } | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static struct platform_driver via_i2c_driver = { | ||
254 | .driver = { | ||
255 | .name = "viafb-i2c", | ||
256 | }, | ||
257 | .probe = viafb_i2c_probe, | ||
258 | .remove = viafb_i2c_remove, | ||
259 | }; | ||
260 | |||
261 | int viafb_i2c_init(void) | ||
262 | { | ||
263 | return platform_driver_register(&via_i2c_driver); | ||
172 | } | 264 | } |
173 | 265 | ||
174 | void viafb_delete_i2c_buss(void *par) | 266 | void viafb_i2c_exit(void) |
175 | { | 267 | { |
176 | i2c_del_adapter(&((struct viafb_par *)par)->shared->i2c_stuff.adapter); | 268 | platform_driver_unregister(&via_i2c_driver); |
177 | } | 269 | } |
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c new file mode 100644 index 000000000000..3cddcff88ab9 --- /dev/null +++ b/drivers/video/via/via_modesetting.c | |||
@@ -0,0 +1,126 @@ | |||
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 | void via_set_primary_address(u32 addr) | ||
33 | { | ||
34 | DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); | ||
35 | via_write_reg(VIACR, 0x0D, addr & 0xFF); | ||
36 | via_write_reg(VIACR, 0x0C, (addr >> 8) & 0xFF); | ||
37 | via_write_reg(VIACR, 0x34, (addr >> 16) & 0xFF); | ||
38 | via_write_reg_mask(VIACR, 0x48, (addr >> 24) & 0x1F, 0x1F); | ||
39 | } | ||
40 | |||
41 | void via_set_secondary_address(u32 addr) | ||
42 | { | ||
43 | DEBUG_MSG(KERN_DEBUG "via_set_secondary_address(0x%08X)\n", addr); | ||
44 | /* secondary display supports only quadword aligned memory */ | ||
45 | via_write_reg_mask(VIACR, 0x62, (addr >> 2) & 0xFE, 0xFE); | ||
46 | via_write_reg(VIACR, 0x63, (addr >> 10) & 0xFF); | ||
47 | via_write_reg(VIACR, 0x64, (addr >> 18) & 0xFF); | ||
48 | via_write_reg_mask(VIACR, 0xA3, (addr >> 26) & 0x07, 0x07); | ||
49 | } | ||
50 | |||
51 | void via_set_primary_pitch(u32 pitch) | ||
52 | { | ||
53 | DEBUG_MSG(KERN_DEBUG "via_set_primary_pitch(0x%08X)\n", pitch); | ||
54 | /* spec does not say that first adapter skips 3 bits but old | ||
55 | * code did it and seems to be reasonable in analogy to 2nd adapter | ||
56 | */ | ||
57 | pitch = pitch >> 3; | ||
58 | via_write_reg(VIACR, 0x13, pitch & 0xFF); | ||
59 | via_write_reg_mask(VIACR, 0x35, (pitch >> (8 - 5)) & 0xE0, 0xE0); | ||
60 | } | ||
61 | |||
62 | void via_set_secondary_pitch(u32 pitch) | ||
63 | { | ||
64 | DEBUG_MSG(KERN_DEBUG "via_set_secondary_pitch(0x%08X)\n", pitch); | ||
65 | pitch = pitch >> 3; | ||
66 | via_write_reg(VIACR, 0x66, pitch & 0xFF); | ||
67 | via_write_reg_mask(VIACR, 0x67, (pitch >> 8) & 0x03, 0x03); | ||
68 | via_write_reg_mask(VIACR, 0x71, (pitch >> (10 - 7)) & 0x80, 0x80); | ||
69 | } | ||
70 | |||
71 | void via_set_primary_color_depth(u8 depth) | ||
72 | { | ||
73 | u8 value; | ||
74 | |||
75 | DEBUG_MSG(KERN_DEBUG "via_set_primary_color_depth(%d)\n", depth); | ||
76 | switch (depth) { | ||
77 | case 8: | ||
78 | value = 0x00; | ||
79 | break; | ||
80 | case 15: | ||
81 | value = 0x04; | ||
82 | break; | ||
83 | case 16: | ||
84 | value = 0x14; | ||
85 | break; | ||
86 | case 24: | ||
87 | value = 0x0C; | ||
88 | break; | ||
89 | case 30: | ||
90 | value = 0x08; | ||
91 | break; | ||
92 | default: | ||
93 | printk(KERN_WARNING "via_set_primary_color_depth: " | ||
94 | "Unsupported depth: %d\n", depth); | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | via_write_reg_mask(VIASR, 0x15, value, 0x1C); | ||
99 | } | ||
100 | |||
101 | void via_set_secondary_color_depth(u8 depth) | ||
102 | { | ||
103 | u8 value; | ||
104 | |||
105 | DEBUG_MSG(KERN_DEBUG "via_set_secondary_color_depth(%d)\n", depth); | ||
106 | switch (depth) { | ||
107 | case 8: | ||
108 | value = 0x00; | ||
109 | break; | ||
110 | case 16: | ||
111 | value = 0x40; | ||
112 | break; | ||
113 | case 24: | ||
114 | value = 0xC0; | ||
115 | break; | ||
116 | case 30: | ||
117 | value = 0x80; | ||
118 | break; | ||
119 | default: | ||
120 | printk(KERN_WARNING "via_set_secondary_color_depth: " | ||
121 | "Unsupported depth: %d\n", depth); | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | via_write_reg_mask(VIACR, 0x67, value, 0xC0); | ||
126 | } | ||
diff --git a/drivers/video/via/via_i2c.h b/drivers/video/via/via_modesetting.h index 3a13242a3152..ae35cfdeb37c 100644 --- a/drivers/video/via/via_i2c.h +++ b/drivers/video/via/via_modesetting.h | |||
@@ -1,46 +1,38 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | 2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. |
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | 3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. |
4 | 4 | * Copyright 2010 Florian Tobias Schandinat <FlorianSchandinat@gmx.de> | |
5 | * | ||
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public | 7 | * modify it under the terms of the GNU General Public |
7 | * License as published by the Free Software Foundation; | 8 | * License as published by the Free Software Foundation; |
8 | * either version 2, or (at your option) any later version. | 9 | * either version 2, or (at your option) any later version. |
9 | 10 | * | |
10 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even | 12 | * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even |
12 | * the implied warranty of MERCHANTABILITY or FITNESS FOR | 13 | * the implied warranty of MERCHANTABILITY or FITNESS FOR |
13 | * A PARTICULAR PURPOSE.See the GNU General Public License | 14 | * A PARTICULAR PURPOSE.See the GNU General Public License |
14 | * for more details. | 15 | * for more details. |
15 | 16 | * | |
16 | * You should have received a copy of the GNU General Public License | 17 | * 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 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., | 19 | * Foundation, Inc., |
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 21 | */ |
21 | #ifndef __VIA_I2C_H__ | 22 | /* |
22 | #define __VIA_I2C_H__ | 23 | * basic modesetting functions |
24 | */ | ||
23 | 25 | ||
24 | #include <linux/i2c.h> | 26 | #ifndef __VIA_MODESETTING_H__ |
25 | #include <linux/i2c-algo-bit.h> | 27 | #define __VIA_MODESETTING_H__ |
26 | 28 | ||
27 | struct via_i2c_stuff { | 29 | #include <linux/types.h> |
28 | u16 i2c_port; /* GPIO or I2C port */ | ||
29 | struct i2c_adapter adapter; | ||
30 | struct i2c_algo_bit_data algo; | ||
31 | }; | ||
32 | 30 | ||
33 | #define I2CPORT 0x3c4 | 31 | void via_set_primary_address(u32 addr); |
34 | #define I2CPORTINDEX 0x31 | 32 | void via_set_secondary_address(u32 addr); |
35 | #define GPIOPORT 0x3C4 | 33 | void via_set_primary_pitch(u32 pitch); |
36 | #define GPIOPORTINDEX 0x2C | 34 | void via_set_secondary_pitch(u32 pitch); |
37 | #define I2C_BUS 1 | 35 | void via_set_primary_color_depth(u8 depth); |
38 | #define GPIO_BUS 2 | 36 | void via_set_secondary_color_depth(u8 depth); |
39 | #define DELAYPORT 0x3C3 | ||
40 | 37 | ||
41 | int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata); | 38 | #endif /* __VIA_MODESETTING_H__ */ |
42 | int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data); | ||
43 | int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len); | ||
44 | int viafb_create_i2c_bus(void *par); | ||
45 | void viafb_delete_i2c_buss(void *par); | ||
46 | #endif /* __VIA_I2C_H__ */ | ||
diff --git a/drivers/video/via/via_utility.c b/drivers/video/via/via_utility.c index aefdeeec89b1..d05ccb62b55f 100644 --- a/drivers/video/via/via_utility.c +++ b/drivers/video/via/via_utility.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/via-core.h> | ||
22 | #include "global.h" | 23 | #include "global.h" |
23 | 24 | ||
24 | void viafb_get_device_support_state(u32 *support_state) | 25 | void viafb_get_device_support_state(u32 *support_state) |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 777b38a06d40..2bc40e682f95 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright 1998-2008 VIA Technologies, Inc. All Rights Reserved. | 2 | * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. |
3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. | 3 | * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. |
4 | 4 | ||
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -23,8 +23,9 @@ | |||
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/stat.h> | 25 | #include <linux/stat.h> |
26 | #define _MASTER_FILE | 26 | #include <linux/via-core.h> |
27 | 27 | ||
28 | #define _MASTER_FILE | ||
28 | #include "global.h" | 29 | #include "global.h" |
29 | 30 | ||
30 | static char *viafb_name = "Via"; | 31 | static char *viafb_name = "Via"; |
@@ -221,7 +222,7 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
221 | /* Adjust var according to our driver's own table */ | 222 | /* Adjust var according to our driver's own table */ |
222 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); | 223 | viafb_fill_var_timing_info(var, viafb_refresh, vmode_entry); |
223 | if (info->var.accel_flags & FB_ACCELF_TEXT && | 224 | if (info->var.accel_flags & FB_ACCELF_TEXT && |
224 | !ppar->shared->engine_mmio) | 225 | !ppar->shared->vdev->engine_mmio) |
225 | info->var.accel_flags = 0; | 226 | info->var.accel_flags = 0; |
226 | 227 | ||
227 | return 0; | 228 | return 0; |
@@ -317,12 +318,12 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, | |||
317 | 318 | ||
318 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); | 319 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); |
319 | if (!viafb_dual_fb) { | 320 | if (!viafb_dual_fb) { |
320 | viafb_set_primary_address(vram_addr); | 321 | via_set_primary_address(vram_addr); |
321 | viafb_set_secondary_address(vram_addr); | 322 | via_set_secondary_address(vram_addr); |
322 | } else if (viapar->iga_path == IGA1) | 323 | } else if (viapar->iga_path == IGA1) |
323 | viafb_set_primary_address(vram_addr); | 324 | via_set_primary_address(vram_addr); |
324 | else | 325 | else |
325 | viafb_set_secondary_address(vram_addr); | 326 | via_set_secondary_address(vram_addr); |
326 | 327 | ||
327 | return 0; | 328 | return 0; |
328 | } | 329 | } |
@@ -696,7 +697,7 @@ static void viafb_fillrect(struct fb_info *info, | |||
696 | rop = 0xF0; | 697 | rop = 0xF0; |
697 | 698 | ||
698 | DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n"); | 699 | DEBUG_MSG(KERN_DEBUG "viafb 2D engine: fillrect\n"); |
699 | if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_FILL, | 700 | if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_FILL, |
700 | rect->width, rect->height, info->var.bits_per_pixel, | 701 | rect->width, rect->height, info->var.bits_per_pixel, |
701 | viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy, | 702 | viapar->vram_addr, info->fix.line_length, rect->dx, rect->dy, |
702 | NULL, 0, 0, 0, 0, fg_color, 0, rop)) | 703 | NULL, 0, 0, 0, 0, fg_color, 0, rop)) |
@@ -718,7 +719,7 @@ static void viafb_copyarea(struct fb_info *info, | |||
718 | return; | 719 | return; |
719 | 720 | ||
720 | DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n"); | 721 | DEBUG_MSG(KERN_DEBUG "viafb 2D engine: copyarea\n"); |
721 | if (shared->hw_bitblt(shared->engine_mmio, VIA_BITBLT_COLOR, | 722 | if (shared->hw_bitblt(shared->vdev->engine_mmio, VIA_BITBLT_COLOR, |
722 | area->width, area->height, info->var.bits_per_pixel, | 723 | area->width, area->height, info->var.bits_per_pixel, |
723 | viapar->vram_addr, info->fix.line_length, area->dx, area->dy, | 724 | viapar->vram_addr, info->fix.line_length, area->dx, area->dy, |
724 | NULL, viapar->vram_addr, info->fix.line_length, | 725 | NULL, viapar->vram_addr, info->fix.line_length, |
@@ -755,7 +756,7 @@ static void viafb_imageblit(struct fb_info *info, | |||
755 | op = VIA_BITBLT_COLOR; | 756 | op = VIA_BITBLT_COLOR; |
756 | 757 | ||
757 | DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n"); | 758 | DEBUG_MSG(KERN_DEBUG "viafb 2D engine: imageblit\n"); |
758 | if (shared->hw_bitblt(shared->engine_mmio, op, | 759 | if (shared->hw_bitblt(shared->vdev->engine_mmio, op, |
759 | image->width, image->height, info->var.bits_per_pixel, | 760 | image->width, image->height, info->var.bits_per_pixel, |
760 | viapar->vram_addr, info->fix.line_length, image->dx, image->dy, | 761 | viapar->vram_addr, info->fix.line_length, image->dx, image->dy, |
761 | (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0)) | 762 | (u32 *)image->data, 0, 0, 0, 0, fg_color, bg_color, 0)) |
@@ -765,7 +766,7 @@ static void viafb_imageblit(struct fb_info *info, | |||
765 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 766 | static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) |
766 | { | 767 | { |
767 | struct viafb_par *viapar = info->par; | 768 | struct viafb_par *viapar = info->par; |
768 | void __iomem *engine = viapar->shared->engine_mmio; | 769 | void __iomem *engine = viapar->shared->vdev->engine_mmio; |
769 | u32 temp, xx, yy, bg_color = 0, fg_color = 0, | 770 | u32 temp, xx, yy, bg_color = 0, fg_color = 0, |
770 | chip_name = viapar->shared->chip_info.gfx_chip_name; | 771 | chip_name = viapar->shared->chip_info.gfx_chip_name; |
771 | int i, j = 0, cur_size = 64; | 772 | int i, j = 0, cur_size = 64; |
@@ -1018,8 +1019,8 @@ static void viafb_set_device(struct device_t active_dev) | |||
1018 | viafb_SAMM_ON = active_dev.samm; | 1019 | viafb_SAMM_ON = active_dev.samm; |
1019 | viafb_primary_dev = active_dev.primary_dev; | 1020 | viafb_primary_dev = active_dev.primary_dev; |
1020 | 1021 | ||
1021 | viafb_set_primary_address(0); | 1022 | via_set_primary_address(0); |
1022 | viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); | 1023 | via_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); |
1023 | viafb_set_iga_path(); | 1024 | viafb_set_iga_path(); |
1024 | } | 1025 | } |
1025 | 1026 | ||
@@ -1165,8 +1166,9 @@ static int apply_device_setting(struct viafb_ioctl_setting setting_info, | |||
1165 | if (viafb_SAMM_ON) | 1166 | if (viafb_SAMM_ON) |
1166 | viafb_primary_dev = setting_info.primary_device; | 1167 | viafb_primary_dev = setting_info.primary_device; |
1167 | 1168 | ||
1168 | viafb_set_primary_address(0); | 1169 | via_set_primary_address(0); |
1169 | viafb_set_secondary_address(viafb_SAMM_ON ? viafb_second_offset : 0); | 1170 | via_set_secondary_address(viafb_SAMM_ON ? |
1171 | viafb_second_offset : 0); | ||
1170 | viafb_set_iga_path(); | 1172 | viafb_set_iga_path(); |
1171 | } | 1173 | } |
1172 | need_set_mode = 1; | 1174 | need_set_mode = 1; |
@@ -1325,6 +1327,8 @@ static void parse_dvi_port(void) | |||
1325 | output_interface); | 1327 | output_interface); |
1326 | } | 1328 | } |
1327 | 1329 | ||
1330 | #ifdef CONFIG_FB_VIA_DIRECT_PROCFS | ||
1331 | |||
1328 | /* | 1332 | /* |
1329 | * The proc filesystem read/write function, a simple proc implement to | 1333 | * The proc filesystem read/write function, a simple proc implement to |
1330 | * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, | 1334 | * get/set the value of DPA DVP0, DVP0DataDriving, DVP0ClockDriving, DVP1, |
@@ -1701,16 +1705,21 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry) | |||
1701 | } | 1705 | } |
1702 | static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) | 1706 | static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) |
1703 | { | 1707 | { |
1704 | /* no problem if it was not registered */ | 1708 | struct chip_information *chip_info = &viaparinfo->shared->chip_info; |
1709 | |||
1705 | remove_proc_entry("dvp0", viafb_entry);/* parent dir */ | 1710 | remove_proc_entry("dvp0", viafb_entry);/* parent dir */ |
1706 | remove_proc_entry("dvp1", viafb_entry); | 1711 | remove_proc_entry("dvp1", viafb_entry); |
1707 | remove_proc_entry("dfph", viafb_entry); | 1712 | remove_proc_entry("dfph", viafb_entry); |
1708 | remove_proc_entry("dfpl", viafb_entry); | 1713 | remove_proc_entry("dfpl", viafb_entry); |
1709 | remove_proc_entry("vt1636", viafb_entry); | 1714 | if (chip_info->lvds_chip_info.lvds_chip_name == VT1636_LVDS |
1710 | remove_proc_entry("vt1625", viafb_entry); | 1715 | || chip_info->lvds_chip_info2.lvds_chip_name == VT1636_LVDS) |
1716 | remove_proc_entry("vt1636", viafb_entry); | ||
1717 | |||
1711 | remove_proc_entry("viafb", NULL); | 1718 | remove_proc_entry("viafb", NULL); |
1712 | } | 1719 | } |
1713 | 1720 | ||
1721 | #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */ | ||
1722 | |||
1714 | static int parse_mode(const char *str, u32 *xres, u32 *yres) | 1723 | static int parse_mode(const char *str, u32 *xres, u32 *yres) |
1715 | { | 1724 | { |
1716 | char *ptr; | 1725 | char *ptr; |
@@ -1732,12 +1741,13 @@ static int parse_mode(const char *str, u32 *xres, u32 *yres) | |||
1732 | return 0; | 1741 | return 0; |
1733 | } | 1742 | } |
1734 | 1743 | ||
1735 | static int __devinit via_pci_probe(struct pci_dev *pdev, | 1744 | |
1736 | const struct pci_device_id *ent) | 1745 | int __devinit via_fb_pci_probe(struct viafb_dev *vdev) |
1737 | { | 1746 | { |
1738 | u32 default_xres, default_yres; | 1747 | u32 default_xres, default_yres; |
1739 | struct VideoModeTable *vmode_entry; | 1748 | struct VideoModeTable *vmode_entry; |
1740 | struct fb_var_screeninfo default_var; | 1749 | struct fb_var_screeninfo default_var; |
1750 | int rc; | ||
1741 | u32 viafb_par_length; | 1751 | u32 viafb_par_length; |
1742 | 1752 | ||
1743 | DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); | 1753 | DEBUG_MSG(KERN_INFO "VIAFB PCI Probe!!\n"); |
@@ -1749,14 +1759,15 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1749 | */ | 1759 | */ |
1750 | viafbinfo = framebuffer_alloc(viafb_par_length + | 1760 | viafbinfo = framebuffer_alloc(viafb_par_length + |
1751 | ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), | 1761 | ALIGN(sizeof(struct viafb_shared), BITS_PER_LONG/8), |
1752 | &pdev->dev); | 1762 | &vdev->pdev->dev); |
1753 | if (!viafbinfo) { | 1763 | if (!viafbinfo) { |
1754 | printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); | 1764 | printk(KERN_ERR"Could not allocate memory for viafb_info.\n"); |
1755 | return -ENODEV; | 1765 | return -ENOMEM; |
1756 | } | 1766 | } |
1757 | 1767 | ||
1758 | viaparinfo = (struct viafb_par *)viafbinfo->par; | 1768 | viaparinfo = (struct viafb_par *)viafbinfo->par; |
1759 | viaparinfo->shared = viafbinfo->par + viafb_par_length; | 1769 | viaparinfo->shared = viafbinfo->par + viafb_par_length; |
1770 | viaparinfo->shared->vdev = vdev; | ||
1760 | viaparinfo->vram_addr = 0; | 1771 | viaparinfo->vram_addr = 0; |
1761 | viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info; | 1772 | viaparinfo->tmds_setting_info = &viaparinfo->shared->tmds_setting_info; |
1762 | viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; | 1773 | viaparinfo->lvds_setting_info = &viaparinfo->shared->lvds_setting_info; |
@@ -1774,23 +1785,20 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1774 | if (!viafb_SAMM_ON) | 1785 | if (!viafb_SAMM_ON) |
1775 | viafb_dual_fb = 0; | 1786 | viafb_dual_fb = 0; |
1776 | 1787 | ||
1777 | /* Set up I2C bus stuff */ | 1788 | viafb_init_chip_info(vdev->chip_type); |
1778 | viafb_create_i2c_bus(viaparinfo); | 1789 | /* |
1779 | 1790 | * The framebuffer will have been successfully mapped by | |
1780 | viafb_init_chip_info(pdev, ent); | 1791 | * the core (or we'd not be here), but we still need to |
1781 | viaparinfo->fbmem = pci_resource_start(pdev, 0); | 1792 | * set up our own accounting. |
1782 | viaparinfo->memsize = viafb_get_fb_size_from_pci(); | 1793 | */ |
1794 | viaparinfo->fbmem = vdev->fbmem_start; | ||
1795 | viaparinfo->memsize = vdev->fbmem_len; | ||
1783 | viaparinfo->fbmem_free = viaparinfo->memsize; | 1796 | viaparinfo->fbmem_free = viaparinfo->memsize; |
1784 | viaparinfo->fbmem_used = 0; | 1797 | viaparinfo->fbmem_used = 0; |
1785 | viafbinfo->screen_base = ioremap_nocache(viaparinfo->fbmem, | 1798 | viafbinfo->screen_base = vdev->fbmem; |
1786 | viaparinfo->memsize); | ||
1787 | if (!viafbinfo->screen_base) { | ||
1788 | printk(KERN_INFO "ioremap failed\n"); | ||
1789 | return -ENOMEM; | ||
1790 | } | ||
1791 | 1799 | ||
1792 | viafbinfo->fix.mmio_start = pci_resource_start(pdev, 1); | 1800 | viafbinfo->fix.mmio_start = vdev->engine_start; |
1793 | viafbinfo->fix.mmio_len = pci_resource_len(pdev, 1); | 1801 | viafbinfo->fix.mmio_len = vdev->engine_len; |
1794 | viafbinfo->node = 0; | 1802 | viafbinfo->node = 0; |
1795 | viafbinfo->fbops = &viafb_ops; | 1803 | viafbinfo->fbops = &viafb_ops; |
1796 | viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 1804 | viafbinfo->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
@@ -1858,12 +1866,13 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1858 | viafbinfo->var = default_var; | 1866 | viafbinfo->var = default_var; |
1859 | 1867 | ||
1860 | if (viafb_dual_fb) { | 1868 | if (viafb_dual_fb) { |
1861 | viafbinfo1 = framebuffer_alloc(viafb_par_length, &pdev->dev); | 1869 | viafbinfo1 = framebuffer_alloc(viafb_par_length, |
1870 | &vdev->pdev->dev); | ||
1862 | if (!viafbinfo1) { | 1871 | if (!viafbinfo1) { |
1863 | printk(KERN_ERR | 1872 | printk(KERN_ERR |
1864 | "allocate the second framebuffer struct error\n"); | 1873 | "allocate the second framebuffer struct error\n"); |
1865 | framebuffer_release(viafbinfo); | 1874 | rc = -ENOMEM; |
1866 | return -ENOMEM; | 1875 | goto out_fb_release; |
1867 | } | 1876 | } |
1868 | viaparinfo1 = viafbinfo1->par; | 1877 | viaparinfo1 = viafbinfo1->par; |
1869 | memcpy(viaparinfo1, viaparinfo, viafb_par_length); | 1878 | memcpy(viaparinfo1, viaparinfo, viafb_par_length); |
@@ -1914,48 +1923,66 @@ static int __devinit via_pci_probe(struct pci_dev *pdev, | |||
1914 | viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, | 1923 | viaparinfo->depth = fb_get_color_depth(&viafbinfo->var, |
1915 | &viafbinfo->fix); | 1924 | &viafbinfo->fix); |
1916 | default_var.activate = FB_ACTIVATE_NOW; | 1925 | default_var.activate = FB_ACTIVATE_NOW; |
1917 | fb_alloc_cmap(&viafbinfo->cmap, 256, 0); | 1926 | rc = fb_alloc_cmap(&viafbinfo->cmap, 256, 0); |
1927 | if (rc) | ||
1928 | goto out_fb1_release; | ||
1918 | 1929 | ||
1919 | if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) | 1930 | if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) |
1920 | && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { | 1931 | && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) { |
1921 | if (register_framebuffer(viafbinfo1) < 0) | 1932 | rc = register_framebuffer(viafbinfo1); |
1922 | return -EINVAL; | 1933 | if (rc) |
1934 | goto out_dealloc_cmap; | ||
1923 | } | 1935 | } |
1924 | if (register_framebuffer(viafbinfo) < 0) | 1936 | rc = register_framebuffer(viafbinfo); |
1925 | return -EINVAL; | 1937 | if (rc) |
1938 | goto out_fb1_unreg_lcd_cle266; | ||
1926 | 1939 | ||
1927 | if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) | 1940 | if (viafb_dual_fb && ((viafb_primary_dev != LCD_Device) |
1928 | || (viaparinfo->chip_info->gfx_chip_name != | 1941 | || (viaparinfo->chip_info->gfx_chip_name != |
1929 | UNICHROME_CLE266))) { | 1942 | UNICHROME_CLE266))) { |
1930 | if (register_framebuffer(viafbinfo1) < 0) | 1943 | rc = register_framebuffer(viafbinfo1); |
1931 | return -EINVAL; | 1944 | if (rc) |
1945 | goto out_fb_unreg; | ||
1932 | } | 1946 | } |
1933 | DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", | 1947 | DEBUG_MSG(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", |
1934 | viafbinfo->node, viafbinfo->fix.id, default_var.xres, | 1948 | viafbinfo->node, viafbinfo->fix.id, default_var.xres, |
1935 | default_var.yres, default_var.bits_per_pixel); | 1949 | default_var.yres, default_var.bits_per_pixel); |
1936 | 1950 | ||
1951 | #ifdef CONFIG_FB_VIA_DIRECT_PROCFS | ||
1937 | viafb_init_proc(&viaparinfo->shared->proc_entry); | 1952 | viafb_init_proc(&viaparinfo->shared->proc_entry); |
1953 | #endif | ||
1938 | viafb_init_dac(IGA2); | 1954 | viafb_init_dac(IGA2); |
1939 | return 0; | 1955 | return 0; |
1956 | |||
1957 | out_fb_unreg: | ||
1958 | unregister_framebuffer(viafbinfo); | ||
1959 | out_fb1_unreg_lcd_cle266: | ||
1960 | if (viafb_dual_fb && (viafb_primary_dev == LCD_Device) | ||
1961 | && (viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266)) | ||
1962 | unregister_framebuffer(viafbinfo1); | ||
1963 | out_dealloc_cmap: | ||
1964 | fb_dealloc_cmap(&viafbinfo->cmap); | ||
1965 | out_fb1_release: | ||
1966 | if (viafbinfo1) | ||
1967 | framebuffer_release(viafbinfo1); | ||
1968 | out_fb_release: | ||
1969 | framebuffer_release(viafbinfo); | ||
1970 | return rc; | ||
1940 | } | 1971 | } |
1941 | 1972 | ||
1942 | static void __devexit via_pci_remove(struct pci_dev *pdev) | 1973 | void __devexit via_fb_pci_remove(struct pci_dev *pdev) |
1943 | { | 1974 | { |
1944 | DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); | 1975 | DEBUG_MSG(KERN_INFO "via_pci_remove!\n"); |
1945 | fb_dealloc_cmap(&viafbinfo->cmap); | 1976 | fb_dealloc_cmap(&viafbinfo->cmap); |
1946 | unregister_framebuffer(viafbinfo); | 1977 | unregister_framebuffer(viafbinfo); |
1947 | if (viafb_dual_fb) | 1978 | if (viafb_dual_fb) |
1948 | unregister_framebuffer(viafbinfo1); | 1979 | unregister_framebuffer(viafbinfo1); |
1949 | iounmap((void *)viafbinfo->screen_base); | 1980 | #ifdef CONFIG_FB_VIA_DIRECT_PROCFS |
1950 | iounmap(viaparinfo->shared->engine_mmio); | 1981 | viafb_remove_proc(viaparinfo->shared->proc_entry); |
1951 | 1982 | #endif | |
1952 | viafb_delete_i2c_buss(viaparinfo); | ||
1953 | |||
1954 | framebuffer_release(viafbinfo); | 1983 | framebuffer_release(viafbinfo); |
1955 | if (viafb_dual_fb) | 1984 | if (viafb_dual_fb) |
1956 | framebuffer_release(viafbinfo1); | 1985 | framebuffer_release(viafbinfo1); |
1957 | |||
1958 | viafb_remove_proc(viaparinfo->shared->proc_entry); | ||
1959 | } | 1986 | } |
1960 | 1987 | ||
1961 | #ifndef MODULE | 1988 | #ifndef MODULE |
@@ -2031,41 +2058,10 @@ static int __init viafb_setup(char *options) | |||
2031 | } | 2058 | } |
2032 | #endif | 2059 | #endif |
2033 | 2060 | ||
2034 | static struct pci_device_id viafb_pci_table[] __devinitdata = { | 2061 | /* |
2035 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID), | 2062 | * These are called out of via-core for now. |
2036 | .driver_data = UNICHROME_CLE266 }, | 2063 | */ |
2037 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID), | 2064 | int __init viafb_init(void) |
2038 | .driver_data = UNICHROME_PM800 }, | ||
2039 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID), | ||
2040 | .driver_data = UNICHROME_K400 }, | ||
2041 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID), | ||
2042 | .driver_data = UNICHROME_K800 }, | ||
2043 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID), | ||
2044 | .driver_data = UNICHROME_CN700 }, | ||
2045 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID), | ||
2046 | .driver_data = UNICHROME_K8M890 }, | ||
2047 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID), | ||
2048 | .driver_data = UNICHROME_CX700 }, | ||
2049 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID), | ||
2050 | .driver_data = UNICHROME_P4M900 }, | ||
2051 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID), | ||
2052 | .driver_data = UNICHROME_CN750 }, | ||
2053 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID), | ||
2054 | .driver_data = UNICHROME_VX800 }, | ||
2055 | { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID), | ||
2056 | .driver_data = UNICHROME_VX855 }, | ||
2057 | { } | ||
2058 | }; | ||
2059 | MODULE_DEVICE_TABLE(pci, viafb_pci_table); | ||
2060 | |||
2061 | static struct pci_driver viafb_driver = { | ||
2062 | .name = "viafb", | ||
2063 | .id_table = viafb_pci_table, | ||
2064 | .probe = via_pci_probe, | ||
2065 | .remove = __devexit_p(via_pci_remove), | ||
2066 | }; | ||
2067 | |||
2068 | static int __init viafb_init(void) | ||
2069 | { | 2065 | { |
2070 | u32 dummy; | 2066 | u32 dummy; |
2071 | #ifndef MODULE | 2067 | #ifndef MODULE |
@@ -2084,13 +2080,12 @@ static int __init viafb_init(void) | |||
2084 | printk(KERN_INFO | 2080 | printk(KERN_INFO |
2085 | "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", | 2081 | "VIA Graphics Intergration Chipset framebuffer %d.%d initializing\n", |
2086 | VERSION_MAJOR, VERSION_MINOR); | 2082 | VERSION_MAJOR, VERSION_MINOR); |
2087 | return pci_register_driver(&viafb_driver); | 2083 | return 0; |
2088 | } | 2084 | } |
2089 | 2085 | ||
2090 | static void __exit viafb_exit(void) | 2086 | void __exit viafb_exit(void) |
2091 | { | 2087 | { |
2092 | DEBUG_MSG(KERN_INFO "viafb_exit!\n"); | 2088 | DEBUG_MSG(KERN_INFO "viafb_exit!\n"); |
2093 | pci_unregister_driver(&viafb_driver); | ||
2094 | } | 2089 | } |
2095 | 2090 | ||
2096 | static struct fb_ops viafb_ops = { | 2091 | static struct fb_ops viafb_ops = { |
@@ -2110,8 +2105,6 @@ static struct fb_ops viafb_ops = { | |||
2110 | .fb_sync = viafb_sync, | 2105 | .fb_sync = viafb_sync, |
2111 | }; | 2106 | }; |
2112 | 2107 | ||
2113 | module_init(viafb_init); | ||
2114 | module_exit(viafb_exit); | ||
2115 | 2108 | ||
2116 | #ifdef MODULE | 2109 | #ifdef MODULE |
2117 | module_param(viafb_mode, charp, S_IRUSR); | 2110 | module_param(viafb_mode, charp, S_IRUSR); |
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h index 61b5953cd159..52a35fabba91 100644 --- a/drivers/video/via/viafbdev.h +++ b/drivers/video/via/viafbdev.h | |||
@@ -24,12 +24,12 @@ | |||
24 | 24 | ||
25 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
26 | #include <linux/fb.h> | 26 | #include <linux/fb.h> |
27 | #include <linux/spinlock.h> | ||
27 | 28 | ||
28 | #include "ioctl.h" | 29 | #include "ioctl.h" |
29 | #include "share.h" | 30 | #include "share.h" |
30 | #include "chip.h" | 31 | #include "chip.h" |
31 | #include "hw.h" | 32 | #include "hw.h" |
32 | #include "via_i2c.h" | ||
33 | 33 | ||
34 | #define VERSION_MAJOR 2 | 34 | #define VERSION_MAJOR 2 |
35 | #define VERSION_KERNEL 6 /* For kernel 2.6 */ | 35 | #define VERSION_KERNEL 6 /* For kernel 2.6 */ |
@@ -37,11 +37,11 @@ | |||
37 | #define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */ | 37 | #define VERSION_OS 0 /* 0: for 32 bits OS, 1: for 64 bits OS */ |
38 | #define VERSION_MINOR 4 | 38 | #define VERSION_MINOR 4 |
39 | 39 | ||
40 | #define VIAFB_NUM_I2C 5 | ||
41 | |||
40 | struct viafb_shared { | 42 | struct viafb_shared { |
41 | struct proc_dir_entry *proc_entry; /*viafb proc entry */ | 43 | struct proc_dir_entry *proc_entry; /*viafb proc entry */ |
42 | 44 | struct viafb_dev *vdev; /* Global dev info */ | |
43 | /* I2C stuff */ | ||
44 | struct via_i2c_stuff i2c_stuff; | ||
45 | 45 | ||
46 | /* All the information will be needed to set engine */ | 46 | /* All the information will be needed to set engine */ |
47 | struct tmds_setting_information tmds_setting_info; | 47 | struct tmds_setting_information tmds_setting_info; |
@@ -51,7 +51,6 @@ struct viafb_shared { | |||
51 | struct chip_information chip_info; | 51 | struct chip_information chip_info; |
52 | 52 | ||
53 | /* hardware acceleration stuff */ | 53 | /* hardware acceleration stuff */ |
54 | void __iomem *engine_mmio; | ||
55 | u32 cursor_vram_addr; | 54 | u32 cursor_vram_addr; |
56 | u32 vq_vram_addr; /* virtual queue address in video ram */ | 55 | u32 vq_vram_addr; /* virtual queue address in video ram */ |
57 | int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height, | 56 | int (*hw_bitblt)(void __iomem *engine, u8 op, u32 width, u32 height, |
@@ -99,4 +98,9 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information | |||
99 | void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information | 98 | void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information |
100 | *plvds_setting_info, struct lvds_chip_information | 99 | *plvds_setting_info, struct lvds_chip_information |
101 | *plvds_chip_info, struct IODATA io_data); | 100 | *plvds_chip_info, struct IODATA io_data); |
101 | int via_fb_pci_probe(struct viafb_dev *vdev); | ||
102 | void via_fb_pci_remove(struct pci_dev *pdev); | ||
103 | /* Temporary */ | ||
104 | int viafb_init(void); | ||
105 | void viafb_exit(void); | ||
102 | #endif /* __VIAFBDEV_H__ */ | 106 | #endif /* __VIAFBDEV_H__ */ |
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index af50e244016c..2dbad3c0f679 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/via-core.h> | ||
22 | #include "global.h" | 23 | #include "global.h" |
23 | struct res_map_refresh res_map_refresh_tbl[] = { | 24 | struct res_map_refresh res_map_refresh_tbl[] = { |
24 | /*hres, vres, vclock, vmode_refresh*/ | 25 | /*hres, vres, vclock, vmode_refresh*/ |
@@ -66,6 +67,7 @@ struct res_map_refresh res_map_refresh_tbl[] = { | |||
66 | {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60}, | 67 | {1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60}, |
67 | {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60}, | 68 | {1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60}, |
68 | {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60}, | 69 | {1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60}, |
70 | {1200, 900, RES_1200X900_60HZ_PIXCLOCK, 60}, | ||
69 | {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60}, | 71 | {1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60}, |
70 | {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50}, | 72 | {1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50}, |
71 | {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50}, | 73 | {1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50}, |
@@ -759,6 +761,16 @@ struct crt_mode_table CRTM1200x720[] = { | |||
759 | {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} } | 761 | {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} } |
760 | }; | 762 | }; |
761 | 763 | ||
764 | /* 1200x900 (DCON) */ | ||
765 | struct crt_mode_table DCON1200x900[] = { | ||
766 | /* r_rate, vclk, hsp, vsp */ | ||
767 | {REFRESH_60, CLK_57_275M, M1200X900_R60_HSP, M1200X900_R60_VSP, | ||
768 | /* The correct htotal is 1240, but this doesn't raster on VX855. */ | ||
769 | /* Via suggested changing to a multiple of 16, hence 1264. */ | ||
770 | /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | ||
771 | {1264, 1200, 1200, 64, 1211, 32, 912, 900, 900, 12, 901, 10} } | ||
772 | }; | ||
773 | |||
762 | /* 1280x600 (GTF) */ | 774 | /* 1280x600 (GTF) */ |
763 | struct crt_mode_table CRTM1280x600[] = { | 775 | struct crt_mode_table CRTM1280x600[] = { |
764 | /* r_rate, vclk, hsp, vsp */ | 776 | /* r_rate, vclk, hsp, vsp */ |
@@ -937,6 +949,9 @@ struct VideoModeTable viafb_modes[] = { | |||
937 | /* Display : 1200x720 (GTF) */ | 949 | /* Display : 1200x720 (GTF) */ |
938 | {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, | 950 | {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)}, |
939 | 951 | ||
952 | /* Display : 1200x900 (DCON) */ | ||
953 | {DCON1200x900, ARRAY_SIZE(DCON1200x900)}, | ||
954 | |||
940 | /* Display : 1280x600 (GTF) */ | 955 | /* Display : 1280x600 (GTF) */ |
941 | {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, | 956 | {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)}, |
942 | 957 | ||
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c index a6b37494e79a..d65bf1aee87c 100644 --- a/drivers/video/via/vt1636.c +++ b/drivers/video/via/vt1636.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/via-core.h> | ||
23 | #include <linux/via_i2c.h> | ||
22 | #include "global.h" | 24 | #include "global.h" |
23 | 25 | ||
24 | u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information | 26 | u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information |
@@ -27,9 +29,8 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information | |||
27 | { | 29 | { |
28 | u8 data; | 30 | u8 data; |
29 | 31 | ||
30 | viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; | 32 | viafb_i2c_readbyte(plvds_chip_info->i2c_port, |
31 | viafb_i2c_readbyte(plvds_chip_info->lvds_chip_slave_addr, index, &data); | 33 | plvds_chip_info->lvds_chip_slave_addr, index, &data); |
32 | |||
33 | return data; | 34 | return data; |
34 | } | 35 | } |
35 | 36 | ||
@@ -39,14 +40,13 @@ void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information | |||
39 | { | 40 | { |
40 | int index, data; | 41 | int index, data; |
41 | 42 | ||
42 | viaparinfo->shared->i2c_stuff.i2c_port = plvds_chip_info->i2c_port; | ||
43 | |||
44 | index = io_data.Index; | 43 | index = io_data.Index; |
45 | data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info, | 44 | data = viafb_gpio_i2c_read_lvds(plvds_setting_info, plvds_chip_info, |
46 | index); | 45 | index); |
47 | data = (data & (~io_data.Mask)) | io_data.Data; | 46 | data = (data & (~io_data.Mask)) | io_data.Data; |
48 | 47 | ||
49 | viafb_i2c_writebyte(plvds_chip_info->lvds_chip_slave_addr, index, data); | 48 | viafb_i2c_writebyte(plvds_chip_info->i2c_port, |
49 | plvds_chip_info->lvds_chip_slave_addr, index, data); | ||
50 | } | 50 | } |
51 | 51 | ||
52 | void viafb_init_lvds_vt1636(struct lvds_setting_information | 52 | void viafb_init_lvds_vt1636(struct lvds_setting_information |
@@ -159,7 +159,7 @@ void viafb_disable_lvds_vt1636(struct lvds_setting_information | |||
159 | } | 159 | } |
160 | } | 160 | } |
161 | 161 | ||
162 | bool viafb_lvds_identify_vt1636(void) | 162 | bool viafb_lvds_identify_vt1636(u8 i2c_adapter) |
163 | { | 163 | { |
164 | u8 Buffer[2]; | 164 | u8 Buffer[2]; |
165 | 165 | ||
@@ -167,26 +167,20 @@ bool viafb_lvds_identify_vt1636(void) | |||
167 | 167 | ||
168 | /* Sense VT1636 LVDS Transmiter */ | 168 | /* Sense VT1636 LVDS Transmiter */ |
169 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = | 169 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = |
170 | VT1636_LVDS_I2C_ADDR; | 170 | VT1636_LVDS_I2C_ADDR; |
171 | 171 | ||
172 | /* Check vendor ID first: */ | 172 | /* Check vendor ID first: */ |
173 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | 173 | if (viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, |
174 | lvds_chip_slave_addr, | 174 | 0x00, &Buffer[0])) |
175 | 0x00, &Buffer[0]); | 175 | return false; |
176 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | 176 | viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x01, &Buffer[1]); |
177 | lvds_chip_slave_addr, | ||
178 | 0x01, &Buffer[1]); | ||
179 | 177 | ||
180 | if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11))) | 178 | if (!((Buffer[0] == 0x06) && (Buffer[1] == 0x11))) |
181 | return false; | 179 | return false; |
182 | 180 | ||
183 | /* Check Chip ID: */ | 181 | /* Check Chip ID: */ |
184 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | 182 | viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x02, &Buffer[0]); |
185 | lvds_chip_slave_addr, | 183 | viafb_i2c_readbyte(i2c_adapter, VT1636_LVDS_I2C_ADDR, 0x03, &Buffer[1]); |
186 | 0x02, &Buffer[0]); | ||
187 | viafb_i2c_readbyte((u8) viaparinfo->chip_info->lvds_chip_info. | ||
188 | lvds_chip_slave_addr, | ||
189 | 0x03, &Buffer[1]); | ||
190 | if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) { | 184 | if ((Buffer[0] == 0x45) && (Buffer[1] == 0x33)) { |
191 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = | 185 | viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = |
192 | VT1636_LVDS; | 186 | VT1636_LVDS; |
diff --git a/drivers/video/via/vt1636.h b/drivers/video/via/vt1636.h index 2a150c58c7ed..4c1314e57468 100644 --- a/drivers/video/via/vt1636.h +++ b/drivers/video/via/vt1636.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #ifndef _VT1636_H_ | 22 | #ifndef _VT1636_H_ |
23 | #define _VT1636_H_ | 23 | #define _VT1636_H_ |
24 | #include "chip.h" | 24 | #include "chip.h" |
25 | bool viafb_lvds_identify_vt1636(void); | 25 | bool viafb_lvds_identify_vt1636(u8 i2c_adapter); |
26 | void viafb_init_lvds_vt1636(struct lvds_setting_information | 26 | void viafb_init_lvds_vt1636(struct lvds_setting_information |
27 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); | 27 | *plvds_setting_info, struct lvds_chip_information *plvds_chip_info); |
28 | void viafb_enable_lvds_vt1636(struct lvds_setting_information | 28 | void viafb_enable_lvds_vt1636(struct lvds_setting_information |