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