aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-05-22 02:36:56 -0400
committerGrant Likely <grant.likely@secretlab.ca>2010-05-22 02:36:56 -0400
commitcf9b59e9d3e008591d1f54830f570982bb307a0d (patch)
tree113478ce8fd8c832ba726ffdf59b82cb46356476 /drivers/video
parent44504b2bebf8b5823c59484e73096a7d6574471d (diff)
parentf4b87dee923342505e1ddba8d34ce9de33e75050 (diff)
Merge remote branch 'origin' into secretlab/next-devicetree
Merging in current state of Linus' tree to deal with merge conflicts and build failures in vio.c after merge. Conflicts: drivers/i2c/busses/i2c-cpm.c drivers/i2c/busses/i2c-mpc.c drivers/net/gianfar.c Also fixed up one line in arch/powerpc/kernel/vio.c to use the correct node pointer. Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig17
-rw-r--r--drivers/video/amifb.c49
-rw-r--r--drivers/video/aty/radeon_base.c4
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c15
-rw-r--r--drivers/video/cirrusfb.c1
-rw-r--r--drivers/video/cobalt_lcdfb.c2
-rw-r--r--drivers/video/efifb.c14
-rw-r--r--drivers/video/fbmem.c77
-rw-r--r--drivers/video/fbsysfs.c1
-rw-r--r--drivers/video/fm2fb.c1
-rw-r--r--drivers/video/mx3fb.c3
-rw-r--r--drivers/video/offb.c28
-rw-r--r--drivers/video/omap2/displays/Kconfig9
-rw-r--r--drivers/video/omap2/displays/Makefile1
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c819
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c78
-rw-r--r--drivers/video/omap2/displays/panel-taal.c143
-rw-r--r--drivers/video/omap2/dss/Kconfig6
-rw-r--r--drivers/video/omap2/dss/Makefile3
-rw-r--r--drivers/video/omap2/dss/core.c85
-rw-r--r--drivers/video/omap2/dss/display.c9
-rw-r--r--drivers/video/omap2/dss/dss.c24
-rw-r--r--drivers/video/omap2/dss/dss.h50
-rw-r--r--drivers/video/omap2/dss/manager.c21
-rw-r--r--drivers/video/omap2/dss/sdi.c26
-rw-r--r--drivers/video/omap2/dss/venc.c15
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c5
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c25
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c27
-rw-r--r--drivers/video/vesafb.c11
-rw-r--r--drivers/video/vga16fb.c26
-rw-r--r--drivers/video/via/Makefile4
-rw-r--r--drivers/video/via/accel.c137
-rw-r--r--drivers/video/via/accel.h40
-rw-r--r--drivers/video/via/chip.h8
-rw-r--r--drivers/video/via/dvi.c37
-rw-r--r--drivers/video/via/global.h1
-rw-r--r--drivers/video/via/hw.c307
-rw-r--r--drivers/video/via/hw.h20
-rw-r--r--drivers/video/via/ioctl.h2
-rw-r--r--drivers/video/via/lcd.c31
-rw-r--r--drivers/video/via/lcd.h2
-rw-r--r--drivers/video/via/share.h20
-rw-r--r--drivers/video/via/via-core.c668
-rw-r--r--drivers/video/via/via-gpio.c285
-rw-r--r--drivers/video/via/via_i2c.c232
-rw-r--r--drivers/video/via/via_modesetting.c126
-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.c1
-rw-r--r--drivers/video/via/viafbdev.c181
-rw-r--r--drivers/video/via/viafbdev.h14
-rw-r--r--drivers/video/via/viamode.c15
-rw-r--r--drivers/video/via/vt1636.c34
-rw-r--r--drivers/video/via/vt1636.h2
54 files changed, 3034 insertions, 770 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6e16244f3ed..1e6fec48797 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1511,6 +1511,7 @@ config FB_VIA
1511 select FB_CFB_IMAGEBLIT 1511 select FB_CFB_IMAGEBLIT
1512 select I2C_ALGOBIT 1512 select I2C_ALGOBIT
1513 select I2C 1513 select I2C
1514 select GPIOLIB
1514 help 1515 help
1515 This is the frame buffer device driver for Graphics chips of VIA 1516 This is the frame buffer device driver for Graphics chips of VIA
1516 UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ 1517 UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/
@@ -1520,6 +1521,21 @@ config FB_VIA
1520 1521
1521 To compile this driver as a module, choose M here: the 1522 To compile this driver as a module, choose M here: the
1522 module will be called viafb. 1523 module will be called viafb.
1524
1525if FB_VIA
1526
1527config FB_VIA_DIRECT_PROCFS
1528 bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
1529 depends on FB_VIA
1530 default n
1531 help
1532 Allow direct hardware access to some output registers via procfs.
1533 This is dangerous but may provide the only chance to get the
1534 correct output device configuration.
1535 Its use is strongly discouraged.
1536
1537endif
1538
1523config FB_NEOMAGIC 1539config FB_NEOMAGIC
1524 tristate "NeoMagic display support" 1540 tristate "NeoMagic display support"
1525 depends on FB && PCI 1541 depends on FB && PCI
@@ -2186,7 +2202,6 @@ config FB_MSM
2186 select FB_CFB_FILLRECT 2202 select FB_CFB_FILLRECT
2187 select FB_CFB_COPYAREA 2203 select FB_CFB_COPYAREA
2188 select FB_CFB_IMAGEBLIT 2204 select FB_CFB_IMAGEBLIT
2189 default y
2190 2205
2191config FB_MX3 2206config FB_MX3
2192 tristate "MX3 Framebuffer support" 2207 tristate "MX3 Framebuffer support"
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index dca48df9844..e5d6b56d444 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -50,8 +50,9 @@
50#include <linux/fb.h> 50#include <linux/fb.h>
51#include <linux/init.h> 51#include <linux/init.h>
52#include <linux/ioport.h> 52#include <linux/ioport.h>
53 53#include <linux/platform_device.h>
54#include <linux/uaccess.h> 54#include <linux/uaccess.h>
55
55#include <asm/system.h> 56#include <asm/system.h>
56#include <asm/irq.h> 57#include <asm/irq.h>
57#include <asm/amigahw.h> 58#include <asm/amigahw.h>
@@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg
1135 * Interface to the low level console driver 1136 * Interface to the low level console driver
1136 */ 1137 */
1137 1138
1138static void amifb_deinit(void); 1139static void amifb_deinit(struct platform_device *pdev);
1139 1140
1140 /* 1141 /*
1141 * Internal routines 1142 * Internal routines
@@ -2246,7 +2247,7 @@ static inline void chipfree(void)
2246 * Initialisation 2247 * Initialisation
2247 */ 2248 */
2248 2249
2249static int __init amifb_init(void) 2250static int __init amifb_probe(struct platform_device *pdev)
2250{ 2251{
2251 int tag, i, err = 0; 2252 int tag, i, err = 0;
2252 u_long chipptr; 2253 u_long chipptr;
@@ -2261,16 +2262,6 @@ static int __init amifb_init(void)
2261 } 2262 }
2262 amifb_setup(option); 2263 amifb_setup(option);
2263#endif 2264#endif
2264 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
2265 return -ENODEV;
2266
2267 /*
2268 * We request all registers starting from bplpt[0]
2269 */
2270 if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
2271 "amifb [Denise/Lisa]"))
2272 return -EBUSY;
2273
2274 custom.dmacon = DMAF_ALL | DMAF_MASTER; 2265 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2275 2266
2276 switch (amiga_chipset) { 2267 switch (amiga_chipset) {
@@ -2377,6 +2368,7 @@ default_chipset:
2377 fb_info.fbops = &amifb_ops; 2368 fb_info.fbops = &amifb_ops;
2378 fb_info.par = &currentpar; 2369 fb_info.par = &currentpar;
2379 fb_info.flags = FBINFO_DEFAULT; 2370 fb_info.flags = FBINFO_DEFAULT;
2371 fb_info.device = &pdev->dev;
2380 2372
2381 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, 2373 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
2382 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { 2374 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
@@ -2451,18 +2443,18 @@ default_chipset:
2451 return 0; 2443 return 0;
2452 2444
2453amifb_error: 2445amifb_error:
2454 amifb_deinit(); 2446 amifb_deinit(pdev);
2455 return err; 2447 return err;
2456} 2448}
2457 2449
2458static void amifb_deinit(void) 2450static void amifb_deinit(struct platform_device *pdev)
2459{ 2451{
2460 if (fb_info.cmap.len) 2452 if (fb_info.cmap.len)
2461 fb_dealloc_cmap(&fb_info.cmap); 2453 fb_dealloc_cmap(&fb_info.cmap);
2454 fb_dealloc_cmap(&fb_info.cmap);
2462 chipfree(); 2455 chipfree();
2463 if (videomemory) 2456 if (videomemory)
2464 iounmap((void*)videomemory); 2457 iounmap((void*)videomemory);
2465 release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
2466 custom.dmacon = DMAF_ALL | DMAF_MASTER; 2458 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2467} 2459}
2468 2460
@@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void)
3794 } 3786 }
3795} 3787}
3796 3788
3797static void __exit amifb_exit(void) 3789static int __exit amifb_remove(struct platform_device *pdev)
3798{ 3790{
3799 unregister_framebuffer(&fb_info); 3791 unregister_framebuffer(&fb_info);
3800 amifb_deinit(); 3792 amifb_deinit(pdev);
3801 amifb_video_off(); 3793 amifb_video_off();
3794 return 0;
3795}
3796
3797static struct platform_driver amifb_driver = {
3798 .remove = __exit_p(amifb_remove),
3799 .driver = {
3800 .name = "amiga-video",
3801 .owner = THIS_MODULE,
3802 },
3803};
3804
3805static int __init amifb_init(void)
3806{
3807 return platform_driver_probe(&amifb_driver, amifb_probe);
3802} 3808}
3803 3809
3804module_init(amifb_init); 3810module_init(amifb_init);
3811
3812static void __exit amifb_exit(void)
3813{
3814 platform_driver_unregister(&amifb_driver);
3815}
3816
3805module_exit(amifb_exit); 3817module_exit(amifb_exit);
3806 3818
3807MODULE_LICENSE("GPL"); 3819MODULE_LICENSE("GPL");
3820MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 6c37e8ee5ef..3c1e13ed1cb 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2099,7 +2099,7 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u
2099} 2099}
2100 2100
2101 2101
2102static ssize_t radeon_show_edid1(struct kobject *kobj, 2102static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj,
2103 struct bin_attribute *bin_attr, 2103 struct bin_attribute *bin_attr,
2104 char *buf, loff_t off, size_t count) 2104 char *buf, loff_t off, size_t count)
2105{ 2105{
@@ -2112,7 +2112,7 @@ static ssize_t radeon_show_edid1(struct kobject *kobj,
2112} 2112}
2113 2113
2114 2114
2115static ssize_t radeon_show_edid2(struct kobject *kobj, 2115static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj,
2116 struct bin_attribute *bin_attr, 2116 struct bin_attribute *bin_attr,
2117 char *buf, loff_t off, size_t count) 2117 char *buf, loff_t off, size_t count)
2118{ 2118{
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 44e49c28b2a..c2ec3dcd4e9 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -488,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
488 fbinfo->fbops = &bfin_t350mcqb_fb_ops; 488 fbinfo->fbops = &bfin_t350mcqb_fb_ops;
489 fbinfo->flags = FBINFO_FLAG_DEFAULT; 489 fbinfo->flags = FBINFO_FLAG_DEFAULT;
490 490
491 info->fb_buffer = 491 info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len +
492 dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, 492 ACTIVE_VIDEO_MEM_OFFSET,
493 GFP_KERNEL); 493 &info->dma_handle, GFP_KERNEL);
494 494
495 if (NULL == info->fb_buffer) { 495 if (NULL == info->fb_buffer) {
496 printk(KERN_ERR DRIVER_NAME 496 printk(KERN_ERR DRIVER_NAME
@@ -568,8 +568,8 @@ out7:
568out6: 568out6:
569 fb_dealloc_cmap(&fbinfo->cmap); 569 fb_dealloc_cmap(&fbinfo->cmap);
570out4: 570out4:
571 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 571 dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET,
572 info->dma_handle); 572 info->fb_buffer, info->dma_handle);
573out3: 573out3:
574 framebuffer_release(fbinfo); 574 framebuffer_release(fbinfo);
575out2: 575out2:
@@ -592,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev)
592 free_irq(info->irq, info); 592 free_irq(info->irq, info);
593 593
594 if (info->fb_buffer != NULL) 594 if (info->fb_buffer != NULL)
595 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 595 dma_free_coherent(NULL, fbinfo->fix.smem_len +
596 info->dma_handle); 596 ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer,
597 info->dma_handle);
597 598
598 fb_dealloc_cmap(&fbinfo->cmap); 599 fb_dealloc_cmap(&fbinfo->cmap);
599 600
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 8d8dfda2f86..6df7c54db0a 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = {
299 }, 299 },
300 { 0 } 300 { 0 }
301}; 301};
302MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
302 303
303static const struct { 304static const struct {
304 zorro_id id2; 305 zorro_id id2;
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 5eb61b5adfe..42fe155aba0 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -123,7 +123,7 @@ static void lcd_clear(struct fb_info *info)
123 lcd_write_control(info, LCD_RESET); 123 lcd_write_control(info, LCD_RESET);
124} 124}
125 125
126static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = { 126static struct fb_fix_screeninfo cobalt_lcdfb_fix __devinitdata = {
127 .id = "cobalt-lcd", 127 .id = "cobalt-lcd",
128 .type = FB_TYPE_TEXT, 128 .type = FB_TYPE_TEXT,
129 .type_aux = FB_AUX_TEXT_MDA, 129 .type_aux = FB_AUX_TEXT_MDA,
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index 581d2dbf675..4a56f46af40 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -49,6 +49,7 @@ enum {
49 M_MBP_2, /* MacBook Pro 2nd gen */ 49 M_MBP_2, /* MacBook Pro 2nd gen */
50 M_MBP_SR, /* MacBook Pro (Santa Rosa) */ 50 M_MBP_SR, /* MacBook Pro (Santa Rosa) */
51 M_MBP_4, /* MacBook Pro, 4th gen */ 51 M_MBP_4, /* MacBook Pro, 4th gen */
52 M_MBP_5_1, /* MacBook Pro, 5,1th gen */
52 M_UNKNOWN /* placeholder */ 53 M_UNKNOWN /* placeholder */
53}; 54};
54 55
@@ -70,6 +71,7 @@ static struct efifb_dmi_info {
70 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */ 71 [M_MBP_2] = { "mbp2", 0, 0, 0, 0 }, /* placeholder */
71 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 }, 72 [M_MBP_SR] = { "mbp3", 0x80030000, 2048 * 4, 1440, 900 },
72 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 }, 73 [M_MBP_4] = { "mbp4", 0xc0060000, 2048 * 4, 1920, 1200 },
74 [M_MBP_5_1] = { "mbp51", 0xc0010000, 2048 * 4, 1440, 900 },
73 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 } 75 [M_UNKNOWN] = { NULL, 0, 0, 0, 0 }
74}; 76};
75 77
@@ -106,6 +108,7 @@ static struct dmi_system_id __initdata dmi_system_table[] = {
106 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR), 108 EFIFB_DMI_SYSTEM_ID("Apple Computer, Inc.", "MacBookPro3,1", M_MBP_SR),
107 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR), 109 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro3,1", M_MBP_SR),
108 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4), 110 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro4,1", M_MBP_4),
111 EFIFB_DMI_SYSTEM_ID("Apple Inc.", "MacBookPro5,1", M_MBP_5_1),
109 {}, 112 {},
110}; 113};
111 114
@@ -165,7 +168,7 @@ static void efifb_destroy(struct fb_info *info)
165{ 168{
166 if (info->screen_base) 169 if (info->screen_base)
167 iounmap(info->screen_base); 170 iounmap(info->screen_base);
168 release_mem_region(info->aperture_base, info->aperture_size); 171 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
169 framebuffer_release(info); 172 framebuffer_release(info);
170} 173}
171 174
@@ -289,8 +292,13 @@ static int __devinit efifb_probe(struct platform_device *dev)
289 info->pseudo_palette = info->par; 292 info->pseudo_palette = info->par;
290 info->par = NULL; 293 info->par = NULL;
291 294
292 info->aperture_base = efifb_fix.smem_start; 295 info->apertures = alloc_apertures(1);
293 info->aperture_size = size_remap; 296 if (!info->apertures) {
297 err = -ENOMEM;
298 goto err_release_fb;
299 }
300 info->apertures->ranges[0].base = efifb_fix.smem_start;
301 info->apertures->ranges[0].size = size_remap;
294 302
295 info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); 303 info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len);
296 if (!info->screen_base) { 304 if (!info->screen_base) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index a15b44e9c00..731fce64df9 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1468,16 +1468,70 @@ static int fb_check_foreignness(struct fb_info *fi)
1468 return 0; 1468 return 0;
1469} 1469}
1470 1470
1471static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) 1471static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
1472{ 1472{
1473 /* is the generic aperture base the same as the HW one */ 1473 /* is the generic aperture base the same as the HW one */
1474 if (gen->aperture_base == hw->aperture_base) 1474 if (gen->base == hw->base)
1475 return true; 1475 return true;
1476 /* is the generic aperture base inside the hw base->hw base+size */ 1476 /* is the generic aperture base inside the hw base->hw base+size */
1477 if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) 1477 if (gen->base > hw->base && gen->base <= hw->base + hw->size)
1478 return true; 1478 return true;
1479 return false; 1479 return false;
1480} 1480}
1481
1482static bool fb_do_apertures_overlap(struct apertures_struct *gena,
1483 struct apertures_struct *hwa)
1484{
1485 int i, j;
1486 if (!hwa || !gena)
1487 return false;
1488
1489 for (i = 0; i < hwa->count; ++i) {
1490 struct aperture *h = &hwa->ranges[i];
1491 for (j = 0; j < gena->count; ++j) {
1492 struct aperture *g = &gena->ranges[j];
1493 printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
1494 (unsigned long long)g->base,
1495 (unsigned long long)g->size,
1496 (unsigned long long)h->base,
1497 (unsigned long long)h->size);
1498 if (apertures_overlap(g, h))
1499 return true;
1500 }
1501 }
1502
1503 return false;
1504}
1505
1506#define VGA_FB_PHYS 0xA0000
1507void remove_conflicting_framebuffers(struct apertures_struct *a,
1508 const char *name, bool primary)
1509{
1510 int i;
1511
1512 /* check all firmware fbs and kick off if the base addr overlaps */
1513 for (i = 0 ; i < FB_MAX; i++) {
1514 struct apertures_struct *gen_aper;
1515 if (!registered_fb[i])
1516 continue;
1517
1518 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
1519 continue;
1520
1521 gen_aper = registered_fb[i]->apertures;
1522 if (fb_do_apertures_overlap(gen_aper, a) ||
1523 (primary && gen_aper && gen_aper->count &&
1524 gen_aper->ranges[0].base == VGA_FB_PHYS)) {
1525
1526 printk(KERN_ERR "fb: conflicting fb hw usage "
1527 "%s vs %s - removing generic driver\n",
1528 name, registered_fb[i]->fix.id);
1529 unregister_framebuffer(registered_fb[i]);
1530 }
1531 }
1532}
1533EXPORT_SYMBOL(remove_conflicting_framebuffers);
1534
1481/** 1535/**
1482 * register_framebuffer - registers a frame buffer device 1536 * register_framebuffer - registers a frame buffer device
1483 * @fb_info: frame buffer info structure 1537 * @fb_info: frame buffer info structure
@@ -1501,21 +1555,8 @@ register_framebuffer(struct fb_info *fb_info)
1501 if (fb_check_foreignness(fb_info)) 1555 if (fb_check_foreignness(fb_info))
1502 return -ENOSYS; 1556 return -ENOSYS;
1503 1557
1504 /* check all firmware fbs and kick off if the base addr overlaps */ 1558 remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
1505 for (i = 0 ; i < FB_MAX; i++) { 1559 fb_is_primary_device(fb_info));
1506 if (!registered_fb[i])
1507 continue;
1508
1509 if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) {
1510 if (fb_do_apertures_overlap(registered_fb[i], fb_info)) {
1511 printk(KERN_ERR "fb: conflicting fb hw usage "
1512 "%s vs %s - removing generic driver\n",
1513 fb_info->fix.id,
1514 registered_fb[i]->fix.id);
1515 unregister_framebuffer(registered_fb[i]);
1516 }
1517 }
1518 }
1519 1560
1520 num_registered_fb++; 1561 num_registered_fb++;
1521 for (i = 0 ; i < FB_MAX; i++) 1562 for (i = 0 ; i < FB_MAX; i++)
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 81aa3129c17..0a08f134122 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -80,6 +80,7 @@ EXPORT_SYMBOL(framebuffer_alloc);
80 */ 80 */
81void framebuffer_release(struct fb_info *info) 81void framebuffer_release(struct fb_info *info)
82{ 82{
83 kfree(info->apertures);
83 kfree(info); 84 kfree(info);
84} 85}
85EXPORT_SYMBOL(framebuffer_release); 86EXPORT_SYMBOL(framebuffer_release);
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c
index 6c91c61cdb6..1b0feb8e724 100644
--- a/drivers/video/fm2fb.c
+++ b/drivers/video/fm2fb.c
@@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = {
219 { ZORRO_PROD_HELFRICH_RAINBOW_II }, 219 { ZORRO_PROD_HELFRICH_RAINBOW_II },
220 { 0 } 220 { 0 }
221}; 221};
222MODULE_DEVICE_TABLE(zorro, fm2fb_devices);
222 223
223static struct zorro_driver fm2fb_driver = { 224static struct zorro_driver fm2fb_driver = {
224 .name = "fm2fb", 225 .name = "fm2fb",
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index 772ba3f45e6..7cfc170bce1 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -387,7 +387,8 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi)
387 387
388 spin_unlock_irqrestore(&mx3fb->lock, flags); 388 spin_unlock_irqrestore(&mx3fb->lock, flags);
389 389
390 mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan); 390 mx3_fbi->txd->chan->device->device_control(mx3_fbi->txd->chan,
391 DMA_TERMINATE_ALL, 0);
391 mx3_fbi->txd = NULL; 392 mx3_fbi->txd = NULL;
392 mx3_fbi->cookie = -EINVAL; 393 mx3_fbi->cookie = -EINVAL;
393} 394}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index 61f8b8f919b..46dda7d8aae 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -285,7 +285,7 @@ static void offb_destroy(struct fb_info *info)
285{ 285{
286 if (info->screen_base) 286 if (info->screen_base)
287 iounmap(info->screen_base); 287 iounmap(info->screen_base);
288 release_mem_region(info->aperture_base, info->aperture_size); 288 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
289 framebuffer_release(info); 289 framebuffer_release(info);
290} 290}
291 291
@@ -491,8 +491,11 @@ static void __init offb_init_fb(const char *name, const char *full_name,
491 var->vmode = FB_VMODE_NONINTERLACED; 491 var->vmode = FB_VMODE_NONINTERLACED;
492 492
493 /* set offb aperture size for generic probing */ 493 /* set offb aperture size for generic probing */
494 info->aperture_base = address; 494 info->apertures = alloc_apertures(1);
495 info->aperture_size = fix->smem_len; 495 if (!info->apertures)
496 goto out_aper;
497 info->apertures->ranges[0].base = address;
498 info->apertures->ranges[0].size = fix->smem_len;
496 499
497 info->fbops = &offb_ops; 500 info->fbops = &offb_ops;
498 info->screen_base = ioremap(address, fix->smem_len); 501 info->screen_base = ioremap(address, fix->smem_len);
@@ -501,17 +504,20 @@ static void __init offb_init_fb(const char *name, const char *full_name,
501 504
502 fb_alloc_cmap(&info->cmap, 256, 0); 505 fb_alloc_cmap(&info->cmap, 256, 0);
503 506
504 if (register_framebuffer(info) < 0) { 507 if (register_framebuffer(info) < 0)
505 iounmap(par->cmap_adr); 508 goto out_err;
506 par->cmap_adr = NULL;
507 iounmap(info->screen_base);
508 framebuffer_release(info);
509 release_mem_region(res_start, res_size);
510 return;
511 }
512 509
513 printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", 510 printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n",
514 info->node, full_name); 511 info->node, full_name);
512 return;
513
514out_err:
515 iounmap(info->screen_base);
516out_aper:
517 iounmap(par->cmap_adr);
518 par->cmap_adr = NULL;
519 framebuffer_release(info);
520 release_mem_region(res_start, res_size);
515} 521}
516 522
517 523
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index dfb57ee5086..881c9f77c75 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,6 +10,7 @@ config PANEL_GENERIC
10config PANEL_SHARP_LS037V7DW01 10config PANEL_SHARP_LS037V7DW01
11 tristate "Sharp LS037V7DW01 LCD Panel" 11 tristate "Sharp LS037V7DW01 LCD Panel"
12 depends on OMAP2_DSS 12 depends on OMAP2_DSS
13 select BACKLIGHT_CLASS_DEVICE
13 help 14 help
14 LCD Panel used in TI's SDP3430 and EVM boards 15 LCD Panel used in TI's SDP3430 and EVM boards
15 16
@@ -33,8 +34,14 @@ config PANEL_TOPPOLY_TDO35S
33 34
34config PANEL_TPO_TD043MTEA1 35config PANEL_TPO_TD043MTEA1
35 tristate "TPO TD043MTEA1 LCD Panel" 36 tristate "TPO TD043MTEA1 LCD Panel"
36 depends on OMAP2_DSS && I2C 37 depends on OMAP2_DSS && SPI
37 help 38 help
38 LCD Panel used in OMAP3 Pandora 39 LCD Panel used in OMAP3 Pandora
39 40
41config PANEL_ACX565AKM
42 tristate "ACX565AKM Panel"
43 depends on OMAP2_DSS_SDI
44 select BACKLIGHT_CLASS_DEVICE
45 help
46 This is the LCD panel used on Nokia N900
40endmenu 47endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index e2bb32168de..aa386095d7c 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
5obj-$(CONFIG_PANEL_TAAL) += panel-taal.o 5obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
6obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o 6obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
new file mode 100644
index 00000000000..1f8eb70e293
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -0,0 +1,819 @@
1/*
2 * Support for ACX565AKM LCD Panel used on Nokia N900
3 *
4 * Copyright (C) 2010 Nokia Corporation
5 *
6 * Original Driver Author: Imre Deak <imre.deak@nokia.com>
7 * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
8 * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/delay.h>
27#include <linux/spi/spi.h>
28#include <linux/jiffies.h>
29#include <linux/sched.h>
30#include <linux/backlight.h>
31#include <linux/fb.h>
32
33#include <plat/display.h>
34
35#define MIPID_CMD_READ_DISP_ID 0x04
36#define MIPID_CMD_READ_RED 0x06
37#define MIPID_CMD_READ_GREEN 0x07
38#define MIPID_CMD_READ_BLUE 0x08
39#define MIPID_CMD_READ_DISP_STATUS 0x09
40#define MIPID_CMD_RDDSDR 0x0F
41#define MIPID_CMD_SLEEP_IN 0x10
42#define MIPID_CMD_SLEEP_OUT 0x11
43#define MIPID_CMD_DISP_OFF 0x28
44#define MIPID_CMD_DISP_ON 0x29
45#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
46#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
47#define MIPID_CMD_WRITE_CTRL_DISP 0x53
48
49#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
50#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
51#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
52#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
53
54#define MIPID_CMD_READ_CTRL_DISP 0x54
55#define MIPID_CMD_WRITE_CABC 0x55
56#define MIPID_CMD_READ_CABC 0x56
57
58#define MIPID_VER_LPH8923 3
59#define MIPID_VER_LS041Y3 4
60#define MIPID_VER_L4F00311 8
61#define MIPID_VER_ACX565AKM 9
62
63struct acx565akm_device {
64 char *name;
65 int enabled;
66 int model;
67 int revision;
68 u8 display_id[3];
69 unsigned has_bc:1;
70 unsigned has_cabc:1;
71 unsigned cabc_mode;
72 unsigned long hw_guard_end; /* next value of jiffies
73 when we can issue the
74 next sleep in/out command */
75 unsigned long hw_guard_wait; /* max guard time in jiffies */
76
77 struct spi_device *spi;
78 struct mutex mutex;
79
80 struct omap_dss_device *dssdev;
81 struct backlight_device *bl_dev;
82};
83
84static struct acx565akm_device acx_dev;
85static int acx565akm_bl_update_status(struct backlight_device *dev);
86
87/*--------------------MIPID interface-----------------------------*/
88
89static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
90 const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
91{
92 struct spi_message m;
93 struct spi_transfer *x, xfer[5];
94 int r;
95
96 BUG_ON(md->spi == NULL);
97
98 spi_message_init(&m);
99
100 memset(xfer, 0, sizeof(xfer));
101 x = &xfer[0];
102
103 cmd &= 0xff;
104 x->tx_buf = &cmd;
105 x->bits_per_word = 9;
106 x->len = 2;
107
108 if (rlen > 1 && wlen == 0) {
109 /*
110 * Between the command and the response data there is a
111 * dummy clock cycle. Add an extra bit after the command
112 * word to account for this.
113 */
114 x->bits_per_word = 10;
115 cmd <<= 1;
116 }
117 spi_message_add_tail(x, &m);
118
119 if (wlen) {
120 x++;
121 x->tx_buf = wbuf;
122 x->len = wlen;
123 x->bits_per_word = 9;
124 spi_message_add_tail(x, &m);
125 }
126
127 if (rlen) {
128 x++;
129 x->rx_buf = rbuf;
130 x->len = rlen;
131 spi_message_add_tail(x, &m);
132 }
133
134 r = spi_sync(md->spi, &m);
135 if (r < 0)
136 dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
137}
138
139static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
140{
141 acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
142}
143
144static inline void acx565akm_write(struct acx565akm_device *md,
145 int reg, const u8 *buf, int len)
146{
147 acx565akm_transfer(md, reg, buf, len, NULL, 0);
148}
149
150static inline void acx565akm_read(struct acx565akm_device *md,
151 int reg, u8 *buf, int len)
152{
153 acx565akm_transfer(md, reg, NULL, 0, buf, len);
154}
155
156static void hw_guard_start(struct acx565akm_device *md, int guard_msec)
157{
158 md->hw_guard_wait = msecs_to_jiffies(guard_msec);
159 md->hw_guard_end = jiffies + md->hw_guard_wait;
160}
161
162static void hw_guard_wait(struct acx565akm_device *md)
163{
164 unsigned long wait = md->hw_guard_end - jiffies;
165
166 if ((long)wait > 0 && wait <= md->hw_guard_wait) {
167 set_current_state(TASK_UNINTERRUPTIBLE);
168 schedule_timeout(wait);
169 }
170}
171
172/*----------------------MIPID wrappers----------------------------*/
173
174static void set_sleep_mode(struct acx565akm_device *md, int on)
175{
176 int cmd;
177
178 if (on)
179 cmd = MIPID_CMD_SLEEP_IN;
180 else
181 cmd = MIPID_CMD_SLEEP_OUT;
182 /*
183 * We have to keep 120msec between sleep in/out commands.
184 * (8.2.15, 8.2.16).
185 */
186 hw_guard_wait(md);
187 acx565akm_cmd(md, cmd);
188 hw_guard_start(md, 120);
189}
190
191static void set_display_state(struct acx565akm_device *md, int enabled)
192{
193 int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
194
195 acx565akm_cmd(md, cmd);
196}
197
198static int panel_enabled(struct acx565akm_device *md)
199{
200 u32 disp_status;
201 int enabled;
202
203 acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
204 disp_status = __be32_to_cpu(disp_status);
205 enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
206 dev_dbg(&md->spi->dev,
207 "LCD panel %senabled by bootloader (status 0x%04x)\n",
208 enabled ? "" : "not ", disp_status);
209 return enabled;
210}
211
212static int panel_detect(struct acx565akm_device *md)
213{
214 acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
215 dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
216 md->display_id[0], md->display_id[1], md->display_id[2]);
217
218 switch (md->display_id[0]) {
219 case 0x10:
220 md->model = MIPID_VER_ACX565AKM;
221 md->name = "acx565akm";
222 md->has_bc = 1;
223 md->has_cabc = 1;
224 break;
225 case 0x29:
226 md->model = MIPID_VER_L4F00311;
227 md->name = "l4f00311";
228 break;
229 case 0x45:
230 md->model = MIPID_VER_LPH8923;
231 md->name = "lph8923";
232 break;
233 case 0x83:
234 md->model = MIPID_VER_LS041Y3;
235 md->name = "ls041y3";
236 break;
237 default:
238 md->name = "unknown";
239 dev_err(&md->spi->dev, "invalid display ID\n");
240 return -ENODEV;
241 }
242
243 md->revision = md->display_id[1];
244
245 dev_info(&md->spi->dev, "omapfb: %s rev %02x LCD detected\n",
246 md->name, md->revision);
247
248 return 0;
249}
250
251/*----------------------Backlight Control-------------------------*/
252
253static void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
254{
255 u16 ctrl;
256
257 acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
258 if (enable) {
259 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
260 CTRL_DISP_BACKLIGHT_ON;
261 } else {
262 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
263 CTRL_DISP_BACKLIGHT_ON);
264 }
265
266 ctrl |= 1 << 8;
267 acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
268}
269
270static void set_cabc_mode(struct acx565akm_device *md, unsigned mode)
271{
272 u16 cabc_ctrl;
273
274 md->cabc_mode = mode;
275 if (!md->enabled)
276 return;
277 cabc_ctrl = 0;
278 acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
279 cabc_ctrl &= ~3;
280 cabc_ctrl |= (1 << 8) | (mode & 3);
281 acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
282}
283
284static unsigned get_cabc_mode(struct acx565akm_device *md)
285{
286 return md->cabc_mode;
287}
288
289static unsigned get_hw_cabc_mode(struct acx565akm_device *md)
290{
291 u8 cabc_ctrl;
292
293 acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
294 return cabc_ctrl & 3;
295}
296
297static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
298{
299 int bv;
300
301 bv = level | (1 << 8);
302 acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
303
304 if (level)
305 enable_backlight_ctrl(md, 1);
306 else
307 enable_backlight_ctrl(md, 0);
308}
309
310static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
311{
312 u8 bv;
313
314 acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
315
316 return bv;
317}
318
319
320static int acx565akm_bl_update_status(struct backlight_device *dev)
321{
322 struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
323 int r;
324 int level;
325
326 dev_dbg(&md->spi->dev, "%s\n", __func__);
327
328 mutex_lock(&md->mutex);
329
330 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
331 dev->props.power == FB_BLANK_UNBLANK)
332 level = dev->props.brightness;
333 else
334 level = 0;
335
336 r = 0;
337 if (md->has_bc)
338 acx565akm_set_brightness(md, level);
339 else if (md->dssdev->set_backlight)
340 r = md->dssdev->set_backlight(md->dssdev, level);
341 else
342 r = -ENODEV;
343
344 mutex_unlock(&md->mutex);
345
346 return r;
347}
348
349static int acx565akm_bl_get_intensity(struct backlight_device *dev)
350{
351 struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
352
353 dev_dbg(&dev->dev, "%s\n", __func__);
354
355 if (!md->has_bc && md->dssdev->set_backlight == NULL)
356 return -ENODEV;
357
358 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
359 dev->props.power == FB_BLANK_UNBLANK) {
360 if (md->has_bc)
361 return acx565akm_get_actual_brightness(md);
362 else
363 return dev->props.brightness;
364 }
365
366 return 0;
367}
368
369static const struct backlight_ops acx565akm_bl_ops = {
370 .get_brightness = acx565akm_bl_get_intensity,
371 .update_status = acx565akm_bl_update_status,
372};
373
374/*--------------------Auto Brightness control via Sysfs---------------------*/
375
376static const char *cabc_modes[] = {
377 "off", /* always used when CABC is not supported */
378 "ui",
379 "still-image",
380 "moving-image",
381};
382
383static ssize_t show_cabc_mode(struct device *dev,
384 struct device_attribute *attr,
385 char *buf)
386{
387 struct acx565akm_device *md = dev_get_drvdata(dev);
388 const char *mode_str;
389 int mode;
390 int len;
391
392 if (!md->has_cabc)
393 mode = 0;
394 else
395 mode = get_cabc_mode(md);
396 mode_str = "unknown";
397 if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
398 mode_str = cabc_modes[mode];
399 len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
400
401 return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
402}
403
404static ssize_t store_cabc_mode(struct device *dev,
405 struct device_attribute *attr,
406 const char *buf, size_t count)
407{
408 struct acx565akm_device *md = dev_get_drvdata(dev);
409 int i;
410
411 for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
412 const char *mode_str = cabc_modes[i];
413 int cmp_len = strlen(mode_str);
414
415 if (count > 0 && buf[count - 1] == '\n')
416 count--;
417 if (count != cmp_len)
418 continue;
419
420 if (strncmp(buf, mode_str, cmp_len) == 0)
421 break;
422 }
423
424 if (i == ARRAY_SIZE(cabc_modes))
425 return -EINVAL;
426
427 if (!md->has_cabc && i != 0)
428 return -EINVAL;
429
430 mutex_lock(&md->mutex);
431 set_cabc_mode(md, i);
432 mutex_unlock(&md->mutex);
433
434 return count;
435}
436
437static ssize_t show_cabc_available_modes(struct device *dev,
438 struct device_attribute *attr,
439 char *buf)
440{
441 struct acx565akm_device *md = dev_get_drvdata(dev);
442 int len;
443 int i;
444
445 if (!md->has_cabc)
446 return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
447
448 for (i = 0, len = 0;
449 len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
450 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
451 i ? " " : "", cabc_modes[i],
452 i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
453
454 return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
455}
456
457static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
458 show_cabc_mode, store_cabc_mode);
459static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
460 show_cabc_available_modes, NULL);
461
462static struct attribute *bldev_attrs[] = {
463 &dev_attr_cabc_mode.attr,
464 &dev_attr_cabc_available_modes.attr,
465 NULL,
466};
467
468static struct attribute_group bldev_attr_group = {
469 .attrs = bldev_attrs,
470};
471
472
473/*---------------------------ACX Panel----------------------------*/
474
475static int acx_get_recommended_bpp(struct omap_dss_device *dssdev)
476{
477 return 16;
478}
479
480static struct omap_video_timings acx_panel_timings = {
481 .x_res = 800,
482 .y_res = 480,
483 .pixel_clock = 24000,
484 .hfp = 28,
485 .hsw = 4,
486 .hbp = 24,
487 .vfp = 3,
488 .vsw = 3,
489 .vbp = 4,
490};
491
492static int acx_panel_probe(struct omap_dss_device *dssdev)
493{
494 int r;
495 struct acx565akm_device *md = &acx_dev;
496 struct backlight_device *bldev;
497 int max_brightness, brightness;
498 struct backlight_properties props;
499
500 dev_dbg(&dssdev->dev, "%s\n", __func__);
501 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
502 OMAP_DSS_LCD_IHS;
503 /* FIXME AC bias ? */
504 dssdev->panel.timings = acx_panel_timings;
505
506 if (dssdev->platform_enable)
507 dssdev->platform_enable(dssdev);
508 /*
509 * After reset we have to wait 5 msec before the first
510 * command can be sent.
511 */
512 msleep(5);
513
514 md->enabled = panel_enabled(md);
515
516 r = panel_detect(md);
517 if (r) {
518 dev_err(&dssdev->dev, "%s panel detect error\n", __func__);
519 if (!md->enabled && dssdev->platform_disable)
520 dssdev->platform_disable(dssdev);
521 return r;
522 }
523
524 mutex_lock(&acx_dev.mutex);
525 acx_dev.dssdev = dssdev;
526 mutex_unlock(&acx_dev.mutex);
527
528 if (!md->enabled) {
529 if (dssdev->platform_disable)
530 dssdev->platform_disable(dssdev);
531 }
532
533 /*------- Backlight control --------*/
534
535 props.fb_blank = FB_BLANK_UNBLANK;
536 props.power = FB_BLANK_UNBLANK;
537
538 bldev = backlight_device_register("acx565akm", &md->spi->dev,
539 md, &acx565akm_bl_ops, &props);
540 md->bl_dev = bldev;
541 if (md->has_cabc) {
542 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
543 if (r) {
544 dev_err(&bldev->dev,
545 "%s failed to create sysfs files\n", __func__);
546 backlight_device_unregister(bldev);
547 return r;
548 }
549 md->cabc_mode = get_hw_cabc_mode(md);
550 }
551
552 if (md->has_bc)
553 max_brightness = 255;
554 else
555 max_brightness = dssdev->max_backlight_level;
556
557 if (md->has_bc)
558 brightness = acx565akm_get_actual_brightness(md);
559 else if (dssdev->get_backlight)
560 brightness = dssdev->get_backlight(dssdev);
561 else
562 brightness = 0;
563
564 bldev->props.max_brightness = max_brightness;
565 bldev->props.brightness = brightness;
566
567 acx565akm_bl_update_status(bldev);
568 return 0;
569}
570
571static void acx_panel_remove(struct omap_dss_device *dssdev)
572{
573 struct acx565akm_device *md = &acx_dev;
574
575 dev_dbg(&dssdev->dev, "%s\n", __func__);
576 sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group);
577 backlight_device_unregister(md->bl_dev);
578 mutex_lock(&acx_dev.mutex);
579 acx_dev.dssdev = NULL;
580 mutex_unlock(&acx_dev.mutex);
581}
582
583static int acx_panel_power_on(struct omap_dss_device *dssdev)
584{
585 struct acx565akm_device *md = &acx_dev;
586 int r;
587
588 dev_dbg(&dssdev->dev, "%s\n", __func__);
589
590 mutex_lock(&md->mutex);
591
592 r = omapdss_sdi_display_enable(dssdev);
593 if (r) {
594 pr_err("%s sdi enable failed\n", __func__);
595 return r;
596 }
597
598 /*FIXME tweak me */
599 msleep(50);
600
601 if (dssdev->platform_enable) {
602 r = dssdev->platform_enable(dssdev);
603 if (r)
604 goto fail;
605 }
606
607 if (md->enabled) {
608 dev_dbg(&md->spi->dev, "panel already enabled\n");
609 mutex_unlock(&md->mutex);
610 return 0;
611 }
612
613 /*
614 * We have to meet all the following delay requirements:
615 * 1. tRW: reset pulse width 10usec (7.12.1)
616 * 2. tRT: reset cancel time 5msec (7.12.1)
617 * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
618 * case (7.6.2)
619 * 4. 120msec before the sleep out command (7.12.1)
620 */
621 msleep(120);
622
623 set_sleep_mode(md, 0);
624 md->enabled = 1;
625
626 /* 5msec between sleep out and the next command. (8.2.16) */
627 msleep(5);
628 set_display_state(md, 1);
629 set_cabc_mode(md, md->cabc_mode);
630
631 mutex_unlock(&md->mutex);
632
633 return acx565akm_bl_update_status(md->bl_dev);
634fail:
635 omapdss_sdi_display_disable(dssdev);
636 return r;
637}
638
639static void acx_panel_power_off(struct omap_dss_device *dssdev)
640{
641 struct acx565akm_device *md = &acx_dev;
642
643 dev_dbg(&dssdev->dev, "%s\n", __func__);
644
645 mutex_lock(&md->mutex);
646
647 if (!md->enabled) {
648 mutex_unlock(&md->mutex);
649 return;
650 }
651 set_display_state(md, 0);
652 set_sleep_mode(md, 1);
653 md->enabled = 0;
654 /*
655 * We have to provide PCLK,HS,VS signals for 2 frames (worst case
656 * ~50msec) after sending the sleep in command and asserting the
657 * reset signal. We probably could assert the reset w/o the delay
658 * but we still delay to avoid possible artifacts. (7.6.1)
659 */
660 msleep(50);
661
662 if (dssdev->platform_disable)
663 dssdev->platform_disable(dssdev);
664
665 /* FIXME need to tweak this delay */
666 msleep(100);
667
668 omapdss_sdi_display_disable(dssdev);
669
670 mutex_unlock(&md->mutex);
671}
672
673static int acx_panel_enable(struct omap_dss_device *dssdev)
674{
675 int r;
676
677 dev_dbg(&dssdev->dev, "%s\n", __func__);
678 r = acx_panel_power_on(dssdev);
679
680 if (r)
681 return r;
682
683 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
684 return 0;
685}
686
687static void acx_panel_disable(struct omap_dss_device *dssdev)
688{
689 dev_dbg(&dssdev->dev, "%s\n", __func__);
690 acx_panel_power_off(dssdev);
691 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
692}
693
694static int acx_panel_suspend(struct omap_dss_device *dssdev)
695{
696 dev_dbg(&dssdev->dev, "%s\n", __func__);
697 acx_panel_power_off(dssdev);
698 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
699 return 0;
700}
701
702static int acx_panel_resume(struct omap_dss_device *dssdev)
703{
704 int r;
705
706 dev_dbg(&dssdev->dev, "%s\n", __func__);
707 r = acx_panel_power_on(dssdev);
708 if (r)
709 return r;
710
711 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
712 return 0;
713}
714
715static void acx_panel_set_timings(struct omap_dss_device *dssdev,
716 struct omap_video_timings *timings)
717{
718 int r;
719
720 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
721 omapdss_sdi_display_disable(dssdev);
722
723 dssdev->panel.timings = *timings;
724
725 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
726 r = omapdss_sdi_display_enable(dssdev);
727 if (r)
728 dev_err(&dssdev->dev, "%s enable failed\n", __func__);
729 }
730}
731
732static void acx_panel_get_timings(struct omap_dss_device *dssdev,
733 struct omap_video_timings *timings)
734{
735 *timings = dssdev->panel.timings;
736}
737
738static int acx_panel_check_timings(struct omap_dss_device *dssdev,
739 struct omap_video_timings *timings)
740{
741 return 0;
742}
743
744
745static struct omap_dss_driver acx_panel_driver = {
746 .probe = acx_panel_probe,
747 .remove = acx_panel_remove,
748
749 .enable = acx_panel_enable,
750 .disable = acx_panel_disable,
751 .suspend = acx_panel_suspend,
752 .resume = acx_panel_resume,
753
754 .set_timings = acx_panel_set_timings,
755 .get_timings = acx_panel_get_timings,
756 .check_timings = acx_panel_check_timings,
757
758 .get_recommended_bpp = acx_get_recommended_bpp,
759
760 .driver = {
761 .name = "panel-acx565akm",
762 .owner = THIS_MODULE,
763 },
764};
765
766/*--------------------SPI probe-------------------------*/
767
768static int acx565akm_spi_probe(struct spi_device *spi)
769{
770 struct acx565akm_device *md = &acx_dev;
771
772 dev_dbg(&spi->dev, "%s\n", __func__);
773
774 spi->mode = SPI_MODE_3;
775 md->spi = spi;
776 mutex_init(&md->mutex);
777 dev_set_drvdata(&spi->dev, md);
778
779 omap_dss_register_driver(&acx_panel_driver);
780
781 return 0;
782}
783
784static int acx565akm_spi_remove(struct spi_device *spi)
785{
786 struct acx565akm_device *md = dev_get_drvdata(&spi->dev);
787
788 dev_dbg(&md->spi->dev, "%s\n", __func__);
789 omap_dss_unregister_driver(&acx_panel_driver);
790
791 return 0;
792}
793
794static struct spi_driver acx565akm_spi_driver = {
795 .driver = {
796 .name = "acx565akm",
797 .bus = &spi_bus_type,
798 .owner = THIS_MODULE,
799 },
800 .probe = acx565akm_spi_probe,
801 .remove = __devexit_p(acx565akm_spi_remove),
802};
803
804static int __init acx565akm_init(void)
805{
806 return spi_register_driver(&acx565akm_spi_driver);
807}
808
809static void __exit acx565akm_exit(void)
810{
811 spi_unregister_driver(&acx565akm_spi_driver);
812}
813
814module_init(acx565akm_init);
815module_exit(acx565akm_exit);
816
817MODULE_AUTHOR("Nokia Corporation");
818MODULE_DESCRIPTION("acx565akm LCD Driver");
819MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 8d51a5e6341..7d9eb2b1f5a 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -20,10 +20,17 @@
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/device.h> 22#include <linux/device.h>
23#include <linux/backlight.h>
24#include <linux/fb.h>
23#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/slab.h>
24 27
25#include <plat/display.h> 28#include <plat/display.h>
26 29
30struct sharp_data {
31 struct backlight_device *bl;
32};
33
27static struct omap_video_timings sharp_ls_timings = { 34static struct omap_video_timings sharp_ls_timings = {
28 .x_res = 480, 35 .x_res = 480,
29 .y_res = 640, 36 .y_res = 640,
@@ -39,18 +46,89 @@ static struct omap_video_timings sharp_ls_timings = {
39 .vbp = 1, 46 .vbp = 1,
40}; 47};
41 48
49static int sharp_ls_bl_update_status(struct backlight_device *bl)
50{
51 struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
52 int level;
53
54 if (!dssdev->set_backlight)
55 return -EINVAL;
56
57 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
58 bl->props.power == FB_BLANK_UNBLANK)
59 level = bl->props.brightness;
60 else
61 level = 0;
62
63 return dssdev->set_backlight(dssdev, level);
64}
65
66static int sharp_ls_bl_get_brightness(struct backlight_device *bl)
67{
68 if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
69 bl->props.power == FB_BLANK_UNBLANK)
70 return bl->props.brightness;
71
72 return 0;
73}
74
75static const struct backlight_ops sharp_ls_bl_ops = {
76 .get_brightness = sharp_ls_bl_get_brightness,
77 .update_status = sharp_ls_bl_update_status,
78};
79
80
81
42static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) 82static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
43{ 83{
84 struct backlight_properties props;
85 struct backlight_device *bl;
86 struct sharp_data *sd;
87 int r;
88
44 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | 89 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
45 OMAP_DSS_LCD_IHS; 90 OMAP_DSS_LCD_IHS;
46 dssdev->panel.acb = 0x28; 91 dssdev->panel.acb = 0x28;
47 dssdev->panel.timings = sharp_ls_timings; 92 dssdev->panel.timings = sharp_ls_timings;
48 93
94 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
95 if (!sd)
96 return -ENOMEM;
97
98 dev_set_drvdata(&dssdev->dev, sd);
99
100 memset(&props, 0, sizeof(struct backlight_properties));
101 props.max_brightness = dssdev->max_backlight_level;
102
103 bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
104 &sharp_ls_bl_ops, &props);
105 if (IS_ERR(bl)) {
106 r = PTR_ERR(bl);
107 kfree(sd);
108 return r;
109 }
110 sd->bl = bl;
111
112 bl->props.fb_blank = FB_BLANK_UNBLANK;
113 bl->props.power = FB_BLANK_UNBLANK;
114 bl->props.brightness = dssdev->max_backlight_level;
115 r = sharp_ls_bl_update_status(bl);
116 if (r < 0)
117 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
118
49 return 0; 119 return 0;
50} 120}
51 121
52static void sharp_ls_panel_remove(struct omap_dss_device *dssdev) 122static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
53{ 123{
124 struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
125 struct backlight_device *bl = sd->bl;
126
127 bl->props.power = FB_BLANK_POWERDOWN;
128 sharp_ls_bl_update_status(bl);
129 backlight_device_unregister(bl);
130
131 kfree(sd);
54} 132}
55 133
56static int sharp_ls_power_on(struct omap_dss_device *dssdev) 134static int sharp_ls_power_on(struct omap_dss_device *dssdev)
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 4f3988a4108..aaf5d308a04 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -31,6 +31,7 @@
31#include <linux/completion.h> 31#include <linux/completion.h>
32#include <linux/workqueue.h> 32#include <linux/workqueue.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <linux/mutex.h>
34 35
35#include <plat/display.h> 36#include <plat/display.h>
36 37
@@ -67,6 +68,8 @@
67static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); 68static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
68 69
69struct taal_data { 70struct taal_data {
71 struct mutex lock;
72
70 struct backlight_device *bldev; 73 struct backlight_device *bldev;
71 74
72 unsigned long hw_guard_end; /* next value of jiffies when we can 75 unsigned long hw_guard_end; /* next value of jiffies when we can
@@ -510,6 +513,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
510 } 513 }
511 td->dssdev = dssdev; 514 td->dssdev = dssdev;
512 515
516 mutex_init(&td->lock);
517
513 td->esd_wq = create_singlethread_workqueue("taal_esd"); 518 td->esd_wq = create_singlethread_workqueue("taal_esd");
514 if (td->esd_wq == NULL) { 519 if (td->esd_wq == NULL) {
515 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 520 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
@@ -697,10 +702,9 @@ static int taal_power_on(struct omap_dss_device *dssdev)
697 702
698 return 0; 703 return 0;
699err: 704err:
700 dsi_bus_unlock();
701
702 omapdss_dsi_display_disable(dssdev); 705 omapdss_dsi_display_disable(dssdev);
703err0: 706err0:
707 dsi_bus_unlock();
704 if (dssdev->platform_disable) 708 if (dssdev->platform_disable)
705 dssdev->platform_disable(dssdev); 709 dssdev->platform_disable(dssdev);
706 710
@@ -733,54 +737,96 @@ static void taal_power_off(struct omap_dss_device *dssdev)
733 737
734static int taal_enable(struct omap_dss_device *dssdev) 738static int taal_enable(struct omap_dss_device *dssdev)
735{ 739{
740 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
736 int r; 741 int r;
742
737 dev_dbg(&dssdev->dev, "enable\n"); 743 dev_dbg(&dssdev->dev, "enable\n");
738 744
739 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) 745 mutex_lock(&td->lock);
740 return -EINVAL; 746
747 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
748 r = -EINVAL;
749 goto err;
750 }
741 751
742 r = taal_power_on(dssdev); 752 r = taal_power_on(dssdev);
743 if (r) 753 if (r)
744 return r; 754 goto err;
745 755
746 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 756 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
747 757
758 mutex_unlock(&td->lock);
759
760 return 0;
761err:
762 dev_dbg(&dssdev->dev, "enable failed\n");
763 mutex_unlock(&td->lock);
748 return r; 764 return r;
749} 765}
750 766
751static void taal_disable(struct omap_dss_device *dssdev) 767static void taal_disable(struct omap_dss_device *dssdev)
752{ 768{
769 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
770
753 dev_dbg(&dssdev->dev, "disable\n"); 771 dev_dbg(&dssdev->dev, "disable\n");
754 772
773 mutex_lock(&td->lock);
774
755 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 775 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
756 taal_power_off(dssdev); 776 taal_power_off(dssdev);
757 777
758 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 778 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
779
780 mutex_unlock(&td->lock);
759} 781}
760 782
761static int taal_suspend(struct omap_dss_device *dssdev) 783static int taal_suspend(struct omap_dss_device *dssdev)
762{ 784{
785 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
786 int r;
787
763 dev_dbg(&dssdev->dev, "suspend\n"); 788 dev_dbg(&dssdev->dev, "suspend\n");
764 789
765 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 790 mutex_lock(&td->lock);
766 return -EINVAL; 791
792 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
793 r = -EINVAL;
794 goto err;
795 }
767 796
768 taal_power_off(dssdev); 797 taal_power_off(dssdev);
769 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 798 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
770 799
800 mutex_unlock(&td->lock);
801
771 return 0; 802 return 0;
803err:
804 mutex_unlock(&td->lock);
805 return r;
772} 806}
773 807
774static int taal_resume(struct omap_dss_device *dssdev) 808static int taal_resume(struct omap_dss_device *dssdev)
775{ 809{
810 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
776 int r; 811 int r;
812
777 dev_dbg(&dssdev->dev, "resume\n"); 813 dev_dbg(&dssdev->dev, "resume\n");
778 814
779 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) 815 mutex_lock(&td->lock);
780 return -EINVAL; 816
817 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
818 r = -EINVAL;
819 goto err;
820 }
781 821
782 r = taal_power_on(dssdev); 822 r = taal_power_on(dssdev);
783 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 823 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
824
825 mutex_unlock(&td->lock);
826
827 return r;
828err:
829 mutex_unlock(&td->lock);
784 return r; 830 return r;
785} 831}
786 832
@@ -799,6 +845,7 @@ static int taal_update(struct omap_dss_device *dssdev,
799 845
800 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 846 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
801 847
848 mutex_lock(&td->lock);
802 dsi_bus_lock(); 849 dsi_bus_lock();
803 850
804 if (!td->enabled) { 851 if (!td->enabled) {
@@ -820,18 +867,24 @@ static int taal_update(struct omap_dss_device *dssdev,
820 goto err; 867 goto err;
821 868
822 /* note: no bus_unlock here. unlock is in framedone_cb */ 869 /* note: no bus_unlock here. unlock is in framedone_cb */
870 mutex_unlock(&td->lock);
823 return 0; 871 return 0;
824err: 872err:
825 dsi_bus_unlock(); 873 dsi_bus_unlock();
874 mutex_unlock(&td->lock);
826 return r; 875 return r;
827} 876}
828 877
829static int taal_sync(struct omap_dss_device *dssdev) 878static int taal_sync(struct omap_dss_device *dssdev)
830{ 879{
880 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
881
831 dev_dbg(&dssdev->dev, "sync\n"); 882 dev_dbg(&dssdev->dev, "sync\n");
832 883
884 mutex_lock(&td->lock);
833 dsi_bus_lock(); 885 dsi_bus_lock();
834 dsi_bus_unlock(); 886 dsi_bus_unlock();
887 mutex_unlock(&td->lock);
835 888
836 dev_dbg(&dssdev->dev, "sync done\n"); 889 dev_dbg(&dssdev->dev, "sync done\n");
837 890
@@ -861,13 +914,16 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
861 914
862static int taal_enable_te(struct omap_dss_device *dssdev, bool enable) 915static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
863{ 916{
917 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
864 int r; 918 int r;
865 919
920 mutex_lock(&td->lock);
866 dsi_bus_lock(); 921 dsi_bus_lock();
867 922
868 r = _taal_enable_te(dssdev, enable); 923 r = _taal_enable_te(dssdev, enable);
869 924
870 dsi_bus_unlock(); 925 dsi_bus_unlock();
926 mutex_unlock(&td->lock);
871 927
872 return r; 928 return r;
873} 929}
@@ -875,7 +931,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
875static int taal_get_te(struct omap_dss_device *dssdev) 931static int taal_get_te(struct omap_dss_device *dssdev)
876{ 932{
877 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 933 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
878 return td->te_enabled; 934 int r;
935
936 mutex_lock(&td->lock);
937 r = td->te_enabled;
938 mutex_unlock(&td->lock);
939
940 return r;
879} 941}
880 942
881static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) 943static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
@@ -885,6 +947,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
885 947
886 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 948 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
887 949
950 mutex_lock(&td->lock);
888 dsi_bus_lock(); 951 dsi_bus_lock();
889 952
890 if (td->enabled) { 953 if (td->enabled) {
@@ -896,16 +959,24 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
896 td->rotate = rotate; 959 td->rotate = rotate;
897 960
898 dsi_bus_unlock(); 961 dsi_bus_unlock();
962 mutex_unlock(&td->lock);
899 return 0; 963 return 0;
900err: 964err:
901 dsi_bus_unlock(); 965 dsi_bus_unlock();
966 mutex_unlock(&td->lock);
902 return r; 967 return r;
903} 968}
904 969
905static u8 taal_get_rotate(struct omap_dss_device *dssdev) 970static u8 taal_get_rotate(struct omap_dss_device *dssdev)
906{ 971{
907 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 972 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
908 return td->rotate; 973 int r;
974
975 mutex_lock(&td->lock);
976 r = td->rotate;
977 mutex_unlock(&td->lock);
978
979 return r;
909} 980}
910 981
911static int taal_mirror(struct omap_dss_device *dssdev, bool enable) 982static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
@@ -915,6 +986,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
915 986
916 dev_dbg(&dssdev->dev, "mirror %d\n", enable); 987 dev_dbg(&dssdev->dev, "mirror %d\n", enable);
917 988
989 mutex_lock(&td->lock);
918 dsi_bus_lock(); 990 dsi_bus_lock();
919 if (td->enabled) { 991 if (td->enabled) {
920 r = taal_set_addr_mode(td->rotate, enable); 992 r = taal_set_addr_mode(td->rotate, enable);
@@ -925,23 +997,33 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
925 td->mirror = enable; 997 td->mirror = enable;
926 998
927 dsi_bus_unlock(); 999 dsi_bus_unlock();
1000 mutex_unlock(&td->lock);
928 return 0; 1001 return 0;
929err: 1002err:
930 dsi_bus_unlock(); 1003 dsi_bus_unlock();
1004 mutex_unlock(&td->lock);
931 return r; 1005 return r;
932} 1006}
933 1007
934static bool taal_get_mirror(struct omap_dss_device *dssdev) 1008static bool taal_get_mirror(struct omap_dss_device *dssdev)
935{ 1009{
936 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1010 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
937 return td->mirror; 1011 int r;
1012
1013 mutex_lock(&td->lock);
1014 r = td->mirror;
1015 mutex_unlock(&td->lock);
1016
1017 return r;
938} 1018}
939 1019
940static int taal_run_test(struct omap_dss_device *dssdev, int test_num) 1020static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
941{ 1021{
1022 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
942 u8 id1, id2, id3; 1023 u8 id1, id2, id3;
943 int r; 1024 int r;
944 1025
1026 mutex_lock(&td->lock);
945 dsi_bus_lock(); 1027 dsi_bus_lock();
946 1028
947 r = taal_dcs_read_1(DCS_GET_ID1, &id1); 1029 r = taal_dcs_read_1(DCS_GET_ID1, &id1);
@@ -955,9 +1037,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
955 goto err; 1037 goto err;
956 1038
957 dsi_bus_unlock(); 1039 dsi_bus_unlock();
1040 mutex_unlock(&td->lock);
958 return 0; 1041 return 0;
959err: 1042err:
960 dsi_bus_unlock(); 1043 dsi_bus_unlock();
1044 mutex_unlock(&td->lock);
961 return r; 1045 return r;
962} 1046}
963 1047
@@ -971,12 +1055,16 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
971 unsigned buf_used = 0; 1055 unsigned buf_used = 0;
972 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1056 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
973 1057
974 if (!td->enabled)
975 return -ENODEV;
976
977 if (size < w * h * 3) 1058 if (size < w * h * 3)
978 return -ENOMEM; 1059 return -ENOMEM;
979 1060
1061 mutex_lock(&td->lock);
1062
1063 if (!td->enabled) {
1064 r = -ENODEV;
1065 goto err1;
1066 }
1067
980 size = min(w * h * 3, 1068 size = min(w * h * 3,
981 dssdev->panel.timings.x_res * 1069 dssdev->panel.timings.x_res *
982 dssdev->panel.timings.y_res * 3); 1070 dssdev->panel.timings.y_res * 3);
@@ -995,7 +1083,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
995 1083
996 r = dsi_vc_set_max_rx_packet_size(TCH, plen); 1084 r = dsi_vc_set_max_rx_packet_size(TCH, plen);
997 if (r) 1085 if (r)
998 goto err0; 1086 goto err2;
999 1087
1000 while (buf_used < size) { 1088 while (buf_used < size) {
1001 u8 dcs_cmd = first ? 0x2e : 0x3e; 1089 u8 dcs_cmd = first ? 0x2e : 0x3e;
@@ -1006,7 +1094,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1006 1094
1007 if (r < 0) { 1095 if (r < 0) {
1008 dev_err(&dssdev->dev, "read error\n"); 1096 dev_err(&dssdev->dev, "read error\n");
1009 goto err; 1097 goto err3;
1010 } 1098 }
1011 1099
1012 buf_used += r; 1100 buf_used += r;
@@ -1020,16 +1108,18 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
1020 dev_err(&dssdev->dev, "signal pending, " 1108 dev_err(&dssdev->dev, "signal pending, "
1021 "aborting memory read\n"); 1109 "aborting memory read\n");
1022 r = -ERESTARTSYS; 1110 r = -ERESTARTSYS;
1023 goto err; 1111 goto err3;
1024 } 1112 }
1025 } 1113 }
1026 1114
1027 r = buf_used; 1115 r = buf_used;
1028 1116
1029err: 1117err3:
1030 dsi_vc_set_max_rx_packet_size(TCH, 1); 1118 dsi_vc_set_max_rx_packet_size(TCH, 1);
1031err0: 1119err2:
1032 dsi_bus_unlock(); 1120 dsi_bus_unlock();
1121err1:
1122 mutex_unlock(&td->lock);
1033 return r; 1123 return r;
1034} 1124}
1035 1125
@@ -1041,8 +1131,12 @@ static void taal_esd_work(struct work_struct *work)
1041 u8 state1, state2; 1131 u8 state1, state2;
1042 int r; 1132 int r;
1043 1133
1044 if (!td->enabled) 1134 mutex_lock(&td->lock);
1135
1136 if (!td->enabled) {
1137 mutex_unlock(&td->lock);
1045 return; 1138 return;
1139 }
1046 1140
1047 dsi_bus_lock(); 1141 dsi_bus_lock();
1048 1142
@@ -1084,16 +1178,19 @@ static void taal_esd_work(struct work_struct *work)
1084 1178
1085 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); 1179 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1086 1180
1181 mutex_unlock(&td->lock);
1087 return; 1182 return;
1088err: 1183err:
1089 dev_err(&dssdev->dev, "performing LCD reset\n"); 1184 dev_err(&dssdev->dev, "performing LCD reset\n");
1090 1185
1091 taal_disable(dssdev); 1186 taal_power_off(dssdev);
1092 taal_enable(dssdev); 1187 taal_power_on(dssdev);
1093 1188
1094 dsi_bus_unlock(); 1189 dsi_bus_unlock();
1095 1190
1096 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD); 1191 queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
1192
1193 mutex_unlock(&td->lock);
1097} 1194}
1098 1195
1099static int taal_set_update_mode(struct omap_dss_device *dssdev, 1196static int taal_set_update_mode(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 87afb81b2c4..43b64403eaa 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -36,6 +36,12 @@ config OMAP2_DSS_COLLECT_IRQ_STATS
36 <debugfs>/omapdss/dispc_irq for DISPC interrupts, and 36 <debugfs>/omapdss/dispc_irq for DISPC interrupts, and
37 <debugfs>/omapdss/dsi_irq for DSI interrupts. 37 <debugfs>/omapdss/dsi_irq for DSI interrupts.
38 38
39config OMAP2_DSS_DPI
40 bool "DPI support"
41 default y
42 help
43 DPI Interface. This is the Parallel Display Interface.
44
39config OMAP2_DSS_RFBI 45config OMAP2_DSS_RFBI
40 bool "RFBI support" 46 bool "RFBI support"
41 default n 47 default n
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 980c72c2db9..d71b5d9d71b 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o 2omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o
3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
3omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
4omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
5omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 7ebe50b335e..b3a498f22d3 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -482,6 +482,14 @@ static void dss_uninitialize_debugfs(void)
482 if (dss_debugfs_dir) 482 if (dss_debugfs_dir)
483 debugfs_remove_recursive(dss_debugfs_dir); 483 debugfs_remove_recursive(dss_debugfs_dir);
484} 484}
485#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
486static inline int dss_initialize_debugfs(void)
487{
488 return 0;
489}
490static inline void dss_uninitialize_debugfs(void)
491{
492}
485#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 493#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
486 494
487/* PLATFORM DEVICE */ 495/* PLATFORM DEVICE */
@@ -499,7 +507,7 @@ static int omap_dss_probe(struct platform_device *pdev)
499 507
500 r = dss_get_clocks(); 508 r = dss_get_clocks();
501 if (r) 509 if (r)
502 goto fail0; 510 goto err_clocks;
503 511
504 dss_clk_enable_all_no_ctx(); 512 dss_clk_enable_all_no_ctx();
505 513
@@ -515,64 +523,64 @@ static int omap_dss_probe(struct platform_device *pdev)
515 r = dss_init(skip_init); 523 r = dss_init(skip_init);
516 if (r) { 524 if (r) {
517 DSSERR("Failed to initialize DSS\n"); 525 DSSERR("Failed to initialize DSS\n");
518 goto fail0; 526 goto err_dss;
519 } 527 }
520 528
521#ifdef CONFIG_OMAP2_DSS_RFBI
522 r = rfbi_init(); 529 r = rfbi_init();
523 if (r) { 530 if (r) {
524 DSSERR("Failed to initialize rfbi\n"); 531 DSSERR("Failed to initialize rfbi\n");
525 goto fail0; 532 goto err_rfbi;
526 } 533 }
527#endif
528 534
529 r = dpi_init(pdev); 535 r = dpi_init(pdev);
530 if (r) { 536 if (r) {
531 DSSERR("Failed to initialize dpi\n"); 537 DSSERR("Failed to initialize dpi\n");
532 goto fail0; 538 goto err_dpi;
533 } 539 }
534 540
535 r = dispc_init(); 541 r = dispc_init();
536 if (r) { 542 if (r) {
537 DSSERR("Failed to initialize dispc\n"); 543 DSSERR("Failed to initialize dispc\n");
538 goto fail0; 544 goto err_dispc;
539 } 545 }
540#ifdef CONFIG_OMAP2_DSS_VENC 546
541 r = venc_init(pdev); 547 r = venc_init(pdev);
542 if (r) { 548 if (r) {
543 DSSERR("Failed to initialize venc\n"); 549 DSSERR("Failed to initialize venc\n");
544 goto fail0; 550 goto err_venc;
545 } 551 }
546#endif 552
547 if (cpu_is_omap34xx()) { 553 if (cpu_is_omap34xx()) {
548#ifdef CONFIG_OMAP2_DSS_SDI
549 r = sdi_init(skip_init); 554 r = sdi_init(skip_init);
550 if (r) { 555 if (r) {
551 DSSERR("Failed to initialize SDI\n"); 556 DSSERR("Failed to initialize SDI\n");
552 goto fail0; 557 goto err_sdi;
553 } 558 }
554#endif 559
555#ifdef CONFIG_OMAP2_DSS_DSI
556 r = dsi_init(pdev); 560 r = dsi_init(pdev);
557 if (r) { 561 if (r) {
558 DSSERR("Failed to initialize DSI\n"); 562 DSSERR("Failed to initialize DSI\n");
559 goto fail0; 563 goto err_dsi;
560 } 564 }
561#endif
562 } 565 }
563 566
564#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
565 r = dss_initialize_debugfs(); 567 r = dss_initialize_debugfs();
566 if (r) 568 if (r)
567 goto fail0; 569 goto err_debugfs;
568#endif
569 570
570 for (i = 0; i < pdata->num_devices; ++i) { 571 for (i = 0; i < pdata->num_devices; ++i) {
571 struct omap_dss_device *dssdev = pdata->devices[i]; 572 struct omap_dss_device *dssdev = pdata->devices[i];
572 573
573 r = omap_dss_register_device(dssdev); 574 r = omap_dss_register_device(dssdev);
574 if (r) 575 if (r) {
575 DSSERR("device reg failed %d\n", i); 576 DSSERR("device %d %s register failed %d\n", i,
577 dssdev->name ?: "unnamed", r);
578
579 while (--i >= 0)
580 omap_dss_unregister_device(pdata->devices[i]);
581
582 goto err_register;
583 }
576 584
577 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) 585 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
578 pdata->default_device = dssdev; 586 pdata->default_device = dssdev;
@@ -582,8 +590,29 @@ static int omap_dss_probe(struct platform_device *pdev)
582 590
583 return 0; 591 return 0;
584 592
585 /* XXX fail correctly */ 593err_register:
586fail0: 594 dss_uninitialize_debugfs();
595err_debugfs:
596 if (cpu_is_omap34xx())
597 dsi_exit();
598err_dsi:
599 if (cpu_is_omap34xx())
600 sdi_exit();
601err_sdi:
602 venc_exit();
603err_venc:
604 dispc_exit();
605err_dispc:
606 dpi_exit();
607err_dpi:
608 rfbi_exit();
609err_rfbi:
610 dss_exit();
611err_dss:
612 dss_clk_disable_all_no_ctx();
613 dss_put_clocks();
614err_clocks:
615
587 return r; 616 return r;
588} 617}
589 618
@@ -593,25 +622,15 @@ static int omap_dss_remove(struct platform_device *pdev)
593 int i; 622 int i;
594 int c; 623 int c;
595 624
596#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
597 dss_uninitialize_debugfs(); 625 dss_uninitialize_debugfs();
598#endif
599 626
600#ifdef CONFIG_OMAP2_DSS_VENC
601 venc_exit(); 627 venc_exit();
602#endif
603 dispc_exit(); 628 dispc_exit();
604 dpi_exit(); 629 dpi_exit();
605#ifdef CONFIG_OMAP2_DSS_RFBI
606 rfbi_exit(); 630 rfbi_exit();
607#endif
608 if (cpu_is_omap34xx()) { 631 if (cpu_is_omap34xx()) {
609#ifdef CONFIG_OMAP2_DSS_DSI
610 dsi_exit(); 632 dsi_exit();
611#endif
612#ifdef CONFIG_OMAP2_DSS_SDI
613 sdi_exit(); 633 sdi_exit();
614#endif
615 } 634 }
616 635
617 dss_exit(); 636 dss_exit();
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 6a74ea116d2..ef8c8529dda 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -392,7 +392,9 @@ void dss_init_device(struct platform_device *pdev,
392 int r; 392 int r;
393 393
394 switch (dssdev->type) { 394 switch (dssdev->type) {
395#ifdef CONFIG_OMAP2_DSS_DPI
395 case OMAP_DISPLAY_TYPE_DPI: 396 case OMAP_DISPLAY_TYPE_DPI:
397#endif
396#ifdef CONFIG_OMAP2_DSS_RFBI 398#ifdef CONFIG_OMAP2_DSS_RFBI
397 case OMAP_DISPLAY_TYPE_DBI: 399 case OMAP_DISPLAY_TYPE_DBI:
398#endif 400#endif
@@ -413,9 +415,11 @@ void dss_init_device(struct platform_device *pdev,
413 } 415 }
414 416
415 switch (dssdev->type) { 417 switch (dssdev->type) {
418#ifdef CONFIG_OMAP2_DSS_DPI
416 case OMAP_DISPLAY_TYPE_DPI: 419 case OMAP_DISPLAY_TYPE_DPI:
417 r = dpi_init_display(dssdev); 420 r = dpi_init_display(dssdev);
418 break; 421 break;
422#endif
419#ifdef CONFIG_OMAP2_DSS_RFBI 423#ifdef CONFIG_OMAP2_DSS_RFBI
420 case OMAP_DISPLAY_TYPE_DBI: 424 case OMAP_DISPLAY_TYPE_DBI:
421 r = rfbi_init_display(dssdev); 425 r = rfbi_init_display(dssdev);
@@ -541,7 +545,10 @@ int dss_resume_all_devices(void)
541static int dss_disable_device(struct device *dev, void *data) 545static int dss_disable_device(struct device *dev, void *data)
542{ 546{
543 struct omap_dss_device *dssdev = to_dss_device(dev); 547 struct omap_dss_device *dssdev = to_dss_device(dev);
544 dssdev->driver->disable(dssdev); 548
549 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
550 dssdev->driver->disable(dssdev);
551
545 return 0; 552 return 0;
546} 553}
547 554
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 54344184dd7..24b18258654 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -223,7 +223,13 @@ void dss_dump_clocks(struct seq_file *s)
223 223
224 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 224 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
225 225
226 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", 226 if (cpu_is_omap3630())
227 seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n",
228 dpll4_ck_rate,
229 dpll4_ck_rate / dpll4_m4_ck_rate,
230 dss_clk_get_rate(DSS_CLK_FCK1));
231 else
232 seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
227 dpll4_ck_rate, 233 dpll4_ck_rate,
228 dpll4_ck_rate / dpll4_m4_ck_rate, 234 dpll4_ck_rate / dpll4_m4_ck_rate,
229 dss_clk_get_rate(DSS_CLK_FCK1)); 235 dss_clk_get_rate(DSS_CLK_FCK1));
@@ -293,7 +299,8 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
293{ 299{
294 unsigned long prate; 300 unsigned long prate;
295 301
296 if (cinfo->fck_div > 16 || cinfo->fck_div == 0) 302 if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) ||
303 cinfo->fck_div == 0)
297 return -EINVAL; 304 return -EINVAL;
298 305
299 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 306 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
@@ -329,7 +336,10 @@ int dss_get_clock_div(struct dss_clock_info *cinfo)
329 if (cpu_is_omap34xx()) { 336 if (cpu_is_omap34xx()) {
330 unsigned long prate; 337 unsigned long prate;
331 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 338 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
332 cinfo->fck_div = prate / (cinfo->fck / 2); 339 if (cpu_is_omap3630())
340 cinfo->fck_div = prate / (cinfo->fck);
341 else
342 cinfo->fck_div = prate / (cinfo->fck / 2);
333 } else { 343 } else {
334 cinfo->fck_div = 0; 344 cinfo->fck_div = 0;
335 } 345 }
@@ -402,10 +412,14 @@ retry:
402 412
403 goto found; 413 goto found;
404 } else if (cpu_is_omap34xx()) { 414 } else if (cpu_is_omap34xx()) {
405 for (fck_div = 16; fck_div > 0; --fck_div) { 415 for (fck_div = (cpu_is_omap3630() ? 32 : 16);
416 fck_div > 0; --fck_div) {
406 struct dispc_clock_info cur_dispc; 417 struct dispc_clock_info cur_dispc;
407 418
408 fck = prate / fck_div * 2; 419 if (cpu_is_omap3630())
420 fck = prate / fck_div;
421 else
422 fck = prate / fck_div * 2;
409 423
410 if (fck > DISPC_MAX_FCK) 424 if (fck > DISPC_MAX_FCK)
411 continue; 425 continue;
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 24326a5fd29..786f433fd57 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -242,11 +242,22 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
242 struct dispc_clock_info *dispc_cinfo); 242 struct dispc_clock_info *dispc_cinfo);
243 243
244/* SDI */ 244/* SDI */
245#ifdef CONFIG_OMAP2_DSS_SDI
245int sdi_init(bool skip_init); 246int sdi_init(bool skip_init);
246void sdi_exit(void); 247void sdi_exit(void);
247int sdi_init_display(struct omap_dss_device *display); 248int sdi_init_display(struct omap_dss_device *display);
249#else
250static inline int sdi_init(bool skip_init)
251{
252 return 0;
253}
254static inline void sdi_exit(void)
255{
256}
257#endif
248 258
249/* DSI */ 259/* DSI */
260#ifdef CONFIG_OMAP2_DSS_DSI
250int dsi_init(struct platform_device *pdev); 261int dsi_init(struct platform_device *pdev);
251void dsi_exit(void); 262void dsi_exit(void);
252 263
@@ -270,11 +281,30 @@ void dsi_pll_uninit(void);
270void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, 281void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
271 u32 fifo_size, enum omap_burst_size *burst_size, 282 u32 fifo_size, enum omap_burst_size *burst_size,
272 u32 *fifo_low, u32 *fifo_high); 283 u32 *fifo_low, u32 *fifo_high);
284#else
285static inline int dsi_init(struct platform_device *pdev)
286{
287 return 0;
288}
289static inline void dsi_exit(void)
290{
291}
292#endif
273 293
274/* DPI */ 294/* DPI */
295#ifdef CONFIG_OMAP2_DSS_DPI
275int dpi_init(struct platform_device *pdev); 296int dpi_init(struct platform_device *pdev);
276void dpi_exit(void); 297void dpi_exit(void);
277int dpi_init_display(struct omap_dss_device *dssdev); 298int dpi_init_display(struct omap_dss_device *dssdev);
299#else
300static inline int dpi_init(struct platform_device *pdev)
301{
302 return 0;
303}
304static inline void dpi_exit(void)
305{
306}
307#endif
278 308
279/* DISPC */ 309/* DISPC */
280int dispc_init(void); 310int dispc_init(void);
@@ -362,12 +392,23 @@ int dispc_get_clock_div(struct dispc_clock_info *cinfo);
362 392
363 393
364/* VENC */ 394/* VENC */
395#ifdef CONFIG_OMAP2_DSS_VENC
365int venc_init(struct platform_device *pdev); 396int venc_init(struct platform_device *pdev);
366void venc_exit(void); 397void venc_exit(void);
367void venc_dump_regs(struct seq_file *s); 398void venc_dump_regs(struct seq_file *s);
368int venc_init_display(struct omap_dss_device *display); 399int venc_init_display(struct omap_dss_device *display);
400#else
401static inline int venc_init(struct platform_device *pdev)
402{
403 return 0;
404}
405static inline void venc_exit(void)
406{
407}
408#endif
369 409
370/* RFBI */ 410/* RFBI */
411#ifdef CONFIG_OMAP2_DSS_RFBI
371int rfbi_init(void); 412int rfbi_init(void);
372void rfbi_exit(void); 413void rfbi_exit(void);
373void rfbi_dump_regs(struct seq_file *s); 414void rfbi_dump_regs(struct seq_file *s);
@@ -379,6 +420,15 @@ void rfbi_transfer_area(u16 width, u16 height,
379void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); 420void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
380unsigned long rfbi_get_max_tx_rate(void); 421unsigned long rfbi_get_max_tx_rate(void);
381int rfbi_init_display(struct omap_dss_device *display); 422int rfbi_init_display(struct omap_dss_device *display);
423#else
424static inline int rfbi_init(void)
425{
426 return 0;
427}
428static inline void rfbi_exit(void)
429{
430}
431#endif
382 432
383 433
384#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 434#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 0820986d4a6..9e1fbe531bf 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -843,6 +843,7 @@ static void configure_manager(enum omap_channel channel)
843 843
844 c = &dss_cache.manager_cache[channel]; 844 c = &dss_cache.manager_cache[channel];
845 845
846 dispc_set_default_color(channel, c->default_color);
846 dispc_set_trans_key(channel, c->trans_key_type, c->trans_key); 847 dispc_set_trans_key(channel, c->trans_key_type, c->trans_key);
847 dispc_enable_trans_key(channel, c->trans_enabled); 848 dispc_enable_trans_key(channel, c->trans_enabled);
848 dispc_enable_alpha_blending(channel, c->alpha_enabled); 849 dispc_enable_alpha_blending(channel, c->alpha_enabled);
@@ -940,6 +941,22 @@ static int configure_dispc(void)
940 return r; 941 return r;
941} 942}
942 943
944/* Make the coordinates even. There are some strange problems with OMAP and
945 * partial DSI update when the update widths are odd. */
946static void make_even(u16 *x, u16 *w)
947{
948 u16 x1, x2;
949
950 x1 = *x;
951 x2 = *x + *w;
952
953 x1 &= ~1;
954 x2 = ALIGN(x2, 2);
955
956 *x = x1;
957 *w = x2 - x1;
958}
959
943/* Configure dispc for partial update. Return possibly modified update 960/* Configure dispc for partial update. Return possibly modified update
944 * area */ 961 * area */
945void dss_setup_partial_planes(struct omap_dss_device *dssdev, 962void dss_setup_partial_planes(struct omap_dss_device *dssdev,
@@ -968,6 +985,8 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
968 return; 985 return;
969 } 986 }
970 987
988 make_even(&x, &w);
989
971 spin_lock_irqsave(&dss_cache.lock, flags); 990 spin_lock_irqsave(&dss_cache.lock, flags);
972 991
973 /* We need to show the whole overlay if it is scaled. So look for 992 /* We need to show the whole overlay if it is scaled. So look for
@@ -1029,6 +1048,8 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
1029 w = x2 - x1; 1048 w = x2 - x1;
1030 h = y2 - y1; 1049 h = y2 - y1;
1031 1050
1051 make_even(&x, &w);
1052
1032 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n", 1053 DSSDBG("changing upd area due to ovl(%d) scaling %d,%d %dx%d\n",
1033 i, x, y, w, h); 1054 i, x, y, w, h);
1034 } 1055 }
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 12eb4042dd8..ee07a3cc22e 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -23,13 +23,16 @@
23#include <linux/clk.h> 23#include <linux/clk.h>
24#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/err.h> 25#include <linux/err.h>
26#include <linux/regulator/consumer.h>
26 27
27#include <plat/display.h> 28#include <plat/display.h>
29#include <plat/cpu.h>
28#include "dss.h" 30#include "dss.h"
29 31
30static struct { 32static struct {
31 bool skip_init; 33 bool skip_init;
32 bool update_enabled; 34 bool update_enabled;
35 struct regulator *vdds_sdi_reg;
33} sdi; 36} sdi;
34 37
35static void sdi_basic_init(void) 38static void sdi_basic_init(void)
@@ -57,6 +60,10 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
57 goto err0; 60 goto err0;
58 } 61 }
59 62
63 r = regulator_enable(sdi.vdds_sdi_reg);
64 if (r)
65 goto err1;
66
60 /* In case of skip_init sdi_init has already enabled the clocks */ 67 /* In case of skip_init sdi_init has already enabled the clocks */
61 if (!sdi.skip_init) 68 if (!sdi.skip_init)
62 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 69 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
@@ -115,19 +122,12 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
115 122
116 dssdev->manager->enable(dssdev->manager); 123 dssdev->manager->enable(dssdev->manager);
117 124
118 if (dssdev->driver->enable) {
119 r = dssdev->driver->enable(dssdev);
120 if (r)
121 goto err3;
122 }
123
124 sdi.skip_init = 0; 125 sdi.skip_init = 0;
125 126
126 return 0; 127 return 0;
127err3:
128 dssdev->manager->disable(dssdev->manager);
129err2: 128err2:
130 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 129 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
130 regulator_disable(sdi.vdds_sdi_reg);
131err1: 131err1:
132 omap_dss_stop_device(dssdev); 132 omap_dss_stop_device(dssdev);
133err0: 133err0:
@@ -137,15 +137,14 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
137 137
138void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 138void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
139{ 139{
140 if (dssdev->driver->disable)
141 dssdev->driver->disable(dssdev);
142
143 dssdev->manager->disable(dssdev->manager); 140 dssdev->manager->disable(dssdev->manager);
144 141
145 dss_sdi_disable(); 142 dss_sdi_disable();
146 143
147 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 144 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
148 145
146 regulator_disable(sdi.vdds_sdi_reg);
147
149 omap_dss_stop_device(dssdev); 148 omap_dss_stop_device(dssdev);
150} 149}
151EXPORT_SYMBOL(omapdss_sdi_display_disable); 150EXPORT_SYMBOL(omapdss_sdi_display_disable);
@@ -162,6 +161,11 @@ int sdi_init(bool skip_init)
162 /* we store this for first display enable, then clear it */ 161 /* we store this for first display enable, then clear it */
163 sdi.skip_init = skip_init; 162 sdi.skip_init = skip_init;
164 163
164 sdi.vdds_sdi_reg = dss_get_vdds_sdi();
165 if (IS_ERR(sdi.vdds_sdi_reg)) {
166 DSSERR("can't get VDDS_SDI regulator\n");
167 return PTR_ERR(sdi.vdds_sdi_reg);
168 }
165 /* 169 /*
166 * Enable clocks already here, otherwise there would be a toggle 170 * Enable clocks already here, otherwise there would be a toggle
167 * of them until sdi_display_enable is called. 171 * of them until sdi_display_enable is called.
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index f0ba5732d84..eff35050e28 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -479,12 +479,6 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
479 goto err1; 479 goto err1;
480 } 480 }
481 481
482 if (dssdev->platform_enable) {
483 r = dssdev->platform_enable(dssdev);
484 if (r)
485 goto err2;
486 }
487
488 venc_power_on(dssdev); 482 venc_power_on(dssdev);
489 483
490 venc.wss_data = 0; 484 venc.wss_data = 0;
@@ -494,13 +488,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
494 /* wait couple of vsyncs until enabling the LCD */ 488 /* wait couple of vsyncs until enabling the LCD */
495 msleep(50); 489 msleep(50);
496 490
497 mutex_unlock(&venc.venc_lock);
498
499 return r;
500err2:
501 venc_power_off(dssdev);
502err1: 491err1:
503 mutex_unlock(&venc.venc_lock); 492 mutex_unlock(&venc.venc_lock);
493
504 return r; 494 return r;
505} 495}
506 496
@@ -524,9 +514,6 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
524 /* wait at least 5 vsyncs after disabling the LCD */ 514 /* wait at least 5 vsyncs after disabling the LCD */
525 msleep(100); 515 msleep(100);
526 516
527 if (dssdev->platform_disable)
528 dssdev->platform_disable(dssdev);
529
530 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 517 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
531end: 518end:
532 mutex_unlock(&venc.venc_lock); 519 mutex_unlock(&venc.venc_lock);
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 1ffa760b854..9c7361871d7 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -183,13 +183,14 @@ int omapfb_update_window(struct fb_info *fbi,
183 struct omapfb2_device *fbdev = ofbi->fbdev; 183 struct omapfb2_device *fbdev = ofbi->fbdev;
184 int r; 184 int r;
185 185
186 if (!lock_fb_info(fbi))
187 return -ENODEV;
186 omapfb_lock(fbdev); 188 omapfb_lock(fbdev);
187 lock_fb_info(fbi);
188 189
189 r = omapfb_update_window_nolock(fbi, x, y, w, h); 190 r = omapfb_update_window_nolock(fbi, x, y, w, h);
190 191
191 unlock_fb_info(fbi);
192 omapfb_unlock(fbdev); 192 omapfb_unlock(fbdev);
193 unlock_fb_info(fbi);
193 194
194 return r; 195 return r;
195} 196}
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 62bb88f5c19..5179219128b 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -57,7 +57,8 @@ static ssize_t store_rotate_type(struct device *dev,
57 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB) 57 if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
58 return -EINVAL; 58 return -EINVAL;
59 59
60 lock_fb_info(fbi); 60 if (!lock_fb_info(fbi))
61 return -ENODEV;
61 62
62 r = 0; 63 r = 0;
63 if (rot_type == ofbi->rotation_type) 64 if (rot_type == ofbi->rotation_type)
@@ -105,7 +106,8 @@ static ssize_t store_mirror(struct device *dev,
105 if (mirror != 0 && mirror != 1) 106 if (mirror != 0 && mirror != 1)
106 return -EINVAL; 107 return -EINVAL;
107 108
108 lock_fb_info(fbi); 109 if (!lock_fb_info(fbi))
110 return -ENODEV;
109 111
110 ofbi->mirror = mirror; 112 ofbi->mirror = mirror;
111 113
@@ -137,8 +139,9 @@ static ssize_t show_overlays(struct device *dev,
137 ssize_t l = 0; 139 ssize_t l = 0;
138 int t; 140 int t;
139 141
142 if (!lock_fb_info(fbi))
143 return -ENODEV;
140 omapfb_lock(fbdev); 144 omapfb_lock(fbdev);
141 lock_fb_info(fbi);
142 145
143 for (t = 0; t < ofbi->num_overlays; t++) { 146 for (t = 0; t < ofbi->num_overlays; t++) {
144 struct omap_overlay *ovl = ofbi->overlays[t]; 147 struct omap_overlay *ovl = ofbi->overlays[t];
@@ -154,8 +157,8 @@ static ssize_t show_overlays(struct device *dev,
154 157
155 l += snprintf(buf + l, PAGE_SIZE - l, "\n"); 158 l += snprintf(buf + l, PAGE_SIZE - l, "\n");
156 159
157 unlock_fb_info(fbi);
158 omapfb_unlock(fbdev); 160 omapfb_unlock(fbdev);
161 unlock_fb_info(fbi);
159 162
160 return l; 163 return l;
161} 164}
@@ -195,8 +198,9 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
195 if (buf[len - 1] == '\n') 198 if (buf[len - 1] == '\n')
196 len = len - 1; 199 len = len - 1;
197 200
201 if (!lock_fb_info(fbi))
202 return -ENODEV;
198 omapfb_lock(fbdev); 203 omapfb_lock(fbdev);
199 lock_fb_info(fbi);
200 204
201 if (len > 0) { 205 if (len > 0) {
202 char *p = (char *)buf; 206 char *p = (char *)buf;
@@ -303,8 +307,8 @@ static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
303 307
304 r = count; 308 r = count;
305out: 309out:
306 unlock_fb_info(fbi);
307 omapfb_unlock(fbdev); 310 omapfb_unlock(fbdev);
311 unlock_fb_info(fbi);
308 312
309 return r; 313 return r;
310} 314}
@@ -317,7 +321,8 @@ static ssize_t show_overlays_rotate(struct device *dev,
317 ssize_t l = 0; 321 ssize_t l = 0;
318 int t; 322 int t;
319 323
320 lock_fb_info(fbi); 324 if (!lock_fb_info(fbi))
325 return -ENODEV;
321 326
322 for (t = 0; t < ofbi->num_overlays; t++) { 327 for (t = 0; t < ofbi->num_overlays; t++) {
323 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d", 328 l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
@@ -345,7 +350,8 @@ static ssize_t store_overlays_rotate(struct device *dev,
345 if (buf[len - 1] == '\n') 350 if (buf[len - 1] == '\n')
346 len = len - 1; 351 len = len - 1;
347 352
348 lock_fb_info(fbi); 353 if (!lock_fb_info(fbi))
354 return -ENODEV;
349 355
350 if (len > 0) { 356 if (len > 0) {
351 char *p = (char *)buf; 357 char *p = (char *)buf;
@@ -416,7 +422,8 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
416 422
417 size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0)); 423 size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
418 424
419 lock_fb_info(fbi); 425 if (!lock_fb_info(fbi))
426 return -ENODEV;
420 427
421 for (i = 0; i < ofbi->num_overlays; i++) { 428 for (i = 0; i < ofbi->num_overlays; i++) {
422 if (ofbi->overlays[i]->info.enabled) { 429 if (ofbi->overlays[i]->info.enabled) {
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index e14bd074912..e8c76994481 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -695,6 +695,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
695 * 1) Enable Runtime PM 695 * 1) Enable Runtime PM
696 * 2) Force Runtime PM Resume since hardware is accessed from probe() 696 * 2) Force Runtime PM Resume since hardware is accessed from probe()
697 */ 697 */
698 priv->dev = &pdev->dev;
698 pm_runtime_enable(priv->dev); 699 pm_runtime_enable(priv->dev);
699 pm_runtime_resume(priv->dev); 700 pm_runtime_resume(priv->dev);
700 return 0; 701 return 0;
@@ -957,25 +958,24 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
957 958
958 if (!pdev->dev.platform_data) { 959 if (!pdev->dev.platform_data) {
959 dev_err(&pdev->dev, "no platform data defined\n"); 960 dev_err(&pdev->dev, "no platform data defined\n");
960 error = -EINVAL; 961 return -EINVAL;
961 goto err0;
962 } 962 }
963 963
964 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 964 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
965 i = platform_get_irq(pdev, 0); 965 i = platform_get_irq(pdev, 0);
966 if (!res || i < 0) { 966 if (!res || i < 0) {
967 dev_err(&pdev->dev, "cannot get platform resources\n"); 967 dev_err(&pdev->dev, "cannot get platform resources\n");
968 error = -ENOENT; 968 return -ENOENT;
969 goto err0;
970 } 969 }
971 970
972 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 971 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
973 if (!priv) { 972 if (!priv) {
974 dev_err(&pdev->dev, "cannot allocate device data\n"); 973 dev_err(&pdev->dev, "cannot allocate device data\n");
975 error = -ENOMEM; 974 return -ENOMEM;
976 goto err0;
977 } 975 }
978 976
977 platform_set_drvdata(pdev, priv);
978
979 error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, 979 error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED,
980 dev_name(&pdev->dev), priv); 980 dev_name(&pdev->dev), priv);
981 if (error) { 981 if (error) {
@@ -984,8 +984,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
984 } 984 }
985 985
986 priv->irq = i; 986 priv->irq = i;
987 priv->dev = &pdev->dev;
988 platform_set_drvdata(pdev, priv);
989 pdata = pdev->dev.platform_data; 987 pdata = pdev->dev.platform_data;
990 988
991 j = 0; 989 j = 0;
@@ -1099,9 +1097,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1099 info = ch->info; 1097 info = ch->info;
1100 1098
1101 if (info->fbdefio) { 1099 if (info->fbdefio) {
1102 priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * 1100 ch->sglist = vmalloc(sizeof(struct scatterlist) *
1103 info->fix.smem_len >> PAGE_SHIFT); 1101 info->fix.smem_len >> PAGE_SHIFT);
1104 if (!priv->ch->sglist) { 1102 if (!ch->sglist) {
1105 dev_err(&pdev->dev, "cannot allocate sglist\n"); 1103 dev_err(&pdev->dev, "cannot allocate sglist\n");
1106 goto err1; 1104 goto err1;
1107 } 1105 }
@@ -1126,9 +1124,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1126 } 1124 }
1127 1125
1128 return 0; 1126 return 0;
1129 err1: 1127err1:
1130 sh_mobile_lcdc_remove(pdev); 1128 sh_mobile_lcdc_remove(pdev);
1131 err0: 1129
1132 return error; 1130 return error;
1133} 1131}
1134 1132
@@ -1139,7 +1137,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1139 int i; 1137 int i;
1140 1138
1141 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1139 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1142 if (priv->ch[i].info->dev) 1140 if (priv->ch[i].info && priv->ch[i].info->dev)
1143 unregister_framebuffer(priv->ch[i].info); 1141 unregister_framebuffer(priv->ch[i].info);
1144 1142
1145 sh_mobile_lcdc_stop(priv); 1143 sh_mobile_lcdc_stop(priv);
@@ -1162,7 +1160,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1162 if (priv->dot_clk) 1160 if (priv->dot_clk)
1163 clk_put(priv->dot_clk); 1161 clk_put(priv->dot_clk);
1164 1162
1165 pm_runtime_disable(priv->dev); 1163 if (priv->dev)
1164 pm_runtime_disable(priv->dev);
1166 1165
1167 if (priv->base) 1166 if (priv->base)
1168 iounmap(priv->base); 1167 iounmap(priv->base);
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 0cadf7aee27..090aa1a9be6 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -177,7 +177,7 @@ static void vesafb_destroy(struct fb_info *info)
177{ 177{
178 if (info->screen_base) 178 if (info->screen_base)
179 iounmap(info->screen_base); 179 iounmap(info->screen_base);
180 release_mem_region(info->aperture_base, info->aperture_size); 180 release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size);
181 framebuffer_release(info); 181 framebuffer_release(info);
182} 182}
183 183
@@ -295,8 +295,13 @@ static int __init vesafb_probe(struct platform_device *dev)
295 info->par = NULL; 295 info->par = NULL;
296 296
297 /* set vesafb aperture size for generic probing */ 297 /* set vesafb aperture size for generic probing */
298 info->aperture_base = screen_info.lfb_base; 298 info->apertures = alloc_apertures(1);
299 info->aperture_size = size_total; 299 if (!info->apertures) {
300 err = -ENOMEM;
301 goto err;
302 }
303 info->apertures->ranges[0].base = screen_info.lfb_base;
304 info->apertures->ranges[0].size = size_total;
300 305
301 info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); 306 info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
302 if (!info->screen_base) { 307 if (!info->screen_base) {
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index bf638a47a5b..149c47ac7e9 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1263,10 +1263,19 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
1263 vga_imageblit_color(info, image); 1263 vga_imageblit_color(info, image);
1264} 1264}
1265 1265
1266static void vga16fb_destroy(struct fb_info *info)
1267{
1268 iounmap(info->screen_base);
1269 fb_dealloc_cmap(&info->cmap);
1270 /* XXX unshare VGA regions */
1271 framebuffer_release(info);
1272}
1273
1266static struct fb_ops vga16fb_ops = { 1274static struct fb_ops vga16fb_ops = {
1267 .owner = THIS_MODULE, 1275 .owner = THIS_MODULE,
1268 .fb_open = vga16fb_open, 1276 .fb_open = vga16fb_open,
1269 .fb_release = vga16fb_release, 1277 .fb_release = vga16fb_release,
1278 .fb_destroy = vga16fb_destroy,
1270 .fb_check_var = vga16fb_check_var, 1279 .fb_check_var = vga16fb_check_var,
1271 .fb_set_par = vga16fb_set_par, 1280 .fb_set_par = vga16fb_set_par,
1272 .fb_setcolreg = vga16fb_setcolreg, 1281 .fb_setcolreg = vga16fb_setcolreg,
@@ -1306,6 +1315,11 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
1306 ret = -ENOMEM; 1315 ret = -ENOMEM;
1307 goto err_fb_alloc; 1316 goto err_fb_alloc;
1308 } 1317 }
1318 info->apertures = alloc_apertures(1);
1319 if (!info->apertures) {
1320 ret = -ENOMEM;
1321 goto err_ioremap;
1322 }
1309 1323
1310 /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ 1324 /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
1311 info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); 1325 info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
@@ -1335,7 +1349,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
1335 info->fix = vga16fb_fix; 1349 info->fix = vga16fb_fix;
1336 /* supports rectangles with widths of multiples of 8 */ 1350 /* supports rectangles with widths of multiples of 8 */
1337 info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31; 1351 info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
1338 info->flags = FBINFO_FLAG_DEFAULT | 1352 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
1339 FBINFO_HWACCEL_YPAN; 1353 FBINFO_HWACCEL_YPAN;
1340 1354
1341 i = (info->var.bits_per_pixel == 8) ? 256 : 16; 1355 i = (info->var.bits_per_pixel == 8) ? 256 : 16;
@@ -1354,6 +1368,9 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
1354 1368
1355 vga16fb_update_fix(info); 1369 vga16fb_update_fix(info);
1356 1370
1371 info->apertures->ranges[0].base = VGA_FB_PHYS;
1372 info->apertures->ranges[0].size = VGA_FB_PHYS_LEN;
1373
1357 if (register_framebuffer(info) < 0) { 1374 if (register_framebuffer(info) < 0) {
1358 printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); 1375 printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
1359 ret = -EINVAL; 1376 ret = -EINVAL;
@@ -1380,13 +1397,8 @@ static int vga16fb_remove(struct platform_device *dev)
1380{ 1397{
1381 struct fb_info *info = platform_get_drvdata(dev); 1398 struct fb_info *info = platform_get_drvdata(dev);
1382 1399
1383 if (info) { 1400 if (info)
1384 unregister_framebuffer(info); 1401 unregister_framebuffer(info);
1385 iounmap(info->screen_base);
1386 fb_dealloc_cmap(&info->cmap);
1387 /* XXX unshare VGA regions */
1388 framebuffer_release(info);
1389 }
1390 1402
1391 return 0; 1403 return 0;
1392} 1404}
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index eeed238ad6a..d496adb0f83 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -4,4 +4,6 @@
4 4
5obj-$(CONFIG_FB_VIA) += viafb.o 5obj-$(CONFIG_FB_VIA) += viafb.o
6 6
7viafb-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 7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o 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 d5077dfa9e0..e44893ea590 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 */
27static int viafb_set_bpp(void __iomem *engine, u8 bpp)
28{
29 u32 gemode;
30
31 /* Preserve the reserved bits */
32 /* Lowest 2 bits to zero gives us no rotation */
33 gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc;
34 switch (bpp) {
35 case 8:
36 gemode |= VIA_GEM_8bpp;
37 break;
38 case 16:
39 gemode |= VIA_GEM_16bpp;
40 break;
41 case 32:
42 gemode |= VIA_GEM_32bpp;
43 break;
44 default:
45 printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp);
46 return -EINVAL;
47 }
48 writel(gemode, engine + VIA_REG_GEMODE);
49 return 0;
50}
51
52
23static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, 53static 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
469void viafb_wait_engine_idle(struct fb_info *info) 504void 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 615c84ad0f0..2c122d29236 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 8c06bd3c0b4..d9b6e06e070 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 */
125enum via_2d_engine {
126 VIA_2D_ENG_H2,
127 VIA_2D_ENG_H5,
128 VIA_2D_ENG_M1,
129};
130
124struct chip_information { 131struct 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 abe59b8c7a0..39b040bb381 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
23static void tmds_register_write(int index, u8 data); 25static 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
161static void tmds_register_write(int index, u8 data) 163static 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
171static int tmds_register_read(int index) 170static 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
183static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) 180static 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 8d95d5fd138..28221a062dd 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 f2583b1b527..b996803ae2c 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
24static struct pll_map pll_value[] = { 25static 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);
525static void set_dvi_output_path(int set_iga, int output_interface); 527static void set_dvi_output_path(int set_iga, int output_interface);
526static void set_lcd_output_path(int set_iga, int output_interface); 528static void set_lcd_output_path(int set_iga, int output_interface);
527static void load_fix_bit_crtc_reg(void); 529static void load_fix_bit_crtc_reg(void);
528static void init_gfx_chip_info(struct pci_dev *pdev, 530static void init_gfx_chip_info(int chip_type);
529 const struct pci_device_id *pdi);
530static void init_tmds_chip_info(void); 531static void init_tmds_chip_info(void);
531static void init_lvds_chip_info(void); 532static void init_lvds_chip_info(void);
532static void device_screen_off(void); 533static void device_screen_off(void);
@@ -537,18 +538,6 @@ static void device_on(void);
537static void enable_second_display_channel(void); 538static void enable_second_display_channel(void);
538static void disable_second_display_channel(void); 539static void disable_second_display_channel(void);
539 540
540void 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}
546u8 viafb_read_reg(int io_port, u8 index)
547{
548 outb(index, io_port);
549 return inb(io_port + 1);
550}
551
552void viafb_lock_crt(void) 541void 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
563void 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
573void write_dac_reg(u8 index, u8 r, u8 g, u8 b) 552void 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
649void 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
658void 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
668void 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
679void 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
688void 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
718void 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
745static void set_color_register(u8 index, u8 red, u8 green, u8 blue) 628static 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,
1126void viafb_write_regx(struct io_reg RegTable[], int ItemNum) 1009void 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
1141void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga) 1020void 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*/
1517void viafb_set_vclock(u32 CLK, int set_iga) 1396void 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
1597void viafb_load_crtc_timing(struct display_timing device_timing, 1473void 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
1913void viafb_init_chip_info(struct pci_dev *pdev, 1781void 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
1983static void init_gfx_chip_info(struct pci_dev *pdev, 1850static 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
2021static void init_tmds_chip_info(void) 1902static 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
2476int 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
2579void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 2354void 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 12ef32d334c..a109de37981 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;
870extern int viafb_DVI_ON; 875extern int viafb_DVI_ON;
871extern int viafb_hotplug; 876extern int viafb_hotplug;
872 877
873void viafb_write_reg_mask(u8 index, int io_port, u8 data, u8 mask);
874void viafb_set_output_path(int device, int set_iga, 878void 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);
885void viafb_crt_enable(void); 889void viafb_crt_enable(void);
886void init_ad9389(void); 890void init_ad9389(void);
887/* Access I/O Function */ 891/* Access I/O Function */
888void viafb_write_reg(u8 index, u16 io_port, u8 data);
889u8 viafb_read_reg(int io_port, u8 index);
890void viafb_lock_crt(void); 892void viafb_lock_crt(void);
891void viafb_unlock_crt(void); 893void viafb_unlock_crt(void);
892void viafb_load_fetch_count_reg(int h_addr, int bpp_byte, int set_iga); 894void 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);
901void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, 903void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh,
902 struct VideoModeTable *vmode_tbl); 904 struct VideoModeTable *vmode_tbl);
903void viafb_init_chip_info(struct pci_dev *pdev, 905void viafb_init_chip_info(int chip_type);
904 const struct pci_device_id *pdi);
905void viafb_init_dac(int set_iga); 906void viafb_init_dac(int set_iga);
906int viafb_get_pixclock(int hres, int vres, int vmode_refresh); 907int viafb_get_pixclock(int hres, int vres, int vmode_refresh);
907int viafb_get_refresh(int hres, int vres, u32 float_refresh); 908int viafb_get_refresh(int hres, int vres, u32 float_refresh);
908void viafb_update_device_setting(int hres, int vres, int bpp, 909void viafb_update_device_setting(int hres, int vres, int bpp,
909 int vmode_refresh, int flag); 910 int vmode_refresh, int flag);
910 911
911int viafb_get_fb_size_from_pci(void);
912void viafb_set_iga_path(void); 912void viafb_set_iga_path(void);
913void viafb_set_primary_address(u32 addr);
914void viafb_set_secondary_address(u32 addr);
915void viafb_set_primary_pitch(u32 pitch);
916void viafb_set_secondary_pitch(u32 pitch);
917void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue); 913void viafb_set_primary_color_register(u8 index, u8 red, u8 green, u8 blue);
918void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue); 914void viafb_set_secondary_color_register(u8 index, u8 red, u8 green, u8 blue);
919void viafb_get_fb_info(unsigned int *fb_base, unsigned int *fb_len); 915void 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 de899807ead..c430fa23008 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 1b1ccdc2d83..2ab0f156439 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
173int viafb_lvds_trasmitter_identify(void) 174int 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 071f47cf5be..9762ec62b49 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
65extern int viafb_LCD2_ON; 67extern int viafb_LCD2_ON;
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index d55aaa7b912..7f0de7f006a 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 00000000000..e8cfe839211
--- /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 */
22static 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 */
35static struct viafb_dev global_dev;
36
37
38/*
39 * Basic register access; spinlock required.
40 */
41static inline void viafb_mmio_write(int reg, u32 v)
42{
43 iowrite32(v, global_dev.engine_mmio + reg);
44}
45
46static 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 */
65static u32 viafb_enabled_ints;
66
67static 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 */
78void viafb_irq_enable(u32 mask)
79{
80 viafb_enabled_ints |= mask;
81 viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE);
82}
83EXPORT_SYMBOL_GPL(viafb_irq_enable);
84
85void 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}
94EXPORT_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 */
109static int viafb_dma_users;
110static 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 */
116static DEFINE_MUTEX(viafb_dma_lock);
117
118/*
119 * The VX855 DMA descriptor (used for s/g transfers) looks
120 * like this.
121 */
122struct 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 */
142static 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 */
161int 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}
187EXPORT_SYMBOL_GPL(viafb_request_dma);
188
189void 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}
199EXPORT_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 */
207void 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}
241EXPORT_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 */
248int 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}
324EXPORT_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 */
333static 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 */
341static 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 */
454static 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;
487out_unmap:
488 iounmap(vdev->engine_mmio);
489 return ret;
490}
491
492static 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 */
501static 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
514static 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
537static 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
551static 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
563static 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
596out_subdevs:
597 via_teardown_subdevs();
598 via_pci_teardown_mmio(&global_dev);
599out_disable:
600 pci_disable_device(pdev);
601 return ret;
602}
603
604static 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
613static 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};
638MODULE_DEVICE_TABLE(pci, via_pci_table);
639
640static 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
647static 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
659static 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
667module_init(via_core_init);
668module_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 00000000000..595516aea69
--- /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
19struct 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
26static 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
72struct 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 */
82static 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
104static 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 */
115static 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
131static 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
148static 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 */
165static void viafb_gpio_enable(struct viafb_gpio *gpio)
166{
167 via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02);
168}
169
170static 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 */
178int 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}
187EXPORT_SYMBOL_GPL(viafb_gpio_lookup);
188
189/*
190 * Platform device stuff.
191 */
192static __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
243static 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
269static 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
277int viafb_gpio_init(void)
278{
279 return platform_driver_register(&via_gpio_driver);
280}
281
282void 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 15543e96824..da9e4ca94b1 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
34static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
35struct viafb_dev *i2c_vdev; /* Passed in from core */
23 36
24static void via_i2c_setscl(void *data, int state) 37static 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
47static int via_i2c_getscl(void *data) 63static 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
56static int via_i2c_getsda(void *data) 76static 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
65static void via_i2c_setsda(void *data, int state) 89static 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
88int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata) 115int 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
105int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data) 132int 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
117int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len) 146int 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
132int viafb_create_i2c_bus(void *viapar) 162/*
163 * Allow other viafb subdevices to look up a specific adapter
164 * by port name.
165 */
166struct 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); 172EXPORT_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); 175static 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
208static 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
237static 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
253static 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
261int viafb_i2c_init(void)
262{
263 return platform_driver_register(&via_i2c_driver);
172} 264}
173 265
174void viafb_delete_i2c_buss(void *par) 266void 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 00000000000..3cddcff88ab
--- /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
32void 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
41void 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
51void 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
62void 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
71void 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
101void 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 3a13242a315..ae35cfdeb37 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
27struct 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 31void via_set_primary_address(u32 addr);
34#define I2CPORTINDEX 0x31 32void via_set_secondary_address(u32 addr);
35#define GPIOPORT 0x3C4 33void via_set_primary_pitch(u32 pitch);
36#define GPIOPORTINDEX 0x2C 34void via_set_secondary_pitch(u32 pitch);
37#define I2C_BUS 1 35void via_set_primary_color_depth(u8 depth);
38#define GPIO_BUS 2 36void via_set_secondary_color_depth(u8 depth);
39#define DELAYPORT 0x3C3
40 37
41int viafb_i2c_readbyte(u8 slave_addr, u8 index, u8 *pdata); 38#endif /* __VIA_MODESETTING_H__ */
42int viafb_i2c_writebyte(u8 slave_addr, u8 index, u8 data);
43int viafb_i2c_readbytes(u8 slave_addr, u8 index, u8 *buff, int buff_len);
44int viafb_create_i2c_bus(void *par);
45void 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 aefdeeec89b..d05ccb62b55 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
24void viafb_get_device_support_state(u32 *support_state) 25void viafb_get_device_support_state(u32 *support_state)
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 777b38a06d4..2bc40e682f9 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
30static char *viafb_name = "Via"; 31static 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,
765static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) 766static 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}
1702static void viafb_remove_proc(struct proc_dir_entry *viafb_entry) 1706static 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
1714static int parse_mode(const char *str, u32 *xres, u32 *yres) 1723static 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
1735static int __devinit via_pci_probe(struct pci_dev *pdev, 1744
1736 const struct pci_device_id *ent) 1745int __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
1957out_fb_unreg:
1958 unregister_framebuffer(viafbinfo);
1959out_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);
1963out_dealloc_cmap:
1964 fb_dealloc_cmap(&viafbinfo->cmap);
1965out_fb1_release:
1966 if (viafbinfo1)
1967 framebuffer_release(viafbinfo1);
1968out_fb_release:
1969 framebuffer_release(viafbinfo);
1970 return rc;
1940} 1971}
1941 1972
1942static void __devexit via_pci_remove(struct pci_dev *pdev) 1973void __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
2034static 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), 2064int __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};
2059MODULE_DEVICE_TABLE(pci, viafb_pci_table);
2060
2061static 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
2068static 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
2090static void __exit viafb_exit(void) 2086void __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
2096static struct fb_ops viafb_ops = { 2091static 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
2113module_init(viafb_init);
2114module_exit(viafb_exit);
2115 2108
2116#ifdef MODULE 2109#ifdef MODULE
2117module_param(viafb_mode, charp, S_IRUSR); 2110module_param(viafb_mode, charp, S_IRUSR);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index 61b5953cd15..52a35fabba9 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
40struct viafb_shared { 42struct 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
99void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information 98void 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);
101int via_fb_pci_probe(struct viafb_dev *vdev);
102void via_fb_pci_remove(struct pci_dev *pdev);
103/* Temporary */
104int viafb_init(void);
105void 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 af50e244016..2dbad3c0f67 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"
23struct res_map_refresh res_map_refresh_tbl[] = { 24struct 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) */
765struct 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) */
763struct crt_mode_table CRTM1280x600[] = { 775struct 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 a6b37494e79..d65bf1aee87 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
24u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information 26u8 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
52void viafb_init_lvds_vt1636(struct lvds_setting_information 52void 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
162bool viafb_lvds_identify_vt1636(void) 162bool 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 2a150c58c7e..4c1314e5746 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"
25bool viafb_lvds_identify_vt1636(void); 25bool viafb_lvds_identify_vt1636(u8 i2c_adapter);
26void viafb_init_lvds_vt1636(struct lvds_setting_information 26void 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);
28void viafb_enable_lvds_vt1636(struct lvds_setting_information 28void viafb_enable_lvds_vt1636(struct lvds_setting_information