diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 14 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/aty/aty128fb.c | 33 | ||||
-rw-r--r-- | drivers/video/aty/atyfb_base.c | 42 | ||||
-rw-r--r-- | drivers/video/aty/mach64_ct.c | 11 | ||||
-rw-r--r-- | drivers/video/aty/radeon_base.c | 10 | ||||
-rw-r--r-- | drivers/video/aty/radeon_i2c.c | 1 | ||||
-rw-r--r-- | drivers/video/aty/radeon_pm.c | 103 | ||||
-rw-r--r-- | drivers/video/aty/radeonfb.h | 2 | ||||
-rw-r--r-- | drivers/video/backlight/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/backlight/da903x_bl.c (renamed from drivers/video/backlight/da903x.c) | 0 | ||||
-rw-r--r-- | drivers/video/fbcmap.c | 20 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 135 | ||||
-rw-r--r-- | drivers/video/i810/i810-i2c.c | 1 | ||||
-rw-r--r-- | drivers/video/intelfb/intelfb_i2c.c | 1 | ||||
-rw-r--r-- | drivers/video/mx3fb.c | 1555 | ||||
-rw-r--r-- | drivers/video/nvidia/nv_i2c.c | 1 | ||||
-rw-r--r-- | drivers/video/omap/lcdc.c | 4 | ||||
-rw-r--r-- | drivers/video/savage/savagefb-i2c.c | 1 |
19 files changed, 1745 insertions, 192 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6372f8b17b45..f0267706cb45 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -41,7 +41,7 @@ menuconfig FB | |||
41 | You need an utility program called fbset to make full use of frame | 41 | You need an utility program called fbset to make full use of frame |
42 | buffer devices. Please read <file:Documentation/fb/framebuffer.txt> | 42 | buffer devices. Please read <file:Documentation/fb/framebuffer.txt> |
43 | and the Framebuffer-HOWTO at | 43 | and the Framebuffer-HOWTO at |
44 | <http://www.tahallah.demon.co.uk/programming/prog.html> for more | 44 | <http://www.munted.org.uk/programming/Framebuffer-HOWTO-1.2.html> for more |
45 | information. | 45 | information. |
46 | 46 | ||
47 | Say Y here and to the driver for your graphics board below if you | 47 | Say Y here and to the driver for your graphics board below if you |
@@ -2123,6 +2123,18 @@ config FB_PRE_INIT_FB | |||
2123 | Select this option if display contents should be inherited as set by | 2123 | Select this option if display contents should be inherited as set by |
2124 | the bootloader. | 2124 | the bootloader. |
2125 | 2125 | ||
2126 | config FB_MX3 | ||
2127 | tristate "MX3 Framebuffer support" | ||
2128 | depends on FB && MX3_IPU | ||
2129 | select FB_CFB_FILLRECT | ||
2130 | select FB_CFB_COPYAREA | ||
2131 | select FB_CFB_IMAGEBLIT | ||
2132 | default y | ||
2133 | help | ||
2134 | This is a framebuffer device for the i.MX31 LCD Controller. So | ||
2135 | far only synchronous displays are supported. If you plan to use | ||
2136 | an LCD display with your i.MX31 system, say Y here. | ||
2137 | |||
2126 | source "drivers/video/omap/Kconfig" | 2138 | source "drivers/video/omap/Kconfig" |
2127 | 2139 | ||
2128 | source "drivers/video/backlight/Kconfig" | 2140 | source "drivers/video/backlight/Kconfig" |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index be2b657546ef..2a998ca6181d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -132,6 +132,7 @@ obj-$(CONFIG_FB_VGA16) += vga16fb.o | |||
132 | obj-$(CONFIG_FB_OF) += offb.o | 132 | obj-$(CONFIG_FB_OF) += offb.o |
133 | obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o | 133 | obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o |
134 | obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o | 134 | obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o |
135 | obj-$(CONFIG_FB_MX3) += mx3fb.o | ||
135 | 136 | ||
136 | # the test framebuffer is last | 137 | # the test framebuffer is last |
137 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o | 138 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index db16112cf197..e6e299feb51b 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -1475,7 +1475,7 @@ static int aty128fb_set_par(struct fb_info *info) | |||
1475 | aty128_set_pll(&par->pll, par); | 1475 | aty128_set_pll(&par->pll, par); |
1476 | aty128_set_fifo(&par->fifo_reg, par); | 1476 | aty128_set_fifo(&par->fifo_reg, par); |
1477 | 1477 | ||
1478 | config = aty_ld_le32(CONFIG_CNTL) & ~3; | 1478 | config = aty_ld_le32(CNFG_CNTL) & ~3; |
1479 | 1479 | ||
1480 | #if defined(__BIG_ENDIAN) | 1480 | #if defined(__BIG_ENDIAN) |
1481 | if (par->crtc.bpp == 32) | 1481 | if (par->crtc.bpp == 32) |
@@ -1484,7 +1484,7 @@ static int aty128fb_set_par(struct fb_info *info) | |||
1484 | config |= 1; /* make aperture do 16 bit swapping */ | 1484 | config |= 1; /* make aperture do 16 bit swapping */ |
1485 | #endif | 1485 | #endif |
1486 | 1486 | ||
1487 | aty_st_le32(CONFIG_CNTL, config); | 1487 | aty_st_le32(CNFG_CNTL, config); |
1488 | aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ | 1488 | aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */ |
1489 | 1489 | ||
1490 | info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; | 1490 | info->fix.line_length = (par->crtc.vxres * par->crtc.bpp) >> 3; |
@@ -1875,7 +1875,7 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i | |||
1875 | u32 dac; | 1875 | u32 dac; |
1876 | 1876 | ||
1877 | /* Get the chip revision */ | 1877 | /* Get the chip revision */ |
1878 | chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; | 1878 | chip_rev = (aty_ld_le32(CNFG_CNTL) >> 16) & 0x1F; |
1879 | 1879 | ||
1880 | strcpy(video_card, "Rage128 XX "); | 1880 | strcpy(video_card, "Rage128 XX "); |
1881 | video_card[8] = ent->device >> 8; | 1881 | video_card[8] = ent->device >> 8; |
@@ -2057,7 +2057,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ | |||
2057 | 2057 | ||
2058 | /* Grab memory size from the card */ | 2058 | /* Grab memory size from the card */ |
2059 | // How does this relate to the resource length from the PCI hardware? | 2059 | // How does this relate to the resource length from the PCI hardware? |
2060 | par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; | 2060 | par->vram_size = aty_ld_le32(CNFG_MEMSIZE) & 0x03FFFFFF; |
2061 | 2061 | ||
2062 | /* Virtualize the framebuffer */ | 2062 | /* Virtualize the framebuffer */ |
2063 | info->screen_base = ioremap(fb_addr, par->vram_size); | 2063 | info->screen_base = ioremap(fb_addr, par->vram_size); |
@@ -2374,6 +2374,8 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) | |||
2374 | /* Set the chip into the appropriate suspend mode (we use D2, | 2374 | /* Set the chip into the appropriate suspend mode (we use D2, |
2375 | * D3 would require a complete re-initialisation of the chip, | 2375 | * D3 would require a complete re-initialisation of the chip, |
2376 | * including PCI config registers, clocks, AGP configuration, ...) | 2376 | * including PCI config registers, clocks, AGP configuration, ...) |
2377 | * | ||
2378 | * For resume, the core will have already brought us back to D0 | ||
2377 | */ | 2379 | */ |
2378 | if (suspend) { | 2380 | if (suspend) { |
2379 | /* Make sure CRTC2 is reset. Remove that the day we decide to | 2381 | /* Make sure CRTC2 is reset. Remove that the day we decide to |
@@ -2391,17 +2393,9 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend) | |||
2391 | aty_st_le32(BUS_CNTL1, 0x00000010); | 2393 | aty_st_le32(BUS_CNTL1, 0x00000010); |
2392 | aty_st_le32(MEM_POWER_MISC, 0x0c830000); | 2394 | aty_st_le32(MEM_POWER_MISC, 0x0c830000); |
2393 | mdelay(100); | 2395 | mdelay(100); |
2394 | pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); | 2396 | |
2395 | /* Switch PCI power management to D2 */ | 2397 | /* Switch PCI power management to D2 */ |
2396 | pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, | 2398 | pci_set_power_state(pdev, PCI_D2); |
2397 | (pwr_command & ~PCI_PM_CTRL_STATE_MASK) | 2); | ||
2398 | pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); | ||
2399 | } else { | ||
2400 | /* Switch back PCI power management to D0 */ | ||
2401 | mdelay(100); | ||
2402 | pci_write_config_word(pdev, par->pm_reg+PCI_PM_CTRL, 0); | ||
2403 | pci_read_config_word(pdev, par->pm_reg+PCI_PM_CTRL, &pwr_command); | ||
2404 | mdelay(100); | ||
2405 | } | 2399 | } |
2406 | } | 2400 | } |
2407 | 2401 | ||
@@ -2410,6 +2404,12 @@ static int aty128_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2410 | struct fb_info *info = pci_get_drvdata(pdev); | 2404 | struct fb_info *info = pci_get_drvdata(pdev); |
2411 | struct aty128fb_par *par = info->par; | 2405 | struct aty128fb_par *par = info->par; |
2412 | 2406 | ||
2407 | /* Because we may change PCI D state ourselves, we need to | ||
2408 | * first save the config space content so the core can | ||
2409 | * restore it properly on resume. | ||
2410 | */ | ||
2411 | pci_save_state(pdev); | ||
2412 | |||
2413 | /* We don't do anything but D2, for now we return 0, but | 2413 | /* We don't do anything but D2, for now we return 0, but |
2414 | * we may want to change that. How do we know if the BIOS | 2414 | * we may want to change that. How do we know if the BIOS |
2415 | * can properly take care of D3 ? Also, with swsusp, we | 2415 | * can properly take care of D3 ? Also, with swsusp, we |
@@ -2476,6 +2476,11 @@ static int aty128_do_resume(struct pci_dev *pdev) | |||
2476 | if (pdev->dev.power.power_state.event == PM_EVENT_ON) | 2476 | if (pdev->dev.power.power_state.event == PM_EVENT_ON) |
2477 | return 0; | 2477 | return 0; |
2478 | 2478 | ||
2479 | /* PCI state will have been restored by the core, so | ||
2480 | * we should be in D0 now with our config space fully | ||
2481 | * restored | ||
2482 | */ | ||
2483 | |||
2479 | /* Wakeup chip */ | 2484 | /* Wakeup chip */ |
2480 | aty128_set_suspend(par, 0); | 2485 | aty128_set_suspend(par, 0); |
2481 | par->asleep = 0; | 2486 | par->asleep = 0; |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index cc6b470073da..1207c208a30b 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
@@ -135,7 +135,7 @@ | |||
135 | #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ | 135 | #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ |
136 | defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) | 136 | defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) |
137 | static const u32 lt_lcd_regs[] = { | 137 | static const u32 lt_lcd_regs[] = { |
138 | CONFIG_PANEL_LG, | 138 | CNFG_PANEL_LG, |
139 | LCD_GEN_CNTL_LG, | 139 | LCD_GEN_CNTL_LG, |
140 | DSTN_CONTROL_LG, | 140 | DSTN_CONTROL_LG, |
141 | HFB_PITCH_ADDR_LG, | 141 | HFB_PITCH_ADDR_LG, |
@@ -446,7 +446,7 @@ static int __devinit correct_chipset(struct atyfb_par *par) | |||
446 | par->pll_limits.ecp_max = aty_chips[i].ecp_max; | 446 | par->pll_limits.ecp_max = aty_chips[i].ecp_max; |
447 | par->features = aty_chips[i].features; | 447 | par->features = aty_chips[i].features; |
448 | 448 | ||
449 | chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); | 449 | chip_id = aty_ld_le32(CNFG_CHIP_ID, par); |
450 | type = chip_id & CFG_CHIP_TYPE; | 450 | type = chip_id & CFG_CHIP_TYPE; |
451 | rev = (chip_id & CFG_CHIP_REV) >> 24; | 451 | rev = (chip_id & CFG_CHIP_REV) >> 24; |
452 | 452 | ||
@@ -629,7 +629,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) | |||
629 | crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); | 629 | crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); |
630 | aty_st_le32(LCD_INDEX, crtc->lcd_index, par); | 630 | aty_st_le32(LCD_INDEX, crtc->lcd_index, par); |
631 | } | 631 | } |
632 | crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par); | 632 | crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par); |
633 | crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); | 633 | crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); |
634 | 634 | ||
635 | 635 | ||
@@ -676,7 +676,7 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) | |||
676 | aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); | 676 | aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); |
677 | 677 | ||
678 | /* update non-shadow registers first */ | 678 | /* update non-shadow registers first */ |
679 | aty_st_lcd(CONFIG_PANEL, crtc->lcd_config_panel, par); | 679 | aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par); |
680 | aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & | 680 | aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & |
681 | ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); | 681 | ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); |
682 | 682 | ||
@@ -858,7 +858,7 @@ static int aty_var_to_crtc(const struct fb_info *info, | |||
858 | if (!M64_HAS(MOBIL_BUS)) | 858 | if (!M64_HAS(MOBIL_BUS)) |
859 | crtc->lcd_index |= CRTC2_DISPLAY_DIS; | 859 | crtc->lcd_index |= CRTC2_DISPLAY_DIS; |
860 | 860 | ||
861 | crtc->lcd_config_panel = aty_ld_lcd(CONFIG_PANEL, par) | 0x4000; | 861 | crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par) | 0x4000; |
862 | crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT; | 862 | crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par) & ~CRTC_RW_SELECT; |
863 | 863 | ||
864 | crtc->lcd_gen_cntl &= | 864 | crtc->lcd_gen_cntl &= |
@@ -1978,7 +1978,7 @@ static int aty_power_mgmt(int sleep, struct atyfb_par *par) | |||
1978 | 1978 | ||
1979 | return timeout ? 0 : -EIO; | 1979 | return timeout ? 0 : -EIO; |
1980 | } | 1980 | } |
1981 | #endif | 1981 | #endif /* CONFIG_PPC_PMAC */ |
1982 | 1982 | ||
1983 | static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 1983 | static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) |
1984 | { | 1984 | { |
@@ -2002,9 +2002,15 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2002 | par->asleep = 1; | 2002 | par->asleep = 1; |
2003 | par->lock_blank = 1; | 2003 | par->lock_blank = 1; |
2004 | 2004 | ||
2005 | /* Because we may change PCI D state ourselves, we need to | ||
2006 | * first save the config space content so the core can | ||
2007 | * restore it properly on resume. | ||
2008 | */ | ||
2009 | pci_save_state(pdev); | ||
2010 | |||
2005 | #ifdef CONFIG_PPC_PMAC | 2011 | #ifdef CONFIG_PPC_PMAC |
2006 | /* Set chip to "suspend" mode */ | 2012 | /* Set chip to "suspend" mode */ |
2007 | if (aty_power_mgmt(1, par)) { | 2013 | if (machine_is(powermac) && aty_power_mgmt(1, par)) { |
2008 | par->asleep = 0; | 2014 | par->asleep = 0; |
2009 | par->lock_blank = 0; | 2015 | par->lock_blank = 0; |
2010 | atyfb_blank(FB_BLANK_UNBLANK, info); | 2016 | atyfb_blank(FB_BLANK_UNBLANK, info); |
@@ -2047,11 +2053,15 @@ static int atyfb_pci_resume(struct pci_dev *pdev) | |||
2047 | 2053 | ||
2048 | acquire_console_sem(); | 2054 | acquire_console_sem(); |
2049 | 2055 | ||
2056 | /* PCI state will have been restored by the core, so | ||
2057 | * we should be in D0 now with our config space fully | ||
2058 | * restored | ||
2059 | */ | ||
2060 | |||
2050 | #ifdef CONFIG_PPC_PMAC | 2061 | #ifdef CONFIG_PPC_PMAC |
2051 | if (pdev->dev.power.power_state.event == 2) | 2062 | if (machine_is(powermac) && |
2063 | pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) | ||
2052 | aty_power_mgmt(0, par); | 2064 | aty_power_mgmt(0, par); |
2053 | #else | ||
2054 | pci_set_power_state(pdev, PCI_D0); | ||
2055 | #endif | 2065 | #endif |
2056 | 2066 | ||
2057 | aty_resume_chip(info); | 2067 | aty_resume_chip(info); |
@@ -2254,7 +2264,7 @@ static int __devinit aty_init(struct fb_info *info) | |||
2254 | if (!M64_HAS(INTEGRATED)) { | 2264 | if (!M64_HAS(INTEGRATED)) { |
2255 | u32 stat0; | 2265 | u32 stat0; |
2256 | u8 dac_type, dac_subtype, clk_type; | 2266 | u8 dac_type, dac_subtype, clk_type; |
2257 | stat0 = aty_ld_le32(CONFIG_STAT0, par); | 2267 | stat0 = aty_ld_le32(CNFG_STAT0, par); |
2258 | par->bus_type = (stat0 >> 0) & 0x07; | 2268 | par->bus_type = (stat0 >> 0) & 0x07; |
2259 | par->ram_type = (stat0 >> 3) & 0x07; | 2269 | par->ram_type = (stat0 >> 3) & 0x07; |
2260 | ramname = aty_gx_ram[par->ram_type]; | 2270 | ramname = aty_gx_ram[par->ram_type]; |
@@ -2324,7 +2334,7 @@ static int __devinit aty_init(struct fb_info *info) | |||
2324 | par->dac_ops = &aty_dac_ct; | 2334 | par->dac_ops = &aty_dac_ct; |
2325 | par->pll_ops = &aty_pll_ct; | 2335 | par->pll_ops = &aty_pll_ct; |
2326 | par->bus_type = PCI; | 2336 | par->bus_type = PCI; |
2327 | par->ram_type = (aty_ld_le32(CONFIG_STAT0, par) & 0x07); | 2337 | par->ram_type = (aty_ld_le32(CNFG_STAT0, par) & 0x07); |
2328 | ramname = aty_ct_ram[par->ram_type]; | 2338 | ramname = aty_ct_ram[par->ram_type]; |
2329 | /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ | 2339 | /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */ |
2330 | if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) | 2340 | if (par->pll_limits.mclk == 67 && par->ram_type < SDRAM) |
@@ -2433,7 +2443,7 @@ static int __devinit aty_init(struct fb_info *info) | |||
2433 | } | 2443 | } |
2434 | 2444 | ||
2435 | if (M64_HAS(MAGIC_VRAM_SIZE)) { | 2445 | if (M64_HAS(MAGIC_VRAM_SIZE)) { |
2436 | if (aty_ld_le32(CONFIG_STAT1, par) & 0x40000000) | 2446 | if (aty_ld_le32(CNFG_STAT1, par) & 0x40000000) |
2437 | info->fix.smem_len += 0x400000; | 2447 | info->fix.smem_len += 0x400000; |
2438 | } | 2448 | } |
2439 | 2449 | ||
@@ -2946,7 +2956,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, | |||
2946 | * Fix PROMs idea of MEM_CNTL settings... | 2956 | * Fix PROMs idea of MEM_CNTL settings... |
2947 | */ | 2957 | */ |
2948 | mem = aty_ld_le32(MEM_CNTL, par); | 2958 | mem = aty_ld_le32(MEM_CNTL, par); |
2949 | chip_id = aty_ld_le32(CONFIG_CHIP_ID, par); | 2959 | chip_id = aty_ld_le32(CNFG_CHIP_ID, par); |
2950 | if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) { | 2960 | if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) && !((chip_id >> 24) & 1)) { |
2951 | switch (mem & 0x0f) { | 2961 | switch (mem & 0x0f) { |
2952 | case 3: | 2962 | case 3: |
@@ -2964,7 +2974,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, | |||
2964 | default: | 2974 | default: |
2965 | break; | 2975 | break; |
2966 | } | 2976 | } |
2967 | if ((aty_ld_le32(CONFIG_STAT0, par) & 7) >= SDRAM) | 2977 | if ((aty_ld_le32(CNFG_STAT0, par) & 7) >= SDRAM) |
2968 | mem &= ~(0x00700000); | 2978 | mem &= ~(0x00700000); |
2969 | } | 2979 | } |
2970 | mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */ | 2980 | mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */ |
@@ -3572,7 +3582,7 @@ static int __init atyfb_atari_probe(void) | |||
3572 | } | 3582 | } |
3573 | 3583 | ||
3574 | /* Fake pci_id for correct_chipset() */ | 3584 | /* Fake pci_id for correct_chipset() */ |
3575 | switch (aty_ld_le32(CONFIG_CHIP_ID, par) & CFG_CHIP_TYPE) { | 3585 | switch (aty_ld_le32(CNFG_CHIP_ID, par) & CFG_CHIP_TYPE) { |
3576 | case 0x00d7: | 3586 | case 0x00d7: |
3577 | par->pci_id = PCI_CHIP_MACH64GX; | 3587 | par->pci_id = PCI_CHIP_MACH64GX; |
3578 | break; | 3588 | break; |
diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c index c50c7cf26fe9..2745b8539485 100644 --- a/drivers/video/aty/mach64_ct.c +++ b/drivers/video/aty/mach64_ct.c | |||
@@ -8,6 +8,9 @@ | |||
8 | #include <asm/io.h> | 8 | #include <asm/io.h> |
9 | #include <video/mach64.h> | 9 | #include <video/mach64.h> |
10 | #include "atyfb.h" | 10 | #include "atyfb.h" |
11 | #ifdef CONFIG_PPC | ||
12 | #include <asm/machdep.h> | ||
13 | #endif | ||
11 | 14 | ||
12 | #undef DEBUG | 15 | #undef DEBUG |
13 | 16 | ||
@@ -536,6 +539,14 @@ static int __devinit aty_init_pll_ct(const struct fb_info *info, | |||
536 | pll->ct.xclk_post_div_real = postdividers[xpost_div]; | 539 | pll->ct.xclk_post_div_real = postdividers[xpost_div]; |
537 | pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8; | 540 | pll->ct.mclk_fb_div = q * pll->ct.xclk_post_div_real / 8; |
538 | 541 | ||
542 | #ifdef CONFIG_PPC | ||
543 | if (machine_is(powermac)) { | ||
544 | /* Override PLL_EXT_CNTL & 0x07. */ | ||
545 | pll->ct.xclk_post_div = xpost_div; | ||
546 | pll->ct.xclk_ref_div = 1; | ||
547 | } | ||
548 | #endif | ||
549 | |||
539 | #ifdef DEBUG | 550 | #ifdef DEBUG |
540 | pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) / | 551 | pllmclk = (1000000 * pll->ct.mclk_fb_mult * pll->ct.mclk_fb_div) / |
541 | (par->ref_clk_per * pll->ct.pll_ref_div); | 552 | (par->ref_clk_per * pll->ct.pll_ref_div); |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index d0f1a7fc2c9d..16bb7e3c0310 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -1936,8 +1936,8 @@ static void fixup_memory_mappings(struct radeonfb_info *rinfo) | |||
1936 | OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); | 1936 | OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); |
1937 | mdelay(100); | 1937 | mdelay(100); |
1938 | 1938 | ||
1939 | aper_base = INREG(CONFIG_APER_0_BASE); | 1939 | aper_base = INREG(CNFG_APER_0_BASE); |
1940 | aper_size = INREG(CONFIG_APER_SIZE); | 1940 | aper_size = INREG(CNFG_APER_SIZE); |
1941 | 1941 | ||
1942 | #ifdef SET_MC_FB_FROM_APERTURE | 1942 | #ifdef SET_MC_FB_FROM_APERTURE |
1943 | /* Set framebuffer to be at the same address as set in PCI BAR */ | 1943 | /* Set framebuffer to be at the same address as set in PCI BAR */ |
@@ -2024,11 +2024,11 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) | |||
2024 | ~CRTC_H_CUTOFF_ACTIVE_EN); | 2024 | ~CRTC_H_CUTOFF_ACTIVE_EN); |
2025 | } | 2025 | } |
2026 | } else { | 2026 | } else { |
2027 | tmp = INREG(CONFIG_MEMSIZE); | 2027 | tmp = INREG(CNFG_MEMSIZE); |
2028 | } | 2028 | } |
2029 | 2029 | ||
2030 | /* mem size is bits [28:0], mask off the rest */ | 2030 | /* mem size is bits [28:0], mask off the rest */ |
2031 | rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK; | 2031 | rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK; |
2032 | 2032 | ||
2033 | /* | 2033 | /* |
2034 | * Hack to get around some busted production M6's | 2034 | * Hack to get around some busted production M6's |
@@ -2228,7 +2228,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, | |||
2228 | */ | 2228 | */ |
2229 | rinfo->errata = 0; | 2229 | rinfo->errata = 0; |
2230 | if (rinfo->family == CHIP_FAMILY_R300 && | 2230 | if (rinfo->family == CHIP_FAMILY_R300 && |
2231 | (INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) | 2231 | (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) |
2232 | == CFG_ATI_REV_A11) | 2232 | == CFG_ATI_REV_A11) |
2233 | rinfo->errata |= CHIP_ERRATA_R300_CG; | 2233 | rinfo->errata |= CHIP_ERRATA_R300_CG; |
2234 | 2234 | ||
diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 2c5567175dca..359fc64e761a 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c | |||
@@ -72,7 +72,6 @@ static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name) | |||
72 | snprintf(chan->adapter.name, sizeof(chan->adapter.name), | 72 | snprintf(chan->adapter.name, sizeof(chan->adapter.name), |
73 | "radeonfb %s", name); | 73 | "radeonfb %s", name); |
74 | chan->adapter.owner = THIS_MODULE; | 74 | chan->adapter.owner = THIS_MODULE; |
75 | chan->adapter.id = I2C_HW_B_RADEON; | ||
76 | chan->adapter.algo_data = &chan->algo; | 75 | chan->adapter.algo_data = &chan->algo; |
77 | chan->adapter.dev.parent = &chan->rinfo->pdev->dev; | 76 | chan->adapter.dev.parent = &chan->rinfo->pdev->dev; |
78 | chan->algo.setsda = radeon_gpio_setsda; | 77 | chan->algo.setsda = radeon_gpio_setsda; |
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 675abdafc2d8..ca5f0dc28546 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c | |||
@@ -333,7 +333,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) | |||
333 | if (!rinfo->has_CRTC2) { | 333 | if (!rinfo->has_CRTC2) { |
334 | tmp = INPLL(pllSCLK_CNTL); | 334 | tmp = INPLL(pllSCLK_CNTL); |
335 | 335 | ||
336 | if ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) | 336 | if ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) > CFG_ATI_REV_A13) |
337 | tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB); | 337 | tmp &= ~(SCLK_CNTL__FORCE_CP | SCLK_CNTL__FORCE_RB); |
338 | tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | | 338 | tmp &= ~(SCLK_CNTL__FORCE_HDP | SCLK_CNTL__FORCE_DISP1 | |
339 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE | | 339 | SCLK_CNTL__FORCE_TOP | SCLK_CNTL__FORCE_SE | |
@@ -468,9 +468,9 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) | |||
468 | 468 | ||
469 | /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ | 469 | /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300*/ |
470 | if ((rinfo->family == CHIP_FAMILY_RV250 && | 470 | if ((rinfo->family == CHIP_FAMILY_RV250 && |
471 | ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || | 471 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) || |
472 | ((rinfo->family == CHIP_FAMILY_RV100) && | 472 | ((rinfo->family == CHIP_FAMILY_RV100) && |
473 | ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { | 473 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) <= CFG_ATI_REV_A13))) { |
474 | tmp |= SCLK_CNTL__FORCE_CP; | 474 | tmp |= SCLK_CNTL__FORCE_CP; |
475 | tmp |= SCLK_CNTL__FORCE_VIP; | 475 | tmp |= SCLK_CNTL__FORCE_VIP; |
476 | } | 476 | } |
@@ -486,7 +486,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) | |||
486 | /* RV200::A11 A12 RV250::A11 A12 */ | 486 | /* RV200::A11 A12 RV250::A11 A12 */ |
487 | if (((rinfo->family == CHIP_FAMILY_RV200) || | 487 | if (((rinfo->family == CHIP_FAMILY_RV200) || |
488 | (rinfo->family == CHIP_FAMILY_RV250)) && | 488 | (rinfo->family == CHIP_FAMILY_RV250)) && |
489 | ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) | 489 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) |
490 | tmp |= SCLK_MORE_CNTL__FORCEON; | 490 | tmp |= SCLK_MORE_CNTL__FORCEON; |
491 | 491 | ||
492 | OUTPLL(pllSCLK_MORE_CNTL, tmp); | 492 | OUTPLL(pllSCLK_MORE_CNTL, tmp); |
@@ -497,7 +497,7 @@ static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo) | |||
497 | /* RV200::A11 A12, RV250::A11 A12 */ | 497 | /* RV200::A11 A12, RV250::A11 A12 */ |
498 | if (((rinfo->family == CHIP_FAMILY_RV200) || | 498 | if (((rinfo->family == CHIP_FAMILY_RV200) || |
499 | (rinfo->family == CHIP_FAMILY_RV250)) && | 499 | (rinfo->family == CHIP_FAMILY_RV250)) && |
500 | ((INREG(CONFIG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { | 500 | ((INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) < CFG_ATI_REV_A13)) { |
501 | tmp = INPLL(pllPLL_PWRMGT_CNTL); | 501 | tmp = INPLL(pllPLL_PWRMGT_CNTL); |
502 | tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE; | 502 | tmp |= PLL_PWRMGT_CNTL__TCL_BYPASS_DISABLE; |
503 | OUTPLL(pllPLL_PWRMGT_CNTL, tmp); | 503 | OUTPLL(pllPLL_PWRMGT_CNTL, tmp); |
@@ -702,7 +702,7 @@ static void radeon_pm_restore_regs(struct radeonfb_info *rinfo) | |||
702 | OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); | 702 | OUTREG(DISPLAY_BASE_ADDR, rinfo->save_regs[31]); |
703 | OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); | 703 | OUTREG(MC_AGP_LOCATION, rinfo->save_regs[32]); |
704 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); | 704 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); |
705 | OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); | 705 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
706 | 706 | ||
707 | OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); | 707 | OUTREG(DISP_MISC_CNTL, rinfo->save_regs[9]); |
708 | OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]); | 708 | OUTREG(DISP_PWR_MAN, rinfo->save_regs[10]); |
@@ -1723,7 +1723,7 @@ static void radeon_reinitialize_M10(struct radeonfb_info *rinfo) | |||
1723 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); | 1723 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, rinfo->save_regs[33]); |
1724 | OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); | 1724 | OUTREG(MC_FB_LOCATION, rinfo->save_regs[30]); |
1725 | OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]); | 1725 | OUTREG(OV0_BASE_ADDR, rinfo->save_regs[80]); |
1726 | OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); | 1726 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
1727 | OUTREG(BUS_CNTL, rinfo->save_regs[36]); | 1727 | OUTREG(BUS_CNTL, rinfo->save_regs[36]); |
1728 | OUTREG(BUS_CNTL1, rinfo->save_regs[14]); | 1728 | OUTREG(BUS_CNTL1, rinfo->save_regs[14]); |
1729 | OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]); | 1729 | OUTREG(MPP_TB_CONFIG, rinfo->save_regs[37]); |
@@ -1961,7 +1961,7 @@ static void radeon_pm_m9p_reconfigure_mc(struct radeonfb_info *rinfo) | |||
1961 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/); | 1961 | OUTMC(rinfo, ixMC_CHP_IO_CNTL_B1, rinfo->save_regs[68] /*0x141555ff*/); |
1962 | OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/); | 1962 | OUTMC(rinfo, ixMC_IMP_CNTL_0, rinfo->save_regs[71] /*0x00009249*/); |
1963 | OUTREG(MC_IND_INDEX, 0); | 1963 | OUTREG(MC_IND_INDEX, 0); |
1964 | OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); | 1964 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
1965 | 1965 | ||
1966 | mdelay(20); | 1966 | mdelay(20); |
1967 | } | 1967 | } |
@@ -2361,7 +2361,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) | |||
2361 | OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249); | 2361 | OUTMC(rinfo, ixMC_IMP_CNTL_0, 0x00009249); |
2362 | OUTREG(MC_IND_INDEX, 0); | 2362 | OUTREG(MC_IND_INDEX, 0); |
2363 | 2363 | ||
2364 | OUTREG(CONFIG_MEMSIZE, rinfo->video_ram); | 2364 | OUTREG(CNFG_MEMSIZE, rinfo->video_ram); |
2365 | 2365 | ||
2366 | radeon_pm_full_reset_sdram(rinfo); | 2366 | radeon_pm_full_reset_sdram(rinfo); |
2367 | 2367 | ||
@@ -2509,9 +2509,7 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) | |||
2509 | 2509 | ||
2510 | static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) | 2510 | static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) |
2511 | { | 2511 | { |
2512 | u16 pwr_cmd; | ||
2513 | u32 tmp; | 2512 | u32 tmp; |
2514 | int i; | ||
2515 | 2513 | ||
2516 | if (!rinfo->pm_reg) | 2514 | if (!rinfo->pm_reg) |
2517 | return; | 2515 | return; |
@@ -2557,32 +2555,14 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) | |||
2557 | } | 2555 | } |
2558 | } | 2556 | } |
2559 | 2557 | ||
2560 | for (i = 0; i < 64; ++i) | ||
2561 | pci_read_config_dword(rinfo->pdev, i * 4, | ||
2562 | &rinfo->cfg_save[i]); | ||
2563 | |||
2564 | /* Switch PCI power management to D2. */ | 2558 | /* Switch PCI power management to D2. */ |
2565 | pci_disable_device(rinfo->pdev); | 2559 | pci_disable_device(rinfo->pdev); |
2566 | for (;;) { | 2560 | pci_save_state(rinfo->pdev); |
2567 | pci_read_config_word( | 2561 | pci_set_power_state(rinfo->pdev, PCI_D2); |
2568 | rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, | ||
2569 | &pwr_cmd); | ||
2570 | if (pwr_cmd & 2) | ||
2571 | break; | ||
2572 | pci_write_config_word( | ||
2573 | rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, | ||
2574 | (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2); | ||
2575 | mdelay(500); | ||
2576 | } | ||
2577 | } else { | 2562 | } else { |
2578 | printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", | 2563 | printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", |
2579 | pci_name(rinfo->pdev)); | 2564 | pci_name(rinfo->pdev)); |
2580 | 2565 | ||
2581 | /* Switch back PCI powermanagment to D0 */ | ||
2582 | mdelay(200); | ||
2583 | pci_write_config_word(rinfo->pdev, rinfo->pm_reg+PCI_PM_CTRL, 0); | ||
2584 | mdelay(500); | ||
2585 | |||
2586 | if (rinfo->family <= CHIP_FAMILY_RV250) { | 2566 | if (rinfo->family <= CHIP_FAMILY_RV250) { |
2587 | /* Reset the SDRAM controller */ | 2567 | /* Reset the SDRAM controller */ |
2588 | radeon_pm_full_reset_sdram(rinfo); | 2568 | radeon_pm_full_reset_sdram(rinfo); |
@@ -2598,37 +2578,10 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) | |||
2598 | } | 2578 | } |
2599 | } | 2579 | } |
2600 | 2580 | ||
2601 | static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo) | ||
2602 | { | ||
2603 | int i; | ||
2604 | static u32 radeon_cfg_after_resume[64]; | ||
2605 | |||
2606 | for (i = 0; i < 64; ++i) | ||
2607 | pci_read_config_dword(rinfo->pdev, i * 4, | ||
2608 | &radeon_cfg_after_resume[i]); | ||
2609 | |||
2610 | if (radeon_cfg_after_resume[PCI_BASE_ADDRESS_0/4] | ||
2611 | == rinfo->cfg_save[PCI_BASE_ADDRESS_0/4]) | ||
2612 | return 0; /* assume everything is ok */ | ||
2613 | |||
2614 | for (i = PCI_BASE_ADDRESS_0/4; i < 64; ++i) { | ||
2615 | if (radeon_cfg_after_resume[i] != rinfo->cfg_save[i]) | ||
2616 | pci_write_config_dword(rinfo->pdev, i * 4, | ||
2617 | rinfo->cfg_save[i]); | ||
2618 | } | ||
2619 | pci_write_config_word(rinfo->pdev, PCI_CACHE_LINE_SIZE, | ||
2620 | rinfo->cfg_save[PCI_CACHE_LINE_SIZE/4]); | ||
2621 | pci_write_config_word(rinfo->pdev, PCI_COMMAND, | ||
2622 | rinfo->cfg_save[PCI_COMMAND/4]); | ||
2623 | return 1; | ||
2624 | } | ||
2625 | |||
2626 | |||
2627 | int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | 2581 | int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) |
2628 | { | 2582 | { |
2629 | struct fb_info *info = pci_get_drvdata(pdev); | 2583 | struct fb_info *info = pci_get_drvdata(pdev); |
2630 | struct radeonfb_info *rinfo = info->par; | 2584 | struct radeonfb_info *rinfo = info->par; |
2631 | int i; | ||
2632 | 2585 | ||
2633 | if (mesg.event == pdev->dev.power.power_state.event) | 2586 | if (mesg.event == pdev->dev.power.power_state.event) |
2634 | return 0; | 2587 | return 0; |
@@ -2674,6 +2627,11 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
2674 | pmac_suspend_agp_for_card(pdev); | 2627 | pmac_suspend_agp_for_card(pdev); |
2675 | #endif /* CONFIG_PPC_PMAC */ | 2628 | #endif /* CONFIG_PPC_PMAC */ |
2676 | 2629 | ||
2630 | /* It's unclear whether or when the generic code will do that, so let's | ||
2631 | * do it ourselves. We save state before we do any power management | ||
2632 | */ | ||
2633 | pci_save_state(pdev); | ||
2634 | |||
2677 | /* If we support wakeup from poweroff, we save all regs we can including cfg | 2635 | /* If we support wakeup from poweroff, we save all regs we can including cfg |
2678 | * space | 2636 | * space |
2679 | */ | 2637 | */ |
@@ -2698,9 +2656,6 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
2698 | mdelay(20); | 2656 | mdelay(20); |
2699 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); | 2657 | OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON)); |
2700 | } | 2658 | } |
2701 | // FIXME: Use PCI layer | ||
2702 | for (i = 0; i < 64; ++i) | ||
2703 | pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]); | ||
2704 | pci_disable_device(pdev); | 2659 | pci_disable_device(pdev); |
2705 | } | 2660 | } |
2706 | /* If we support D2, we go to it (should be fixed later with a flag forcing | 2661 | /* If we support D2, we go to it (should be fixed later with a flag forcing |
@@ -2717,6 +2672,13 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
2717 | return 0; | 2672 | return 0; |
2718 | } | 2673 | } |
2719 | 2674 | ||
2675 | static int radeon_check_power_loss(struct radeonfb_info *rinfo) | ||
2676 | { | ||
2677 | return rinfo->save_regs[4] != INPLL(CLK_PIN_CNTL) || | ||
2678 | rinfo->save_regs[2] != INPLL(MCLK_CNTL) || | ||
2679 | rinfo->save_regs[3] != INPLL(SCLK_CNTL); | ||
2680 | } | ||
2681 | |||
2720 | int radeonfb_pci_resume(struct pci_dev *pdev) | 2682 | int radeonfb_pci_resume(struct pci_dev *pdev) |
2721 | { | 2683 | { |
2722 | struct fb_info *info = pci_get_drvdata(pdev); | 2684 | struct fb_info *info = pci_get_drvdata(pdev); |
@@ -2735,20 +2697,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) | |||
2735 | printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", | 2697 | printk(KERN_DEBUG "radeonfb (%s): resuming from state: %d...\n", |
2736 | pci_name(pdev), pdev->dev.power.power_state.event); | 2698 | pci_name(pdev), pdev->dev.power.power_state.event); |
2737 | 2699 | ||
2738 | 2700 | /* PCI state will have been restored by the core, so | |
2739 | if (pci_enable_device(pdev)) { | 2701 | * we should be in D0 now with our config space fully |
2740 | rc = -ENODEV; | 2702 | * restored |
2741 | printk(KERN_ERR "radeonfb (%s): can't enable PCI device !\n", | 2703 | */ |
2742 | pci_name(pdev)); | ||
2743 | goto bail; | ||
2744 | } | ||
2745 | pci_set_master(pdev); | ||
2746 | |||
2747 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { | 2704 | if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { |
2748 | /* Wakeup chip. Check from config space if we were powered off | 2705 | /* Wakeup chip */ |
2749 | * (todo: additionally, check CLK_PIN_CNTL too) | 2706 | if ((rinfo->pm_mode & radeon_pm_off) && radeon_check_power_loss(rinfo)) { |
2750 | */ | ||
2751 | if ((rinfo->pm_mode & radeon_pm_off) && radeon_restore_pci_cfg(rinfo)) { | ||
2752 | if (rinfo->reinit_func != NULL) | 2707 | if (rinfo->reinit_func != NULL) |
2753 | rinfo->reinit_func(rinfo); | 2708 | rinfo->reinit_func(rinfo); |
2754 | else { | 2709 | else { |
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 3ea1b00fdd22..7351e66c7f54 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h | |||
@@ -361,8 +361,6 @@ struct radeonfb_info { | |||
361 | #ifdef CONFIG_FB_RADEON_I2C | 361 | #ifdef CONFIG_FB_RADEON_I2C |
362 | struct radeon_i2c_chan i2c[4]; | 362 | struct radeon_i2c_chan i2c[4]; |
363 | #endif | 363 | #endif |
364 | |||
365 | u32 cfg_save[64]; | ||
366 | }; | 364 | }; |
367 | 365 | ||
368 | 366 | ||
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 363b3cb2f01b..63d759498165 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -18,7 +18,7 @@ obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | |||
18 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | 18 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o |
19 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 19 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
20 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | 20 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o |
21 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x.o | 21 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o |
22 | obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o | 22 | obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o |
23 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o | 23 | obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o |
24 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o | 24 | obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o |
diff --git a/drivers/video/backlight/da903x.c b/drivers/video/backlight/da903x_bl.c index 93bb4340cc64..93bb4340cc64 100644 --- a/drivers/video/backlight/da903x.c +++ b/drivers/video/backlight/da903x_bl.c | |||
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index 91b78e691505..f53b9f1d6aba 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c | |||
@@ -250,10 +250,6 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) | |||
250 | int rc, size = cmap->len * sizeof(u16); | 250 | int rc, size = cmap->len * sizeof(u16); |
251 | struct fb_cmap umap; | 251 | struct fb_cmap umap; |
252 | 252 | ||
253 | if (cmap->start < 0 || (!info->fbops->fb_setcolreg && | ||
254 | !info->fbops->fb_setcmap)) | ||
255 | return -EINVAL; | ||
256 | |||
257 | memset(&umap, 0, sizeof(struct fb_cmap)); | 253 | memset(&umap, 0, sizeof(struct fb_cmap)); |
258 | rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL); | 254 | rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL); |
259 | if (rc) | 255 | if (rc) |
@@ -262,11 +258,23 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) | |||
262 | copy_from_user(umap.green, cmap->green, size) || | 258 | copy_from_user(umap.green, cmap->green, size) || |
263 | copy_from_user(umap.blue, cmap->blue, size) || | 259 | copy_from_user(umap.blue, cmap->blue, size) || |
264 | (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) { | 260 | (cmap->transp && copy_from_user(umap.transp, cmap->transp, size))) { |
265 | fb_dealloc_cmap(&umap); | 261 | rc = -EFAULT; |
266 | return -EFAULT; | 262 | goto out; |
267 | } | 263 | } |
268 | umap.start = cmap->start; | 264 | umap.start = cmap->start; |
265 | if (!lock_fb_info(info)) { | ||
266 | rc = -ENODEV; | ||
267 | goto out; | ||
268 | } | ||
269 | if (cmap->start < 0 || (!info->fbops->fb_setcolreg && | ||
270 | !info->fbops->fb_setcmap)) { | ||
271 | rc = -EINVAL; | ||
272 | goto out1; | ||
273 | } | ||
269 | rc = fb_set_cmap(&umap, info); | 274 | rc = fb_set_cmap(&umap, info); |
275 | out1: | ||
276 | unlock_fb_info(info); | ||
277 | out: | ||
270 | fb_dealloc_cmap(&umap); | 278 | fb_dealloc_cmap(&umap); |
271 | return rc; | 279 | return rc; |
272 | } | 280 | } |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 756efeb91abc..cfd9dce1ce0b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1013,132 +1013,139 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1013 | struct fb_var_screeninfo var; | 1013 | struct fb_var_screeninfo var; |
1014 | struct fb_fix_screeninfo fix; | 1014 | struct fb_fix_screeninfo fix; |
1015 | struct fb_con2fbmap con2fb; | 1015 | struct fb_con2fbmap con2fb; |
1016 | struct fb_cmap cmap_from; | ||
1016 | struct fb_cmap_user cmap; | 1017 | struct fb_cmap_user cmap; |
1017 | struct fb_event event; | 1018 | struct fb_event event; |
1018 | void __user *argp = (void __user *)arg; | 1019 | void __user *argp = (void __user *)arg; |
1019 | long ret = 0; | 1020 | long ret = 0; |
1020 | 1021 | ||
1021 | fb = info->fbops; | ||
1022 | if (!fb) | ||
1023 | return -ENODEV; | ||
1024 | |||
1025 | switch (cmd) { | 1022 | switch (cmd) { |
1026 | case FBIOGET_VSCREENINFO: | 1023 | case FBIOGET_VSCREENINFO: |
1027 | ret = copy_to_user(argp, &info->var, | 1024 | if (!lock_fb_info(info)) |
1028 | sizeof(var)) ? -EFAULT : 0; | 1025 | return -ENODEV; |
1026 | var = info->var; | ||
1027 | unlock_fb_info(info); | ||
1028 | |||
1029 | ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0; | ||
1029 | break; | 1030 | break; |
1030 | case FBIOPUT_VSCREENINFO: | 1031 | case FBIOPUT_VSCREENINFO: |
1031 | if (copy_from_user(&var, argp, sizeof(var))) { | 1032 | if (copy_from_user(&var, argp, sizeof(var))) |
1032 | ret = -EFAULT; | 1033 | return -EFAULT; |
1033 | break; | 1034 | if (!lock_fb_info(info)) |
1034 | } | 1035 | return -ENODEV; |
1035 | acquire_console_sem(); | 1036 | acquire_console_sem(); |
1036 | info->flags |= FBINFO_MISC_USEREVENT; | 1037 | info->flags |= FBINFO_MISC_USEREVENT; |
1037 | ret = fb_set_var(info, &var); | 1038 | ret = fb_set_var(info, &var); |
1038 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1039 | info->flags &= ~FBINFO_MISC_USEREVENT; |
1039 | release_console_sem(); | 1040 | release_console_sem(); |
1040 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | 1041 | unlock_fb_info(info); |
1042 | if (!ret && copy_to_user(argp, &var, sizeof(var))) | ||
1041 | ret = -EFAULT; | 1043 | ret = -EFAULT; |
1042 | break; | 1044 | break; |
1043 | case FBIOGET_FSCREENINFO: | 1045 | case FBIOGET_FSCREENINFO: |
1044 | ret = copy_to_user(argp, &info->fix, | 1046 | if (!lock_fb_info(info)) |
1045 | sizeof(fix)) ? -EFAULT : 0; | 1047 | return -ENODEV; |
1048 | fix = info->fix; | ||
1049 | unlock_fb_info(info); | ||
1050 | |||
1051 | ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0; | ||
1046 | break; | 1052 | break; |
1047 | case FBIOPUTCMAP: | 1053 | case FBIOPUTCMAP: |
1048 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1054 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
1049 | ret = -EFAULT; | 1055 | return -EFAULT; |
1050 | else | 1056 | ret = fb_set_user_cmap(&cmap, info); |
1051 | ret = fb_set_user_cmap(&cmap, info); | ||
1052 | break; | 1057 | break; |
1053 | case FBIOGETCMAP: | 1058 | case FBIOGETCMAP: |
1054 | if (copy_from_user(&cmap, argp, sizeof(cmap))) | 1059 | if (copy_from_user(&cmap, argp, sizeof(cmap))) |
1055 | ret = -EFAULT; | 1060 | return -EFAULT; |
1056 | else | 1061 | if (!lock_fb_info(info)) |
1057 | ret = fb_cmap_to_user(&info->cmap, &cmap); | 1062 | return -ENODEV; |
1063 | cmap_from = info->cmap; | ||
1064 | unlock_fb_info(info); | ||
1065 | ret = fb_cmap_to_user(&cmap_from, &cmap); | ||
1058 | break; | 1066 | break; |
1059 | case FBIOPAN_DISPLAY: | 1067 | case FBIOPAN_DISPLAY: |
1060 | if (copy_from_user(&var, argp, sizeof(var))) { | 1068 | if (copy_from_user(&var, argp, sizeof(var))) |
1061 | ret = -EFAULT; | 1069 | return -EFAULT; |
1062 | break; | 1070 | if (!lock_fb_info(info)) |
1063 | } | 1071 | return -ENODEV; |
1064 | acquire_console_sem(); | 1072 | acquire_console_sem(); |
1065 | ret = fb_pan_display(info, &var); | 1073 | ret = fb_pan_display(info, &var); |
1066 | release_console_sem(); | 1074 | release_console_sem(); |
1075 | unlock_fb_info(info); | ||
1067 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) | 1076 | if (ret == 0 && copy_to_user(argp, &var, sizeof(var))) |
1068 | ret = -EFAULT; | 1077 | return -EFAULT; |
1069 | break; | 1078 | break; |
1070 | case FBIO_CURSOR: | 1079 | case FBIO_CURSOR: |
1071 | ret = -EINVAL; | 1080 | ret = -EINVAL; |
1072 | break; | 1081 | break; |
1073 | case FBIOGET_CON2FBMAP: | 1082 | case FBIOGET_CON2FBMAP: |
1074 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) | 1083 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
1075 | ret = -EFAULT; | 1084 | return -EFAULT; |
1076 | else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) | 1085 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
1077 | ret = -EINVAL; | 1086 | return -EINVAL; |
1078 | else { | 1087 | con2fb.framebuffer = -1; |
1079 | con2fb.framebuffer = -1; | 1088 | event.data = &con2fb; |
1080 | event.info = info; | 1089 | |
1081 | event.data = &con2fb; | 1090 | if (!lock_fb_info(info)) |
1082 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, | 1091 | return -ENODEV; |
1083 | &event); | 1092 | event.info = info; |
1084 | ret = copy_to_user(argp, &con2fb, | 1093 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); |
1085 | sizeof(con2fb)) ? -EFAULT : 0; | 1094 | unlock_fb_info(info); |
1086 | } | 1095 | |
1096 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; | ||
1087 | break; | 1097 | break; |
1088 | case FBIOPUT_CON2FBMAP: | 1098 | case FBIOPUT_CON2FBMAP: |
1089 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) { | 1099 | if (copy_from_user(&con2fb, argp, sizeof(con2fb))) |
1090 | ret = -EFAULT; | 1100 | return -EFAULT; |
1091 | break; | 1101 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) |
1092 | } | 1102 | return -EINVAL; |
1093 | if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) { | 1103 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) |
1094 | ret = -EINVAL; | 1104 | return -EINVAL; |
1095 | break; | ||
1096 | } | ||
1097 | if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) { | ||
1098 | ret = -EINVAL; | ||
1099 | break; | ||
1100 | } | ||
1101 | if (!registered_fb[con2fb.framebuffer]) | 1105 | if (!registered_fb[con2fb.framebuffer]) |
1102 | request_module("fb%d", con2fb.framebuffer); | 1106 | request_module("fb%d", con2fb.framebuffer); |
1103 | if (!registered_fb[con2fb.framebuffer]) { | 1107 | if (!registered_fb[con2fb.framebuffer]) { |
1104 | ret = -EINVAL; | 1108 | ret = -EINVAL; |
1105 | break; | 1109 | break; |
1106 | } | 1110 | } |
1107 | event.info = info; | ||
1108 | event.data = &con2fb; | 1111 | event.data = &con2fb; |
1112 | if (!lock_fb_info(info)) | ||
1113 | return -ENODEV; | ||
1114 | event.info = info; | ||
1109 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | 1115 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, |
1110 | &event); | 1116 | &event); |
1117 | unlock_fb_info(info); | ||
1111 | break; | 1118 | break; |
1112 | case FBIOBLANK: | 1119 | case FBIOBLANK: |
1120 | if (!lock_fb_info(info)) | ||
1121 | return -ENODEV; | ||
1113 | acquire_console_sem(); | 1122 | acquire_console_sem(); |
1114 | info->flags |= FBINFO_MISC_USEREVENT; | 1123 | info->flags |= FBINFO_MISC_USEREVENT; |
1115 | ret = fb_blank(info, arg); | 1124 | ret = fb_blank(info, arg); |
1116 | info->flags &= ~FBINFO_MISC_USEREVENT; | 1125 | info->flags &= ~FBINFO_MISC_USEREVENT; |
1117 | release_console_sem(); | 1126 | release_console_sem(); |
1118 | break;; | 1127 | unlock_fb_info(info); |
1128 | break; | ||
1119 | default: | 1129 | default: |
1120 | if (fb->fb_ioctl == NULL) | 1130 | if (!lock_fb_info(info)) |
1121 | ret = -ENOTTY; | 1131 | return -ENODEV; |
1122 | else | 1132 | fb = info->fbops; |
1133 | if (fb->fb_ioctl) | ||
1123 | ret = fb->fb_ioctl(info, cmd, arg); | 1134 | ret = fb->fb_ioctl(info, cmd, arg); |
1135 | else | ||
1136 | ret = -ENOTTY; | ||
1137 | unlock_fb_info(info); | ||
1124 | } | 1138 | } |
1125 | return ret; | 1139 | return ret; |
1126 | } | 1140 | } |
1127 | 1141 | ||
1128 | static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1142 | static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1129 | __acquires(&info->lock) | ||
1130 | __releases(&info->lock) | ||
1131 | { | 1143 | { |
1132 | struct inode *inode = file->f_path.dentry->d_inode; | 1144 | struct inode *inode = file->f_path.dentry->d_inode; |
1133 | int fbidx = iminor(inode); | 1145 | int fbidx = iminor(inode); |
1134 | struct fb_info *info; | 1146 | struct fb_info *info = registered_fb[fbidx]; |
1135 | long ret; | ||
1136 | 1147 | ||
1137 | info = registered_fb[fbidx]; | 1148 | return do_fb_ioctl(info, cmd, arg); |
1138 | mutex_lock(&info->lock); | ||
1139 | ret = do_fb_ioctl(info, cmd, arg); | ||
1140 | mutex_unlock(&info->lock); | ||
1141 | return ret; | ||
1142 | } | 1149 | } |
1143 | 1150 | ||
1144 | #ifdef CONFIG_COMPAT | 1151 | #ifdef CONFIG_COMPAT |
@@ -1257,8 +1264,6 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, | |||
1257 | 1264 | ||
1258 | static long fb_compat_ioctl(struct file *file, unsigned int cmd, | 1265 | static long fb_compat_ioctl(struct file *file, unsigned int cmd, |
1259 | unsigned long arg) | 1266 | unsigned long arg) |
1260 | __acquires(&info->lock) | ||
1261 | __releases(&info->lock) | ||
1262 | { | 1267 | { |
1263 | struct inode *inode = file->f_path.dentry->d_inode; | 1268 | struct inode *inode = file->f_path.dentry->d_inode; |
1264 | int fbidx = iminor(inode); | 1269 | int fbidx = iminor(inode); |
@@ -1266,7 +1271,6 @@ __releases(&info->lock) | |||
1266 | struct fb_ops *fb = info->fbops; | 1271 | struct fb_ops *fb = info->fbops; |
1267 | long ret = -ENOIOCTLCMD; | 1272 | long ret = -ENOIOCTLCMD; |
1268 | 1273 | ||
1269 | mutex_lock(&info->lock); | ||
1270 | switch(cmd) { | 1274 | switch(cmd) { |
1271 | case FBIOGET_VSCREENINFO: | 1275 | case FBIOGET_VSCREENINFO: |
1272 | case FBIOPUT_VSCREENINFO: | 1276 | case FBIOPUT_VSCREENINFO: |
@@ -1292,7 +1296,6 @@ __releases(&info->lock) | |||
1292 | ret = fb->fb_compat_ioctl(info, cmd, arg); | 1296 | ret = fb->fb_compat_ioctl(info, cmd, arg); |
1293 | break; | 1297 | break; |
1294 | } | 1298 | } |
1295 | mutex_unlock(&info->lock); | ||
1296 | return ret; | 1299 | return ret; |
1297 | } | 1300 | } |
1298 | #endif | 1301 | #endif |
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index 7787c3322ffb..9dd55e5324a1 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c | |||
@@ -90,7 +90,6 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) | |||
90 | chan->adapter.owner = THIS_MODULE; | 90 | chan->adapter.owner = THIS_MODULE; |
91 | chan->adapter.algo_data = &chan->algo; | 91 | chan->adapter.algo_data = &chan->algo; |
92 | chan->adapter.dev.parent = &chan->par->dev->dev; | 92 | chan->adapter.dev.parent = &chan->par->dev->dev; |
93 | chan->adapter.id = I2C_HW_B_I810; | ||
94 | chan->algo.setsda = i810i2c_setsda; | 93 | chan->algo.setsda = i810i2c_setsda; |
95 | chan->algo.setscl = i810i2c_setscl; | 94 | chan->algo.setscl = i810i2c_setscl; |
96 | chan->algo.getsda = i810i2c_getsda; | 95 | chan->algo.getsda = i810i2c_getsda; |
diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c index 5d896b81f4e0..b3065492bb20 100644 --- a/drivers/video/intelfb/intelfb_i2c.c +++ b/drivers/video/intelfb/intelfb_i2c.c | |||
@@ -111,7 +111,6 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo, | |||
111 | "intelfb %s", name); | 111 | "intelfb %s", name); |
112 | chan->adapter.class = class; | 112 | chan->adapter.class = class; |
113 | chan->adapter.owner = THIS_MODULE; | 113 | chan->adapter.owner = THIS_MODULE; |
114 | chan->adapter.id = I2C_HW_B_INTELFB; | ||
115 | chan->adapter.algo_data = &chan->algo; | 114 | chan->adapter.algo_data = &chan->algo; |
116 | chan->adapter.dev.parent = &chan->dinfo->pdev->dev; | 115 | chan->adapter.dev.parent = &chan->dinfo->pdev->dev; |
117 | chan->algo.setsda = intelfb_gpio_setsda; | 116 | chan->algo.setsda = intelfb_gpio_setsda; |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c new file mode 100644 index 000000000000..8a75d05f4334 --- /dev/null +++ b/drivers/video/mx3fb.c | |||
@@ -0,0 +1,1555 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 | ||
3 | * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> | ||
4 | * | ||
5 | * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/fb.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/ioport.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/dmaengine.h> | ||
26 | #include <linux/console.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/mutex.h> | ||
29 | |||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/ipu.h> | ||
32 | #include <mach/mx3fb.h> | ||
33 | |||
34 | #include <asm/io.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | #define MX3FB_NAME "mx3_sdc_fb" | ||
38 | |||
39 | #define MX3FB_REG_OFFSET 0xB4 | ||
40 | |||
41 | /* SDC Registers */ | ||
42 | #define SDC_COM_CONF (0xB4 - MX3FB_REG_OFFSET) | ||
43 | #define SDC_GW_CTRL (0xB8 - MX3FB_REG_OFFSET) | ||
44 | #define SDC_FG_POS (0xBC - MX3FB_REG_OFFSET) | ||
45 | #define SDC_BG_POS (0xC0 - MX3FB_REG_OFFSET) | ||
46 | #define SDC_CUR_POS (0xC4 - MX3FB_REG_OFFSET) | ||
47 | #define SDC_PWM_CTRL (0xC8 - MX3FB_REG_OFFSET) | ||
48 | #define SDC_CUR_MAP (0xCC - MX3FB_REG_OFFSET) | ||
49 | #define SDC_HOR_CONF (0xD0 - MX3FB_REG_OFFSET) | ||
50 | #define SDC_VER_CONF (0xD4 - MX3FB_REG_OFFSET) | ||
51 | #define SDC_SHARP_CONF_1 (0xD8 - MX3FB_REG_OFFSET) | ||
52 | #define SDC_SHARP_CONF_2 (0xDC - MX3FB_REG_OFFSET) | ||
53 | |||
54 | /* Register bits */ | ||
55 | #define SDC_COM_TFT_COLOR 0x00000001UL | ||
56 | #define SDC_COM_FG_EN 0x00000010UL | ||
57 | #define SDC_COM_GWSEL 0x00000020UL | ||
58 | #define SDC_COM_GLB_A 0x00000040UL | ||
59 | #define SDC_COM_KEY_COLOR_G 0x00000080UL | ||
60 | #define SDC_COM_BG_EN 0x00000200UL | ||
61 | #define SDC_COM_SHARP 0x00001000UL | ||
62 | |||
63 | #define SDC_V_SYNC_WIDTH_L 0x00000001UL | ||
64 | |||
65 | /* Display Interface registers */ | ||
66 | #define DI_DISP_IF_CONF (0x0124 - MX3FB_REG_OFFSET) | ||
67 | #define DI_DISP_SIG_POL (0x0128 - MX3FB_REG_OFFSET) | ||
68 | #define DI_SER_DISP1_CONF (0x012C - MX3FB_REG_OFFSET) | ||
69 | #define DI_SER_DISP2_CONF (0x0130 - MX3FB_REG_OFFSET) | ||
70 | #define DI_HSP_CLK_PER (0x0134 - MX3FB_REG_OFFSET) | ||
71 | #define DI_DISP0_TIME_CONF_1 (0x0138 - MX3FB_REG_OFFSET) | ||
72 | #define DI_DISP0_TIME_CONF_2 (0x013C - MX3FB_REG_OFFSET) | ||
73 | #define DI_DISP0_TIME_CONF_3 (0x0140 - MX3FB_REG_OFFSET) | ||
74 | #define DI_DISP1_TIME_CONF_1 (0x0144 - MX3FB_REG_OFFSET) | ||
75 | #define DI_DISP1_TIME_CONF_2 (0x0148 - MX3FB_REG_OFFSET) | ||
76 | #define DI_DISP1_TIME_CONF_3 (0x014C - MX3FB_REG_OFFSET) | ||
77 | #define DI_DISP2_TIME_CONF_1 (0x0150 - MX3FB_REG_OFFSET) | ||
78 | #define DI_DISP2_TIME_CONF_2 (0x0154 - MX3FB_REG_OFFSET) | ||
79 | #define DI_DISP2_TIME_CONF_3 (0x0158 - MX3FB_REG_OFFSET) | ||
80 | #define DI_DISP3_TIME_CONF (0x015C - MX3FB_REG_OFFSET) | ||
81 | #define DI_DISP0_DB0_MAP (0x0160 - MX3FB_REG_OFFSET) | ||
82 | #define DI_DISP0_DB1_MAP (0x0164 - MX3FB_REG_OFFSET) | ||
83 | #define DI_DISP0_DB2_MAP (0x0168 - MX3FB_REG_OFFSET) | ||
84 | #define DI_DISP0_CB0_MAP (0x016C - MX3FB_REG_OFFSET) | ||
85 | #define DI_DISP0_CB1_MAP (0x0170 - MX3FB_REG_OFFSET) | ||
86 | #define DI_DISP0_CB2_MAP (0x0174 - MX3FB_REG_OFFSET) | ||
87 | #define DI_DISP1_DB0_MAP (0x0178 - MX3FB_REG_OFFSET) | ||
88 | #define DI_DISP1_DB1_MAP (0x017C - MX3FB_REG_OFFSET) | ||
89 | #define DI_DISP1_DB2_MAP (0x0180 - MX3FB_REG_OFFSET) | ||
90 | #define DI_DISP1_CB0_MAP (0x0184 - MX3FB_REG_OFFSET) | ||
91 | #define DI_DISP1_CB1_MAP (0x0188 - MX3FB_REG_OFFSET) | ||
92 | #define DI_DISP1_CB2_MAP (0x018C - MX3FB_REG_OFFSET) | ||
93 | #define DI_DISP2_DB0_MAP (0x0190 - MX3FB_REG_OFFSET) | ||
94 | #define DI_DISP2_DB1_MAP (0x0194 - MX3FB_REG_OFFSET) | ||
95 | #define DI_DISP2_DB2_MAP (0x0198 - MX3FB_REG_OFFSET) | ||
96 | #define DI_DISP2_CB0_MAP (0x019C - MX3FB_REG_OFFSET) | ||
97 | #define DI_DISP2_CB1_MAP (0x01A0 - MX3FB_REG_OFFSET) | ||
98 | #define DI_DISP2_CB2_MAP (0x01A4 - MX3FB_REG_OFFSET) | ||
99 | #define DI_DISP3_B0_MAP (0x01A8 - MX3FB_REG_OFFSET) | ||
100 | #define DI_DISP3_B1_MAP (0x01AC - MX3FB_REG_OFFSET) | ||
101 | #define DI_DISP3_B2_MAP (0x01B0 - MX3FB_REG_OFFSET) | ||
102 | #define DI_DISP_ACC_CC (0x01B4 - MX3FB_REG_OFFSET) | ||
103 | #define DI_DISP_LLA_CONF (0x01B8 - MX3FB_REG_OFFSET) | ||
104 | #define DI_DISP_LLA_DATA (0x01BC - MX3FB_REG_OFFSET) | ||
105 | |||
106 | /* DI_DISP_SIG_POL bits */ | ||
107 | #define DI_D3_VSYNC_POL_SHIFT 28 | ||
108 | #define DI_D3_HSYNC_POL_SHIFT 27 | ||
109 | #define DI_D3_DRDY_SHARP_POL_SHIFT 26 | ||
110 | #define DI_D3_CLK_POL_SHIFT 25 | ||
111 | #define DI_D3_DATA_POL_SHIFT 24 | ||
112 | |||
113 | /* DI_DISP_IF_CONF bits */ | ||
114 | #define DI_D3_CLK_IDLE_SHIFT 26 | ||
115 | #define DI_D3_CLK_SEL_SHIFT 25 | ||
116 | #define DI_D3_DATAMSK_SHIFT 24 | ||
117 | |||
118 | enum ipu_panel { | ||
119 | IPU_PANEL_SHARP_TFT, | ||
120 | IPU_PANEL_TFT, | ||
121 | }; | ||
122 | |||
123 | struct ipu_di_signal_cfg { | ||
124 | unsigned datamask_en:1; | ||
125 | unsigned clksel_en:1; | ||
126 | unsigned clkidle_en:1; | ||
127 | unsigned data_pol:1; /* true = inverted */ | ||
128 | unsigned clk_pol:1; /* true = rising edge */ | ||
129 | unsigned enable_pol:1; | ||
130 | unsigned Hsync_pol:1; /* true = active high */ | ||
131 | unsigned Vsync_pol:1; | ||
132 | }; | ||
133 | |||
134 | static const struct fb_videomode mx3fb_modedb[] = { | ||
135 | { | ||
136 | /* 240x320 @ 60 Hz */ | ||
137 | .name = "Sharp-QVGA", | ||
138 | .refresh = 60, | ||
139 | .xres = 240, | ||
140 | .yres = 320, | ||
141 | .pixclock = 185925, | ||
142 | .left_margin = 9, | ||
143 | .right_margin = 16, | ||
144 | .upper_margin = 7, | ||
145 | .lower_margin = 9, | ||
146 | .hsync_len = 1, | ||
147 | .vsync_len = 1, | ||
148 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | | ||
149 | FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT | | ||
150 | FB_SYNC_CLK_IDLE_EN, | ||
151 | .vmode = FB_VMODE_NONINTERLACED, | ||
152 | .flag = 0, | ||
153 | }, { | ||
154 | /* 240x33 @ 60 Hz */ | ||
155 | .name = "Sharp-CLI", | ||
156 | .refresh = 60, | ||
157 | .xres = 240, | ||
158 | .yres = 33, | ||
159 | .pixclock = 185925, | ||
160 | .left_margin = 9, | ||
161 | .right_margin = 16, | ||
162 | .upper_margin = 7, | ||
163 | .lower_margin = 9 + 287, | ||
164 | .hsync_len = 1, | ||
165 | .vsync_len = 1, | ||
166 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | | ||
167 | FB_SYNC_CLK_INVERT | FB_SYNC_DATA_INVERT | | ||
168 | FB_SYNC_CLK_IDLE_EN, | ||
169 | .vmode = FB_VMODE_NONINTERLACED, | ||
170 | .flag = 0, | ||
171 | }, { | ||
172 | /* 640x480 @ 60 Hz */ | ||
173 | .name = "NEC-VGA", | ||
174 | .refresh = 60, | ||
175 | .xres = 640, | ||
176 | .yres = 480, | ||
177 | .pixclock = 38255, | ||
178 | .left_margin = 144, | ||
179 | .right_margin = 0, | ||
180 | .upper_margin = 34, | ||
181 | .lower_margin = 40, | ||
182 | .hsync_len = 1, | ||
183 | .vsync_len = 1, | ||
184 | .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH, | ||
185 | .vmode = FB_VMODE_NONINTERLACED, | ||
186 | .flag = 0, | ||
187 | }, { | ||
188 | /* NTSC TV output */ | ||
189 | .name = "TV-NTSC", | ||
190 | .refresh = 60, | ||
191 | .xres = 640, | ||
192 | .yres = 480, | ||
193 | .pixclock = 37538, | ||
194 | .left_margin = 38, | ||
195 | .right_margin = 858 - 640 - 38 - 3, | ||
196 | .upper_margin = 36, | ||
197 | .lower_margin = 518 - 480 - 36 - 1, | ||
198 | .hsync_len = 3, | ||
199 | .vsync_len = 1, | ||
200 | .sync = 0, | ||
201 | .vmode = FB_VMODE_NONINTERLACED, | ||
202 | .flag = 0, | ||
203 | }, { | ||
204 | /* PAL TV output */ | ||
205 | .name = "TV-PAL", | ||
206 | .refresh = 50, | ||
207 | .xres = 640, | ||
208 | .yres = 480, | ||
209 | .pixclock = 37538, | ||
210 | .left_margin = 38, | ||
211 | .right_margin = 960 - 640 - 38 - 32, | ||
212 | .upper_margin = 32, | ||
213 | .lower_margin = 555 - 480 - 32 - 3, | ||
214 | .hsync_len = 32, | ||
215 | .vsync_len = 3, | ||
216 | .sync = 0, | ||
217 | .vmode = FB_VMODE_NONINTERLACED, | ||
218 | .flag = 0, | ||
219 | }, { | ||
220 | /* TV output VGA mode, 640x480 @ 65 Hz */ | ||
221 | .name = "TV-VGA", | ||
222 | .refresh = 60, | ||
223 | .xres = 640, | ||
224 | .yres = 480, | ||
225 | .pixclock = 40574, | ||
226 | .left_margin = 35, | ||
227 | .right_margin = 45, | ||
228 | .upper_margin = 9, | ||
229 | .lower_margin = 1, | ||
230 | .hsync_len = 46, | ||
231 | .vsync_len = 5, | ||
232 | .sync = 0, | ||
233 | .vmode = FB_VMODE_NONINTERLACED, | ||
234 | .flag = 0, | ||
235 | }, | ||
236 | }; | ||
237 | |||
238 | struct mx3fb_data { | ||
239 | struct fb_info *fbi; | ||
240 | int backlight_level; | ||
241 | void __iomem *reg_base; | ||
242 | spinlock_t lock; | ||
243 | struct device *dev; | ||
244 | |||
245 | uint32_t h_start_width; | ||
246 | uint32_t v_start_width; | ||
247 | }; | ||
248 | |||
249 | struct dma_chan_request { | ||
250 | struct mx3fb_data *mx3fb; | ||
251 | enum ipu_channel id; | ||
252 | }; | ||
253 | |||
254 | /* MX3 specific framebuffer information. */ | ||
255 | struct mx3fb_info { | ||
256 | int blank; | ||
257 | enum ipu_channel ipu_ch; | ||
258 | uint32_t cur_ipu_buf; | ||
259 | |||
260 | u32 pseudo_palette[16]; | ||
261 | |||
262 | struct completion flip_cmpl; | ||
263 | struct mutex mutex; /* Protects fb-ops */ | ||
264 | struct mx3fb_data *mx3fb; | ||
265 | struct idmac_channel *idmac_channel; | ||
266 | struct dma_async_tx_descriptor *txd; | ||
267 | dma_cookie_t cookie; | ||
268 | struct scatterlist sg[2]; | ||
269 | |||
270 | u32 sync; /* preserve var->sync flags */ | ||
271 | }; | ||
272 | |||
273 | static void mx3fb_dma_done(void *); | ||
274 | |||
275 | /* Used fb-mode and bpp. Can be set on kernel command line, therefore file-static. */ | ||
276 | static const char *fb_mode; | ||
277 | static unsigned long default_bpp = 16; | ||
278 | |||
279 | static u32 mx3fb_read_reg(struct mx3fb_data *mx3fb, unsigned long reg) | ||
280 | { | ||
281 | return __raw_readl(mx3fb->reg_base + reg); | ||
282 | } | ||
283 | |||
284 | static void mx3fb_write_reg(struct mx3fb_data *mx3fb, u32 value, unsigned long reg) | ||
285 | { | ||
286 | __raw_writel(value, mx3fb->reg_base + reg); | ||
287 | } | ||
288 | |||
289 | static const uint32_t di_mappings[] = { | ||
290 | 0x1600AAAA, 0x00E05555, 0x00070000, 3, /* RGB888 */ | ||
291 | 0x0005000F, 0x000B000F, 0x0011000F, 1, /* RGB666 */ | ||
292 | 0x0011000F, 0x000B000F, 0x0005000F, 1, /* BGR666 */ | ||
293 | 0x0004003F, 0x000A000F, 0x000F003F, 1 /* RGB565 */ | ||
294 | }; | ||
295 | |||
296 | static void sdc_fb_init(struct mx3fb_info *fbi) | ||
297 | { | ||
298 | struct mx3fb_data *mx3fb = fbi->mx3fb; | ||
299 | uint32_t reg; | ||
300 | |||
301 | reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); | ||
302 | |||
303 | mx3fb_write_reg(mx3fb, reg | SDC_COM_BG_EN, SDC_COM_CONF); | ||
304 | } | ||
305 | |||
306 | /* Returns enabled flag before uninit */ | ||
307 | static uint32_t sdc_fb_uninit(struct mx3fb_info *fbi) | ||
308 | { | ||
309 | struct mx3fb_data *mx3fb = fbi->mx3fb; | ||
310 | uint32_t reg; | ||
311 | |||
312 | reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); | ||
313 | |||
314 | mx3fb_write_reg(mx3fb, reg & ~SDC_COM_BG_EN, SDC_COM_CONF); | ||
315 | |||
316 | return reg & SDC_COM_BG_EN; | ||
317 | } | ||
318 | |||
319 | static void sdc_enable_channel(struct mx3fb_info *mx3_fbi) | ||
320 | { | ||
321 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; | ||
322 | struct idmac_channel *ichan = mx3_fbi->idmac_channel; | ||
323 | struct dma_chan *dma_chan = &ichan->dma_chan; | ||
324 | unsigned long flags; | ||
325 | dma_cookie_t cookie; | ||
326 | |||
327 | dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi, | ||
328 | to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg); | ||
329 | |||
330 | /* This enables the channel */ | ||
331 | if (mx3_fbi->cookie < 0) { | ||
332 | mx3_fbi->txd = dma_chan->device->device_prep_slave_sg(dma_chan, | ||
333 | &mx3_fbi->sg[0], 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); | ||
334 | if (!mx3_fbi->txd) { | ||
335 | dev_err(mx3fb->dev, "Cannot allocate descriptor on %d\n", | ||
336 | dma_chan->chan_id); | ||
337 | return; | ||
338 | } | ||
339 | |||
340 | mx3_fbi->txd->callback_param = mx3_fbi->txd; | ||
341 | mx3_fbi->txd->callback = mx3fb_dma_done; | ||
342 | |||
343 | cookie = mx3_fbi->txd->tx_submit(mx3_fbi->txd); | ||
344 | dev_dbg(mx3fb->dev, "%d: Submit %p #%d [%c]\n", __LINE__, | ||
345 | mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+'); | ||
346 | } else { | ||
347 | if (!mx3_fbi->txd || !mx3_fbi->txd->tx_submit) { | ||
348 | dev_err(mx3fb->dev, "Cannot enable channel %d\n", | ||
349 | dma_chan->chan_id); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | /* Just re-activate the same buffer */ | ||
354 | dma_async_issue_pending(dma_chan); | ||
355 | cookie = mx3_fbi->cookie; | ||
356 | dev_dbg(mx3fb->dev, "%d: Re-submit %p #%d [%c]\n", __LINE__, | ||
357 | mx3_fbi->txd, cookie, list_empty(&ichan->queue) ? '-' : '+'); | ||
358 | } | ||
359 | |||
360 | if (cookie >= 0) { | ||
361 | spin_lock_irqsave(&mx3fb->lock, flags); | ||
362 | sdc_fb_init(mx3_fbi); | ||
363 | mx3_fbi->cookie = cookie; | ||
364 | spin_unlock_irqrestore(&mx3fb->lock, flags); | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Attention! Without this msleep the channel keeps generating | ||
369 | * interrupts. Next sdc_set_brightness() is going to be called | ||
370 | * from mx3fb_blank(). | ||
371 | */ | ||
372 | msleep(2); | ||
373 | } | ||
374 | |||
375 | static void sdc_disable_channel(struct mx3fb_info *mx3_fbi) | ||
376 | { | ||
377 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; | ||
378 | uint32_t enabled; | ||
379 | unsigned long flags; | ||
380 | |||
381 | spin_lock_irqsave(&mx3fb->lock, flags); | ||
382 | |||
383 | enabled = sdc_fb_uninit(mx3_fbi); | ||
384 | |||
385 | spin_unlock_irqrestore(&mx3fb->lock, flags); | ||
386 | |||
387 | mx3_fbi->txd->chan->device->device_terminate_all(mx3_fbi->txd->chan); | ||
388 | mx3_fbi->txd = NULL; | ||
389 | mx3_fbi->cookie = -EINVAL; | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * sdc_set_window_pos() - set window position of the respective plane. | ||
394 | * @mx3fb: mx3fb context. | ||
395 | * @channel: IPU DMAC channel ID. | ||
396 | * @x_pos: X coordinate relative to the top left corner to place window at. | ||
397 | * @y_pos: Y coordinate relative to the top left corner to place window at. | ||
398 | * @return: 0 on success or negative error code on failure. | ||
399 | */ | ||
400 | static int sdc_set_window_pos(struct mx3fb_data *mx3fb, enum ipu_channel channel, | ||
401 | int16_t x_pos, int16_t y_pos) | ||
402 | { | ||
403 | x_pos += mx3fb->h_start_width; | ||
404 | y_pos += mx3fb->v_start_width; | ||
405 | |||
406 | if (channel != IDMAC_SDC_0) | ||
407 | return -EINVAL; | ||
408 | |||
409 | mx3fb_write_reg(mx3fb, (x_pos << 16) | y_pos, SDC_BG_POS); | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * sdc_init_panel() - initialize a synchronous LCD panel. | ||
415 | * @mx3fb: mx3fb context. | ||
416 | * @panel: panel type. | ||
417 | * @pixel_clk: desired pixel clock frequency in Hz. | ||
418 | * @width: width of panel in pixels. | ||
419 | * @height: height of panel in pixels. | ||
420 | * @pixel_fmt: pixel format of buffer as FOURCC ASCII code. | ||
421 | * @h_start_width: number of pixel clocks between the HSYNC signal pulse | ||
422 | * and the start of valid data. | ||
423 | * @h_sync_width: width of the HSYNC signal in units of pixel clocks. | ||
424 | * @h_end_width: number of pixel clocks between the end of valid data | ||
425 | * and the HSYNC signal for next line. | ||
426 | * @v_start_width: number of lines between the VSYNC signal pulse and the | ||
427 | * start of valid data. | ||
428 | * @v_sync_width: width of the VSYNC signal in units of lines | ||
429 | * @v_end_width: number of lines between the end of valid data and the | ||
430 | * VSYNC signal for next frame. | ||
431 | * @sig: bitfield of signal polarities for LCD interface. | ||
432 | * @return: 0 on success or negative error code on failure. | ||
433 | */ | ||
434 | static int sdc_init_panel(struct mx3fb_data *mx3fb, enum ipu_panel panel, | ||
435 | uint32_t pixel_clk, | ||
436 | uint16_t width, uint16_t height, | ||
437 | enum pixel_fmt pixel_fmt, | ||
438 | uint16_t h_start_width, uint16_t h_sync_width, | ||
439 | uint16_t h_end_width, uint16_t v_start_width, | ||
440 | uint16_t v_sync_width, uint16_t v_end_width, | ||
441 | struct ipu_di_signal_cfg sig) | ||
442 | { | ||
443 | unsigned long lock_flags; | ||
444 | uint32_t reg; | ||
445 | uint32_t old_conf; | ||
446 | uint32_t div; | ||
447 | struct clk *ipu_clk; | ||
448 | |||
449 | dev_dbg(mx3fb->dev, "panel size = %d x %d", width, height); | ||
450 | |||
451 | if (v_sync_width == 0 || h_sync_width == 0) | ||
452 | return -EINVAL; | ||
453 | |||
454 | /* Init panel size and blanking periods */ | ||
455 | reg = ((uint32_t) (h_sync_width - 1) << 26) | | ||
456 | ((uint32_t) (width + h_start_width + h_end_width - 1) << 16); | ||
457 | mx3fb_write_reg(mx3fb, reg, SDC_HOR_CONF); | ||
458 | |||
459 | #ifdef DEBUG | ||
460 | printk(KERN_CONT " hor_conf %x,", reg); | ||
461 | #endif | ||
462 | |||
463 | reg = ((uint32_t) (v_sync_width - 1) << 26) | SDC_V_SYNC_WIDTH_L | | ||
464 | ((uint32_t) (height + v_start_width + v_end_width - 1) << 16); | ||
465 | mx3fb_write_reg(mx3fb, reg, SDC_VER_CONF); | ||
466 | |||
467 | #ifdef DEBUG | ||
468 | printk(KERN_CONT " ver_conf %x\n", reg); | ||
469 | #endif | ||
470 | |||
471 | mx3fb->h_start_width = h_start_width; | ||
472 | mx3fb->v_start_width = v_start_width; | ||
473 | |||
474 | switch (panel) { | ||
475 | case IPU_PANEL_SHARP_TFT: | ||
476 | mx3fb_write_reg(mx3fb, 0x00FD0102L, SDC_SHARP_CONF_1); | ||
477 | mx3fb_write_reg(mx3fb, 0x00F500F4L, SDC_SHARP_CONF_2); | ||
478 | mx3fb_write_reg(mx3fb, SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); | ||
479 | break; | ||
480 | case IPU_PANEL_TFT: | ||
481 | mx3fb_write_reg(mx3fb, SDC_COM_TFT_COLOR, SDC_COM_CONF); | ||
482 | break; | ||
483 | default: | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | /* Init clocking */ | ||
488 | |||
489 | /* | ||
490 | * Calculate divider: fractional part is 4 bits so simply multiple by | ||
491 | * 24 to get fractional part, as long as we stay under ~250MHz and on | ||
492 | * i.MX31 it (HSP_CLK) is <= 178MHz. Currently 128.267MHz | ||
493 | */ | ||
494 | dev_dbg(mx3fb->dev, "pixel clk = %d\n", pixel_clk); | ||
495 | |||
496 | ipu_clk = clk_get(mx3fb->dev, "ipu_clk"); | ||
497 | div = clk_get_rate(ipu_clk) * 16 / pixel_clk; | ||
498 | clk_put(ipu_clk); | ||
499 | |||
500 | if (div < 0x40) { /* Divider less than 4 */ | ||
501 | dev_dbg(mx3fb->dev, | ||
502 | "InitPanel() - Pixel clock divider less than 4\n"); | ||
503 | div = 0x40; | ||
504 | } | ||
505 | |||
506 | spin_lock_irqsave(&mx3fb->lock, lock_flags); | ||
507 | |||
508 | /* | ||
509 | * DISP3_IF_CLK_DOWN_WR is half the divider value and 2 fraction bits | ||
510 | * fewer. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR based on timing | ||
511 | * debug. DISP3_IF_CLK_UP_WR is 0 | ||
512 | */ | ||
513 | mx3fb_write_reg(mx3fb, (((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF); | ||
514 | |||
515 | /* DI settings */ | ||
516 | old_conf = mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF) & 0x78FFFFFF; | ||
517 | old_conf |= sig.datamask_en << DI_D3_DATAMSK_SHIFT | | ||
518 | sig.clksel_en << DI_D3_CLK_SEL_SHIFT | | ||
519 | sig.clkidle_en << DI_D3_CLK_IDLE_SHIFT; | ||
520 | mx3fb_write_reg(mx3fb, old_conf, DI_DISP_IF_CONF); | ||
521 | |||
522 | old_conf = mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL) & 0xE0FFFFFF; | ||
523 | old_conf |= sig.data_pol << DI_D3_DATA_POL_SHIFT | | ||
524 | sig.clk_pol << DI_D3_CLK_POL_SHIFT | | ||
525 | sig.enable_pol << DI_D3_DRDY_SHARP_POL_SHIFT | | ||
526 | sig.Hsync_pol << DI_D3_HSYNC_POL_SHIFT | | ||
527 | sig.Vsync_pol << DI_D3_VSYNC_POL_SHIFT; | ||
528 | mx3fb_write_reg(mx3fb, old_conf, DI_DISP_SIG_POL); | ||
529 | |||
530 | switch (pixel_fmt) { | ||
531 | case IPU_PIX_FMT_RGB24: | ||
532 | mx3fb_write_reg(mx3fb, di_mappings[0], DI_DISP3_B0_MAP); | ||
533 | mx3fb_write_reg(mx3fb, di_mappings[1], DI_DISP3_B1_MAP); | ||
534 | mx3fb_write_reg(mx3fb, di_mappings[2], DI_DISP3_B2_MAP); | ||
535 | mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | | ||
536 | ((di_mappings[3] - 1) << 12), DI_DISP_ACC_CC); | ||
537 | break; | ||
538 | case IPU_PIX_FMT_RGB666: | ||
539 | mx3fb_write_reg(mx3fb, di_mappings[4], DI_DISP3_B0_MAP); | ||
540 | mx3fb_write_reg(mx3fb, di_mappings[5], DI_DISP3_B1_MAP); | ||
541 | mx3fb_write_reg(mx3fb, di_mappings[6], DI_DISP3_B2_MAP); | ||
542 | mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | | ||
543 | ((di_mappings[7] - 1) << 12), DI_DISP_ACC_CC); | ||
544 | break; | ||
545 | case IPU_PIX_FMT_BGR666: | ||
546 | mx3fb_write_reg(mx3fb, di_mappings[8], DI_DISP3_B0_MAP); | ||
547 | mx3fb_write_reg(mx3fb, di_mappings[9], DI_DISP3_B1_MAP); | ||
548 | mx3fb_write_reg(mx3fb, di_mappings[10], DI_DISP3_B2_MAP); | ||
549 | mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | | ||
550 | ((di_mappings[11] - 1) << 12), DI_DISP_ACC_CC); | ||
551 | break; | ||
552 | default: | ||
553 | mx3fb_write_reg(mx3fb, di_mappings[12], DI_DISP3_B0_MAP); | ||
554 | mx3fb_write_reg(mx3fb, di_mappings[13], DI_DISP3_B1_MAP); | ||
555 | mx3fb_write_reg(mx3fb, di_mappings[14], DI_DISP3_B2_MAP); | ||
556 | mx3fb_write_reg(mx3fb, mx3fb_read_reg(mx3fb, DI_DISP_ACC_CC) | | ||
557 | ((di_mappings[15] - 1) << 12), DI_DISP_ACC_CC); | ||
558 | break; | ||
559 | } | ||
560 | |||
561 | spin_unlock_irqrestore(&mx3fb->lock, lock_flags); | ||
562 | |||
563 | dev_dbg(mx3fb->dev, "DI_DISP_IF_CONF = 0x%08X\n", | ||
564 | mx3fb_read_reg(mx3fb, DI_DISP_IF_CONF)); | ||
565 | dev_dbg(mx3fb->dev, "DI_DISP_SIG_POL = 0x%08X\n", | ||
566 | mx3fb_read_reg(mx3fb, DI_DISP_SIG_POL)); | ||
567 | dev_dbg(mx3fb->dev, "DI_DISP3_TIME_CONF = 0x%08X\n", | ||
568 | mx3fb_read_reg(mx3fb, DI_DISP3_TIME_CONF)); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | /** | ||
574 | * sdc_set_color_key() - set the transparent color key for SDC graphic plane. | ||
575 | * @mx3fb: mx3fb context. | ||
576 | * @channel: IPU DMAC channel ID. | ||
577 | * @enable: boolean to enable or disable color keyl. | ||
578 | * @color_key: 24-bit RGB color to use as transparent color key. | ||
579 | * @return: 0 on success or negative error code on failure. | ||
580 | */ | ||
581 | static int sdc_set_color_key(struct mx3fb_data *mx3fb, enum ipu_channel channel, | ||
582 | bool enable, uint32_t color_key) | ||
583 | { | ||
584 | uint32_t reg, sdc_conf; | ||
585 | unsigned long lock_flags; | ||
586 | |||
587 | spin_lock_irqsave(&mx3fb->lock, lock_flags); | ||
588 | |||
589 | sdc_conf = mx3fb_read_reg(mx3fb, SDC_COM_CONF); | ||
590 | if (channel == IDMAC_SDC_0) | ||
591 | sdc_conf &= ~SDC_COM_GWSEL; | ||
592 | else | ||
593 | sdc_conf |= SDC_COM_GWSEL; | ||
594 | |||
595 | if (enable) { | ||
596 | reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0xFF000000L; | ||
597 | mx3fb_write_reg(mx3fb, reg | (color_key & 0x00FFFFFFL), | ||
598 | SDC_GW_CTRL); | ||
599 | |||
600 | sdc_conf |= SDC_COM_KEY_COLOR_G; | ||
601 | } else { | ||
602 | sdc_conf &= ~SDC_COM_KEY_COLOR_G; | ||
603 | } | ||
604 | mx3fb_write_reg(mx3fb, sdc_conf, SDC_COM_CONF); | ||
605 | |||
606 | spin_unlock_irqrestore(&mx3fb->lock, lock_flags); | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | /** | ||
612 | * sdc_set_global_alpha() - set global alpha blending modes. | ||
613 | * @mx3fb: mx3fb context. | ||
614 | * @enable: boolean to enable or disable global alpha blending. If disabled, | ||
615 | * per pixel blending is used. | ||
616 | * @alpha: global alpha value. | ||
617 | * @return: 0 on success or negative error code on failure. | ||
618 | */ | ||
619 | static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t alpha) | ||
620 | { | ||
621 | uint32_t reg; | ||
622 | unsigned long lock_flags; | ||
623 | |||
624 | spin_lock_irqsave(&mx3fb->lock, lock_flags); | ||
625 | |||
626 | if (enable) { | ||
627 | reg = mx3fb_read_reg(mx3fb, SDC_GW_CTRL) & 0x00FFFFFFL; | ||
628 | mx3fb_write_reg(mx3fb, reg | ((uint32_t) alpha << 24), SDC_GW_CTRL); | ||
629 | |||
630 | reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); | ||
631 | mx3fb_write_reg(mx3fb, reg | SDC_COM_GLB_A, SDC_COM_CONF); | ||
632 | } else { | ||
633 | reg = mx3fb_read_reg(mx3fb, SDC_COM_CONF); | ||
634 | mx3fb_write_reg(mx3fb, reg & ~SDC_COM_GLB_A, SDC_COM_CONF); | ||
635 | } | ||
636 | |||
637 | spin_unlock_irqrestore(&mx3fb->lock, lock_flags); | ||
638 | |||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value) | ||
643 | { | ||
644 | /* This might be board-specific */ | ||
645 | mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL); | ||
646 | return; | ||
647 | } | ||
648 | |||
649 | static uint32_t bpp_to_pixfmt(int bpp) | ||
650 | { | ||
651 | uint32_t pixfmt = 0; | ||
652 | switch (bpp) { | ||
653 | case 24: | ||
654 | pixfmt = IPU_PIX_FMT_BGR24; | ||
655 | break; | ||
656 | case 32: | ||
657 | pixfmt = IPU_PIX_FMT_BGR32; | ||
658 | break; | ||
659 | case 16: | ||
660 | pixfmt = IPU_PIX_FMT_RGB565; | ||
661 | break; | ||
662 | } | ||
663 | return pixfmt; | ||
664 | } | ||
665 | |||
666 | static int mx3fb_blank(int blank, struct fb_info *fbi); | ||
667 | static int mx3fb_map_video_memory(struct fb_info *fbi); | ||
668 | static int mx3fb_unmap_video_memory(struct fb_info *fbi); | ||
669 | |||
670 | /** | ||
671 | * mx3fb_set_fix() - set fixed framebuffer parameters from variable settings. | ||
672 | * @info: framebuffer information pointer | ||
673 | * @return: 0 on success or negative error code on failure. | ||
674 | */ | ||
675 | static int mx3fb_set_fix(struct fb_info *fbi) | ||
676 | { | ||
677 | struct fb_fix_screeninfo *fix = &fbi->fix; | ||
678 | struct fb_var_screeninfo *var = &fbi->var; | ||
679 | |||
680 | strncpy(fix->id, "DISP3 BG", 8); | ||
681 | |||
682 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; | ||
683 | |||
684 | fix->type = FB_TYPE_PACKED_PIXELS; | ||
685 | fix->accel = FB_ACCEL_NONE; | ||
686 | fix->visual = FB_VISUAL_TRUECOLOR; | ||
687 | fix->xpanstep = 1; | ||
688 | fix->ypanstep = 1; | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static void mx3fb_dma_done(void *arg) | ||
694 | { | ||
695 | struct idmac_tx_desc *tx_desc = to_tx_desc(arg); | ||
696 | struct dma_chan *chan = tx_desc->txd.chan; | ||
697 | struct idmac_channel *ichannel = to_idmac_chan(chan); | ||
698 | struct mx3fb_data *mx3fb = ichannel->client; | ||
699 | struct mx3fb_info *mx3_fbi = mx3fb->fbi->par; | ||
700 | |||
701 | dev_dbg(mx3fb->dev, "irq %d callback\n", ichannel->eof_irq); | ||
702 | |||
703 | /* We only need one interrupt, it will be re-enabled as needed */ | ||
704 | disable_irq(ichannel->eof_irq); | ||
705 | |||
706 | complete(&mx3_fbi->flip_cmpl); | ||
707 | } | ||
708 | |||
709 | /** | ||
710 | * mx3fb_set_par() - set framebuffer parameters and change the operating mode. | ||
711 | * @fbi: framebuffer information pointer. | ||
712 | * @return: 0 on success or negative error code on failure. | ||
713 | */ | ||
714 | static int mx3fb_set_par(struct fb_info *fbi) | ||
715 | { | ||
716 | u32 mem_len; | ||
717 | struct ipu_di_signal_cfg sig_cfg; | ||
718 | enum ipu_panel mode = IPU_PANEL_TFT; | ||
719 | struct mx3fb_info *mx3_fbi = fbi->par; | ||
720 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; | ||
721 | struct idmac_channel *ichan = mx3_fbi->idmac_channel; | ||
722 | struct idmac_video_param *video = &ichan->params.video; | ||
723 | struct scatterlist *sg = mx3_fbi->sg; | ||
724 | size_t screen_size; | ||
725 | |||
726 | dev_dbg(mx3fb->dev, "%s [%c]\n", __func__, list_empty(&ichan->queue) ? '-' : '+'); | ||
727 | |||
728 | mutex_lock(&mx3_fbi->mutex); | ||
729 | |||
730 | /* Total cleanup */ | ||
731 | if (mx3_fbi->txd) | ||
732 | sdc_disable_channel(mx3_fbi); | ||
733 | |||
734 | mx3fb_set_fix(fbi); | ||
735 | |||
736 | mem_len = fbi->var.yres_virtual * fbi->fix.line_length; | ||
737 | if (mem_len > fbi->fix.smem_len) { | ||
738 | if (fbi->fix.smem_start) | ||
739 | mx3fb_unmap_video_memory(fbi); | ||
740 | |||
741 | fbi->fix.smem_len = mem_len; | ||
742 | if (mx3fb_map_video_memory(fbi) < 0) { | ||
743 | mutex_unlock(&mx3_fbi->mutex); | ||
744 | return -ENOMEM; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | screen_size = fbi->fix.line_length * fbi->var.yres; | ||
749 | |||
750 | sg_init_table(&sg[0], 1); | ||
751 | sg_init_table(&sg[1], 1); | ||
752 | |||
753 | sg_dma_address(&sg[0]) = fbi->fix.smem_start; | ||
754 | sg_set_page(&sg[0], virt_to_page(fbi->screen_base), | ||
755 | fbi->fix.smem_len, | ||
756 | offset_in_page(fbi->screen_base)); | ||
757 | |||
758 | if (mx3_fbi->ipu_ch == IDMAC_SDC_0) { | ||
759 | memset(&sig_cfg, 0, sizeof(sig_cfg)); | ||
760 | if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) | ||
761 | sig_cfg.Hsync_pol = true; | ||
762 | if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) | ||
763 | sig_cfg.Vsync_pol = true; | ||
764 | if (fbi->var.sync & FB_SYNC_CLK_INVERT) | ||
765 | sig_cfg.clk_pol = true; | ||
766 | if (fbi->var.sync & FB_SYNC_DATA_INVERT) | ||
767 | sig_cfg.data_pol = true; | ||
768 | if (fbi->var.sync & FB_SYNC_OE_ACT_HIGH) | ||
769 | sig_cfg.enable_pol = true; | ||
770 | if (fbi->var.sync & FB_SYNC_CLK_IDLE_EN) | ||
771 | sig_cfg.clkidle_en = true; | ||
772 | if (fbi->var.sync & FB_SYNC_CLK_SEL_EN) | ||
773 | sig_cfg.clksel_en = true; | ||
774 | if (fbi->var.sync & FB_SYNC_SHARP_MODE) | ||
775 | mode = IPU_PANEL_SHARP_TFT; | ||
776 | |||
777 | dev_dbg(fbi->device, "pixclock = %ul Hz\n", | ||
778 | (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL)); | ||
779 | |||
780 | if (sdc_init_panel(mx3fb, mode, | ||
781 | (PICOS2KHZ(fbi->var.pixclock)) * 1000UL, | ||
782 | fbi->var.xres, fbi->var.yres, | ||
783 | (fbi->var.sync & FB_SYNC_SWAP_RGB) ? | ||
784 | IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666, | ||
785 | fbi->var.left_margin, | ||
786 | fbi->var.hsync_len, | ||
787 | fbi->var.right_margin + | ||
788 | fbi->var.hsync_len, | ||
789 | fbi->var.upper_margin, | ||
790 | fbi->var.vsync_len, | ||
791 | fbi->var.lower_margin + | ||
792 | fbi->var.vsync_len, sig_cfg) != 0) { | ||
793 | mutex_unlock(&mx3_fbi->mutex); | ||
794 | dev_err(fbi->device, | ||
795 | "mx3fb: Error initializing panel.\n"); | ||
796 | return -EINVAL; | ||
797 | } | ||
798 | } | ||
799 | |||
800 | sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0); | ||
801 | |||
802 | mx3_fbi->cur_ipu_buf = 0; | ||
803 | |||
804 | video->out_pixel_fmt = bpp_to_pixfmt(fbi->var.bits_per_pixel); | ||
805 | video->out_width = fbi->var.xres; | ||
806 | video->out_height = fbi->var.yres; | ||
807 | video->out_stride = fbi->var.xres_virtual; | ||
808 | |||
809 | if (mx3_fbi->blank == FB_BLANK_UNBLANK) | ||
810 | sdc_enable_channel(mx3_fbi); | ||
811 | |||
812 | mutex_unlock(&mx3_fbi->mutex); | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | /** | ||
818 | * mx3fb_check_var() - check and adjust framebuffer variable parameters. | ||
819 | * @var: framebuffer variable parameters | ||
820 | * @fbi: framebuffer information pointer | ||
821 | */ | ||
822 | static int mx3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi) | ||
823 | { | ||
824 | struct mx3fb_info *mx3_fbi = fbi->par; | ||
825 | u32 vtotal; | ||
826 | u32 htotal; | ||
827 | |||
828 | dev_dbg(fbi->device, "%s\n", __func__); | ||
829 | |||
830 | if (var->xres_virtual < var->xres) | ||
831 | var->xres_virtual = var->xres; | ||
832 | if (var->yres_virtual < var->yres) | ||
833 | var->yres_virtual = var->yres; | ||
834 | |||
835 | if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) && | ||
836 | (var->bits_per_pixel != 16)) | ||
837 | var->bits_per_pixel = default_bpp; | ||
838 | |||
839 | switch (var->bits_per_pixel) { | ||
840 | case 16: | ||
841 | var->red.length = 5; | ||
842 | var->red.offset = 11; | ||
843 | var->red.msb_right = 0; | ||
844 | |||
845 | var->green.length = 6; | ||
846 | var->green.offset = 5; | ||
847 | var->green.msb_right = 0; | ||
848 | |||
849 | var->blue.length = 5; | ||
850 | var->blue.offset = 0; | ||
851 | var->blue.msb_right = 0; | ||
852 | |||
853 | var->transp.length = 0; | ||
854 | var->transp.offset = 0; | ||
855 | var->transp.msb_right = 0; | ||
856 | break; | ||
857 | case 24: | ||
858 | var->red.length = 8; | ||
859 | var->red.offset = 16; | ||
860 | var->red.msb_right = 0; | ||
861 | |||
862 | var->green.length = 8; | ||
863 | var->green.offset = 8; | ||
864 | var->green.msb_right = 0; | ||
865 | |||
866 | var->blue.length = 8; | ||
867 | var->blue.offset = 0; | ||
868 | var->blue.msb_right = 0; | ||
869 | |||
870 | var->transp.length = 0; | ||
871 | var->transp.offset = 0; | ||
872 | var->transp.msb_right = 0; | ||
873 | break; | ||
874 | case 32: | ||
875 | var->red.length = 8; | ||
876 | var->red.offset = 16; | ||
877 | var->red.msb_right = 0; | ||
878 | |||
879 | var->green.length = 8; | ||
880 | var->green.offset = 8; | ||
881 | var->green.msb_right = 0; | ||
882 | |||
883 | var->blue.length = 8; | ||
884 | var->blue.offset = 0; | ||
885 | var->blue.msb_right = 0; | ||
886 | |||
887 | var->transp.length = 8; | ||
888 | var->transp.offset = 24; | ||
889 | var->transp.msb_right = 0; | ||
890 | break; | ||
891 | } | ||
892 | |||
893 | if (var->pixclock < 1000) { | ||
894 | htotal = var->xres + var->right_margin + var->hsync_len + | ||
895 | var->left_margin; | ||
896 | vtotal = var->yres + var->lower_margin + var->vsync_len + | ||
897 | var->upper_margin; | ||
898 | var->pixclock = (vtotal * htotal * 6UL) / 100UL; | ||
899 | var->pixclock = KHZ2PICOS(var->pixclock); | ||
900 | dev_dbg(fbi->device, "pixclock set for 60Hz refresh = %u ps\n", | ||
901 | var->pixclock); | ||
902 | } | ||
903 | |||
904 | var->height = -1; | ||
905 | var->width = -1; | ||
906 | var->grayscale = 0; | ||
907 | |||
908 | /* Preserve sync flags */ | ||
909 | var->sync |= mx3_fbi->sync; | ||
910 | mx3_fbi->sync |= var->sync; | ||
911 | |||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf) | ||
916 | { | ||
917 | chan &= 0xffff; | ||
918 | chan >>= 16 - bf->length; | ||
919 | return chan << bf->offset; | ||
920 | } | ||
921 | |||
922 | static int mx3fb_setcolreg(unsigned int regno, unsigned int red, | ||
923 | unsigned int green, unsigned int blue, | ||
924 | unsigned int trans, struct fb_info *fbi) | ||
925 | { | ||
926 | struct mx3fb_info *mx3_fbi = fbi->par; | ||
927 | u32 val; | ||
928 | int ret = 1; | ||
929 | |||
930 | dev_dbg(fbi->device, "%s\n", __func__); | ||
931 | |||
932 | mutex_lock(&mx3_fbi->mutex); | ||
933 | /* | ||
934 | * If greyscale is true, then we convert the RGB value | ||
935 | * to greyscale no matter what visual we are using. | ||
936 | */ | ||
937 | if (fbi->var.grayscale) | ||
938 | red = green = blue = (19595 * red + 38470 * green + | ||
939 | 7471 * blue) >> 16; | ||
940 | switch (fbi->fix.visual) { | ||
941 | case FB_VISUAL_TRUECOLOR: | ||
942 | /* | ||
943 | * 16-bit True Colour. We encode the RGB value | ||
944 | * according to the RGB bitfield information. | ||
945 | */ | ||
946 | if (regno < 16) { | ||
947 | u32 *pal = fbi->pseudo_palette; | ||
948 | |||
949 | val = chan_to_field(red, &fbi->var.red); | ||
950 | val |= chan_to_field(green, &fbi->var.green); | ||
951 | val |= chan_to_field(blue, &fbi->var.blue); | ||
952 | |||
953 | pal[regno] = val; | ||
954 | |||
955 | ret = 0; | ||
956 | } | ||
957 | break; | ||
958 | |||
959 | case FB_VISUAL_STATIC_PSEUDOCOLOR: | ||
960 | case FB_VISUAL_PSEUDOCOLOR: | ||
961 | break; | ||
962 | } | ||
963 | mutex_unlock(&mx3_fbi->mutex); | ||
964 | |||
965 | return ret; | ||
966 | } | ||
967 | |||
968 | /** | ||
969 | * mx3fb_blank() - blank the display. | ||
970 | */ | ||
971 | static int mx3fb_blank(int blank, struct fb_info *fbi) | ||
972 | { | ||
973 | struct mx3fb_info *mx3_fbi = fbi->par; | ||
974 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; | ||
975 | |||
976 | dev_dbg(fbi->device, "%s\n", __func__); | ||
977 | |||
978 | dev_dbg(fbi->device, "blank = %d\n", blank); | ||
979 | |||
980 | if (mx3_fbi->blank == blank) | ||
981 | return 0; | ||
982 | |||
983 | mutex_lock(&mx3_fbi->mutex); | ||
984 | mx3_fbi->blank = blank; | ||
985 | |||
986 | switch (blank) { | ||
987 | case FB_BLANK_POWERDOWN: | ||
988 | case FB_BLANK_VSYNC_SUSPEND: | ||
989 | case FB_BLANK_HSYNC_SUSPEND: | ||
990 | case FB_BLANK_NORMAL: | ||
991 | sdc_disable_channel(mx3_fbi); | ||
992 | sdc_set_brightness(mx3fb, 0); | ||
993 | break; | ||
994 | case FB_BLANK_UNBLANK: | ||
995 | sdc_enable_channel(mx3_fbi); | ||
996 | sdc_set_brightness(mx3fb, mx3fb->backlight_level); | ||
997 | break; | ||
998 | } | ||
999 | mutex_unlock(&mx3_fbi->mutex); | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | /** | ||
1005 | * mx3fb_pan_display() - pan or wrap the display | ||
1006 | * @var: variable screen buffer information. | ||
1007 | * @info: framebuffer information pointer. | ||
1008 | * | ||
1009 | * We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag | ||
1010 | */ | ||
1011 | static int mx3fb_pan_display(struct fb_var_screeninfo *var, | ||
1012 | struct fb_info *fbi) | ||
1013 | { | ||
1014 | struct mx3fb_info *mx3_fbi = fbi->par; | ||
1015 | u32 y_bottom; | ||
1016 | unsigned long base; | ||
1017 | off_t offset; | ||
1018 | dma_cookie_t cookie; | ||
1019 | struct scatterlist *sg = mx3_fbi->sg; | ||
1020 | struct dma_chan *dma_chan = &mx3_fbi->idmac_channel->dma_chan; | ||
1021 | struct dma_async_tx_descriptor *txd; | ||
1022 | int ret; | ||
1023 | |||
1024 | dev_dbg(fbi->device, "%s [%c]\n", __func__, | ||
1025 | list_empty(&mx3_fbi->idmac_channel->queue) ? '-' : '+'); | ||
1026 | |||
1027 | if (var->xoffset > 0) { | ||
1028 | dev_dbg(fbi->device, "x panning not supported\n"); | ||
1029 | return -EINVAL; | ||
1030 | } | ||
1031 | |||
1032 | if (fbi->var.xoffset == var->xoffset && | ||
1033 | fbi->var.yoffset == var->yoffset) | ||
1034 | return 0; /* No change, do nothing */ | ||
1035 | |||
1036 | y_bottom = var->yoffset; | ||
1037 | |||
1038 | if (!(var->vmode & FB_VMODE_YWRAP)) | ||
1039 | y_bottom += var->yres; | ||
1040 | |||
1041 | if (y_bottom > fbi->var.yres_virtual) | ||
1042 | return -EINVAL; | ||
1043 | |||
1044 | mutex_lock(&mx3_fbi->mutex); | ||
1045 | |||
1046 | offset = (var->yoffset * var->xres_virtual + var->xoffset) * | ||
1047 | (var->bits_per_pixel / 8); | ||
1048 | base = fbi->fix.smem_start + offset; | ||
1049 | |||
1050 | dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", | ||
1051 | mx3_fbi->cur_ipu_buf, base); | ||
1052 | |||
1053 | /* | ||
1054 | * We enable the End of Frame interrupt, which will free a tx-descriptor, | ||
1055 | * which we will need for the next device_prep_slave_sg(). The | ||
1056 | * IRQ-handler will disable the IRQ again. | ||
1057 | */ | ||
1058 | init_completion(&mx3_fbi->flip_cmpl); | ||
1059 | enable_irq(mx3_fbi->idmac_channel->eof_irq); | ||
1060 | |||
1061 | ret = wait_for_completion_timeout(&mx3_fbi->flip_cmpl, HZ / 10); | ||
1062 | if (ret <= 0) { | ||
1063 | mutex_unlock(&mx3_fbi->mutex); | ||
1064 | dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ? | ||
1065 | "user interrupt" : "timeout"); | ||
1066 | return ret ? : -ETIMEDOUT; | ||
1067 | } | ||
1068 | |||
1069 | mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf; | ||
1070 | |||
1071 | sg_dma_address(&sg[mx3_fbi->cur_ipu_buf]) = base; | ||
1072 | sg_set_page(&sg[mx3_fbi->cur_ipu_buf], | ||
1073 | virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len, | ||
1074 | offset_in_page(fbi->screen_base + offset)); | ||
1075 | |||
1076 | txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg + | ||
1077 | mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT); | ||
1078 | if (!txd) { | ||
1079 | dev_err(fbi->device, | ||
1080 | "Error preparing a DMA transaction descriptor.\n"); | ||
1081 | mutex_unlock(&mx3_fbi->mutex); | ||
1082 | return -EIO; | ||
1083 | } | ||
1084 | |||
1085 | txd->callback_param = txd; | ||
1086 | txd->callback = mx3fb_dma_done; | ||
1087 | |||
1088 | /* | ||
1089 | * Emulate original mx3fb behaviour: each new call to idmac_tx_submit() | ||
1090 | * should switch to another buffer | ||
1091 | */ | ||
1092 | cookie = txd->tx_submit(txd); | ||
1093 | dev_dbg(fbi->device, "%d: Submit %p #%d\n", __LINE__, txd, cookie); | ||
1094 | if (cookie < 0) { | ||
1095 | dev_err(fbi->device, | ||
1096 | "Error updating SDC buf %d to address=0x%08lX\n", | ||
1097 | mx3_fbi->cur_ipu_buf, base); | ||
1098 | mutex_unlock(&mx3_fbi->mutex); | ||
1099 | return -EIO; | ||
1100 | } | ||
1101 | |||
1102 | if (mx3_fbi->txd) | ||
1103 | async_tx_ack(mx3_fbi->txd); | ||
1104 | mx3_fbi->txd = txd; | ||
1105 | |||
1106 | fbi->var.xoffset = var->xoffset; | ||
1107 | fbi->var.yoffset = var->yoffset; | ||
1108 | |||
1109 | if (var->vmode & FB_VMODE_YWRAP) | ||
1110 | fbi->var.vmode |= FB_VMODE_YWRAP; | ||
1111 | else | ||
1112 | fbi->var.vmode &= ~FB_VMODE_YWRAP; | ||
1113 | |||
1114 | mutex_unlock(&mx3_fbi->mutex); | ||
1115 | |||
1116 | dev_dbg(fbi->device, "Update complete\n"); | ||
1117 | |||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | /* | ||
1122 | * This structure contains the pointers to the control functions that are | ||
1123 | * invoked by the core framebuffer driver to perform operations like | ||
1124 | * blitting, rectangle filling, copy regions and cursor definition. | ||
1125 | */ | ||
1126 | static struct fb_ops mx3fb_ops = { | ||
1127 | .owner = THIS_MODULE, | ||
1128 | .fb_set_par = mx3fb_set_par, | ||
1129 | .fb_check_var = mx3fb_check_var, | ||
1130 | .fb_setcolreg = mx3fb_setcolreg, | ||
1131 | .fb_pan_display = mx3fb_pan_display, | ||
1132 | .fb_fillrect = cfb_fillrect, | ||
1133 | .fb_copyarea = cfb_copyarea, | ||
1134 | .fb_imageblit = cfb_imageblit, | ||
1135 | .fb_blank = mx3fb_blank, | ||
1136 | }; | ||
1137 | |||
1138 | #ifdef CONFIG_PM | ||
1139 | /* | ||
1140 | * Power management hooks. Note that we won't be called from IRQ context, | ||
1141 | * unlike the blank functions above, so we may sleep. | ||
1142 | */ | ||
1143 | |||
1144 | /* | ||
1145 | * Suspends the framebuffer and blanks the screen. Power management support | ||
1146 | */ | ||
1147 | static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state) | ||
1148 | { | ||
1149 | struct mx3fb_data *drv_data = platform_get_drvdata(pdev); | ||
1150 | struct mx3fb_info *mx3_fbi = drv_data->fbi->par; | ||
1151 | |||
1152 | acquire_console_sem(); | ||
1153 | fb_set_suspend(drv_data->fbi, 1); | ||
1154 | release_console_sem(); | ||
1155 | |||
1156 | if (mx3_fbi->blank == FB_BLANK_UNBLANK) { | ||
1157 | sdc_disable_channel(mx3_fbi); | ||
1158 | sdc_set_brightness(mx3fb, 0); | ||
1159 | |||
1160 | } | ||
1161 | return 0; | ||
1162 | } | ||
1163 | |||
1164 | /* | ||
1165 | * Resumes the framebuffer and unblanks the screen. Power management support | ||
1166 | */ | ||
1167 | static int mx3fb_resume(struct platform_device *pdev) | ||
1168 | { | ||
1169 | struct mx3fb_data *drv_data = platform_get_drvdata(pdev); | ||
1170 | struct mx3fb_info *mx3_fbi = drv_data->fbi->par; | ||
1171 | |||
1172 | if (mx3_fbi->blank == FB_BLANK_UNBLANK) { | ||
1173 | sdc_enable_channel(mx3_fbi); | ||
1174 | sdc_set_brightness(mx3fb, drv_data->backlight_level); | ||
1175 | } | ||
1176 | |||
1177 | acquire_console_sem(); | ||
1178 | fb_set_suspend(drv_data->fbi, 0); | ||
1179 | release_console_sem(); | ||
1180 | |||
1181 | return 0; | ||
1182 | } | ||
1183 | #else | ||
1184 | #define mx3fb_suspend NULL | ||
1185 | #define mx3fb_resume NULL | ||
1186 | #endif | ||
1187 | |||
1188 | /* | ||
1189 | * Main framebuffer functions | ||
1190 | */ | ||
1191 | |||
1192 | /** | ||
1193 | * mx3fb_map_video_memory() - allocates the DRAM memory for the frame buffer. | ||
1194 | * @fbi: framebuffer information pointer | ||
1195 | * @return: Error code indicating success or failure | ||
1196 | * | ||
1197 | * This buffer is remapped into a non-cached, non-buffered, memory region to | ||
1198 | * allow palette and pixel writes to occur without flushing the cache. Once this | ||
1199 | * area is remapped, all virtual memory access to the video memory should occur | ||
1200 | * at the new region. | ||
1201 | */ | ||
1202 | static int mx3fb_map_video_memory(struct fb_info *fbi) | ||
1203 | { | ||
1204 | int retval = 0; | ||
1205 | dma_addr_t addr; | ||
1206 | |||
1207 | fbi->screen_base = dma_alloc_writecombine(fbi->device, | ||
1208 | fbi->fix.smem_len, | ||
1209 | &addr, GFP_DMA); | ||
1210 | |||
1211 | if (!fbi->screen_base) { | ||
1212 | dev_err(fbi->device, "Cannot allocate %u bytes framebuffer memory\n", | ||
1213 | fbi->fix.smem_len); | ||
1214 | retval = -EBUSY; | ||
1215 | goto err0; | ||
1216 | } | ||
1217 | |||
1218 | fbi->fix.smem_start = addr; | ||
1219 | |||
1220 | dev_dbg(fbi->device, "allocated fb @ p=0x%08x, v=0x%p, size=%d.\n", | ||
1221 | (uint32_t) fbi->fix.smem_start, fbi->screen_base, fbi->fix.smem_len); | ||
1222 | |||
1223 | fbi->screen_size = fbi->fix.smem_len; | ||
1224 | |||
1225 | /* Clear the screen */ | ||
1226 | memset((char *)fbi->screen_base, 0, fbi->fix.smem_len); | ||
1227 | |||
1228 | return 0; | ||
1229 | |||
1230 | err0: | ||
1231 | fbi->fix.smem_len = 0; | ||
1232 | fbi->fix.smem_start = 0; | ||
1233 | fbi->screen_base = NULL; | ||
1234 | return retval; | ||
1235 | } | ||
1236 | |||
1237 | /** | ||
1238 | * mx3fb_unmap_video_memory() - de-allocate frame buffer memory. | ||
1239 | * @fbi: framebuffer information pointer | ||
1240 | * @return: error code indicating success or failure | ||
1241 | */ | ||
1242 | static int mx3fb_unmap_video_memory(struct fb_info *fbi) | ||
1243 | { | ||
1244 | dma_free_writecombine(fbi->device, fbi->fix.smem_len, | ||
1245 | fbi->screen_base, fbi->fix.smem_start); | ||
1246 | |||
1247 | fbi->screen_base = 0; | ||
1248 | fbi->fix.smem_start = 0; | ||
1249 | fbi->fix.smem_len = 0; | ||
1250 | return 0; | ||
1251 | } | ||
1252 | |||
1253 | /** | ||
1254 | * mx3fb_init_fbinfo() - initialize framebuffer information object. | ||
1255 | * @return: initialized framebuffer structure. | ||
1256 | */ | ||
1257 | static struct fb_info *mx3fb_init_fbinfo(struct device *dev, struct fb_ops *ops) | ||
1258 | { | ||
1259 | struct fb_info *fbi; | ||
1260 | struct mx3fb_info *mx3fbi; | ||
1261 | int ret; | ||
1262 | |||
1263 | /* Allocate sufficient memory for the fb structure */ | ||
1264 | fbi = framebuffer_alloc(sizeof(struct mx3fb_info), dev); | ||
1265 | if (!fbi) | ||
1266 | return NULL; | ||
1267 | |||
1268 | mx3fbi = fbi->par; | ||
1269 | mx3fbi->cookie = -EINVAL; | ||
1270 | mx3fbi->cur_ipu_buf = 0; | ||
1271 | |||
1272 | fbi->var.activate = FB_ACTIVATE_NOW; | ||
1273 | |||
1274 | fbi->fbops = ops; | ||
1275 | fbi->flags = FBINFO_FLAG_DEFAULT; | ||
1276 | fbi->pseudo_palette = mx3fbi->pseudo_palette; | ||
1277 | |||
1278 | mutex_init(&mx3fbi->mutex); | ||
1279 | |||
1280 | /* Allocate colormap */ | ||
1281 | ret = fb_alloc_cmap(&fbi->cmap, 16, 0); | ||
1282 | if (ret < 0) { | ||
1283 | framebuffer_release(fbi); | ||
1284 | return NULL; | ||
1285 | } | ||
1286 | |||
1287 | return fbi; | ||
1288 | } | ||
1289 | |||
1290 | static int init_fb_chan(struct mx3fb_data *mx3fb, struct idmac_channel *ichan) | ||
1291 | { | ||
1292 | struct device *dev = mx3fb->dev; | ||
1293 | struct mx3fb_platform_data *mx3fb_pdata = dev->platform_data; | ||
1294 | const char *name = mx3fb_pdata->name; | ||
1295 | unsigned int irq; | ||
1296 | struct fb_info *fbi; | ||
1297 | struct mx3fb_info *mx3fbi; | ||
1298 | const struct fb_videomode *mode; | ||
1299 | int ret, num_modes; | ||
1300 | |||
1301 | ichan->client = mx3fb; | ||
1302 | irq = ichan->eof_irq; | ||
1303 | |||
1304 | if (ichan->dma_chan.chan_id != IDMAC_SDC_0) | ||
1305 | return -EINVAL; | ||
1306 | |||
1307 | fbi = mx3fb_init_fbinfo(dev, &mx3fb_ops); | ||
1308 | if (!fbi) | ||
1309 | return -ENOMEM; | ||
1310 | |||
1311 | if (!fb_mode) | ||
1312 | fb_mode = name; | ||
1313 | |||
1314 | if (!fb_mode) { | ||
1315 | ret = -EINVAL; | ||
1316 | goto emode; | ||
1317 | } | ||
1318 | |||
1319 | if (mx3fb_pdata->mode && mx3fb_pdata->num_modes) { | ||
1320 | mode = mx3fb_pdata->mode; | ||
1321 | num_modes = mx3fb_pdata->num_modes; | ||
1322 | } else { | ||
1323 | mode = mx3fb_modedb; | ||
1324 | num_modes = ARRAY_SIZE(mx3fb_modedb); | ||
1325 | } | ||
1326 | |||
1327 | if (!fb_find_mode(&fbi->var, fbi, fb_mode, mode, | ||
1328 | num_modes, NULL, default_bpp)) { | ||
1329 | ret = -EBUSY; | ||
1330 | goto emode; | ||
1331 | } | ||
1332 | |||
1333 | fb_videomode_to_modelist(mode, num_modes, &fbi->modelist); | ||
1334 | |||
1335 | /* Default Y virtual size is 2x panel size */ | ||
1336 | fbi->var.yres_virtual = fbi->var.yres * 2; | ||
1337 | |||
1338 | mx3fb->fbi = fbi; | ||
1339 | |||
1340 | /* set Display Interface clock period */ | ||
1341 | mx3fb_write_reg(mx3fb, 0x00100010L, DI_HSP_CLK_PER); | ||
1342 | /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ | ||
1343 | |||
1344 | sdc_set_brightness(mx3fb, 255); | ||
1345 | sdc_set_global_alpha(mx3fb, true, 0xFF); | ||
1346 | sdc_set_color_key(mx3fb, IDMAC_SDC_0, false, 0); | ||
1347 | |||
1348 | mx3fbi = fbi->par; | ||
1349 | mx3fbi->idmac_channel = ichan; | ||
1350 | mx3fbi->ipu_ch = ichan->dma_chan.chan_id; | ||
1351 | mx3fbi->mx3fb = mx3fb; | ||
1352 | mx3fbi->blank = FB_BLANK_NORMAL; | ||
1353 | |||
1354 | init_completion(&mx3fbi->flip_cmpl); | ||
1355 | disable_irq(ichan->eof_irq); | ||
1356 | dev_dbg(mx3fb->dev, "disabling irq %d\n", ichan->eof_irq); | ||
1357 | ret = mx3fb_set_par(fbi); | ||
1358 | if (ret < 0) | ||
1359 | goto esetpar; | ||
1360 | |||
1361 | mx3fb_blank(FB_BLANK_UNBLANK, fbi); | ||
1362 | |||
1363 | dev_info(dev, "mx3fb: fb registered, using mode %s\n", fb_mode); | ||
1364 | |||
1365 | ret = register_framebuffer(fbi); | ||
1366 | if (ret < 0) | ||
1367 | goto erfb; | ||
1368 | |||
1369 | return 0; | ||
1370 | |||
1371 | erfb: | ||
1372 | esetpar: | ||
1373 | emode: | ||
1374 | fb_dealloc_cmap(&fbi->cmap); | ||
1375 | framebuffer_release(fbi); | ||
1376 | |||
1377 | return ret; | ||
1378 | } | ||
1379 | |||
1380 | static bool chan_filter(struct dma_chan *chan, void *arg) | ||
1381 | { | ||
1382 | struct dma_chan_request *rq = arg; | ||
1383 | struct device *dev; | ||
1384 | struct mx3fb_platform_data *mx3fb_pdata; | ||
1385 | |||
1386 | if (!rq) | ||
1387 | return false; | ||
1388 | |||
1389 | dev = rq->mx3fb->dev; | ||
1390 | mx3fb_pdata = dev->platform_data; | ||
1391 | |||
1392 | return rq->id == chan->chan_id && | ||
1393 | mx3fb_pdata->dma_dev == chan->device->dev; | ||
1394 | } | ||
1395 | |||
1396 | static void release_fbi(struct fb_info *fbi) | ||
1397 | { | ||
1398 | mx3fb_unmap_video_memory(fbi); | ||
1399 | |||
1400 | fb_dealloc_cmap(&fbi->cmap); | ||
1401 | |||
1402 | unregister_framebuffer(fbi); | ||
1403 | framebuffer_release(fbi); | ||
1404 | } | ||
1405 | |||
1406 | static int mx3fb_probe(struct platform_device *pdev) | ||
1407 | { | ||
1408 | struct device *dev = &pdev->dev; | ||
1409 | int ret; | ||
1410 | struct resource *sdc_reg; | ||
1411 | struct mx3fb_data *mx3fb; | ||
1412 | dma_cap_mask_t mask; | ||
1413 | struct dma_chan *chan; | ||
1414 | struct dma_chan_request rq; | ||
1415 | |||
1416 | /* | ||
1417 | * Display Interface (DI) and Synchronous Display Controller (SDC) | ||
1418 | * registers | ||
1419 | */ | ||
1420 | sdc_reg = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1421 | if (!sdc_reg) | ||
1422 | return -EINVAL; | ||
1423 | |||
1424 | mx3fb = kzalloc(sizeof(*mx3fb), GFP_KERNEL); | ||
1425 | if (!mx3fb) | ||
1426 | return -ENOMEM; | ||
1427 | |||
1428 | spin_lock_init(&mx3fb->lock); | ||
1429 | |||
1430 | mx3fb->reg_base = ioremap(sdc_reg->start, resource_size(sdc_reg)); | ||
1431 | if (!mx3fb->reg_base) { | ||
1432 | ret = -ENOMEM; | ||
1433 | goto eremap; | ||
1434 | } | ||
1435 | |||
1436 | pr_debug("Remapped %x to %x at %p\n", sdc_reg->start, sdc_reg->end, | ||
1437 | mx3fb->reg_base); | ||
1438 | |||
1439 | /* IDMAC interface */ | ||
1440 | dmaengine_get(); | ||
1441 | |||
1442 | mx3fb->dev = dev; | ||
1443 | platform_set_drvdata(pdev, mx3fb); | ||
1444 | |||
1445 | rq.mx3fb = mx3fb; | ||
1446 | |||
1447 | dma_cap_zero(mask); | ||
1448 | dma_cap_set(DMA_SLAVE, mask); | ||
1449 | dma_cap_set(DMA_PRIVATE, mask); | ||
1450 | rq.id = IDMAC_SDC_0; | ||
1451 | chan = dma_request_channel(mask, chan_filter, &rq); | ||
1452 | if (!chan) { | ||
1453 | ret = -EBUSY; | ||
1454 | goto ersdc0; | ||
1455 | } | ||
1456 | |||
1457 | ret = init_fb_chan(mx3fb, to_idmac_chan(chan)); | ||
1458 | if (ret < 0) | ||
1459 | goto eisdc0; | ||
1460 | |||
1461 | mx3fb->backlight_level = 255; | ||
1462 | |||
1463 | return 0; | ||
1464 | |||
1465 | eisdc0: | ||
1466 | dma_release_channel(chan); | ||
1467 | ersdc0: | ||
1468 | dmaengine_put(); | ||
1469 | iounmap(mx3fb->reg_base); | ||
1470 | eremap: | ||
1471 | kfree(mx3fb); | ||
1472 | dev_err(dev, "mx3fb: failed to register fb\n"); | ||
1473 | return ret; | ||
1474 | } | ||
1475 | |||
1476 | static int mx3fb_remove(struct platform_device *dev) | ||
1477 | { | ||
1478 | struct mx3fb_data *mx3fb = platform_get_drvdata(dev); | ||
1479 | struct fb_info *fbi = mx3fb->fbi; | ||
1480 | struct mx3fb_info *mx3_fbi = fbi->par; | ||
1481 | struct dma_chan *chan; | ||
1482 | |||
1483 | chan = &mx3_fbi->idmac_channel->dma_chan; | ||
1484 | release_fbi(fbi); | ||
1485 | |||
1486 | dma_release_channel(chan); | ||
1487 | dmaengine_put(); | ||
1488 | |||
1489 | iounmap(mx3fb->reg_base); | ||
1490 | kfree(mx3fb); | ||
1491 | return 0; | ||
1492 | } | ||
1493 | |||
1494 | static struct platform_driver mx3fb_driver = { | ||
1495 | .driver = { | ||
1496 | .name = MX3FB_NAME, | ||
1497 | }, | ||
1498 | .probe = mx3fb_probe, | ||
1499 | .remove = mx3fb_remove, | ||
1500 | .suspend = mx3fb_suspend, | ||
1501 | .resume = mx3fb_resume, | ||
1502 | }; | ||
1503 | |||
1504 | /* | ||
1505 | * Parse user specified options (`video=mx3fb:') | ||
1506 | * example: | ||
1507 | * video=mx3fb:bpp=16 | ||
1508 | */ | ||
1509 | static int mx3fb_setup(void) | ||
1510 | { | ||
1511 | #ifndef MODULE | ||
1512 | char *opt, *options = NULL; | ||
1513 | |||
1514 | if (fb_get_options("mx3fb", &options)) | ||
1515 | return -ENODEV; | ||
1516 | |||
1517 | if (!options || !*options) | ||
1518 | return 0; | ||
1519 | |||
1520 | while ((opt = strsep(&options, ",")) != NULL) { | ||
1521 | if (!*opt) | ||
1522 | continue; | ||
1523 | if (!strncmp(opt, "bpp=", 4)) | ||
1524 | default_bpp = simple_strtoul(opt + 4, NULL, 0); | ||
1525 | else | ||
1526 | fb_mode = opt; | ||
1527 | } | ||
1528 | #endif | ||
1529 | |||
1530 | return 0; | ||
1531 | } | ||
1532 | |||
1533 | static int __init mx3fb_init(void) | ||
1534 | { | ||
1535 | int ret = mx3fb_setup(); | ||
1536 | |||
1537 | if (ret < 0) | ||
1538 | return ret; | ||
1539 | |||
1540 | ret = platform_driver_register(&mx3fb_driver); | ||
1541 | return ret; | ||
1542 | } | ||
1543 | |||
1544 | static void __exit mx3fb_exit(void) | ||
1545 | { | ||
1546 | platform_driver_unregister(&mx3fb_driver); | ||
1547 | } | ||
1548 | |||
1549 | module_init(mx3fb_init); | ||
1550 | module_exit(mx3fb_exit); | ||
1551 | |||
1552 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
1553 | MODULE_DESCRIPTION("MX3 framebuffer driver"); | ||
1554 | MODULE_ALIAS("platform:" MX3FB_NAME); | ||
1555 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index 6fd7cb8f9b8e..6aaddb4f6788 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c | |||
@@ -87,7 +87,6 @@ static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name, | |||
87 | 87 | ||
88 | strcpy(chan->adapter.name, name); | 88 | strcpy(chan->adapter.name, name); |
89 | chan->adapter.owner = THIS_MODULE; | 89 | chan->adapter.owner = THIS_MODULE; |
90 | chan->adapter.id = I2C_HW_B_NVIDIA; | ||
91 | chan->adapter.class = i2c_class; | 90 | chan->adapter.class = i2c_class; |
92 | chan->adapter.algo_data = &chan->algo; | 91 | chan->adapter.algo_data = &chan->algo; |
93 | chan->adapter.dev.parent = &chan->par->pci_dev->dev; | 92 | chan->adapter.dev.parent = &chan->par->pci_dev->dev; |
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c index 6e2ea7518761..ab3949256677 100644 --- a/drivers/video/omap/lcdc.c +++ b/drivers/video/omap/lcdc.c | |||
@@ -800,14 +800,14 @@ static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode, | |||
800 | /* FIXME: | 800 | /* FIXME: |
801 | * According to errata some platforms have a clock rate limitiation | 801 | * According to errata some platforms have a clock rate limitiation |
802 | */ | 802 | */ |
803 | lcdc.lcd_ck = clk_get(NULL, "lcd_ck"); | 803 | lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck"); |
804 | if (IS_ERR(lcdc.lcd_ck)) { | 804 | if (IS_ERR(lcdc.lcd_ck)) { |
805 | dev_err(fbdev->dev, "unable to access LCD clock\n"); | 805 | dev_err(fbdev->dev, "unable to access LCD clock\n"); |
806 | r = PTR_ERR(lcdc.lcd_ck); | 806 | r = PTR_ERR(lcdc.lcd_ck); |
807 | goto fail0; | 807 | goto fail0; |
808 | } | 808 | } |
809 | 809 | ||
810 | tc_ck = clk_get(NULL, "tc_ck"); | 810 | tc_ck = clk_get(fbdev->dev, "tc_ck"); |
811 | if (IS_ERR(tc_ck)) { | 811 | if (IS_ERR(tc_ck)) { |
812 | dev_err(fbdev->dev, "unable to access TC clock\n"); | 812 | dev_err(fbdev->dev, "unable to access TC clock\n"); |
813 | r = PTR_ERR(tc_ck); | 813 | r = PTR_ERR(tc_ck); |
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 783d4adffb93..574b29e9f8f2 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c | |||
@@ -137,7 +137,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan, | |||
137 | if (chan->par) { | 137 | if (chan->par) { |
138 | strcpy(chan->adapter.name, name); | 138 | strcpy(chan->adapter.name, name); |
139 | chan->adapter.owner = THIS_MODULE; | 139 | chan->adapter.owner = THIS_MODULE; |
140 | chan->adapter.id = I2C_HW_B_SAVAGE; | ||
141 | chan->adapter.algo_data = &chan->algo; | 140 | chan->adapter.algo_data = &chan->algo; |
142 | chan->adapter.dev.parent = &chan->par->pcidev->dev; | 141 | chan->adapter.dev.parent = &chan->par->pcidev->dev; |
143 | chan->algo.udelay = 10; | 142 | chan->algo.udelay = 10; |