diff options
Diffstat (limited to 'drivers/video')
159 files changed, 11189 insertions, 7294 deletions
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 75a39eab70c3..a425d65d5ba2 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c | |||
| @@ -378,8 +378,8 @@ static int mc68x328fb_pan_display(struct fb_var_screeninfo *var, | |||
| 378 | || var->xoffset) | 378 | || var->xoffset) |
| 379 | return -EINVAL; | 379 | return -EINVAL; |
| 380 | } else { | 380 | } else { |
| 381 | if (var->xoffset + var->xres > info->var.xres_virtual || | 381 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
| 382 | var->yoffset + var->yres > info->var.yres_virtual) | 382 | var->yoffset + info->var.yres > info->var.yres_virtual) |
| 383 | return -EINVAL; | 383 | return -EINVAL; |
| 384 | } | 384 | } |
| 385 | info->var.xoffset = var->xoffset; | 385 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 549b960667c8..d83e967e4e15 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -259,6 +259,15 @@ config FB_TILEBLITTING | |||
| 259 | comment "Frame buffer hardware drivers" | 259 | comment "Frame buffer hardware drivers" |
| 260 | depends on FB | 260 | depends on FB |
| 261 | 261 | ||
| 262 | config FB_GRVGA | ||
| 263 | tristate "Aeroflex Gaisler framebuffer support" | ||
| 264 | depends on FB && SPARC | ||
| 265 | select FB_CFB_FILLRECT | ||
| 266 | select FB_CFB_COPYAREA | ||
| 267 | select FB_CFB_IMAGEBLIT | ||
| 268 | ---help--- | ||
| 269 | This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler. | ||
| 270 | |||
| 262 | config FB_CIRRUS | 271 | config FB_CIRRUS |
| 263 | tristate "Cirrus Logic support" | 272 | tristate "Cirrus Logic support" |
| 264 | depends on FB && (ZORRO || PCI) | 273 | depends on FB && (ZORRO || PCI) |
| @@ -1744,7 +1753,7 @@ endchoice | |||
| 1744 | 1753 | ||
| 1745 | config FB_AU1100 | 1754 | config FB_AU1100 |
| 1746 | bool "Au1100 LCD Driver" | 1755 | bool "Au1100 LCD Driver" |
| 1747 | depends on (FB = y) && MIPS && SOC_AU1100 | 1756 | depends on (FB = y) && MIPS_ALCHEMY |
| 1748 | select FB_CFB_FILLRECT | 1757 | select FB_CFB_FILLRECT |
| 1749 | select FB_CFB_COPYAREA | 1758 | select FB_CFB_COPYAREA |
| 1750 | select FB_CFB_IMAGEBLIT | 1759 | select FB_CFB_IMAGEBLIT |
| @@ -1755,10 +1764,11 @@ config FB_AU1100 | |||
| 1755 | 1764 | ||
| 1756 | config FB_AU1200 | 1765 | config FB_AU1200 |
| 1757 | bool "Au1200 LCD Driver" | 1766 | bool "Au1200 LCD Driver" |
| 1758 | depends on (FB = y) && MIPS && SOC_AU1200 | 1767 | depends on (FB = y) && MIPS_ALCHEMY |
| 1759 | select FB_CFB_FILLRECT | 1768 | select FB_SYS_FILLRECT |
| 1760 | select FB_CFB_COPYAREA | 1769 | select FB_SYS_COPYAREA |
| 1761 | select FB_CFB_IMAGEBLIT | 1770 | select FB_SYS_IMAGEBLIT |
| 1771 | select FB_SYS_FOPS | ||
| 1762 | help | 1772 | help |
| 1763 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive | 1773 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive |
| 1764 | various panels and CRTs by passing in kernel cmd line option | 1774 | various panels and CRTs by passing in kernel cmd line option |
| @@ -2027,7 +2037,7 @@ config FB_TMIO_ACCELL | |||
| 2027 | 2037 | ||
| 2028 | config FB_S3C | 2038 | config FB_S3C |
| 2029 | tristate "Samsung S3C framebuffer support" | 2039 | tristate "Samsung S3C framebuffer support" |
| 2030 | depends on FB && S3C_DEV_FB | 2040 | depends on FB && (S3C_DEV_FB || S5P_DEV_FIMD0) |
| 2031 | select FB_CFB_FILLRECT | 2041 | select FB_CFB_FILLRECT |
| 2032 | select FB_CFB_COPYAREA | 2042 | select FB_CFB_COPYAREA |
| 2033 | select FB_CFB_IMAGEBLIT | 2043 | select FB_CFB_IMAGEBLIT |
| @@ -2110,6 +2120,22 @@ config FB_SM501 | |||
| 2110 | 2120 | ||
| 2111 | If unsure, say N. | 2121 | If unsure, say N. |
| 2112 | 2122 | ||
| 2123 | config FB_SMSCUFX | ||
| 2124 | tristate "SMSC UFX6000/7000 USB Framebuffer support" | ||
| 2125 | depends on FB && USB | ||
| 2126 | select FB_MODE_HELPERS | ||
| 2127 | select FB_SYS_FILLRECT | ||
| 2128 | select FB_SYS_COPYAREA | ||
| 2129 | select FB_SYS_IMAGEBLIT | ||
| 2130 | select FB_SYS_FOPS | ||
| 2131 | select FB_DEFERRED_IO | ||
| 2132 | ---help--- | ||
| 2133 | This is a kernel framebuffer driver for SMSC UFX USB devices. | ||
| 2134 | Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and | ||
| 2135 | mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000 | ||
| 2136 | (USB 3.0) devices. | ||
| 2137 | To compile as a module, choose M here: the module name is smscufx. | ||
| 2138 | |||
| 2113 | config FB_UDL | 2139 | config FB_UDL |
| 2114 | tristate "Displaylink USB Framebuffer support" | 2140 | tristate "Displaylink USB Framebuffer support" |
| 2115 | depends on FB && USB | 2141 | depends on FB && USB |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 8b83129e209c..9b9d8fff7732 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
| @@ -33,6 +33,7 @@ obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o | |||
| 33 | obj-$(CONFIG_FB_ARC) += arcfb.o | 33 | obj-$(CONFIG_FB_ARC) += arcfb.o |
| 34 | obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o | 34 | obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o |
| 35 | obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o | 35 | obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o |
| 36 | obj-$(CONFIG_FB_GRVGA) += grvga.o | ||
| 36 | obj-$(CONFIG_FB_PM2) += pm2fb.o | 37 | obj-$(CONFIG_FB_PM2) += pm2fb.o |
| 37 | obj-$(CONFIG_FB_PM3) += pm3fb.o | 38 | obj-$(CONFIG_FB_PM3) += pm3fb.o |
| 38 | 39 | ||
| @@ -127,6 +128,7 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | |||
| 127 | obj-$(CONFIG_FB_PS3) += ps3fb.o | 128 | obj-$(CONFIG_FB_PS3) += ps3fb.o |
| 128 | obj-$(CONFIG_FB_SM501) += sm501fb.o | 129 | obj-$(CONFIG_FB_SM501) += sm501fb.o |
| 129 | obj-$(CONFIG_FB_UDL) += udlfb.o | 130 | obj-$(CONFIG_FB_UDL) += udlfb.o |
| 131 | obj-$(CONFIG_FB_SMSCUFX) += smscufx.o | ||
| 130 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o | 132 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o |
| 131 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o | 133 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o |
| 132 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o | 134 | obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o |
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 6183a57eb69d..b303f1715065 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c | |||
| @@ -850,9 +850,10 @@ acornfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 850 | u_int y_bottom = var->yoffset; | 850 | u_int y_bottom = var->yoffset; |
| 851 | 851 | ||
| 852 | if (!(var->vmode & FB_VMODE_YWRAP)) | 852 | if (!(var->vmode & FB_VMODE_YWRAP)) |
| 853 | y_bottom += var->yres; | 853 | y_bottom += info->var.yres; |
| 854 | 854 | ||
| 855 | BUG_ON(y_bottom > var->yres_virtual); | 855 | if (y_bottom > info->var.yres_virtual) |
| 856 | return -EINVAL; | ||
| 856 | 857 | ||
| 857 | acornfb_update_dma(info, var); | 858 | acornfb_update_dma(info, var); |
| 858 | 859 | ||
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index cf03ad067147..2cda6ba0939b 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
| @@ -447,6 +447,10 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
| 447 | goto out; | 447 | goto out; |
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | ret = clk_prepare(fb->clk); | ||
| 451 | if (ret) | ||
| 452 | goto free_clk; | ||
| 453 | |||
| 450 | fb->fb.device = &fb->dev->dev; | 454 | fb->fb.device = &fb->dev->dev; |
| 451 | 455 | ||
| 452 | fb->fb.fix.mmio_start = fb->dev->res.start; | 456 | fb->fb.fix.mmio_start = fb->dev->res.start; |
| @@ -456,7 +460,7 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
| 456 | if (!fb->regs) { | 460 | if (!fb->regs) { |
| 457 | printk(KERN_ERR "CLCD: unable to remap registers\n"); | 461 | printk(KERN_ERR "CLCD: unable to remap registers\n"); |
| 458 | ret = -ENOMEM; | 462 | ret = -ENOMEM; |
| 459 | goto free_clk; | 463 | goto clk_unprep; |
| 460 | } | 464 | } |
| 461 | 465 | ||
| 462 | fb->fb.fbops = &clcdfb_ops; | 466 | fb->fb.fbops = &clcdfb_ops; |
| @@ -530,6 +534,8 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
| 530 | fb_dealloc_cmap(&fb->fb.cmap); | 534 | fb_dealloc_cmap(&fb->fb.cmap); |
| 531 | unmap: | 535 | unmap: |
| 532 | iounmap(fb->regs); | 536 | iounmap(fb->regs); |
| 537 | clk_unprep: | ||
| 538 | clk_unprepare(fb->clk); | ||
| 533 | free_clk: | 539 | free_clk: |
| 534 | clk_put(fb->clk); | 540 | clk_put(fb->clk); |
| 535 | out: | 541 | out: |
| @@ -595,6 +601,7 @@ static int clcdfb_remove(struct amba_device *dev) | |||
| 595 | if (fb->fb.cmap.len) | 601 | if (fb->fb.cmap.len) |
| 596 | fb_dealloc_cmap(&fb->fb.cmap); | 602 | fb_dealloc_cmap(&fb->fb.cmap); |
| 597 | iounmap(fb->regs); | 603 | iounmap(fb->regs); |
| 604 | clk_unprepare(fb->clk); | ||
| 598 | clk_put(fb->clk); | 605 | clk_put(fb->clk); |
| 599 | 606 | ||
| 600 | fb->board->remove(fb); | 607 | fb->board->remove(fb); |
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 8686429cbdf0..555dd4c64f5b 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c | |||
| @@ -908,13 +908,14 @@ static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info | |||
| 908 | unsigned int offset; | 908 | unsigned int offset; |
| 909 | 909 | ||
| 910 | /* Calculate the offset */ | 910 | /* Calculate the offset */ |
| 911 | if (var->bits_per_pixel == 0) { | 911 | if (info->var.bits_per_pixel == 0) { |
| 912 | offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); | 912 | offset = (var->yoffset / 16) * (info->var.xres_virtual / 2) |
| 913 | + (var->xoffset / 2); | ||
| 913 | offset = offset >> 2; | 914 | offset = offset >> 2; |
| 914 | } else { | 915 | } else { |
| 915 | offset = (var->yoffset * info->fix.line_length) + | 916 | offset = (var->yoffset * info->fix.line_length) + |
| 916 | (var->xoffset * var->bits_per_pixel / 8); | 917 | (var->xoffset * info->var.bits_per_pixel / 8); |
| 917 | offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3); | 918 | offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 3); |
| 918 | } | 919 | } |
| 919 | 920 | ||
| 920 | /* Set the offset */ | 921 | /* Set the offset */ |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 817ab60f7537..63409c122ae8 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
| @@ -18,10 +18,11 @@ | |||
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/backlight.h> | 19 | #include <linux/backlight.h> |
| 20 | #include <linux/gfp.h> | 20 | #include <linux/gfp.h> |
| 21 | #include <linux/module.h> | ||
| 21 | 22 | ||
| 22 | #include <mach/board.h> | 23 | #include <mach/board.h> |
| 23 | #include <mach/cpu.h> | 24 | #include <mach/cpu.h> |
| 24 | #include <mach/gpio.h> | 25 | #include <asm/gpio.h> |
| 25 | 26 | ||
| 26 | #include <video/atmel_lcdc.h> | 27 | #include <video/atmel_lcdc.h> |
| 27 | 28 | ||
| @@ -39,7 +40,8 @@ | |||
| 39 | | FBINFO_HWACCEL_YPAN) | 40 | | FBINFO_HWACCEL_YPAN) |
| 40 | 41 | ||
| 41 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | 42 | static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
| 42 | struct fb_var_screeninfo *var) | 43 | struct fb_var_screeninfo *var, |
| 44 | struct fb_info *info) | ||
| 43 | { | 45 | { |
| 44 | 46 | ||
| 45 | } | 47 | } |
| @@ -50,14 +52,16 @@ static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | |||
| 50 | | FBINFO_HWACCEL_YPAN) | 52 | | FBINFO_HWACCEL_YPAN) |
| 51 | 53 | ||
| 52 | static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | 54 | static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, |
| 53 | struct fb_var_screeninfo *var) | 55 | struct fb_var_screeninfo *var, |
| 56 | struct fb_info *info) | ||
| 54 | { | 57 | { |
| 55 | u32 dma2dcfg; | 58 | u32 dma2dcfg; |
| 56 | u32 pixeloff; | 59 | u32 pixeloff; |
| 57 | 60 | ||
| 58 | pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f; | 61 | pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f; |
| 59 | 62 | ||
| 60 | dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8; | 63 | dma2dcfg = (info->var.xres_virtual - info->var.xres) |
| 64 | * info->var.bits_per_pixel / 8; | ||
| 61 | dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; | 65 | dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET; |
| 62 | lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); | 66 | lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg); |
| 63 | 67 | ||
| @@ -249,14 +253,14 @@ static void atmel_lcdfb_update_dma(struct fb_info *info, | |||
| 249 | unsigned long dma_addr; | 253 | unsigned long dma_addr; |
| 250 | 254 | ||
| 251 | dma_addr = (fix->smem_start + var->yoffset * fix->line_length | 255 | dma_addr = (fix->smem_start + var->yoffset * fix->line_length |
| 252 | + var->xoffset * var->bits_per_pixel / 8); | 256 | + var->xoffset * info->var.bits_per_pixel / 8); |
| 253 | 257 | ||
| 254 | dma_addr &= ~3UL; | 258 | dma_addr &= ~3UL; |
| 255 | 259 | ||
| 256 | /* Set framebuffer DMA base address and pixel offset */ | 260 | /* Set framebuffer DMA base address and pixel offset */ |
| 257 | lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); | 261 | lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr); |
| 258 | 262 | ||
| 259 | atmel_lcdfb_update_dma2d(sinfo, var); | 263 | atmel_lcdfb_update_dma2d(sinfo, var, info); |
| 260 | } | 264 | } |
| 261 | 265 | ||
| 262 | static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) | 266 | static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo) |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 32f8cf6200a7..150684882ef7 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
| @@ -845,16 +845,16 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, | |||
| 845 | { | 845 | { |
| 846 | struct radeonfb_info *rinfo = info->par; | 846 | struct radeonfb_info *rinfo = info->par; |
| 847 | 847 | ||
| 848 | if ((var->xoffset + var->xres > var->xres_virtual) | 848 | if ((var->xoffset + info->var.xres > info->var.xres_virtual) |
| 849 | || (var->yoffset + var->yres > var->yres_virtual)) | 849 | || (var->yoffset + info->var.yres > info->var.yres_virtual)) |
| 850 | return -EINVAL; | 850 | return -EINVAL; |
| 851 | 851 | ||
| 852 | if (rinfo->asleep) | 852 | if (rinfo->asleep) |
| 853 | return 0; | 853 | return 0; |
| 854 | 854 | ||
| 855 | radeon_fifo_wait(2); | 855 | radeon_fifo_wait(2); |
| 856 | OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) | 856 | OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length + |
| 857 | * var->bits_per_pixel / 8) & ~7); | 857 | var->xoffset * info->var.bits_per_pixel / 8) & ~7); |
| 858 | return 0; | 858 | return 0; |
| 859 | } | 859 | } |
| 860 | 860 | ||
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 01a8fde67f20..649cb35de4ed 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c | |||
| @@ -110,12 +110,6 @@ static struct fb_var_screeninfo au1100fb_var __devinitdata = { | |||
| 110 | .vmode = FB_VMODE_NONINTERLACED, | 110 | .vmode = FB_VMODE_NONINTERLACED, |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | static struct au1100fb_drv_info drv_info; | ||
| 114 | |||
| 115 | static int nocursor = 0; | ||
| 116 | module_param(nocursor, int, 0644); | ||
| 117 | MODULE_PARM_DESC(nocursor, "cursor enable/disable"); | ||
| 118 | |||
| 119 | /* fb_blank | 113 | /* fb_blank |
| 120 | * Blank the screen. Depending on the mode, the screen will be | 114 | * Blank the screen. Depending on the mode, the screen will be |
| 121 | * activated with the backlight color, or desactivated | 115 | * activated with the backlight color, or desactivated |
| @@ -132,7 +126,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | |||
| 132 | /* Turn on panel */ | 126 | /* Turn on panel */ |
| 133 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; | 127 | fbdev->regs->lcd_control |= LCD_CONTROL_GO; |
| 134 | #ifdef CONFIG_MIPS_PB1100 | 128 | #ifdef CONFIG_MIPS_PB1100 |
| 135 | if (drv_info.panel_idx == 1) { | 129 | if (fbdev->panel_idx == 1) { |
| 136 | au_writew(au_readw(PB1100_G_CONTROL) | 130 | au_writew(au_readw(PB1100_G_CONTROL) |
| 137 | | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | 131 | | (PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), |
| 138 | PB1100_G_CONTROL); | 132 | PB1100_G_CONTROL); |
| @@ -147,7 +141,7 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) | |||
| 147 | /* Turn off panel */ | 141 | /* Turn off panel */ |
| 148 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; | 142 | fbdev->regs->lcd_control &= ~LCD_CONTROL_GO; |
| 149 | #ifdef CONFIG_MIPS_PB1100 | 143 | #ifdef CONFIG_MIPS_PB1100 |
| 150 | if (drv_info.panel_idx == 1) { | 144 | if (fbdev->panel_idx == 1) { |
| 151 | au_writew(au_readw(PB1100_G_CONTROL) | 145 | au_writew(au_readw(PB1100_G_CONTROL) |
| 152 | & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), | 146 | & ~(PB1100_G_CONTROL_BL | PB1100_G_CONTROL_VDD), |
| 153 | PB1100_G_CONTROL); | 147 | PB1100_G_CONTROL); |
| @@ -428,17 +422,6 @@ int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) | |||
| 428 | return 0; | 422 | return 0; |
| 429 | } | 423 | } |
| 430 | 424 | ||
| 431 | /* fb_cursor | ||
| 432 | * Used to disable cursor drawing... | ||
| 433 | */ | ||
| 434 | int au1100fb_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
| 435 | { | ||
| 436 | if (nocursor) | ||
| 437 | return 0; | ||
| 438 | else | ||
| 439 | return -EINVAL; /* just to force soft_cursor() call */ | ||
| 440 | } | ||
| 441 | |||
| 442 | static struct fb_ops au1100fb_ops = | 425 | static struct fb_ops au1100fb_ops = |
| 443 | { | 426 | { |
| 444 | .owner = THIS_MODULE, | 427 | .owner = THIS_MODULE, |
| @@ -450,13 +433,53 @@ static struct fb_ops au1100fb_ops = | |||
| 450 | .fb_imageblit = cfb_imageblit, | 433 | .fb_imageblit = cfb_imageblit, |
| 451 | .fb_rotate = au1100fb_fb_rotate, | 434 | .fb_rotate = au1100fb_fb_rotate, |
| 452 | .fb_mmap = au1100fb_fb_mmap, | 435 | .fb_mmap = au1100fb_fb_mmap, |
| 453 | .fb_cursor = au1100fb_fb_cursor, | ||
| 454 | }; | 436 | }; |
| 455 | 437 | ||
| 456 | 438 | ||
| 457 | /*-------------------------------------------------------------------------*/ | 439 | /*-------------------------------------------------------------------------*/ |
| 458 | 440 | ||
| 459 | /* AU1100 LCD controller device driver */ | 441 | static int au1100fb_setup(struct au1100fb_device *fbdev) |
| 442 | { | ||
| 443 | char *this_opt, *options; | ||
| 444 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
| 445 | |||
| 446 | if (num_panels <= 0) { | ||
| 447 | print_err("No LCD panels supported by driver!"); | ||
| 448 | return -ENODEV; | ||
| 449 | } | ||
| 450 | |||
| 451 | if (fb_get_options(DRIVER_NAME, &options)) | ||
| 452 | return -ENODEV; | ||
| 453 | if (!options) | ||
| 454 | return -ENODEV; | ||
| 455 | |||
| 456 | while ((this_opt = strsep(&options, ",")) != NULL) { | ||
| 457 | /* Panel option */ | ||
| 458 | if (!strncmp(this_opt, "panel:", 6)) { | ||
| 459 | int i; | ||
| 460 | this_opt += 6; | ||
| 461 | for (i = 0; i < num_panels; i++) { | ||
| 462 | if (!strncmp(this_opt, known_lcd_panels[i].name, | ||
| 463 | strlen(this_opt))) { | ||
| 464 | fbdev->panel = &known_lcd_panels[i]; | ||
| 465 | fbdev->panel_idx = i; | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | } | ||
| 469 | if (i >= num_panels) { | ||
| 470 | print_warn("Panel '%s' not supported!", this_opt); | ||
| 471 | return -ENODEV; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | /* Unsupported option */ | ||
| 475 | else | ||
| 476 | print_warn("Unsupported option \"%s\"", this_opt); | ||
| 477 | } | ||
| 478 | |||
| 479 | print_info("Panel=%s", fbdev->panel->name); | ||
| 480 | |||
| 481 | return 0; | ||
| 482 | } | ||
| 460 | 483 | ||
| 461 | static int __devinit au1100fb_drv_probe(struct platform_device *dev) | 484 | static int __devinit au1100fb_drv_probe(struct platform_device *dev) |
| 462 | { | 485 | { |
| @@ -465,22 +488,21 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) | |||
| 465 | unsigned long page; | 488 | unsigned long page; |
| 466 | u32 sys_clksrc; | 489 | u32 sys_clksrc; |
| 467 | 490 | ||
| 468 | if (!dev) | ||
| 469 | return -EINVAL; | ||
| 470 | |||
| 471 | /* Allocate new device private */ | 491 | /* Allocate new device private */ |
| 472 | if (!(fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL))) { | 492 | fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL); |
| 493 | if (!fbdev) { | ||
| 473 | print_err("fail to allocate device private record"); | 494 | print_err("fail to allocate device private record"); |
| 474 | return -ENOMEM; | 495 | return -ENOMEM; |
| 475 | } | 496 | } |
| 476 | 497 | ||
| 477 | fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; | 498 | if (au1100fb_setup(fbdev)) |
| 499 | goto failed; | ||
| 478 | 500 | ||
| 479 | platform_set_drvdata(dev, (void *)fbdev); | 501 | platform_set_drvdata(dev, (void *)fbdev); |
| 480 | 502 | ||
| 481 | /* Allocate region for our registers and map them */ | 503 | /* Allocate region for our registers and map them */ |
| 482 | if (!(regs_res = platform_get_resource(to_platform_device(dev), | 504 | regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
| 483 | IORESOURCE_MEM, 0))) { | 505 | if (!regs_res) { |
| 484 | print_err("fail to retrieve registers resource"); | 506 | print_err("fail to retrieve registers resource"); |
| 485 | return -EFAULT; | 507 | return -EFAULT; |
| 486 | } | 508 | } |
| @@ -500,13 +522,11 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) | |||
| 500 | print_dbg("Register memory map at %p", fbdev->regs); | 522 | print_dbg("Register memory map at %p", fbdev->regs); |
| 501 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); | 523 | print_dbg("phys=0x%08x, size=%d", fbdev->regs_phys, fbdev->regs_len); |
| 502 | 524 | ||
| 503 | |||
| 504 | |||
| 505 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ | 525 | /* Allocate the framebuffer to the maximum screen size * nbr of video buffers */ |
| 506 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * | 526 | fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * |
| 507 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; | 527 | (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; |
| 508 | 528 | ||
| 509 | fbdev->fb_mem = dma_alloc_coherent(dev, PAGE_ALIGN(fbdev->fb_len), | 529 | fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), |
| 510 | &fbdev->fb_phys, GFP_KERNEL); | 530 | &fbdev->fb_phys, GFP_KERNEL); |
| 511 | if (!fbdev->fb_mem) { | 531 | if (!fbdev->fb_mem) { |
| 512 | print_err("fail to allocate frambuffer (size: %dK))", | 532 | print_err("fail to allocate frambuffer (size: %dK))", |
| @@ -525,7 +545,7 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev) | |||
| 525 | page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); | 545 | page < PAGE_ALIGN((unsigned long)fbdev->fb_mem + fbdev->fb_len); |
| 526 | page += PAGE_SIZE) { | 546 | page += PAGE_SIZE) { |
| 527 | #if CONFIG_DMA_NONCOHERENT | 547 | #if CONFIG_DMA_NONCOHERENT |
| 528 | SetPageReserved(virt_to_page(CAC_ADDR(page))); | 548 | SetPageReserved(virt_to_page(CAC_ADDR((void *)page))); |
| 529 | #else | 549 | #else |
| 530 | SetPageReserved(virt_to_page(page)); | 550 | SetPageReserved(virt_to_page(page)); |
| 531 | #endif | 551 | #endif |
| @@ -578,7 +598,8 @@ failed: | |||
| 578 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | 598 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); |
| 579 | } | 599 | } |
| 580 | if (fbdev->fb_mem) { | 600 | if (fbdev->fb_mem) { |
| 581 | dma_free_noncoherent(dev, fbdev->fb_len, fbdev->fb_mem, fbdev->fb_phys); | 601 | dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, |
| 602 | fbdev->fb_phys); | ||
| 582 | } | 603 | } |
| 583 | if (fbdev->info.cmap.len != 0) { | 604 | if (fbdev->info.cmap.len != 0) { |
| 584 | fb_dealloc_cmap(&fbdev->info.cmap); | 605 | fb_dealloc_cmap(&fbdev->info.cmap); |
| @@ -608,7 +629,8 @@ int au1100fb_drv_remove(struct platform_device *dev) | |||
| 608 | 629 | ||
| 609 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); | 630 | release_mem_region(fbdev->regs_phys, fbdev->regs_len); |
| 610 | 631 | ||
| 611 | dma_free_coherent(dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); | 632 | dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, |
| 633 | fbdev->fb_phys); | ||
| 612 | 634 | ||
| 613 | fb_dealloc_cmap(&fbdev->info.cmap); | 635 | fb_dealloc_cmap(&fbdev->info.cmap); |
| 614 | kfree(fbdev->info.pseudo_palette); | 636 | kfree(fbdev->info.pseudo_palette); |
| @@ -675,101 +697,18 @@ static struct platform_driver au1100fb_driver = { | |||
| 675 | .resume = au1100fb_drv_resume, | 697 | .resume = au1100fb_drv_resume, |
| 676 | }; | 698 | }; |
| 677 | 699 | ||
| 678 | /*-------------------------------------------------------------------------*/ | 700 | static int __init au1100fb_load(void) |
| 679 | |||
| 680 | /* Kernel driver */ | ||
| 681 | |||
| 682 | int au1100fb_setup(char *options) | ||
| 683 | { | ||
| 684 | char* this_opt; | ||
| 685 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
| 686 | char* mode = NULL; | ||
| 687 | int panel_idx = 0; | ||
| 688 | |||
| 689 | if (num_panels <= 0) { | ||
| 690 | print_err("No LCD panels supported by driver!"); | ||
| 691 | return -EFAULT; | ||
| 692 | } | ||
| 693 | |||
| 694 | if (options) { | ||
| 695 | while ((this_opt = strsep(&options,",")) != NULL) { | ||
| 696 | /* Panel option */ | ||
| 697 | if (!strncmp(this_opt, "panel:", 6)) { | ||
| 698 | int i; | ||
| 699 | this_opt += 6; | ||
| 700 | for (i = 0; i < num_panels; i++) { | ||
| 701 | if (!strncmp(this_opt, | ||
| 702 | known_lcd_panels[i].name, | ||
| 703 | strlen(this_opt))) { | ||
| 704 | panel_idx = i; | ||
| 705 | break; | ||
| 706 | } | ||
| 707 | } | ||
| 708 | if (i >= num_panels) { | ||
| 709 | print_warn("Panel %s not supported!", this_opt); | ||
| 710 | } | ||
| 711 | } | ||
| 712 | if (!strncmp(this_opt, "nocursor", 8)) { | ||
| 713 | this_opt += 8; | ||
| 714 | nocursor = 1; | ||
| 715 | print_info("Cursor disabled"); | ||
| 716 | } | ||
| 717 | /* Mode option (only option that start with digit) */ | ||
| 718 | else if (isdigit(this_opt[0])) { | ||
| 719 | mode = kstrdup(this_opt, GFP_KERNEL); | ||
| 720 | if (!mode) { | ||
| 721 | print_err("memory allocation failed"); | ||
| 722 | return -ENOMEM; | ||
| 723 | } | ||
| 724 | } | ||
| 725 | /* Unsupported option */ | ||
| 726 | else { | ||
| 727 | print_warn("Unsupported option \"%s\"", this_opt); | ||
| 728 | } | ||
| 729 | } | ||
| 730 | } | ||
| 731 | |||
| 732 | drv_info.panel_idx = panel_idx; | ||
| 733 | drv_info.opt_mode = mode; | ||
| 734 | |||
| 735 | print_info("Panel=%s Mode=%s", | ||
| 736 | known_lcd_panels[drv_info.panel_idx].name, | ||
| 737 | drv_info.opt_mode ? drv_info.opt_mode : "default"); | ||
| 738 | |||
| 739 | return 0; | ||
| 740 | } | ||
| 741 | |||
| 742 | int __init au1100fb_init(void) | ||
| 743 | { | 701 | { |
| 744 | char* options; | ||
| 745 | int ret; | ||
| 746 | |||
| 747 | print_info("" DRIVER_DESC ""); | ||
| 748 | |||
| 749 | memset(&drv_info, 0, sizeof(drv_info)); | ||
| 750 | |||
| 751 | if (fb_get_options(DRIVER_NAME, &options)) | ||
| 752 | return -ENODEV; | ||
| 753 | |||
| 754 | /* Setup driver with options */ | ||
| 755 | ret = au1100fb_setup(options); | ||
| 756 | if (ret < 0) { | ||
| 757 | print_err("Fail to setup driver"); | ||
| 758 | return ret; | ||
| 759 | } | ||
| 760 | |||
| 761 | return platform_driver_register(&au1100fb_driver); | 702 | return platform_driver_register(&au1100fb_driver); |
| 762 | } | 703 | } |
| 763 | 704 | ||
| 764 | void __exit au1100fb_cleanup(void) | 705 | static void __exit au1100fb_unload(void) |
| 765 | { | 706 | { |
| 766 | platform_driver_unregister(&au1100fb_driver); | 707 | platform_driver_unregister(&au1100fb_driver); |
| 767 | |||
| 768 | kfree(drv_info.opt_mode); | ||
| 769 | } | 708 | } |
| 770 | 709 | ||
| 771 | module_init(au1100fb_init); | 710 | module_init(au1100fb_load); |
| 772 | module_exit(au1100fb_cleanup); | 711 | module_exit(au1100fb_unload); |
| 773 | 712 | ||
| 774 | MODULE_DESCRIPTION(DRIVER_DESC); | 713 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 775 | MODULE_LICENSE("GPL"); | 714 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/video/au1100fb.h b/drivers/video/au1100fb.h index 164fe2f231ec..12d9642d5465 100644 --- a/drivers/video/au1100fb.h +++ b/drivers/video/au1100fb.h | |||
| @@ -108,6 +108,7 @@ struct au1100fb_device { | |||
| 108 | unsigned char* fb_mem; /* FrameBuffer memory map */ | 108 | unsigned char* fb_mem; /* FrameBuffer memory map */ |
| 109 | size_t fb_len; | 109 | size_t fb_len; |
| 110 | dma_addr_t fb_phys; | 110 | dma_addr_t fb_phys; |
| 111 | int panel_idx; | ||
| 111 | }; | 112 | }; |
| 112 | 113 | ||
| 113 | /********************************************************************/ | 114 | /********************************************************************/ |
| @@ -364,11 +365,6 @@ static struct au1100fb_panel known_lcd_panels[] = | |||
| 364 | }, | 365 | }, |
| 365 | }; | 366 | }; |
| 366 | 367 | ||
| 367 | struct au1100fb_drv_info { | ||
| 368 | int panel_idx; | ||
| 369 | char *opt_mode; | ||
| 370 | }; | ||
| 371 | |||
| 372 | /********************************************************************/ | 368 | /********************************************************************/ |
| 373 | 369 | ||
| 374 | /* Inline helpers */ | 370 | /* Inline helpers */ |
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 5dff32ac8044..72005598040f 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c | |||
| @@ -46,18 +46,10 @@ | |||
| 46 | #include <asm/mach-au1x00/au1000.h> | 46 | #include <asm/mach-au1x00/au1000.h> |
| 47 | #include "au1200fb.h" | 47 | #include "au1200fb.h" |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_PM | ||
| 50 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
| 51 | #endif | ||
| 52 | |||
| 53 | #ifndef CONFIG_FB_AU1200_DEVS | ||
| 54 | #define CONFIG_FB_AU1200_DEVS 4 | ||
| 55 | #endif | ||
| 56 | |||
| 57 | #define DRIVER_NAME "au1200fb" | 49 | #define DRIVER_NAME "au1200fb" |
| 58 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" | 50 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" |
| 59 | 51 | ||
| 60 | #define DEBUG 1 | 52 | #define DEBUG 0 |
| 61 | 53 | ||
| 62 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | 54 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) |
| 63 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | 55 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) |
| @@ -150,7 +142,7 @@ struct au1200_lcd_iodata_t { | |||
| 150 | 142 | ||
| 151 | /* Private, per-framebuffer management information (independent of the panel itself) */ | 143 | /* Private, per-framebuffer management information (independent of the panel itself) */ |
| 152 | struct au1200fb_device { | 144 | struct au1200fb_device { |
| 153 | struct fb_info fb_info; /* FB driver info record */ | 145 | struct fb_info *fb_info; /* FB driver info record */ |
| 154 | 146 | ||
| 155 | int plane; | 147 | int plane; |
| 156 | unsigned char* fb_mem; /* FrameBuffer memory map */ | 148 | unsigned char* fb_mem; /* FrameBuffer memory map */ |
| @@ -158,7 +150,6 @@ struct au1200fb_device { | |||
| 158 | dma_addr_t fb_phys; | 150 | dma_addr_t fb_phys; |
| 159 | }; | 151 | }; |
| 160 | 152 | ||
| 161 | static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | ||
| 162 | /********************************************************************/ | 153 | /********************************************************************/ |
| 163 | 154 | ||
| 164 | /* LCD controller restrictions */ | 155 | /* LCD controller restrictions */ |
| @@ -171,10 +162,18 @@ static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | |||
| 171 | /* Default number of visible screen buffer to allocate */ | 162 | /* Default number of visible screen buffer to allocate */ |
| 172 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 | 163 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 |
| 173 | 164 | ||
| 165 | /* Default maximum number of fb devices to create */ | ||
| 166 | #define MAX_DEVICE_COUNT 4 | ||
| 167 | |||
| 168 | /* Default window configuration entry to use (see windows[]) */ | ||
| 169 | #define DEFAULT_WINDOW_INDEX 2 | ||
| 170 | |||
| 174 | /********************************************************************/ | 171 | /********************************************************************/ |
| 175 | 172 | ||
| 173 | static struct fb_info *_au1200fb_infos[MAX_DEVICE_COUNT]; | ||
| 176 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; | 174 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; |
| 177 | static int window_index = 2; /* default is zero */ | 175 | static int device_count = MAX_DEVICE_COUNT; |
| 176 | static int window_index = DEFAULT_WINDOW_INDEX; /* default is zero */ | ||
| 178 | static int panel_index = 2; /* default is zero */ | 177 | static int panel_index = 2; /* default is zero */ |
| 179 | static struct window_settings *win; | 178 | static struct window_settings *win; |
| 180 | static struct panel_settings *panel; | 179 | static struct panel_settings *panel; |
| @@ -205,12 +204,6 @@ struct window_settings { | |||
| 205 | extern int board_au1200fb_panel_init (void); | 204 | extern int board_au1200fb_panel_init (void); |
| 206 | extern int board_au1200fb_panel_shutdown (void); | 205 | extern int board_au1200fb_panel_shutdown (void); |
| 207 | 206 | ||
| 208 | #ifdef CONFIG_PM | ||
| 209 | int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 210 | au1xxx_request_t request, void *data); | ||
| 211 | au1xxx_power_dev_t *LCD_pm_dev; | ||
| 212 | #endif | ||
| 213 | |||
| 214 | /* | 207 | /* |
| 215 | * Default window configurations | 208 | * Default window configurations |
| 216 | */ | 209 | */ |
| @@ -652,25 +645,6 @@ static struct panel_settings known_lcd_panels[] = | |||
| 652 | 645 | ||
| 653 | /********************************************************************/ | 646 | /********************************************************************/ |
| 654 | 647 | ||
| 655 | #ifdef CONFIG_PM | ||
| 656 | static int set_brightness(unsigned int brightness) | ||
| 657 | { | ||
| 658 | unsigned int hi1, divider; | ||
| 659 | |||
| 660 | /* limit brightness pwm duty to >= 30/1600 */ | ||
| 661 | if (brightness < 30) { | ||
| 662 | brightness = 30; | ||
| 663 | } | ||
| 664 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 665 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 666 | hi1 = (((brightness & 0xFF) + 1) * divider >> 8); | ||
| 667 | lcd->pwmhi &= 0xFFFF; | ||
| 668 | lcd->pwmhi |= (hi1 << 16); | ||
| 669 | |||
| 670 | return brightness; | ||
| 671 | } | ||
| 672 | #endif /* CONFIG_PM */ | ||
| 673 | |||
| 674 | static int winbpp (unsigned int winctrl1) | 648 | static int winbpp (unsigned int winctrl1) |
| 675 | { | 649 | { |
| 676 | int bits = 0; | 650 | int bits = 0; |
| @@ -712,8 +686,8 @@ static int fbinfo2index (struct fb_info *fb_info) | |||
| 712 | { | 686 | { |
| 713 | int i; | 687 | int i; |
| 714 | 688 | ||
| 715 | for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { | 689 | for (i = 0; i < device_count; ++i) { |
| 716 | if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) | 690 | if (fb_info == _au1200fb_infos[i]) |
| 717 | return i; | 691 | return i; |
| 718 | } | 692 | } |
| 719 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); | 693 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); |
| @@ -962,7 +936,7 @@ static void au1200_setmode(struct au1200fb_device *fbdev) | |||
| 962 | lcd->window[plane].winctrl2 = ( 0 | 936 | lcd->window[plane].winctrl2 = ( 0 |
| 963 | | LCD_WINCTRL2_CKMODE_00 | 937 | | LCD_WINCTRL2_CKMODE_00 |
| 964 | | LCD_WINCTRL2_DBM | 938 | | LCD_WINCTRL2_DBM |
| 965 | | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | 939 | | LCD_WINCTRL2_BX_N(fbdev->fb_info->fix.line_length) |
| 966 | | LCD_WINCTRL2_SCX_1 | 940 | | LCD_WINCTRL2_SCX_1 |
| 967 | | LCD_WINCTRL2_SCY_1 | 941 | | LCD_WINCTRL2_SCY_1 |
| 968 | ) ; | 942 | ) ; |
| @@ -1050,7 +1024,7 @@ static void au1200fb_update_fbinfo(struct fb_info *fbi) | |||
| 1050 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | 1024 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, |
| 1051 | struct fb_info *fbi) | 1025 | struct fb_info *fbi) |
| 1052 | { | 1026 | { |
| 1053 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | 1027 | struct au1200fb_device *fbdev = fbi->par; |
| 1054 | u32 pixclock; | 1028 | u32 pixclock; |
| 1055 | int screen_size, plane; | 1029 | int screen_size, plane; |
| 1056 | 1030 | ||
| @@ -1142,7 +1116,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | |||
| 1142 | */ | 1116 | */ |
| 1143 | static int au1200fb_fb_set_par(struct fb_info *fbi) | 1117 | static int au1200fb_fb_set_par(struct fb_info *fbi) |
| 1144 | { | 1118 | { |
| 1145 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | 1119 | struct au1200fb_device *fbdev = fbi->par; |
| 1146 | 1120 | ||
| 1147 | au1200fb_update_fbinfo(fbi); | 1121 | au1200fb_update_fbinfo(fbi); |
| 1148 | au1200_setmode(fbdev); | 1122 | au1200_setmode(fbdev); |
| @@ -1246,11 +1220,7 @@ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | |||
| 1246 | { | 1220 | { |
| 1247 | unsigned int len; | 1221 | unsigned int len; |
| 1248 | unsigned long start=0, off; | 1222 | unsigned long start=0, off; |
| 1249 | struct au1200fb_device *fbdev = (struct au1200fb_device *) info; | 1223 | struct au1200fb_device *fbdev = info->par; |
| 1250 | |||
| 1251 | #ifdef CONFIG_PM | ||
| 1252 | au1xxx_pm_access(LCD_pm_dev); | ||
| 1253 | #endif | ||
| 1254 | 1224 | ||
| 1255 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | 1225 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { |
| 1256 | return -EINVAL; | 1226 | return -EINVAL; |
| @@ -1461,10 +1431,6 @@ static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 1461 | int plane; | 1431 | int plane; |
| 1462 | int val; | 1432 | int val; |
| 1463 | 1433 | ||
| 1464 | #ifdef CONFIG_PM | ||
| 1465 | au1xxx_pm_access(LCD_pm_dev); | ||
| 1466 | #endif | ||
| 1467 | |||
| 1468 | plane = fbinfo2index(info); | 1434 | plane = fbinfo2index(info); |
| 1469 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); | 1435 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); |
| 1470 | 1436 | ||
| @@ -1536,9 +1502,11 @@ static struct fb_ops au1200fb_fb_ops = { | |||
| 1536 | .fb_set_par = au1200fb_fb_set_par, | 1502 | .fb_set_par = au1200fb_fb_set_par, |
| 1537 | .fb_setcolreg = au1200fb_fb_setcolreg, | 1503 | .fb_setcolreg = au1200fb_fb_setcolreg, |
| 1538 | .fb_blank = au1200fb_fb_blank, | 1504 | .fb_blank = au1200fb_fb_blank, |
| 1539 | .fb_fillrect = cfb_fillrect, | 1505 | .fb_fillrect = sys_fillrect, |
| 1540 | .fb_copyarea = cfb_copyarea, | 1506 | .fb_copyarea = sys_copyarea, |
| 1541 | .fb_imageblit = cfb_imageblit, | 1507 | .fb_imageblit = sys_imageblit, |
| 1508 | .fb_read = fb_sys_read, | ||
| 1509 | .fb_write = fb_sys_write, | ||
| 1542 | .fb_sync = NULL, | 1510 | .fb_sync = NULL, |
| 1543 | .fb_ioctl = au1200fb_ioctl, | 1511 | .fb_ioctl = au1200fb_ioctl, |
| 1544 | .fb_mmap = au1200fb_fb_mmap, | 1512 | .fb_mmap = au1200fb_fb_mmap, |
| @@ -1561,10 +1529,9 @@ static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id) | |||
| 1561 | 1529 | ||
| 1562 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | 1530 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) |
| 1563 | { | 1531 | { |
| 1564 | struct fb_info *fbi = &fbdev->fb_info; | 1532 | struct fb_info *fbi = fbdev->fb_info; |
| 1565 | int bpp; | 1533 | int bpp; |
| 1566 | 1534 | ||
| 1567 | memset(fbi, 0, sizeof(struct fb_info)); | ||
| 1568 | fbi->fbops = &au1200fb_fb_ops; | 1535 | fbi->fbops = &au1200fb_fb_ops; |
| 1569 | 1536 | ||
| 1570 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); | 1537 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); |
| @@ -1623,24 +1590,36 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | |||
| 1623 | 1590 | ||
| 1624 | /* AU1200 LCD controller device driver */ | 1591 | /* AU1200 LCD controller device driver */ |
| 1625 | 1592 | ||
| 1626 | static int au1200fb_drv_probe(struct platform_device *dev) | 1593 | static int __devinit au1200fb_drv_probe(struct platform_device *dev) |
| 1627 | { | 1594 | { |
| 1628 | struct au1200fb_device *fbdev; | 1595 | struct au1200fb_device *fbdev; |
| 1596 | struct fb_info *fbi = NULL; | ||
| 1629 | unsigned long page; | 1597 | unsigned long page; |
| 1630 | int bpp, plane, ret; | 1598 | int bpp, plane, ret, irq; |
| 1631 | 1599 | ||
| 1632 | if (!dev) | 1600 | /* shut gcc up */ |
| 1633 | return -EINVAL; | 1601 | ret = 0; |
| 1602 | fbdev = NULL; | ||
| 1603 | |||
| 1604 | /* Kickstart the panel */ | ||
| 1605 | au1200_setpanel(panel); | ||
| 1634 | 1606 | ||
| 1635 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | 1607 | for (plane = 0; plane < device_count; ++plane) { |
| 1636 | bpp = winbpp(win->w[plane].mode_winctrl1); | 1608 | bpp = winbpp(win->w[plane].mode_winctrl1); |
| 1637 | if (win->w[plane].xres == 0) | 1609 | if (win->w[plane].xres == 0) |
| 1638 | win->w[plane].xres = panel->Xres; | 1610 | win->w[plane].xres = panel->Xres; |
| 1639 | if (win->w[plane].yres == 0) | 1611 | if (win->w[plane].yres == 0) |
| 1640 | win->w[plane].yres = panel->Yres; | 1612 | win->w[plane].yres = panel->Yres; |
| 1641 | 1613 | ||
| 1642 | fbdev = &_au1200fb_devices[plane]; | 1614 | fbi = framebuffer_alloc(sizeof(struct au1200fb_device), |
| 1643 | memset(fbdev, 0, sizeof(struct au1200fb_device)); | 1615 | &dev->dev); |
| 1616 | if (!fbi) | ||
| 1617 | goto failed; | ||
| 1618 | |||
| 1619 | _au1200fb_infos[plane] = fbi; | ||
| 1620 | fbdev = fbi->par; | ||
| 1621 | fbdev->fb_info = fbi; | ||
| 1622 | |||
| 1644 | fbdev->plane = plane; | 1623 | fbdev->plane = plane; |
| 1645 | 1624 | ||
| 1646 | /* Allocate the framebuffer to the maximum screen size */ | 1625 | /* Allocate the framebuffer to the maximum screen size */ |
| @@ -1673,30 +1652,31 @@ static int au1200fb_drv_probe(struct platform_device *dev) | |||
| 1673 | goto failed; | 1652 | goto failed; |
| 1674 | 1653 | ||
| 1675 | /* Register new framebuffer */ | 1654 | /* Register new framebuffer */ |
| 1676 | if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { | 1655 | ret = register_framebuffer(fbi); |
| 1656 | if (ret < 0) { | ||
| 1677 | print_err("cannot register new framebuffer"); | 1657 | print_err("cannot register new framebuffer"); |
| 1678 | goto failed; | 1658 | goto failed; |
| 1679 | } | 1659 | } |
| 1680 | 1660 | ||
| 1681 | au1200fb_fb_set_par(&fbdev->fb_info); | 1661 | au1200fb_fb_set_par(fbi); |
| 1682 | 1662 | ||
| 1683 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | 1663 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) |
| 1684 | if (plane == 0) | 1664 | if (plane == 0) |
| 1685 | if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { | 1665 | if (fb_prepare_logo(fbi, FB_ROTATE_UR)) { |
| 1686 | /* Start display and show logo on boot */ | 1666 | /* Start display and show logo on boot */ |
| 1687 | fb_set_cmap(&fbdev->fb_info.cmap, | 1667 | fb_set_cmap(&fbi->cmap, fbi); |
| 1688 | &fbdev->fb_info); | 1668 | fb_show_logo(fbi, FB_ROTATE_UR); |
| 1689 | |||
| 1690 | fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); | ||
| 1691 | } | 1669 | } |
| 1692 | #endif | 1670 | #endif |
| 1693 | } | 1671 | } |
| 1694 | 1672 | ||
| 1695 | /* Now hook interrupt too */ | 1673 | /* Now hook interrupt too */ |
| 1696 | if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, | 1674 | irq = platform_get_irq(dev, 0); |
| 1697 | IRQF_DISABLED | IRQF_SHARED, "lcd", (void *)dev)) < 0) { | 1675 | ret = request_irq(irq, au1200fb_handle_irq, |
| 1676 | IRQF_SHARED, "lcd", (void *)dev); | ||
| 1677 | if (ret) { | ||
| 1698 | print_err("fail to request interrupt line %d (err: %d)", | 1678 | print_err("fail to request interrupt line %d (err: %d)", |
| 1699 | AU1200_LCD_INT, ret); | 1679 | irq, ret); |
| 1700 | goto failed; | 1680 | goto failed; |
| 1701 | } | 1681 | } |
| 1702 | 1682 | ||
| @@ -1705,84 +1685,108 @@ static int au1200fb_drv_probe(struct platform_device *dev) | |||
| 1705 | failed: | 1685 | failed: |
| 1706 | /* NOTE: This only does the current plane/window that failed; others are still active */ | 1686 | /* NOTE: This only does the current plane/window that failed; others are still active */ |
| 1707 | if (fbdev->fb_mem) | 1687 | if (fbdev->fb_mem) |
| 1708 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | 1688 | dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), |
| 1709 | fbdev->fb_mem, fbdev->fb_phys); | 1689 | fbdev->fb_mem, fbdev->fb_phys); |
| 1710 | if (fbdev->fb_info.cmap.len != 0) | 1690 | if (fbi) { |
| 1711 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | 1691 | if (fbi->cmap.len != 0) |
| 1712 | if (fbdev->fb_info.pseudo_palette) | 1692 | fb_dealloc_cmap(&fbi->cmap); |
| 1713 | kfree(fbdev->fb_info.pseudo_palette); | 1693 | kfree(fbi->pseudo_palette); |
| 1694 | } | ||
| 1714 | if (plane == 0) | 1695 | if (plane == 0) |
| 1715 | free_irq(AU1200_LCD_INT, (void*)dev); | 1696 | free_irq(AU1200_LCD_INT, (void*)dev); |
| 1716 | return ret; | 1697 | return ret; |
| 1717 | } | 1698 | } |
| 1718 | 1699 | ||
| 1719 | static int au1200fb_drv_remove(struct platform_device *dev) | 1700 | static int __devexit au1200fb_drv_remove(struct platform_device *dev) |
| 1720 | { | 1701 | { |
| 1721 | struct au1200fb_device *fbdev; | 1702 | struct au1200fb_device *fbdev; |
| 1703 | struct fb_info *fbi; | ||
| 1722 | int plane; | 1704 | int plane; |
| 1723 | 1705 | ||
| 1724 | if (!dev) | ||
| 1725 | return -ENODEV; | ||
| 1726 | |||
| 1727 | /* Turn off the panel */ | 1706 | /* Turn off the panel */ |
| 1728 | au1200_setpanel(NULL); | 1707 | au1200_setpanel(NULL); |
| 1729 | 1708 | ||
| 1730 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) | 1709 | for (plane = 0; plane < device_count; ++plane) { |
| 1731 | { | 1710 | fbi = _au1200fb_infos[plane]; |
| 1732 | fbdev = &_au1200fb_devices[plane]; | 1711 | fbdev = fbi->par; |
| 1733 | 1712 | ||
| 1734 | /* Clean up all probe data */ | 1713 | /* Clean up all probe data */ |
| 1735 | unregister_framebuffer(&fbdev->fb_info); | 1714 | unregister_framebuffer(fbi); |
| 1736 | if (fbdev->fb_mem) | 1715 | if (fbdev->fb_mem) |
| 1737 | dma_free_noncoherent(&dev->dev, | 1716 | dma_free_noncoherent(&dev->dev, |
| 1738 | PAGE_ALIGN(fbdev->fb_len), | 1717 | PAGE_ALIGN(fbdev->fb_len), |
| 1739 | fbdev->fb_mem, fbdev->fb_phys); | 1718 | fbdev->fb_mem, fbdev->fb_phys); |
| 1740 | if (fbdev->fb_info.cmap.len != 0) | 1719 | if (fbi->cmap.len != 0) |
| 1741 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | 1720 | fb_dealloc_cmap(&fbi->cmap); |
| 1742 | if (fbdev->fb_info.pseudo_palette) | 1721 | kfree(fbi->pseudo_palette); |
| 1743 | kfree(fbdev->fb_info.pseudo_palette); | 1722 | |
| 1723 | framebuffer_release(fbi); | ||
| 1724 | _au1200fb_infos[plane] = NULL; | ||
| 1744 | } | 1725 | } |
| 1745 | 1726 | ||
| 1746 | free_irq(AU1200_LCD_INT, (void *)dev); | 1727 | free_irq(platform_get_irq(dev, 0), (void *)dev); |
| 1747 | 1728 | ||
| 1748 | return 0; | 1729 | return 0; |
| 1749 | } | 1730 | } |
| 1750 | 1731 | ||
| 1751 | #ifdef CONFIG_PM | 1732 | #ifdef CONFIG_PM |
| 1752 | static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) | 1733 | static int au1200fb_drv_suspend(struct device *dev) |
| 1753 | { | 1734 | { |
| 1754 | /* TODO */ | 1735 | au1200_setpanel(NULL); |
| 1736 | |||
| 1737 | lcd->outmask = 0; | ||
| 1738 | au_sync(); | ||
| 1739 | |||
| 1755 | return 0; | 1740 | return 0; |
| 1756 | } | 1741 | } |
| 1757 | 1742 | ||
| 1758 | static int au1200fb_drv_resume(struct platform_device *dev) | 1743 | static int au1200fb_drv_resume(struct device *dev) |
| 1759 | { | 1744 | { |
| 1760 | /* TODO */ | 1745 | struct fb_info *fbi; |
| 1746 | int i; | ||
| 1747 | |||
| 1748 | /* Kickstart the panel */ | ||
| 1749 | au1200_setpanel(panel); | ||
| 1750 | |||
| 1751 | for (i = 0; i < device_count; i++) { | ||
| 1752 | fbi = _au1200fb_infos[i]; | ||
| 1753 | au1200fb_fb_set_par(fbi); | ||
| 1754 | } | ||
| 1755 | |||
| 1761 | return 0; | 1756 | return 0; |
| 1762 | } | 1757 | } |
| 1758 | |||
| 1759 | static const struct dev_pm_ops au1200fb_pmops = { | ||
| 1760 | .suspend = au1200fb_drv_suspend, | ||
| 1761 | .resume = au1200fb_drv_resume, | ||
| 1762 | .freeze = au1200fb_drv_suspend, | ||
| 1763 | .thaw = au1200fb_drv_resume, | ||
| 1764 | }; | ||
| 1765 | |||
| 1766 | #define AU1200FB_PMOPS (&au1200fb_pmops) | ||
| 1767 | |||
| 1768 | #else | ||
| 1769 | #define AU1200FB_PMOPS NULL | ||
| 1763 | #endif /* CONFIG_PM */ | 1770 | #endif /* CONFIG_PM */ |
| 1764 | 1771 | ||
| 1765 | static struct platform_driver au1200fb_driver = { | 1772 | static struct platform_driver au1200fb_driver = { |
| 1766 | .driver = { | 1773 | .driver = { |
| 1767 | .name = "au1200-lcd", | 1774 | .name = "au1200-lcd", |
| 1768 | .owner = THIS_MODULE, | 1775 | .owner = THIS_MODULE, |
| 1776 | .pm = AU1200FB_PMOPS, | ||
| 1769 | }, | 1777 | }, |
| 1770 | .probe = au1200fb_drv_probe, | 1778 | .probe = au1200fb_drv_probe, |
| 1771 | .remove = au1200fb_drv_remove, | 1779 | .remove = __devexit_p(au1200fb_drv_remove), |
| 1772 | #ifdef CONFIG_PM | ||
| 1773 | .suspend = au1200fb_drv_suspend, | ||
| 1774 | .resume = au1200fb_drv_resume, | ||
| 1775 | #endif | ||
| 1776 | }; | 1780 | }; |
| 1777 | 1781 | ||
| 1778 | /*-------------------------------------------------------------------------*/ | 1782 | /*-------------------------------------------------------------------------*/ |
| 1779 | 1783 | ||
| 1780 | /* Kernel driver */ | 1784 | /* Kernel driver */ |
| 1781 | 1785 | ||
| 1782 | static void au1200fb_setup(void) | 1786 | static int au1200fb_setup(void) |
| 1783 | { | 1787 | { |
| 1784 | char* options = NULL; | 1788 | char *options = NULL; |
| 1785 | char* this_opt; | 1789 | char *this_opt, *endptr; |
| 1786 | int num_panels = ARRAY_SIZE(known_lcd_panels); | 1790 | int num_panels = ARRAY_SIZE(known_lcd_panels); |
| 1787 | int panel_idx = -1; | 1791 | int panel_idx = -1; |
| 1788 | 1792 | ||
| @@ -1827,70 +1831,42 @@ static void au1200fb_setup(void) | |||
| 1827 | nohwcursor = 1; | 1831 | nohwcursor = 1; |
| 1828 | } | 1832 | } |
| 1829 | 1833 | ||
| 1830 | /* Unsupported option */ | 1834 | else if (strncmp(this_opt, "devices:", 8) == 0) { |
| 1831 | else { | 1835 | this_opt += 8; |
| 1832 | print_warn("Unsupported option \"%s\"", this_opt); | 1836 | device_count = simple_strtol(this_opt, |
| 1837 | &endptr, 0); | ||
| 1838 | if ((device_count < 0) || | ||
| 1839 | (device_count > MAX_DEVICE_COUNT)) | ||
| 1840 | device_count = MAX_DEVICE_COUNT; | ||
| 1833 | } | 1841 | } |
| 1834 | } | ||
| 1835 | } | ||
| 1836 | } | ||
| 1837 | 1842 | ||
| 1838 | #ifdef CONFIG_PM | 1843 | else if (strncmp(this_opt, "wincfg:", 7) == 0) { |
| 1839 | static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | 1844 | this_opt += 7; |
| 1840 | au1xxx_request_t request, void *data) { | 1845 | window_index = simple_strtol(this_opt, |
| 1841 | int retval = -1; | 1846 | &endptr, 0); |
| 1842 | unsigned int d = 0; | 1847 | if ((window_index < 0) || |
| 1843 | unsigned int brightness = 0; | 1848 | (window_index >= ARRAY_SIZE(windows))) |
| 1844 | 1849 | window_index = DEFAULT_WINDOW_INDEX; | |
| 1845 | if (request == AU1XXX_PM_SLEEP) { | ||
| 1846 | board_au1200fb_panel_shutdown(); | ||
| 1847 | } | ||
| 1848 | else if (request == AU1XXX_PM_WAKEUP) { | ||
| 1849 | if(dev->prev_state == SLEEP_STATE) | ||
| 1850 | { | ||
| 1851 | int plane; | ||
| 1852 | au1200_setpanel(panel); | ||
| 1853 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 1854 | struct au1200fb_device *fbdev; | ||
| 1855 | fbdev = &_au1200fb_devices[plane]; | ||
| 1856 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 1857 | } | 1850 | } |
| 1858 | } | ||
| 1859 | 1851 | ||
| 1860 | d = *((unsigned int*)data); | 1852 | else if (strncmp(this_opt, "off", 3) == 0) |
| 1861 | if(d <=10) brightness = 26; | 1853 | return 1; |
| 1862 | else if(d<=20) brightness = 51; | 1854 | /* Unsupported option */ |
| 1863 | else if(d<=30) brightness = 77; | 1855 | else { |
| 1864 | else if(d<=40) brightness = 102; | 1856 | print_warn("Unsupported option \"%s\"", this_opt); |
| 1865 | else if(d<=50) brightness = 128; | 1857 | } |
| 1866 | else if(d<=60) brightness = 153; | ||
| 1867 | else if(d<=70) brightness = 179; | ||
| 1868 | else if(d<=80) brightness = 204; | ||
| 1869 | else if(d<=90) brightness = 230; | ||
| 1870 | else brightness = 255; | ||
| 1871 | set_brightness(brightness); | ||
| 1872 | } else if (request == AU1XXX_PM_GETSTATUS) { | ||
| 1873 | return dev->cur_state; | ||
| 1874 | } else if (request == AU1XXX_PM_ACCESS) { | ||
| 1875 | if (dev->cur_state != SLEEP_STATE) | ||
| 1876 | return retval; | ||
| 1877 | else { | ||
| 1878 | au1200_setpanel(panel); | ||
| 1879 | } | 1858 | } |
| 1880 | } else if (request == AU1XXX_PM_IDLE) { | ||
| 1881 | } else if (request == AU1XXX_PM_CLEANUP) { | ||
| 1882 | } | 1859 | } |
| 1883 | 1860 | return 0; | |
| 1884 | return retval; | ||
| 1885 | } | 1861 | } |
| 1886 | #endif | ||
| 1887 | 1862 | ||
| 1888 | static int __init au1200fb_init(void) | 1863 | static int __init au1200fb_init(void) |
| 1889 | { | 1864 | { |
| 1890 | print_info("" DRIVER_DESC ""); | 1865 | print_info("" DRIVER_DESC ""); |
| 1891 | 1866 | ||
| 1892 | /* Setup driver with options */ | 1867 | /* Setup driver with options */ |
| 1893 | au1200fb_setup(); | 1868 | if (au1200fb_setup()) |
| 1869 | return -ENODEV; | ||
| 1894 | 1870 | ||
| 1895 | /* Point to the panel selected */ | 1871 | /* Point to the panel selected */ |
| 1896 | panel = &known_lcd_panels[panel_index]; | 1872 | panel = &known_lcd_panels[panel_index]; |
| @@ -1899,17 +1875,6 @@ static int __init au1200fb_init(void) | |||
| 1899 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); | 1875 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); |
| 1900 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); | 1876 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); |
| 1901 | 1877 | ||
| 1902 | /* Kickstart the panel, the framebuffers/windows come soon enough */ | ||
| 1903 | au1200_setpanel(panel); | ||
| 1904 | |||
| 1905 | #ifdef CONFIG_PM | ||
| 1906 | LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); | ||
| 1907 | if ( LCD_pm_dev == NULL) | ||
| 1908 | printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); | ||
| 1909 | else | ||
| 1910 | printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); | ||
| 1911 | #endif | ||
| 1912 | |||
| 1913 | return platform_driver_register(&au1200fb_driver); | 1878 | return platform_driver_register(&au1200fb_driver); |
| 1914 | } | 1879 | } |
| 1915 | 1880 | ||
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index c04b94da81f7..1105fa1ed7f4 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
| 18 | #include <linux/backlight.h> | 18 | #include <linux/backlight.h> |
| 19 | #include <linux/mfd/88pm860x.h> | 19 | #include <linux/mfd/88pm860x.h> |
| 20 | #include <linux/module.h> | ||
| 20 | 21 | ||
| 21 | #define MAX_BRIGHTNESS (0xFF) | 22 | #define MAX_BRIGHTNESS (0xFF) |
| 22 | #define MIN_BRIGHTNESS (0) | 23 | #define MIN_BRIGHTNESS (0) |
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index d1aee730d7d8..dfb763e9147f 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/backlight.h> | 13 | #include <linux/backlight.h> |
| 14 | #include <linux/mfd/adp5520.h> | 14 | #include <linux/mfd/adp5520.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/module.h> | ||
| 16 | 17 | ||
| 17 | struct adp5520_bl { | 18 | struct adp5520_bl { |
| 18 | struct device *master; | 19 | struct device *master; |
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 183b6f639852..66bc74d9ce2a 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/version.h> | ||
| 11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 13 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index d06886a2bfb5..6c68a6899e87 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/version.h> | ||
| 11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
| 12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 13 | #include <linux/pm.h> | 12 | #include <linux/pm.h> |
| @@ -932,7 +931,6 @@ out: | |||
| 932 | out1: | 931 | out1: |
| 933 | backlight_device_unregister(bl); | 932 | backlight_device_unregister(bl); |
| 934 | out2: | 933 | out2: |
| 935 | i2c_set_clientdata(client, NULL); | ||
| 936 | kfree(data); | 934 | kfree(data); |
| 937 | 935 | ||
| 938 | return ret; | 936 | return ret; |
| @@ -952,7 +950,6 @@ static int __devexit adp8870_remove(struct i2c_client *client) | |||
| 952 | &adp8870_bl_attr_group); | 950 | &adp8870_bl_attr_group); |
| 953 | 951 | ||
| 954 | backlight_device_unregister(data->bl); | 952 | backlight_device_unregister(data->bl); |
| 955 | i2c_set_clientdata(client, NULL); | ||
| 956 | kfree(data); | 953 | kfree(data); |
| 957 | 954 | ||
| 958 | return 0; | 955 | return 0; |
diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index 9f0a491e2a05..7838a23fbdd1 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #include <linux/wait.h> | 24 | #include <linux/wait.h> |
| 25 | #include <linux/module.h> | ||
| 25 | #include <linux/fb.h> | 26 | #include <linux/fb.h> |
| 26 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 27 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 80d292fb92d8..7363c1b169e8 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <asm/backlight.h> | 19 | #include <asm/backlight.h> |
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | static const char const *backlight_types[] = { | 22 | static const char *const backlight_types[] = { |
| 23 | [BACKLIGHT_RAW] = "raw", | 23 | [BACKLIGHT_RAW] = "raw", |
| 24 | [BACKLIGHT_PLATFORM] = "platform", | 24 | [BACKLIGHT_PLATFORM] = "platform", |
| 25 | [BACKLIGHT_FIRMWARE] = "firmware", | 25 | [BACKLIGHT_FIRMWARE] = "firmware", |
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 62043f12a5a4..d68f14bbb687 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/backlight.h> | 19 | #include <linux/backlight.h> |
| 20 | #include <linux/mfd/da903x.h> | 20 | #include <linux/mfd/da903x.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/module.h> | ||
| 22 | 23 | ||
| 23 | #define DA9030_WLED_CONTROL 0x25 | 24 | #define DA9030_WLED_CONTROL 0x25 |
| 24 | #define DA9030_WLED_CP_EN (1 << 6) | 25 | #define DA9030_WLED_CP_EN (1 << 6) |
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index b0582917f0c8..c74a6f4baa12 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| 16 | #include <linux/module.h> | ||
| 16 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 17 | #include <linux/fb.h> | 18 | #include <linux/fb.h> |
| 18 | #include <linux/backlight.h> | 19 | #include <linux/backlight.h> |
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index 8c6befd65a33..adb191466d64 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c | |||
| @@ -56,7 +56,7 @@ static int genericbl_get_intensity(struct backlight_device *bd) | |||
| 56 | * Called when the battery is low to limit the backlight intensity. | 56 | * Called when the battery is low to limit the backlight intensity. |
| 57 | * If limit==0 clear any limit, otherwise limit the intensity | 57 | * If limit==0 clear any limit, otherwise limit the intensity |
| 58 | */ | 58 | */ |
| 59 | void corgibl_limit_intensity(int limit) | 59 | void genericbl_limit_intensity(int limit) |
| 60 | { | 60 | { |
| 61 | struct backlight_device *bd = generic_backlight_device; | 61 | struct backlight_device *bd = generic_backlight_device; |
| 62 | 62 | ||
| @@ -68,7 +68,7 @@ void corgibl_limit_intensity(int limit) | |||
| 68 | backlight_update_status(generic_backlight_device); | 68 | backlight_update_status(generic_backlight_device); |
| 69 | mutex_unlock(&bd->ops_lock); | 69 | mutex_unlock(&bd->ops_lock); |
| 70 | } | 70 | } |
| 71 | EXPORT_SYMBOL(corgibl_limit_intensity); | 71 | EXPORT_SYMBOL(genericbl_limit_intensity); |
| 72 | 72 | ||
| 73 | static const struct backlight_ops genericbl_ops = { | 73 | static const struct backlight_ops genericbl_ops = { |
| 74 | .options = BL_CORE_SUSPENDRESUME, | 74 | .options = BL_CORE_SUSPENDRESUME, |
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index 98ad3e5f7c85..4f5d1c4cb6ab 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <linux/module.h> | ||
| 17 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
| 18 | #include <linux/lcd.h> | 19 | #include <linux/lcd.h> |
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| @@ -52,15 +53,11 @@ static void l4f00242t03_lcd_init(struct spi_device *spi) | |||
| 52 | 53 | ||
| 53 | dev_dbg(&spi->dev, "initializing LCD\n"); | 54 | dev_dbg(&spi->dev, "initializing LCD\n"); |
| 54 | 55 | ||
| 55 | if (priv->io_reg) { | 56 | regulator_set_voltage(priv->io_reg, 1800000, 1800000); |
| 56 | regulator_set_voltage(priv->io_reg, 1800000, 1800000); | 57 | regulator_enable(priv->io_reg); |
| 57 | regulator_enable(priv->io_reg); | ||
| 58 | } | ||
| 59 | 58 | ||
| 60 | if (priv->core_reg) { | 59 | regulator_set_voltage(priv->core_reg, 2800000, 2800000); |
| 61 | regulator_set_voltage(priv->core_reg, 2800000, 2800000); | 60 | regulator_enable(priv->core_reg); |
| 62 | regulator_enable(priv->core_reg); | ||
| 63 | } | ||
| 64 | 61 | ||
| 65 | l4f00242t03_reset(pdata->reset_gpio); | 62 | l4f00242t03_reset(pdata->reset_gpio); |
| 66 | 63 | ||
| @@ -78,11 +75,8 @@ static void l4f00242t03_lcd_powerdown(struct spi_device *spi) | |||
| 78 | 75 | ||
| 79 | gpio_set_value(pdata->data_enable_gpio, 0); | 76 | gpio_set_value(pdata->data_enable_gpio, 0); |
| 80 | 77 | ||
| 81 | if (priv->io_reg) | 78 | regulator_disable(priv->io_reg); |
| 82 | regulator_disable(priv->io_reg); | 79 | regulator_disable(priv->core_reg); |
| 83 | |||
| 84 | if (priv->core_reg) | ||
| 85 | regulator_disable(priv->core_reg); | ||
| 86 | } | 80 | } |
| 87 | 81 | ||
| 88 | static int l4f00242t03_lcd_power_get(struct lcd_device *ld) | 82 | static int l4f00242t03_lcd_power_get(struct lcd_device *ld) |
| @@ -178,47 +172,34 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
| 178 | 172 | ||
| 179 | priv->spi = spi; | 173 | priv->spi = spi; |
| 180 | 174 | ||
| 181 | ret = gpio_request(pdata->reset_gpio, "lcd l4f00242t03 reset"); | 175 | ret = gpio_request_one(pdata->reset_gpio, GPIOF_OUT_INIT_HIGH, |
| 176 | "lcd l4f00242t03 reset"); | ||
| 182 | if (ret) { | 177 | if (ret) { |
| 183 | dev_err(&spi->dev, | 178 | dev_err(&spi->dev, |
| 184 | "Unable to get the lcd l4f00242t03 reset gpio.\n"); | 179 | "Unable to get the lcd l4f00242t03 reset gpio.\n"); |
| 185 | goto err; | 180 | goto err; |
| 186 | } | 181 | } |
| 187 | 182 | ||
| 188 | ret = gpio_direction_output(pdata->reset_gpio, 1); | 183 | ret = gpio_request_one(pdata->data_enable_gpio, GPIOF_OUT_INIT_LOW, |
| 189 | if (ret) | 184 | "lcd l4f00242t03 data enable"); |
| 190 | goto err2; | ||
| 191 | |||
| 192 | ret = gpio_request(pdata->data_enable_gpio, | ||
| 193 | "lcd l4f00242t03 data enable"); | ||
| 194 | if (ret) { | 185 | if (ret) { |
| 195 | dev_err(&spi->dev, | 186 | dev_err(&spi->dev, |
| 196 | "Unable to get the lcd l4f00242t03 data en gpio.\n"); | 187 | "Unable to get the lcd l4f00242t03 data en gpio.\n"); |
| 197 | goto err2; | 188 | goto err2; |
| 198 | } | 189 | } |
| 199 | 190 | ||
| 200 | ret = gpio_direction_output(pdata->data_enable_gpio, 0); | 191 | priv->io_reg = regulator_get(&spi->dev, "vdd"); |
| 201 | if (ret) | 192 | if (IS_ERR(priv->io_reg)) { |
| 193 | dev_err(&spi->dev, "%s: Unable to get the IO regulator\n", | ||
| 194 | __func__); | ||
| 202 | goto err3; | 195 | goto err3; |
| 203 | |||
| 204 | if (pdata->io_supply) { | ||
| 205 | priv->io_reg = regulator_get(NULL, pdata->io_supply); | ||
| 206 | |||
| 207 | if (IS_ERR(priv->io_reg)) { | ||
| 208 | pr_err("%s: Unable to get the IO regulator\n", | ||
| 209 | __func__); | ||
| 210 | goto err3; | ||
| 211 | } | ||
| 212 | } | 196 | } |
| 213 | 197 | ||
| 214 | if (pdata->core_supply) { | 198 | priv->core_reg = regulator_get(&spi->dev, "vcore"); |
| 215 | priv->core_reg = regulator_get(NULL, pdata->core_supply); | 199 | if (IS_ERR(priv->core_reg)) { |
| 216 | 200 | dev_err(&spi->dev, "%s: Unable to get the core regulator\n", | |
| 217 | if (IS_ERR(priv->core_reg)) { | 201 | __func__); |
| 218 | pr_err("%s: Unable to get the core regulator\n", | 202 | goto err4; |
| 219 | __func__); | ||
| 220 | goto err4; | ||
| 221 | } | ||
| 222 | } | 203 | } |
| 223 | 204 | ||
| 224 | priv->ld = lcd_device_register("l4f00242t03", | 205 | priv->ld = lcd_device_register("l4f00242t03", |
| @@ -238,11 +219,9 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
| 238 | return 0; | 219 | return 0; |
| 239 | 220 | ||
| 240 | err5: | 221 | err5: |
| 241 | if (priv->core_reg) | 222 | regulator_put(priv->core_reg); |
| 242 | regulator_put(priv->core_reg); | ||
| 243 | err4: | 223 | err4: |
| 244 | if (priv->io_reg) | 224 | regulator_put(priv->io_reg); |
| 245 | regulator_put(priv->io_reg); | ||
| 246 | err3: | 225 | err3: |
| 247 | gpio_free(pdata->data_enable_gpio); | 226 | gpio_free(pdata->data_enable_gpio); |
| 248 | err2: | 227 | err2: |
| @@ -266,10 +245,8 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi) | |||
| 266 | gpio_free(pdata->data_enable_gpio); | 245 | gpio_free(pdata->data_enable_gpio); |
| 267 | gpio_free(pdata->reset_gpio); | 246 | gpio_free(pdata->reset_gpio); |
| 268 | 247 | ||
| 269 | if (priv->io_reg) | 248 | regulator_put(priv->io_reg); |
| 270 | regulator_put(priv->io_reg); | 249 | regulator_put(priv->core_reg); |
| 271 | if (priv->core_reg) | ||
| 272 | regulator_put(priv->core_reg); | ||
| 273 | 250 | ||
| 274 | kfree(priv); | 251 | kfree(priv); |
| 275 | 252 | ||
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c index 5934655eb1ff..da9a5ce0ccb8 100644 --- a/drivers/video/backlight/ld9040.c +++ b/drivers/video/backlight/ld9040.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/lcd.h> | 31 | #include <linux/lcd.h> |
| 32 | #include <linux/backlight.h> | 32 | #include <linux/backlight.h> |
| 33 | #include <linux/module.h> | ||
| 33 | 34 | ||
| 34 | #include "ld9040_gamma.h" | 35 | #include "ld9040_gamma.h" |
| 35 | 36 | ||
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 5d3cf33953ac..4ec78cfe26ea 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
| 19 | #include <linux/spi/lms283gf05.h> | 19 | #include <linux/spi/lms283gf05.h> |
| 20 | #include <linux/module.h> | ||
| 20 | 21 | ||
| 21 | struct lms283gf05_state { | 22 | struct lms283gf05_state { |
| 22 | struct spi_device *spi; | 23 | struct spi_device *spi; |
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index 07e8e273ced0..7bbc802560ea 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/backlight.h> | 17 | #include <linux/backlight.h> |
| 18 | #include <linux/mfd/max8925.h> | 18 | #include <linux/mfd/max8925.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/module.h> | ||
| 20 | 21 | ||
| 21 | #define MAX_BRIGHTNESS (0xff) | 22 | #define MAX_BRIGHTNESS (0xff) |
| 22 | #define MIN_BRIGHTNESS (0) | 23 | #define MIN_BRIGHTNESS (0) |
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 694e5aab0d69..e132157d8545 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
| 31 | #include <linux/lcd.h> | 31 | #include <linux/lcd.h> |
| 32 | #include <linux/backlight.h> | 32 | #include <linux/backlight.h> |
| 33 | #include <linux/module.h> | ||
| 33 | 34 | ||
| 34 | #include "s6e63m0_gamma.h" | 35 | #include "s6e63m0_gamma.h" |
| 35 | 36 | ||
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c index d4c6eb248ff9..fbe9e9316f3b 100644 --- a/drivers/video/backlight/wm831x_bl.c +++ b/drivers/video/backlight/wm831x_bl.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
| 14 | #include <linux/module.h> | ||
| 14 | #include <linux/fb.h> | 15 | #include <linux/fb.h> |
| 15 | #include <linux/backlight.h> | 16 | #include <linux/backlight.h> |
| 16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 2464b910b590..56720fb476b3 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
| @@ -633,7 +633,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev) | |||
| 633 | goto out7; | 633 | goto out7; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | if (request_irq(info->irq, bfin_bf54x_irq_error, IRQF_DISABLED, | 636 | if (request_irq(info->irq, bfin_bf54x_irq_error, 0, |
| 637 | "PPI ERROR", info) < 0) { | 637 | "PPI ERROR", info) < 0) { |
| 638 | printk(KERN_ERR DRIVER_NAME | 638 | printk(KERN_ERR DRIVER_NAME |
| 639 | ": unable to request PPI ERROR IRQ\n"); | 639 | ": unable to request PPI ERROR IRQ\n"); |
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c index 23b6c4b62c78..c633068372c9 100644 --- a/drivers/video/bfin-lq035q1-fb.c +++ b/drivers/video/bfin-lq035q1-fb.c | |||
| @@ -695,7 +695,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev) | |||
| 695 | goto out7; | 695 | goto out7; |
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | ret = request_irq(info->irq, bfin_lq035q1_irq_error, IRQF_DISABLED, | 698 | ret = request_irq(info->irq, bfin_lq035q1_irq_error, 0, |
| 699 | DRIVER_NAME" PPI ERROR", info); | 699 | DRIVER_NAME" PPI ERROR", info); |
| 700 | if (ret < 0) { | 700 | if (ret < 0) { |
| 701 | dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); | 701 | dev_err(&pdev->dev, "unable to request PPI ERROR IRQ\n"); |
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index d8de29f0dd8d..d5e126759612 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c | |||
| @@ -529,7 +529,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) | |||
| 529 | goto out7; | 529 | goto out7; |
| 530 | } | 530 | } |
| 531 | 531 | ||
| 532 | ret = request_irq(info->irq, bfin_t350mcqb_irq_error, IRQF_DISABLED, | 532 | ret = request_irq(info->irq, bfin_t350mcqb_irq_error, 0, |
| 533 | "PPI ERROR", info); | 533 | "PPI ERROR", info); |
| 534 | if (ret < 0) { | 534 | if (ret < 0) { |
| 535 | printk(KERN_ERR DRIVER_NAME | 535 | printk(KERN_ERR DRIVER_NAME |
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c index 8486f541156b..811dd7f6aa41 100644 --- a/drivers/video/bfin_adv7393fb.c +++ b/drivers/video/bfin_adv7393fb.c | |||
| @@ -481,7 +481,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client, | |||
| 481 | goto out_4; | 481 | goto out_4; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, IRQF_DISABLED, | 484 | if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0, |
| 485 | "PPI ERROR", fbdev) < 0) { | 485 | "PPI ERROR", fbdev) < 0) { |
| 486 | dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); | 486 | dev_err(&client->dev, "unable to request PPI ERROR IRQ\n"); |
| 487 | ret = -EFAULT; | 487 | ret = -EFAULT; |
diff --git a/drivers/video/carminefb.c b/drivers/video/carminefb.c index caaa27d4a46a..2c76fdf23f2a 100644 --- a/drivers/video/carminefb.c +++ b/drivers/video/carminefb.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/module.h> | ||
| 15 | 16 | ||
| 16 | #include "carminefb.h" | 17 | #include "carminefb.h" |
| 17 | #include "carminefb_regs.h" | 18 | #include "carminefb_regs.h" |
| @@ -32,11 +33,11 @@ | |||
| 32 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 | 33 | #define CARMINEFB_DEFAULT_VIDEO_MODE 1 |
| 33 | 34 | ||
| 34 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; | 35 | static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE; |
| 35 | module_param(fb_mode, uint, 444); | 36 | module_param(fb_mode, uint, 0444); |
| 36 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); | 37 | MODULE_PARM_DESC(fb_mode, "Initial video mode as integer."); |
| 37 | 38 | ||
| 38 | static char *fb_mode_str; | 39 | static char *fb_mode_str; |
| 39 | module_param(fb_mode_str, charp, 444); | 40 | module_param(fb_mode_str, charp, 0444); |
| 40 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | 41 | MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); |
| 41 | 42 | ||
| 42 | /* | 43 | /* |
| @@ -46,7 +47,7 @@ MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters."); | |||
| 46 | * 0b010 Display 1 | 47 | * 0b010 Display 1 |
| 47 | */ | 48 | */ |
| 48 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; | 49 | static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1; |
| 49 | module_param(fb_displays, int, 444); | 50 | module_param(fb_displays, int, 0444); |
| 50 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); | 51 | MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used"); |
| 51 | 52 | ||
| 52 | struct carmine_hw { | 53 | struct carmine_hw { |
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index e02764319ff7..f56699d8122a 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
| 25 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
| 26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 27 | #include <linux/module.h> | ||
| 27 | 28 | ||
| 28 | /* | 29 | /* |
| 29 | * Cursor position address | 30 | * Cursor position address |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 915fd74da7a2..d449a74d4a31 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
| @@ -50,7 +50,7 @@ | |||
| 50 | #include <video/vga.h> | 50 | #include <video/vga.h> |
| 51 | #include <asm/io.h> | 51 | #include <asm/io.h> |
| 52 | 52 | ||
| 53 | static DEFINE_SPINLOCK(vga_lock); | 53 | static DEFINE_RAW_SPINLOCK(vga_lock); |
| 54 | static int cursor_size_lastfrom; | 54 | static int cursor_size_lastfrom; |
| 55 | static int cursor_size_lastto; | 55 | static int cursor_size_lastto; |
| 56 | static u32 vgacon_xres; | 56 | static u32 vgacon_xres; |
| @@ -157,7 +157,7 @@ static inline void write_vga(unsigned char reg, unsigned int val) | |||
| 157 | * ddprintk might set the console position from interrupt | 157 | * ddprintk might set the console position from interrupt |
| 158 | * handlers, thus the write has to be IRQ-atomic. | 158 | * handlers, thus the write has to be IRQ-atomic. |
| 159 | */ | 159 | */ |
| 160 | spin_lock_irqsave(&vga_lock, flags); | 160 | raw_spin_lock_irqsave(&vga_lock, flags); |
| 161 | 161 | ||
| 162 | #ifndef SLOW_VGA | 162 | #ifndef SLOW_VGA |
| 163 | v1 = reg + (val & 0xff00); | 163 | v1 = reg + (val & 0xff00); |
| @@ -170,7 +170,7 @@ static inline void write_vga(unsigned char reg, unsigned int val) | |||
| 170 | outb_p(reg + 1, vga_video_port_reg); | 170 | outb_p(reg + 1, vga_video_port_reg); |
| 171 | outb_p(val & 0xff, vga_video_port_val); | 171 | outb_p(val & 0xff, vga_video_port_val); |
| 172 | #endif | 172 | #endif |
| 173 | spin_unlock_irqrestore(&vga_lock, flags); | 173 | raw_spin_unlock_irqrestore(&vga_lock, flags); |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | static inline void vga_set_mem_top(struct vc_data *c) | 176 | static inline void vga_set_mem_top(struct vc_data *c) |
| @@ -664,7 +664,7 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) | |||
| 664 | cursor_size_lastfrom = from; | 664 | cursor_size_lastfrom = from; |
| 665 | cursor_size_lastto = to; | 665 | cursor_size_lastto = to; |
| 666 | 666 | ||
| 667 | spin_lock_irqsave(&vga_lock, flags); | 667 | raw_spin_lock_irqsave(&vga_lock, flags); |
| 668 | if (vga_video_type >= VIDEO_TYPE_VGAC) { | 668 | if (vga_video_type >= VIDEO_TYPE_VGAC) { |
| 669 | outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); | 669 | outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); |
| 670 | curs = inb_p(vga_video_port_val); | 670 | curs = inb_p(vga_video_port_val); |
| @@ -682,7 +682,7 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) | |||
| 682 | outb_p(curs, vga_video_port_val); | 682 | outb_p(curs, vga_video_port_val); |
| 683 | outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); | 683 | outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); |
| 684 | outb_p(cure, vga_video_port_val); | 684 | outb_p(cure, vga_video_port_val); |
| 685 | spin_unlock_irqrestore(&vga_lock, flags); | 685 | raw_spin_unlock_irqrestore(&vga_lock, flags); |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | static void vgacon_cursor(struct vc_data *c, int mode) | 688 | static void vgacon_cursor(struct vc_data *c, int mode) |
| @@ -757,7 +757,7 @@ static int vgacon_doresize(struct vc_data *c, | |||
| 757 | unsigned int scanlines = height * c->vc_font.height; | 757 | unsigned int scanlines = height * c->vc_font.height; |
| 758 | u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan; | 758 | u8 scanlines_lo = 0, r7 = 0, vsync_end = 0, mode, max_scan; |
| 759 | 759 | ||
| 760 | spin_lock_irqsave(&vga_lock, flags); | 760 | raw_spin_lock_irqsave(&vga_lock, flags); |
| 761 | 761 | ||
| 762 | vgacon_xres = width * VGA_FONTWIDTH; | 762 | vgacon_xres = width * VGA_FONTWIDTH; |
| 763 | vgacon_yres = height * c->vc_font.height; | 763 | vgacon_yres = height * c->vc_font.height; |
| @@ -808,7 +808,7 @@ static int vgacon_doresize(struct vc_data *c, | |||
| 808 | outb_p(vsync_end, vga_video_port_val); | 808 | outb_p(vsync_end, vga_video_port_val); |
| 809 | } | 809 | } |
| 810 | 810 | ||
| 811 | spin_unlock_irqrestore(&vga_lock, flags); | 811 | raw_spin_unlock_irqrestore(&vga_lock, flags); |
| 812 | return 0; | 812 | return 0; |
| 813 | } | 813 | } |
| 814 | 814 | ||
| @@ -891,11 +891,11 @@ static void vga_vesa_blank(struct vgastate *state, int mode) | |||
| 891 | { | 891 | { |
| 892 | /* save original values of VGA controller registers */ | 892 | /* save original values of VGA controller registers */ |
| 893 | if (!vga_vesa_blanked) { | 893 | if (!vga_vesa_blanked) { |
| 894 | spin_lock_irq(&vga_lock); | 894 | raw_spin_lock_irq(&vga_lock); |
| 895 | vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I); | 895 | vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I); |
| 896 | vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg); | 896 | vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg); |
| 897 | vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R); | 897 | vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R); |
| 898 | spin_unlock_irq(&vga_lock); | 898 | raw_spin_unlock_irq(&vga_lock); |
| 899 | 899 | ||
| 900 | outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ | 900 | outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ |
| 901 | vga_state.HorizontalTotal = inb_p(vga_video_port_val); | 901 | vga_state.HorizontalTotal = inb_p(vga_video_port_val); |
| @@ -918,7 +918,7 @@ static void vga_vesa_blank(struct vgastate *state, int mode) | |||
| 918 | 918 | ||
| 919 | /* assure that video is enabled */ | 919 | /* assure that video is enabled */ |
| 920 | /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ | 920 | /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ |
| 921 | spin_lock_irq(&vga_lock); | 921 | raw_spin_lock_irq(&vga_lock); |
| 922 | vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20); | 922 | vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20); |
| 923 | 923 | ||
| 924 | /* test for vertical retrace in process.... */ | 924 | /* test for vertical retrace in process.... */ |
| @@ -954,13 +954,13 @@ static void vga_vesa_blank(struct vgastate *state, int mode) | |||
| 954 | /* restore both index registers */ | 954 | /* restore both index registers */ |
| 955 | vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); | 955 | vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); |
| 956 | outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); | 956 | outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); |
| 957 | spin_unlock_irq(&vga_lock); | 957 | raw_spin_unlock_irq(&vga_lock); |
| 958 | } | 958 | } |
| 959 | 959 | ||
| 960 | static void vga_vesa_unblank(struct vgastate *state) | 960 | static void vga_vesa_unblank(struct vgastate *state) |
| 961 | { | 961 | { |
| 962 | /* restore original values of VGA controller registers */ | 962 | /* restore original values of VGA controller registers */ |
| 963 | spin_lock_irq(&vga_lock); | 963 | raw_spin_lock_irq(&vga_lock); |
| 964 | vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO); | 964 | vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO); |
| 965 | 965 | ||
| 966 | outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ | 966 | outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ |
| @@ -985,7 +985,7 @@ static void vga_vesa_unblank(struct vgastate *state) | |||
| 985 | /* restore index/control registers */ | 985 | /* restore index/control registers */ |
| 986 | vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); | 986 | vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); |
| 987 | outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); | 987 | outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); |
| 988 | spin_unlock_irq(&vga_lock); | 988 | raw_spin_unlock_irq(&vga_lock); |
| 989 | } | 989 | } |
| 990 | 990 | ||
| 991 | static void vga_pal_blank(struct vgastate *state) | 991 | static void vga_pal_blank(struct vgastate *state) |
| @@ -1104,7 +1104,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
| 1104 | charmap += 4 * cmapsz; | 1104 | charmap += 4 * cmapsz; |
| 1105 | #endif | 1105 | #endif |
| 1106 | 1106 | ||
| 1107 | spin_lock_irq(&vga_lock); | 1107 | raw_spin_lock_irq(&vga_lock); |
| 1108 | /* First, the Sequencer */ | 1108 | /* First, the Sequencer */ |
| 1109 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); | 1109 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
| 1110 | /* CPU writes only to map 2 */ | 1110 | /* CPU writes only to map 2 */ |
| @@ -1120,7 +1120,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
| 1120 | vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00); | 1120 | vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x00); |
| 1121 | /* map start at A000:0000 */ | 1121 | /* map start at A000:0000 */ |
| 1122 | vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00); | 1122 | vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x00); |
| 1123 | spin_unlock_irq(&vga_lock); | 1123 | raw_spin_unlock_irq(&vga_lock); |
| 1124 | 1124 | ||
| 1125 | if (arg) { | 1125 | if (arg) { |
| 1126 | if (set) | 1126 | if (set) |
| @@ -1147,7 +1147,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
| 1147 | } | 1147 | } |
| 1148 | } | 1148 | } |
| 1149 | 1149 | ||
| 1150 | spin_lock_irq(&vga_lock); | 1150 | raw_spin_lock_irq(&vga_lock); |
| 1151 | /* First, the sequencer, Synchronous reset */ | 1151 | /* First, the sequencer, Synchronous reset */ |
| 1152 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01); | 1152 | vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01); |
| 1153 | /* CPU writes to maps 0 and 1 */ | 1153 | /* CPU writes to maps 0 and 1 */ |
| @@ -1186,7 +1186,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
| 1186 | inb_p(video_port_status); | 1186 | inb_p(video_port_status); |
| 1187 | vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); | 1187 | vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); |
| 1188 | } | 1188 | } |
| 1189 | spin_unlock_irq(&vga_lock); | 1189 | raw_spin_unlock_irq(&vga_lock); |
| 1190 | return 0; | 1190 | return 0; |
| 1191 | } | 1191 | } |
| 1192 | 1192 | ||
| @@ -1211,26 +1211,26 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight) | |||
| 1211 | registers; they are write-only on EGA, but it appears that they | 1211 | registers; they are write-only on EGA, but it appears that they |
| 1212 | are all don't care bits on EGA, so I guess it doesn't matter. */ | 1212 | are all don't care bits on EGA, so I guess it doesn't matter. */ |
| 1213 | 1213 | ||
| 1214 | spin_lock_irq(&vga_lock); | 1214 | raw_spin_lock_irq(&vga_lock); |
| 1215 | outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */ | 1215 | outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */ |
| 1216 | ovr = inb_p(vga_video_port_val); | 1216 | ovr = inb_p(vga_video_port_val); |
| 1217 | outb_p(0x09, vga_video_port_reg); /* Font size register */ | 1217 | outb_p(0x09, vga_video_port_reg); /* Font size register */ |
| 1218 | fsr = inb_p(vga_video_port_val); | 1218 | fsr = inb_p(vga_video_port_val); |
| 1219 | spin_unlock_irq(&vga_lock); | 1219 | raw_spin_unlock_irq(&vga_lock); |
| 1220 | 1220 | ||
| 1221 | vde = maxscan & 0xff; /* Vertical display end reg */ | 1221 | vde = maxscan & 0xff; /* Vertical display end reg */ |
| 1222 | ovr = (ovr & 0xbd) + /* Overflow register */ | 1222 | ovr = (ovr & 0xbd) + /* Overflow register */ |
| 1223 | ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3); | 1223 | ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3); |
| 1224 | fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */ | 1224 | fsr = (fsr & 0xe0) + (fontheight - 1); /* Font size register */ |
| 1225 | 1225 | ||
| 1226 | spin_lock_irq(&vga_lock); | 1226 | raw_spin_lock_irq(&vga_lock); |
| 1227 | outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */ | 1227 | outb_p(0x07, vga_video_port_reg); /* CRTC overflow register */ |
| 1228 | outb_p(ovr, vga_video_port_val); | 1228 | outb_p(ovr, vga_video_port_val); |
| 1229 | outb_p(0x09, vga_video_port_reg); /* Font size */ | 1229 | outb_p(0x09, vga_video_port_reg); /* Font size */ |
| 1230 | outb_p(fsr, vga_video_port_val); | 1230 | outb_p(fsr, vga_video_port_val); |
| 1231 | outb_p(0x12, vga_video_port_reg); /* Vertical display limit */ | 1231 | outb_p(0x12, vga_video_port_reg); /* Vertical display limit */ |
| 1232 | outb_p(vde, vga_video_port_val); | 1232 | outb_p(vde, vga_video_port_val); |
| 1233 | spin_unlock_irq(&vga_lock); | 1233 | raw_spin_unlock_irq(&vga_lock); |
| 1234 | vga_video_font_height = fontheight; | 1234 | vga_video_font_height = fontheight; |
| 1235 | 1235 | ||
| 1236 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 1236 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 9075bea55879..7b2c40abae15 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c | |||
| @@ -550,7 +550,7 @@ static void control_set_hardware(struct fb_info_control *p, struct fb_par_contro | |||
| 550 | 550 | ||
| 551 | 551 | ||
| 552 | /* | 552 | /* |
| 553 | * Parse user speficied options (`video=controlfb:') | 553 | * Parse user specified options (`video=controlfb:') |
| 554 | */ | 554 | */ |
| 555 | static void __init control_setup(char *options) | 555 | static void __init control_setup(char *options) |
| 556 | { | 556 | { |
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index fcdac872522d..55f91d9ab00b 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c | |||
| @@ -35,6 +35,9 @@ | |||
| 35 | 35 | ||
| 36 | #define DRIVER_NAME "da8xx_lcdc" | 36 | #define DRIVER_NAME "da8xx_lcdc" |
| 37 | 37 | ||
| 38 | #define LCD_VERSION_1 1 | ||
| 39 | #define LCD_VERSION_2 2 | ||
| 40 | |||
| 38 | /* LCD Status Register */ | 41 | /* LCD Status Register */ |
| 39 | #define LCD_END_OF_FRAME1 BIT(9) | 42 | #define LCD_END_OF_FRAME1 BIT(9) |
| 40 | #define LCD_END_OF_FRAME0 BIT(8) | 43 | #define LCD_END_OF_FRAME0 BIT(8) |
| @@ -49,7 +52,9 @@ | |||
| 49 | #define LCD_DMA_BURST_4 0x2 | 52 | #define LCD_DMA_BURST_4 0x2 |
| 50 | #define LCD_DMA_BURST_8 0x3 | 53 | #define LCD_DMA_BURST_8 0x3 |
| 51 | #define LCD_DMA_BURST_16 0x4 | 54 | #define LCD_DMA_BURST_16 0x4 |
| 52 | #define LCD_END_OF_FRAME_INT_ENA BIT(2) | 55 | #define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) |
| 56 | #define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) | ||
| 57 | #define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) | ||
| 53 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) | 58 | #define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) |
| 54 | 59 | ||
| 55 | /* LCD Control Register */ | 60 | /* LCD Control Register */ |
| @@ -65,12 +70,18 @@ | |||
| 65 | #define LCD_MONO_8BIT_MODE BIT(9) | 70 | #define LCD_MONO_8BIT_MODE BIT(9) |
| 66 | #define LCD_RASTER_ORDER BIT(8) | 71 | #define LCD_RASTER_ORDER BIT(8) |
| 67 | #define LCD_TFT_MODE BIT(7) | 72 | #define LCD_TFT_MODE BIT(7) |
| 68 | #define LCD_UNDERFLOW_INT_ENA BIT(6) | 73 | #define LCD_V1_UNDERFLOW_INT_ENA BIT(6) |
| 69 | #define LCD_PL_ENABLE BIT(4) | 74 | #define LCD_V2_UNDERFLOW_INT_ENA BIT(5) |
| 75 | #define LCD_V1_PL_INT_ENA BIT(4) | ||
| 76 | #define LCD_V2_PL_INT_ENA BIT(6) | ||
| 70 | #define LCD_MONOCHROME_MODE BIT(1) | 77 | #define LCD_MONOCHROME_MODE BIT(1) |
| 71 | #define LCD_RASTER_ENABLE BIT(0) | 78 | #define LCD_RASTER_ENABLE BIT(0) |
| 72 | #define LCD_TFT_ALT_ENABLE BIT(23) | 79 | #define LCD_TFT_ALT_ENABLE BIT(23) |
| 73 | #define LCD_STN_565_ENABLE BIT(24) | 80 | #define LCD_STN_565_ENABLE BIT(24) |
| 81 | #define LCD_V2_DMA_CLK_EN BIT(2) | ||
| 82 | #define LCD_V2_LIDD_CLK_EN BIT(1) | ||
| 83 | #define LCD_V2_CORE_CLK_EN BIT(0) | ||
| 84 | #define LCD_V2_LPP_B10 26 | ||
| 74 | 85 | ||
| 75 | /* LCD Raster Timing 2 Register */ | 86 | /* LCD Raster Timing 2 Register */ |
| 76 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) | 87 | #define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) |
| @@ -82,6 +93,7 @@ | |||
| 82 | #define LCD_INVERT_FRAME_CLOCK BIT(20) | 93 | #define LCD_INVERT_FRAME_CLOCK BIT(20) |
| 83 | 94 | ||
| 84 | /* LCD Block */ | 95 | /* LCD Block */ |
| 96 | #define LCD_PID_REG 0x0 | ||
| 85 | #define LCD_CTRL_REG 0x4 | 97 | #define LCD_CTRL_REG 0x4 |
| 86 | #define LCD_STAT_REG 0x8 | 98 | #define LCD_STAT_REG 0x8 |
| 87 | #define LCD_RASTER_CTRL_REG 0x28 | 99 | #define LCD_RASTER_CTRL_REG 0x28 |
| @@ -94,6 +106,17 @@ | |||
| 94 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C | 106 | #define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C |
| 95 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 | 107 | #define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 |
| 96 | 108 | ||
| 109 | /* Interrupt Registers available only in Version 2 */ | ||
| 110 | #define LCD_RAW_STAT_REG 0x58 | ||
| 111 | #define LCD_MASKED_STAT_REG 0x5c | ||
| 112 | #define LCD_INT_ENABLE_SET_REG 0x60 | ||
| 113 | #define LCD_INT_ENABLE_CLR_REG 0x64 | ||
| 114 | #define LCD_END_OF_INT_IND_REG 0x68 | ||
| 115 | |||
| 116 | /* Clock registers available only on Version 2 */ | ||
| 117 | #define LCD_CLK_ENABLE_REG 0x6c | ||
| 118 | #define LCD_CLK_RESET_REG 0x70 | ||
| 119 | |||
| 97 | #define LCD_NUM_BUFFERS 2 | 120 | #define LCD_NUM_BUFFERS 2 |
| 98 | 121 | ||
| 99 | #define WSI_TIMEOUT 50 | 122 | #define WSI_TIMEOUT 50 |
| @@ -105,6 +128,8 @@ | |||
| 105 | 128 | ||
| 106 | static resource_size_t da8xx_fb_reg_base; | 129 | static resource_size_t da8xx_fb_reg_base; |
| 107 | static struct resource *lcdc_regs; | 130 | static struct resource *lcdc_regs; |
| 131 | static unsigned int lcd_revision; | ||
| 132 | static irq_handler_t lcdc_irq_handler; | ||
| 108 | 133 | ||
| 109 | static inline unsigned int lcdc_read(unsigned int addr) | 134 | static inline unsigned int lcdc_read(unsigned int addr) |
| 110 | { | 135 | { |
| @@ -240,6 +265,7 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
| 240 | u32 end; | 265 | u32 end; |
| 241 | u32 reg_ras; | 266 | u32 reg_ras; |
| 242 | u32 reg_dma; | 267 | u32 reg_dma; |
| 268 | u32 reg_int; | ||
| 243 | 269 | ||
| 244 | /* init reg to clear PLM (loading mode) fields */ | 270 | /* init reg to clear PLM (loading mode) fields */ |
| 245 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 271 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
| @@ -252,7 +278,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
| 252 | end = par->dma_end; | 278 | end = par->dma_end; |
| 253 | 279 | ||
| 254 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); | 280 | reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); |
| 255 | reg_dma |= LCD_END_OF_FRAME_INT_ENA; | 281 | if (lcd_revision == LCD_VERSION_1) { |
| 282 | reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; | ||
| 283 | } else { | ||
| 284 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
| 285 | LCD_V2_END_OF_FRAME0_INT_ENA | | ||
| 286 | LCD_V2_END_OF_FRAME1_INT_ENA; | ||
| 287 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
| 288 | } | ||
| 256 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; | 289 | reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; |
| 257 | 290 | ||
| 258 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 291 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
| @@ -264,7 +297,14 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | |||
| 264 | end = start + par->palette_sz - 1; | 297 | end = start + par->palette_sz - 1; |
| 265 | 298 | ||
| 266 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); | 299 | reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); |
| 267 | reg_ras |= LCD_PL_ENABLE; | 300 | |
| 301 | if (lcd_revision == LCD_VERSION_1) { | ||
| 302 | reg_ras |= LCD_V1_PL_INT_ENA; | ||
| 303 | } else { | ||
| 304 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
| 305 | LCD_V2_PL_INT_ENA; | ||
| 306 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
| 307 | } | ||
| 268 | 308 | ||
| 269 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | 309 | lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); |
| 270 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | 310 | lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); |
| @@ -348,6 +388,7 @@ static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, | |||
| 348 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | 388 | static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) |
| 349 | { | 389 | { |
| 350 | u32 reg; | 390 | u32 reg; |
| 391 | u32 reg_int; | ||
| 351 | 392 | ||
| 352 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | | 393 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | |
| 353 | LCD_MONO_8BIT_MODE | | 394 | LCD_MONO_8BIT_MODE | |
| @@ -375,7 +416,13 @@ static int lcd_cfg_display(const struct lcd_ctrl_config *cfg) | |||
| 375 | } | 416 | } |
| 376 | 417 | ||
| 377 | /* enable additional interrupts here */ | 418 | /* enable additional interrupts here */ |
| 378 | reg |= LCD_UNDERFLOW_INT_ENA; | 419 | if (lcd_revision == LCD_VERSION_1) { |
| 420 | reg |= LCD_V1_UNDERFLOW_INT_ENA; | ||
| 421 | } else { | ||
| 422 | reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | | ||
| 423 | LCD_V2_UNDERFLOW_INT_ENA; | ||
| 424 | lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); | ||
| 425 | } | ||
| 379 | 426 | ||
| 380 | lcdc_write(reg, LCD_RASTER_CTRL_REG); | 427 | lcdc_write(reg, LCD_RASTER_CTRL_REG); |
| 381 | 428 | ||
| @@ -413,18 +460,43 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, | |||
| 413 | 460 | ||
| 414 | /* Set the Panel Width */ | 461 | /* Set the Panel Width */ |
| 415 | /* Pixels per line = (PPL + 1)*16 */ | 462 | /* Pixels per line = (PPL + 1)*16 */ |
| 416 | /*0x3F in bits 4..9 gives max horisontal resolution = 1024 pixels*/ | 463 | if (lcd_revision == LCD_VERSION_1) { |
| 417 | width &= 0x3f0; | 464 | /* |
| 465 | * 0x3F in bits 4..9 gives max horizontal resolution = 1024 | ||
| 466 | * pixels. | ||
| 467 | */ | ||
| 468 | width &= 0x3f0; | ||
| 469 | } else { | ||
| 470 | /* | ||
| 471 | * 0x7F in bits 4..10 gives max horizontal resolution = 2048 | ||
| 472 | * pixels. | ||
| 473 | */ | ||
| 474 | width &= 0x7f0; | ||
| 475 | } | ||
| 476 | |||
| 418 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG); | 477 | reg = lcdc_read(LCD_RASTER_TIMING_0_REG); |
| 419 | reg &= 0xfffffc00; | 478 | reg &= 0xfffffc00; |
| 420 | reg |= ((width >> 4) - 1) << 4; | 479 | if (lcd_revision == LCD_VERSION_1) { |
| 480 | reg |= ((width >> 4) - 1) << 4; | ||
| 481 | } else { | ||
| 482 | width = (width >> 4) - 1; | ||
| 483 | reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); | ||
| 484 | } | ||
| 421 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); | 485 | lcdc_write(reg, LCD_RASTER_TIMING_0_REG); |
| 422 | 486 | ||
| 423 | /* Set the Panel Height */ | 487 | /* Set the Panel Height */ |
| 488 | /* Set bits 9:0 of Lines Per Pixel */ | ||
| 424 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG); | 489 | reg = lcdc_read(LCD_RASTER_TIMING_1_REG); |
| 425 | reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); | 490 | reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); |
| 426 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); | 491 | lcdc_write(reg, LCD_RASTER_TIMING_1_REG); |
| 427 | 492 | ||
| 493 | /* Set bit 10 of Lines Per Pixel */ | ||
| 494 | if (lcd_revision == LCD_VERSION_2) { | ||
| 495 | reg = lcdc_read(LCD_RASTER_TIMING_2_REG); | ||
| 496 | reg |= ((height - 1) & 0x400) << 16; | ||
| 497 | lcdc_write(reg, LCD_RASTER_TIMING_2_REG); | ||
| 498 | } | ||
| 499 | |||
| 428 | /* Set the Raster Order of the Frame Buffer */ | 500 | /* Set the Raster Order of the Frame Buffer */ |
| 429 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); | 501 | reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); |
| 430 | if (raster_order) | 502 | if (raster_order) |
| @@ -511,6 +583,9 @@ static void lcd_reset(struct da8xx_fb_par *par) | |||
| 511 | /* DMA has to be disabled */ | 583 | /* DMA has to be disabled */ |
| 512 | lcdc_write(0, LCD_DMA_CTRL_REG); | 584 | lcdc_write(0, LCD_DMA_CTRL_REG); |
| 513 | lcdc_write(0, LCD_RASTER_CTRL_REG); | 585 | lcdc_write(0, LCD_RASTER_CTRL_REG); |
| 586 | |||
| 587 | if (lcd_revision == LCD_VERSION_2) | ||
| 588 | lcdc_write(0, LCD_INT_ENABLE_SET_REG); | ||
| 514 | } | 589 | } |
| 515 | 590 | ||
| 516 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | 591 | static void lcd_calc_clk_divider(struct da8xx_fb_par *par) |
| @@ -523,6 +598,11 @@ static void lcd_calc_clk_divider(struct da8xx_fb_par *par) | |||
| 523 | /* Configure the LCD clock divisor. */ | 598 | /* Configure the LCD clock divisor. */ |
| 524 | lcdc_write(LCD_CLK_DIVISOR(div) | | 599 | lcdc_write(LCD_CLK_DIVISOR(div) | |
| 525 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); | 600 | (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); |
| 601 | |||
| 602 | if (lcd_revision == LCD_VERSION_2) | ||
| 603 | lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | | ||
| 604 | LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); | ||
| 605 | |||
| 526 | } | 606 | } |
| 527 | 607 | ||
| 528 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | 608 | static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, |
| @@ -583,7 +663,63 @@ static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, | |||
| 583 | return 0; | 663 | return 0; |
| 584 | } | 664 | } |
| 585 | 665 | ||
| 586 | static irqreturn_t lcdc_irq_handler(int irq, void *arg) | 666 | /* IRQ handler for version 2 of LCDC */ |
| 667 | static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) | ||
| 668 | { | ||
| 669 | struct da8xx_fb_par *par = arg; | ||
| 670 | u32 stat = lcdc_read(LCD_MASKED_STAT_REG); | ||
| 671 | u32 reg_int; | ||
| 672 | |||
| 673 | if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { | ||
| 674 | lcd_disable_raster(); | ||
| 675 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
| 676 | lcd_enable_raster(); | ||
| 677 | } else if (stat & LCD_PL_LOAD_DONE) { | ||
| 678 | /* | ||
| 679 | * Must disable raster before changing state of any control bit. | ||
| 680 | * And also must be disabled before clearing the PL loading | ||
| 681 | * interrupt via the following write to the status register. If | ||
| 682 | * this is done after then one gets multiple PL done interrupts. | ||
| 683 | */ | ||
| 684 | lcd_disable_raster(); | ||
| 685 | |||
| 686 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
| 687 | |||
| 688 | /* Disable PL completion inerrupt */ | ||
| 689 | reg_int = lcdc_read(LCD_INT_ENABLE_CLR_REG) | | ||
| 690 | (LCD_V2_PL_INT_ENA); | ||
| 691 | lcdc_write(reg_int, LCD_INT_ENABLE_CLR_REG); | ||
| 692 | |||
| 693 | /* Setup and start data loading mode */ | ||
| 694 | lcd_blit(LOAD_DATA, par); | ||
| 695 | } else { | ||
| 696 | lcdc_write(stat, LCD_MASKED_STAT_REG); | ||
| 697 | |||
| 698 | if (stat & LCD_END_OF_FRAME0) { | ||
| 699 | lcdc_write(par->dma_start, | ||
| 700 | LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); | ||
| 701 | lcdc_write(par->dma_end, | ||
| 702 | LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); | ||
| 703 | par->vsync_flag = 1; | ||
| 704 | wake_up_interruptible(&par->vsync_wait); | ||
| 705 | } | ||
| 706 | |||
| 707 | if (stat & LCD_END_OF_FRAME1) { | ||
| 708 | lcdc_write(par->dma_start, | ||
| 709 | LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); | ||
| 710 | lcdc_write(par->dma_end, | ||
| 711 | LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); | ||
| 712 | par->vsync_flag = 1; | ||
| 713 | wake_up_interruptible(&par->vsync_wait); | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 717 | lcdc_write(0, LCD_END_OF_INT_IND_REG); | ||
| 718 | return IRQ_HANDLED; | ||
| 719 | } | ||
| 720 | |||
| 721 | /* IRQ handler for version 1 LCDC */ | ||
| 722 | static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) | ||
| 587 | { | 723 | { |
| 588 | struct da8xx_fb_par *par = arg; | 724 | struct da8xx_fb_par *par = arg; |
| 589 | u32 stat = lcdc_read(LCD_STAT_REG); | 725 | u32 stat = lcdc_read(LCD_STAT_REG); |
| @@ -606,7 +742,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *arg) | |||
| 606 | 742 | ||
| 607 | /* Disable PL completion inerrupt */ | 743 | /* Disable PL completion inerrupt */ |
| 608 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); | 744 | reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); |
| 609 | reg_ras &= ~LCD_PL_ENABLE; | 745 | reg_ras &= ~LCD_V1_PL_INT_ENA; |
| 610 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); | 746 | lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); |
| 611 | 747 | ||
| 612 | /* Setup and start data loading mode */ | 748 | /* Setup and start data loading mode */ |
| @@ -877,8 +1013,8 @@ static int da8xx_pan_display(struct fb_var_screeninfo *var, | |||
| 877 | 1013 | ||
| 878 | start = fix->smem_start + | 1014 | start = fix->smem_start + |
| 879 | new_var.yoffset * fix->line_length + | 1015 | new_var.yoffset * fix->line_length + |
| 880 | new_var.xoffset * var->bits_per_pixel / 8; | 1016 | new_var.xoffset * fbi->var.bits_per_pixel / 8; |
| 881 | end = start + var->yres * fix->line_length - 1; | 1017 | end = start + fbi->var.yres * fix->line_length - 1; |
| 882 | par->dma_start = start; | 1018 | par->dma_start = start; |
| 883 | par->dma_end = end; | 1019 | par->dma_end = end; |
| 884 | } | 1020 | } |
| @@ -945,6 +1081,22 @@ static int __devinit fb_probe(struct platform_device *device) | |||
| 945 | if (ret) | 1081 | if (ret) |
| 946 | goto err_clk_put; | 1082 | goto err_clk_put; |
| 947 | 1083 | ||
| 1084 | /* Determine LCD IP Version */ | ||
| 1085 | switch (lcdc_read(LCD_PID_REG)) { | ||
| 1086 | case 0x4C100102: | ||
| 1087 | lcd_revision = LCD_VERSION_1; | ||
| 1088 | break; | ||
| 1089 | case 0x4F200800: | ||
| 1090 | lcd_revision = LCD_VERSION_2; | ||
| 1091 | break; | ||
| 1092 | default: | ||
| 1093 | dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " | ||
| 1094 | "defaulting to LCD revision 1\n", | ||
| 1095 | lcdc_read(LCD_PID_REG)); | ||
| 1096 | lcd_revision = LCD_VERSION_1; | ||
| 1097 | break; | ||
| 1098 | } | ||
| 1099 | |||
| 948 | for (i = 0, lcdc_info = known_lcd_panels; | 1100 | for (i = 0, lcdc_info = known_lcd_panels; |
| 949 | i < ARRAY_SIZE(known_lcd_panels); | 1101 | i < ARRAY_SIZE(known_lcd_panels); |
| 950 | i++, lcdc_info++) { | 1102 | i++, lcdc_info++) { |
| @@ -1085,7 +1237,13 @@ static int __devinit fb_probe(struct platform_device *device) | |||
| 1085 | } | 1237 | } |
| 1086 | #endif | 1238 | #endif |
| 1087 | 1239 | ||
| 1088 | ret = request_irq(par->irq, lcdc_irq_handler, 0, DRIVER_NAME, par); | 1240 | if (lcd_revision == LCD_VERSION_1) |
| 1241 | lcdc_irq_handler = lcdc_irq_handler_rev01; | ||
| 1242 | else | ||
| 1243 | lcdc_irq_handler = lcdc_irq_handler_rev02; | ||
| 1244 | |||
| 1245 | ret = request_irq(par->irq, lcdc_irq_handler, 0, | ||
| 1246 | DRIVER_NAME, par); | ||
| 1089 | if (ret) | 1247 | if (ret) |
| 1090 | goto irq_freq; | 1248 | goto irq_freq; |
| 1091 | return 0; | 1249 | return 0; |
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index 40e5f17d1e4b..2e830ec52a5a 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/module.h> | ||
| 21 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
| 22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 23 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c index 27f2c57e06e9..60a787fa32cf 100644 --- a/drivers/video/fb-puv3.c +++ b/drivers/video/fb-puv3.c | |||
| @@ -624,8 +624,8 @@ static int unifb_pan_display(struct fb_var_screeninfo *var, | |||
| 624 | || var->xoffset) | 624 | || var->xoffset) |
| 625 | return -EINVAL; | 625 | return -EINVAL; |
| 626 | } else { | 626 | } else { |
| 627 | if (var->xoffset + var->xres > info->var.xres_virtual || | 627 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
| 628 | var->yoffset + var->yres > info->var.yres_virtual) | 628 | var->yoffset + info->var.yres > info->var.yres_virtual) |
| 629 | return -EINVAL; | 629 | return -EINVAL; |
| 630 | } | 630 | } |
| 631 | info->var.xoffset = var->xoffset; | 631 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c index 4a874c8d039c..2b106f046fde 100644 --- a/drivers/video/fb_ddc.c +++ b/drivers/video/fb_ddc.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * driver/vide/fb_ddc.c - DDC/EDID read support. | 2 | * drivers/video/fb_ddc.c - DDC/EDID read support. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com> | 4 | * Copyright (C) 2006 Dennis Munsie <dmunsie@cecropia.com> |
| 5 | * | 5 | * |
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
| 12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
| 13 | #include <linux/module.h> | ||
| 13 | #include <linux/fb.h> | 14 | #include <linux/fb.h> |
| 14 | #include <linux/i2c-algo-bit.h> | 15 | #include <linux/i2c-algo-bit.h> |
| 15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 32814e8800e0..c27e153d8882 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
| @@ -223,8 +223,7 @@ void fb_deferred_io_cleanup(struct fb_info *info) | |||
| 223 | int i; | 223 | int i; |
| 224 | 224 | ||
| 225 | BUG_ON(!fbdefio); | 225 | BUG_ON(!fbdefio); |
| 226 | cancel_delayed_work(&info->deferred_work); | 226 | cancel_delayed_work_sync(&info->deferred_work); |
| 227 | flush_scheduled_work(); | ||
| 228 | 227 | ||
| 229 | /* clear out the mapping that we setup */ | 228 | /* clear out the mapping that we setup */ |
| 230 | for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { | 229 | for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { |
diff --git a/drivers/video/fb_notify.c b/drivers/video/fb_notify.c index 8c020389e4fa..74c2da528884 100644 --- a/drivers/video/fb_notify.c +++ b/drivers/video/fb_notify.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | */ | 12 | */ |
| 13 | #include <linux/fb.h> | 13 | #include <linux/fb.h> |
| 14 | #include <linux/notifier.h> | 14 | #include <linux/notifier.h> |
| 15 | #include <linux/export.h> | ||
| 15 | 16 | ||
| 16 | static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); | 17 | static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); |
| 17 | 18 | ||
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 5aac00eb1830..ad936295d8f4 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -1738,8 +1738,6 @@ void fb_set_suspend(struct fb_info *info, int state) | |||
| 1738 | { | 1738 | { |
| 1739 | struct fb_event event; | 1739 | struct fb_event event; |
| 1740 | 1740 | ||
| 1741 | if (!lock_fb_info(info)) | ||
| 1742 | return; | ||
| 1743 | event.info = info; | 1741 | event.info = info; |
| 1744 | if (state) { | 1742 | if (state) { |
| 1745 | fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); | 1743 | fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); |
| @@ -1748,7 +1746,6 @@ void fb_set_suspend(struct fb_info *info, int state) | |||
| 1748 | info->state = FBINFO_STATE_RUNNING; | 1746 | info->state = FBINFO_STATE_RUNNING; |
| 1749 | fb_notifier_call_chain(FB_EVENT_RESUME, &event); | 1747 | fb_notifier_call_chain(FB_EVENT_RESUME, &event); |
| 1750 | } | 1748 | } |
| 1751 | unlock_fb_info(info); | ||
| 1752 | } | 1749 | } |
| 1753 | 1750 | ||
| 1754 | /** | 1751 | /** |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 4f57485f8c54..cef65574db6c 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
| @@ -493,7 +493,8 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
| 493 | return num; | 493 | return num; |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | 496 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode, |
| 497 | int ver, int rev) | ||
| 497 | { | 498 | { |
| 498 | int xres, yres = 0, refresh, ratio, i; | 499 | int xres, yres = 0, refresh, ratio, i; |
| 499 | 500 | ||
| @@ -504,7 +505,11 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
| 504 | ratio = (block[1] & 0xc0) >> 6; | 505 | ratio = (block[1] & 0xc0) >> 6; |
| 505 | switch (ratio) { | 506 | switch (ratio) { |
| 506 | case 0: | 507 | case 0: |
| 507 | yres = xres; | 508 | /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */ |
| 509 | if (ver < 1 || (ver == 1 && rev < 3)) | ||
| 510 | yres = xres; | ||
| 511 | else | ||
| 512 | yres = (xres * 10)/16; | ||
| 508 | break; | 513 | break; |
| 509 | case 1: | 514 | case 1: |
| 510 | yres = (xres * 3)/4; | 515 | yres = (xres * 3)/4; |
| @@ -533,12 +538,12 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
| 533 | } | 538 | } |
| 534 | 539 | ||
| 535 | static int get_dst_timing(unsigned char *block, | 540 | static int get_dst_timing(unsigned char *block, |
| 536 | struct fb_videomode *mode) | 541 | struct fb_videomode *mode, int ver, int rev) |
| 537 | { | 542 | { |
| 538 | int j, num = 0; | 543 | int j, num = 0; |
| 539 | 544 | ||
| 540 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) | 545 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) |
| 541 | num += get_std_timing(block, &mode[num]); | 546 | num += get_std_timing(block, &mode[num], ver, rev); |
| 542 | 547 | ||
| 543 | return num; | 548 | return num; |
| 544 | } | 549 | } |
| @@ -599,6 +604,10 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
| 599 | struct fb_videomode *mode, *m; | 604 | struct fb_videomode *mode, *m; |
| 600 | unsigned char *block; | 605 | unsigned char *block; |
| 601 | int num = 0, i, first = 1; | 606 | int num = 0, i, first = 1; |
| 607 | int ver, rev; | ||
| 608 | |||
| 609 | ver = edid[EDID_STRUCT_VERSION]; | ||
| 610 | rev = edid[EDID_STRUCT_REVISION]; | ||
| 602 | 611 | ||
| 603 | mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); | 612 | mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL); |
| 604 | if (mode == NULL) | 613 | if (mode == NULL) |
| @@ -632,12 +641,12 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
| 632 | DPRINTK(" Standard Timings\n"); | 641 | DPRINTK(" Standard Timings\n"); |
| 633 | block = edid + STD_TIMING_DESCRIPTIONS_START; | 642 | block = edid + STD_TIMING_DESCRIPTIONS_START; |
| 634 | for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) | 643 | for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) |
| 635 | num += get_std_timing(block, &mode[num]); | 644 | num += get_std_timing(block, &mode[num], ver, rev); |
| 636 | 645 | ||
| 637 | block = edid + DETAILED_TIMING_DESCRIPTIONS_START; | 646 | block = edid + DETAILED_TIMING_DESCRIPTIONS_START; |
| 638 | for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { | 647 | for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { |
| 639 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) | 648 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) |
| 640 | num += get_dst_timing(block + 5, &mode[num]); | 649 | num += get_dst_timing(block + 5, &mode[num], ver, rev); |
| 641 | } | 650 | } |
| 642 | 651 | ||
| 643 | /* Yikes, EDID data is totally useless */ | 652 | /* Yikes, EDID data is totally useless */ |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 04251ce89184..67afa9c2289d 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
| @@ -399,9 +399,12 @@ static ssize_t store_fbstate(struct device *device, | |||
| 399 | 399 | ||
| 400 | state = simple_strtoul(buf, &last, 0); | 400 | state = simple_strtoul(buf, &last, 0); |
| 401 | 401 | ||
| 402 | if (!lock_fb_info(fb_info)) | ||
| 403 | return -ENODEV; | ||
| 402 | console_lock(); | 404 | console_lock(); |
| 403 | fb_set_suspend(fb_info, (int)state); | 405 | fb_set_suspend(fb_info, (int)state); |
| 404 | console_unlock(); | 406 | console_unlock(); |
| 407 | unlock_fb_info(fb_info); | ||
| 405 | 408 | ||
| 406 | return count; | 409 | return count; |
| 407 | } | 410 | } |
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 0acc7d65aeaa..a16beeb5f548 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c | |||
| @@ -30,37 +30,40 @@ | |||
| 30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
| 31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
| 32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
| 33 | 33 | #include <linux/spinlock.h> | |
| 34 | #include <linux/of_platform.h> | ||
| 35 | 34 | ||
| 36 | #include <sysdev/fsl_soc.h> | 35 | #include <sysdev/fsl_soc.h> |
| 37 | #include <linux/fsl-diu-fb.h> | 36 | #include <linux/fsl-diu-fb.h> |
| 38 | #include "edid.h" | 37 | #include "edid.h" |
| 39 | 38 | ||
| 40 | /* | 39 | #define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ |
| 41 | * These parameters give default parameters | 40 | /* 1 for plane 0, 2 for plane 1&2 each */ |
| 42 | * for video output 1024x768, | 41 | |
| 43 | * FIXME - change timing to proper amounts | 42 | /* HW cursor parameters */ |
| 44 | * hsync 31.5kHz, vsync 60Hz | 43 | #define MAX_CURS 32 |
| 45 | */ | 44 | |
| 46 | static struct fb_videomode __devinitdata fsl_diu_default_mode = { | 45 | /* INT_STATUS/INT_MASK field descriptions */ |
| 47 | .refresh = 60, | 46 | #define INT_VSYNC 0x01 /* Vsync interrupt */ |
| 48 | .xres = 1024, | 47 | #define INT_VSYNC_WB 0x02 /* Vsync interrupt for write back operation */ |
| 49 | .yres = 768, | 48 | #define INT_UNDRUN 0x04 /* Under run exception interrupt */ |
| 50 | .pixclock = 15385, | 49 | #define INT_PARERR 0x08 /* Display parameters error interrupt */ |
| 51 | .left_margin = 160, | 50 | #define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ |
| 52 | .right_margin = 24, | 51 | |
| 53 | .upper_margin = 29, | 52 | struct diu_addr { |
| 54 | .lower_margin = 3, | 53 | void *vaddr; /* Virtual address */ |
| 55 | .hsync_len = 136, | 54 | dma_addr_t paddr; /* Physical address */ |
| 56 | .vsync_len = 6, | 55 | __u32 offset; |
| 57 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 58 | .vmode = FB_VMODE_NONINTERLACED | ||
| 59 | }; | 56 | }; |
| 60 | 57 | ||
| 58 | /* | ||
| 59 | * List of supported video modes | ||
| 60 | * | ||
| 61 | * The first entry is the default video mode. The remain entries are in | ||
| 62 | * order if increasing resolution and frequency. The 320x240-60 mode is | ||
| 63 | * the initial AOI for the second and third planes. | ||
| 64 | */ | ||
| 61 | static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | 65 | static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { |
| 62 | { | 66 | { |
| 63 | .name = "1024x768-60", | ||
| 64 | .refresh = 60, | 67 | .refresh = 60, |
| 65 | .xres = 1024, | 68 | .xres = 1024, |
| 66 | .yres = 768, | 69 | .yres = 768, |
| @@ -75,7 +78,132 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
| 75 | .vmode = FB_VMODE_NONINTERLACED | 78 | .vmode = FB_VMODE_NONINTERLACED |
| 76 | }, | 79 | }, |
| 77 | { | 80 | { |
| 78 | .name = "1024x768-70", | 81 | .refresh = 60, |
| 82 | .xres = 320, | ||
| 83 | .yres = 240, | ||
| 84 | .pixclock = 79440, | ||
| 85 | .left_margin = 16, | ||
| 86 | .right_margin = 16, | ||
| 87 | .upper_margin = 16, | ||
| 88 | .lower_margin = 5, | ||
| 89 | .hsync_len = 48, | ||
| 90 | .vsync_len = 1, | ||
| 91 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 92 | .vmode = FB_VMODE_NONINTERLACED | ||
| 93 | }, | ||
| 94 | { | ||
| 95 | .refresh = 60, | ||
| 96 | .xres = 640, | ||
| 97 | .yres = 480, | ||
| 98 | .pixclock = 39722, | ||
| 99 | .left_margin = 48, | ||
| 100 | .right_margin = 16, | ||
| 101 | .upper_margin = 33, | ||
| 102 | .lower_margin = 10, | ||
| 103 | .hsync_len = 96, | ||
| 104 | .vsync_len = 2, | ||
| 105 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 106 | .vmode = FB_VMODE_NONINTERLACED | ||
| 107 | }, | ||
| 108 | { | ||
| 109 | .refresh = 72, | ||
| 110 | .xres = 640, | ||
| 111 | .yres = 480, | ||
| 112 | .pixclock = 32052, | ||
| 113 | .left_margin = 128, | ||
| 114 | .right_margin = 24, | ||
| 115 | .upper_margin = 28, | ||
| 116 | .lower_margin = 9, | ||
| 117 | .hsync_len = 40, | ||
| 118 | .vsync_len = 3, | ||
| 119 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 120 | .vmode = FB_VMODE_NONINTERLACED | ||
| 121 | }, | ||
| 122 | { | ||
| 123 | .refresh = 75, | ||
| 124 | .xres = 640, | ||
| 125 | .yres = 480, | ||
| 126 | .pixclock = 31747, | ||
| 127 | .left_margin = 120, | ||
| 128 | .right_margin = 16, | ||
| 129 | .upper_margin = 16, | ||
| 130 | .lower_margin = 1, | ||
| 131 | .hsync_len = 64, | ||
| 132 | .vsync_len = 3, | ||
| 133 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 134 | .vmode = FB_VMODE_NONINTERLACED | ||
| 135 | }, | ||
| 136 | { | ||
| 137 | .refresh = 90, | ||
| 138 | .xres = 640, | ||
| 139 | .yres = 480, | ||
| 140 | .pixclock = 25057, | ||
| 141 | .left_margin = 120, | ||
| 142 | .right_margin = 32, | ||
| 143 | .upper_margin = 14, | ||
| 144 | .lower_margin = 25, | ||
| 145 | .hsync_len = 40, | ||
| 146 | .vsync_len = 14, | ||
| 147 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 148 | .vmode = FB_VMODE_NONINTERLACED | ||
| 149 | }, | ||
| 150 | { | ||
| 151 | .refresh = 100, | ||
| 152 | .xres = 640, | ||
| 153 | .yres = 480, | ||
| 154 | .pixclock = 22272, | ||
| 155 | .left_margin = 48, | ||
| 156 | .right_margin = 32, | ||
| 157 | .upper_margin = 17, | ||
| 158 | .lower_margin = 22, | ||
| 159 | .hsync_len = 128, | ||
| 160 | .vsync_len = 12, | ||
| 161 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 162 | .vmode = FB_VMODE_NONINTERLACED | ||
| 163 | }, | ||
| 164 | { | ||
| 165 | .refresh = 60, | ||
| 166 | .xres = 800, | ||
| 167 | .yres = 480, | ||
| 168 | .pixclock = 33805, | ||
| 169 | .left_margin = 96, | ||
| 170 | .right_margin = 24, | ||
| 171 | .upper_margin = 10, | ||
| 172 | .lower_margin = 3, | ||
| 173 | .hsync_len = 72, | ||
| 174 | .vsync_len = 7, | ||
| 175 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 176 | .vmode = FB_VMODE_NONINTERLACED | ||
| 177 | }, | ||
| 178 | { | ||
| 179 | .refresh = 60, | ||
| 180 | .xres = 800, | ||
| 181 | .yres = 600, | ||
| 182 | .pixclock = 25000, | ||
| 183 | .left_margin = 88, | ||
| 184 | .right_margin = 40, | ||
| 185 | .upper_margin = 23, | ||
| 186 | .lower_margin = 1, | ||
| 187 | .hsync_len = 128, | ||
| 188 | .vsync_len = 4, | ||
| 189 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 190 | .vmode = FB_VMODE_NONINTERLACED | ||
| 191 | }, | ||
| 192 | { | ||
| 193 | .refresh = 60, | ||
| 194 | .xres = 854, | ||
| 195 | .yres = 480, | ||
| 196 | .pixclock = 31518, | ||
| 197 | .left_margin = 104, | ||
| 198 | .right_margin = 16, | ||
| 199 | .upper_margin = 13, | ||
| 200 | .lower_margin = 1, | ||
| 201 | .hsync_len = 88, | ||
| 202 | .vsync_len = 3, | ||
| 203 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 204 | .vmode = FB_VMODE_NONINTERLACED | ||
| 205 | }, | ||
| 206 | { | ||
| 79 | .refresh = 70, | 207 | .refresh = 70, |
| 80 | .xres = 1024, | 208 | .xres = 1024, |
| 81 | .yres = 768, | 209 | .yres = 768, |
| @@ -90,7 +218,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
| 90 | .vmode = FB_VMODE_NONINTERLACED | 218 | .vmode = FB_VMODE_NONINTERLACED |
| 91 | }, | 219 | }, |
| 92 | { | 220 | { |
| 93 | .name = "1024x768-75", | ||
| 94 | .refresh = 75, | 221 | .refresh = 75, |
| 95 | .xres = 1024, | 222 | .xres = 1024, |
| 96 | .yres = 768, | 223 | .yres = 768, |
| @@ -105,7 +232,34 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
| 105 | .vmode = FB_VMODE_NONINTERLACED | 232 | .vmode = FB_VMODE_NONINTERLACED |
| 106 | }, | 233 | }, |
| 107 | { | 234 | { |
| 108 | .name = "1280x1024-60", | 235 | .refresh = 60, |
| 236 | .xres = 1280, | ||
| 237 | .yres = 480, | ||
| 238 | .pixclock = 18939, | ||
| 239 | .left_margin = 353, | ||
| 240 | .right_margin = 47, | ||
| 241 | .upper_margin = 39, | ||
| 242 | .lower_margin = 4, | ||
| 243 | .hsync_len = 8, | ||
| 244 | .vsync_len = 2, | ||
| 245 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 246 | .vmode = FB_VMODE_NONINTERLACED | ||
| 247 | }, | ||
| 248 | { | ||
| 249 | .refresh = 60, | ||
| 250 | .xres = 1280, | ||
| 251 | .yres = 720, | ||
| 252 | .pixclock = 13426, | ||
| 253 | .left_margin = 192, | ||
| 254 | .right_margin = 64, | ||
| 255 | .upper_margin = 22, | ||
| 256 | .lower_margin = 1, | ||
| 257 | .hsync_len = 136, | ||
| 258 | .vsync_len = 3, | ||
| 259 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 260 | .vmode = FB_VMODE_NONINTERLACED | ||
| 261 | }, | ||
| 262 | { | ||
| 109 | .refresh = 60, | 263 | .refresh = 60, |
| 110 | .xres = 1280, | 264 | .xres = 1280, |
| 111 | .yres = 1024, | 265 | .yres = 1024, |
| @@ -120,7 +274,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
| 120 | .vmode = FB_VMODE_NONINTERLACED | 274 | .vmode = FB_VMODE_NONINTERLACED |
| 121 | }, | 275 | }, |
| 122 | { | 276 | { |
| 123 | .name = "1280x1024-70", | ||
| 124 | .refresh = 70, | 277 | .refresh = 70, |
| 125 | .xres = 1280, | 278 | .xres = 1280, |
| 126 | .yres = 1024, | 279 | .yres = 1024, |
| @@ -135,7 +288,6 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
| 135 | .vmode = FB_VMODE_NONINTERLACED | 288 | .vmode = FB_VMODE_NONINTERLACED |
| 136 | }, | 289 | }, |
| 137 | { | 290 | { |
| 138 | .name = "1280x1024-75", | ||
| 139 | .refresh = 75, | 291 | .refresh = 75, |
| 140 | .xres = 1280, | 292 | .xres = 1280, |
| 141 | .yres = 1024, | 293 | .yres = 1024, |
| @@ -150,40 +302,25 @@ static struct fb_videomode __devinitdata fsl_diu_mode_db[] = { | |||
| 150 | .vmode = FB_VMODE_NONINTERLACED | 302 | .vmode = FB_VMODE_NONINTERLACED |
| 151 | }, | 303 | }, |
| 152 | { | 304 | { |
| 153 | .name = "320x240", /* for AOI only */ | ||
| 154 | .refresh = 60, | 305 | .refresh = 60, |
| 155 | .xres = 320, | 306 | .xres = 1920, |
| 156 | .yres = 240, | 307 | .yres = 1080, |
| 157 | .pixclock = 15385, | 308 | .pixclock = 5787, |
| 158 | .left_margin = 0, | 309 | .left_margin = 328, |
| 159 | .right_margin = 0, | 310 | .right_margin = 120, |
| 160 | .upper_margin = 0, | 311 | .upper_margin = 34, |
| 161 | .lower_margin = 0, | 312 | .lower_margin = 1, |
| 162 | .hsync_len = 0, | 313 | .hsync_len = 208, |
| 163 | .vsync_len = 0, | 314 | .vsync_len = 3, |
| 164 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 165 | .vmode = FB_VMODE_NONINTERLACED | ||
| 166 | }, | ||
| 167 | { | ||
| 168 | .name = "1280x480-60", | ||
| 169 | .refresh = 60, | ||
| 170 | .xres = 1280, | ||
| 171 | .yres = 480, | ||
| 172 | .pixclock = 18939, | ||
| 173 | .left_margin = 353, | ||
| 174 | .right_margin = 47, | ||
| 175 | .upper_margin = 39, | ||
| 176 | .lower_margin = 4, | ||
| 177 | .hsync_len = 8, | ||
| 178 | .vsync_len = 2, | ||
| 179 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 315 | .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
| 180 | .vmode = FB_VMODE_NONINTERLACED | 316 | .vmode = FB_VMODE_NONINTERLACED |
| 181 | }, | 317 | }, |
| 182 | }; | 318 | }; |
| 183 | 319 | ||
| 184 | static char *fb_mode = "1024x768-32@60"; | 320 | static char *fb_mode; |
| 185 | static unsigned long default_bpp = 32; | 321 | static unsigned long default_bpp = 32; |
| 186 | static int monitor_port; | 322 | static enum fsl_diu_monitor_port monitor_port; |
| 323 | static char *monitor_string; | ||
| 187 | 324 | ||
| 188 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 325 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
| 189 | static u8 *coherence_data; | 326 | static u8 *coherence_data; |
| @@ -201,15 +338,27 @@ struct fsl_diu_data { | |||
| 201 | void *dummy_aoi_virt; | 338 | void *dummy_aoi_virt; |
| 202 | unsigned int irq; | 339 | unsigned int irq; |
| 203 | int fb_enabled; | 340 | int fb_enabled; |
| 204 | int monitor_port; | 341 | enum fsl_diu_monitor_port monitor_port; |
| 342 | struct diu __iomem *diu_reg; | ||
| 343 | spinlock_t reg_lock; | ||
| 344 | struct diu_addr ad; | ||
| 345 | struct diu_addr gamma; | ||
| 346 | struct diu_addr pallete; | ||
| 347 | struct diu_addr cursor; | ||
| 348 | }; | ||
| 349 | |||
| 350 | enum mfb_index { | ||
| 351 | PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */ | ||
| 352 | PLANE1_AOI0, /* Plane 1, first AOI */ | ||
| 353 | PLANE1_AOI1, /* Plane 1, second AOI */ | ||
| 354 | PLANE2_AOI0, /* Plane 2, first AOI */ | ||
| 355 | PLANE2_AOI1, /* Plane 2, second AOI */ | ||
| 205 | }; | 356 | }; |
| 206 | 357 | ||
| 207 | struct mfb_info { | 358 | struct mfb_info { |
| 208 | int index; | 359 | enum mfb_index index; |
| 209 | int type; | ||
| 210 | char *id; | 360 | char *id; |
| 211 | int registered; | 361 | int registered; |
| 212 | int blank; | ||
| 213 | unsigned long pseudo_palette[16]; | 362 | unsigned long pseudo_palette[16]; |
| 214 | struct diu_ad *ad; | 363 | struct diu_ad *ad; |
| 215 | int cursor_reset; | 364 | int cursor_reset; |
| @@ -223,63 +372,82 @@ struct mfb_info { | |||
| 223 | 372 | ||
| 224 | 373 | ||
| 225 | static struct mfb_info mfb_template[] = { | 374 | static struct mfb_info mfb_template[] = { |
| 226 | { /* AOI 0 for plane 0 */ | 375 | { |
| 227 | .index = 0, | 376 | .index = PLANE0, |
| 228 | .type = MFB_TYPE_OUTPUT, | 377 | .id = "Panel0", |
| 229 | .id = "Panel0", | 378 | .registered = 0, |
| 230 | .registered = 0, | 379 | .count = 0, |
| 231 | .count = 0, | 380 | .x_aoi_d = 0, |
| 232 | .x_aoi_d = 0, | 381 | .y_aoi_d = 0, |
| 233 | .y_aoi_d = 0, | ||
| 234 | }, | 382 | }, |
| 235 | { /* AOI 0 for plane 1 */ | 383 | { |
| 236 | .index = 1, | 384 | .index = PLANE1_AOI0, |
| 237 | .type = MFB_TYPE_OUTPUT, | 385 | .id = "Panel1 AOI0", |
| 238 | .id = "Panel1 AOI0", | 386 | .registered = 0, |
| 239 | .registered = 0, | 387 | .g_alpha = 0xff, |
| 240 | .g_alpha = 0xff, | 388 | .count = 0, |
| 241 | .count = 0, | 389 | .x_aoi_d = 0, |
| 242 | .x_aoi_d = 0, | 390 | .y_aoi_d = 0, |
| 243 | .y_aoi_d = 0, | ||
| 244 | }, | 391 | }, |
| 245 | { /* AOI 1 for plane 1 */ | 392 | { |
| 246 | .index = 2, | 393 | .index = PLANE1_AOI1, |
| 247 | .type = MFB_TYPE_OUTPUT, | 394 | .id = "Panel1 AOI1", |
| 248 | .id = "Panel1 AOI1", | 395 | .registered = 0, |
| 249 | .registered = 0, | 396 | .g_alpha = 0xff, |
| 250 | .g_alpha = 0xff, | 397 | .count = 0, |
| 251 | .count = 0, | 398 | .x_aoi_d = 0, |
| 252 | .x_aoi_d = 0, | 399 | .y_aoi_d = 480, |
| 253 | .y_aoi_d = 480, | ||
| 254 | }, | 400 | }, |
| 255 | { /* AOI 0 for plane 2 */ | 401 | { |
| 256 | .index = 3, | 402 | .index = PLANE2_AOI0, |
| 257 | .type = MFB_TYPE_OUTPUT, | 403 | .id = "Panel2 AOI0", |
| 258 | .id = "Panel2 AOI0", | 404 | .registered = 0, |
| 259 | .registered = 0, | 405 | .g_alpha = 0xff, |
| 260 | .g_alpha = 0xff, | 406 | .count = 0, |
| 261 | .count = 0, | 407 | .x_aoi_d = 640, |
| 262 | .x_aoi_d = 640, | 408 | .y_aoi_d = 0, |
| 263 | .y_aoi_d = 0, | ||
| 264 | }, | 409 | }, |
| 265 | { /* AOI 1 for plane 2 */ | 410 | { |
| 266 | .index = 4, | 411 | .index = PLANE2_AOI1, |
| 267 | .type = MFB_TYPE_OUTPUT, | 412 | .id = "Panel2 AOI1", |
| 268 | .id = "Panel2 AOI1", | 413 | .registered = 0, |
| 269 | .registered = 0, | 414 | .g_alpha = 0xff, |
| 270 | .g_alpha = 0xff, | 415 | .count = 0, |
| 271 | .count = 0, | 416 | .x_aoi_d = 640, |
| 272 | .x_aoi_d = 640, | 417 | .y_aoi_d = 480, |
| 273 | .y_aoi_d = 480, | ||
| 274 | }, | 418 | }, |
| 275 | }; | 419 | }; |
| 276 | 420 | ||
| 277 | static struct diu_hw dr = { | 421 | /** |
| 278 | .mode = MFB_MODE1, | 422 | * fsl_diu_name_to_port - convert a port name to a monitor port enum |
| 279 | .reg_lock = __SPIN_LOCK_UNLOCKED(diu_hw.reg_lock), | 423 | * |
| 280 | }; | 424 | * Takes the name of a monitor port ("dvi", "lvds", or "dlvds") and returns |
| 425 | * the enum fsl_diu_monitor_port that corresponds to that string. | ||
| 426 | * | ||
| 427 | * For compatibility with older versions, a number ("0", "1", or "2") is also | ||
| 428 | * supported. | ||
| 429 | * | ||
| 430 | * If the string is unknown, DVI is assumed. | ||
| 431 | * | ||
| 432 | * If the particular port is not supported by the platform, another port | ||
| 433 | * (platform-specific) is chosen instead. | ||
| 434 | */ | ||
| 435 | static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s) | ||
| 436 | { | ||
| 437 | enum fsl_diu_monitor_port port = FSL_DIU_PORT_DVI; | ||
| 438 | unsigned long val; | ||
| 281 | 439 | ||
| 282 | static struct diu_pool pool; | 440 | if (s) { |
| 441 | if (!strict_strtoul(s, 10, &val) && (val <= 2)) | ||
| 442 | port = (enum fsl_diu_monitor_port) val; | ||
| 443 | else if (strncmp(s, "lvds", 4) == 0) | ||
| 444 | port = FSL_DIU_PORT_LVDS; | ||
| 445 | else if (strncmp(s, "dlvds", 5) == 0) | ||
| 446 | port = FSL_DIU_PORT_DLVDS; | ||
| 447 | } | ||
| 448 | |||
| 449 | return diu_ops.valid_monitor_port(port); | ||
| 450 | } | ||
| 283 | 451 | ||
| 284 | /** | 452 | /** |
| 285 | * fsl_diu_alloc - allocate memory for the DIU | 453 | * fsl_diu_alloc - allocate memory for the DIU |
| @@ -292,14 +460,9 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys) | |||
| 292 | { | 460 | { |
| 293 | void *virt; | 461 | void *virt; |
| 294 | 462 | ||
| 295 | pr_debug("size=%zu\n", size); | ||
| 296 | |||
| 297 | virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); | 463 | virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); |
| 298 | if (virt) { | 464 | if (virt) |
| 299 | *phys = virt_to_phys(virt); | 465 | *phys = virt_to_phys(virt); |
| 300 | pr_debug("virt=%p phys=%llx\n", virt, | ||
| 301 | (unsigned long long)*phys); | ||
| 302 | } | ||
| 303 | 466 | ||
| 304 | return virt; | 467 | return virt; |
| 305 | } | 468 | } |
| @@ -313,8 +476,6 @@ static void *fsl_diu_alloc(size_t size, phys_addr_t *phys) | |||
| 313 | */ | 476 | */ |
| 314 | static void fsl_diu_free(void *virt, size_t size) | 477 | static void fsl_diu_free(void *virt, size_t size) |
| 315 | { | 478 | { |
| 316 | pr_debug("virt=%p size=%zu\n", virt, size); | ||
| 317 | |||
| 318 | if (virt && size) | 479 | if (virt && size) |
| 319 | free_pages_exact(virt, size); | 480 | free_pages_exact(virt, size); |
| 320 | } | 481 | } |
| @@ -330,82 +491,72 @@ void wr_reg_wa(u32 *reg, u32 val) | |||
| 330 | } while (in_be32(reg) != val); | 491 | } while (in_be32(reg) != val); |
| 331 | } | 492 | } |
| 332 | 493 | ||
| 333 | static int fsl_diu_enable_panel(struct fb_info *info) | 494 | static void fsl_diu_enable_panel(struct fb_info *info) |
| 334 | { | 495 | { |
| 335 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 496 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
| 336 | struct diu *hw = dr.diu_reg; | ||
| 337 | struct diu_ad *ad = mfbi->ad; | 497 | struct diu_ad *ad = mfbi->ad; |
| 338 | struct fsl_diu_data *machine_data = mfbi->parent; | 498 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 339 | int res = 0; | 499 | struct diu __iomem *hw = machine_data->diu_reg; |
| 340 | 500 | ||
| 341 | pr_debug("enable_panel index %d\n", mfbi->index); | 501 | switch (mfbi->index) { |
| 342 | if (mfbi->type != MFB_TYPE_OFF) { | 502 | case PLANE0: |
| 343 | switch (mfbi->index) { | 503 | if (hw->desc[0] != ad->paddr) |
| 344 | case 0: /* plane 0 */ | 504 | wr_reg_wa(&hw->desc[0], ad->paddr); |
| 345 | if (hw->desc[0] != ad->paddr) | 505 | break; |
| 346 | wr_reg_wa(&hw->desc[0], ad->paddr); | 506 | case PLANE1_AOI0: |
| 347 | break; | 507 | cmfbi = machine_data->fsl_diu_info[2]->par; |
| 348 | case 1: /* plane 1 AOI 0 */ | 508 | if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ |
| 349 | cmfbi = machine_data->fsl_diu_info[2]->par; | 509 | if (cmfbi->count > 0) /* AOI1 open */ |
| 350 | if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ | 510 | ad->next_ad = |
| 351 | if (cmfbi->count > 0) /* AOI1 open */ | 511 | cpu_to_le32(cmfbi->ad->paddr); |
| 352 | ad->next_ad = | 512 | else |
| 353 | cpu_to_le32(cmfbi->ad->paddr); | 513 | ad->next_ad = 0; |
| 354 | else | 514 | wr_reg_wa(&hw->desc[1], ad->paddr); |
| 355 | ad->next_ad = 0; | ||
| 356 | wr_reg_wa(&hw->desc[1], ad->paddr); | ||
| 357 | } | ||
| 358 | break; | ||
| 359 | case 3: /* plane 2 AOI 0 */ | ||
| 360 | cmfbi = machine_data->fsl_diu_info[4]->par; | ||
| 361 | if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ | ||
| 362 | if (cmfbi->count > 0) /* AOI1 open */ | ||
| 363 | ad->next_ad = | ||
| 364 | cpu_to_le32(cmfbi->ad->paddr); | ||
| 365 | else | ||
| 366 | ad->next_ad = 0; | ||
| 367 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
| 368 | } | ||
| 369 | break; | ||
| 370 | case 2: /* plane 1 AOI 1 */ | ||
| 371 | pmfbi = machine_data->fsl_diu_info[1]->par; | ||
| 372 | ad->next_ad = 0; | ||
| 373 | if (hw->desc[1] == machine_data->dummy_ad->paddr) | ||
| 374 | wr_reg_wa(&hw->desc[1], ad->paddr); | ||
| 375 | else /* AOI0 open */ | ||
| 376 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
| 377 | break; | ||
| 378 | case 4: /* plane 2 AOI 1 */ | ||
| 379 | pmfbi = machine_data->fsl_diu_info[3]->par; | ||
| 380 | ad->next_ad = 0; | ||
| 381 | if (hw->desc[2] == machine_data->dummy_ad->paddr) | ||
| 382 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
| 383 | else /* AOI0 was open */ | ||
| 384 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
| 385 | break; | ||
| 386 | default: | ||
| 387 | res = -EINVAL; | ||
| 388 | break; | ||
| 389 | } | 515 | } |
| 390 | } else | 516 | break; |
| 391 | res = -EINVAL; | 517 | case PLANE2_AOI0: |
| 392 | return res; | 518 | cmfbi = machine_data->fsl_diu_info[4]->par; |
| 519 | if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ | ||
| 520 | if (cmfbi->count > 0) /* AOI1 open */ | ||
| 521 | ad->next_ad = | ||
| 522 | cpu_to_le32(cmfbi->ad->paddr); | ||
| 523 | else | ||
| 524 | ad->next_ad = 0; | ||
| 525 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
| 526 | } | ||
| 527 | break; | ||
| 528 | case PLANE1_AOI1: | ||
| 529 | pmfbi = machine_data->fsl_diu_info[1]->par; | ||
| 530 | ad->next_ad = 0; | ||
| 531 | if (hw->desc[1] == machine_data->dummy_ad->paddr) | ||
| 532 | wr_reg_wa(&hw->desc[1], ad->paddr); | ||
| 533 | else /* AOI0 open */ | ||
| 534 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
| 535 | break; | ||
| 536 | case PLANE2_AOI1: | ||
| 537 | pmfbi = machine_data->fsl_diu_info[3]->par; | ||
| 538 | ad->next_ad = 0; | ||
| 539 | if (hw->desc[2] == machine_data->dummy_ad->paddr) | ||
| 540 | wr_reg_wa(&hw->desc[2], ad->paddr); | ||
| 541 | else /* AOI0 was open */ | ||
| 542 | pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); | ||
| 543 | break; | ||
| 544 | } | ||
| 393 | } | 545 | } |
| 394 | 546 | ||
| 395 | static int fsl_diu_disable_panel(struct fb_info *info) | 547 | static void fsl_diu_disable_panel(struct fb_info *info) |
| 396 | { | 548 | { |
| 397 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; | 549 | struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; |
| 398 | struct diu *hw = dr.diu_reg; | ||
| 399 | struct diu_ad *ad = mfbi->ad; | 550 | struct diu_ad *ad = mfbi->ad; |
| 400 | struct fsl_diu_data *machine_data = mfbi->parent; | 551 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 401 | int res = 0; | 552 | struct diu __iomem *hw = machine_data->diu_reg; |
| 402 | 553 | ||
| 403 | switch (mfbi->index) { | 554 | switch (mfbi->index) { |
| 404 | case 0: /* plane 0 */ | 555 | case PLANE0: |
| 405 | if (hw->desc[0] != machine_data->dummy_ad->paddr) | 556 | if (hw->desc[0] != machine_data->dummy_ad->paddr) |
| 406 | wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); | 557 | wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); |
| 407 | break; | 558 | break; |
| 408 | case 1: /* plane 1 AOI 0 */ | 559 | case PLANE1_AOI0: |
| 409 | cmfbi = machine_data->fsl_diu_info[2]->par; | 560 | cmfbi = machine_data->fsl_diu_info[2]->par; |
| 410 | if (cmfbi->count > 0) /* AOI1 is open */ | 561 | if (cmfbi->count > 0) /* AOI1 is open */ |
| 411 | wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); | 562 | wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); |
| @@ -414,7 +565,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
| 414 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); | 565 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); |
| 415 | /* close AOI 0 */ | 566 | /* close AOI 0 */ |
| 416 | break; | 567 | break; |
| 417 | case 3: /* plane 2 AOI 0 */ | 568 | case PLANE2_AOI0: |
| 418 | cmfbi = machine_data->fsl_diu_info[4]->par; | 569 | cmfbi = machine_data->fsl_diu_info[4]->par; |
| 419 | if (cmfbi->count > 0) /* AOI1 is open */ | 570 | if (cmfbi->count > 0) /* AOI1 is open */ |
| 420 | wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); | 571 | wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); |
| @@ -423,7 +574,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
| 423 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); | 574 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); |
| 424 | /* close AOI 0 */ | 575 | /* close AOI 0 */ |
| 425 | break; | 576 | break; |
| 426 | case 2: /* plane 1 AOI 1 */ | 577 | case PLANE1_AOI1: |
| 427 | pmfbi = machine_data->fsl_diu_info[1]->par; | 578 | pmfbi = machine_data->fsl_diu_info[1]->par; |
| 428 | if (hw->desc[1] != ad->paddr) { | 579 | if (hw->desc[1] != ad->paddr) { |
| 429 | /* AOI1 is not the first in the chain */ | 580 | /* AOI1 is not the first in the chain */ |
| @@ -434,7 +585,7 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
| 434 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); | 585 | wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); |
| 435 | /* close AOI 1 */ | 586 | /* close AOI 1 */ |
| 436 | break; | 587 | break; |
| 437 | case 4: /* plane 2 AOI 1 */ | 588 | case PLANE2_AOI1: |
| 438 | pmfbi = machine_data->fsl_diu_info[3]->par; | 589 | pmfbi = machine_data->fsl_diu_info[3]->par; |
| 439 | if (hw->desc[2] != ad->paddr) { | 590 | if (hw->desc[2] != ad->paddr) { |
| 440 | /* AOI1 is not the first in the chain */ | 591 | /* AOI1 is not the first in the chain */ |
| @@ -445,31 +596,26 @@ static int fsl_diu_disable_panel(struct fb_info *info) | |||
| 445 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); | 596 | wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); |
| 446 | /* close AOI 1 */ | 597 | /* close AOI 1 */ |
| 447 | break; | 598 | break; |
| 448 | default: | ||
| 449 | res = -EINVAL; | ||
| 450 | break; | ||
| 451 | } | 599 | } |
| 452 | |||
| 453 | return res; | ||
| 454 | } | 600 | } |
| 455 | 601 | ||
| 456 | static void enable_lcdc(struct fb_info *info) | 602 | static void enable_lcdc(struct fb_info *info) |
| 457 | { | 603 | { |
| 458 | struct diu *hw = dr.diu_reg; | ||
| 459 | struct mfb_info *mfbi = info->par; | 604 | struct mfb_info *mfbi = info->par; |
| 460 | struct fsl_diu_data *machine_data = mfbi->parent; | 605 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 606 | struct diu __iomem *hw = machine_data->diu_reg; | ||
| 461 | 607 | ||
| 462 | if (!machine_data->fb_enabled) { | 608 | if (!machine_data->fb_enabled) { |
| 463 | out_be32(&hw->diu_mode, dr.mode); | 609 | out_be32(&hw->diu_mode, MFB_MODE1); |
| 464 | machine_data->fb_enabled++; | 610 | machine_data->fb_enabled++; |
| 465 | } | 611 | } |
| 466 | } | 612 | } |
| 467 | 613 | ||
| 468 | static void disable_lcdc(struct fb_info *info) | 614 | static void disable_lcdc(struct fb_info *info) |
| 469 | { | 615 | { |
| 470 | struct diu *hw = dr.diu_reg; | ||
| 471 | struct mfb_info *mfbi = info->par; | 616 | struct mfb_info *mfbi = info->par; |
| 472 | struct fsl_diu_data *machine_data = mfbi->parent; | 617 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 618 | struct diu __iomem *hw = machine_data->diu_reg; | ||
| 473 | 619 | ||
| 474 | if (machine_data->fb_enabled) { | 620 | if (machine_data->fb_enabled) { |
| 475 | out_be32(&hw->diu_mode, 0); | 621 | out_be32(&hw->diu_mode, 0); |
| @@ -482,7 +628,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
| 482 | { | 628 | { |
| 483 | struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; | 629 | struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; |
| 484 | struct fsl_diu_data *machine_data = mfbi->parent; | 630 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 485 | int available_height, upper_aoi_bottom, index = mfbi->index; | 631 | int available_height, upper_aoi_bottom; |
| 632 | enum mfb_index index = mfbi->index; | ||
| 486 | int lower_aoi_is_open, upper_aoi_is_open; | 633 | int lower_aoi_is_open, upper_aoi_is_open; |
| 487 | __u32 base_plane_width, base_plane_height, upper_aoi_height; | 634 | __u32 base_plane_width, base_plane_height, upper_aoi_height; |
| 488 | 635 | ||
| @@ -494,14 +641,14 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
| 494 | if (mfbi->y_aoi_d < 0) | 641 | if (mfbi->y_aoi_d < 0) |
| 495 | mfbi->y_aoi_d = 0; | 642 | mfbi->y_aoi_d = 0; |
| 496 | switch (index) { | 643 | switch (index) { |
| 497 | case 0: | 644 | case PLANE0: |
| 498 | if (mfbi->x_aoi_d != 0) | 645 | if (mfbi->x_aoi_d != 0) |
| 499 | mfbi->x_aoi_d = 0; | 646 | mfbi->x_aoi_d = 0; |
| 500 | if (mfbi->y_aoi_d != 0) | 647 | if (mfbi->y_aoi_d != 0) |
| 501 | mfbi->y_aoi_d = 0; | 648 | mfbi->y_aoi_d = 0; |
| 502 | break; | 649 | break; |
| 503 | case 1: /* AOI 0 */ | 650 | case PLANE1_AOI0: |
| 504 | case 3: | 651 | case PLANE2_AOI0: |
| 505 | lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; | 652 | lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; |
| 506 | lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; | 653 | lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; |
| 507 | if (var->xres > base_plane_width) | 654 | if (var->xres > base_plane_width) |
| @@ -518,8 +665,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
| 518 | if ((mfbi->y_aoi_d + var->yres) > available_height) | 665 | if ((mfbi->y_aoi_d + var->yres) > available_height) |
| 519 | mfbi->y_aoi_d = available_height - var->yres; | 666 | mfbi->y_aoi_d = available_height - var->yres; |
| 520 | break; | 667 | break; |
| 521 | case 2: /* AOI 1 */ | 668 | case PLANE1_AOI1: |
| 522 | case 4: | 669 | case PLANE2_AOI1: |
| 523 | upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; | 670 | upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; |
| 524 | upper_aoi_height = | 671 | upper_aoi_height = |
| 525 | machine_data->fsl_diu_info[index-1]->var.yres; | 672 | machine_data->fsl_diu_info[index-1]->var.yres; |
| @@ -555,9 +702,6 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var, | |||
| 555 | static int fsl_diu_check_var(struct fb_var_screeninfo *var, | 702 | static int fsl_diu_check_var(struct fb_var_screeninfo *var, |
| 556 | struct fb_info *info) | 703 | struct fb_info *info) |
| 557 | { | 704 | { |
| 558 | pr_debug("check_var xres: %d\n", var->xres); | ||
| 559 | pr_debug("check_var yres: %d\n", var->yres); | ||
| 560 | |||
| 561 | if (var->xres_virtual < var->xres) | 705 | if (var->xres_virtual < var->xres) |
| 562 | var->xres_virtual = var->xres; | 706 | var->xres_virtual = var->xres; |
| 563 | if (var->yres_virtual < var->yres) | 707 | if (var->yres_virtual < var->yres) |
| @@ -652,7 +796,7 @@ static void set_fix(struct fb_info *info) | |||
| 652 | struct fb_var_screeninfo *var = &info->var; | 796 | struct fb_var_screeninfo *var = &info->var; |
| 653 | struct mfb_info *mfbi = info->par; | 797 | struct mfb_info *mfbi = info->par; |
| 654 | 798 | ||
| 655 | strncpy(fix->id, mfbi->id, strlen(mfbi->id)); | 799 | strncpy(fix->id, mfbi->id, sizeof(fix->id)); |
| 656 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; | 800 | fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; |
| 657 | fix->type = FB_TYPE_PACKED_PIXELS; | 801 | fix->type = FB_TYPE_PACKED_PIXELS; |
| 658 | fix->accel = FB_ACCEL_NONE; | 802 | fix->accel = FB_ACCEL_NONE; |
| @@ -666,45 +810,37 @@ static void update_lcdc(struct fb_info *info) | |||
| 666 | struct fb_var_screeninfo *var = &info->var; | 810 | struct fb_var_screeninfo *var = &info->var; |
| 667 | struct mfb_info *mfbi = info->par; | 811 | struct mfb_info *mfbi = info->par; |
| 668 | struct fsl_diu_data *machine_data = mfbi->parent; | 812 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 669 | struct diu *hw; | 813 | struct diu __iomem *hw; |
| 670 | int i, j; | 814 | int i, j; |
| 671 | char __iomem *cursor_base, *gamma_table_base; | 815 | char __iomem *cursor_base, *gamma_table_base; |
| 672 | 816 | ||
| 673 | u32 temp; | 817 | u32 temp; |
| 674 | 818 | ||
| 675 | hw = dr.diu_reg; | 819 | hw = machine_data->diu_reg; |
| 676 | |||
| 677 | if (mfbi->type == MFB_TYPE_OFF) { | ||
| 678 | fsl_diu_disable_panel(info); | ||
| 679 | return; | ||
| 680 | } | ||
| 681 | 820 | ||
| 682 | diu_ops.set_monitor_port(machine_data->monitor_port); | 821 | diu_ops.set_monitor_port(machine_data->monitor_port); |
| 683 | gamma_table_base = pool.gamma.vaddr; | 822 | gamma_table_base = machine_data->gamma.vaddr; |
| 684 | cursor_base = pool.cursor.vaddr; | 823 | cursor_base = machine_data->cursor.vaddr; |
| 685 | /* Prep for DIU init - gamma table, cursor table */ | 824 | /* Prep for DIU init - gamma table, cursor table */ |
| 686 | 825 | ||
| 687 | for (i = 0; i <= 2; i++) | 826 | for (i = 0; i <= 2; i++) |
| 688 | for (j = 0; j <= 255; j++) | 827 | for (j = 0; j <= 255; j++) |
| 689 | *gamma_table_base++ = j; | 828 | *gamma_table_base++ = j; |
| 690 | 829 | ||
| 691 | diu_ops.set_gamma_table(machine_data->monitor_port, pool.gamma.vaddr); | 830 | diu_ops.set_gamma_table(machine_data->monitor_port, |
| 831 | machine_data->gamma.vaddr); | ||
| 692 | 832 | ||
| 693 | pr_debug("update-lcdc: HW - %p\n Disabling DIU\n", hw); | ||
| 694 | disable_lcdc(info); | 833 | disable_lcdc(info); |
| 695 | 834 | ||
| 696 | /* Program DIU registers */ | 835 | /* Program DIU registers */ |
| 697 | 836 | ||
| 698 | out_be32(&hw->gamma, pool.gamma.paddr); | 837 | out_be32(&hw->gamma, machine_data->gamma.paddr); |
| 699 | out_be32(&hw->cursor, pool.cursor.paddr); | 838 | out_be32(&hw->cursor, machine_data->cursor.paddr); |
| 700 | 839 | ||
| 701 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ | 840 | out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ |
| 702 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ | 841 | out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ |
| 703 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); | 842 | out_be32(&hw->disp_size, (var->yres << 16 | var->xres)); |
| 704 | /* DISP SIZE */ | 843 | /* DISP SIZE */ |
| 705 | pr_debug("DIU xres: %d\n", var->xres); | ||
| 706 | pr_debug("DIU yres: %d\n", var->yres); | ||
| 707 | |||
| 708 | out_be32(&hw->wb_size, 0); /* WB SIZE */ | 844 | out_be32(&hw->wb_size, 0); /* WB SIZE */ |
| 709 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ | 845 | out_be32(&hw->wb_mem_addr, 0); /* WB MEM ADDR */ |
| 710 | 846 | ||
| @@ -721,15 +857,6 @@ static void update_lcdc(struct fb_info *info) | |||
| 721 | 857 | ||
| 722 | out_be32(&hw->vsyn_para, temp); | 858 | out_be32(&hw->vsyn_para, temp); |
| 723 | 859 | ||
| 724 | pr_debug("DIU right_margin - %d\n", var->right_margin); | ||
| 725 | pr_debug("DIU left_margin - %d\n", var->left_margin); | ||
| 726 | pr_debug("DIU hsync_len - %d\n", var->hsync_len); | ||
| 727 | pr_debug("DIU upper_margin - %d\n", var->upper_margin); | ||
| 728 | pr_debug("DIU lower_margin - %d\n", var->lower_margin); | ||
| 729 | pr_debug("DIU vsync_len - %d\n", var->vsync_len); | ||
| 730 | pr_debug("DIU HSYNC - 0x%08x\n", hw->hsyn_para); | ||
| 731 | pr_debug("DIU VSYNC - 0x%08x\n", hw->vsyn_para); | ||
| 732 | |||
| 733 | diu_ops.set_pixel_clock(var->pixclock); | 860 | diu_ops.set_pixel_clock(var->pixclock); |
| 734 | 861 | ||
| 735 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ | 862 | out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */ |
| @@ -746,14 +873,9 @@ static int map_video_memory(struct fb_info *info) | |||
| 746 | phys_addr_t phys; | 873 | phys_addr_t phys; |
| 747 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; | 874 | u32 smem_len = info->fix.line_length * info->var.yres_virtual; |
| 748 | 875 | ||
| 749 | pr_debug("info->var.xres_virtual = %d\n", info->var.xres_virtual); | ||
| 750 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | ||
| 751 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | ||
| 752 | pr_debug("MAP_VIDEO_MEMORY: smem_len = %u\n", smem_len); | ||
| 753 | |||
| 754 | info->screen_base = fsl_diu_alloc(smem_len, &phys); | 876 | info->screen_base = fsl_diu_alloc(smem_len, &phys); |
| 755 | if (info->screen_base == NULL) { | 877 | if (info->screen_base == NULL) { |
| 756 | printk(KERN_ERR "Unable to allocate fb memory\n"); | 878 | dev_err(info->dev, "unable to allocate fb memory\n"); |
| 757 | return -ENOMEM; | 879 | return -ENOMEM; |
| 758 | } | 880 | } |
| 759 | mutex_lock(&info->mm_lock); | 881 | mutex_lock(&info->mm_lock); |
| @@ -762,10 +884,6 @@ static int map_video_memory(struct fb_info *info) | |||
| 762 | mutex_unlock(&info->mm_lock); | 884 | mutex_unlock(&info->mm_lock); |
| 763 | info->screen_size = info->fix.smem_len; | 885 | info->screen_size = info->fix.smem_len; |
| 764 | 886 | ||
| 765 | pr_debug("Allocated fb @ paddr=0x%08lx, size=%d.\n", | ||
| 766 | info->fix.smem_start, info->fix.smem_len); | ||
| 767 | pr_debug("screen base %p\n", info->screen_base); | ||
| 768 | |||
| 769 | return 0; | 887 | return 0; |
| 770 | } | 888 | } |
| 771 | 889 | ||
| @@ -810,9 +928,9 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
| 810 | struct mfb_info *mfbi = info->par; | 928 | struct mfb_info *mfbi = info->par; |
| 811 | struct fsl_diu_data *machine_data = mfbi->parent; | 929 | struct fsl_diu_data *machine_data = mfbi->parent; |
| 812 | struct diu_ad *ad = mfbi->ad; | 930 | struct diu_ad *ad = mfbi->ad; |
| 813 | struct diu *hw; | 931 | struct diu __iomem *hw; |
| 814 | 932 | ||
| 815 | hw = dr.diu_reg; | 933 | hw = machine_data->diu_reg; |
| 816 | 934 | ||
| 817 | set_fix(info); | 935 | set_fix(info); |
| 818 | mfbi->cursor_reset = 1; | 936 | mfbi->cursor_reset = 1; |
| @@ -822,18 +940,16 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
| 822 | if (len != info->fix.smem_len) { | 940 | if (len != info->fix.smem_len) { |
| 823 | if (info->fix.smem_start) | 941 | if (info->fix.smem_start) |
| 824 | unmap_video_memory(info); | 942 | unmap_video_memory(info); |
| 825 | pr_debug("SET PAR: smem_len = %d\n", info->fix.smem_len); | ||
| 826 | 943 | ||
| 827 | /* Memory allocation for framebuffer */ | 944 | /* Memory allocation for framebuffer */ |
| 828 | if (map_video_memory(info)) { | 945 | if (map_video_memory(info)) { |
| 829 | printk(KERN_ERR "Unable to allocate fb memory 1\n"); | 946 | dev_err(info->dev, "unable to allocate fb memory 1\n"); |
| 830 | return -ENOMEM; | 947 | return -ENOMEM; |
| 831 | } | 948 | } |
| 832 | } | 949 | } |
| 833 | 950 | ||
| 834 | ad->pix_fmt = | 951 | ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port, |
| 835 | diu_ops.get_pixel_format(var->bits_per_pixel, | 952 | var->bits_per_pixel); |
| 836 | machine_data->monitor_port); | ||
| 837 | ad->addr = cpu_to_le32(info->fix.smem_start); | 953 | ad->addr = cpu_to_le32(info->fix.smem_start); |
| 838 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | | 954 | ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | |
| 839 | var->xres_virtual) | mfbi->g_alpha; | 955 | var->xres_virtual) | mfbi->g_alpha; |
| @@ -851,14 +967,14 @@ static int fsl_diu_set_par(struct fb_info *info) | |||
| 851 | ad->ckmin_g = 255; | 967 | ad->ckmin_g = 255; |
| 852 | ad->ckmin_b = 255; | 968 | ad->ckmin_b = 255; |
| 853 | 969 | ||
| 854 | if (mfbi->index == 0) | 970 | if (mfbi->index == PLANE0) |
| 855 | update_lcdc(info); | 971 | update_lcdc(info); |
| 856 | return 0; | 972 | return 0; |
| 857 | } | 973 | } |
| 858 | 974 | ||
| 859 | static inline __u32 CNVT_TOHW(__u32 val, __u32 width) | 975 | static inline __u32 CNVT_TOHW(__u32 val, __u32 width) |
| 860 | { | 976 | { |
| 861 | return ((val<<width) + 0x7FFF - val)>>16; | 977 | return ((val << width) + 0x7FFF - val) >> 16; |
| 862 | } | 978 | } |
| 863 | 979 | ||
| 864 | /* | 980 | /* |
| @@ -870,8 +986,9 @@ static inline __u32 CNVT_TOHW(__u32 val, __u32 width) | |||
| 870 | * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited | 986 | * pseudo_palette in struct fb_info. For pseudocolor mode we have a limited |
| 871 | * color palette. | 987 | * color palette. |
| 872 | */ | 988 | */ |
| 873 | static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, | 989 | static int fsl_diu_setcolreg(unsigned int regno, unsigned int red, |
| 874 | unsigned blue, unsigned transp, struct fb_info *info) | 990 | unsigned int green, unsigned int blue, |
| 991 | unsigned int transp, struct fb_info *info) | ||
| 875 | { | 992 | { |
| 876 | int ret = 1; | 993 | int ret = 1; |
| 877 | 994 | ||
| @@ -906,9 +1023,6 @@ static int fsl_diu_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
| 906 | ret = 0; | 1023 | ret = 0; |
| 907 | } | 1024 | } |
| 908 | break; | 1025 | break; |
| 909 | case FB_VISUAL_STATIC_PSEUDOCOLOR: | ||
| 910 | case FB_VISUAL_PSEUDOCOLOR: | ||
| 911 | break; | ||
| 912 | } | 1026 | } |
| 913 | 1027 | ||
| 914 | return ret; | 1028 | return ret; |
| @@ -944,37 +1058,6 @@ static int fsl_diu_pan_display(struct fb_var_screeninfo *var, | |||
| 944 | return 0; | 1058 | return 0; |
| 945 | } | 1059 | } |
| 946 | 1060 | ||
| 947 | /* | ||
| 948 | * Blank the screen if blank_mode != 0, else unblank. Return 0 if blanking | ||
| 949 | * succeeded, != 0 if un-/blanking failed. | ||
| 950 | * blank_mode == 2: suspend vsync | ||
| 951 | * blank_mode == 3: suspend hsync | ||
| 952 | * blank_mode == 4: powerdown | ||
| 953 | */ | ||
| 954 | static int fsl_diu_blank(int blank_mode, struct fb_info *info) | ||
| 955 | { | ||
| 956 | struct mfb_info *mfbi = info->par; | ||
| 957 | |||
| 958 | mfbi->blank = blank_mode; | ||
| 959 | |||
| 960 | switch (blank_mode) { | ||
| 961 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 962 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 963 | /* FIXME: fixes to enable_panel and enable lcdc needed */ | ||
| 964 | case FB_BLANK_NORMAL: | ||
| 965 | /* fsl_diu_disable_panel(info);*/ | ||
| 966 | break; | ||
| 967 | case FB_BLANK_POWERDOWN: | ||
| 968 | /* disable_lcdc(info); */ | ||
| 969 | break; | ||
| 970 | case FB_BLANK_UNBLANK: | ||
| 971 | /* fsl_diu_enable_panel(info);*/ | ||
| 972 | break; | ||
| 973 | } | ||
| 974 | |||
| 975 | return 0; | ||
| 976 | } | ||
| 977 | |||
| 978 | static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | 1061 | static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, |
| 979 | unsigned long arg) | 1062 | unsigned long arg) |
| 980 | { | 1063 | { |
| @@ -989,25 +1072,29 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 989 | if (!arg) | 1072 | if (!arg) |
| 990 | return -EINVAL; | 1073 | return -EINVAL; |
| 991 | switch (cmd) { | 1074 | switch (cmd) { |
| 1075 | case MFB_SET_PIXFMT_OLD: | ||
| 1076 | dev_warn(info->dev, | ||
| 1077 | "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n", | ||
| 1078 | MFB_SET_PIXFMT_OLD); | ||
| 992 | case MFB_SET_PIXFMT: | 1079 | case MFB_SET_PIXFMT: |
| 993 | if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) | 1080 | if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) |
| 994 | return -EFAULT; | 1081 | return -EFAULT; |
| 995 | ad->pix_fmt = pix_fmt; | 1082 | ad->pix_fmt = pix_fmt; |
| 996 | pr_debug("Set pixel format to 0x%08x\n", ad->pix_fmt); | ||
| 997 | break; | 1083 | break; |
| 1084 | case MFB_GET_PIXFMT_OLD: | ||
| 1085 | dev_warn(info->dev, | ||
| 1086 | "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n", | ||
| 1087 | MFB_GET_PIXFMT_OLD); | ||
| 998 | case MFB_GET_PIXFMT: | 1088 | case MFB_GET_PIXFMT: |
| 999 | pix_fmt = ad->pix_fmt; | 1089 | pix_fmt = ad->pix_fmt; |
| 1000 | if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) | 1090 | if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) |
| 1001 | return -EFAULT; | 1091 | return -EFAULT; |
| 1002 | pr_debug("get pixel format 0x%08x\n", ad->pix_fmt); | ||
| 1003 | break; | 1092 | break; |
| 1004 | case MFB_SET_AOID: | 1093 | case MFB_SET_AOID: |
| 1005 | if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) | 1094 | if (copy_from_user(&aoi_d, buf, sizeof(aoi_d))) |
| 1006 | return -EFAULT; | 1095 | return -EFAULT; |
| 1007 | mfbi->x_aoi_d = aoi_d.x_aoi_d; | 1096 | mfbi->x_aoi_d = aoi_d.x_aoi_d; |
| 1008 | mfbi->y_aoi_d = aoi_d.y_aoi_d; | 1097 | mfbi->y_aoi_d = aoi_d.y_aoi_d; |
| 1009 | pr_debug("set AOI display offset of index %d to (%d,%d)\n", | ||
| 1010 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | ||
| 1011 | fsl_diu_check_var(&info->var, info); | 1098 | fsl_diu_check_var(&info->var, info); |
| 1012 | fsl_diu_set_aoi(info); | 1099 | fsl_diu_set_aoi(info); |
| 1013 | break; | 1100 | break; |
| @@ -1016,14 +1103,11 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 1016 | aoi_d.y_aoi_d = mfbi->y_aoi_d; | 1103 | aoi_d.y_aoi_d = mfbi->y_aoi_d; |
| 1017 | if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) | 1104 | if (copy_to_user(buf, &aoi_d, sizeof(aoi_d))) |
| 1018 | return -EFAULT; | 1105 | return -EFAULT; |
| 1019 | pr_debug("get AOI display offset of index %d (%d,%d)\n", | ||
| 1020 | mfbi->index, aoi_d.x_aoi_d, aoi_d.y_aoi_d); | ||
| 1021 | break; | 1106 | break; |
| 1022 | case MFB_GET_ALPHA: | 1107 | case MFB_GET_ALPHA: |
| 1023 | global_alpha = mfbi->g_alpha; | 1108 | global_alpha = mfbi->g_alpha; |
| 1024 | if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) | 1109 | if (copy_to_user(buf, &global_alpha, sizeof(global_alpha))) |
| 1025 | return -EFAULT; | 1110 | return -EFAULT; |
| 1026 | pr_debug("get global alpha of index %d\n", mfbi->index); | ||
| 1027 | break; | 1111 | break; |
| 1028 | case MFB_SET_ALPHA: | 1112 | case MFB_SET_ALPHA: |
| 1029 | /* set panel information */ | 1113 | /* set panel information */ |
| @@ -1032,7 +1116,6 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 1032 | ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | | 1116 | ad->src_size_g_alpha = (ad->src_size_g_alpha & (~0xff)) | |
| 1033 | (global_alpha & 0xff); | 1117 | (global_alpha & 0xff); |
| 1034 | mfbi->g_alpha = global_alpha; | 1118 | mfbi->g_alpha = global_alpha; |
| 1035 | pr_debug("set global alpha for index %d\n", mfbi->index); | ||
| 1036 | break; | 1119 | break; |
| 1037 | case MFB_SET_CHROMA_KEY: | 1120 | case MFB_SET_CHROMA_KEY: |
| 1038 | /* set panel winformation */ | 1121 | /* set panel winformation */ |
| @@ -1060,27 +1143,9 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 1060 | ad->ckmin_g = ck.green_min; | 1143 | ad->ckmin_g = ck.green_min; |
| 1061 | ad->ckmin_b = ck.blue_min; | 1144 | ad->ckmin_b = ck.blue_min; |
| 1062 | } | 1145 | } |
| 1063 | pr_debug("set chroma key\n"); | ||
| 1064 | break; | 1146 | break; |
| 1065 | case FBIOGET_GWINFO: | ||
| 1066 | if (mfbi->type == MFB_TYPE_OFF) | ||
| 1067 | return -ENODEV; | ||
| 1068 | /* get graphic window information */ | ||
| 1069 | if (copy_to_user(buf, ad, sizeof(*ad))) | ||
| 1070 | return -EFAULT; | ||
| 1071 | break; | ||
| 1072 | case FBIOGET_HWCINFO: | ||
| 1073 | pr_debug("FBIOGET_HWCINFO:0x%08x\n", FBIOGET_HWCINFO); | ||
| 1074 | break; | ||
| 1075 | case FBIOPUT_MODEINFO: | ||
| 1076 | pr_debug("FBIOPUT_MODEINFO:0x%08x\n", FBIOPUT_MODEINFO); | ||
| 1077 | break; | ||
| 1078 | case FBIOGET_DISPINFO: | ||
| 1079 | pr_debug("FBIOGET_DISPINFO:0x%08x\n", FBIOGET_DISPINFO); | ||
| 1080 | break; | ||
| 1081 | |||
| 1082 | default: | 1147 | default: |
| 1083 | printk(KERN_ERR "Unknown ioctl command (0x%08X)\n", cmd); | 1148 | dev_err(info->dev, "unknown ioctl command (0x%08X)\n", cmd); |
| 1084 | return -ENOIOCTLCMD; | 1149 | return -ENOIOCTLCMD; |
| 1085 | } | 1150 | } |
| 1086 | 1151 | ||
| @@ -1095,22 +1160,18 @@ static int fsl_diu_open(struct fb_info *info, int user) | |||
| 1095 | int res = 0; | 1160 | int res = 0; |
| 1096 | 1161 | ||
| 1097 | /* free boot splash memory on first /dev/fb0 open */ | 1162 | /* free boot splash memory on first /dev/fb0 open */ |
| 1098 | if (!mfbi->index && diu_ops.release_bootmem) | 1163 | if ((mfbi->index == PLANE0) && diu_ops.release_bootmem) |
| 1099 | diu_ops.release_bootmem(); | 1164 | diu_ops.release_bootmem(); |
| 1100 | 1165 | ||
| 1101 | spin_lock(&diu_lock); | 1166 | spin_lock(&diu_lock); |
| 1102 | mfbi->count++; | 1167 | mfbi->count++; |
| 1103 | if (mfbi->count == 1) { | 1168 | if (mfbi->count == 1) { |
| 1104 | pr_debug("open plane index %d\n", mfbi->index); | ||
| 1105 | fsl_diu_check_var(&info->var, info); | 1169 | fsl_diu_check_var(&info->var, info); |
| 1106 | res = fsl_diu_set_par(info); | 1170 | res = fsl_diu_set_par(info); |
| 1107 | if (res < 0) | 1171 | if (res < 0) |
| 1108 | mfbi->count--; | 1172 | mfbi->count--; |
| 1109 | else { | 1173 | else |
| 1110 | res = fsl_diu_enable_panel(info); | 1174 | fsl_diu_enable_panel(info); |
| 1111 | if (res < 0) | ||
| 1112 | mfbi->count--; | ||
| 1113 | } | ||
| 1114 | } | 1175 | } |
| 1115 | 1176 | ||
| 1116 | spin_unlock(&diu_lock); | 1177 | spin_unlock(&diu_lock); |
| @@ -1126,12 +1187,9 @@ static int fsl_diu_release(struct fb_info *info, int user) | |||
| 1126 | 1187 | ||
| 1127 | spin_lock(&diu_lock); | 1188 | spin_lock(&diu_lock); |
| 1128 | mfbi->count--; | 1189 | mfbi->count--; |
| 1129 | if (mfbi->count == 0) { | 1190 | if (mfbi->count == 0) |
| 1130 | pr_debug("release plane index %d\n", mfbi->index); | 1191 | fsl_diu_disable_panel(info); |
| 1131 | res = fsl_diu_disable_panel(info); | 1192 | |
| 1132 | if (res < 0) | ||
| 1133 | mfbi->count++; | ||
| 1134 | } | ||
| 1135 | spin_unlock(&diu_lock); | 1193 | spin_unlock(&diu_lock); |
| 1136 | return res; | 1194 | return res; |
| 1137 | } | 1195 | } |
| @@ -1141,7 +1199,6 @@ static struct fb_ops fsl_diu_ops = { | |||
| 1141 | .fb_check_var = fsl_diu_check_var, | 1199 | .fb_check_var = fsl_diu_check_var, |
| 1142 | .fb_set_par = fsl_diu_set_par, | 1200 | .fb_set_par = fsl_diu_set_par, |
| 1143 | .fb_setcolreg = fsl_diu_setcolreg, | 1201 | .fb_setcolreg = fsl_diu_setcolreg, |
| 1144 | .fb_blank = fsl_diu_blank, | ||
| 1145 | .fb_pan_display = fsl_diu_pan_display, | 1202 | .fb_pan_display = fsl_diu_pan_display, |
| 1146 | .fb_fillrect = cfb_fillrect, | 1203 | .fb_fillrect = cfb_fillrect, |
| 1147 | .fb_copyarea = cfb_copyarea, | 1204 | .fb_copyarea = cfb_copyarea, |
| @@ -1178,7 +1235,7 @@ static int __devinit install_fb(struct fb_info *info) | |||
| 1178 | if (init_fbinfo(info)) | 1235 | if (init_fbinfo(info)) |
| 1179 | return -EINVAL; | 1236 | return -EINVAL; |
| 1180 | 1237 | ||
| 1181 | if (mfbi->index == 0) { /* plane 0 */ | 1238 | if (mfbi->index == PLANE0) { |
| 1182 | if (mfbi->edid_data) { | 1239 | if (mfbi->edid_data) { |
| 1183 | /* Now build modedb from EDID */ | 1240 | /* Now build modedb from EDID */ |
| 1184 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); | 1241 | fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs); |
| @@ -1192,43 +1249,23 @@ static int __devinit install_fb(struct fb_info *info) | |||
| 1192 | } else { | 1249 | } else { |
| 1193 | aoi_mode = init_aoi_mode; | 1250 | aoi_mode = init_aoi_mode; |
| 1194 | } | 1251 | } |
| 1195 | pr_debug("mode used = %s\n", aoi_mode); | 1252 | rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, NULL, |
| 1196 | rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize, | 1253 | default_bpp); |
| 1197 | &fsl_diu_default_mode, default_bpp); | 1254 | if (!rc) { |
| 1198 | switch (rc) { | ||
| 1199 | case 1: | ||
| 1200 | pr_debug("using mode specified in @mode\n"); | ||
| 1201 | break; | ||
| 1202 | case 2: | ||
| 1203 | pr_debug("using mode specified in @mode " | ||
| 1204 | "with ignored refresh rate\n"); | ||
| 1205 | break; | ||
| 1206 | case 3: | ||
| 1207 | pr_debug("using mode default mode\n"); | ||
| 1208 | break; | ||
| 1209 | case 4: | ||
| 1210 | pr_debug("using mode from list\n"); | ||
| 1211 | break; | ||
| 1212 | default: | ||
| 1213 | pr_debug("rc = %d\n", rc); | ||
| 1214 | pr_debug("failed to find mode\n"); | ||
| 1215 | /* | 1255 | /* |
| 1216 | * For plane 0 we continue and look into | 1256 | * For plane 0 we continue and look into |
| 1217 | * driver's internal modedb. | 1257 | * driver's internal modedb. |
| 1218 | */ | 1258 | */ |
| 1219 | if (mfbi->index == 0 && mfbi->edid_data) | 1259 | if ((mfbi->index == PLANE0) && mfbi->edid_data) |
| 1220 | has_default_mode = 0; | 1260 | has_default_mode = 0; |
| 1221 | else | 1261 | else |
| 1222 | return -EINVAL; | 1262 | return -EINVAL; |
| 1223 | break; | ||
| 1224 | } | 1263 | } |
| 1225 | 1264 | ||
| 1226 | if (!has_default_mode) { | 1265 | if (!has_default_mode) { |
| 1227 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, | 1266 | rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, |
| 1228 | ARRAY_SIZE(fsl_diu_mode_db), | 1267 | ARRAY_SIZE(fsl_diu_mode_db), NULL, default_bpp); |
| 1229 | &fsl_diu_default_mode, | 1268 | if (rc) |
| 1230 | default_bpp); | ||
| 1231 | if (rc > 0 && rc < 5) | ||
| 1232 | has_default_mode = 1; | 1269 | has_default_mode = 1; |
| 1233 | } | 1270 | } |
| 1234 | 1271 | ||
| @@ -1256,33 +1293,22 @@ static int __devinit install_fb(struct fb_info *info) | |||
| 1256 | fb_videomode_to_var(&info->var, modedb); | 1293 | fb_videomode_to_var(&info->var, modedb); |
| 1257 | } | 1294 | } |
| 1258 | 1295 | ||
| 1259 | pr_debug("xres_virtual %d\n", info->var.xres_virtual); | ||
| 1260 | pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); | ||
| 1261 | |||
| 1262 | pr_debug("info->var.yres_virtual = %d\n", info->var.yres_virtual); | ||
| 1263 | pr_debug("info->fix.line_length = %d\n", info->fix.line_length); | ||
| 1264 | |||
| 1265 | if (mfbi->type == MFB_TYPE_OFF) | ||
| 1266 | mfbi->blank = FB_BLANK_NORMAL; | ||
| 1267 | else | ||
| 1268 | mfbi->blank = FB_BLANK_UNBLANK; | ||
| 1269 | |||
| 1270 | if (fsl_diu_check_var(&info->var, info)) { | 1296 | if (fsl_diu_check_var(&info->var, info)) { |
| 1271 | printk(KERN_ERR "fb_check_var failed"); | 1297 | dev_err(info->dev, "fsl_diu_check_var failed\n"); |
| 1298 | unmap_video_memory(info); | ||
| 1272 | fb_dealloc_cmap(&info->cmap); | 1299 | fb_dealloc_cmap(&info->cmap); |
| 1273 | return -EINVAL; | 1300 | return -EINVAL; |
| 1274 | } | 1301 | } |
| 1275 | 1302 | ||
| 1276 | if (register_framebuffer(info) < 0) { | 1303 | if (register_framebuffer(info) < 0) { |
| 1277 | printk(KERN_ERR "register_framebuffer failed"); | 1304 | dev_err(info->dev, "register_framebuffer failed\n"); |
| 1278 | unmap_video_memory(info); | 1305 | unmap_video_memory(info); |
| 1279 | fb_dealloc_cmap(&info->cmap); | 1306 | fb_dealloc_cmap(&info->cmap); |
| 1280 | return -EINVAL; | 1307 | return -EINVAL; |
| 1281 | } | 1308 | } |
| 1282 | 1309 | ||
| 1283 | mfbi->registered = 1; | 1310 | mfbi->registered = 1; |
| 1284 | printk(KERN_INFO "fb%d: %s fb device registered successfully.\n", | 1311 | dev_info(info->dev, "%s registered successfully\n", mfbi->id); |
| 1285 | info->node, info->fix.id); | ||
| 1286 | 1312 | ||
| 1287 | return 0; | 1313 | return 0; |
| 1288 | } | 1314 | } |
| @@ -1294,7 +1320,7 @@ static void uninstall_fb(struct fb_info *info) | |||
| 1294 | if (!mfbi->registered) | 1320 | if (!mfbi->registered) |
| 1295 | return; | 1321 | return; |
| 1296 | 1322 | ||
| 1297 | if (mfbi->index == 0) | 1323 | if (mfbi->index == PLANE0) |
| 1298 | kfree(mfbi->edid_data); | 1324 | kfree(mfbi->edid_data); |
| 1299 | 1325 | ||
| 1300 | unregister_framebuffer(info); | 1326 | unregister_framebuffer(info); |
| @@ -1307,20 +1333,20 @@ static void uninstall_fb(struct fb_info *info) | |||
| 1307 | 1333 | ||
| 1308 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | 1334 | static irqreturn_t fsl_diu_isr(int irq, void *dev_id) |
| 1309 | { | 1335 | { |
| 1310 | struct diu *hw = dr.diu_reg; | 1336 | struct diu __iomem *hw = dev_id; |
| 1311 | unsigned int status = in_be32(&hw->int_status); | 1337 | unsigned int status = in_be32(&hw->int_status); |
| 1312 | 1338 | ||
| 1313 | if (status) { | 1339 | if (status) { |
| 1314 | /* This is the workaround for underrun */ | 1340 | /* This is the workaround for underrun */ |
| 1315 | if (status & INT_UNDRUN) { | 1341 | if (status & INT_UNDRUN) { |
| 1316 | out_be32(&hw->diu_mode, 0); | 1342 | out_be32(&hw->diu_mode, 0); |
| 1317 | pr_debug("Err: DIU occurs underrun!\n"); | ||
| 1318 | udelay(1); | 1343 | udelay(1); |
| 1319 | out_be32(&hw->diu_mode, 1); | 1344 | out_be32(&hw->diu_mode, 1); |
| 1320 | } | 1345 | } |
| 1321 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1346 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
| 1322 | else if (status & INT_VSYNC) { | 1347 | else if (status & INT_VSYNC) { |
| 1323 | unsigned int i; | 1348 | unsigned int i; |
| 1349 | |||
| 1324 | for (i = 0; i < coherence_data_size; | 1350 | for (i = 0; i < coherence_data_size; |
| 1325 | i += d_cache_line_size) | 1351 | i += d_cache_line_size) |
| 1326 | __asm__ __volatile__ ( | 1352 | __asm__ __volatile__ ( |
| @@ -1333,43 +1359,38 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id) | |||
| 1333 | return IRQ_NONE; | 1359 | return IRQ_NONE; |
| 1334 | } | 1360 | } |
| 1335 | 1361 | ||
| 1336 | static int request_irq_local(int irq) | 1362 | static int request_irq_local(struct fsl_diu_data *machine_data) |
| 1337 | { | 1363 | { |
| 1338 | unsigned long status, ints; | 1364 | struct diu __iomem *hw = machine_data->diu_reg; |
| 1339 | struct diu *hw; | 1365 | u32 ints; |
| 1340 | int ret; | 1366 | int ret; |
| 1341 | 1367 | ||
| 1342 | hw = dr.diu_reg; | ||
| 1343 | |||
| 1344 | /* Read to clear the status */ | 1368 | /* Read to clear the status */ |
| 1345 | status = in_be32(&hw->int_status); | 1369 | in_be32(&hw->int_status); |
| 1346 | 1370 | ||
| 1347 | ret = request_irq(irq, fsl_diu_isr, 0, "diu", NULL); | 1371 | ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); |
| 1348 | if (ret) | 1372 | if (!ret) { |
| 1349 | pr_info("Request diu IRQ failed.\n"); | ||
| 1350 | else { | ||
| 1351 | ints = INT_PARERR | INT_LS_BF_VS; | 1373 | ints = INT_PARERR | INT_LS_BF_VS; |
| 1352 | #if !defined(CONFIG_NOT_COHERENT_CACHE) | 1374 | #if !defined(CONFIG_NOT_COHERENT_CACHE) |
| 1353 | ints |= INT_VSYNC; | 1375 | ints |= INT_VSYNC; |
| 1354 | #endif | 1376 | #endif |
| 1355 | if (dr.mode == MFB_MODE2 || dr.mode == MFB_MODE3) | ||
| 1356 | ints |= INT_VSYNC_WB; | ||
| 1357 | 1377 | ||
| 1358 | /* Read to clear the status */ | 1378 | /* Read to clear the status */ |
| 1359 | status = in_be32(&hw->int_status); | 1379 | in_be32(&hw->int_status); |
| 1360 | out_be32(&hw->int_mask, ints); | 1380 | out_be32(&hw->int_mask, ints); |
| 1361 | } | 1381 | } |
| 1382 | |||
| 1362 | return ret; | 1383 | return ret; |
| 1363 | } | 1384 | } |
| 1364 | 1385 | ||
| 1365 | static void free_irq_local(int irq) | 1386 | static void free_irq_local(struct fsl_diu_data *machine_data) |
| 1366 | { | 1387 | { |
| 1367 | struct diu *hw = dr.diu_reg; | 1388 | struct diu __iomem *hw = machine_data->diu_reg; |
| 1368 | 1389 | ||
| 1369 | /* Disable all LCDC interrupt */ | 1390 | /* Disable all LCDC interrupt */ |
| 1370 | out_be32(&hw->int_mask, 0x1f); | 1391 | out_be32(&hw->int_mask, 0x1f); |
| 1371 | 1392 | ||
| 1372 | free_irq(irq, NULL); | 1393 | free_irq(machine_data->irq, NULL); |
| 1373 | } | 1394 | } |
| 1374 | 1395 | ||
| 1375 | #ifdef CONFIG_PM | 1396 | #ifdef CONFIG_PM |
| @@ -1406,49 +1427,42 @@ static int fsl_diu_resume(struct platform_device *ofdev) | |||
| 1406 | static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size, | 1427 | static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size, |
| 1407 | u32 bytes_align) | 1428 | u32 bytes_align) |
| 1408 | { | 1429 | { |
| 1409 | u32 offset, ssize; | 1430 | u32 offset; |
| 1410 | u32 mask; | 1431 | dma_addr_t mask; |
| 1411 | dma_addr_t paddr = 0; | ||
| 1412 | 1432 | ||
| 1413 | ssize = size + bytes_align; | 1433 | buf->vaddr = |
| 1414 | buf->vaddr = dma_alloc_coherent(dev, ssize, &paddr, GFP_DMA | | 1434 | dma_alloc_coherent(dev, size + bytes_align, &buf->paddr, |
| 1415 | __GFP_ZERO); | 1435 | GFP_DMA | __GFP_ZERO); |
| 1416 | if (!buf->vaddr) | 1436 | if (!buf->vaddr) |
| 1417 | return -ENOMEM; | 1437 | return -ENOMEM; |
| 1418 | 1438 | ||
| 1419 | buf->paddr = (__u32) paddr; | ||
| 1420 | |||
| 1421 | mask = bytes_align - 1; | 1439 | mask = bytes_align - 1; |
| 1422 | offset = (u32)buf->paddr & mask; | 1440 | offset = buf->paddr & mask; |
| 1423 | if (offset) { | 1441 | if (offset) { |
| 1424 | buf->offset = bytes_align - offset; | 1442 | buf->offset = bytes_align - offset; |
| 1425 | buf->paddr = (u32)buf->paddr + offset; | 1443 | buf->paddr = buf->paddr + offset; |
| 1426 | } else | 1444 | } else |
| 1427 | buf->offset = 0; | 1445 | buf->offset = 0; |
| 1446 | |||
| 1428 | return 0; | 1447 | return 0; |
| 1429 | } | 1448 | } |
| 1430 | 1449 | ||
| 1431 | static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, | 1450 | static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, |
| 1432 | u32 bytes_align) | 1451 | u32 bytes_align) |
| 1433 | { | 1452 | { |
| 1434 | dma_free_coherent(dev, size + bytes_align, | 1453 | dma_free_coherent(dev, size + bytes_align, buf->vaddr, |
| 1435 | buf->vaddr, (buf->paddr - buf->offset)); | 1454 | buf->paddr - buf->offset); |
| 1436 | return; | ||
| 1437 | } | 1455 | } |
| 1438 | 1456 | ||
| 1439 | static ssize_t store_monitor(struct device *device, | 1457 | static ssize_t store_monitor(struct device *device, |
| 1440 | struct device_attribute *attr, const char *buf, size_t count) | 1458 | struct device_attribute *attr, const char *buf, size_t count) |
| 1441 | { | 1459 | { |
| 1442 | int old_monitor_port; | 1460 | enum fsl_diu_monitor_port old_monitor_port; |
| 1443 | unsigned long val; | ||
| 1444 | struct fsl_diu_data *machine_data = | 1461 | struct fsl_diu_data *machine_data = |
| 1445 | container_of(attr, struct fsl_diu_data, dev_attr); | 1462 | container_of(attr, struct fsl_diu_data, dev_attr); |
| 1446 | 1463 | ||
| 1447 | if (strict_strtoul(buf, 10, &val)) | ||
| 1448 | return 0; | ||
| 1449 | |||
| 1450 | old_monitor_port = machine_data->monitor_port; | 1464 | old_monitor_port = machine_data->monitor_port; |
| 1451 | machine_data->monitor_port = diu_ops.set_sysfs_monitor_port(val); | 1465 | machine_data->monitor_port = fsl_diu_name_to_port(buf); |
| 1452 | 1466 | ||
| 1453 | if (old_monitor_port != machine_data->monitor_port) { | 1467 | if (old_monitor_port != machine_data->monitor_port) { |
| 1454 | /* All AOIs need adjust pixel format | 1468 | /* All AOIs need adjust pixel format |
| @@ -1468,16 +1482,25 @@ static ssize_t show_monitor(struct device *device, | |||
| 1468 | { | 1482 | { |
| 1469 | struct fsl_diu_data *machine_data = | 1483 | struct fsl_diu_data *machine_data = |
| 1470 | container_of(attr, struct fsl_diu_data, dev_attr); | 1484 | container_of(attr, struct fsl_diu_data, dev_attr); |
| 1471 | return diu_ops.show_monitor_port(machine_data->monitor_port, buf); | 1485 | |
| 1486 | switch (machine_data->monitor_port) { | ||
| 1487 | case FSL_DIU_PORT_DVI: | ||
| 1488 | return sprintf(buf, "DVI\n"); | ||
| 1489 | case FSL_DIU_PORT_LVDS: | ||
| 1490 | return sprintf(buf, "Single-link LVDS\n"); | ||
| 1491 | case FSL_DIU_PORT_DLVDS: | ||
| 1492 | return sprintf(buf, "Dual-link LVDS\n"); | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | return 0; | ||
| 1472 | } | 1496 | } |
| 1473 | 1497 | ||
| 1474 | static int __devinit fsl_diu_probe(struct platform_device *ofdev) | 1498 | static int __devinit fsl_diu_probe(struct platform_device *pdev) |
| 1475 | { | 1499 | { |
| 1476 | struct device_node *np = ofdev->dev.of_node; | 1500 | struct device_node *np = pdev->dev.of_node; |
| 1477 | struct mfb_info *mfbi; | 1501 | struct mfb_info *mfbi; |
| 1478 | phys_addr_t dummy_ad_addr; | 1502 | phys_addr_t dummy_ad_addr = 0; |
| 1479 | int ret, i, error = 0; | 1503 | int ret, i, error = 0; |
| 1480 | struct resource res; | ||
| 1481 | struct fsl_diu_data *machine_data; | 1504 | struct fsl_diu_data *machine_data; |
| 1482 | int diu_mode; | 1505 | int diu_mode; |
| 1483 | 1506 | ||
| @@ -1485,11 +1508,13 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
| 1485 | if (!machine_data) | 1508 | if (!machine_data) |
| 1486 | return -ENOMEM; | 1509 | return -ENOMEM; |
| 1487 | 1510 | ||
| 1511 | spin_lock_init(&machine_data->reg_lock); | ||
| 1512 | |||
| 1488 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { | 1513 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { |
| 1489 | machine_data->fsl_diu_info[i] = | 1514 | machine_data->fsl_diu_info[i] = |
| 1490 | framebuffer_alloc(sizeof(struct mfb_info), &ofdev->dev); | 1515 | framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev); |
| 1491 | if (!machine_data->fsl_diu_info[i]) { | 1516 | if (!machine_data->fsl_diu_info[i]) { |
| 1492 | dev_err(&ofdev->dev, "cannot allocate memory\n"); | 1517 | dev_err(&pdev->dev, "cannot allocate memory\n"); |
| 1493 | ret = -ENOMEM; | 1518 | ret = -ENOMEM; |
| 1494 | goto error2; | 1519 | goto error2; |
| 1495 | } | 1520 | } |
| @@ -1497,7 +1522,7 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
| 1497 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); | 1522 | memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); |
| 1498 | mfbi->parent = machine_data; | 1523 | mfbi->parent = machine_data; |
| 1499 | 1524 | ||
| 1500 | if (mfbi->index == 0) { | 1525 | if (mfbi->index == PLANE0) { |
| 1501 | const u8 *prop; | 1526 | const u8 *prop; |
| 1502 | int len; | 1527 | int len; |
| 1503 | 1528 | ||
| @@ -1509,60 +1534,49 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
| 1509 | } | 1534 | } |
| 1510 | } | 1535 | } |
| 1511 | 1536 | ||
| 1512 | ret = of_address_to_resource(np, 0, &res); | 1537 | machine_data->diu_reg = of_iomap(np, 0); |
| 1513 | if (ret) { | 1538 | if (!machine_data->diu_reg) { |
| 1514 | dev_err(&ofdev->dev, "could not obtain DIU address\n"); | 1539 | dev_err(&pdev->dev, "cannot map DIU registers\n"); |
| 1515 | goto error; | ||
| 1516 | } | ||
| 1517 | if (!res.start) { | ||
| 1518 | dev_err(&ofdev->dev, "invalid DIU address\n"); | ||
| 1519 | goto error; | ||
| 1520 | } | ||
| 1521 | dev_dbg(&ofdev->dev, "%s, res.start: 0x%08x\n", __func__, res.start); | ||
| 1522 | |||
| 1523 | dr.diu_reg = ioremap(res.start, sizeof(struct diu)); | ||
| 1524 | if (!dr.diu_reg) { | ||
| 1525 | dev_err(&ofdev->dev, "Err: can't map DIU registers!\n"); | ||
| 1526 | ret = -EFAULT; | 1540 | ret = -EFAULT; |
| 1527 | goto error2; | 1541 | goto error2; |
| 1528 | } | 1542 | } |
| 1529 | 1543 | ||
| 1530 | diu_mode = in_be32(&dr.diu_reg->diu_mode); | 1544 | diu_mode = in_be32(&machine_data->diu_reg->diu_mode); |
| 1531 | if (diu_mode != MFB_MODE1) | 1545 | if (diu_mode == MFB_MODE0) |
| 1532 | out_be32(&dr.diu_reg->diu_mode, 0); /* disable DIU */ | 1546 | out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */ |
| 1533 | 1547 | ||
| 1534 | /* Get the IRQ of the DIU */ | 1548 | /* Get the IRQ of the DIU */ |
| 1535 | machine_data->irq = irq_of_parse_and_map(np, 0); | 1549 | machine_data->irq = irq_of_parse_and_map(np, 0); |
| 1536 | 1550 | ||
| 1537 | if (!machine_data->irq) { | 1551 | if (!machine_data->irq) { |
| 1538 | dev_err(&ofdev->dev, "could not get DIU IRQ\n"); | 1552 | dev_err(&pdev->dev, "could not get DIU IRQ\n"); |
| 1539 | ret = -EINVAL; | 1553 | ret = -EINVAL; |
| 1540 | goto error; | 1554 | goto error; |
| 1541 | } | 1555 | } |
| 1542 | machine_data->monitor_port = monitor_port; | 1556 | machine_data->monitor_port = monitor_port; |
| 1543 | 1557 | ||
| 1544 | /* Area descriptor memory pool aligns to 64-bit boundary */ | 1558 | /* Area descriptor memory pool aligns to 64-bit boundary */ |
| 1545 | if (allocate_buf(&ofdev->dev, &pool.ad, | 1559 | if (allocate_buf(&pdev->dev, &machine_data->ad, |
| 1546 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) | 1560 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) |
| 1547 | return -ENOMEM; | 1561 | return -ENOMEM; |
| 1548 | 1562 | ||
| 1549 | /* Get memory for Gamma Table - 32-byte aligned memory */ | 1563 | /* Get memory for Gamma Table - 32-byte aligned memory */ |
| 1550 | if (allocate_buf(&ofdev->dev, &pool.gamma, 768, 32)) { | 1564 | if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) { |
| 1551 | ret = -ENOMEM; | 1565 | ret = -ENOMEM; |
| 1552 | goto error; | 1566 | goto error; |
| 1553 | } | 1567 | } |
| 1554 | 1568 | ||
| 1555 | /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ | 1569 | /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ |
| 1556 | if (allocate_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, | 1570 | if (allocate_buf(&pdev->dev, &machine_data->cursor, |
| 1557 | 32)) { | 1571 | MAX_CURS * MAX_CURS * 2, 32)) { |
| 1558 | ret = -ENOMEM; | 1572 | ret = -ENOMEM; |
| 1559 | goto error; | 1573 | goto error; |
| 1560 | } | 1574 | } |
| 1561 | 1575 | ||
| 1562 | i = ARRAY_SIZE(machine_data->fsl_diu_info); | 1576 | i = ARRAY_SIZE(machine_data->fsl_diu_info); |
| 1563 | machine_data->dummy_ad = (struct diu_ad *) | 1577 | machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr + |
| 1564 | ((u32)pool.ad.vaddr + pool.ad.offset) + i; | 1578 | machine_data->ad.offset) + i; |
| 1565 | machine_data->dummy_ad->paddr = pool.ad.paddr + | 1579 | machine_data->dummy_ad->paddr = machine_data->ad.paddr + |
| 1566 | i * sizeof(struct diu_ad); | 1580 | i * sizeof(struct diu_ad); |
| 1567 | machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); | 1581 | machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); |
| 1568 | if (!machine_data->dummy_aoi_virt) { | 1582 | if (!machine_data->dummy_aoi_virt) { |
| @@ -1581,30 +1595,29 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
| 1581 | * Let DIU display splash screen if it was pre-initialized | 1595 | * Let DIU display splash screen if it was pre-initialized |
| 1582 | * by the bootloader, set dummy area descriptor otherwise. | 1596 | * by the bootloader, set dummy area descriptor otherwise. |
| 1583 | */ | 1597 | */ |
| 1584 | if (diu_mode != MFB_MODE1) | 1598 | if (diu_mode == MFB_MODE0) |
| 1585 | out_be32(&dr.diu_reg->desc[0], machine_data->dummy_ad->paddr); | 1599 | out_be32(&machine_data->diu_reg->desc[0], |
| 1600 | machine_data->dummy_ad->paddr); | ||
| 1586 | 1601 | ||
| 1587 | out_be32(&dr.diu_reg->desc[1], machine_data->dummy_ad->paddr); | 1602 | out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr); |
| 1588 | out_be32(&dr.diu_reg->desc[2], machine_data->dummy_ad->paddr); | 1603 | out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr); |
| 1589 | 1604 | ||
| 1590 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { | 1605 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { |
| 1591 | machine_data->fsl_diu_info[i]->fix.smem_start = 0; | 1606 | machine_data->fsl_diu_info[i]->fix.smem_start = 0; |
| 1592 | mfbi = machine_data->fsl_diu_info[i]->par; | 1607 | mfbi = machine_data->fsl_diu_info[i]->par; |
| 1593 | mfbi->ad = (struct diu_ad *)((u32)pool.ad.vaddr | 1608 | mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr |
| 1594 | + pool.ad.offset) + i; | 1609 | + machine_data->ad.offset) + i; |
| 1595 | mfbi->ad->paddr = pool.ad.paddr + i * sizeof(struct diu_ad); | 1610 | mfbi->ad->paddr = |
| 1611 | machine_data->ad.paddr + i * sizeof(struct diu_ad); | ||
| 1596 | ret = install_fb(machine_data->fsl_diu_info[i]); | 1612 | ret = install_fb(machine_data->fsl_diu_info[i]); |
| 1597 | if (ret) { | 1613 | if (ret) { |
| 1598 | dev_err(&ofdev->dev, | 1614 | dev_err(&pdev->dev, "could not register fb %d\n", i); |
| 1599 | "Failed to register framebuffer %d\n", | ||
| 1600 | i); | ||
| 1601 | goto error; | 1615 | goto error; |
| 1602 | } | 1616 | } |
| 1603 | } | 1617 | } |
| 1604 | 1618 | ||
| 1605 | if (request_irq_local(machine_data->irq)) { | 1619 | if (request_irq_local(machine_data)) { |
| 1606 | dev_err(machine_data->fsl_diu_info[0]->dev, | 1620 | dev_err(&pdev->dev, "could not claim irq\n"); |
| 1607 | "could not request irq for diu."); | ||
| 1608 | goto error; | 1621 | goto error; |
| 1609 | } | 1622 | } |
| 1610 | 1623 | ||
| @@ -1616,29 +1629,28 @@ static int __devinit fsl_diu_probe(struct platform_device *ofdev) | |||
| 1616 | error = device_create_file(machine_data->fsl_diu_info[0]->dev, | 1629 | error = device_create_file(machine_data->fsl_diu_info[0]->dev, |
| 1617 | &machine_data->dev_attr); | 1630 | &machine_data->dev_attr); |
| 1618 | if (error) { | 1631 | if (error) { |
| 1619 | dev_err(machine_data->fsl_diu_info[0]->dev, | 1632 | dev_err(&pdev->dev, "could not create sysfs file %s\n", |
| 1620 | "could not create sysfs %s file\n", | ||
| 1621 | machine_data->dev_attr.attr.name); | 1633 | machine_data->dev_attr.attr.name); |
| 1622 | } | 1634 | } |
| 1623 | 1635 | ||
| 1624 | dev_set_drvdata(&ofdev->dev, machine_data); | 1636 | dev_set_drvdata(&pdev->dev, machine_data); |
| 1625 | return 0; | 1637 | return 0; |
| 1626 | 1638 | ||
| 1627 | error: | 1639 | error: |
| 1628 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); | 1640 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
| 1629 | i > 0; i--) | 1641 | uninstall_fb(machine_data->fsl_diu_info[i]); |
| 1630 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); | 1642 | |
| 1631 | if (pool.ad.vaddr) | 1643 | if (machine_data->ad.vaddr) |
| 1632 | free_buf(&ofdev->dev, &pool.ad, | 1644 | free_buf(&pdev->dev, &machine_data->ad, |
| 1633 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); | 1645 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); |
| 1634 | if (pool.gamma.vaddr) | 1646 | if (machine_data->gamma.vaddr) |
| 1635 | free_buf(&ofdev->dev, &pool.gamma, 768, 32); | 1647 | free_buf(&pdev->dev, &machine_data->gamma, 768, 32); |
| 1636 | if (pool.cursor.vaddr) | 1648 | if (machine_data->cursor.vaddr) |
| 1637 | free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, | 1649 | free_buf(&pdev->dev, &machine_data->cursor, |
| 1638 | 32); | 1650 | MAX_CURS * MAX_CURS * 2, 32); |
| 1639 | if (machine_data->dummy_aoi_virt) | 1651 | if (machine_data->dummy_aoi_virt) |
| 1640 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); | 1652 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); |
| 1641 | iounmap(dr.diu_reg); | 1653 | iounmap(machine_data->diu_reg); |
| 1642 | 1654 | ||
| 1643 | error2: | 1655 | error2: |
| 1644 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) | 1656 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
| @@ -1649,28 +1661,27 @@ error2: | |||
| 1649 | return ret; | 1661 | return ret; |
| 1650 | } | 1662 | } |
| 1651 | 1663 | ||
| 1652 | 1664 | static int fsl_diu_remove(struct platform_device *pdev) | |
| 1653 | static int fsl_diu_remove(struct platform_device *ofdev) | ||
| 1654 | { | 1665 | { |
| 1655 | struct fsl_diu_data *machine_data; | 1666 | struct fsl_diu_data *machine_data; |
| 1656 | int i; | 1667 | int i; |
| 1657 | 1668 | ||
| 1658 | machine_data = dev_get_drvdata(&ofdev->dev); | 1669 | machine_data = dev_get_drvdata(&pdev->dev); |
| 1659 | disable_lcdc(machine_data->fsl_diu_info[0]); | 1670 | disable_lcdc(machine_data->fsl_diu_info[0]); |
| 1660 | free_irq_local(machine_data->irq); | 1671 | free_irq_local(machine_data); |
| 1661 | for (i = ARRAY_SIZE(machine_data->fsl_diu_info); i > 0; i--) | 1672 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
| 1662 | uninstall_fb(machine_data->fsl_diu_info[i - 1]); | 1673 | uninstall_fb(machine_data->fsl_diu_info[i]); |
| 1663 | if (pool.ad.vaddr) | 1674 | if (machine_data->ad.vaddr) |
| 1664 | free_buf(&ofdev->dev, &pool.ad, | 1675 | free_buf(&pdev->dev, &machine_data->ad, |
| 1665 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); | 1676 | sizeof(struct diu_ad) * FSL_AOI_NUM, 8); |
| 1666 | if (pool.gamma.vaddr) | 1677 | if (machine_data->gamma.vaddr) |
| 1667 | free_buf(&ofdev->dev, &pool.gamma, 768, 32); | 1678 | free_buf(&pdev->dev, &machine_data->gamma, 768, 32); |
| 1668 | if (pool.cursor.vaddr) | 1679 | if (machine_data->cursor.vaddr) |
| 1669 | free_buf(&ofdev->dev, &pool.cursor, MAX_CURS * MAX_CURS * 2, | 1680 | free_buf(&pdev->dev, &machine_data->cursor, |
| 1670 | 32); | 1681 | MAX_CURS * MAX_CURS * 2, 32); |
| 1671 | if (machine_data->dummy_aoi_virt) | 1682 | if (machine_data->dummy_aoi_virt) |
| 1672 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); | 1683 | fsl_diu_free(machine_data->dummy_aoi_virt, 64); |
| 1673 | iounmap(dr.diu_reg); | 1684 | iounmap(machine_data->diu_reg); |
| 1674 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) | 1685 | for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) |
| 1675 | if (machine_data->fsl_diu_info[i]) | 1686 | if (machine_data->fsl_diu_info[i]) |
| 1676 | framebuffer_release(machine_data->fsl_diu_info[i]); | 1687 | framebuffer_release(machine_data->fsl_diu_info[i]); |
| @@ -1692,8 +1703,7 @@ static int __init fsl_diu_setup(char *options) | |||
| 1692 | if (!*opt) | 1703 | if (!*opt) |
| 1693 | continue; | 1704 | continue; |
| 1694 | if (!strncmp(opt, "monitor=", 8)) { | 1705 | if (!strncmp(opt, "monitor=", 8)) { |
| 1695 | if (!strict_strtoul(opt + 8, 10, &val) && (val <= 2)) | 1706 | monitor_port = fsl_diu_name_to_port(opt + 8); |
| 1696 | monitor_port = val; | ||
| 1697 | } else if (!strncmp(opt, "bpp=", 4)) { | 1707 | } else if (!strncmp(opt, "bpp=", 4)) { |
| 1698 | if (!strict_strtoul(opt + 4, 10, &val)) | 1708 | if (!strict_strtoul(opt + 4, 10, &val)) |
| 1699 | default_bpp = val; | 1709 | default_bpp = val; |
| @@ -1720,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, fsl_diu_match); | |||
| 1720 | 1730 | ||
| 1721 | static struct platform_driver fsl_diu_driver = { | 1731 | static struct platform_driver fsl_diu_driver = { |
| 1722 | .driver = { | 1732 | .driver = { |
| 1723 | .name = "fsl_diu", | 1733 | .name = "fsl-diu-fb", |
| 1724 | .owner = THIS_MODULE, | 1734 | .owner = THIS_MODULE, |
| 1725 | .of_match_table = fsl_diu_match, | 1735 | .of_match_table = fsl_diu_match, |
| 1726 | }, | 1736 | }, |
| @@ -1746,48 +1756,54 @@ static int __init fsl_diu_init(void) | |||
| 1746 | if (fb_get_options("fslfb", &option)) | 1756 | if (fb_get_options("fslfb", &option)) |
| 1747 | return -ENODEV; | 1757 | return -ENODEV; |
| 1748 | fsl_diu_setup(option); | 1758 | fsl_diu_setup(option); |
| 1759 | #else | ||
| 1760 | monitor_port = fsl_diu_name_to_port(monitor_string); | ||
| 1749 | #endif | 1761 | #endif |
| 1750 | printk(KERN_INFO "Freescale DIU driver\n"); | 1762 | pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n"); |
| 1751 | 1763 | ||
| 1752 | #ifdef CONFIG_NOT_COHERENT_CACHE | 1764 | #ifdef CONFIG_NOT_COHERENT_CACHE |
| 1753 | np = of_find_node_by_type(NULL, "cpu"); | 1765 | np = of_find_node_by_type(NULL, "cpu"); |
| 1754 | if (!np) { | 1766 | if (!np) { |
| 1755 | printk(KERN_ERR "Err: can't find device node 'cpu'\n"); | 1767 | pr_err("fsl-diu-fb: can't find 'cpu' device node\n"); |
| 1756 | return -ENODEV; | 1768 | return -ENODEV; |
| 1757 | } | 1769 | } |
| 1758 | 1770 | ||
| 1759 | prop = of_get_property(np, "d-cache-size", NULL); | 1771 | prop = of_get_property(np, "d-cache-size", NULL); |
| 1760 | if (prop == NULL) { | 1772 | if (prop == NULL) { |
| 1773 | pr_err("fsl-diu-fb: missing 'd-cache-size' property' " | ||
| 1774 | "in 'cpu' node\n"); | ||
| 1761 | of_node_put(np); | 1775 | of_node_put(np); |
| 1762 | return -ENODEV; | 1776 | return -ENODEV; |
| 1763 | } | 1777 | } |
| 1764 | 1778 | ||
| 1765 | /* Freescale PLRU requires 13/8 times the cache size to do a proper | 1779 | /* |
| 1766 | displacement flush | 1780 | * Freescale PLRU requires 13/8 times the cache size to do a proper |
| 1781 | * displacement flush | ||
| 1767 | */ | 1782 | */ |
| 1768 | coherence_data_size = *prop * 13; | 1783 | coherence_data_size = be32_to_cpup(prop) * 13; |
| 1769 | coherence_data_size /= 8; | 1784 | coherence_data_size /= 8; |
| 1770 | 1785 | ||
| 1771 | prop = of_get_property(np, "d-cache-line-size", NULL); | 1786 | prop = of_get_property(np, "d-cache-line-size", NULL); |
| 1772 | if (prop == NULL) { | 1787 | if (prop == NULL) { |
| 1788 | pr_err("fsl-diu-fb: missing 'd-cache-line-size' property' " | ||
| 1789 | "in 'cpu' node\n"); | ||
| 1773 | of_node_put(np); | 1790 | of_node_put(np); |
| 1774 | return -ENODEV; | 1791 | return -ENODEV; |
| 1775 | } | 1792 | } |
| 1776 | d_cache_line_size = *prop; | 1793 | d_cache_line_size = be32_to_cpup(prop); |
| 1777 | 1794 | ||
| 1778 | of_node_put(np); | 1795 | of_node_put(np); |
| 1779 | coherence_data = vmalloc(coherence_data_size); | 1796 | coherence_data = vmalloc(coherence_data_size); |
| 1780 | if (!coherence_data) | 1797 | if (!coherence_data) |
| 1781 | return -ENOMEM; | 1798 | return -ENOMEM; |
| 1782 | #endif | 1799 | #endif |
| 1800 | |||
| 1783 | ret = platform_driver_register(&fsl_diu_driver); | 1801 | ret = platform_driver_register(&fsl_diu_driver); |
| 1784 | if (ret) { | 1802 | if (ret) { |
| 1785 | printk(KERN_ERR | 1803 | pr_err("fsl-diu-fb: failed to register platform driver\n"); |
| 1786 | "fsl-diu: failed to register platform driver\n"); | ||
| 1787 | #if defined(CONFIG_NOT_COHERENT_CACHE) | 1804 | #if defined(CONFIG_NOT_COHERENT_CACHE) |
| 1788 | vfree(coherence_data); | 1805 | vfree(coherence_data); |
| 1789 | #endif | 1806 | #endif |
| 1790 | iounmap(dr.diu_reg); | ||
| 1791 | } | 1807 | } |
| 1792 | return ret; | 1808 | return ret; |
| 1793 | } | 1809 | } |
| @@ -1811,8 +1827,8 @@ module_param_named(mode, fb_mode, charp, 0); | |||
| 1811 | MODULE_PARM_DESC(mode, | 1827 | MODULE_PARM_DESC(mode, |
| 1812 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); | 1828 | "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); |
| 1813 | module_param_named(bpp, default_bpp, ulong, 0); | 1829 | module_param_named(bpp, default_bpp, ulong, 0); |
| 1814 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); | 1830 | MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified in 'mode'"); |
| 1815 | module_param_named(monitor, monitor_port, int, 0); | 1831 | module_param_named(monitor, monitor_string, charp, 0); |
| 1816 | MODULE_PARM_DESC(monitor, | 1832 | MODULE_PARM_DESC(monitor, "Specify the monitor port " |
| 1817 | "Specify the monitor port (0, 1 or 2) if supported by the platform"); | 1833 | "(\"dvi\", \"lvds\", or \"dlvds\") if supported by the platform"); |
| 1818 | 1834 | ||
diff --git a/drivers/video/g364fb.c b/drivers/video/g364fb.c index d662317d85e3..223896cc5f7d 100644 --- a/drivers/video/g364fb.c +++ b/drivers/video/g364fb.c | |||
| @@ -149,10 +149,11 @@ int g364fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
| 149 | static int g364fb_pan_display(struct fb_var_screeninfo *var, | 149 | static int g364fb_pan_display(struct fb_var_screeninfo *var, |
| 150 | struct fb_info *info) | 150 | struct fb_info *info) |
| 151 | { | 151 | { |
| 152 | if (var->xoffset || var->yoffset + var->yres > var->yres_virtual) | 152 | if (var->xoffset || |
| 153 | var->yoffset + info->var.yres > info->var.yres_virtual) | ||
| 153 | return -EINVAL; | 154 | return -EINVAL; |
| 154 | 155 | ||
| 155 | *(unsigned int *) TOP_REG = var->yoffset * var->xres; | 156 | *(unsigned int *) TOP_REG = var->yoffset * info->var.xres; |
| 156 | return 0; | 157 | return 0; |
| 157 | } | 158 | } |
| 158 | 159 | ||
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c new file mode 100644 index 000000000000..f37e02538203 --- /dev/null +++ b/drivers/video/grvga.c | |||
| @@ -0,0 +1,579 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Aeroflex Gaisler SVGACTRL framebuffer device. | ||
| 3 | * | ||
| 4 | * 2011 (c) Aeroflex Gaisler AB | ||
| 5 | * | ||
| 6 | * Full documentation of the core can be found here: | ||
| 7 | * http://www.gaisler.com/products/grlib/grip.pdf | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | * | ||
| 14 | * Contributors: Kristoffer Glembo <kristoffer@gaisler.com> | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/dma-mapping.h> | ||
| 20 | #include <linux/of_platform.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/string.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | #include <linux/tty.h> | ||
| 30 | #include <linux/mm.h> | ||
| 31 | #include <linux/fb.h> | ||
| 32 | #include <linux/io.h> | ||
| 33 | |||
| 34 | struct grvga_regs { | ||
| 35 | u32 status; /* 0x00 */ | ||
| 36 | u32 video_length; /* 0x04 */ | ||
| 37 | u32 front_porch; /* 0x08 */ | ||
| 38 | u32 sync_length; /* 0x0C */ | ||
| 39 | u32 line_length; /* 0x10 */ | ||
| 40 | u32 fb_pos; /* 0x14 */ | ||
| 41 | u32 clk_vector[4]; /* 0x18 */ | ||
| 42 | u32 clut; /* 0x20 */ | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct grvga_par { | ||
| 46 | struct grvga_regs *regs; | ||
| 47 | u32 color_palette[16]; /* 16 entry pseudo palette used by fbcon in true color mode */ | ||
| 48 | int clk_sel; | ||
| 49 | int fb_alloced; /* = 1 if framebuffer is allocated in main memory */ | ||
| 50 | }; | ||
| 51 | |||
| 52 | |||
| 53 | static const struct fb_videomode grvga_modedb[] = { | ||
| 54 | { | ||
| 55 | /* 640x480 @ 60 Hz */ | ||
| 56 | NULL, 60, 640, 480, 40000, 48, 16, 39, 11, 96, 2, | ||
| 57 | 0, FB_VMODE_NONINTERLACED | ||
| 58 | }, { | ||
| 59 | /* 800x600 @ 60 Hz */ | ||
| 60 | NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, | ||
| 61 | 0, FB_VMODE_NONINTERLACED | ||
| 62 | }, { | ||
| 63 | /* 800x600 @ 72 Hz */ | ||
| 64 | NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, | ||
| 65 | 0, FB_VMODE_NONINTERLACED | ||
| 66 | }, { | ||
| 67 | /* 1024x768 @ 60 Hz */ | ||
| 68 | NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, | ||
| 69 | 0, FB_VMODE_NONINTERLACED | ||
| 70 | } | ||
| 71 | }; | ||
| 72 | |||
| 73 | static struct fb_fix_screeninfo grvga_fix __initdata = { | ||
| 74 | .id = "AG SVGACTRL", | ||
| 75 | .type = FB_TYPE_PACKED_PIXELS, | ||
| 76 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
| 77 | .xpanstep = 0, | ||
| 78 | .ypanstep = 1, | ||
| 79 | .ywrapstep = 0, | ||
| 80 | .accel = FB_ACCEL_NONE, | ||
| 81 | }; | ||
| 82 | |||
| 83 | static int grvga_check_var(struct fb_var_screeninfo *var, | ||
| 84 | struct fb_info *info) | ||
| 85 | { | ||
| 86 | struct grvga_par *par = info->par; | ||
| 87 | int i; | ||
| 88 | |||
| 89 | if (!var->xres) | ||
| 90 | var->xres = 1; | ||
| 91 | if (!var->yres) | ||
| 92 | var->yres = 1; | ||
| 93 | if (var->bits_per_pixel <= 8) | ||
| 94 | var->bits_per_pixel = 8; | ||
| 95 | else if (var->bits_per_pixel <= 16) | ||
| 96 | var->bits_per_pixel = 16; | ||
| 97 | else if (var->bits_per_pixel <= 24) | ||
| 98 | var->bits_per_pixel = 24; | ||
| 99 | else if (var->bits_per_pixel <= 32) | ||
| 100 | var->bits_per_pixel = 32; | ||
| 101 | else | ||
| 102 | return -EINVAL; | ||
| 103 | |||
| 104 | var->xres_virtual = var->xres; | ||
| 105 | var->yres_virtual = 2*var->yres; | ||
| 106 | |||
| 107 | if (info->fix.smem_len) { | ||
| 108 | if ((var->yres_virtual*var->xres_virtual*var->bits_per_pixel/8) > info->fix.smem_len) | ||
| 109 | return -ENOMEM; | ||
| 110 | } | ||
| 111 | |||
| 112 | /* Which clocks that are available can be read out in these registers */ | ||
| 113 | for (i = 0; i <= 3 ; i++) { | ||
| 114 | if (var->pixclock == par->regs->clk_vector[i]) | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | if (i <= 3) | ||
| 118 | par->clk_sel = i; | ||
| 119 | else | ||
| 120 | return -EINVAL; | ||
| 121 | |||
| 122 | switch (info->var.bits_per_pixel) { | ||
| 123 | case 8: | ||
| 124 | var->red = (struct fb_bitfield) {0, 8, 0}; /* offset, length, msb-right */ | ||
| 125 | var->green = (struct fb_bitfield) {0, 8, 0}; | ||
| 126 | var->blue = (struct fb_bitfield) {0, 8, 0}; | ||
| 127 | var->transp = (struct fb_bitfield) {0, 0, 0}; | ||
| 128 | break; | ||
| 129 | case 16: | ||
| 130 | var->red = (struct fb_bitfield) {11, 5, 0}; | ||
| 131 | var->green = (struct fb_bitfield) {5, 6, 0}; | ||
| 132 | var->blue = (struct fb_bitfield) {0, 5, 0}; | ||
| 133 | var->transp = (struct fb_bitfield) {0, 0, 0}; | ||
| 134 | break; | ||
| 135 | case 24: | ||
| 136 | case 32: | ||
| 137 | var->red = (struct fb_bitfield) {16, 8, 0}; | ||
| 138 | var->green = (struct fb_bitfield) {8, 8, 0}; | ||
| 139 | var->blue = (struct fb_bitfield) {0, 8, 0}; | ||
| 140 | var->transp = (struct fb_bitfield) {24, 8, 0}; | ||
| 141 | break; | ||
| 142 | default: | ||
| 143 | return -EINVAL; | ||
| 144 | } | ||
| 145 | |||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int grvga_set_par(struct fb_info *info) | ||
| 150 | { | ||
| 151 | |||
| 152 | u32 func = 0; | ||
| 153 | struct grvga_par *par = info->par; | ||
| 154 | |||
| 155 | __raw_writel(((info->var.yres - 1) << 16) | (info->var.xres - 1), | ||
| 156 | &par->regs->video_length); | ||
| 157 | |||
| 158 | __raw_writel((info->var.lower_margin << 16) | (info->var.right_margin), | ||
| 159 | &par->regs->front_porch); | ||
| 160 | |||
| 161 | __raw_writel((info->var.vsync_len << 16) | (info->var.hsync_len), | ||
| 162 | &par->regs->sync_length); | ||
| 163 | |||
| 164 | __raw_writel(((info->var.yres + info->var.lower_margin + info->var.upper_margin + info->var.vsync_len - 1) << 16) | | ||
| 165 | (info->var.xres + info->var.right_margin + info->var.left_margin + info->var.hsync_len - 1), | ||
| 166 | &par->regs->line_length); | ||
| 167 | |||
| 168 | switch (info->var.bits_per_pixel) { | ||
| 169 | case 8: | ||
| 170 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
| 171 | func = 1; | ||
| 172 | break; | ||
| 173 | case 16: | ||
| 174 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 175 | func = 2; | ||
| 176 | break; | ||
| 177 | case 24: | ||
| 178 | case 32: | ||
| 179 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 180 | func = 3; | ||
| 181 | break; | ||
| 182 | default: | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | |||
| 186 | __raw_writel((par->clk_sel << 6) | (func << 4) | 1, | ||
| 187 | &par->regs->status); | ||
| 188 | |||
| 189 | info->fix.line_length = (info->var.xres_virtual*info->var.bits_per_pixel)/8; | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int grvga_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) | ||
| 194 | { | ||
| 195 | struct grvga_par *par; | ||
| 196 | par = info->par; | ||
| 197 | |||
| 198 | if (regno >= 256) /* Size of CLUT */ | ||
| 199 | return -EINVAL; | ||
| 200 | |||
| 201 | if (info->var.grayscale) { | ||
| 202 | /* grayscale = 0.30*R + 0.59*G + 0.11*B */ | ||
| 203 | red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | |||
| 208 | #define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16) | ||
| 209 | |||
| 210 | red = CNVT_TOHW(red, info->var.red.length); | ||
| 211 | green = CNVT_TOHW(green, info->var.green.length); | ||
| 212 | blue = CNVT_TOHW(blue, info->var.blue.length); | ||
| 213 | transp = CNVT_TOHW(transp, info->var.transp.length); | ||
| 214 | |||
| 215 | #undef CNVT_TOHW | ||
| 216 | |||
| 217 | /* In PSEUDOCOLOR we use the hardware CLUT */ | ||
| 218 | if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) | ||
| 219 | __raw_writel((regno << 24) | (red << 16) | (green << 8) | blue, | ||
| 220 | &par->regs->clut); | ||
| 221 | |||
| 222 | /* Truecolor uses the pseudo palette */ | ||
| 223 | else if (info->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
| 224 | u32 v; | ||
| 225 | if (regno >= 16) | ||
| 226 | return -EINVAL; | ||
| 227 | |||
| 228 | |||
| 229 | v = (red << info->var.red.offset) | | ||
| 230 | (green << info->var.green.offset) | | ||
| 231 | (blue << info->var.blue.offset) | | ||
| 232 | (transp << info->var.transp.offset); | ||
| 233 | |||
| 234 | ((u32 *) (info->pseudo_palette))[regno] = v; | ||
| 235 | } | ||
| 236 | return 0; | ||
| 237 | } | ||
| 238 | |||
| 239 | static int grvga_pan_display(struct fb_var_screeninfo *var, | ||
| 240 | struct fb_info *info) | ||
| 241 | { | ||
| 242 | struct grvga_par *par = info->par; | ||
| 243 | struct fb_fix_screeninfo *fix = &info->fix; | ||
| 244 | u32 base_addr; | ||
| 245 | |||
| 246 | if (var->xoffset != 0) | ||
| 247 | return -EINVAL; | ||
| 248 | |||
| 249 | base_addr = fix->smem_start + (var->yoffset * fix->line_length); | ||
| 250 | base_addr &= ~3UL; | ||
| 251 | |||
| 252 | /* Set framebuffer base address */ | ||
| 253 | __raw_writel(base_addr, | ||
| 254 | &par->regs->fb_pos); | ||
| 255 | |||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static struct fb_ops grvga_ops = { | ||
| 260 | .owner = THIS_MODULE, | ||
| 261 | .fb_check_var = grvga_check_var, | ||
| 262 | .fb_set_par = grvga_set_par, | ||
| 263 | .fb_setcolreg = grvga_setcolreg, | ||
| 264 | .fb_pan_display = grvga_pan_display, | ||
| 265 | .fb_fillrect = cfb_fillrect, | ||
| 266 | .fb_copyarea = cfb_copyarea, | ||
| 267 | .fb_imageblit = cfb_imageblit | ||
| 268 | }; | ||
| 269 | |||
| 270 | static int __init grvga_parse_custom(char *options, | ||
| 271 | struct fb_var_screeninfo *screendata) | ||
| 272 | { | ||
| 273 | char *this_opt; | ||
| 274 | int count = 0; | ||
| 275 | if (!options || !*options) | ||
| 276 | return -1; | ||
| 277 | |||
| 278 | while ((this_opt = strsep(&options, " ")) != NULL) { | ||
| 279 | if (!*this_opt) | ||
| 280 | continue; | ||
| 281 | |||
| 282 | switch (count) { | ||
| 283 | case 0: | ||
| 284 | screendata->pixclock = simple_strtoul(this_opt, NULL, 0); | ||
| 285 | count++; | ||
| 286 | break; | ||
| 287 | case 1: | ||
| 288 | screendata->xres = screendata->xres_virtual = simple_strtoul(this_opt, NULL, 0); | ||
| 289 | count++; | ||
| 290 | break; | ||
| 291 | case 2: | ||
| 292 | screendata->right_margin = simple_strtoul(this_opt, NULL, 0); | ||
| 293 | count++; | ||
| 294 | break; | ||
| 295 | case 3: | ||
| 296 | screendata->hsync_len = simple_strtoul(this_opt, NULL, 0); | ||
| 297 | count++; | ||
| 298 | break; | ||
| 299 | case 4: | ||
| 300 | screendata->left_margin = simple_strtoul(this_opt, NULL, 0); | ||
| 301 | count++; | ||
| 302 | break; | ||
| 303 | case 5: | ||
| 304 | screendata->yres = screendata->yres_virtual = simple_strtoul(this_opt, NULL, 0); | ||
| 305 | count++; | ||
| 306 | break; | ||
| 307 | case 6: | ||
| 308 | screendata->lower_margin = simple_strtoul(this_opt, NULL, 0); | ||
| 309 | count++; | ||
| 310 | break; | ||
| 311 | case 7: | ||
| 312 | screendata->vsync_len = simple_strtoul(this_opt, NULL, 0); | ||
| 313 | count++; | ||
| 314 | break; | ||
| 315 | case 8: | ||
| 316 | screendata->upper_margin = simple_strtoul(this_opt, NULL, 0); | ||
| 317 | count++; | ||
| 318 | break; | ||
| 319 | case 9: | ||
| 320 | screendata->bits_per_pixel = simple_strtoul(this_opt, NULL, 0); | ||
| 321 | count++; | ||
| 322 | break; | ||
| 323 | default: | ||
| 324 | return -1; | ||
| 325 | } | ||
| 326 | } | ||
| 327 | screendata->activate = FB_ACTIVATE_NOW; | ||
| 328 | screendata->vmode = FB_VMODE_NONINTERLACED; | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | static int __devinit grvga_probe(struct platform_device *dev) | ||
| 333 | { | ||
| 334 | struct fb_info *info; | ||
| 335 | int retval = -ENOMEM; | ||
| 336 | unsigned long virtual_start; | ||
| 337 | unsigned long grvga_fix_addr = 0; | ||
| 338 | unsigned long physical_start = 0; | ||
| 339 | unsigned long grvga_mem_size = 0; | ||
| 340 | struct grvga_par *par = NULL; | ||
| 341 | char *options = NULL, *mode_opt = NULL; | ||
| 342 | |||
| 343 | info = framebuffer_alloc(sizeof(struct grvga_par), &dev->dev); | ||
| 344 | if (!info) { | ||
| 345 | dev_err(&dev->dev, "framebuffer_alloc failed\n"); | ||
| 346 | return -ENOMEM; | ||
| 347 | } | ||
| 348 | |||
| 349 | /* Expecting: "grvga: modestring, [addr:<framebuffer physical address>], [size:<framebuffer size>] | ||
| 350 | * | ||
| 351 | * If modestring is custom:<custom mode string> we parse the string which then contains all videoparameters | ||
| 352 | * If address is left out, we allocate memory, | ||
| 353 | * if size is left out we only allocate enough to support the given mode. | ||
| 354 | */ | ||
| 355 | if (fb_get_options("grvga", &options)) { | ||
| 356 | retval = -ENODEV; | ||
| 357 | goto err; | ||
| 358 | } | ||
| 359 | |||
| 360 | if (!options || !*options) | ||
| 361 | options = "640x480-8@60"; | ||
| 362 | |||
| 363 | while (1) { | ||
| 364 | char *this_opt = strsep(&options, ","); | ||
| 365 | |||
| 366 | if (!this_opt) | ||
| 367 | break; | ||
| 368 | |||
| 369 | if (!strncmp(this_opt, "custom", 6)) { | ||
| 370 | if (grvga_parse_custom(this_opt, &info->var) < 0) { | ||
| 371 | dev_err(&dev->dev, "Failed to parse custom mode (%s).\n", this_opt); | ||
| 372 | retval = -EINVAL; | ||
| 373 | goto err1; | ||
| 374 | } | ||
| 375 | } else if (!strncmp(this_opt, "addr", 4)) | ||
| 376 | grvga_fix_addr = simple_strtoul(this_opt + 5, NULL, 16); | ||
| 377 | else if (!strncmp(this_opt, "size", 4)) | ||
| 378 | grvga_mem_size = simple_strtoul(this_opt + 5, NULL, 0); | ||
| 379 | else | ||
| 380 | mode_opt = this_opt; | ||
| 381 | } | ||
| 382 | |||
| 383 | par = info->par; | ||
| 384 | info->fbops = &grvga_ops; | ||
| 385 | info->fix = grvga_fix; | ||
| 386 | info->pseudo_palette = par->color_palette; | ||
| 387 | info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN; | ||
| 388 | info->fix.smem_len = grvga_mem_size; | ||
| 389 | |||
| 390 | if (!request_mem_region(dev->resource[0].start, resource_size(&dev->resource[0]), "grlib-svgactrl regs")) { | ||
| 391 | dev_err(&dev->dev, "registers already mapped\n"); | ||
| 392 | retval = -EBUSY; | ||
| 393 | goto err; | ||
| 394 | } | ||
| 395 | |||
| 396 | par->regs = of_ioremap(&dev->resource[0], 0, | ||
| 397 | resource_size(&dev->resource[0]), | ||
| 398 | "grlib-svgactrl regs"); | ||
| 399 | |||
| 400 | if (!par->regs) { | ||
| 401 | dev_err(&dev->dev, "failed to map registers\n"); | ||
| 402 | retval = -ENOMEM; | ||
| 403 | goto err1; | ||
| 404 | } | ||
| 405 | |||
| 406 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | ||
| 407 | if (retval < 0) { | ||
| 408 | dev_err(&dev->dev, "failed to allocate mem with fb_alloc_cmap\n"); | ||
| 409 | retval = -ENOMEM; | ||
| 410 | goto err2; | ||
| 411 | } | ||
| 412 | |||
| 413 | if (mode_opt) { | ||
| 414 | retval = fb_find_mode(&info->var, info, mode_opt, | ||
| 415 | grvga_modedb, sizeof(grvga_modedb), &grvga_modedb[0], 8); | ||
| 416 | if (!retval || retval == 4) { | ||
| 417 | retval = -EINVAL; | ||
| 418 | goto err3; | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | if (!grvga_mem_size) | ||
| 423 | grvga_mem_size = info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel/8; | ||
| 424 | |||
| 425 | if (grvga_fix_addr) { | ||
| 426 | /* Got framebuffer base address from argument list */ | ||
| 427 | |||
| 428 | physical_start = grvga_fix_addr; | ||
| 429 | |||
| 430 | if (!request_mem_region(physical_start, grvga_mem_size, dev->name)) { | ||
| 431 | dev_err(&dev->dev, "failed to request memory region\n"); | ||
| 432 | retval = -ENOMEM; | ||
| 433 | goto err3; | ||
| 434 | } | ||
| 435 | |||
| 436 | virtual_start = (unsigned long) ioremap(physical_start, grvga_mem_size); | ||
| 437 | |||
| 438 | if (!virtual_start) { | ||
| 439 | dev_err(&dev->dev, "error mapping framebuffer memory\n"); | ||
| 440 | retval = -ENOMEM; | ||
| 441 | goto err4; | ||
| 442 | } | ||
| 443 | } else { /* Allocate frambuffer memory */ | ||
| 444 | |||
| 445 | unsigned long page; | ||
| 446 | |||
| 447 | virtual_start = (unsigned long) __get_free_pages(GFP_DMA, | ||
| 448 | get_order(grvga_mem_size)); | ||
| 449 | if (!virtual_start) { | ||
| 450 | dev_err(&dev->dev, | ||
| 451 | "unable to allocate framebuffer memory (%lu bytes)\n", | ||
| 452 | grvga_mem_size); | ||
| 453 | retval = -ENOMEM; | ||
| 454 | goto err3; | ||
| 455 | } | ||
| 456 | |||
| 457 | physical_start = dma_map_single(&dev->dev, (void *)virtual_start, grvga_mem_size, DMA_TO_DEVICE); | ||
| 458 | |||
| 459 | /* Set page reserved so that mmap will work. This is necessary | ||
| 460 | * since we'll be remapping normal memory. | ||
| 461 | */ | ||
| 462 | for (page = virtual_start; | ||
| 463 | page < PAGE_ALIGN(virtual_start + grvga_mem_size); | ||
| 464 | page += PAGE_SIZE) { | ||
| 465 | SetPageReserved(virt_to_page(page)); | ||
| 466 | } | ||
| 467 | |||
| 468 | par->fb_alloced = 1; | ||
| 469 | } | ||
| 470 | |||
| 471 | memset((unsigned long *) virtual_start, 0, grvga_mem_size); | ||
| 472 | |||
| 473 | info->screen_base = (char __iomem *) virtual_start; | ||
| 474 | info->fix.smem_start = physical_start; | ||
| 475 | info->fix.smem_len = grvga_mem_size; | ||
| 476 | |||
| 477 | dev_set_drvdata(&dev->dev, info); | ||
| 478 | |||
| 479 | dev_info(&dev->dev, | ||
| 480 | "Aeroflex Gaisler framebuffer device (fb%d), %dx%d-%d, using %luK of video memory @ %p\n", | ||
| 481 | info->node, info->var.xres, info->var.yres, info->var.bits_per_pixel, | ||
| 482 | grvga_mem_size >> 10, info->screen_base); | ||
| 483 | |||
| 484 | retval = register_framebuffer(info); | ||
| 485 | if (retval < 0) { | ||
| 486 | dev_err(&dev->dev, "failed to register framebuffer\n"); | ||
| 487 | goto err4; | ||
| 488 | } | ||
| 489 | |||
| 490 | __raw_writel(physical_start, &par->regs->fb_pos); | ||
| 491 | __raw_writel(__raw_readl(&par->regs->status) | 1, /* Enable framebuffer */ | ||
| 492 | &par->regs->status); | ||
| 493 | |||
| 494 | return 0; | ||
| 495 | |||
| 496 | err4: | ||
| 497 | dev_set_drvdata(&dev->dev, NULL); | ||
| 498 | if (grvga_fix_addr) { | ||
| 499 | release_mem_region(physical_start, grvga_mem_size); | ||
| 500 | iounmap((void *)virtual_start); | ||
| 501 | } else | ||
| 502 | kfree((void *)virtual_start); | ||
| 503 | err3: | ||
| 504 | fb_dealloc_cmap(&info->cmap); | ||
| 505 | err2: | ||
| 506 | of_iounmap(&dev->resource[0], par->regs, | ||
| 507 | resource_size(&dev->resource[0])); | ||
| 508 | err1: | ||
| 509 | release_mem_region(dev->resource[0].start, resource_size(&dev->resource[0])); | ||
| 510 | err: | ||
| 511 | framebuffer_release(info); | ||
| 512 | |||
| 513 | return retval; | ||
| 514 | } | ||
| 515 | |||
| 516 | static int __devexit grvga_remove(struct platform_device *device) | ||
| 517 | { | ||
| 518 | struct fb_info *info = dev_get_drvdata(&device->dev); | ||
| 519 | struct grvga_par *par = info->par; | ||
| 520 | |||
| 521 | if (info) { | ||
| 522 | unregister_framebuffer(info); | ||
| 523 | fb_dealloc_cmap(&info->cmap); | ||
| 524 | |||
| 525 | of_iounmap(&device->resource[0], par->regs, | ||
| 526 | resource_size(&device->resource[0])); | ||
| 527 | release_mem_region(device->resource[0].start, resource_size(&device->resource[0])); | ||
| 528 | |||
| 529 | if (!par->fb_alloced) { | ||
| 530 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
| 531 | iounmap(info->screen_base); | ||
| 532 | } else | ||
| 533 | kfree((void *)info->screen_base); | ||
| 534 | |||
| 535 | framebuffer_release(info); | ||
| 536 | dev_set_drvdata(&device->dev, NULL); | ||
| 537 | } | ||
| 538 | |||
| 539 | return 0; | ||
| 540 | } | ||
| 541 | |||
| 542 | static struct of_device_id svgactrl_of_match[] = { | ||
| 543 | { | ||
| 544 | .name = "GAISLER_SVGACTRL", | ||
| 545 | }, | ||
| 546 | { | ||
| 547 | .name = "01_063", | ||
| 548 | }, | ||
| 549 | {}, | ||
| 550 | }; | ||
| 551 | MODULE_DEVICE_TABLE(of, svgactrl_of_match); | ||
| 552 | |||
| 553 | static struct platform_driver grvga_driver = { | ||
| 554 | .driver = { | ||
| 555 | .name = "grlib-svgactrl", | ||
| 556 | .owner = THIS_MODULE, | ||
| 557 | .of_match_table = svgactrl_of_match, | ||
| 558 | }, | ||
| 559 | .probe = grvga_probe, | ||
| 560 | .remove = __devexit_p(grvga_remove), | ||
| 561 | }; | ||
| 562 | |||
| 563 | |||
| 564 | static int __init grvga_init(void) | ||
| 565 | { | ||
| 566 | return platform_driver_register(&grvga_driver); | ||
| 567 | } | ||
| 568 | |||
| 569 | static void __exit grvga_exit(void) | ||
| 570 | { | ||
| 571 | platform_driver_unregister(&grvga_driver); | ||
| 572 | } | ||
| 573 | |||
| 574 | module_init(grvga_init); | ||
| 575 | module_exit(grvga_exit); | ||
| 576 | |||
| 577 | MODULE_LICENSE("GPL"); | ||
| 578 | MODULE_AUTHOR("Aeroflex Gaisler"); | ||
| 579 | MODULE_DESCRIPTION("Aeroflex Gaisler framebuffer device driver"); | ||
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c index 896e53dea906..0fad23f810a3 100644 --- a/drivers/video/gxt4500.c +++ b/drivers/video/gxt4500.c | |||
| @@ -543,8 +543,8 @@ static int gxt4500_pan_display(struct fb_var_screeninfo *var, | |||
| 543 | 543 | ||
| 544 | if (var->xoffset & 7) | 544 | if (var->xoffset & 7) |
| 545 | return -EINVAL; | 545 | return -EINVAL; |
| 546 | if (var->xoffset + var->xres > var->xres_virtual || | 546 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
| 547 | var->yoffset + var->yres > var->yres_virtual) | 547 | var->yoffset + info->var.yres > info->var.yres_virtual) |
| 548 | return -EINVAL; | 548 | return -EINVAL; |
| 549 | 549 | ||
| 550 | writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); | 550 | writereg(par, REFRESH_START, (var->xoffset << 16) | var->yoffset); |
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c index 4052718eefaa..4394389caf68 100644 --- a/drivers/video/hgafb.c +++ b/drivers/video/hgafb.c | |||
| @@ -422,8 +422,8 @@ static int hgafb_pan_display(struct fb_var_screeninfo *var, | |||
| 422 | var->xoffset) | 422 | var->xoffset) |
| 423 | return -EINVAL; | 423 | return -EINVAL; |
| 424 | } else { | 424 | } else { |
| 425 | if (var->xoffset + var->xres > info->var.xres_virtual | 425 | if (var->xoffset + info->var.xres > info->var.xres_virtual |
| 426 | || var->yoffset + var->yres > info->var.yres_virtual | 426 | || var->yoffset + info->var.yres > info->var.yres_virtual |
| 427 | || var->yoffset % 8) | 427 | || var->yoffset % 8) |
| 428 | return -EINVAL; | 428 | return -EINVAL; |
| 429 | } | 429 | } |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index d885c770eb84..2d97752f79a5 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
| @@ -428,7 +428,7 @@ static int __init igafb_init(void) | |||
| 428 | * | 428 | * |
| 429 | * IGS2000 has its I/O memory mapped and we want | 429 | * IGS2000 has its I/O memory mapped and we want |
| 430 | * to generate memory cycles on PCI, e.g. do ioremap(), | 430 | * to generate memory cycles on PCI, e.g. do ioremap(), |
| 431 | * then readb/writeb() as in Documentation/IO-mapping.txt. | 431 | * then readb/writeb() as in Documentation/io-mapping.txt. |
| 432 | * | 432 | * |
| 433 | * IGS1682 is more traditional, it responds to PCI I/O | 433 | * IGS1682 is more traditional, it responds to PCI I/O |
| 434 | * cycles, so we want to access it with inb()/outb(). | 434 | * cycles, so we want to access it with inb()/outb(). |
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index efb2c10656b0..8149356471e4 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c | |||
| @@ -749,7 +749,7 @@ set_offset (struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 749 | { | 749 | { |
| 750 | struct imstt_par *par = info->par; | 750 | struct imstt_par *par = info->par; |
| 751 | __u32 off = var->yoffset * (info->fix.line_length >> 3) | 751 | __u32 off = var->yoffset * (info->fix.line_length >> 3) |
| 752 | + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3); | 752 | + ((var->xoffset * (info->var.bits_per_pixel >> 3)) >> 3); |
| 753 | write_reg_le32(par->dc_regs, SSR, off); | 753 | write_reg_le32(par->dc_regs, SSR, off); |
| 754 | } | 754 | } |
| 755 | 755 | ||
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 38065cf94ac4..fbad61da359f 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
| @@ -390,12 +390,12 @@ int intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 390 | xoffset = ROUND_DOWN_TO(var->xoffset, 8); | 390 | xoffset = ROUND_DOWN_TO(var->xoffset, 8); |
| 391 | yoffset = var->yoffset; | 391 | yoffset = var->yoffset; |
| 392 | 392 | ||
| 393 | if ((xoffset + var->xres > var->xres_virtual) || | 393 | if ((xoffset + info->var.xres > info->var.xres_virtual) || |
| 394 | (yoffset + var->yres > var->yres_virtual)) | 394 | (yoffset + info->var.yres > info->var.yres_virtual)) |
| 395 | return -EINVAL; | 395 | return -EINVAL; |
| 396 | 396 | ||
| 397 | offset = (yoffset * dinfo->pitch) + | 397 | offset = (yoffset * dinfo->pitch) + |
| 398 | (xoffset * var->bits_per_pixel) / 8; | 398 | (xoffset * info->var.bits_per_pixel) / 8; |
| 399 | 399 | ||
| 400 | offset += dinfo->fb.offset << 12; | 400 | offset += dinfo->fb.offset << 12; |
| 401 | 401 | ||
diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/mb862xx/mb862xx-i2c.c index b953099edd8e..273769bb8deb 100644 --- a/drivers/video/mb862xx/mb862xx-i2c.c +++ b/drivers/video/mb862xx/mb862xx-i2c.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
| 14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/export.h> | ||
| 16 | 17 | ||
| 17 | #include "mb862xxfb.h" | 18 | #include "mb862xxfb.h" |
| 18 | #include "mb862xx_reg.h" | 19 | #include "mb862xx_reg.h" |
| @@ -23,7 +24,7 @@ static int mb862xx_i2c_wait_event(struct i2c_adapter *adap) | |||
| 23 | u32 reg; | 24 | u32 reg; |
| 24 | 25 | ||
| 25 | do { | 26 | do { |
| 26 | udelay(1); | 27 | udelay(10); |
| 27 | reg = inreg(i2c, GC_I2C_BCR); | 28 | reg = inreg(i2c, GC_I2C_BCR); |
| 28 | if (reg & (I2C_INT | I2C_BER)) | 29 | if (reg & (I2C_INT | I2C_BER)) |
| 29 | break; | 30 | break; |
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c index ee1de3e26dec..11a7a333701d 100644 --- a/drivers/video/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/mb862xx/mb862xxfbdrv.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/fb.h> | 17 | #include <linux/fb.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
| 20 | #include <linux/module.h> | ||
| 20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
| 22 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| @@ -278,7 +279,7 @@ static int mb862xxfb_pan(struct fb_var_screeninfo *var, | |||
| 278 | reg = pack(var->yoffset, var->xoffset); | 279 | reg = pack(var->yoffset, var->xoffset); |
| 279 | outreg(disp, GC_L0WY_L0WX, reg); | 280 | outreg(disp, GC_L0WY_L0WX, reg); |
| 280 | 281 | ||
| 281 | reg = pack(var->yres_virtual, var->xres_virtual); | 282 | reg = pack(info->var.yres_virtual, info->var.xres_virtual); |
| 282 | outreg(disp, GC_L0WH_L0WW, reg); | 283 | outreg(disp, GC_L0WH_L0WW, reg); |
| 283 | return 0; | 284 | return 0; |
| 284 | } | 285 | } |
| @@ -737,7 +738,7 @@ static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev) | |||
| 737 | if (mb862xx_gdc_init(par)) | 738 | if (mb862xx_gdc_init(par)) |
| 738 | goto io_unmap; | 739 | goto io_unmap; |
| 739 | 740 | ||
| 740 | if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, | 741 | if (request_irq(par->irq, mb862xx_intr, 0, |
| 741 | DRV_NAME, (void *)par)) { | 742 | DRV_NAME, (void *)par)) { |
| 742 | dev_err(dev, "Cannot request irq\n"); | 743 | dev_err(dev, "Cannot request irq\n"); |
| 743 | goto io_unmap; | 744 | goto io_unmap; |
| @@ -1073,7 +1074,7 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, | |||
| 1073 | if (mb862xx_pci_gdc_init(par)) | 1074 | if (mb862xx_pci_gdc_init(par)) |
| 1074 | goto io_unmap; | 1075 | goto io_unmap; |
| 1075 | 1076 | ||
| 1076 | if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, | 1077 | if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED, |
| 1077 | DRV_NAME, (void *)par)) { | 1078 | DRV_NAME, (void *)par)) { |
| 1078 | dev_err(dev, "Cannot request irq\n"); | 1079 | dev_err(dev, "Cannot request irq\n"); |
| 1079 | goto io_unmap; | 1080 | goto io_unmap; |
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c index afea9abbd678..6ce34160da78 100644 --- a/drivers/video/mbx/mbxfb.c +++ b/drivers/video/mbx/mbxfb.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #include "regs.h" | 34 | #include "regs.h" |
| 35 | #include "reg_bits.h" | 35 | #include "reg_bits.h" |
| 36 | 36 | ||
| 37 | static unsigned long virt_base_2700; | 37 | static void __iomem *virt_base_2700; |
| 38 | 38 | ||
| 39 | #define write_reg(val, reg) do { writel((val), (reg)); } while(0) | 39 | #define write_reg(val, reg) do { writel((val), (reg)); } while(0) |
| 40 | 40 | ||
| @@ -850,7 +850,7 @@ static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) | |||
| 850 | { | 850 | { |
| 851 | /* make frame buffer memory enter self-refresh mode */ | 851 | /* make frame buffer memory enter self-refresh mode */ |
| 852 | write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR); | 852 | write_reg_dly(LMPWR_MC_PWR_SRM, LMPWR); |
| 853 | while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) | 853 | while (readl(LMPWRSTAT) != LMPWRSTAT_MC_PWR_SRM) |
| 854 | ; /* empty statement */ | 854 | ; /* empty statement */ |
| 855 | 855 | ||
| 856 | /* reset the device, since it's initial state is 'mostly sleeping' */ | 856 | /* reset the device, since it's initial state is 'mostly sleeping' */ |
| @@ -946,7 +946,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev) | |||
| 946 | ret = -EINVAL; | 946 | ret = -EINVAL; |
| 947 | goto err3; | 947 | goto err3; |
| 948 | } | 948 | } |
| 949 | virt_base_2700 = (unsigned long)mfbi->reg_virt_addr; | 949 | virt_base_2700 = mfbi->reg_virt_addr; |
| 950 | 950 | ||
| 951 | mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, | 951 | mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, |
| 952 | res_size(mfbi->fb_req)); | 952 | res_size(mfbi->fb_req)); |
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index cb175fe7abc0..a9a907c440d7 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
| @@ -491,55 +491,56 @@ EXPORT_SYMBOL(vesa_modes); | |||
| 491 | static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, | 491 | static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, |
| 492 | const struct fb_videomode *mode, unsigned int bpp) | 492 | const struct fb_videomode *mode, unsigned int bpp) |
| 493 | { | 493 | { |
| 494 | int err = 0; | 494 | int err = 0; |
| 495 | 495 | ||
| 496 | DPRINTK("Trying mode %s %dx%d-%d@%d\n", mode->name ? mode->name : "noname", | 496 | DPRINTK("Trying mode %s %dx%d-%d@%d\n", |
| 497 | mode->xres, mode->yres, bpp, mode->refresh); | 497 | mode->name ? mode->name : "noname", |
| 498 | var->xres = mode->xres; | 498 | mode->xres, mode->yres, bpp, mode->refresh); |
| 499 | var->yres = mode->yres; | 499 | var->xres = mode->xres; |
| 500 | var->xres_virtual = mode->xres; | 500 | var->yres = mode->yres; |
| 501 | var->yres_virtual = mode->yres; | 501 | var->xres_virtual = mode->xres; |
| 502 | var->xoffset = 0; | 502 | var->yres_virtual = mode->yres; |
| 503 | var->yoffset = 0; | 503 | var->xoffset = 0; |
| 504 | var->bits_per_pixel = bpp; | 504 | var->yoffset = 0; |
| 505 | var->activate |= FB_ACTIVATE_TEST; | 505 | var->bits_per_pixel = bpp; |
| 506 | var->pixclock = mode->pixclock; | 506 | var->activate |= FB_ACTIVATE_TEST; |
| 507 | var->left_margin = mode->left_margin; | 507 | var->pixclock = mode->pixclock; |
| 508 | var->right_margin = mode->right_margin; | 508 | var->left_margin = mode->left_margin; |
| 509 | var->upper_margin = mode->upper_margin; | 509 | var->right_margin = mode->right_margin; |
| 510 | var->lower_margin = mode->lower_margin; | 510 | var->upper_margin = mode->upper_margin; |
| 511 | var->hsync_len = mode->hsync_len; | 511 | var->lower_margin = mode->lower_margin; |
| 512 | var->vsync_len = mode->vsync_len; | 512 | var->hsync_len = mode->hsync_len; |
| 513 | var->sync = mode->sync; | 513 | var->vsync_len = mode->vsync_len; |
| 514 | var->vmode = mode->vmode; | 514 | var->sync = mode->sync; |
| 515 | if (info->fbops->fb_check_var) | 515 | var->vmode = mode->vmode; |
| 516 | err = info->fbops->fb_check_var(var, info); | 516 | if (info->fbops->fb_check_var) |
| 517 | var->activate &= ~FB_ACTIVATE_TEST; | 517 | err = info->fbops->fb_check_var(var, info); |
| 518 | return err; | 518 | var->activate &= ~FB_ACTIVATE_TEST; |
| 519 | return err; | ||
| 519 | } | 520 | } |
| 520 | 521 | ||
| 521 | /** | 522 | /** |
| 522 | * fb_find_mode - finds a valid video mode | 523 | * fb_find_mode - finds a valid video mode |
| 523 | * @var: frame buffer user defined part of display | 524 | * @var: frame buffer user defined part of display |
| 524 | * @info: frame buffer info structure | 525 | * @info: frame buffer info structure |
| 525 | * @mode_option: string video mode to find | 526 | * @mode_option: string video mode to find |
| 526 | * @db: video mode database | 527 | * @db: video mode database |
| 527 | * @dbsize: size of @db | 528 | * @dbsize: size of @db |
| 528 | * @default_mode: default video mode to fall back to | 529 | * @default_mode: default video mode to fall back to |
| 529 | * @default_bpp: default color depth in bits per pixel | 530 | * @default_bpp: default color depth in bits per pixel |
| 530 | * | 531 | * |
| 531 | * Finds a suitable video mode, starting with the specified mode | 532 | * Finds a suitable video mode, starting with the specified mode |
| 532 | * in @mode_option with fallback to @default_mode. If | 533 | * in @mode_option with fallback to @default_mode. If |
| 533 | * @default_mode fails, all modes in the video mode database will | 534 | * @default_mode fails, all modes in the video mode database will |
| 534 | * be tried. | 535 | * be tried. |
| 535 | * | 536 | * |
| 536 | * Valid mode specifiers for @mode_option: | 537 | * Valid mode specifiers for @mode_option: |
| 537 | * | 538 | * |
| 538 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or | 539 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or |
| 539 | * <name>[-<bpp>][@<refresh>] | 540 | * <name>[-<bpp>][@<refresh>] |
| 540 | * | 541 | * |
| 541 | * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and | 542 | * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and |
| 542 | * <name> a string. | 543 | * <name> a string. |
| 543 | * | 544 | * |
| 544 | * If 'M' is present after yres (and before refresh/bpp if present), | 545 | * If 'M' is present after yres (and before refresh/bpp if present), |
| 545 | * the function will compute the timings using VESA(tm) Coordinated | 546 | * the function will compute the timings using VESA(tm) Coordinated |
| @@ -551,12 +552,12 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, | |||
| 551 | * | 552 | * |
| 552 | * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. | 553 | * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. |
| 553 | * | 554 | * |
| 554 | * NOTE: The passed struct @var is _not_ cleared! This allows you | 555 | * NOTE: The passed struct @var is _not_ cleared! This allows you |
| 555 | * to supply values for e.g. the grayscale and accel_flags fields. | 556 | * to supply values for e.g. the grayscale and accel_flags fields. |
| 556 | * | 557 | * |
| 557 | * Returns zero for failure, 1 if using specified @mode_option, | 558 | * Returns zero for failure, 1 if using specified @mode_option, |
| 558 | * 2 if using specified @mode_option with an ignored refresh rate, | 559 | * 2 if using specified @mode_option with an ignored refresh rate, |
| 559 | * 3 if default mode is used, 4 if fall back to any valid mode. | 560 | * 3 if default mode is used, 4 if fall back to any valid mode. |
| 560 | * | 561 | * |
| 561 | */ | 562 | */ |
| 562 | 563 | ||
| @@ -566,198 +567,203 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
| 566 | const struct fb_videomode *default_mode, | 567 | const struct fb_videomode *default_mode, |
| 567 | unsigned int default_bpp) | 568 | unsigned int default_bpp) |
| 568 | { | 569 | { |
| 569 | int i; | 570 | int i; |
| 570 | |||
| 571 | /* Set up defaults */ | ||
| 572 | if (!db) { | ||
| 573 | db = modedb; | ||
| 574 | dbsize = ARRAY_SIZE(modedb); | ||
| 575 | } | ||
| 576 | |||
| 577 | if (!default_mode) | ||
| 578 | default_mode = &db[0]; | ||
| 579 | |||
| 580 | if (!default_bpp) | ||
| 581 | default_bpp = 8; | ||
| 582 | |||
| 583 | /* Did the user specify a video mode? */ | ||
| 584 | if (!mode_option) | ||
| 585 | mode_option = fb_mode_option; | ||
| 586 | if (mode_option) { | ||
| 587 | const char *name = mode_option; | ||
| 588 | unsigned int namelen = strlen(name); | ||
| 589 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | ||
| 590 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; | ||
| 591 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; | ||
| 592 | u32 best, diff, tdiff; | ||
| 593 | |||
| 594 | for (i = namelen-1; i >= 0; i--) { | ||
| 595 | switch (name[i]) { | ||
| 596 | case '@': | ||
| 597 | namelen = i; | ||
| 598 | if (!refresh_specified && !bpp_specified && | ||
| 599 | !yres_specified) { | ||
| 600 | refresh = simple_strtol(&name[i+1], NULL, 10); | ||
| 601 | refresh_specified = 1; | ||
| 602 | if (cvt || rb) | ||
| 603 | cvt = 0; | ||
| 604 | } else | ||
| 605 | goto done; | ||
| 606 | break; | ||
| 607 | case '-': | ||
| 608 | namelen = i; | ||
| 609 | if (!bpp_specified && !yres_specified) { | ||
| 610 | bpp = simple_strtol(&name[i+1], NULL, 10); | ||
| 611 | bpp_specified = 1; | ||
| 612 | if (cvt || rb) | ||
| 613 | cvt = 0; | ||
| 614 | } else | ||
| 615 | goto done; | ||
| 616 | break; | ||
| 617 | case 'x': | ||
| 618 | if (!yres_specified) { | ||
| 619 | yres = simple_strtol(&name[i+1], NULL, 10); | ||
| 620 | yres_specified = 1; | ||
| 621 | } else | ||
| 622 | goto done; | ||
| 623 | break; | ||
| 624 | case '0' ... '9': | ||
| 625 | break; | ||
| 626 | case 'M': | ||
| 627 | if (!yres_specified) | ||
| 628 | cvt = 1; | ||
| 629 | break; | ||
| 630 | case 'R': | ||
| 631 | if (!cvt) | ||
| 632 | rb = 1; | ||
| 633 | break; | ||
| 634 | case 'm': | ||
| 635 | if (!cvt) | ||
| 636 | margins = 1; | ||
| 637 | break; | ||
| 638 | case 'i': | ||
| 639 | if (!cvt) | ||
| 640 | interlace = 1; | ||
| 641 | break; | ||
| 642 | default: | ||
| 643 | goto done; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | if (i < 0 && yres_specified) { | ||
| 647 | xres = simple_strtol(name, NULL, 10); | ||
| 648 | res_specified = 1; | ||
| 649 | } | ||
| 650 | done: | ||
| 651 | if (cvt) { | ||
| 652 | struct fb_videomode cvt_mode; | ||
| 653 | int ret; | ||
| 654 | |||
| 655 | DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres, | ||
| 656 | (refresh) ? refresh : 60, (rb) ? " reduced blanking" : | ||
| 657 | "", (margins) ? " with margins" : "", (interlace) ? | ||
| 658 | " interlaced" : ""); | ||
| 659 | |||
| 660 | memset(&cvt_mode, 0, sizeof(cvt_mode)); | ||
| 661 | cvt_mode.xres = xres; | ||
| 662 | cvt_mode.yres = yres; | ||
| 663 | cvt_mode.refresh = (refresh) ? refresh : 60; | ||
| 664 | 571 | ||
| 665 | if (interlace) | 572 | /* Set up defaults */ |
| 666 | cvt_mode.vmode |= FB_VMODE_INTERLACED; | 573 | if (!db) { |
| 667 | else | 574 | db = modedb; |
| 668 | cvt_mode.vmode &= ~FB_VMODE_INTERLACED; | 575 | dbsize = ARRAY_SIZE(modedb); |
| 576 | } | ||
| 669 | 577 | ||
| 670 | ret = fb_find_mode_cvt(&cvt_mode, margins, rb); | 578 | if (!default_mode) |
| 579 | default_mode = &db[0]; | ||
| 580 | |||
| 581 | if (!default_bpp) | ||
| 582 | default_bpp = 8; | ||
| 583 | |||
| 584 | /* Did the user specify a video mode? */ | ||
| 585 | if (!mode_option) | ||
| 586 | mode_option = fb_mode_option; | ||
| 587 | if (mode_option) { | ||
| 588 | const char *name = mode_option; | ||
| 589 | unsigned int namelen = strlen(name); | ||
| 590 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | ||
| 591 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; | ||
| 592 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0; | ||
| 593 | int margins = 0; | ||
| 594 | u32 best, diff, tdiff; | ||
| 595 | |||
| 596 | for (i = namelen-1; i >= 0; i--) { | ||
| 597 | switch (name[i]) { | ||
| 598 | case '@': | ||
| 599 | namelen = i; | ||
| 600 | if (!refresh_specified && !bpp_specified && | ||
| 601 | !yres_specified) { | ||
| 602 | refresh = simple_strtol(&name[i+1], NULL, | ||
| 603 | 10); | ||
| 604 | refresh_specified = 1; | ||
| 605 | if (cvt || rb) | ||
| 606 | cvt = 0; | ||
| 607 | } else | ||
| 608 | goto done; | ||
| 609 | break; | ||
| 610 | case '-': | ||
| 611 | namelen = i; | ||
| 612 | if (!bpp_specified && !yres_specified) { | ||
| 613 | bpp = simple_strtol(&name[i+1], NULL, | ||
| 614 | 10); | ||
| 615 | bpp_specified = 1; | ||
| 616 | if (cvt || rb) | ||
| 617 | cvt = 0; | ||
| 618 | } else | ||
| 619 | goto done; | ||
| 620 | break; | ||
| 621 | case 'x': | ||
| 622 | if (!yres_specified) { | ||
| 623 | yres = simple_strtol(&name[i+1], NULL, | ||
| 624 | 10); | ||
| 625 | yres_specified = 1; | ||
| 626 | } else | ||
| 627 | goto done; | ||
| 628 | break; | ||
| 629 | case '0' ... '9': | ||
| 630 | break; | ||
| 631 | case 'M': | ||
| 632 | if (!yres_specified) | ||
| 633 | cvt = 1; | ||
| 634 | break; | ||
| 635 | case 'R': | ||
| 636 | if (!cvt) | ||
| 637 | rb = 1; | ||
| 638 | break; | ||
| 639 | case 'm': | ||
| 640 | if (!cvt) | ||
| 641 | margins = 1; | ||
| 642 | break; | ||
| 643 | case 'i': | ||
| 644 | if (!cvt) | ||
| 645 | interlace = 1; | ||
| 646 | break; | ||
| 647 | default: | ||
| 648 | goto done; | ||
| 649 | } | ||
| 650 | } | ||
| 651 | if (i < 0 && yres_specified) { | ||
| 652 | xres = simple_strtol(name, NULL, 10); | ||
| 653 | res_specified = 1; | ||
| 654 | } | ||
| 655 | done: | ||
| 656 | if (cvt) { | ||
| 657 | struct fb_videomode cvt_mode; | ||
| 658 | int ret; | ||
| 659 | |||
| 660 | DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres, | ||
| 661 | (refresh) ? refresh : 60, | ||
| 662 | (rb) ? " reduced blanking" : "", | ||
| 663 | (margins) ? " with margins" : "", | ||
| 664 | (interlace) ? " interlaced" : ""); | ||
| 665 | |||
| 666 | memset(&cvt_mode, 0, sizeof(cvt_mode)); | ||
| 667 | cvt_mode.xres = xres; | ||
| 668 | cvt_mode.yres = yres; | ||
| 669 | cvt_mode.refresh = (refresh) ? refresh : 60; | ||
| 670 | |||
| 671 | if (interlace) | ||
| 672 | cvt_mode.vmode |= FB_VMODE_INTERLACED; | ||
| 673 | else | ||
| 674 | cvt_mode.vmode &= ~FB_VMODE_INTERLACED; | ||
| 675 | |||
| 676 | ret = fb_find_mode_cvt(&cvt_mode, margins, rb); | ||
| 677 | |||
| 678 | if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) { | ||
| 679 | DPRINTK("modedb CVT: CVT mode ok\n"); | ||
| 680 | return 1; | ||
| 681 | } | ||
| 671 | 682 | ||
| 672 | if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) { | 683 | DPRINTK("CVT mode invalid, getting mode from database\n"); |
| 673 | DPRINTK("modedb CVT: CVT mode ok\n"); | 684 | } |
| 674 | return 1; | ||
| 675 | } | ||
| 676 | 685 | ||
| 677 | DPRINTK("CVT mode invalid, getting mode from database\n"); | 686 | DPRINTK("Trying specified video mode%s %ix%i\n", |
| 678 | } | 687 | refresh_specified ? "" : " (ignoring refresh rate)", |
| 688 | xres, yres); | ||
| 679 | 689 | ||
| 680 | DPRINTK("Trying specified video mode%s %ix%i\n", | 690 | if (!refresh_specified) { |
| 681 | refresh_specified ? "" : " (ignoring refresh rate)", xres, yres); | 691 | /* |
| 682 | 692 | * If the caller has provided a custom mode database and | |
| 683 | if (!refresh_specified) { | 693 | * a valid monspecs structure, we look for the mode with |
| 684 | /* | 694 | * the highest refresh rate. Otherwise we play it safe |
| 685 | * If the caller has provided a custom mode database and a | 695 | * it and try to find a mode with a refresh rate closest |
| 686 | * valid monspecs structure, we look for the mode with the | 696 | * to the standard 60 Hz. |
| 687 | * highest refresh rate. Otherwise we play it safe it and | 697 | */ |
| 688 | * try to find a mode with a refresh rate closest to the | 698 | if (db != modedb && |
| 689 | * standard 60 Hz. | 699 | info->monspecs.vfmin && info->monspecs.vfmax && |
| 690 | */ | 700 | info->monspecs.hfmin && info->monspecs.hfmax && |
| 691 | if (db != modedb && | 701 | info->monspecs.dclkmax) { |
| 692 | info->monspecs.vfmin && info->monspecs.vfmax && | 702 | refresh = 1000; |
| 693 | info->monspecs.hfmin && info->monspecs.hfmax && | 703 | } else { |
| 694 | info->monspecs.dclkmax) { | 704 | refresh = 60; |
| 695 | refresh = 1000; | 705 | } |
| 696 | } else { | ||
| 697 | refresh = 60; | ||
| 698 | } | 706 | } |
| 699 | } | ||
| 700 | 707 | ||
| 701 | diff = -1; | 708 | diff = -1; |
| 702 | best = -1; | 709 | best = -1; |
| 703 | for (i = 0; i < dbsize; i++) { | 710 | for (i = 0; i < dbsize; i++) { |
| 704 | if ((name_matches(db[i], name, namelen) || | 711 | if ((name_matches(db[i], name, namelen) || |
| 705 | (res_specified && res_matches(db[i], xres, yres))) && | 712 | (res_specified && res_matches(db[i], xres, yres))) && |
| 706 | !fb_try_mode(var, info, &db[i], bpp)) { | 713 | !fb_try_mode(var, info, &db[i], bpp)) { |
| 707 | if (refresh_specified && db[i].refresh == refresh) { | 714 | if (refresh_specified && db[i].refresh == refresh) |
| 708 | return 1; | 715 | return 1; |
| 709 | } else { | 716 | |
| 710 | if (abs(db[i].refresh - refresh) < diff) { | 717 | if (abs(db[i].refresh - refresh) < diff) { |
| 711 | diff = abs(db[i].refresh - refresh); | 718 | diff = abs(db[i].refresh - refresh); |
| 712 | best = i; | 719 | best = i; |
| 713 | } | 720 | } |
| 714 | } | 721 | } |
| 715 | } | 722 | } |
| 716 | } | 723 | if (best != -1) { |
| 717 | if (best != -1) { | 724 | fb_try_mode(var, info, &db[best], bpp); |
| 718 | fb_try_mode(var, info, &db[best], bpp); | 725 | return (refresh_specified) ? 2 : 1; |
| 719 | return (refresh_specified) ? 2 : 1; | 726 | } |
| 720 | } | ||
| 721 | |||
| 722 | diff = 2 * (xres + yres); | ||
| 723 | best = -1; | ||
| 724 | DPRINTK("Trying best-fit modes\n"); | ||
| 725 | for (i = 0; i < dbsize; i++) { | ||
| 726 | DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); | ||
| 727 | if (!fb_try_mode(var, info, &db[i], bpp)) { | ||
| 728 | tdiff = abs(db[i].xres - xres) + | ||
| 729 | abs(db[i].yres - yres); | ||
| 730 | |||
| 731 | /* | ||
| 732 | * Penalize modes with resolutions smaller | ||
| 733 | * than requested. | ||
| 734 | */ | ||
| 735 | if (xres > db[i].xres || yres > db[i].yres) | ||
| 736 | tdiff += xres + yres; | ||
| 737 | 727 | ||
| 738 | if (diff > tdiff) { | 728 | diff = 2 * (xres + yres); |
| 739 | diff = tdiff; | 729 | best = -1; |
| 740 | best = i; | 730 | DPRINTK("Trying best-fit modes\n"); |
| 731 | for (i = 0; i < dbsize; i++) { | ||
| 732 | DPRINTK("Trying %ix%i\n", db[i].xres, db[i].yres); | ||
| 733 | if (!fb_try_mode(var, info, &db[i], bpp)) { | ||
| 734 | tdiff = abs(db[i].xres - xres) + | ||
| 735 | abs(db[i].yres - yres); | ||
| 736 | |||
| 737 | /* | ||
| 738 | * Penalize modes with resolutions smaller | ||
| 739 | * than requested. | ||
| 740 | */ | ||
| 741 | if (xres > db[i].xres || yres > db[i].yres) | ||
| 742 | tdiff += xres + yres; | ||
| 743 | |||
| 744 | if (diff > tdiff) { | ||
| 745 | diff = tdiff; | ||
| 746 | best = i; | ||
| 747 | } | ||
| 741 | } | 748 | } |
| 742 | } | 749 | } |
| 750 | if (best != -1) { | ||
| 751 | fb_try_mode(var, info, &db[best], bpp); | ||
| 752 | return 5; | ||
| 753 | } | ||
| 743 | } | 754 | } |
| 744 | if (best != -1) { | ||
| 745 | fb_try_mode(var, info, &db[best], bpp); | ||
| 746 | return 5; | ||
| 747 | } | ||
| 748 | } | ||
| 749 | 755 | ||
| 750 | DPRINTK("Trying default video mode\n"); | 756 | DPRINTK("Trying default video mode\n"); |
| 751 | if (!fb_try_mode(var, info, default_mode, default_bpp)) | 757 | if (!fb_try_mode(var, info, default_mode, default_bpp)) |
| 752 | return 3; | 758 | return 3; |
| 753 | 759 | ||
| 754 | DPRINTK("Trying all modes\n"); | 760 | DPRINTK("Trying all modes\n"); |
| 755 | for (i = 0; i < dbsize; i++) | 761 | for (i = 0; i < dbsize; i++) |
| 756 | if (!fb_try_mode(var, info, &db[i], default_bpp)) | 762 | if (!fb_try_mode(var, info, &db[i], default_bpp)) |
| 757 | return 4; | 763 | return 4; |
| 758 | 764 | ||
| 759 | DPRINTK("No valid mode found\n"); | 765 | DPRINTK("No valid mode found\n"); |
| 760 | return 0; | 766 | return 0; |
| 761 | } | 767 | } |
| 762 | 768 | ||
| 763 | /** | 769 | /** |
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c index 178b0720bd79..4527cbf0a4ec 100644 --- a/drivers/video/msm/mddi.c +++ b/drivers/video/msm/mddi.c | |||
| @@ -715,7 +715,7 @@ static int __devinit mddi_probe(struct platform_device *pdev) | |||
| 715 | 715 | ||
| 716 | mddi->int_enable = 0; | 716 | mddi->int_enable = 0; |
| 717 | mddi_writel(mddi->int_enable, INTEN); | 717 | mddi_writel(mddi->int_enable, INTEN); |
| 718 | ret = request_irq(mddi->irq, mddi_isr, IRQF_DISABLED, "mddi", | 718 | ret = request_irq(mddi->irq, mddi_isr, 0, "mddi", |
| 719 | &mddi->client_data); | 719 | &mddi->client_data); |
| 720 | if (ret) { | 720 | if (ret) { |
| 721 | printk(KERN_ERR "mddi: failed to request enable irq!\n"); | 721 | printk(KERN_ERR "mddi: failed to request enable irq!\n"); |
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index 243d16f09b8a..cb2ddf164c98 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <mach/msm_iomap.h> | 28 | #include <mach/msm_iomap.h> |
| 29 | #include <mach/msm_fb.h> | 29 | #include <mach/msm_fb.h> |
| 30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| 31 | #include <linux/export.h> | ||
| 31 | 32 | ||
| 32 | #include "mdp_hw.h" | 33 | #include "mdp_hw.h" |
| 33 | 34 | ||
| @@ -421,10 +422,11 @@ int mdp_probe(struct platform_device *pdev) | |||
| 421 | clk = clk_get(&pdev->dev, "mdp_clk"); | 422 | clk = clk_get(&pdev->dev, "mdp_clk"); |
| 422 | if (IS_ERR(clk)) { | 423 | if (IS_ERR(clk)) { |
| 423 | printk(KERN_INFO "mdp: failed to get mdp clk"); | 424 | printk(KERN_INFO "mdp: failed to get mdp clk"); |
| 424 | return PTR_ERR(clk); | 425 | ret = PTR_ERR(clk); |
| 426 | goto error_get_clk; | ||
| 425 | } | 427 | } |
| 426 | 428 | ||
| 427 | ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp); | 429 | ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp); |
| 428 | if (ret) | 430 | if (ret) |
| 429 | goto error_request_irq; | 431 | goto error_request_irq; |
| 430 | disable_irq(mdp->irq); | 432 | disable_irq(mdp->irq); |
| @@ -495,6 +497,7 @@ int mdp_probe(struct platform_device *pdev) | |||
| 495 | error_device_register: | 497 | error_device_register: |
| 496 | free_irq(mdp->irq, mdp); | 498 | free_irq(mdp->irq, mdp); |
| 497 | error_request_irq: | 499 | error_request_irq: |
| 500 | error_get_clk: | ||
| 498 | iounmap(mdp->base); | 501 | iounmap(mdp->base); |
| 499 | error_get_irq: | 502 | error_get_irq: |
| 500 | error_ioremap: | 503 | error_ioremap: |
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 7e3a490e8d76..e3406ab31305 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c | |||
| @@ -382,6 +382,9 @@ static void sdc_disable_channel(struct mx3fb_info *mx3_fbi) | |||
| 382 | uint32_t enabled; | 382 | uint32_t enabled; |
| 383 | unsigned long flags; | 383 | unsigned long flags; |
| 384 | 384 | ||
| 385 | if (mx3_fbi->txd == NULL) | ||
| 386 | return; | ||
| 387 | |||
| 385 | spin_lock_irqsave(&mx3fb->lock, flags); | 388 | spin_lock_irqsave(&mx3fb->lock, flags); |
| 386 | 389 | ||
| 387 | enabled = sdc_fb_uninit(mx3_fbi); | 390 | enabled = sdc_fb_uninit(mx3_fbi); |
| @@ -986,9 +989,19 @@ static void __blank(int blank, struct fb_info *fbi) | |||
| 986 | { | 989 | { |
| 987 | struct mx3fb_info *mx3_fbi = fbi->par; | 990 | struct mx3fb_info *mx3_fbi = fbi->par; |
| 988 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; | 991 | struct mx3fb_data *mx3fb = mx3_fbi->mx3fb; |
| 992 | int was_blank = mx3_fbi->blank; | ||
| 989 | 993 | ||
| 990 | mx3_fbi->blank = blank; | 994 | mx3_fbi->blank = blank; |
| 991 | 995 | ||
| 996 | /* Attention! | ||
| 997 | * Do not call sdc_disable_channel() for a channel that is disabled | ||
| 998 | * already! This will result in a kernel NULL pointer dereference | ||
| 999 | * (mx3_fbi->txd is NULL). Hide the fact, that all blank modes are | ||
| 1000 | * handled equally by this driver. | ||
| 1001 | */ | ||
| 1002 | if (blank > FB_BLANK_UNBLANK && was_blank > FB_BLANK_UNBLANK) | ||
| 1003 | return; | ||
| 1004 | |||
| 992 | switch (blank) { | 1005 | switch (blank) { |
| 993 | case FB_BLANK_POWERDOWN: | 1006 | case FB_BLANK_POWERDOWN: |
| 994 | case FB_BLANK_VSYNC_SUSPEND: | 1007 | case FB_BLANK_VSYNC_SUSPEND: |
| @@ -1062,15 +1075,15 @@ static int mx3fb_pan_display(struct fb_var_screeninfo *var, | |||
| 1062 | y_bottom = var->yoffset; | 1075 | y_bottom = var->yoffset; |
| 1063 | 1076 | ||
| 1064 | if (!(var->vmode & FB_VMODE_YWRAP)) | 1077 | if (!(var->vmode & FB_VMODE_YWRAP)) |
| 1065 | y_bottom += var->yres; | 1078 | y_bottom += fbi->var.yres; |
| 1066 | 1079 | ||
| 1067 | if (y_bottom > fbi->var.yres_virtual) | 1080 | if (y_bottom > fbi->var.yres_virtual) |
| 1068 | return -EINVAL; | 1081 | return -EINVAL; |
| 1069 | 1082 | ||
| 1070 | mutex_lock(&mx3_fbi->mutex); | 1083 | mutex_lock(&mx3_fbi->mutex); |
| 1071 | 1084 | ||
| 1072 | offset = (var->yoffset * var->xres_virtual + var->xoffset) * | 1085 | offset = var->yoffset * fbi->fix.line_length |
| 1073 | (var->bits_per_pixel / 8); | 1086 | + var->xoffset * (fbi->var.bits_per_pixel / 8); |
| 1074 | base = fbi->fix.smem_start + offset; | 1087 | base = fbi->fix.smem_start + offset; |
| 1075 | 1088 | ||
| 1076 | dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", | 1089 | dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n", |
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 0b2f2dd41416..d837d63c456f 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | * the required value in the imx_fb_videomode structure. | 39 | * the required value in the imx_fb_videomode structure. |
| 40 | */ | 40 | */ |
| 41 | 41 | ||
| 42 | #include <linux/module.h> | ||
| 42 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
| 43 | #include <linux/platform_device.h> | 44 | #include <linux/platform_device.h> |
| 44 | #include <linux/clk.h> | 45 | #include <linux/clk.h> |
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 588527a254c2..feea7b1dc386 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
| @@ -1185,8 +1185,8 @@ static int neofb_pan_display(struct fb_var_screeninfo *var, | |||
| 1185 | 1185 | ||
| 1186 | DBG("neofb_update_start"); | 1186 | DBG("neofb_update_start"); |
| 1187 | 1187 | ||
| 1188 | Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2; | 1188 | Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2; |
| 1189 | Base *= (var->bits_per_pixel + 7) / 8; | 1189 | Base *= (info->var.bits_per_pixel + 7) / 8; |
| 1190 | 1190 | ||
| 1191 | neoUnlock(); | 1191 | neoUnlock(); |
| 1192 | 1192 | ||
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c index 0fff59782e45..d1fbbd888cf4 100644 --- a/drivers/video/nuc900fb.c +++ b/drivers/video/nuc900fb.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <mach/regs-clock.h> | 39 | #include <mach/regs-clock.h> |
| 40 | #include <mach/regs-ldm.h> | 40 | #include <mach/regs-ldm.h> |
| 41 | #include <mach/fb.h> | 41 | #include <mach/fb.h> |
| 42 | #include <mach/clkdev.h> | ||
| 43 | 42 | ||
| 44 | #include "nuc900fb.h" | 43 | #include "nuc900fb.h" |
| 45 | 44 | ||
| @@ -588,7 +587,7 @@ static int __devinit nuc900fb_probe(struct platform_device *pdev) | |||
| 588 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | 587 | fbinfo->flags = FBINFO_FLAG_DEFAULT; |
| 589 | fbinfo->pseudo_palette = &fbi->pseudo_pal; | 588 | fbinfo->pseudo_palette = &fbi->pseudo_pal; |
| 590 | 589 | ||
| 591 | ret = request_irq(irq, nuc900fb_irqhandler, IRQF_DISABLED, | 590 | ret = request_irq(irq, nuc900fb_irqhandler, 0, |
| 592 | pdev->name, fbinfo); | 591 | pdev->name, fbinfo); |
| 593 | if (ret) { | 592 | if (ret) { |
| 594 | dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", | 593 | dev_err(&pdev->dev, "cannot register irq handler %d -err %d\n", |
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 196fa2e7f438..84ff23208c25 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig | |||
| @@ -9,35 +9,6 @@ config FB_OMAP | |||
| 9 | help | 9 | help |
| 10 | Frame buffer driver for OMAP based boards. | 10 | Frame buffer driver for OMAP based boards. |
| 11 | 11 | ||
| 12 | config FB_OMAP_LCD_VGA | ||
| 13 | bool "Use LCD in VGA mode" | ||
| 14 | depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP | ||
| 15 | help | ||
| 16 | Set LCD resolution as VGA (640 X 480). | ||
| 17 | Default resolution without this option is QVGA(320 X 240). | ||
| 18 | Please take a look at drivers/video/omap/lcd_ldp.c file | ||
| 19 | for lcd driver code. | ||
| 20 | choice | ||
| 21 | depends on FB_OMAP && MACH_OVERO | ||
| 22 | prompt "Screen resolution" | ||
| 23 | default FB_OMAP_079M3R | ||
| 24 | help | ||
| 25 | Selected desired screen resolution | ||
| 26 | |||
| 27 | config FB_OMAP_031M3R | ||
| 28 | boolean "640 x 480 @ 60 Hz Reduced blanking" | ||
| 29 | |||
| 30 | config FB_OMAP_048M3R | ||
| 31 | boolean "800 x 600 @ 60 Hz Reduced blanking" | ||
| 32 | |||
| 33 | config FB_OMAP_079M3R | ||
| 34 | boolean "1024 x 768 @ 60 Hz Reduced blanking" | ||
| 35 | |||
| 36 | config FB_OMAP_092M9R | ||
| 37 | boolean "1280 x 720 @ 60 Hz Reduced blanking" | ||
| 38 | |||
| 39 | endchoice | ||
| 40 | |||
| 41 | config FB_OMAP_LCDC_EXTERNAL | 12 | config FB_OMAP_LCDC_EXTERNAL |
| 42 | bool "External LCD controller support" | 13 | bool "External LCD controller support" |
| 43 | depends on FB_OMAP | 14 | depends on FB_OMAP |
diff --git a/drivers/video/omap/Makefile b/drivers/video/omap/Makefile index 25db55696e14..ef78550917ff 100644 --- a/drivers/video/omap/Makefile +++ b/drivers/video/omap/Makefile | |||
| @@ -17,7 +17,6 @@ objs-y$(CONFIG_FB_OMAP_LCDC_HWA742) += hwa742.o | |||
| 17 | objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o | 17 | objs-y$(CONFIG_FB_OMAP_LCDC_BLIZZARD) += blizzard.o |
| 18 | 18 | ||
| 19 | objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o | 19 | objs-y$(CONFIG_MACH_AMS_DELTA) += lcd_ams_delta.o |
| 20 | objs-y$(CONFIG_MACH_OMAP_H4) += lcd_h4.o | ||
| 21 | objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o | 20 | objs-y$(CONFIG_MACH_OMAP_H3) += lcd_h3.o |
| 22 | objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o | 21 | objs-y$(CONFIG_MACH_OMAP_PALMTE) += lcd_palmte.o |
| 23 | objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o | 22 | objs-y$(CONFIG_MACH_OMAP_PALMTT) += lcd_palmtt.o |
| @@ -26,14 +25,7 @@ objs-$(CONFIG_ARCH_OMAP16XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1610.o | |||
| 26 | objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o | 25 | objs-$(CONFIG_ARCH_OMAP15XX)$(CONFIG_MACH_OMAP_INNOVATOR) += lcd_inn1510.o |
| 27 | objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o | 26 | objs-y$(CONFIG_MACH_OMAP_OSK) += lcd_osk.o |
| 28 | 27 | ||
| 29 | objs-y$(CONFIG_MACH_OMAP_APOLLON) += lcd_apollon.o | ||
| 30 | objs-y$(CONFIG_MACH_OMAP_2430SDP) += lcd_2430sdp.o | ||
| 31 | objs-y$(CONFIG_MACH_OMAP_3430SDP) += lcd_2430sdp.o | ||
| 32 | objs-y$(CONFIG_MACH_OMAP_LDP) += lcd_ldp.o | ||
| 33 | objs-y$(CONFIG_MACH_OMAP3EVM) += lcd_omap3evm.o | ||
| 34 | objs-y$(CONFIG_MACH_OMAP3_BEAGLE) += lcd_omap3beagle.o | ||
| 35 | objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o | 28 | objs-y$(CONFIG_FB_OMAP_LCD_MIPID) += lcd_mipid.o |
| 36 | objs-y$(CONFIG_MACH_OVERO) += lcd_overo.o | ||
| 37 | objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o | 29 | objs-y$(CONFIG_MACH_HERALD) += lcd_htcherald.o |
| 38 | 30 | ||
| 39 | omapfb-objs := $(objs-yy) | 31 | omapfb-objs := $(objs-yy) |
diff --git a/drivers/video/omap/lcd_2430sdp.c b/drivers/video/omap/lcd_2430sdp.c deleted file mode 100644 index e3eccc9af78e..000000000000 --- a/drivers/video/omap/lcd_2430sdp.c +++ /dev/null | |||
| @@ -1,203 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the TI 2430SDP board | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 MontaVista | ||
| 5 | * Author: Hunyue Yau <hyau@mvista.com> | ||
| 6 | * | ||
| 7 | * Derived from drivers/video/omap/lcd-apollon.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/gpio.h> | ||
| 28 | #include <linux/i2c/twl.h> | ||
| 29 | |||
| 30 | #include <plat/mux.h> | ||
| 31 | #include <asm/mach-types.h> | ||
| 32 | |||
| 33 | #include "omapfb.h" | ||
| 34 | |||
| 35 | #define SDP2430_LCD_PANEL_BACKLIGHT_GPIO 91 | ||
| 36 | #define SDP2430_LCD_PANEL_ENABLE_GPIO 154 | ||
| 37 | #define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 24 | ||
| 38 | #define SDP3430_LCD_PANEL_ENABLE_GPIO 28 | ||
| 39 | |||
| 40 | static unsigned backlight_gpio; | ||
| 41 | static unsigned enable_gpio; | ||
| 42 | |||
| 43 | #define LCD_PIXCLOCK_MAX 5400 /* freq 5.4 MHz */ | ||
| 44 | #define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER | ||
| 45 | #define ENABLE_VAUX2_DEDICATED 0x09 | ||
| 46 | #define ENABLE_VAUX2_DEV_GRP 0x20 | ||
| 47 | #define ENABLE_VAUX3_DEDICATED 0x03 | ||
| 48 | #define ENABLE_VAUX3_DEV_GRP 0x20 | ||
| 49 | |||
| 50 | #define ENABLE_VPLL2_DEDICATED 0x05 | ||
| 51 | #define ENABLE_VPLL2_DEV_GRP 0xE0 | ||
| 52 | #define TWL4030_VPLL2_DEV_GRP 0x33 | ||
| 53 | #define TWL4030_VPLL2_DEDICATED 0x36 | ||
| 54 | |||
| 55 | #define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) | ||
| 56 | |||
| 57 | |||
| 58 | static int sdp2430_panel_init(struct lcd_panel *panel, | ||
| 59 | struct omapfb_device *fbdev) | ||
| 60 | { | ||
| 61 | if (machine_is_omap_3430sdp()) { | ||
| 62 | enable_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO; | ||
| 63 | backlight_gpio = SDP3430_LCD_PANEL_BACKLIGHT_GPIO; | ||
| 64 | } else { | ||
| 65 | enable_gpio = SDP2430_LCD_PANEL_ENABLE_GPIO; | ||
| 66 | backlight_gpio = SDP2430_LCD_PANEL_BACKLIGHT_GPIO; | ||
| 67 | } | ||
| 68 | |||
| 69 | gpio_request(enable_gpio, "LCD enable"); /* LCD panel */ | ||
| 70 | gpio_request(backlight_gpio, "LCD bl"); /* LCD backlight */ | ||
| 71 | gpio_direction_output(enable_gpio, 0); | ||
| 72 | gpio_direction_output(backlight_gpio, 0); | ||
| 73 | |||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static void sdp2430_panel_cleanup(struct lcd_panel *panel) | ||
| 78 | { | ||
| 79 | gpio_free(backlight_gpio); | ||
| 80 | gpio_free(enable_gpio); | ||
| 81 | } | ||
| 82 | |||
| 83 | static int sdp2430_panel_enable(struct lcd_panel *panel) | ||
| 84 | { | ||
| 85 | u8 ded_val, ded_reg; | ||
| 86 | u8 grp_val, grp_reg; | ||
| 87 | |||
| 88 | if (machine_is_omap_3430sdp()) { | ||
| 89 | ded_reg = TWL4030_VAUX3_DEDICATED; | ||
| 90 | ded_val = ENABLE_VAUX3_DEDICATED; | ||
| 91 | grp_reg = TWL4030_VAUX3_DEV_GRP; | ||
| 92 | grp_val = ENABLE_VAUX3_DEV_GRP; | ||
| 93 | |||
| 94 | if (omap_rev() > OMAP3430_REV_ES1_0) { | ||
| 95 | t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, | ||
| 96 | TWL4030_VPLL2_DEDICATED); | ||
| 97 | t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, | ||
| 98 | TWL4030_VPLL2_DEV_GRP); | ||
| 99 | } | ||
| 100 | } else { | ||
| 101 | ded_reg = TWL4030_VAUX2_DEDICATED; | ||
| 102 | ded_val = ENABLE_VAUX2_DEDICATED; | ||
| 103 | grp_reg = TWL4030_VAUX2_DEV_GRP; | ||
| 104 | grp_val = ENABLE_VAUX2_DEV_GRP; | ||
| 105 | } | ||
| 106 | |||
| 107 | gpio_set_value(enable_gpio, 1); | ||
| 108 | gpio_set_value(backlight_gpio, 1); | ||
| 109 | |||
| 110 | if (0 != t2_out(PM_RECEIVER, ded_val, ded_reg)) | ||
| 111 | return -EIO; | ||
| 112 | if (0 != t2_out(PM_RECEIVER, grp_val, grp_reg)) | ||
| 113 | return -EIO; | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static void sdp2430_panel_disable(struct lcd_panel *panel) | ||
| 119 | { | ||
| 120 | gpio_set_value(enable_gpio, 0); | ||
| 121 | gpio_set_value(backlight_gpio, 0); | ||
| 122 | if (omap_rev() > OMAP3430_REV_ES1_0) { | ||
| 123 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); | ||
| 124 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); | ||
| 125 | msleep(4); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | static unsigned long sdp2430_panel_get_caps(struct lcd_panel *panel) | ||
| 130 | { | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | struct lcd_panel sdp2430_panel = { | ||
| 135 | .name = "sdp2430", | ||
| 136 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
| 137 | OMAP_LCDC_INV_HSYNC, | ||
| 138 | |||
| 139 | .bpp = 16, | ||
| 140 | .data_lines = 16, | ||
| 141 | .x_res = 240, | ||
| 142 | .y_res = 320, | ||
| 143 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
| 144 | .hfp = 3, /* right_margin (4) - 1 */ | ||
| 145 | .hbp = 39, /* left_margin (40) - 1 */ | ||
| 146 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
| 147 | .vfp = 2, /* lower_margin */ | ||
| 148 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
| 149 | |||
| 150 | .pixel_clock = LCD_PIXCLOCK_MAX, | ||
| 151 | |||
| 152 | .init = sdp2430_panel_init, | ||
| 153 | .cleanup = sdp2430_panel_cleanup, | ||
| 154 | .enable = sdp2430_panel_enable, | ||
| 155 | .disable = sdp2430_panel_disable, | ||
| 156 | .get_caps = sdp2430_panel_get_caps, | ||
| 157 | }; | ||
| 158 | |||
| 159 | static int sdp2430_panel_probe(struct platform_device *pdev) | ||
| 160 | { | ||
| 161 | omapfb_register_panel(&sdp2430_panel); | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int sdp2430_panel_remove(struct platform_device *pdev) | ||
| 166 | { | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | static int sdp2430_panel_suspend(struct platform_device *pdev, | ||
| 171 | pm_message_t mesg) | ||
| 172 | { | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | static int sdp2430_panel_resume(struct platform_device *pdev) | ||
| 177 | { | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | struct platform_driver sdp2430_panel_driver = { | ||
| 182 | .probe = sdp2430_panel_probe, | ||
| 183 | .remove = sdp2430_panel_remove, | ||
| 184 | .suspend = sdp2430_panel_suspend, | ||
| 185 | .resume = sdp2430_panel_resume, | ||
| 186 | .driver = { | ||
| 187 | .name = "sdp2430_lcd", | ||
| 188 | .owner = THIS_MODULE, | ||
| 189 | }, | ||
| 190 | }; | ||
| 191 | |||
| 192 | static int __init sdp2430_panel_drv_init(void) | ||
| 193 | { | ||
| 194 | return platform_driver_register(&sdp2430_panel_driver); | ||
| 195 | } | ||
| 196 | |||
| 197 | static void __exit sdp2430_panel_drv_exit(void) | ||
| 198 | { | ||
| 199 | platform_driver_unregister(&sdp2430_panel_driver); | ||
| 200 | } | ||
| 201 | |||
| 202 | module_init(sdp2430_panel_drv_init); | ||
| 203 | module_exit(sdp2430_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_apollon.c b/drivers/video/omap/lcd_apollon.c deleted file mode 100644 index 10459d8bd9a0..000000000000 --- a/drivers/video/omap/lcd_apollon.c +++ /dev/null | |||
| @@ -1,136 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the Samsung OMAP2 Apollon board | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005,2006 Samsung Electronics | ||
| 5 | * Author: Kyungmin Park <kyungmin.park@samsung.com> | ||
| 6 | * | ||
| 7 | * Derived from drivers/video/omap/lcd-h4.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | |||
| 27 | #include <mach/gpio.h> | ||
| 28 | |||
| 29 | #include "omapfb.h" | ||
| 30 | |||
| 31 | /* #define USE_35INCH_LCD 1 */ | ||
| 32 | |||
| 33 | static int apollon_panel_init(struct lcd_panel *panel, | ||
| 34 | struct omapfb_device *fbdev) | ||
| 35 | { | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | static void apollon_panel_cleanup(struct lcd_panel *panel) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | static int apollon_panel_enable(struct lcd_panel *panel) | ||
| 44 | { | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | static void apollon_panel_disable(struct lcd_panel *panel) | ||
| 49 | { | ||
| 50 | } | ||
| 51 | |||
| 52 | static unsigned long apollon_panel_get_caps(struct lcd_panel *panel) | ||
| 53 | { | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | struct lcd_panel apollon_panel = { | ||
| 58 | .name = "apollon", | ||
| 59 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
| 60 | OMAP_LCDC_INV_HSYNC, | ||
| 61 | |||
| 62 | .bpp = 16, | ||
| 63 | .data_lines = 18, | ||
| 64 | #ifdef USE_35INCH_LCD | ||
| 65 | .x_res = 240, | ||
| 66 | .y_res = 320, | ||
| 67 | .hsw = 2, | ||
| 68 | .hfp = 3, | ||
| 69 | .hbp = 9, | ||
| 70 | .vsw = 4, | ||
| 71 | .vfp = 3, | ||
| 72 | .vbp = 5, | ||
| 73 | #else | ||
| 74 | .x_res = 480, | ||
| 75 | .y_res = 272, | ||
| 76 | .hsw = 41, | ||
| 77 | .hfp = 2, | ||
| 78 | .hbp = 2, | ||
| 79 | .vsw = 10, | ||
| 80 | .vfp = 2, | ||
| 81 | .vbp = 2, | ||
| 82 | #endif | ||
| 83 | .pixel_clock = 6250, | ||
| 84 | |||
| 85 | .init = apollon_panel_init, | ||
| 86 | .cleanup = apollon_panel_cleanup, | ||
| 87 | .enable = apollon_panel_enable, | ||
| 88 | .disable = apollon_panel_disable, | ||
| 89 | .get_caps = apollon_panel_get_caps, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int apollon_panel_probe(struct platform_device *pdev) | ||
| 93 | { | ||
| 94 | omapfb_register_panel(&apollon_panel); | ||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static int apollon_panel_remove(struct platform_device *pdev) | ||
| 99 | { | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int apollon_panel_suspend(struct platform_device *pdev, | ||
| 104 | pm_message_t mesg) | ||
| 105 | { | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int apollon_panel_resume(struct platform_device *pdev) | ||
| 110 | { | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | struct platform_driver apollon_panel_driver = { | ||
| 115 | .probe = apollon_panel_probe, | ||
| 116 | .remove = apollon_panel_remove, | ||
| 117 | .suspend = apollon_panel_suspend, | ||
| 118 | .resume = apollon_panel_resume, | ||
| 119 | .driver = { | ||
| 120 | .name = "apollon_lcd", | ||
| 121 | .owner = THIS_MODULE, | ||
| 122 | }, | ||
| 123 | }; | ||
| 124 | |||
| 125 | static int __init apollon_panel_drv_init(void) | ||
| 126 | { | ||
| 127 | return platform_driver_register(&apollon_panel_driver); | ||
| 128 | } | ||
| 129 | |||
| 130 | static void __exit apollon_panel_drv_exit(void) | ||
| 131 | { | ||
| 132 | platform_driver_unregister(&apollon_panel_driver); | ||
| 133 | } | ||
| 134 | |||
| 135 | module_init(apollon_panel_drv_init); | ||
| 136 | module_exit(apollon_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c index 8df688748b5a..622ad839fd9d 100644 --- a/drivers/video/omap/lcd_h3.c +++ b/drivers/video/omap/lcd_h3.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/i2c/tps65010.h> | 24 | #include <linux/i2c/tps65010.h> |
| 25 | 25 | ||
| 26 | #include <mach/gpio.h> | 26 | #include <asm/gpio.h> |
| 27 | #include "omapfb.h" | 27 | #include "omapfb.h" |
| 28 | 28 | ||
| 29 | #define MODULE_NAME "omapfb-lcd_h3" | 29 | #define MODULE_NAME "omapfb-lcd_h3" |
diff --git a/drivers/video/omap/lcd_h4.c b/drivers/video/omap/lcd_h4.c deleted file mode 100644 index 03a06a982750..000000000000 --- a/drivers/video/omap/lcd_h4.c +++ /dev/null | |||
| @@ -1,117 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the TI OMAP H4 board | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Nokia Corporation | ||
| 5 | * Author: Imre Deak <imre.deak@nokia.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but | ||
| 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 15 | * General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along | ||
| 18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | |||
| 25 | #include "omapfb.h" | ||
| 26 | |||
| 27 | static int h4_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | ||
| 28 | { | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | static void h4_panel_cleanup(struct lcd_panel *panel) | ||
| 33 | { | ||
| 34 | } | ||
| 35 | |||
| 36 | static int h4_panel_enable(struct lcd_panel *panel) | ||
| 37 | { | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | static void h4_panel_disable(struct lcd_panel *panel) | ||
| 42 | { | ||
| 43 | } | ||
| 44 | |||
| 45 | static unsigned long h4_panel_get_caps(struct lcd_panel *panel) | ||
| 46 | { | ||
| 47 | return 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static struct lcd_panel h4_panel = { | ||
| 51 | .name = "h4", | ||
| 52 | .config = OMAP_LCDC_PANEL_TFT, | ||
| 53 | |||
| 54 | .bpp = 16, | ||
| 55 | .data_lines = 16, | ||
| 56 | .x_res = 240, | ||
| 57 | .y_res = 320, | ||
| 58 | .pixel_clock = 6250, | ||
| 59 | .hsw = 15, | ||
| 60 | .hfp = 15, | ||
| 61 | .hbp = 60, | ||
| 62 | .vsw = 1, | ||
| 63 | .vfp = 1, | ||
| 64 | .vbp = 1, | ||
| 65 | |||
| 66 | .init = h4_panel_init, | ||
| 67 | .cleanup = h4_panel_cleanup, | ||
| 68 | .enable = h4_panel_enable, | ||
| 69 | .disable = h4_panel_disable, | ||
| 70 | .get_caps = h4_panel_get_caps, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static int h4_panel_probe(struct platform_device *pdev) | ||
| 74 | { | ||
| 75 | omapfb_register_panel(&h4_panel); | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int h4_panel_remove(struct platform_device *pdev) | ||
| 80 | { | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int h4_panel_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
| 85 | { | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int h4_panel_resume(struct platform_device *pdev) | ||
| 90 | { | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static struct platform_driver h4_panel_driver = { | ||
| 95 | .probe = h4_panel_probe, | ||
| 96 | .remove = h4_panel_remove, | ||
| 97 | .suspend = h4_panel_suspend, | ||
| 98 | .resume = h4_panel_resume, | ||
| 99 | .driver = { | ||
| 100 | .name = "lcd_h4", | ||
| 101 | .owner = THIS_MODULE, | ||
| 102 | }, | ||
| 103 | }; | ||
| 104 | |||
| 105 | static int __init h4_panel_drv_init(void) | ||
| 106 | { | ||
| 107 | return platform_driver_register(&h4_panel_driver); | ||
| 108 | } | ||
| 109 | |||
| 110 | static void __exit h4_panel_drv_cleanup(void) | ||
| 111 | { | ||
| 112 | platform_driver_unregister(&h4_panel_driver); | ||
| 113 | } | ||
| 114 | |||
| 115 | module_init(h4_panel_drv_init); | ||
| 116 | module_exit(h4_panel_drv_cleanup); | ||
| 117 | |||
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c index 9fff86f67bde..12cc52a70f96 100644 --- a/drivers/video/omap/lcd_inn1610.c +++ b/drivers/video/omap/lcd_inn1610.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | 24 | ||
| 25 | #include <mach/gpio.h> | 25 | #include <asm/gpio.h> |
| 26 | #include "omapfb.h" | 26 | #include "omapfb.h" |
| 27 | 27 | ||
| 28 | #define MODULE_NAME "omapfb-lcd_h3" | 28 | #define MODULE_NAME "omapfb-lcd_h3" |
diff --git a/drivers/video/omap/lcd_ldp.c b/drivers/video/omap/lcd_ldp.c deleted file mode 100644 index 0f5952cae85e..000000000000 --- a/drivers/video/omap/lcd_ldp.c +++ /dev/null | |||
| @@ -1,201 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the TI LDP board | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 WindRiver | ||
| 5 | * Author: Stanley Miao <stanley.miao@windriver.com> | ||
| 6 | * | ||
| 7 | * Derived from drivers/video/omap/lcd-2430sdp.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/platform_device.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/i2c/twl.h> | ||
| 28 | |||
| 29 | #include <mach/gpio.h> | ||
| 30 | #include <plat/mux.h> | ||
| 31 | #include <asm/mach-types.h> | ||
| 32 | |||
| 33 | #include "omapfb.h" | ||
| 34 | |||
| 35 | #define LCD_PANEL_BACKLIGHT_GPIO (15 + OMAP_MAX_GPIO_LINES) | ||
| 36 | #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) | ||
| 37 | |||
| 38 | #define LCD_PANEL_RESET_GPIO 55 | ||
| 39 | #define LCD_PANEL_QVGA_GPIO 56 | ||
| 40 | |||
| 41 | #ifdef CONFIG_FB_OMAP_LCD_VGA | ||
| 42 | #define LCD_XRES 480 | ||
| 43 | #define LCD_YRES 640 | ||
| 44 | #define LCD_PIXCLOCK_MAX 41700 | ||
| 45 | #else | ||
| 46 | #define LCD_XRES 240 | ||
| 47 | #define LCD_YRES 320 | ||
| 48 | #define LCD_PIXCLOCK_MAX 185186 | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #define PM_RECEIVER TWL4030_MODULE_PM_RECEIVER | ||
| 52 | #define ENABLE_VAUX2_DEDICATED 0x09 | ||
| 53 | #define ENABLE_VAUX2_DEV_GRP 0x20 | ||
| 54 | #define ENABLE_VAUX3_DEDICATED 0x03 | ||
| 55 | #define ENABLE_VAUX3_DEV_GRP 0x20 | ||
| 56 | |||
| 57 | #define ENABLE_VPLL2_DEDICATED 0x05 | ||
| 58 | #define ENABLE_VPLL2_DEV_GRP 0xE0 | ||
| 59 | #define TWL4030_VPLL2_DEV_GRP 0x33 | ||
| 60 | #define TWL4030_VPLL2_DEDICATED 0x36 | ||
| 61 | |||
| 62 | #define t2_out(c, r, v) twl_i2c_write_u8(c, r, v) | ||
| 63 | |||
| 64 | |||
| 65 | static int ldp_panel_init(struct lcd_panel *panel, | ||
| 66 | struct omapfb_device *fbdev) | ||
| 67 | { | ||
| 68 | gpio_request(LCD_PANEL_RESET_GPIO, "lcd reset"); | ||
| 69 | gpio_request(LCD_PANEL_QVGA_GPIO, "lcd qvga"); | ||
| 70 | gpio_request(LCD_PANEL_ENABLE_GPIO, "lcd panel"); | ||
| 71 | gpio_request(LCD_PANEL_BACKLIGHT_GPIO, "lcd backlight"); | ||
| 72 | |||
| 73 | gpio_direction_output(LCD_PANEL_QVGA_GPIO, 0); | ||
| 74 | gpio_direction_output(LCD_PANEL_RESET_GPIO, 0); | ||
| 75 | gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); | ||
| 76 | gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); | ||
| 77 | |||
| 78 | #ifdef CONFIG_FB_OMAP_LCD_VGA | ||
| 79 | gpio_set_value(LCD_PANEL_QVGA_GPIO, 0); | ||
| 80 | #else | ||
| 81 | gpio_set_value(LCD_PANEL_QVGA_GPIO, 1); | ||
| 82 | #endif | ||
| 83 | gpio_set_value(LCD_PANEL_RESET_GPIO, 1); | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static void ldp_panel_cleanup(struct lcd_panel *panel) | ||
| 89 | { | ||
| 90 | gpio_free(LCD_PANEL_BACKLIGHT_GPIO); | ||
| 91 | gpio_free(LCD_PANEL_ENABLE_GPIO); | ||
| 92 | gpio_free(LCD_PANEL_QVGA_GPIO); | ||
| 93 | gpio_free(LCD_PANEL_RESET_GPIO); | ||
| 94 | } | ||
| 95 | |||
| 96 | static int ldp_panel_enable(struct lcd_panel *panel) | ||
| 97 | { | ||
| 98 | if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEDICATED, | ||
| 99 | TWL4030_VPLL2_DEDICATED)) | ||
| 100 | return -EIO; | ||
| 101 | if (0 != t2_out(PM_RECEIVER, ENABLE_VPLL2_DEV_GRP, | ||
| 102 | TWL4030_VPLL2_DEV_GRP)) | ||
| 103 | return -EIO; | ||
| 104 | |||
| 105 | gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 1); | ||
| 106 | gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 1); | ||
| 107 | |||
| 108 | if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEDICATED, | ||
| 109 | TWL4030_VAUX3_DEDICATED)) | ||
| 110 | return -EIO; | ||
| 111 | if (0 != t2_out(PM_RECEIVER, ENABLE_VAUX3_DEV_GRP, | ||
| 112 | TWL4030_VAUX3_DEV_GRP)) | ||
| 113 | return -EIO; | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static void ldp_panel_disable(struct lcd_panel *panel) | ||
| 119 | { | ||
| 120 | gpio_direction_output(LCD_PANEL_ENABLE_GPIO, 0); | ||
| 121 | gpio_direction_output(LCD_PANEL_BACKLIGHT_GPIO, 0); | ||
| 122 | |||
| 123 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEDICATED); | ||
| 124 | t2_out(PM_RECEIVER, 0x0, TWL4030_VPLL2_DEV_GRP); | ||
| 125 | msleep(4); | ||
| 126 | } | ||
| 127 | |||
| 128 | static unsigned long ldp_panel_get_caps(struct lcd_panel *panel) | ||
| 129 | { | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | struct lcd_panel ldp_panel = { | ||
| 134 | .name = "ldp", | ||
| 135 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
| 136 | OMAP_LCDC_INV_HSYNC, | ||
| 137 | |||
| 138 | .bpp = 16, | ||
| 139 | .data_lines = 18, | ||
| 140 | .x_res = LCD_XRES, | ||
| 141 | .y_res = LCD_YRES, | ||
| 142 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
| 143 | .hfp = 3, /* right_margin (4) - 1 */ | ||
| 144 | .hbp = 39, /* left_margin (40) - 1 */ | ||
| 145 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
| 146 | .vfp = 2, /* lower_margin */ | ||
| 147 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
| 148 | |||
| 149 | .pixel_clock = LCD_PIXCLOCK_MAX, | ||
| 150 | |||
| 151 | .init = ldp_panel_init, | ||
| 152 | .cleanup = ldp_panel_cleanup, | ||
| 153 | .enable = ldp_panel_enable, | ||
| 154 | .disable = ldp_panel_disable, | ||
| 155 | .get_caps = ldp_panel_get_caps, | ||
| 156 | }; | ||
| 157 | |||
| 158 | static int ldp_panel_probe(struct platform_device *pdev) | ||
| 159 | { | ||
| 160 | omapfb_register_panel(&ldp_panel); | ||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int ldp_panel_remove(struct platform_device *pdev) | ||
| 165 | { | ||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int ldp_panel_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
| 170 | { | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int ldp_panel_resume(struct platform_device *pdev) | ||
| 175 | { | ||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | struct platform_driver ldp_panel_driver = { | ||
| 180 | .probe = ldp_panel_probe, | ||
| 181 | .remove = ldp_panel_remove, | ||
| 182 | .suspend = ldp_panel_suspend, | ||
| 183 | .resume = ldp_panel_resume, | ||
| 184 | .driver = { | ||
| 185 | .name = "ldp_lcd", | ||
| 186 | .owner = THIS_MODULE, | ||
| 187 | }, | ||
| 188 | }; | ||
| 189 | |||
| 190 | static int __init ldp_panel_drv_init(void) | ||
| 191 | { | ||
| 192 | return platform_driver_register(&ldp_panel_driver); | ||
| 193 | } | ||
| 194 | |||
| 195 | static void __exit ldp_panel_drv_exit(void) | ||
| 196 | { | ||
| 197 | platform_driver_unregister(&ldp_panel_driver); | ||
| 198 | } | ||
| 199 | |||
| 200 | module_init(ldp_panel_drv_init); | ||
| 201 | module_exit(ldp_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c index 90e3bdd1b7ab..eb381db7fe51 100644 --- a/drivers/video/omap/lcd_mipid.c +++ b/drivers/video/omap/lcd_mipid.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
| 25 | #include <linux/spi/spi.h> | 25 | #include <linux/spi/spi.h> |
| 26 | #include <linux/module.h> | ||
| 26 | 27 | ||
| 27 | #include <plat/lcd_mipid.h> | 28 | #include <plat/lcd_mipid.h> |
| 28 | 29 | ||
diff --git a/drivers/video/omap/lcd_omap3beagle.c b/drivers/video/omap/lcd_omap3beagle.c deleted file mode 100644 index d7c6c3e0afc6..000000000000 --- a/drivers/video/omap/lcd_omap3beagle.c +++ /dev/null | |||
| @@ -1,130 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the TI OMAP3 Beagle board | ||
| 3 | * | ||
| 4 | * Author: Koen Kooi <koen@openembedded.org> | ||
| 5 | * | ||
| 6 | * Derived from drivers/video/omap/lcd-omap3evm.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/gpio.h> | ||
| 26 | #include <linux/i2c/twl.h> | ||
| 27 | |||
| 28 | #include <asm/mach-types.h> | ||
| 29 | |||
| 30 | #include "omapfb.h" | ||
| 31 | |||
| 32 | #define LCD_PANEL_ENABLE_GPIO 170 | ||
| 33 | |||
| 34 | static int omap3beagle_panel_init(struct lcd_panel *panel, | ||
| 35 | struct omapfb_device *fbdev) | ||
| 36 | { | ||
| 37 | gpio_request(LCD_PANEL_ENABLE_GPIO, "LCD enable"); | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | static void omap3beagle_panel_cleanup(struct lcd_panel *panel) | ||
| 42 | { | ||
| 43 | gpio_free(LCD_PANEL_ENABLE_GPIO); | ||
| 44 | } | ||
| 45 | |||
| 46 | static int omap3beagle_panel_enable(struct lcd_panel *panel) | ||
| 47 | { | ||
| 48 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void omap3beagle_panel_disable(struct lcd_panel *panel) | ||
| 53 | { | ||
| 54 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); | ||
| 55 | } | ||
| 56 | |||
| 57 | static unsigned long omap3beagle_panel_get_caps(struct lcd_panel *panel) | ||
| 58 | { | ||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | struct lcd_panel omap3beagle_panel = { | ||
| 63 | .name = "omap3beagle", | ||
| 64 | .config = OMAP_LCDC_PANEL_TFT, | ||
| 65 | |||
| 66 | .bpp = 16, | ||
| 67 | .data_lines = 24, | ||
| 68 | .x_res = 1024, | ||
| 69 | .y_res = 768, | ||
| 70 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
| 71 | .hfp = 3, /* right_margin (4) - 1 */ | ||
| 72 | .hbp = 39, /* left_margin (40) - 1 */ | ||
| 73 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
| 74 | .vfp = 2, /* lower_margin */ | ||
| 75 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
| 76 | |||
| 77 | .pixel_clock = 64000, | ||
| 78 | |||
| 79 | .init = omap3beagle_panel_init, | ||
| 80 | .cleanup = omap3beagle_panel_cleanup, | ||
| 81 | .enable = omap3beagle_panel_enable, | ||
| 82 | .disable = omap3beagle_panel_disable, | ||
| 83 | .get_caps = omap3beagle_panel_get_caps, | ||
| 84 | }; | ||
| 85 | |||
| 86 | static int omap3beagle_panel_probe(struct platform_device *pdev) | ||
| 87 | { | ||
| 88 | omapfb_register_panel(&omap3beagle_panel); | ||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int omap3beagle_panel_remove(struct platform_device *pdev) | ||
| 93 | { | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | static int omap3beagle_panel_suspend(struct platform_device *pdev, | ||
| 98 | pm_message_t mesg) | ||
| 99 | { | ||
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int omap3beagle_panel_resume(struct platform_device *pdev) | ||
| 104 | { | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | struct platform_driver omap3beagle_panel_driver = { | ||
| 109 | .probe = omap3beagle_panel_probe, | ||
| 110 | .remove = omap3beagle_panel_remove, | ||
| 111 | .suspend = omap3beagle_panel_suspend, | ||
| 112 | .resume = omap3beagle_panel_resume, | ||
| 113 | .driver = { | ||
| 114 | .name = "omap3beagle_lcd", | ||
| 115 | .owner = THIS_MODULE, | ||
| 116 | }, | ||
| 117 | }; | ||
| 118 | |||
| 119 | static int __init omap3beagle_panel_drv_init(void) | ||
| 120 | { | ||
| 121 | return platform_driver_register(&omap3beagle_panel_driver); | ||
| 122 | } | ||
| 123 | |||
| 124 | static void __exit omap3beagle_panel_drv_exit(void) | ||
| 125 | { | ||
| 126 | platform_driver_unregister(&omap3beagle_panel_driver); | ||
| 127 | } | ||
| 128 | |||
| 129 | module_init(omap3beagle_panel_drv_init); | ||
| 130 | module_exit(omap3beagle_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_omap3evm.c b/drivers/video/omap/lcd_omap3evm.c deleted file mode 100644 index 06840da0b094..000000000000 --- a/drivers/video/omap/lcd_omap3evm.c +++ /dev/null | |||
| @@ -1,193 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the TI OMAP3 EVM board | ||
| 3 | * | ||
| 4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
| 5 | * | ||
| 6 | * Derived from drivers/video/omap/lcd-apollon.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along | ||
| 19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/gpio.h> | ||
| 26 | #include <linux/i2c/twl.h> | ||
| 27 | |||
| 28 | #include <plat/mux.h> | ||
| 29 | #include <asm/mach-types.h> | ||
| 30 | |||
| 31 | #include "omapfb.h" | ||
| 32 | |||
| 33 | #define LCD_PANEL_ENABLE_GPIO 153 | ||
| 34 | #define LCD_PANEL_LR 2 | ||
| 35 | #define LCD_PANEL_UD 3 | ||
| 36 | #define LCD_PANEL_INI 152 | ||
| 37 | #define LCD_PANEL_QVGA 154 | ||
| 38 | #define LCD_PANEL_RESB 155 | ||
| 39 | |||
| 40 | #define ENABLE_VDAC_DEDICATED 0x03 | ||
| 41 | #define ENABLE_VDAC_DEV_GRP 0x20 | ||
| 42 | #define ENABLE_VPLL2_DEDICATED 0x05 | ||
| 43 | #define ENABLE_VPLL2_DEV_GRP 0xE0 | ||
| 44 | |||
| 45 | #define TWL_LED_LEDEN 0x00 | ||
| 46 | #define TWL_PWMA_PWMAON 0x00 | ||
| 47 | #define TWL_PWMA_PWMAOFF 0x01 | ||
| 48 | |||
| 49 | static unsigned int bklight_level; | ||
| 50 | |||
| 51 | static int omap3evm_panel_init(struct lcd_panel *panel, | ||
| 52 | struct omapfb_device *fbdev) | ||
| 53 | { | ||
| 54 | gpio_request(LCD_PANEL_LR, "LCD lr"); | ||
| 55 | gpio_request(LCD_PANEL_UD, "LCD ud"); | ||
| 56 | gpio_request(LCD_PANEL_INI, "LCD ini"); | ||
| 57 | gpio_request(LCD_PANEL_RESB, "LCD resb"); | ||
| 58 | gpio_request(LCD_PANEL_QVGA, "LCD qvga"); | ||
| 59 | |||
| 60 | gpio_direction_output(LCD_PANEL_RESB, 1); | ||
| 61 | gpio_direction_output(LCD_PANEL_INI, 1); | ||
| 62 | gpio_direction_output(LCD_PANEL_QVGA, 0); | ||
| 63 | gpio_direction_output(LCD_PANEL_LR, 1); | ||
| 64 | gpio_direction_output(LCD_PANEL_UD, 1); | ||
| 65 | |||
| 66 | twl_i2c_write_u8(TWL4030_MODULE_LED, 0x11, TWL_LED_LEDEN); | ||
| 67 | twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x01, TWL_PWMA_PWMAON); | ||
| 68 | twl_i2c_write_u8(TWL4030_MODULE_PWMA, 0x02, TWL_PWMA_PWMAOFF); | ||
| 69 | bklight_level = 100; | ||
| 70 | |||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static void omap3evm_panel_cleanup(struct lcd_panel *panel) | ||
| 75 | { | ||
| 76 | gpio_free(LCD_PANEL_QVGA); | ||
| 77 | gpio_free(LCD_PANEL_RESB); | ||
| 78 | gpio_free(LCD_PANEL_INI); | ||
| 79 | gpio_free(LCD_PANEL_UD); | ||
| 80 | gpio_free(LCD_PANEL_LR); | ||
| 81 | } | ||
| 82 | |||
| 83 | static int omap3evm_panel_enable(struct lcd_panel *panel) | ||
| 84 | { | ||
| 85 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 0); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static void omap3evm_panel_disable(struct lcd_panel *panel) | ||
| 90 | { | ||
| 91 | gpio_set_value(LCD_PANEL_ENABLE_GPIO, 1); | ||
| 92 | } | ||
| 93 | |||
| 94 | static unsigned long omap3evm_panel_get_caps(struct lcd_panel *panel) | ||
| 95 | { | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int omap3evm_bklight_setlevel(struct lcd_panel *panel, | ||
| 100 | unsigned int level) | ||
| 101 | { | ||
| 102 | u8 c; | ||
| 103 | if ((level >= 0) && (level <= 100)) { | ||
| 104 | c = (125 * (100 - level)) / 100 + 2; | ||
| 105 | twl_i2c_write_u8(TWL4030_MODULE_PWMA, c, TWL_PWMA_PWMAOFF); | ||
| 106 | bklight_level = level; | ||
| 107 | } | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | static unsigned int omap3evm_bklight_getlevel(struct lcd_panel *panel) | ||
| 112 | { | ||
| 113 | return bklight_level; | ||
| 114 | } | ||
| 115 | |||
| 116 | static unsigned int omap3evm_bklight_getmaxlevel(struct lcd_panel *panel) | ||
| 117 | { | ||
| 118 | return 100; | ||
| 119 | } | ||
| 120 | |||
| 121 | struct lcd_panel omap3evm_panel = { | ||
| 122 | .name = "omap3evm", | ||
| 123 | .config = OMAP_LCDC_PANEL_TFT | OMAP_LCDC_INV_VSYNC | | ||
| 124 | OMAP_LCDC_INV_HSYNC, | ||
| 125 | |||
| 126 | .bpp = 16, | ||
| 127 | .data_lines = 18, | ||
| 128 | .x_res = 480, | ||
| 129 | .y_res = 640, | ||
| 130 | .hsw = 3, /* hsync_len (4) - 1 */ | ||
| 131 | .hfp = 3, /* right_margin (4) - 1 */ | ||
| 132 | .hbp = 39, /* left_margin (40) - 1 */ | ||
| 133 | .vsw = 1, /* vsync_len (2) - 1 */ | ||
| 134 | .vfp = 2, /* lower_margin */ | ||
| 135 | .vbp = 7, /* upper_margin (8) - 1 */ | ||
| 136 | |||
| 137 | .pixel_clock = 26000, | ||
| 138 | |||
| 139 | .init = omap3evm_panel_init, | ||
| 140 | .cleanup = omap3evm_panel_cleanup, | ||
| 141 | .enable = omap3evm_panel_enable, | ||
| 142 | .disable = omap3evm_panel_disable, | ||
| 143 | .get_caps = omap3evm_panel_get_caps, | ||
| 144 | .set_bklight_level = omap3evm_bklight_setlevel, | ||
| 145 | .get_bklight_level = omap3evm_bklight_getlevel, | ||
| 146 | .get_bklight_max = omap3evm_bklight_getmaxlevel, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static int omap3evm_panel_probe(struct platform_device *pdev) | ||
| 150 | { | ||
| 151 | omapfb_register_panel(&omap3evm_panel); | ||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int omap3evm_panel_remove(struct platform_device *pdev) | ||
| 156 | { | ||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int omap3evm_panel_suspend(struct platform_device *pdev, | ||
| 161 | pm_message_t mesg) | ||
| 162 | { | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | static int omap3evm_panel_resume(struct platform_device *pdev) | ||
| 167 | { | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | struct platform_driver omap3evm_panel_driver = { | ||
| 172 | .probe = omap3evm_panel_probe, | ||
| 173 | .remove = omap3evm_panel_remove, | ||
| 174 | .suspend = omap3evm_panel_suspend, | ||
| 175 | .resume = omap3evm_panel_resume, | ||
| 176 | .driver = { | ||
| 177 | .name = "omap3evm_lcd", | ||
| 178 | .owner = THIS_MODULE, | ||
| 179 | }, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static int __init omap3evm_panel_drv_init(void) | ||
| 183 | { | ||
| 184 | return platform_driver_register(&omap3evm_panel_driver); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void __exit omap3evm_panel_drv_exit(void) | ||
| 188 | { | ||
| 189 | platform_driver_unregister(&omap3evm_panel_driver); | ||
| 190 | } | ||
| 191 | |||
| 192 | module_init(omap3evm_panel_drv_init); | ||
| 193 | module_exit(omap3evm_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c index b87e8b83f29c..6f8d13c41202 100644 --- a/drivers/video/omap/lcd_osk.c +++ b/drivers/video/omap/lcd_osk.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 25 | 25 | ||
| 26 | #include <mach/gpio.h> | 26 | #include <asm/gpio.h> |
| 27 | #include <plat/mux.h> | 27 | #include <plat/mux.h> |
| 28 | #include "omapfb.h" | 28 | #include "omapfb.h" |
| 29 | 29 | ||
diff --git a/drivers/video/omap/lcd_overo.c b/drivers/video/omap/lcd_overo.c deleted file mode 100644 index 564933ffac6e..000000000000 --- a/drivers/video/omap/lcd_overo.c +++ /dev/null | |||
| @@ -1,180 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * LCD panel support for the Gumstix Overo | ||
| 3 | * | ||
| 4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along | ||
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/i2c/twl.h> | ||
| 25 | |||
| 26 | #include <mach/gpio.h> | ||
| 27 | #include <plat/mux.h> | ||
| 28 | #include <asm/mach-types.h> | ||
| 29 | |||
| 30 | #include "omapfb.h" | ||
| 31 | |||
| 32 | #define LCD_ENABLE 144 | ||
| 33 | |||
| 34 | static int overo_panel_init(struct lcd_panel *panel, | ||
| 35 | struct omapfb_device *fbdev) | ||
| 36 | { | ||
| 37 | if ((gpio_request(LCD_ENABLE, "LCD_ENABLE") == 0) && | ||
| 38 | (gpio_direction_output(LCD_ENABLE, 1) == 0)) | ||
| 39 | gpio_export(LCD_ENABLE, 0); | ||
| 40 | else | ||
| 41 | printk(KERN_ERR "could not obtain gpio for LCD_ENABLE\n"); | ||
| 42 | |||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static void overo_panel_cleanup(struct lcd_panel *panel) | ||
| 47 | { | ||
| 48 | gpio_free(LCD_ENABLE); | ||
| 49 | } | ||
| 50 | |||
| 51 | static int overo_panel_enable(struct lcd_panel *panel) | ||
| 52 | { | ||
| 53 | gpio_set_value(LCD_ENABLE, 1); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void overo_panel_disable(struct lcd_panel *panel) | ||
| 58 | { | ||
| 59 | gpio_set_value(LCD_ENABLE, 0); | ||
| 60 | } | ||
| 61 | |||
| 62 | static unsigned long overo_panel_get_caps(struct lcd_panel *panel) | ||
| 63 | { | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | struct lcd_panel overo_panel = { | ||
| 68 | .name = "overo", | ||
| 69 | .config = OMAP_LCDC_PANEL_TFT, | ||
| 70 | .bpp = 16, | ||
| 71 | .data_lines = 24, | ||
| 72 | |||
| 73 | #if defined CONFIG_FB_OMAP_031M3R | ||
| 74 | |||
| 75 | /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
| 76 | .x_res = 640, | ||
| 77 | .y_res = 480, | ||
| 78 | .hfp = 48, | ||
| 79 | .hsw = 32, | ||
| 80 | .hbp = 80, | ||
| 81 | .vfp = 3, | ||
| 82 | .vsw = 4, | ||
| 83 | .vbp = 7, | ||
| 84 | .pixel_clock = 23500, | ||
| 85 | |||
| 86 | #elif defined CONFIG_FB_OMAP_048M3R | ||
| 87 | |||
| 88 | /* 800 x 600 @ 60 Hz Reduced blanking VESA CVT 0.48M3-R */ | ||
| 89 | .x_res = 800, | ||
| 90 | .y_res = 600, | ||
| 91 | .hfp = 48, | ||
| 92 | .hsw = 32, | ||
| 93 | .hbp = 80, | ||
| 94 | .vfp = 3, | ||
| 95 | .vsw = 4, | ||
| 96 | .vbp = 11, | ||
| 97 | .pixel_clock = 35500, | ||
| 98 | |||
| 99 | #elif defined CONFIG_FB_OMAP_079M3R | ||
| 100 | |||
| 101 | /* 1024 x 768 @ 60 Hz Reduced blanking VESA CVT 0.79M3-R */ | ||
| 102 | .x_res = 1024, | ||
| 103 | .y_res = 768, | ||
| 104 | .hfp = 48, | ||
| 105 | .hsw = 32, | ||
| 106 | .hbp = 80, | ||
| 107 | .vfp = 3, | ||
| 108 | .vsw = 4, | ||
| 109 | .vbp = 15, | ||
| 110 | .pixel_clock = 56000, | ||
| 111 | |||
| 112 | #elif defined CONFIG_FB_OMAP_092M9R | ||
| 113 | |||
| 114 | /* 1280 x 720 @ 60 Hz Reduced blanking VESA CVT 0.92M9-R */ | ||
| 115 | .x_res = 1280, | ||
| 116 | .y_res = 720, | ||
| 117 | .hfp = 48, | ||
| 118 | .hsw = 32, | ||
| 119 | .hbp = 80, | ||
| 120 | .vfp = 3, | ||
| 121 | .vsw = 5, | ||
| 122 | .vbp = 13, | ||
| 123 | .pixel_clock = 64000, | ||
| 124 | |||
| 125 | #else | ||
| 126 | |||
| 127 | /* use 640 x 480 if no config option */ | ||
| 128 | /* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */ | ||
| 129 | .x_res = 640, | ||
| 130 | .y_res = 480, | ||
| 131 | .hfp = 48, | ||
| 132 | .hsw = 32, | ||
| 133 | .hbp = 80, | ||
| 134 | .vfp = 3, | ||
| 135 | .vsw = 4, | ||
| 136 | .vbp = 7, | ||
| 137 | .pixel_clock = 23500, | ||
| 138 | |||
| 139 | #endif | ||
| 140 | |||
| 141 | .init = overo_panel_init, | ||
| 142 | .cleanup = overo_panel_cleanup, | ||
| 143 | .enable = overo_panel_enable, | ||
| 144 | .disable = overo_panel_disable, | ||
| 145 | .get_caps = overo_panel_get_caps, | ||
| 146 | }; | ||
| 147 | |||
| 148 | static int overo_panel_probe(struct platform_device *pdev) | ||
| 149 | { | ||
| 150 | omapfb_register_panel(&overo_panel); | ||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | static int overo_panel_remove(struct platform_device *pdev) | ||
| 155 | { | ||
| 156 | /* omapfb does not have unregister_panel */ | ||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static struct platform_driver overo_panel_driver = { | ||
| 161 | .probe = overo_panel_probe, | ||
| 162 | .remove = overo_panel_remove, | ||
| 163 | .driver = { | ||
| 164 | .name = "overo_lcd", | ||
| 165 | .owner = THIS_MODULE, | ||
| 166 | }, | ||
| 167 | }; | ||
| 168 | |||
| 169 | static int __init overo_panel_drv_init(void) | ||
| 170 | { | ||
| 171 | return platform_driver_register(&overo_panel_driver); | ||
| 172 | } | ||
| 173 | |||
| 174 | static void __exit overo_panel_drv_exit(void) | ||
| 175 | { | ||
| 176 | platform_driver_unregister(&overo_panel_driver); | ||
| 177 | } | ||
| 178 | |||
| 179 | module_init(overo_panel_drv_init); | ||
| 180 | module_exit(overo_panel_drv_exit); | ||
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c index ff0e6d7ab3a2..b51b332e5a2b 100644 --- a/drivers/video/omap/lcd_palmtt.c +++ b/drivers/video/omap/lcd_palmtt.c | |||
| @@ -29,7 +29,7 @@ GPIO13 - screen blanking | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
| 31 | 31 | ||
| 32 | #include <mach/gpio.h> | 32 | #include <asm/gpio.h> |
| 33 | #include "omapfb.h" | 33 | #include "omapfb.h" |
| 34 | 34 | ||
| 35 | static int palmtt_panel_init(struct lcd_panel *panel, | 35 | static int palmtt_panel_init(struct lcd_panel *panel, |
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index b3ddd743d8a6..25d8e5103193 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
| 31 | #include <linux/module.h> | ||
| 31 | 32 | ||
| 32 | #include <plat/dma.h> | 33 | #include <plat/dma.h> |
| 33 | 34 | ||
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 609a28073178..8d8e1fe1901c 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig | |||
| @@ -10,6 +10,13 @@ config PANEL_GENERIC_DPI | |||
| 10 | Supports LCD Panel used in TI SDP3430 and EVM boards, | 10 | Supports LCD Panel used in TI SDP3430 and EVM boards, |
| 11 | OMAP3517 EVM boards and CM-T35. | 11 | OMAP3517 EVM boards and CM-T35. |
| 12 | 12 | ||
| 13 | config PANEL_DVI | ||
| 14 | tristate "DVI output" | ||
| 15 | depends on OMAP2_DSS_DPI | ||
| 16 | help | ||
| 17 | Driver for external monitors, connected via DVI. The driver uses i2c | ||
| 18 | to read EDID information from the monitor. | ||
| 19 | |||
| 13 | config PANEL_LGPHILIPS_LB035Q02 | 20 | config PANEL_LGPHILIPS_LB035Q02 |
| 14 | tristate "LG.Philips LB035Q02 LCD Panel" | 21 | tristate "LG.Philips LB035Q02 LCD Panel" |
| 15 | depends on OMAP2_DSS_DPI && SPI | 22 | depends on OMAP2_DSS_DPI && SPI |
| @@ -19,20 +26,30 @@ config PANEL_LGPHILIPS_LB035Q02 | |||
| 19 | config PANEL_SHARP_LS037V7DW01 | 26 | config PANEL_SHARP_LS037V7DW01 |
| 20 | tristate "Sharp LS037V7DW01 LCD Panel" | 27 | tristate "Sharp LS037V7DW01 LCD Panel" |
| 21 | depends on OMAP2_DSS_DPI | 28 | depends on OMAP2_DSS_DPI |
| 22 | select BACKLIGHT_CLASS_DEVICE | 29 | depends on BACKLIGHT_CLASS_DEVICE |
| 23 | help | 30 | help |
| 24 | LCD Panel used in TI's SDP3430 and EVM boards | 31 | LCD Panel used in TI's SDP3430 and EVM boards |
| 25 | 32 | ||
| 26 | config PANEL_NEC_NL8048HL11_01B | 33 | config PANEL_NEC_NL8048HL11_01B |
| 27 | tristate "NEC NL8048HL11-01B Panel" | 34 | tristate "NEC NL8048HL11-01B Panel" |
| 28 | depends on OMAP2_DSS_DPI | 35 | depends on OMAP2_DSS_DPI |
| 36 | depends on SPI | ||
| 37 | depends on BACKLIGHT_CLASS_DEVICE | ||
| 29 | help | 38 | help |
| 30 | This NEC NL8048HL11-01B panel is TFT LCD | 39 | This NEC NL8048HL11-01B panel is TFT LCD |
| 31 | used in the Zoom2/3/3630 sdp boards. | 40 | used in the Zoom2/3/3630 sdp boards. |
| 32 | 41 | ||
| 42 | config PANEL_PICODLP | ||
| 43 | tristate "TI PICO DLP mini-projector" | ||
| 44 | depends on OMAP2_DSS && I2C | ||
| 45 | help | ||
| 46 | A mini-projector used in TI's SDP4430 and EVM boards | ||
| 47 | For more info please visit http://www.dlp.com/projector/ | ||
| 48 | |||
| 33 | config PANEL_TAAL | 49 | config PANEL_TAAL |
| 34 | tristate "Taal DSI Panel" | 50 | tristate "Taal DSI Panel" |
| 35 | depends on OMAP2_DSS_DSI | 51 | depends on OMAP2_DSS_DSI |
| 52 | depends on BACKLIGHT_CLASS_DEVICE | ||
| 36 | help | 53 | help |
| 37 | Taal DSI command mode panel from TPO. | 54 | Taal DSI command mode panel from TPO. |
| 38 | 55 | ||
| @@ -45,7 +62,14 @@ config PANEL_TPO_TD043MTEA1 | |||
| 45 | config PANEL_ACX565AKM | 62 | config PANEL_ACX565AKM |
| 46 | tristate "ACX565AKM Panel" | 63 | tristate "ACX565AKM Panel" |
| 47 | depends on OMAP2_DSS_SDI && SPI | 64 | depends on OMAP2_DSS_SDI && SPI |
| 48 | select BACKLIGHT_CLASS_DEVICE | 65 | depends on BACKLIGHT_CLASS_DEVICE |
| 49 | help | 66 | help |
| 50 | This is the LCD panel used on Nokia N900 | 67 | This is the LCD panel used on Nokia N900 |
| 68 | |||
| 69 | config PANEL_N8X0 | ||
| 70 | tristate "N8X0 Panel" | ||
| 71 | depends on OMAP2_DSS_RFBI && SPI | ||
| 72 | depends on BACKLIGHT_CLASS_DEVICE | ||
| 73 | help | ||
| 74 | This is the LCD panel used on Nokia N8x0 | ||
| 51 | endmenu | 75 | endmenu |
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 0f601ab3abf4..fbfafc6eebb4 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o | 1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o |
| 2 | obj-$(CONFIG_PANEL_DVI) += panel-dvi.o | ||
| 2 | obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o | 3 | obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o |
| 3 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o | 4 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o |
| 4 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o | 5 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o |
| 5 | 6 | ||
| 6 | obj-$(CONFIG_PANEL_TAAL) += panel-taal.o | 7 | obj-$(CONFIG_PANEL_TAAL) += panel-taal.o |
| 8 | obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o | ||
| 7 | obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o | 9 | obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o |
| 8 | obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o | 10 | obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o |
| 11 | obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o | ||
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-dvi.c new file mode 100644 index 000000000000..03eb14af33e0 --- /dev/null +++ b/drivers/video/omap2/displays/panel-dvi.c | |||
| @@ -0,0 +1,363 @@ | |||
| 1 | /* | ||
| 2 | * DVI output support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Texas Instruments Inc | ||
| 5 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published by | ||
| 9 | * the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along with | ||
| 17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | #include <video/omapdss.h> | ||
| 23 | #include <linux/i2c.h> | ||
| 24 | #include <drm/drm_edid.h> | ||
| 25 | |||
| 26 | #include <video/omap-panel-dvi.h> | ||
| 27 | |||
| 28 | static const struct omap_video_timings panel_dvi_default_timings = { | ||
| 29 | .x_res = 640, | ||
| 30 | .y_res = 480, | ||
| 31 | |||
| 32 | .pixel_clock = 23500, | ||
| 33 | |||
| 34 | .hfp = 48, | ||
| 35 | .hsw = 32, | ||
| 36 | .hbp = 80, | ||
| 37 | |||
| 38 | .vfp = 3, | ||
| 39 | .vsw = 4, | ||
| 40 | .vbp = 7, | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct panel_drv_data { | ||
| 44 | struct omap_dss_device *dssdev; | ||
| 45 | |||
| 46 | struct mutex lock; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static inline struct panel_dvi_platform_data | ||
| 50 | *get_pdata(const struct omap_dss_device *dssdev) | ||
| 51 | { | ||
| 52 | return dssdev->data; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int panel_dvi_power_on(struct omap_dss_device *dssdev) | ||
| 56 | { | ||
| 57 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
| 58 | int r; | ||
| 59 | |||
| 60 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
| 61 | return 0; | ||
| 62 | |||
| 63 | r = omapdss_dpi_display_enable(dssdev); | ||
| 64 | if (r) | ||
| 65 | goto err0; | ||
| 66 | |||
| 67 | if (pdata->platform_enable) { | ||
| 68 | r = pdata->platform_enable(dssdev); | ||
| 69 | if (r) | ||
| 70 | goto err1; | ||
| 71 | } | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | err1: | ||
| 75 | omapdss_dpi_display_disable(dssdev); | ||
| 76 | err0: | ||
| 77 | return r; | ||
| 78 | } | ||
| 79 | |||
| 80 | static void panel_dvi_power_off(struct omap_dss_device *dssdev) | ||
| 81 | { | ||
| 82 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
| 83 | |||
| 84 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
| 85 | return; | ||
| 86 | |||
| 87 | if (pdata->platform_disable) | ||
| 88 | pdata->platform_disable(dssdev); | ||
| 89 | |||
| 90 | omapdss_dpi_display_disable(dssdev); | ||
| 91 | } | ||
| 92 | |||
| 93 | static int panel_dvi_probe(struct omap_dss_device *dssdev) | ||
| 94 | { | ||
| 95 | struct panel_drv_data *ddata; | ||
| 96 | |||
| 97 | ddata = kzalloc(sizeof(*ddata), GFP_KERNEL); | ||
| 98 | if (!ddata) | ||
| 99 | return -ENOMEM; | ||
| 100 | |||
| 101 | dssdev->panel.timings = panel_dvi_default_timings; | ||
| 102 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | ||
| 103 | |||
| 104 | ddata->dssdev = dssdev; | ||
| 105 | mutex_init(&ddata->lock); | ||
| 106 | |||
| 107 | dev_set_drvdata(&dssdev->dev, ddata); | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void __exit panel_dvi_remove(struct omap_dss_device *dssdev) | ||
| 113 | { | ||
| 114 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 115 | |||
| 116 | mutex_lock(&ddata->lock); | ||
| 117 | |||
| 118 | dev_set_drvdata(&dssdev->dev, NULL); | ||
| 119 | |||
| 120 | mutex_unlock(&ddata->lock); | ||
| 121 | |||
| 122 | kfree(ddata); | ||
| 123 | } | ||
| 124 | |||
| 125 | static int panel_dvi_enable(struct omap_dss_device *dssdev) | ||
| 126 | { | ||
| 127 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 128 | int r; | ||
| 129 | |||
| 130 | mutex_lock(&ddata->lock); | ||
| 131 | |||
| 132 | r = panel_dvi_power_on(dssdev); | ||
| 133 | if (r == 0) | ||
| 134 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
| 135 | |||
| 136 | mutex_unlock(&ddata->lock); | ||
| 137 | |||
| 138 | return r; | ||
| 139 | } | ||
| 140 | |||
| 141 | static void panel_dvi_disable(struct omap_dss_device *dssdev) | ||
| 142 | { | ||
| 143 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 144 | |||
| 145 | mutex_lock(&ddata->lock); | ||
| 146 | |||
| 147 | panel_dvi_power_off(dssdev); | ||
| 148 | |||
| 149 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
| 150 | |||
| 151 | mutex_unlock(&ddata->lock); | ||
| 152 | } | ||
| 153 | |||
| 154 | static int panel_dvi_suspend(struct omap_dss_device *dssdev) | ||
| 155 | { | ||
| 156 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 157 | |||
| 158 | mutex_lock(&ddata->lock); | ||
| 159 | |||
| 160 | panel_dvi_power_off(dssdev); | ||
| 161 | |||
| 162 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
| 163 | |||
| 164 | mutex_unlock(&ddata->lock); | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int panel_dvi_resume(struct omap_dss_device *dssdev) | ||
| 170 | { | ||
| 171 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 172 | int r; | ||
| 173 | |||
| 174 | mutex_lock(&ddata->lock); | ||
| 175 | |||
| 176 | r = panel_dvi_power_on(dssdev); | ||
| 177 | if (r == 0) | ||
| 178 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
| 179 | |||
| 180 | mutex_unlock(&ddata->lock); | ||
| 181 | |||
| 182 | return r; | ||
| 183 | } | ||
| 184 | |||
| 185 | static void panel_dvi_set_timings(struct omap_dss_device *dssdev, | ||
| 186 | struct omap_video_timings *timings) | ||
| 187 | { | ||
| 188 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 189 | |||
| 190 | mutex_lock(&ddata->lock); | ||
| 191 | dpi_set_timings(dssdev, timings); | ||
| 192 | mutex_unlock(&ddata->lock); | ||
| 193 | } | ||
| 194 | |||
| 195 | static void panel_dvi_get_timings(struct omap_dss_device *dssdev, | ||
| 196 | struct omap_video_timings *timings) | ||
| 197 | { | ||
| 198 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 199 | |||
| 200 | mutex_lock(&ddata->lock); | ||
| 201 | *timings = dssdev->panel.timings; | ||
| 202 | mutex_unlock(&ddata->lock); | ||
| 203 | } | ||
| 204 | |||
| 205 | static int panel_dvi_check_timings(struct omap_dss_device *dssdev, | ||
| 206 | struct omap_video_timings *timings) | ||
| 207 | { | ||
| 208 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 209 | int r; | ||
| 210 | |||
| 211 | mutex_lock(&ddata->lock); | ||
| 212 | r = dpi_check_timings(dssdev, timings); | ||
| 213 | mutex_unlock(&ddata->lock); | ||
| 214 | |||
| 215 | return r; | ||
| 216 | } | ||
| 217 | |||
| 218 | |||
| 219 | static int panel_dvi_ddc_read(struct i2c_adapter *adapter, | ||
| 220 | unsigned char *buf, u16 count, u8 offset) | ||
| 221 | { | ||
| 222 | int r, retries; | ||
| 223 | |||
| 224 | for (retries = 3; retries > 0; retries--) { | ||
| 225 | struct i2c_msg msgs[] = { | ||
| 226 | { | ||
| 227 | .addr = DDC_ADDR, | ||
| 228 | .flags = 0, | ||
| 229 | .len = 1, | ||
| 230 | .buf = &offset, | ||
| 231 | }, { | ||
| 232 | .addr = DDC_ADDR, | ||
| 233 | .flags = I2C_M_RD, | ||
| 234 | .len = count, | ||
| 235 | .buf = buf, | ||
| 236 | } | ||
| 237 | }; | ||
| 238 | |||
| 239 | r = i2c_transfer(adapter, msgs, 2); | ||
| 240 | if (r == 2) | ||
| 241 | return 0; | ||
| 242 | |||
| 243 | if (r != -EAGAIN) | ||
| 244 | break; | ||
| 245 | } | ||
| 246 | |||
| 247 | return r < 0 ? r : -EIO; | ||
| 248 | } | ||
| 249 | |||
| 250 | static int panel_dvi_read_edid(struct omap_dss_device *dssdev, | ||
| 251 | u8 *edid, int len) | ||
| 252 | { | ||
| 253 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 254 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
| 255 | struct i2c_adapter *adapter; | ||
| 256 | int r, l, bytes_read; | ||
| 257 | |||
| 258 | mutex_lock(&ddata->lock); | ||
| 259 | |||
| 260 | if (pdata->i2c_bus_num == 0) { | ||
| 261 | r = -ENODEV; | ||
| 262 | goto err; | ||
| 263 | } | ||
| 264 | |||
| 265 | adapter = i2c_get_adapter(pdata->i2c_bus_num); | ||
| 266 | if (!adapter) { | ||
| 267 | dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", | ||
| 268 | pdata->i2c_bus_num); | ||
| 269 | r = -EINVAL; | ||
| 270 | goto err; | ||
| 271 | } | ||
| 272 | |||
| 273 | l = min(EDID_LENGTH, len); | ||
| 274 | r = panel_dvi_ddc_read(adapter, edid, l, 0); | ||
| 275 | if (r) | ||
| 276 | goto err; | ||
| 277 | |||
| 278 | bytes_read = l; | ||
| 279 | |||
| 280 | /* if there are extensions, read second block */ | ||
| 281 | if (len > EDID_LENGTH && edid[0x7e] > 0) { | ||
| 282 | l = min(EDID_LENGTH, len - EDID_LENGTH); | ||
| 283 | |||
| 284 | r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH, | ||
| 285 | l, EDID_LENGTH); | ||
| 286 | if (r) | ||
| 287 | goto err; | ||
| 288 | |||
| 289 | bytes_read += l; | ||
| 290 | } | ||
| 291 | |||
| 292 | mutex_unlock(&ddata->lock); | ||
| 293 | |||
| 294 | return bytes_read; | ||
| 295 | |||
| 296 | err: | ||
| 297 | mutex_unlock(&ddata->lock); | ||
| 298 | return r; | ||
| 299 | } | ||
| 300 | |||
| 301 | static bool panel_dvi_detect(struct omap_dss_device *dssdev) | ||
| 302 | { | ||
| 303 | struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); | ||
| 304 | struct panel_dvi_platform_data *pdata = get_pdata(dssdev); | ||
| 305 | struct i2c_adapter *adapter; | ||
| 306 | unsigned char out; | ||
| 307 | int r; | ||
| 308 | |||
| 309 | mutex_lock(&ddata->lock); | ||
| 310 | |||
| 311 | if (pdata->i2c_bus_num == 0) | ||
| 312 | goto out; | ||
| 313 | |||
| 314 | adapter = i2c_get_adapter(pdata->i2c_bus_num); | ||
| 315 | if (!adapter) | ||
| 316 | goto out; | ||
| 317 | |||
| 318 | r = panel_dvi_ddc_read(adapter, &out, 1, 0); | ||
| 319 | |||
| 320 | mutex_unlock(&ddata->lock); | ||
| 321 | |||
| 322 | return r == 0; | ||
| 323 | |||
| 324 | out: | ||
| 325 | mutex_unlock(&ddata->lock); | ||
| 326 | return true; | ||
| 327 | } | ||
| 328 | |||
| 329 | static struct omap_dss_driver panel_dvi_driver = { | ||
| 330 | .probe = panel_dvi_probe, | ||
| 331 | .remove = __exit_p(panel_dvi_remove), | ||
| 332 | |||
| 333 | .enable = panel_dvi_enable, | ||
| 334 | .disable = panel_dvi_disable, | ||
| 335 | .suspend = panel_dvi_suspend, | ||
| 336 | .resume = panel_dvi_resume, | ||
| 337 | |||
| 338 | .set_timings = panel_dvi_set_timings, | ||
| 339 | .get_timings = panel_dvi_get_timings, | ||
| 340 | .check_timings = panel_dvi_check_timings, | ||
| 341 | |||
| 342 | .read_edid = panel_dvi_read_edid, | ||
| 343 | .detect = panel_dvi_detect, | ||
| 344 | |||
| 345 | .driver = { | ||
| 346 | .name = "dvi", | ||
| 347 | .owner = THIS_MODULE, | ||
| 348 | }, | ||
| 349 | }; | ||
| 350 | |||
| 351 | static int __init panel_dvi_init(void) | ||
| 352 | { | ||
| 353 | return omap_dss_register_driver(&panel_dvi_driver); | ||
| 354 | } | ||
| 355 | |||
| 356 | static void __exit panel_dvi_exit(void) | ||
| 357 | { | ||
| 358 | omap_dss_unregister_driver(&panel_dvi_driver); | ||
| 359 | } | ||
| 360 | |||
| 361 | module_init(panel_dvi_init); | ||
| 362 | module_exit(panel_dvi_exit); | ||
| 363 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 9c90f75653fb..519c47d2057f 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
| @@ -58,30 +58,6 @@ struct panel_config { | |||
| 58 | 58 | ||
| 59 | /* Panel configurations */ | 59 | /* Panel configurations */ |
| 60 | static struct panel_config generic_dpi_panels[] = { | 60 | static struct panel_config generic_dpi_panels[] = { |
| 61 | /* Generic Panel */ | ||
| 62 | { | ||
| 63 | { | ||
| 64 | .x_res = 640, | ||
| 65 | .y_res = 480, | ||
| 66 | |||
| 67 | .pixel_clock = 23500, | ||
| 68 | |||
| 69 | .hfp = 48, | ||
| 70 | .hsw = 32, | ||
| 71 | .hbp = 80, | ||
| 72 | |||
| 73 | .vfp = 3, | ||
| 74 | .vsw = 4, | ||
| 75 | .vbp = 7, | ||
| 76 | }, | ||
| 77 | .acbi = 0x0, | ||
| 78 | .acb = 0x0, | ||
| 79 | .config = OMAP_DSS_LCD_TFT, | ||
| 80 | .power_on_delay = 0, | ||
| 81 | .power_off_delay = 0, | ||
| 82 | .name = "generic", | ||
| 83 | }, | ||
| 84 | |||
| 85 | /* Sharp LQ043T1DG01 */ | 61 | /* Sharp LQ043T1DG01 */ |
| 86 | { | 62 | { |
| 87 | { | 63 | { |
| @@ -232,6 +208,95 @@ static struct panel_config generic_dpi_panels[] = { | |||
| 232 | .power_off_delay = 0, | 208 | .power_off_delay = 0, |
| 233 | .name = "powertip_ph480272t", | 209 | .name = "powertip_ph480272t", |
| 234 | }, | 210 | }, |
| 211 | |||
| 212 | /* Innolux AT070TN83 */ | ||
| 213 | { | ||
| 214 | { | ||
| 215 | .x_res = 800, | ||
| 216 | .y_res = 480, | ||
| 217 | |||
| 218 | .pixel_clock = 40000, | ||
| 219 | |||
| 220 | .hsw = 48, | ||
| 221 | .hfp = 1, | ||
| 222 | .hbp = 1, | ||
| 223 | |||
| 224 | .vsw = 3, | ||
| 225 | .vfp = 12, | ||
| 226 | .vbp = 25, | ||
| 227 | }, | ||
| 228 | .acbi = 0x0, | ||
| 229 | .acb = 0x28, | ||
| 230 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
| 231 | OMAP_DSS_LCD_IHS, | ||
| 232 | .power_on_delay = 0, | ||
| 233 | .power_off_delay = 0, | ||
| 234 | .name = "innolux_at070tn83", | ||
| 235 | }, | ||
| 236 | |||
| 237 | /* NEC NL2432DR22-11B */ | ||
| 238 | { | ||
| 239 | { | ||
| 240 | .x_res = 240, | ||
| 241 | .y_res = 320, | ||
| 242 | |||
| 243 | .pixel_clock = 5400, | ||
| 244 | |||
| 245 | .hsw = 3, | ||
| 246 | .hfp = 3, | ||
| 247 | .hbp = 39, | ||
| 248 | |||
| 249 | .vsw = 1, | ||
| 250 | .vfp = 2, | ||
| 251 | .vbp = 7, | ||
| 252 | }, | ||
| 253 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
| 254 | OMAP_DSS_LCD_IHS, | ||
| 255 | .name = "nec_nl2432dr22-11b", | ||
| 256 | }, | ||
| 257 | |||
| 258 | /* Unknown panel used in OMAP H4 */ | ||
| 259 | { | ||
| 260 | { | ||
| 261 | .x_res = 240, | ||
| 262 | .y_res = 320, | ||
| 263 | |||
| 264 | .pixel_clock = 6250, | ||
| 265 | |||
| 266 | .hsw = 15, | ||
| 267 | .hfp = 15, | ||
| 268 | .hbp = 60, | ||
| 269 | |||
| 270 | .vsw = 1, | ||
| 271 | .vfp = 1, | ||
| 272 | .vbp = 1, | ||
| 273 | }, | ||
| 274 | .config = OMAP_DSS_LCD_TFT, | ||
| 275 | |||
| 276 | .name = "h4", | ||
| 277 | }, | ||
| 278 | |||
| 279 | /* Unknown panel used in Samsung OMAP2 Apollon */ | ||
| 280 | { | ||
| 281 | { | ||
| 282 | .x_res = 480, | ||
| 283 | .y_res = 272, | ||
| 284 | |||
| 285 | .pixel_clock = 6250, | ||
| 286 | |||
| 287 | .hsw = 41, | ||
| 288 | .hfp = 2, | ||
| 289 | .hbp = 2, | ||
| 290 | |||
| 291 | .vsw = 10, | ||
| 292 | .vfp = 2, | ||
| 293 | .vbp = 2, | ||
| 294 | }, | ||
| 295 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
| 296 | OMAP_DSS_LCD_IHS, | ||
| 297 | |||
| 298 | .name = "apollon", | ||
| 299 | }, | ||
| 235 | }; | 300 | }; |
| 236 | 301 | ||
| 237 | struct panel_drv_data { | 302 | struct panel_drv_data { |
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c new file mode 100644 index 000000000000..150e8bae35a1 --- /dev/null +++ b/drivers/video/omap2/displays/panel-n8x0.c | |||
| @@ -0,0 +1,747 @@ | |||
| 1 | /* #define DEBUG */ | ||
| 2 | |||
| 3 | #include <linux/module.h> | ||
| 4 | #include <linux/delay.h> | ||
| 5 | #include <linux/slab.h> | ||
| 6 | #include <linux/gpio.h> | ||
| 7 | #include <linux/spi/spi.h> | ||
| 8 | #include <linux/backlight.h> | ||
| 9 | #include <linux/fb.h> | ||
| 10 | |||
| 11 | #include <video/omapdss.h> | ||
| 12 | #include <video/omap-panel-n8x0.h> | ||
| 13 | |||
| 14 | #define BLIZZARD_REV_CODE 0x00 | ||
| 15 | #define BLIZZARD_CONFIG 0x02 | ||
| 16 | #define BLIZZARD_PLL_DIV 0x04 | ||
| 17 | #define BLIZZARD_PLL_LOCK_RANGE 0x06 | ||
| 18 | #define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08 | ||
| 19 | #define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a | ||
| 20 | #define BLIZZARD_PLL_MODE 0x0c | ||
| 21 | #define BLIZZARD_CLK_SRC 0x0e | ||
| 22 | #define BLIZZARD_MEM_BANK0_ACTIVATE 0x10 | ||
| 23 | #define BLIZZARD_MEM_BANK0_STATUS 0x14 | ||
| 24 | #define BLIZZARD_PANEL_CONFIGURATION 0x28 | ||
| 25 | #define BLIZZARD_HDISP 0x2a | ||
| 26 | #define BLIZZARD_HNDP 0x2c | ||
| 27 | #define BLIZZARD_VDISP0 0x2e | ||
| 28 | #define BLIZZARD_VDISP1 0x30 | ||
| 29 | #define BLIZZARD_VNDP 0x32 | ||
| 30 | #define BLIZZARD_HSW 0x34 | ||
| 31 | #define BLIZZARD_VSW 0x38 | ||
| 32 | #define BLIZZARD_DISPLAY_MODE 0x68 | ||
| 33 | #define BLIZZARD_INPUT_WIN_X_START_0 0x6c | ||
| 34 | #define BLIZZARD_DATA_SOURCE_SELECT 0x8e | ||
| 35 | #define BLIZZARD_DISP_MEM_DATA_PORT 0x90 | ||
| 36 | #define BLIZZARD_DISP_MEM_READ_ADDR0 0x92 | ||
| 37 | #define BLIZZARD_POWER_SAVE 0xE6 | ||
| 38 | #define BLIZZARD_NDISP_CTRL_STATUS 0xE8 | ||
| 39 | |||
| 40 | /* Data source select */ | ||
| 41 | /* For S1D13745 */ | ||
| 42 | #define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00 | ||
| 43 | #define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01 | ||
| 44 | #define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04 | ||
| 45 | #define BLIZZARD_SRC_DISABLE_OVERLAY 0x05 | ||
| 46 | /* For S1D13744 */ | ||
| 47 | #define BLIZZARD_SRC_WRITE_LCD 0x00 | ||
| 48 | #define BLIZZARD_SRC_BLT_LCD 0x06 | ||
| 49 | |||
| 50 | #define BLIZZARD_COLOR_RGB565 0x01 | ||
| 51 | #define BLIZZARD_COLOR_YUV420 0x09 | ||
| 52 | |||
| 53 | #define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */ | ||
| 54 | #define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */ | ||
| 55 | |||
| 56 | #define MIPID_CMD_READ_DISP_ID 0x04 | ||
| 57 | #define MIPID_CMD_READ_RED 0x06 | ||
| 58 | #define MIPID_CMD_READ_GREEN 0x07 | ||
| 59 | #define MIPID_CMD_READ_BLUE 0x08 | ||
| 60 | #define MIPID_CMD_READ_DISP_STATUS 0x09 | ||
| 61 | #define MIPID_CMD_RDDSDR 0x0F | ||
| 62 | #define MIPID_CMD_SLEEP_IN 0x10 | ||
| 63 | #define MIPID_CMD_SLEEP_OUT 0x11 | ||
| 64 | #define MIPID_CMD_DISP_OFF 0x28 | ||
| 65 | #define MIPID_CMD_DISP_ON 0x29 | ||
| 66 | |||
| 67 | static struct panel_drv_data { | ||
| 68 | struct mutex lock; | ||
| 69 | |||
| 70 | struct omap_dss_device *dssdev; | ||
| 71 | struct spi_device *spidev; | ||
| 72 | struct backlight_device *bldev; | ||
| 73 | |||
| 74 | int blizzard_ver; | ||
| 75 | } s_drv_data; | ||
| 76 | |||
| 77 | |||
| 78 | static inline | ||
| 79 | struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev) | ||
| 80 | { | ||
| 81 | return dssdev->data; | ||
| 82 | } | ||
| 83 | |||
| 84 | static inline | ||
| 85 | struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev) | ||
| 86 | { | ||
| 87 | return &s_drv_data; | ||
| 88 | } | ||
| 89 | |||
| 90 | |||
| 91 | static inline void blizzard_cmd(u8 cmd) | ||
| 92 | { | ||
| 93 | omap_rfbi_write_command(&cmd, 1); | ||
| 94 | } | ||
| 95 | |||
| 96 | static inline void blizzard_write(u8 cmd, const u8 *buf, int len) | ||
| 97 | { | ||
| 98 | omap_rfbi_write_command(&cmd, 1); | ||
| 99 | omap_rfbi_write_data(buf, len); | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline void blizzard_read(u8 cmd, u8 *buf, int len) | ||
| 103 | { | ||
| 104 | omap_rfbi_write_command(&cmd, 1); | ||
| 105 | omap_rfbi_read_data(buf, len); | ||
| 106 | } | ||
| 107 | |||
| 108 | static u8 blizzard_read_reg(u8 cmd) | ||
| 109 | { | ||
| 110 | u8 data; | ||
| 111 | blizzard_read(cmd, &data, 1); | ||
| 112 | return data; | ||
| 113 | } | ||
| 114 | |||
| 115 | static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev, | ||
| 116 | int x, int y, int w, int h) | ||
| 117 | { | ||
| 118 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 119 | u8 tmp[18]; | ||
| 120 | int x_end, y_end; | ||
| 121 | |||
| 122 | x_end = x + w - 1; | ||
| 123 | y_end = y + h - 1; | ||
| 124 | |||
| 125 | tmp[0] = x; | ||
| 126 | tmp[1] = x >> 8; | ||
| 127 | tmp[2] = y; | ||
| 128 | tmp[3] = y >> 8; | ||
| 129 | tmp[4] = x_end; | ||
| 130 | tmp[5] = x_end >> 8; | ||
| 131 | tmp[6] = y_end; | ||
| 132 | tmp[7] = y_end >> 8; | ||
| 133 | |||
| 134 | /* scaling? */ | ||
| 135 | tmp[8] = x; | ||
| 136 | tmp[9] = x >> 8; | ||
| 137 | tmp[10] = y; | ||
| 138 | tmp[11] = y >> 8; | ||
| 139 | tmp[12] = x_end; | ||
| 140 | tmp[13] = x_end >> 8; | ||
| 141 | tmp[14] = y_end; | ||
| 142 | tmp[15] = y_end >> 8; | ||
| 143 | |||
| 144 | tmp[16] = BLIZZARD_COLOR_RGB565; | ||
| 145 | |||
| 146 | if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745) | ||
| 147 | tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND; | ||
| 148 | else | ||
| 149 | tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ? | ||
| 150 | BLIZZARD_SRC_WRITE_LCD : | ||
| 151 | BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; | ||
| 152 | |||
| 153 | omap_rfbi_configure(dssdev, 16, 8); | ||
| 154 | |||
| 155 | blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); | ||
| 156 | |||
| 157 | omap_rfbi_configure(dssdev, 16, 16); | ||
| 158 | } | ||
| 159 | |||
| 160 | static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, | ||
| 161 | int wlen, u8 *rbuf, int rlen) | ||
| 162 | { | ||
| 163 | struct spi_message m; | ||
| 164 | struct spi_transfer *x, xfer[4]; | ||
| 165 | u16 w; | ||
| 166 | int r; | ||
| 167 | |||
| 168 | spi_message_init(&m); | ||
| 169 | |||
| 170 | memset(xfer, 0, sizeof(xfer)); | ||
| 171 | x = &xfer[0]; | ||
| 172 | |||
| 173 | cmd &= 0xff; | ||
| 174 | x->tx_buf = &cmd; | ||
| 175 | x->bits_per_word = 9; | ||
| 176 | x->len = 2; | ||
| 177 | spi_message_add_tail(x, &m); | ||
| 178 | |||
| 179 | if (wlen) { | ||
| 180 | x++; | ||
| 181 | x->tx_buf = wbuf; | ||
| 182 | x->len = wlen; | ||
| 183 | x->bits_per_word = 9; | ||
| 184 | spi_message_add_tail(x, &m); | ||
| 185 | } | ||
| 186 | |||
| 187 | if (rlen) { | ||
| 188 | x++; | ||
| 189 | x->rx_buf = &w; | ||
| 190 | x->len = 1; | ||
| 191 | spi_message_add_tail(x, &m); | ||
| 192 | |||
| 193 | if (rlen > 1) { | ||
| 194 | /* Arrange for the extra clock before the first | ||
| 195 | * data bit. | ||
| 196 | */ | ||
| 197 | x->bits_per_word = 9; | ||
| 198 | x->len = 2; | ||
| 199 | |||
| 200 | x++; | ||
| 201 | x->rx_buf = &rbuf[1]; | ||
| 202 | x->len = rlen - 1; | ||
| 203 | spi_message_add_tail(x, &m); | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | r = spi_sync(spi, &m); | ||
| 208 | if (r < 0) | ||
| 209 | dev_dbg(&spi->dev, "spi_sync %d\n", r); | ||
| 210 | |||
| 211 | if (rlen) | ||
| 212 | rbuf[0] = w & 0xff; | ||
| 213 | } | ||
| 214 | |||
| 215 | static inline void mipid_cmd(struct spi_device *spi, int cmd) | ||
| 216 | { | ||
| 217 | mipid_transfer(spi, cmd, NULL, 0, NULL, 0); | ||
| 218 | } | ||
| 219 | |||
| 220 | static inline void mipid_write(struct spi_device *spi, | ||
| 221 | int reg, const u8 *buf, int len) | ||
| 222 | { | ||
| 223 | mipid_transfer(spi, reg, buf, len, NULL, 0); | ||
| 224 | } | ||
| 225 | |||
| 226 | static inline void mipid_read(struct spi_device *spi, | ||
| 227 | int reg, u8 *buf, int len) | ||
| 228 | { | ||
| 229 | mipid_transfer(spi, reg, NULL, 0, buf, len); | ||
| 230 | } | ||
| 231 | |||
| 232 | static void set_data_lines(struct spi_device *spi, int data_lines) | ||
| 233 | { | ||
| 234 | u16 par; | ||
| 235 | |||
| 236 | switch (data_lines) { | ||
| 237 | case 16: | ||
| 238 | par = 0x150; | ||
| 239 | break; | ||
| 240 | case 18: | ||
| 241 | par = 0x160; | ||
| 242 | break; | ||
| 243 | case 24: | ||
| 244 | par = 0x170; | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 248 | mipid_write(spi, 0x3a, (u8 *)&par, 2); | ||
| 249 | } | ||
| 250 | |||
| 251 | static void send_init_string(struct spi_device *spi) | ||
| 252 | { | ||
| 253 | u16 initpar[] = { 0x0102, 0x0100, 0x0100 }; | ||
| 254 | mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar)); | ||
| 255 | } | ||
| 256 | |||
| 257 | static void send_display_on(struct spi_device *spi) | ||
| 258 | { | ||
| 259 | mipid_cmd(spi, MIPID_CMD_DISP_ON); | ||
| 260 | } | ||
| 261 | |||
| 262 | static void send_display_off(struct spi_device *spi) | ||
| 263 | { | ||
| 264 | mipid_cmd(spi, MIPID_CMD_DISP_OFF); | ||
| 265 | } | ||
| 266 | |||
| 267 | static void send_sleep_out(struct spi_device *spi) | ||
| 268 | { | ||
| 269 | mipid_cmd(spi, MIPID_CMD_SLEEP_OUT); | ||
| 270 | msleep(120); | ||
| 271 | } | ||
| 272 | |||
| 273 | static void send_sleep_in(struct spi_device *spi) | ||
| 274 | { | ||
| 275 | mipid_cmd(spi, MIPID_CMD_SLEEP_IN); | ||
| 276 | msleep(50); | ||
| 277 | } | ||
| 278 | |||
| 279 | static int n8x0_panel_power_on(struct omap_dss_device *dssdev) | ||
| 280 | { | ||
| 281 | int r; | ||
| 282 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
| 283 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 284 | struct spi_device *spi = ddata->spidev; | ||
| 285 | u8 rev, conf; | ||
| 286 | u8 display_id[3]; | ||
| 287 | const char *panel_name; | ||
| 288 | |||
| 289 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
| 290 | return 0; | ||
| 291 | |||
| 292 | gpio_direction_output(bdata->ctrl_pwrdown, 1); | ||
| 293 | |||
| 294 | if (bdata->platform_enable) { | ||
| 295 | r = bdata->platform_enable(dssdev); | ||
| 296 | if (r) | ||
| 297 | goto err_plat_en; | ||
| 298 | } | ||
| 299 | |||
| 300 | r = omapdss_rfbi_display_enable(dssdev); | ||
| 301 | if (r) | ||
| 302 | goto err_rfbi_en; | ||
| 303 | |||
| 304 | rev = blizzard_read_reg(BLIZZARD_REV_CODE); | ||
| 305 | conf = blizzard_read_reg(BLIZZARD_CONFIG); | ||
| 306 | |||
| 307 | switch (rev & 0xfc) { | ||
| 308 | case 0x9c: | ||
| 309 | ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744; | ||
| 310 | dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d " | ||
| 311 | "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); | ||
| 312 | break; | ||
| 313 | case 0xa4: | ||
| 314 | ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745; | ||
| 315 | dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d " | ||
| 316 | "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07); | ||
| 317 | break; | ||
| 318 | default: | ||
| 319 | dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev); | ||
| 320 | r = -ENODEV; | ||
| 321 | goto err_inv_chip; | ||
| 322 | } | ||
| 323 | |||
| 324 | /* panel */ | ||
| 325 | |||
| 326 | gpio_direction_output(bdata->panel_reset, 1); | ||
| 327 | |||
| 328 | mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3); | ||
| 329 | dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n", | ||
| 330 | display_id[0], display_id[1], display_id[2]); | ||
| 331 | |||
| 332 | switch (display_id[0]) { | ||
| 333 | case 0x45: | ||
| 334 | panel_name = "lph8923"; | ||
| 335 | break; | ||
| 336 | case 0x83: | ||
| 337 | panel_name = "ls041y3"; | ||
| 338 | break; | ||
| 339 | default: | ||
| 340 | dev_err(&dssdev->dev, "invalid display ID 0x%x\n", | ||
| 341 | display_id[0]); | ||
| 342 | r = -ENODEV; | ||
| 343 | goto err_inv_panel; | ||
| 344 | } | ||
| 345 | |||
| 346 | dev_info(&dssdev->dev, "%s rev %02x LCD detected\n", | ||
| 347 | panel_name, display_id[1]); | ||
| 348 | |||
| 349 | send_sleep_out(spi); | ||
| 350 | send_init_string(spi); | ||
| 351 | set_data_lines(spi, 24); | ||
| 352 | send_display_on(spi); | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | |||
| 356 | err_inv_panel: | ||
| 357 | /* | ||
| 358 | * HACK: we should turn off the panel here, but there is some problem | ||
| 359 | * with the initialization sequence, and we fail to init the panel if we | ||
| 360 | * have turned it off | ||
| 361 | */ | ||
| 362 | /* gpio_direction_output(bdata->panel_reset, 0); */ | ||
| 363 | err_inv_chip: | ||
| 364 | omapdss_rfbi_display_disable(dssdev); | ||
| 365 | err_rfbi_en: | ||
| 366 | if (bdata->platform_disable) | ||
| 367 | bdata->platform_disable(dssdev); | ||
| 368 | err_plat_en: | ||
| 369 | gpio_direction_output(bdata->ctrl_pwrdown, 0); | ||
| 370 | return r; | ||
| 371 | } | ||
| 372 | |||
| 373 | static void n8x0_panel_power_off(struct omap_dss_device *dssdev) | ||
| 374 | { | ||
| 375 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
| 376 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 377 | struct spi_device *spi = ddata->spidev; | ||
| 378 | |||
| 379 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
| 380 | return; | ||
| 381 | |||
| 382 | send_display_off(spi); | ||
| 383 | send_sleep_in(spi); | ||
| 384 | |||
| 385 | if (bdata->platform_disable) | ||
| 386 | bdata->platform_disable(dssdev); | ||
| 387 | |||
| 388 | /* | ||
| 389 | * HACK: we should turn off the panel here, but there is some problem | ||
| 390 | * with the initialization sequence, and we fail to init the panel if we | ||
| 391 | * have turned it off | ||
| 392 | */ | ||
| 393 | /* gpio_direction_output(bdata->panel_reset, 0); */ | ||
| 394 | gpio_direction_output(bdata->ctrl_pwrdown, 0); | ||
| 395 | omapdss_rfbi_display_disable(dssdev); | ||
| 396 | } | ||
| 397 | |||
| 398 | static const struct rfbi_timings n8x0_panel_timings = { | ||
| 399 | .cs_on_time = 0, | ||
| 400 | |||
| 401 | .we_on_time = 9000, | ||
| 402 | .we_off_time = 18000, | ||
| 403 | .we_cycle_time = 36000, | ||
| 404 | |||
| 405 | .re_on_time = 9000, | ||
| 406 | .re_off_time = 27000, | ||
| 407 | .re_cycle_time = 36000, | ||
| 408 | |||
| 409 | .access_time = 27000, | ||
| 410 | .cs_off_time = 36000, | ||
| 411 | |||
| 412 | .cs_pulse_width = 0, | ||
| 413 | }; | ||
| 414 | |||
| 415 | static int n8x0_bl_update_status(struct backlight_device *dev) | ||
| 416 | { | ||
| 417 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | ||
| 418 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
| 419 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 420 | int r; | ||
| 421 | int level; | ||
| 422 | |||
| 423 | mutex_lock(&ddata->lock); | ||
| 424 | |||
| 425 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
| 426 | dev->props.power == FB_BLANK_UNBLANK) | ||
| 427 | level = dev->props.brightness; | ||
| 428 | else | ||
| 429 | level = 0; | ||
| 430 | |||
| 431 | dev_dbg(&dssdev->dev, "update brightness to %d\n", level); | ||
| 432 | |||
| 433 | if (!bdata->set_backlight) | ||
| 434 | r = -EINVAL; | ||
| 435 | else | ||
| 436 | r = bdata->set_backlight(dssdev, level); | ||
| 437 | |||
| 438 | mutex_unlock(&ddata->lock); | ||
| 439 | |||
| 440 | return r; | ||
| 441 | } | ||
| 442 | |||
| 443 | static int n8x0_bl_get_intensity(struct backlight_device *dev) | ||
| 444 | { | ||
| 445 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
| 446 | dev->props.power == FB_BLANK_UNBLANK) | ||
| 447 | return dev->props.brightness; | ||
| 448 | |||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | static const struct backlight_ops n8x0_bl_ops = { | ||
| 453 | .get_brightness = n8x0_bl_get_intensity, | ||
| 454 | .update_status = n8x0_bl_update_status, | ||
| 455 | }; | ||
| 456 | |||
| 457 | static int n8x0_panel_probe(struct omap_dss_device *dssdev) | ||
| 458 | { | ||
| 459 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
| 460 | struct panel_drv_data *ddata; | ||
| 461 | struct backlight_device *bldev; | ||
| 462 | struct backlight_properties props; | ||
| 463 | int r; | ||
| 464 | |||
| 465 | dev_dbg(&dssdev->dev, "probe\n"); | ||
| 466 | |||
| 467 | if (!bdata) | ||
| 468 | return -EINVAL; | ||
| 469 | |||
| 470 | s_drv_data.dssdev = dssdev; | ||
| 471 | |||
| 472 | ddata = &s_drv_data; | ||
| 473 | |||
| 474 | mutex_init(&ddata->lock); | ||
| 475 | |||
| 476 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | ||
| 477 | dssdev->panel.timings.x_res = 800; | ||
| 478 | dssdev->panel.timings.y_res = 480; | ||
| 479 | dssdev->ctrl.pixel_size = 16; | ||
| 480 | dssdev->ctrl.rfbi_timings = n8x0_panel_timings; | ||
| 481 | |||
| 482 | memset(&props, 0, sizeof(props)); | ||
| 483 | props.max_brightness = 127; | ||
| 484 | props.type = BACKLIGHT_PLATFORM; | ||
| 485 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, | ||
| 486 | dssdev, &n8x0_bl_ops, &props); | ||
| 487 | if (IS_ERR(bldev)) { | ||
| 488 | r = PTR_ERR(bldev); | ||
| 489 | dev_err(&dssdev->dev, "register backlight failed\n"); | ||
| 490 | return r; | ||
| 491 | } | ||
| 492 | |||
| 493 | ddata->bldev = bldev; | ||
| 494 | |||
| 495 | bldev->props.fb_blank = FB_BLANK_UNBLANK; | ||
| 496 | bldev->props.power = FB_BLANK_UNBLANK; | ||
| 497 | bldev->props.brightness = 127; | ||
| 498 | |||
| 499 | n8x0_bl_update_status(bldev); | ||
| 500 | |||
| 501 | return 0; | ||
| 502 | } | ||
| 503 | |||
| 504 | static void n8x0_panel_remove(struct omap_dss_device *dssdev) | ||
| 505 | { | ||
| 506 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 507 | struct backlight_device *bldev; | ||
| 508 | |||
| 509 | dev_dbg(&dssdev->dev, "remove\n"); | ||
| 510 | |||
| 511 | bldev = ddata->bldev; | ||
| 512 | bldev->props.power = FB_BLANK_POWERDOWN; | ||
| 513 | n8x0_bl_update_status(bldev); | ||
| 514 | backlight_device_unregister(bldev); | ||
| 515 | |||
| 516 | dev_set_drvdata(&dssdev->dev, NULL); | ||
| 517 | } | ||
| 518 | |||
| 519 | static int n8x0_panel_enable(struct omap_dss_device *dssdev) | ||
| 520 | { | ||
| 521 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 522 | int r; | ||
| 523 | |||
| 524 | dev_dbg(&dssdev->dev, "enable\n"); | ||
| 525 | |||
| 526 | mutex_lock(&ddata->lock); | ||
| 527 | |||
| 528 | rfbi_bus_lock(); | ||
| 529 | |||
| 530 | r = n8x0_panel_power_on(dssdev); | ||
| 531 | |||
| 532 | rfbi_bus_unlock(); | ||
| 533 | |||
| 534 | if (r) { | ||
| 535 | mutex_unlock(&ddata->lock); | ||
| 536 | return r; | ||
| 537 | } | ||
| 538 | |||
| 539 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
| 540 | |||
| 541 | mutex_unlock(&ddata->lock); | ||
| 542 | |||
| 543 | return 0; | ||
| 544 | } | ||
| 545 | |||
| 546 | static void n8x0_panel_disable(struct omap_dss_device *dssdev) | ||
| 547 | { | ||
| 548 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 549 | |||
| 550 | dev_dbg(&dssdev->dev, "disable\n"); | ||
| 551 | |||
| 552 | mutex_lock(&ddata->lock); | ||
| 553 | |||
| 554 | rfbi_bus_lock(); | ||
| 555 | |||
| 556 | n8x0_panel_power_off(dssdev); | ||
| 557 | |||
| 558 | rfbi_bus_unlock(); | ||
| 559 | |||
| 560 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
| 561 | |||
| 562 | mutex_unlock(&ddata->lock); | ||
| 563 | } | ||
| 564 | |||
| 565 | static int n8x0_panel_suspend(struct omap_dss_device *dssdev) | ||
| 566 | { | ||
| 567 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 568 | |||
| 569 | dev_dbg(&dssdev->dev, "suspend\n"); | ||
| 570 | |||
| 571 | mutex_lock(&ddata->lock); | ||
| 572 | |||
| 573 | rfbi_bus_lock(); | ||
| 574 | |||
| 575 | n8x0_panel_power_off(dssdev); | ||
| 576 | |||
| 577 | rfbi_bus_unlock(); | ||
| 578 | |||
| 579 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
| 580 | |||
| 581 | mutex_unlock(&ddata->lock); | ||
| 582 | |||
| 583 | return 0; | ||
| 584 | } | ||
| 585 | |||
| 586 | static int n8x0_panel_resume(struct omap_dss_device *dssdev) | ||
| 587 | { | ||
| 588 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 589 | int r; | ||
| 590 | |||
| 591 | dev_dbg(&dssdev->dev, "resume\n"); | ||
| 592 | |||
| 593 | mutex_lock(&ddata->lock); | ||
| 594 | |||
| 595 | rfbi_bus_lock(); | ||
| 596 | |||
| 597 | r = n8x0_panel_power_on(dssdev); | ||
| 598 | |||
| 599 | rfbi_bus_unlock(); | ||
| 600 | |||
| 601 | if (r) { | ||
| 602 | mutex_unlock(&ddata->lock); | ||
| 603 | return r; | ||
| 604 | } | ||
| 605 | |||
| 606 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
| 607 | |||
| 608 | mutex_unlock(&ddata->lock); | ||
| 609 | |||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | |||
| 613 | static void n8x0_panel_get_timings(struct omap_dss_device *dssdev, | ||
| 614 | struct omap_video_timings *timings) | ||
| 615 | { | ||
| 616 | *timings = dssdev->panel.timings; | ||
| 617 | } | ||
| 618 | |||
| 619 | static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, | ||
| 620 | u16 *xres, u16 *yres) | ||
| 621 | { | ||
| 622 | *xres = dssdev->panel.timings.x_res; | ||
| 623 | *yres = dssdev->panel.timings.y_res; | ||
| 624 | } | ||
| 625 | |||
| 626 | static void update_done(void *data) | ||
| 627 | { | ||
| 628 | rfbi_bus_unlock(); | ||
| 629 | } | ||
| 630 | |||
| 631 | static int n8x0_panel_update(struct omap_dss_device *dssdev, | ||
| 632 | u16 x, u16 y, u16 w, u16 h) | ||
| 633 | { | ||
| 634 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 635 | |||
| 636 | dev_dbg(&dssdev->dev, "update\n"); | ||
| 637 | |||
| 638 | mutex_lock(&ddata->lock); | ||
| 639 | rfbi_bus_lock(); | ||
| 640 | |||
| 641 | omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h); | ||
| 642 | |||
| 643 | blizzard_ctrl_setup_update(dssdev, x, y, w, h); | ||
| 644 | |||
| 645 | omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL); | ||
| 646 | |||
| 647 | mutex_unlock(&ddata->lock); | ||
| 648 | |||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 652 | static int n8x0_panel_sync(struct omap_dss_device *dssdev) | ||
| 653 | { | ||
| 654 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
| 655 | |||
| 656 | dev_dbg(&dssdev->dev, "sync\n"); | ||
| 657 | |||
| 658 | mutex_lock(&ddata->lock); | ||
| 659 | rfbi_bus_lock(); | ||
| 660 | rfbi_bus_unlock(); | ||
| 661 | mutex_unlock(&ddata->lock); | ||
| 662 | |||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | static struct omap_dss_driver n8x0_panel_driver = { | ||
| 667 | .probe = n8x0_panel_probe, | ||
| 668 | .remove = n8x0_panel_remove, | ||
| 669 | |||
| 670 | .enable = n8x0_panel_enable, | ||
| 671 | .disable = n8x0_panel_disable, | ||
| 672 | .suspend = n8x0_panel_suspend, | ||
| 673 | .resume = n8x0_panel_resume, | ||
| 674 | |||
| 675 | .update = n8x0_panel_update, | ||
| 676 | .sync = n8x0_panel_sync, | ||
| 677 | |||
| 678 | .get_resolution = n8x0_panel_get_resolution, | ||
| 679 | .get_recommended_bpp = omapdss_default_get_recommended_bpp, | ||
| 680 | |||
| 681 | .get_timings = n8x0_panel_get_timings, | ||
| 682 | |||
| 683 | .driver = { | ||
| 684 | .name = "n8x0_panel", | ||
| 685 | .owner = THIS_MODULE, | ||
| 686 | }, | ||
| 687 | }; | ||
| 688 | |||
| 689 | /* PANEL */ | ||
| 690 | |||
| 691 | static int mipid_spi_probe(struct spi_device *spi) | ||
| 692 | { | ||
| 693 | dev_dbg(&spi->dev, "mipid_spi_probe\n"); | ||
| 694 | |||
| 695 | spi->mode = SPI_MODE_0; | ||
| 696 | |||
| 697 | s_drv_data.spidev = spi; | ||
| 698 | |||
| 699 | return 0; | ||
| 700 | } | ||
| 701 | |||
| 702 | static int mipid_spi_remove(struct spi_device *spi) | ||
| 703 | { | ||
| 704 | dev_dbg(&spi->dev, "mipid_spi_remove\n"); | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | |||
| 708 | static struct spi_driver mipid_spi_driver = { | ||
| 709 | .driver = { | ||
| 710 | .name = "lcd_mipid", | ||
| 711 | .bus = &spi_bus_type, | ||
| 712 | .owner = THIS_MODULE, | ||
| 713 | }, | ||
| 714 | .probe = mipid_spi_probe, | ||
| 715 | .remove = __devexit_p(mipid_spi_remove), | ||
| 716 | }; | ||
| 717 | |||
| 718 | static int __init n8x0_panel_drv_init(void) | ||
| 719 | { | ||
| 720 | int r; | ||
| 721 | |||
| 722 | r = spi_register_driver(&mipid_spi_driver); | ||
| 723 | if (r) { | ||
| 724 | pr_err("n8x0_panel: spi driver registration failed\n"); | ||
| 725 | return r; | ||
| 726 | } | ||
| 727 | |||
| 728 | r = omap_dss_register_driver(&n8x0_panel_driver); | ||
| 729 | if (r) { | ||
| 730 | pr_err("n8x0_panel: dss driver registration failed\n"); | ||
| 731 | spi_unregister_driver(&mipid_spi_driver); | ||
| 732 | return r; | ||
| 733 | } | ||
| 734 | |||
| 735 | return 0; | ||
| 736 | } | ||
| 737 | |||
| 738 | static void __exit n8x0_panel_drv_exit(void) | ||
| 739 | { | ||
| 740 | spi_unregister_driver(&mipid_spi_driver); | ||
| 741 | |||
| 742 | omap_dss_unregister_driver(&n8x0_panel_driver); | ||
| 743 | } | ||
| 744 | |||
| 745 | module_init(n8x0_panel_drv_init); | ||
| 746 | module_exit(n8x0_panel_drv_exit); | ||
| 747 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c new file mode 100644 index 000000000000..98ebdaddab5a --- /dev/null +++ b/drivers/video/omap2/displays/panel-picodlp.c | |||
| @@ -0,0 +1,594 @@ | |||
| 1 | /* | ||
| 2 | * picodlp panel driver | ||
| 3 | * picodlp_i2c_driver: i2c_client driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2009-2011 Texas Instruments | ||
| 6 | * Author: Mythri P K <mythripk@ti.com> | ||
| 7 | * Mayuresh Janorkar <mayur@ti.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License version 2 as published by | ||
| 11 | * the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 16 | * more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along with | ||
| 19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/input.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/interrupt.h> | ||
| 26 | #include <linux/firmware.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/mutex.h> | ||
| 29 | #include <linux/i2c.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/gpio.h> | ||
| 32 | |||
| 33 | #include <video/omapdss.h> | ||
| 34 | #include <video/omap-panel-picodlp.h> | ||
| 35 | |||
| 36 | #include "panel-picodlp.h" | ||
| 37 | |||
| 38 | struct picodlp_data { | ||
| 39 | struct mutex lock; | ||
| 40 | struct i2c_client *picodlp_i2c_client; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static struct i2c_board_info picodlp_i2c_board_info = { | ||
| 44 | I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b), | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct picodlp_i2c_data { | ||
| 48 | struct mutex xfer_lock; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static struct i2c_device_id picodlp_i2c_id[] = { | ||
| 52 | { "picodlp_i2c_driver", 0 }, | ||
| 53 | }; | ||
| 54 | |||
| 55 | struct picodlp_i2c_command { | ||
| 56 | u8 reg; | ||
| 57 | u32 value; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static struct omap_video_timings pico_ls_timings = { | ||
| 61 | .x_res = 864, | ||
| 62 | .y_res = 480, | ||
| 63 | .hsw = 7, | ||
| 64 | .hfp = 11, | ||
| 65 | .hbp = 7, | ||
| 66 | |||
| 67 | .pixel_clock = 19200, | ||
| 68 | |||
| 69 | .vsw = 2, | ||
| 70 | .vfp = 3, | ||
| 71 | .vbp = 14, | ||
| 72 | }; | ||
| 73 | |||
| 74 | static inline struct picodlp_panel_data | ||
| 75 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
| 76 | { | ||
| 77 | return (struct picodlp_panel_data *) dssdev->data; | ||
| 78 | } | ||
| 79 | |||
| 80 | static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg) | ||
| 81 | { | ||
| 82 | u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4]; | ||
| 83 | struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); | ||
| 84 | struct i2c_msg msg[2]; | ||
| 85 | |||
| 86 | mutex_lock(&picodlp_i2c_data->xfer_lock); | ||
| 87 | |||
| 88 | msg[0].addr = client->addr; | ||
| 89 | msg[0].flags = 0; | ||
| 90 | msg[0].len = 2; | ||
| 91 | msg[0].buf = read_cmd; | ||
| 92 | |||
| 93 | msg[1].addr = client->addr; | ||
| 94 | msg[1].flags = I2C_M_RD; | ||
| 95 | msg[1].len = 4; | ||
| 96 | msg[1].buf = data; | ||
| 97 | |||
| 98 | i2c_transfer(client->adapter, msg, 2); | ||
| 99 | mutex_unlock(&picodlp_i2c_data->xfer_lock); | ||
| 100 | return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24)); | ||
| 101 | } | ||
| 102 | |||
| 103 | static int picodlp_i2c_write_block(struct i2c_client *client, | ||
| 104 | u8 *data, int len) | ||
| 105 | { | ||
| 106 | struct i2c_msg msg; | ||
| 107 | int i, r, msg_count = 1; | ||
| 108 | |||
| 109 | struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client); | ||
| 110 | |||
| 111 | if (len < 1 || len > 32) { | ||
| 112 | dev_err(&client->dev, | ||
| 113 | "too long syn_write_block len %d\n", len); | ||
| 114 | return -EIO; | ||
| 115 | } | ||
| 116 | mutex_lock(&picodlp_i2c_data->xfer_lock); | ||
| 117 | |||
| 118 | msg.addr = client->addr; | ||
| 119 | msg.flags = 0; | ||
| 120 | msg.len = len; | ||
| 121 | msg.buf = data; | ||
| 122 | r = i2c_transfer(client->adapter, &msg, msg_count); | ||
| 123 | mutex_unlock(&picodlp_i2c_data->xfer_lock); | ||
| 124 | |||
| 125 | /* | ||
| 126 | * i2c_transfer returns: | ||
| 127 | * number of messages sent in case of success | ||
| 128 | * a negative error number in case of failure | ||
| 129 | */ | ||
| 130 | if (r != msg_count) | ||
| 131 | goto err; | ||
| 132 | |||
| 133 | /* In case of success */ | ||
| 134 | for (i = 0; i < len; i++) | ||
| 135 | dev_dbg(&client->dev, | ||
| 136 | "addr %x bw 0x%02x[%d]: 0x%02x\n", | ||
| 137 | client->addr, data[0] + i, i, data[i]); | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | err: | ||
| 141 | dev_err(&client->dev, "picodlp_i2c_write error\n"); | ||
| 142 | return r; | ||
| 143 | } | ||
| 144 | |||
| 145 | static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value) | ||
| 146 | { | ||
| 147 | u8 data[5]; | ||
| 148 | int i; | ||
| 149 | |||
| 150 | data[0] = reg; | ||
| 151 | for (i = 1; i < 5; i++) | ||
| 152 | data[i] = (value >> (32 - (i) * 8)) & 0xFF; | ||
| 153 | |||
| 154 | return picodlp_i2c_write_block(client, data, 5); | ||
| 155 | } | ||
| 156 | |||
| 157 | static int picodlp_i2c_write_array(struct i2c_client *client, | ||
| 158 | const struct picodlp_i2c_command commands[], | ||
| 159 | int count) | ||
| 160 | { | ||
| 161 | int i, r = 0; | ||
| 162 | for (i = 0; i < count; i++) { | ||
| 163 | r = picodlp_i2c_write(client, commands[i].reg, | ||
| 164 | commands[i].value); | ||
| 165 | if (r) | ||
| 166 | return r; | ||
| 167 | } | ||
| 168 | return r; | ||
| 169 | } | ||
| 170 | |||
| 171 | static int picodlp_wait_for_dma_done(struct i2c_client *client) | ||
| 172 | { | ||
| 173 | u8 trial = 100; | ||
| 174 | |||
| 175 | do { | ||
| 176 | msleep(1); | ||
| 177 | if (!trial--) | ||
| 178 | return -ETIMEDOUT; | ||
| 179 | } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS); | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * picodlp_i2c_init: i2c_initialization routine | ||
| 186 | * client: i2c_client for communication | ||
| 187 | * | ||
| 188 | * return | ||
| 189 | * 0 : Success, no error | ||
| 190 | * error code : Failure | ||
| 191 | */ | ||
| 192 | static int picodlp_i2c_init(struct i2c_client *client) | ||
| 193 | { | ||
| 194 | int r; | ||
| 195 | static const struct picodlp_i2c_command init_cmd_set1[] = { | ||
| 196 | {SOFT_RESET, 1}, | ||
| 197 | {DMD_PARK_TRIGGER, 1}, | ||
| 198 | {MISC_REG, 5}, | ||
| 199 | {SEQ_CONTROL, 0}, | ||
| 200 | {SEQ_VECTOR, 0x100}, | ||
| 201 | {DMD_BLOCK_COUNT, 7}, | ||
| 202 | {DMD_VCC_CONTROL, 0x109}, | ||
| 203 | {DMD_PARK_PULSE_COUNT, 0xA}, | ||
| 204 | {DMD_PARK_PULSE_WIDTH, 0xB}, | ||
| 205 | {DMD_PARK_DELAY, 0x2ED}, | ||
| 206 | {DMD_SHADOW_ENABLE, 0}, | ||
| 207 | {FLASH_OPCODE, 0xB}, | ||
| 208 | {FLASH_DUMMY_BYTES, 1}, | ||
| 209 | {FLASH_ADDR_BYTES, 3}, | ||
| 210 | {PBC_CONTROL, 0}, | ||
| 211 | {FLASH_START_ADDR, CMT_LUT_0_START_ADDR}, | ||
| 212 | {FLASH_READ_BYTES, CMT_LUT_0_SIZE}, | ||
| 213 | {CMT_SPLASH_LUT_START_ADDR, 0}, | ||
| 214 | {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL}, | ||
| 215 | {PBC_CONTROL, 1}, | ||
| 216 | }; | ||
| 217 | |||
| 218 | static const struct picodlp_i2c_command init_cmd_set2[] = { | ||
| 219 | {PBC_CONTROL, 0}, | ||
| 220 | {CMT_SPLASH_LUT_DEST_SELECT, 0}, | ||
| 221 | {PBC_CONTROL, 0}, | ||
| 222 | {FLASH_START_ADDR, SEQUENCE_0_START_ADDR}, | ||
| 223 | {FLASH_READ_BYTES, SEQUENCE_0_SIZE}, | ||
| 224 | {SEQ_RESET_LUT_START_ADDR, 0}, | ||
| 225 | {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT}, | ||
| 226 | {PBC_CONTROL, 1}, | ||
| 227 | }; | ||
| 228 | |||
| 229 | static const struct picodlp_i2c_command init_cmd_set3[] = { | ||
| 230 | {PBC_CONTROL, 0}, | ||
| 231 | {SEQ_RESET_LUT_DEST_SELECT, 0}, | ||
| 232 | {PBC_CONTROL, 0}, | ||
| 233 | {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR}, | ||
| 234 | {FLASH_READ_BYTES, DRC_TABLE_0_SIZE}, | ||
| 235 | {SEQ_RESET_LUT_START_ADDR, 0}, | ||
| 236 | {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL}, | ||
| 237 | {PBC_CONTROL, 1}, | ||
| 238 | }; | ||
| 239 | |||
| 240 | static const struct picodlp_i2c_command init_cmd_set4[] = { | ||
| 241 | {PBC_CONTROL, 0}, | ||
| 242 | {SEQ_RESET_LUT_DEST_SELECT, 0}, | ||
| 243 | {SDC_ENABLE, 1}, | ||
| 244 | {AGC_CTRL, 7}, | ||
| 245 | {CCA_C1A, 0x100}, | ||
| 246 | {CCA_C1B, 0x0}, | ||
| 247 | {CCA_C1C, 0x0}, | ||
| 248 | {CCA_C2A, 0x0}, | ||
| 249 | {CCA_C2B, 0x100}, | ||
| 250 | {CCA_C2C, 0x0}, | ||
| 251 | {CCA_C3A, 0x0}, | ||
| 252 | {CCA_C3B, 0x0}, | ||
| 253 | {CCA_C3C, 0x100}, | ||
| 254 | {CCA_C7A, 0x100}, | ||
| 255 | {CCA_C7B, 0x100}, | ||
| 256 | {CCA_C7C, 0x100}, | ||
| 257 | {CCA_ENABLE, 1}, | ||
| 258 | {CPU_IF_MODE, 1}, | ||
| 259 | {SHORT_FLIP, 1}, | ||
| 260 | {CURTAIN_CONTROL, 0}, | ||
| 261 | {DMD_PARK_TRIGGER, 0}, | ||
| 262 | {R_DRIVE_CURRENT, 0x298}, | ||
| 263 | {G_DRIVE_CURRENT, 0x298}, | ||
| 264 | {B_DRIVE_CURRENT, 0x298}, | ||
| 265 | {RGB_DRIVER_ENABLE, 7}, | ||
| 266 | {SEQ_CONTROL, 0}, | ||
| 267 | {ACTGEN_CONTROL, 0x10}, | ||
| 268 | {SEQUENCE_MODE, SEQ_LOCK}, | ||
| 269 | {DATA_FORMAT, RGB888}, | ||
| 270 | {INPUT_RESOLUTION, WVGA_864_LANDSCAPE}, | ||
| 271 | {INPUT_SOURCE, PARALLEL_RGB}, | ||
| 272 | {CPU_IF_SYNC_METHOD, 1}, | ||
| 273 | {SEQ_CONTROL, 1} | ||
| 274 | }; | ||
| 275 | |||
| 276 | r = picodlp_i2c_write_array(client, init_cmd_set1, | ||
| 277 | ARRAY_SIZE(init_cmd_set1)); | ||
| 278 | if (r) | ||
| 279 | return r; | ||
| 280 | |||
| 281 | r = picodlp_wait_for_dma_done(client); | ||
| 282 | if (r) | ||
| 283 | return r; | ||
| 284 | |||
| 285 | r = picodlp_i2c_write_array(client, init_cmd_set2, | ||
| 286 | ARRAY_SIZE(init_cmd_set2)); | ||
| 287 | if (r) | ||
| 288 | return r; | ||
| 289 | |||
| 290 | r = picodlp_wait_for_dma_done(client); | ||
| 291 | if (r) | ||
| 292 | return r; | ||
| 293 | |||
| 294 | r = picodlp_i2c_write_array(client, init_cmd_set3, | ||
| 295 | ARRAY_SIZE(init_cmd_set3)); | ||
| 296 | if (r) | ||
| 297 | return r; | ||
| 298 | |||
| 299 | r = picodlp_wait_for_dma_done(client); | ||
| 300 | if (r) | ||
| 301 | return r; | ||
| 302 | |||
| 303 | r = picodlp_i2c_write_array(client, init_cmd_set4, | ||
| 304 | ARRAY_SIZE(init_cmd_set4)); | ||
| 305 | if (r) | ||
| 306 | return r; | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int picodlp_i2c_probe(struct i2c_client *client, | ||
| 312 | const struct i2c_device_id *id) | ||
| 313 | { | ||
| 314 | struct picodlp_i2c_data *picodlp_i2c_data; | ||
| 315 | |||
| 316 | picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL); | ||
| 317 | |||
| 318 | if (!picodlp_i2c_data) | ||
| 319 | return -ENOMEM; | ||
| 320 | |||
| 321 | mutex_init(&picodlp_i2c_data->xfer_lock); | ||
| 322 | i2c_set_clientdata(client, picodlp_i2c_data); | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int picodlp_i2c_remove(struct i2c_client *client) | ||
| 328 | { | ||
| 329 | struct picodlp_i2c_data *picodlp_i2c_data = | ||
| 330 | i2c_get_clientdata(client); | ||
| 331 | kfree(picodlp_i2c_data); | ||
| 332 | return 0; | ||
| 333 | } | ||
| 334 | |||
| 335 | static struct i2c_driver picodlp_i2c_driver = { | ||
| 336 | .driver = { | ||
| 337 | .name = "picodlp_i2c_driver", | ||
| 338 | }, | ||
| 339 | .probe = picodlp_i2c_probe, | ||
| 340 | .remove = picodlp_i2c_remove, | ||
| 341 | .id_table = picodlp_i2c_id, | ||
| 342 | }; | ||
| 343 | |||
| 344 | static int picodlp_panel_power_on(struct omap_dss_device *dssdev) | ||
| 345 | { | ||
| 346 | int r, trial = 100; | ||
| 347 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
| 348 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | ||
| 349 | |||
| 350 | if (dssdev->platform_enable) { | ||
| 351 | r = dssdev->platform_enable(dssdev); | ||
| 352 | if (r) | ||
| 353 | return r; | ||
| 354 | } | ||
| 355 | |||
| 356 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); | ||
| 357 | msleep(1); | ||
| 358 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); | ||
| 359 | |||
| 360 | while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) { | ||
| 361 | if (!trial--) { | ||
| 362 | dev_err(&dssdev->dev, "emu_done signal not" | ||
| 363 | " going high\n"); | ||
| 364 | return -ETIMEDOUT; | ||
| 365 | } | ||
| 366 | msleep(5); | ||
| 367 | } | ||
| 368 | /* | ||
| 369 | * As per dpp2600 programming guide, | ||
| 370 | * it is required to sleep for 1000ms after emu_done signal goes high | ||
| 371 | * then only i2c commands can be successfully sent to dpp2600 | ||
| 372 | */ | ||
| 373 | msleep(1000); | ||
| 374 | r = omapdss_dpi_display_enable(dssdev); | ||
| 375 | if (r) { | ||
| 376 | dev_err(&dssdev->dev, "failed to enable DPI\n"); | ||
| 377 | goto err1; | ||
| 378 | } | ||
| 379 | |||
| 380 | r = picodlp_i2c_init(picod->picodlp_i2c_client); | ||
| 381 | if (r) | ||
| 382 | goto err; | ||
| 383 | |||
| 384 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
| 385 | |||
| 386 | return r; | ||
| 387 | err: | ||
| 388 | omapdss_dpi_display_disable(dssdev); | ||
| 389 | err1: | ||
| 390 | if (dssdev->platform_disable) | ||
| 391 | dssdev->platform_disable(dssdev); | ||
| 392 | |||
| 393 | return r; | ||
| 394 | } | ||
| 395 | |||
| 396 | static void picodlp_panel_power_off(struct omap_dss_device *dssdev) | ||
| 397 | { | ||
| 398 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | ||
| 399 | |||
| 400 | omapdss_dpi_display_disable(dssdev); | ||
| 401 | |||
| 402 | gpio_set_value(picodlp_pdata->emu_done_gpio, 0); | ||
| 403 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); | ||
| 404 | |||
| 405 | if (dssdev->platform_disable) | ||
| 406 | dssdev->platform_disable(dssdev); | ||
| 407 | } | ||
| 408 | |||
| 409 | static int picodlp_panel_probe(struct omap_dss_device *dssdev) | ||
| 410 | { | ||
| 411 | struct picodlp_data *picod; | ||
| 412 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | ||
| 413 | struct i2c_adapter *adapter; | ||
| 414 | struct i2c_client *picodlp_i2c_client; | ||
| 415 | int r = 0, picodlp_adapter_id; | ||
| 416 | |||
| 417 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_ONOFF | | ||
| 418 | OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IVS; | ||
| 419 | dssdev->panel.acb = 0x0; | ||
| 420 | dssdev->panel.timings = pico_ls_timings; | ||
| 421 | |||
| 422 | picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL); | ||
| 423 | if (!picod) | ||
| 424 | return -ENOMEM; | ||
| 425 | |||
| 426 | mutex_init(&picod->lock); | ||
| 427 | |||
| 428 | picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id; | ||
| 429 | |||
| 430 | adapter = i2c_get_adapter(picodlp_adapter_id); | ||
| 431 | if (!adapter) { | ||
| 432 | dev_err(&dssdev->dev, "can't get i2c adapter\n"); | ||
| 433 | r = -ENODEV; | ||
| 434 | goto err; | ||
| 435 | } | ||
| 436 | |||
| 437 | picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); | ||
| 438 | if (!picodlp_i2c_client) { | ||
| 439 | dev_err(&dssdev->dev, "can't add i2c device::" | ||
| 440 | " picodlp_i2c_client is NULL\n"); | ||
| 441 | r = -ENODEV; | ||
| 442 | goto err; | ||
| 443 | } | ||
| 444 | |||
| 445 | picod->picodlp_i2c_client = picodlp_i2c_client; | ||
| 446 | |||
| 447 | dev_set_drvdata(&dssdev->dev, picod); | ||
| 448 | return r; | ||
| 449 | err: | ||
| 450 | kfree(picod); | ||
| 451 | return r; | ||
| 452 | } | ||
| 453 | |||
| 454 | static void picodlp_panel_remove(struct omap_dss_device *dssdev) | ||
| 455 | { | ||
| 456 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
| 457 | |||
| 458 | i2c_unregister_device(picod->picodlp_i2c_client); | ||
| 459 | dev_set_drvdata(&dssdev->dev, NULL); | ||
| 460 | dev_dbg(&dssdev->dev, "removing picodlp panel\n"); | ||
| 461 | |||
| 462 | kfree(picod); | ||
| 463 | } | ||
| 464 | |||
| 465 | static int picodlp_panel_enable(struct omap_dss_device *dssdev) | ||
| 466 | { | ||
| 467 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
| 468 | int r; | ||
| 469 | |||
| 470 | dev_dbg(&dssdev->dev, "enabling picodlp panel\n"); | ||
| 471 | |||
| 472 | mutex_lock(&picod->lock); | ||
| 473 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
| 474 | mutex_unlock(&picod->lock); | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | |||
| 478 | r = picodlp_panel_power_on(dssdev); | ||
| 479 | mutex_unlock(&picod->lock); | ||
| 480 | |||
| 481 | return r; | ||
| 482 | } | ||
| 483 | |||
| 484 | static void picodlp_panel_disable(struct omap_dss_device *dssdev) | ||
| 485 | { | ||
| 486 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
| 487 | |||
| 488 | mutex_lock(&picod->lock); | ||
| 489 | /* Turn off DLP Power */ | ||
| 490 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
| 491 | picodlp_panel_power_off(dssdev); | ||
| 492 | |||
| 493 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
| 494 | mutex_unlock(&picod->lock); | ||
| 495 | |||
| 496 | dev_dbg(&dssdev->dev, "disabling picodlp panel\n"); | ||
| 497 | } | ||
| 498 | |||
| 499 | static int picodlp_panel_suspend(struct omap_dss_device *dssdev) | ||
| 500 | { | ||
| 501 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
| 502 | |||
| 503 | mutex_lock(&picod->lock); | ||
| 504 | /* Turn off DLP Power */ | ||
| 505 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
| 506 | mutex_unlock(&picod->lock); | ||
| 507 | dev_err(&dssdev->dev, "unable to suspend picodlp panel," | ||
| 508 | " panel is not ACTIVE\n"); | ||
| 509 | return -EINVAL; | ||
| 510 | } | ||
| 511 | |||
| 512 | picodlp_panel_power_off(dssdev); | ||
| 513 | |||
| 514 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
| 515 | mutex_unlock(&picod->lock); | ||
| 516 | |||
| 517 | dev_dbg(&dssdev->dev, "suspending picodlp panel\n"); | ||
| 518 | return 0; | ||
| 519 | } | ||
| 520 | |||
| 521 | static int picodlp_panel_resume(struct omap_dss_device *dssdev) | ||
| 522 | { | ||
| 523 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | ||
| 524 | int r; | ||
| 525 | |||
| 526 | mutex_lock(&picod->lock); | ||
| 527 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | ||
| 528 | mutex_unlock(&picod->lock); | ||
| 529 | dev_err(&dssdev->dev, "unable to resume picodlp panel," | ||
| 530 | " panel is not ACTIVE\n"); | ||
| 531 | return -EINVAL; | ||
| 532 | } | ||
| 533 | |||
| 534 | r = picodlp_panel_power_on(dssdev); | ||
| 535 | mutex_unlock(&picod->lock); | ||
| 536 | dev_dbg(&dssdev->dev, "resuming picodlp panel\n"); | ||
| 537 | return r; | ||
| 538 | } | ||
| 539 | |||
| 540 | static void picodlp_get_resolution(struct omap_dss_device *dssdev, | ||
| 541 | u16 *xres, u16 *yres) | ||
| 542 | { | ||
| 543 | *xres = dssdev->panel.timings.x_res; | ||
| 544 | *yres = dssdev->panel.timings.y_res; | ||
| 545 | } | ||
| 546 | |||
| 547 | static struct omap_dss_driver picodlp_driver = { | ||
| 548 | .probe = picodlp_panel_probe, | ||
| 549 | .remove = picodlp_panel_remove, | ||
| 550 | |||
| 551 | .enable = picodlp_panel_enable, | ||
| 552 | .disable = picodlp_panel_disable, | ||
| 553 | |||
| 554 | .get_resolution = picodlp_get_resolution, | ||
| 555 | |||
| 556 | .suspend = picodlp_panel_suspend, | ||
| 557 | .resume = picodlp_panel_resume, | ||
| 558 | |||
| 559 | .driver = { | ||
| 560 | .name = "picodlp_panel", | ||
| 561 | .owner = THIS_MODULE, | ||
| 562 | }, | ||
| 563 | }; | ||
| 564 | |||
| 565 | static int __init picodlp_init(void) | ||
| 566 | { | ||
| 567 | int r = 0; | ||
| 568 | |||
| 569 | r = i2c_add_driver(&picodlp_i2c_driver); | ||
| 570 | if (r) { | ||
| 571 | printk(KERN_WARNING "picodlp_i2c_driver" \ | ||
| 572 | " registration failed\n"); | ||
| 573 | return r; | ||
| 574 | } | ||
| 575 | |||
| 576 | r = omap_dss_register_driver(&picodlp_driver); | ||
| 577 | if (r) | ||
| 578 | i2c_del_driver(&picodlp_i2c_driver); | ||
| 579 | |||
| 580 | return r; | ||
| 581 | } | ||
| 582 | |||
| 583 | static void __exit picodlp_exit(void) | ||
| 584 | { | ||
| 585 | i2c_del_driver(&picodlp_i2c_driver); | ||
| 586 | omap_dss_unregister_driver(&picodlp_driver); | ||
| 587 | } | ||
| 588 | |||
| 589 | module_init(picodlp_init); | ||
| 590 | module_exit(picodlp_exit); | ||
| 591 | |||
| 592 | MODULE_AUTHOR("Mythri P K <mythripk@ti.com>"); | ||
| 593 | MODULE_DESCRIPTION("picodlp driver"); | ||
| 594 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h new file mode 100644 index 000000000000..a34b431a7267 --- /dev/null +++ b/drivers/video/omap2/displays/panel-picodlp.h | |||
| @@ -0,0 +1,288 @@ | |||
| 1 | /* | ||
| 2 | * Header file required by picodlp panel driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009-2011 Texas Instruments | ||
| 5 | * Author: Mythri P K <mythripk@ti.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License version 2 as published by | ||
| 9 | * the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 14 | * more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License along with | ||
| 17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H | ||
| 21 | #define __OMAP2_DISPLAY_PANEL_PICODLP_H | ||
| 22 | |||
| 23 | /* Commands used for configuring picodlp panel */ | ||
| 24 | |||
| 25 | #define MAIN_STATUS 0x03 | ||
| 26 | #define PBC_CONTROL 0x08 | ||
| 27 | #define INPUT_SOURCE 0x0B | ||
| 28 | #define INPUT_RESOLUTION 0x0C | ||
| 29 | #define DATA_FORMAT 0x0D | ||
| 30 | #define IMG_ROTATION 0x0E | ||
| 31 | #define LONG_FLIP 0x0F | ||
| 32 | #define SHORT_FLIP 0x10 | ||
| 33 | #define TEST_PAT_SELECT 0x11 | ||
| 34 | #define R_DRIVE_CURRENT 0x12 | ||
| 35 | #define G_DRIVE_CURRENT 0x13 | ||
| 36 | #define B_DRIVE_CURRENT 0x14 | ||
| 37 | #define READ_REG_SELECT 0x15 | ||
| 38 | #define RGB_DRIVER_ENABLE 0x16 | ||
| 39 | |||
| 40 | #define CPU_IF_MODE 0x18 | ||
| 41 | #define FRAME_RATE 0x19 | ||
| 42 | #define CPU_IF_SYNC_METHOD 0x1A | ||
| 43 | #define CPU_IF_SOF 0x1B | ||
| 44 | #define CPU_IF_EOF 0x1C | ||
| 45 | #define CPU_IF_SLEEP 0x1D | ||
| 46 | |||
| 47 | #define SEQUENCE_MODE 0x1E | ||
| 48 | #define SOFT_RESET 0x1F | ||
| 49 | #define FRONT_END_RESET 0x21 | ||
| 50 | #define AUTO_PWR_ENABLE 0x22 | ||
| 51 | |||
| 52 | #define VSYNC_LINE_DELAY 0x23 | ||
| 53 | #define CPU_PI_HORIZ_START 0x24 | ||
| 54 | #define CPU_PI_VERT_START 0x25 | ||
| 55 | #define CPU_PI_HORIZ_WIDTH 0x26 | ||
| 56 | #define CPU_PI_VERT_HEIGHT 0x27 | ||
| 57 | |||
| 58 | #define PIXEL_MASK_CROP 0x28 | ||
| 59 | #define CROP_FIRST_LINE 0x29 | ||
| 60 | #define CROP_LAST_LINE 0x2A | ||
| 61 | #define CROP_FIRST_PIXEL 0x2B | ||
| 62 | #define CROP_LAST_PIXEL 0x2C | ||
| 63 | #define DMD_PARK_TRIGGER 0x2D | ||
| 64 | |||
| 65 | #define MISC_REG 0x30 | ||
| 66 | |||
| 67 | /* AGC registers */ | ||
| 68 | #define AGC_CTRL 0x50 | ||
| 69 | #define AGC_CLIPPED_PIXS 0x55 | ||
| 70 | #define AGC_BRIGHT_PIXS 0x56 | ||
| 71 | #define AGC_BG_PIXS 0x57 | ||
| 72 | #define AGC_SAFETY_MARGIN 0x17 | ||
| 73 | |||
| 74 | /* Color Coordinate Adjustment registers */ | ||
| 75 | #define CCA_ENABLE 0x5E | ||
| 76 | #define CCA_C1A 0x5F | ||
| 77 | #define CCA_C1B 0x60 | ||
| 78 | #define CCA_C1C 0x61 | ||
| 79 | #define CCA_C2A 0x62 | ||
| 80 | #define CCA_C2B 0x63 | ||
| 81 | #define CCA_C2C 0x64 | ||
| 82 | #define CCA_C3A 0x65 | ||
| 83 | #define CCA_C3B 0x66 | ||
| 84 | #define CCA_C3C 0x67 | ||
| 85 | #define CCA_C7A 0x71 | ||
| 86 | #define CCA_C7B 0x72 | ||
| 87 | #define CCA_C7C 0x73 | ||
| 88 | |||
| 89 | /** | ||
| 90 | * DLP Pico Processor 2600 comes with flash | ||
| 91 | * We can do DMA operations from flash for accessing Look Up Tables | ||
| 92 | */ | ||
| 93 | #define DMA_STATUS 0x100 | ||
| 94 | #define FLASH_ADDR_BYTES 0x74 | ||
| 95 | #define FLASH_DUMMY_BYTES 0x75 | ||
| 96 | #define FLASH_WRITE_BYTES 0x76 | ||
| 97 | #define FLASH_READ_BYTES 0x77 | ||
| 98 | #define FLASH_OPCODE 0x78 | ||
| 99 | #define FLASH_START_ADDR 0x79 | ||
| 100 | #define FLASH_DUMMY2 0x7A | ||
| 101 | #define FLASH_WRITE_DATA 0x7B | ||
| 102 | |||
| 103 | #define TEMPORAL_DITH_DISABLE 0x7E | ||
| 104 | #define SEQ_CONTROL 0x82 | ||
| 105 | #define SEQ_VECTOR 0x83 | ||
| 106 | |||
| 107 | /* DMD is Digital Micromirror Device */ | ||
| 108 | #define DMD_BLOCK_COUNT 0x84 | ||
| 109 | #define DMD_VCC_CONTROL 0x86 | ||
| 110 | #define DMD_PARK_PULSE_COUNT 0x87 | ||
| 111 | #define DMD_PARK_PULSE_WIDTH 0x88 | ||
| 112 | #define DMD_PARK_DELAY 0x89 | ||
| 113 | #define DMD_SHADOW_ENABLE 0x8E | ||
| 114 | #define SEQ_STATUS 0x8F | ||
| 115 | #define FLASH_CLOCK_CONTROL 0x98 | ||
| 116 | #define DMD_PARK 0x2D | ||
| 117 | |||
| 118 | #define SDRAM_BIST_ENABLE 0x46 | ||
| 119 | #define DDR_DRIVER_STRENGTH 0x9A | ||
| 120 | #define SDC_ENABLE 0x9D | ||
| 121 | #define SDC_BUFF_SWAP_DISABLE 0xA3 | ||
| 122 | #define CURTAIN_CONTROL 0xA6 | ||
| 123 | #define DDR_BUS_SWAP_ENABLE 0xA7 | ||
| 124 | #define DMD_TRC_ENABLE 0xA8 | ||
| 125 | #define DMD_BUS_SWAP_ENABLE 0xA9 | ||
| 126 | |||
| 127 | #define ACTGEN_ENABLE 0xAE | ||
| 128 | #define ACTGEN_CONTROL 0xAF | ||
| 129 | #define ACTGEN_HORIZ_BP 0xB0 | ||
| 130 | #define ACTGEN_VERT_BP 0xB1 | ||
| 131 | |||
| 132 | /* Look Up Table access */ | ||
| 133 | #define CMT_SPLASH_LUT_START_ADDR 0xFA | ||
| 134 | #define CMT_SPLASH_LUT_DEST_SELECT 0xFB | ||
| 135 | #define CMT_SPLASH_LUT_DATA 0xFC | ||
| 136 | #define SEQ_RESET_LUT_START_ADDR 0xFD | ||
| 137 | #define SEQ_RESET_LUT_DEST_SELECT 0xFE | ||
| 138 | #define SEQ_RESET_LUT_DATA 0xFF | ||
| 139 | |||
| 140 | /* Input source definitions */ | ||
| 141 | #define PARALLEL_RGB 0 | ||
| 142 | #define INT_TEST_PATTERN 1 | ||
| 143 | #define SPLASH_SCREEN 2 | ||
| 144 | #define CPU_INTF 3 | ||
| 145 | #define BT656 4 | ||
| 146 | |||
| 147 | /* Standard input resolution definitions */ | ||
| 148 | #define QWVGA_LANDSCAPE 3 /* (427h*240v) */ | ||
| 149 | #define WVGA_864_LANDSCAPE 21 /* (864h*480v) */ | ||
| 150 | #define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */ | ||
| 151 | |||
| 152 | /* Standard data format definitions */ | ||
| 153 | #define RGB565 0 | ||
| 154 | #define RGB666 1 | ||
| 155 | #define RGB888 2 | ||
| 156 | |||
| 157 | /* Test Pattern definitions */ | ||
| 158 | #define TPG_CHECKERBOARD 0 | ||
| 159 | #define TPG_BLACK 1 | ||
| 160 | #define TPG_WHITE 2 | ||
| 161 | #define TPG_RED 3 | ||
| 162 | #define TPG_BLUE 4 | ||
| 163 | #define TPG_GREEN 5 | ||
| 164 | #define TPG_VLINES_BLACK 6 | ||
| 165 | #define TPG_HLINES_BLACK 7 | ||
| 166 | #define TPG_VLINES_ALT 8 | ||
| 167 | #define TPG_HLINES_ALT 9 | ||
| 168 | #define TPG_DIAG_LINES 10 | ||
| 169 | #define TPG_GREYRAMP_VERT 11 | ||
| 170 | #define TPG_GREYRAMP_HORIZ 12 | ||
| 171 | #define TPG_ANSI_CHECKERBOARD 13 | ||
| 172 | |||
| 173 | /* sequence mode definitions */ | ||
| 174 | #define SEQ_FREE_RUN 0 | ||
| 175 | #define SEQ_LOCK 1 | ||
| 176 | |||
| 177 | /* curtain color definitions */ | ||
| 178 | #define CURTAIN_BLACK 0 | ||
| 179 | #define CURTAIN_RED 1 | ||
| 180 | #define CURTAIN_GREEN 2 | ||
| 181 | #define CURTAIN_BLUE 3 | ||
| 182 | #define CURTAIN_YELLOW 4 | ||
| 183 | #define CURTAIN_MAGENTA 5 | ||
| 184 | #define CURTAIN_CYAN 6 | ||
| 185 | #define CURTAIN_WHITE 7 | ||
| 186 | |||
| 187 | /* LUT definitions */ | ||
| 188 | #define CMT_LUT_NONE 0 | ||
| 189 | #define CMT_LUT_GREEN 1 | ||
| 190 | #define CMT_LUT_RED 2 | ||
| 191 | #define CMT_LUT_BLUE 3 | ||
| 192 | #define CMT_LUT_ALL 4 | ||
| 193 | #define SPLASH_LUT 5 | ||
| 194 | |||
| 195 | #define SEQ_LUT_NONE 0 | ||
| 196 | #define SEQ_DRC_LUT_0 1 | ||
| 197 | #define SEQ_DRC_LUT_1 2 | ||
| 198 | #define SEQ_DRC_LUT_2 3 | ||
| 199 | #define SEQ_DRC_LUT_3 4 | ||
| 200 | #define SEQ_SEQ_LUT 5 | ||
| 201 | #define SEQ_DRC_LUT_ALL 6 | ||
| 202 | #define WPC_PROGRAM_LUT 7 | ||
| 203 | |||
| 204 | #define BITSTREAM_START_ADDR 0x00000000 | ||
| 205 | #define BITSTREAM_SIZE 0x00040000 | ||
| 206 | |||
| 207 | #define WPC_FW_0_START_ADDR 0x00040000 | ||
| 208 | #define WPC_FW_0_SIZE 0x00000ce8 | ||
| 209 | |||
| 210 | #define SEQUENCE_0_START_ADDR 0x00044000 | ||
| 211 | #define SEQUENCE_0_SIZE 0x00001000 | ||
| 212 | |||
| 213 | #define SEQUENCE_1_START_ADDR 0x00045000 | ||
| 214 | #define SEQUENCE_1_SIZE 0x00000d10 | ||
| 215 | |||
| 216 | #define SEQUENCE_2_START_ADDR 0x00046000 | ||
| 217 | #define SEQUENCE_2_SIZE 0x00000d10 | ||
| 218 | |||
| 219 | #define SEQUENCE_3_START_ADDR 0x00047000 | ||
| 220 | #define SEQUENCE_3_SIZE 0x00000d10 | ||
| 221 | |||
| 222 | #define SEQUENCE_4_START_ADDR 0x00048000 | ||
| 223 | #define SEQUENCE_4_SIZE 0x00000d10 | ||
| 224 | |||
| 225 | #define SEQUENCE_5_START_ADDR 0x00049000 | ||
| 226 | #define SEQUENCE_5_SIZE 0x00000d10 | ||
| 227 | |||
| 228 | #define SEQUENCE_6_START_ADDR 0x0004a000 | ||
| 229 | #define SEQUENCE_6_SIZE 0x00000d10 | ||
| 230 | |||
| 231 | #define CMT_LUT_0_START_ADDR 0x0004b200 | ||
| 232 | #define CMT_LUT_0_SIZE 0x00000600 | ||
| 233 | |||
| 234 | #define CMT_LUT_1_START_ADDR 0x0004b800 | ||
| 235 | #define CMT_LUT_1_SIZE 0x00000600 | ||
| 236 | |||
| 237 | #define CMT_LUT_2_START_ADDR 0x0004be00 | ||
| 238 | #define CMT_LUT_2_SIZE 0x00000600 | ||
| 239 | |||
| 240 | #define CMT_LUT_3_START_ADDR 0x0004c400 | ||
| 241 | #define CMT_LUT_3_SIZE 0x00000600 | ||
| 242 | |||
| 243 | #define CMT_LUT_4_START_ADDR 0x0004ca00 | ||
| 244 | #define CMT_LUT_4_SIZE 0x00000600 | ||
| 245 | |||
| 246 | #define CMT_LUT_5_START_ADDR 0x0004d000 | ||
| 247 | #define CMT_LUT_5_SIZE 0x00000600 | ||
| 248 | |||
| 249 | #define CMT_LUT_6_START_ADDR 0x0004d600 | ||
| 250 | #define CMT_LUT_6_SIZE 0x00000600 | ||
| 251 | |||
| 252 | #define DRC_TABLE_0_START_ADDR 0x0004dc00 | ||
| 253 | #define DRC_TABLE_0_SIZE 0x00000100 | ||
| 254 | |||
| 255 | #define SPLASH_0_START_ADDR 0x0004dd00 | ||
| 256 | #define SPLASH_0_SIZE 0x00032280 | ||
| 257 | |||
| 258 | #define SEQUENCE_7_START_ADDR 0x00080000 | ||
| 259 | #define SEQUENCE_7_SIZE 0x00000d10 | ||
| 260 | |||
| 261 | #define SEQUENCE_8_START_ADDR 0x00081800 | ||
| 262 | #define SEQUENCE_8_SIZE 0x00000d10 | ||
| 263 | |||
| 264 | #define SEQUENCE_9_START_ADDR 0x00083000 | ||
| 265 | #define SEQUENCE_9_SIZE 0x00000d10 | ||
| 266 | |||
| 267 | #define CMT_LUT_7_START_ADDR 0x0008e000 | ||
| 268 | #define CMT_LUT_7_SIZE 0x00000600 | ||
| 269 | |||
| 270 | #define CMT_LUT_8_START_ADDR 0x0008e800 | ||
| 271 | #define CMT_LUT_8_SIZE 0x00000600 | ||
| 272 | |||
| 273 | #define CMT_LUT_9_START_ADDR 0x0008f000 | ||
| 274 | #define CMT_LUT_9_SIZE 0x00000600 | ||
| 275 | |||
| 276 | #define SPLASH_1_START_ADDR 0x0009a000 | ||
| 277 | #define SPLASH_1_SIZE 0x00032280 | ||
| 278 | |||
| 279 | #define SPLASH_2_START_ADDR 0x000cd000 | ||
| 280 | #define SPLASH_2_SIZE 0x00032280 | ||
| 281 | |||
| 282 | #define SPLASH_3_START_ADDR 0x00100000 | ||
| 283 | #define SPLASH_3_SIZE 0x00032280 | ||
| 284 | |||
| 285 | #define OPT_SPLASH_0_START_ADDR 0x00134000 | ||
| 286 | #define OPT_SPLASH_0_SIZE 0x000cb100 | ||
| 287 | |||
| 288 | #endif | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 4e888ac09b3f..80c3f6ab1a94 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
| @@ -35,26 +35,12 @@ | |||
| 35 | 35 | ||
| 36 | #include <video/omapdss.h> | 36 | #include <video/omapdss.h> |
| 37 | #include <video/omap-panel-nokia-dsi.h> | 37 | #include <video/omap-panel-nokia-dsi.h> |
| 38 | #include <video/mipi_display.h> | ||
| 38 | 39 | ||
| 39 | /* DSI Virtual channel. Hardcoded for now. */ | 40 | /* DSI Virtual channel. Hardcoded for now. */ |
| 40 | #define TCH 0 | 41 | #define TCH 0 |
| 41 | 42 | ||
| 42 | #define DCS_READ_NUM_ERRORS 0x05 | 43 | #define DCS_READ_NUM_ERRORS 0x05 |
| 43 | #define DCS_READ_POWER_MODE 0x0a | ||
| 44 | #define DCS_READ_MADCTL 0x0b | ||
| 45 | #define DCS_READ_PIXEL_FORMAT 0x0c | ||
| 46 | #define DCS_RDDSDR 0x0f | ||
| 47 | #define DCS_SLEEP_IN 0x10 | ||
| 48 | #define DCS_SLEEP_OUT 0x11 | ||
| 49 | #define DCS_DISPLAY_OFF 0x28 | ||
| 50 | #define DCS_DISPLAY_ON 0x29 | ||
| 51 | #define DCS_COLUMN_ADDR 0x2a | ||
| 52 | #define DCS_PAGE_ADDR 0x2b | ||
| 53 | #define DCS_MEMORY_WRITE 0x2c | ||
| 54 | #define DCS_TEAR_OFF 0x34 | ||
| 55 | #define DCS_TEAR_ON 0x35 | ||
| 56 | #define DCS_MEM_ACC_CTRL 0x36 | ||
| 57 | #define DCS_PIXEL_FORMAT 0x3a | ||
| 58 | #define DCS_BRIGHTNESS 0x51 | 44 | #define DCS_BRIGHTNESS 0x51 |
| 59 | #define DCS_CTRL_DISPLAY 0x53 | 45 | #define DCS_CTRL_DISPLAY 0x53 |
| 60 | #define DCS_WRITE_CABC 0x55 | 46 | #define DCS_WRITE_CABC 0x55 |
| @@ -222,8 +208,6 @@ struct taal_data { | |||
| 222 | 208 | ||
| 223 | struct delayed_work te_timeout_work; | 209 | struct delayed_work te_timeout_work; |
| 224 | 210 | ||
| 225 | bool use_dsi_bl; | ||
| 226 | |||
| 227 | bool cabc_broken; | 211 | bool cabc_broken; |
| 228 | unsigned cabc_mode; | 212 | unsigned cabc_mode; |
| 229 | 213 | ||
| @@ -302,7 +286,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
| 302 | 286 | ||
| 303 | hw_guard_wait(td); | 287 | hw_guard_wait(td); |
| 304 | 288 | ||
| 305 | cmd = DCS_SLEEP_IN; | 289 | cmd = MIPI_DCS_ENTER_SLEEP_MODE; |
| 306 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); | 290 | r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); |
| 307 | if (r) | 291 | if (r) |
| 308 | return r; | 292 | return r; |
| @@ -321,7 +305,7 @@ static int taal_sleep_out(struct taal_data *td) | |||
| 321 | 305 | ||
| 322 | hw_guard_wait(td); | 306 | hw_guard_wait(td); |
| 323 | 307 | ||
| 324 | r = taal_dcs_write_0(td, DCS_SLEEP_OUT); | 308 | r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE); |
| 325 | if (r) | 309 | if (r) |
| 326 | return r; | 310 | return r; |
| 327 | 311 | ||
| @@ -356,7 +340,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) | |||
| 356 | u8 mode; | 340 | u8 mode; |
| 357 | int b5, b6, b7; | 341 | int b5, b6, b7; |
| 358 | 342 | ||
| 359 | r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); | 343 | r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode); |
| 360 | if (r) | 344 | if (r) |
| 361 | return r; | 345 | return r; |
| 362 | 346 | ||
| @@ -390,7 +374,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) | |||
| 390 | mode &= ~((1<<7) | (1<<6) | (1<<5)); | 374 | mode &= ~((1<<7) | (1<<6) | (1<<5)); |
| 391 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | 375 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); |
| 392 | 376 | ||
| 393 | return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); | 377 | return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode); |
| 394 | } | 378 | } |
| 395 | 379 | ||
| 396 | static int taal_set_update_window(struct taal_data *td, | 380 | static int taal_set_update_window(struct taal_data *td, |
| @@ -403,7 +387,7 @@ static int taal_set_update_window(struct taal_data *td, | |||
| 403 | u16 y2 = y + h - 1; | 387 | u16 y2 = y + h - 1; |
| 404 | 388 | ||
| 405 | u8 buf[5]; | 389 | u8 buf[5]; |
| 406 | buf[0] = DCS_COLUMN_ADDR; | 390 | buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS; |
| 407 | buf[1] = (x1 >> 8) & 0xff; | 391 | buf[1] = (x1 >> 8) & 0xff; |
| 408 | buf[2] = (x1 >> 0) & 0xff; | 392 | buf[2] = (x1 >> 0) & 0xff; |
| 409 | buf[3] = (x2 >> 8) & 0xff; | 393 | buf[3] = (x2 >> 8) & 0xff; |
| @@ -413,7 +397,7 @@ static int taal_set_update_window(struct taal_data *td, | |||
| 413 | if (r) | 397 | if (r) |
| 414 | return r; | 398 | return r; |
| 415 | 399 | ||
| 416 | buf[0] = DCS_PAGE_ADDR; | 400 | buf[0] = MIPI_DCS_SET_PAGE_ADDRESS; |
| 417 | buf[1] = (y1 >> 8) & 0xff; | 401 | buf[1] = (y1 >> 8) & 0xff; |
| 418 | buf[2] = (y1 >> 0) & 0xff; | 402 | buf[2] = (y1 >> 0) & 0xff; |
| 419 | buf[3] = (y2 >> 8) & 0xff; | 403 | buf[3] = (y2 >> 8) & 0xff; |
| @@ -555,7 +539,6 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
| 555 | { | 539 | { |
| 556 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | 540 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); |
| 557 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 541 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
| 558 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | ||
| 559 | int r; | 542 | int r; |
| 560 | int level; | 543 | int level; |
| 561 | 544 | ||
| @@ -569,23 +552,16 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
| 569 | 552 | ||
| 570 | mutex_lock(&td->lock); | 553 | mutex_lock(&td->lock); |
| 571 | 554 | ||
| 572 | if (td->use_dsi_bl) { | 555 | if (td->enabled) { |
| 573 | if (td->enabled) { | 556 | dsi_bus_lock(dssdev); |
| 574 | dsi_bus_lock(dssdev); | ||
| 575 | 557 | ||
| 576 | r = taal_wake_up(dssdev); | 558 | r = taal_wake_up(dssdev); |
| 577 | if (!r) | 559 | if (!r) |
| 578 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); | 560 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); |
| 579 | 561 | ||
| 580 | dsi_bus_unlock(dssdev); | 562 | dsi_bus_unlock(dssdev); |
| 581 | } else { | ||
| 582 | r = 0; | ||
| 583 | } | ||
| 584 | } else { | 563 | } else { |
| 585 | if (!panel_data->set_backlight) | 564 | r = 0; |
| 586 | r = -EINVAL; | ||
| 587 | else | ||
| 588 | r = panel_data->set_backlight(dssdev, level); | ||
| 589 | } | 565 | } |
| 590 | 566 | ||
| 591 | mutex_unlock(&td->lock); | 567 | mutex_unlock(&td->lock); |
| @@ -964,7 +940,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
| 964 | { | 940 | { |
| 965 | struct backlight_properties props; | 941 | struct backlight_properties props; |
| 966 | struct taal_data *td; | 942 | struct taal_data *td; |
| 967 | struct backlight_device *bldev; | 943 | struct backlight_device *bldev = NULL; |
| 968 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); | 944 | struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev); |
| 969 | struct panel_config *panel_config = NULL; | 945 | struct panel_config *panel_config = NULL; |
| 970 | int r, i; | 946 | int r, i; |
| @@ -990,7 +966,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
| 990 | 966 | ||
| 991 | dssdev->panel.config = OMAP_DSS_LCD_TFT; | 967 | dssdev->panel.config = OMAP_DSS_LCD_TFT; |
| 992 | dssdev->panel.timings = panel_config->timings; | 968 | dssdev->panel.timings = panel_config->timings; |
| 993 | dssdev->ctrl.pixel_size = 24; | 969 | dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; |
| 994 | 970 | ||
| 995 | td = kzalloc(sizeof(*td), GFP_KERNEL); | 971 | td = kzalloc(sizeof(*td), GFP_KERNEL); |
| 996 | if (!td) { | 972 | if (!td) { |
| @@ -1025,35 +1001,26 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
| 1025 | 1001 | ||
| 1026 | taal_hw_reset(dssdev); | 1002 | taal_hw_reset(dssdev); |
| 1027 | 1003 | ||
| 1028 | /* if no platform set_backlight() defined, presume DSI backlight | 1004 | if (panel_data->use_dsi_backlight) { |
| 1029 | * control */ | 1005 | memset(&props, 0, sizeof(struct backlight_properties)); |
| 1030 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
| 1031 | if (!panel_data->set_backlight) | ||
| 1032 | td->use_dsi_bl = true; | ||
| 1033 | |||
| 1034 | if (td->use_dsi_bl) | ||
| 1035 | props.max_brightness = 255; | 1006 | props.max_brightness = 255; |
| 1036 | else | ||
| 1037 | props.max_brightness = 127; | ||
| 1038 | |||
| 1039 | props.type = BACKLIGHT_RAW; | ||
| 1040 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, | ||
| 1041 | dssdev, &taal_bl_ops, &props); | ||
| 1042 | if (IS_ERR(bldev)) { | ||
| 1043 | r = PTR_ERR(bldev); | ||
| 1044 | goto err_bl; | ||
| 1045 | } | ||
| 1046 | 1007 | ||
| 1047 | td->bldev = bldev; | 1008 | props.type = BACKLIGHT_RAW; |
| 1009 | bldev = backlight_device_register(dev_name(&dssdev->dev), | ||
| 1010 | &dssdev->dev, dssdev, &taal_bl_ops, &props); | ||
| 1011 | if (IS_ERR(bldev)) { | ||
| 1012 | r = PTR_ERR(bldev); | ||
| 1013 | goto err_bl; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | td->bldev = bldev; | ||
| 1048 | 1017 | ||
| 1049 | bldev->props.fb_blank = FB_BLANK_UNBLANK; | 1018 | bldev->props.fb_blank = FB_BLANK_UNBLANK; |
| 1050 | bldev->props.power = FB_BLANK_UNBLANK; | 1019 | bldev->props.power = FB_BLANK_UNBLANK; |
| 1051 | if (td->use_dsi_bl) | ||
| 1052 | bldev->props.brightness = 255; | 1020 | bldev->props.brightness = 255; |
| 1053 | else | ||
| 1054 | bldev->props.brightness = 127; | ||
| 1055 | 1021 | ||
| 1056 | taal_bl_update_status(bldev); | 1022 | taal_bl_update_status(bldev); |
| 1023 | } | ||
| 1057 | 1024 | ||
| 1058 | if (panel_data->use_ext_te) { | 1025 | if (panel_data->use_ext_te) { |
| 1059 | int gpio = panel_data->ext_te_gpio; | 1026 | int gpio = panel_data->ext_te_gpio; |
| @@ -1067,7 +1034,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
| 1067 | gpio_direction_input(gpio); | 1034 | gpio_direction_input(gpio); |
| 1068 | 1035 | ||
| 1069 | r = request_irq(gpio_to_irq(gpio), taal_te_isr, | 1036 | r = request_irq(gpio_to_irq(gpio), taal_te_isr, |
| 1070 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | 1037 | IRQF_TRIGGER_RISING, |
| 1071 | "taal vsync", dssdev); | 1038 | "taal vsync", dssdev); |
| 1072 | 1039 | ||
| 1073 | if (r) { | 1040 | if (r) { |
| @@ -1111,7 +1078,8 @@ err_irq: | |||
| 1111 | if (panel_data->use_ext_te) | 1078 | if (panel_data->use_ext_te) |
| 1112 | gpio_free(panel_data->ext_te_gpio); | 1079 | gpio_free(panel_data->ext_te_gpio); |
| 1113 | err_gpio: | 1080 | err_gpio: |
| 1114 | backlight_device_unregister(bldev); | 1081 | if (bldev != NULL) |
| 1082 | backlight_device_unregister(bldev); | ||
| 1115 | err_bl: | 1083 | err_bl: |
| 1116 | destroy_workqueue(td->workqueue); | 1084 | destroy_workqueue(td->workqueue); |
| 1117 | err_wq: | 1085 | err_wq: |
| @@ -1140,9 +1108,11 @@ static void __exit taal_remove(struct omap_dss_device *dssdev) | |||
| 1140 | } | 1108 | } |
| 1141 | 1109 | ||
| 1142 | bldev = td->bldev; | 1110 | bldev = td->bldev; |
| 1143 | bldev->props.power = FB_BLANK_POWERDOWN; | 1111 | if (bldev != NULL) { |
| 1144 | taal_bl_update_status(bldev); | 1112 | bldev->props.power = FB_BLANK_POWERDOWN; |
| 1145 | backlight_device_unregister(bldev); | 1113 | taal_bl_update_status(bldev); |
| 1114 | backlight_device_unregister(bldev); | ||
| 1115 | } | ||
| 1146 | 1116 | ||
| 1147 | taal_cancel_ulps_work(dssdev); | 1117 | taal_cancel_ulps_work(dssdev); |
| 1148 | taal_cancel_esd_work(dssdev); | 1118 | taal_cancel_esd_work(dssdev); |
| @@ -1195,7 +1165,8 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
| 1195 | if (r) | 1165 | if (r) |
| 1196 | goto err; | 1166 | goto err; |
| 1197 | 1167 | ||
| 1198 | r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 1168 | r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT, |
| 1169 | MIPI_DCS_PIXEL_FMT_24BIT); | ||
| 1199 | if (r) | 1170 | if (r) |
| 1200 | goto err; | 1171 | goto err; |
| 1201 | 1172 | ||
| @@ -1209,7 +1180,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
| 1209 | goto err; | 1180 | goto err; |
| 1210 | } | 1181 | } |
| 1211 | 1182 | ||
| 1212 | r = taal_dcs_write_0(td, DCS_DISPLAY_ON); | 1183 | r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON); |
| 1213 | if (r) | 1184 | if (r) |
| 1214 | goto err; | 1185 | goto err; |
| 1215 | 1186 | ||
| @@ -1246,7 +1217,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
| 1246 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1217 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
| 1247 | int r; | 1218 | int r; |
| 1248 | 1219 | ||
| 1249 | r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); | 1220 | r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF); |
| 1250 | if (!r) | 1221 | if (!r) |
| 1251 | r = taal_sleep_in(td); | 1222 | r = taal_sleep_in(td); |
| 1252 | 1223 | ||
| @@ -1529,9 +1500,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
| 1529 | int r; | 1500 | int r; |
| 1530 | 1501 | ||
| 1531 | if (enable) | 1502 | if (enable) |
| 1532 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); | 1503 | r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); |
| 1533 | else | 1504 | else |
| 1534 | r = taal_dcs_write_0(td, DCS_TEAR_OFF); | 1505 | r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); |
| 1535 | 1506 | ||
| 1536 | if (!panel_data->use_ext_te) | 1507 | if (!panel_data->use_ext_te) |
| 1537 | omapdss_dsi_enable_te(dssdev, enable); | 1508 | omapdss_dsi_enable_te(dssdev, enable); |
| @@ -1851,7 +1822,7 @@ static void taal_esd_work(struct work_struct *work) | |||
| 1851 | goto err; | 1822 | goto err; |
| 1852 | } | 1823 | } |
| 1853 | 1824 | ||
| 1854 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); | 1825 | r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1); |
| 1855 | if (r) { | 1826 | if (r) { |
| 1856 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1827 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
| 1857 | goto err; | 1828 | goto err; |
| @@ -1864,7 +1835,7 @@ static void taal_esd_work(struct work_struct *work) | |||
| 1864 | goto err; | 1835 | goto err; |
| 1865 | } | 1836 | } |
| 1866 | 1837 | ||
| 1867 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); | 1838 | r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2); |
| 1868 | if (r) { | 1839 | if (r) { |
| 1869 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1840 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
| 1870 | goto err; | 1841 | goto err; |
| @@ -1880,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work) | |||
| 1880 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1851 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
| 1881 | * to re-enable TE after self diagnostics */ | 1852 | * to re-enable TE after self diagnostics */ |
| 1882 | if (td->te_enabled && panel_data->use_ext_te) { | 1853 | if (td->te_enabled && panel_data->use_ext_te) { |
| 1883 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); | 1854 | r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); |
| 1884 | if (r) | 1855 | if (r) |
| 1885 | goto err; | 1856 | goto err; |
| 1886 | } | 1857 | } |
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 0d12524db14b..7be7c06a249e 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | menuconfig OMAP2_DSS | 1 | menuconfig OMAP2_DSS |
| 2 | tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ Display Subsystem support" |
| 3 | depends on ARCH_OMAP2PLUS | 3 | depends on ARCH_OMAP2PLUS |
| 4 | help | 4 | help |
| 5 | OMAP2+ Display Subsystem support. | 5 | OMAP2+ Display Subsystem support. |
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 10d9d3bb3e24..bd34ac5b2026 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile | |||
| @@ -6,4 +6,4 @@ omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o | |||
| 6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | 6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o |
| 7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
| 8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | 8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ |
| 9 | hdmi_omap4_panel.o | 9 | hdmi_panel.o ti_hdmi_4xxx_ip.o |
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 76821fefce9a..86ec12e16c7c 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
| @@ -145,6 +145,10 @@ static int dss_initialize_debugfs(void) | |||
| 145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, | 145 | debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, |
| 146 | &venc_dump_regs, &dss_debug_fops); | 146 | &venc_dump_regs, &dss_debug_fops); |
| 147 | #endif | 147 | #endif |
| 148 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
| 149 | debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir, | ||
| 150 | &hdmi_dump_regs, &dss_debug_fops); | ||
| 151 | #endif | ||
| 148 | return 0; | 152 | return 0; |
| 149 | } | 153 | } |
| 150 | 154 | ||
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 0f3961a1ce26..3532782551cb 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
| 27 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
| 28 | #include <linux/export.h> | ||
| 28 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
| 29 | #include <linux/io.h> | 30 | #include <linux/io.h> |
| 30 | #include <linux/jiffies.h> | 31 | #include <linux/jiffies.h> |
| @@ -106,7 +107,7 @@ static struct { | |||
| 106 | int irq; | 107 | int irq; |
| 107 | struct clk *dss_clk; | 108 | struct clk *dss_clk; |
| 108 | 109 | ||
| 109 | u32 fifo_size[3]; | 110 | u32 fifo_size[MAX_DSS_OVERLAYS]; |
| 110 | 111 | ||
| 111 | spinlock_t irq_lock; | 112 | spinlock_t irq_lock; |
| 112 | u32 irq_error_mask; | 113 | u32 irq_error_mask; |
| @@ -171,172 +172,98 @@ static int dispc_get_ctx_loss_count(void) | |||
| 171 | 172 | ||
| 172 | static void dispc_save_context(void) | 173 | static void dispc_save_context(void) |
| 173 | { | 174 | { |
| 174 | int i; | 175 | int i, j; |
| 175 | 176 | ||
| 176 | DSSDBG("dispc_save_context\n"); | 177 | DSSDBG("dispc_save_context\n"); |
| 177 | 178 | ||
| 178 | SR(IRQENABLE); | 179 | SR(IRQENABLE); |
| 179 | SR(CONTROL); | 180 | SR(CONTROL); |
| 180 | SR(CONFIG); | 181 | SR(CONFIG); |
| 181 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
| 182 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 183 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
| 184 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 185 | SR(LINE_NUMBER); | 182 | SR(LINE_NUMBER); |
| 186 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); | 183 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || |
| 187 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); | 184 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) |
| 188 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); | ||
| 189 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); | ||
| 190 | if (dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
| 191 | SR(GLOBAL_ALPHA); | 185 | SR(GLOBAL_ALPHA); |
| 192 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 193 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); | ||
| 194 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 186 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
| 195 | SR(CONTROL2); | 187 | SR(CONTROL2); |
| 196 | SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 197 | SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 198 | SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 199 | SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); | ||
| 200 | SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); | ||
| 201 | SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); | ||
| 202 | SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); | ||
| 203 | SR(CONFIG2); | 188 | SR(CONFIG2); |
| 204 | } | 189 | } |
| 205 | 190 | ||
| 206 | SR(OVL_BA0(OMAP_DSS_GFX)); | 191 | for (i = 0; i < dss_feat_get_num_mgrs(); i++) { |
| 207 | SR(OVL_BA1(OMAP_DSS_GFX)); | 192 | SR(DEFAULT_COLOR(i)); |
| 208 | SR(OVL_POSITION(OMAP_DSS_GFX)); | 193 | SR(TRANS_COLOR(i)); |
| 209 | SR(OVL_SIZE(OMAP_DSS_GFX)); | 194 | SR(SIZE_MGR(i)); |
| 210 | SR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); | 195 | if (i == OMAP_DSS_CHANNEL_DIGIT) |
| 211 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); | 196 | continue; |
| 212 | SR(OVL_ROW_INC(OMAP_DSS_GFX)); | 197 | SR(TIMING_H(i)); |
| 213 | SR(OVL_PIXEL_INC(OMAP_DSS_GFX)); | 198 | SR(TIMING_V(i)); |
| 214 | SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | 199 | SR(POL_FREQ(i)); |
| 215 | SR(OVL_TABLE_BA(OMAP_DSS_GFX)); | 200 | SR(DIVISORo(i)); |
| 216 | 201 | ||
| 217 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | 202 | SR(DATA_CYCLE1(i)); |
| 218 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | 203 | SR(DATA_CYCLE2(i)); |
| 219 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | 204 | SR(DATA_CYCLE3(i)); |
| 220 | 205 | ||
| 221 | if (dss_has_feature(FEAT_CPR)) { | ||
| 222 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | ||
| 223 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | ||
| 224 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
| 225 | } | ||
| 226 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
| 227 | if (dss_has_feature(FEAT_CPR)) { | 206 | if (dss_has_feature(FEAT_CPR)) { |
| 228 | SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | 207 | SR(CPR_COEF_R(i)); |
| 229 | SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | 208 | SR(CPR_COEF_G(i)); |
| 230 | SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | 209 | SR(CPR_COEF_B(i)); |
| 231 | } | 210 | } |
| 232 | |||
| 233 | SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | ||
| 234 | SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | ||
| 235 | SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | ||
| 236 | } | 211 | } |
| 237 | 212 | ||
| 238 | if (dss_has_feature(FEAT_PRELOAD)) | 213 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { |
| 239 | SR(OVL_PRELOAD(OMAP_DSS_GFX)); | 214 | SR(OVL_BA0(i)); |
| 240 | 215 | SR(OVL_BA1(i)); | |
| 241 | /* VID1 */ | 216 | SR(OVL_POSITION(i)); |
| 242 | SR(OVL_BA0(OMAP_DSS_VIDEO1)); | 217 | SR(OVL_SIZE(i)); |
| 243 | SR(OVL_BA1(OMAP_DSS_VIDEO1)); | 218 | SR(OVL_ATTRIBUTES(i)); |
| 244 | SR(OVL_POSITION(OMAP_DSS_VIDEO1)); | 219 | SR(OVL_FIFO_THRESHOLD(i)); |
| 245 | SR(OVL_SIZE(OMAP_DSS_VIDEO1)); | 220 | SR(OVL_ROW_INC(i)); |
| 246 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); | 221 | SR(OVL_PIXEL_INC(i)); |
| 247 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); | 222 | if (dss_has_feature(FEAT_PRELOAD)) |
| 248 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); | 223 | SR(OVL_PRELOAD(i)); |
| 249 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); | 224 | if (i == OMAP_DSS_GFX) { |
| 250 | SR(OVL_FIR(OMAP_DSS_VIDEO1)); | 225 | SR(OVL_WINDOW_SKIP(i)); |
| 251 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); | 226 | SR(OVL_TABLE_BA(i)); |
| 252 | SR(OVL_ACCU0(OMAP_DSS_VIDEO1)); | 227 | continue; |
| 253 | SR(OVL_ACCU1(OMAP_DSS_VIDEO1)); | 228 | } |
| 254 | 229 | SR(OVL_FIR(i)); | |
| 255 | for (i = 0; i < 8; i++) | 230 | SR(OVL_PICTURE_SIZE(i)); |
| 256 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); | 231 | SR(OVL_ACCU0(i)); |
| 257 | 232 | SR(OVL_ACCU1(i)); | |
| 258 | for (i = 0; i < 8; i++) | ||
| 259 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); | ||
| 260 | |||
| 261 | for (i = 0; i < 5; i++) | ||
| 262 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); | ||
| 263 | |||
| 264 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
| 265 | for (i = 0; i < 8; i++) | ||
| 266 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); | ||
| 267 | } | ||
| 268 | |||
| 269 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
| 270 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); | ||
| 271 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); | ||
| 272 | SR(OVL_FIR2(OMAP_DSS_VIDEO1)); | ||
| 273 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); | ||
| 274 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | ||
| 275 | |||
| 276 | for (i = 0; i < 8; i++) | ||
| 277 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); | ||
| 278 | |||
| 279 | for (i = 0; i < 8; i++) | ||
| 280 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | ||
| 281 | |||
| 282 | for (i = 0; i < 8; i++) | ||
| 283 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); | ||
| 284 | } | ||
| 285 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 286 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
| 287 | |||
| 288 | if (dss_has_feature(FEAT_PRELOAD)) | ||
| 289 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
| 290 | |||
| 291 | /* VID2 */ | ||
| 292 | SR(OVL_BA0(OMAP_DSS_VIDEO2)); | ||
| 293 | SR(OVL_BA1(OMAP_DSS_VIDEO2)); | ||
| 294 | SR(OVL_POSITION(OMAP_DSS_VIDEO2)); | ||
| 295 | SR(OVL_SIZE(OMAP_DSS_VIDEO2)); | ||
| 296 | SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); | ||
| 297 | SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); | ||
| 298 | SR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); | ||
| 299 | SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); | ||
| 300 | SR(OVL_FIR(OMAP_DSS_VIDEO2)); | ||
| 301 | SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); | ||
| 302 | SR(OVL_ACCU0(OMAP_DSS_VIDEO2)); | ||
| 303 | SR(OVL_ACCU1(OMAP_DSS_VIDEO2)); | ||
| 304 | 233 | ||
| 305 | for (i = 0; i < 8; i++) | 234 | for (j = 0; j < 8; j++) |
| 306 | SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); | 235 | SR(OVL_FIR_COEF_H(i, j)); |
| 307 | 236 | ||
| 308 | for (i = 0; i < 8; i++) | 237 | for (j = 0; j < 8; j++) |
| 309 | SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); | 238 | SR(OVL_FIR_COEF_HV(i, j)); |
| 310 | 239 | ||
| 311 | for (i = 0; i < 5; i++) | 240 | for (j = 0; j < 5; j++) |
| 312 | SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); | 241 | SR(OVL_CONV_COEF(i, j)); |
| 313 | 242 | ||
| 314 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | 243 | if (dss_has_feature(FEAT_FIR_COEF_V)) { |
| 315 | for (i = 0; i < 8; i++) | 244 | for (j = 0; j < 8; j++) |
| 316 | SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); | 245 | SR(OVL_FIR_COEF_V(i, j)); |
| 317 | } | 246 | } |
| 318 | 247 | ||
| 319 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | 248 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
| 320 | SR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); | 249 | SR(OVL_BA0_UV(i)); |
| 321 | SR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); | 250 | SR(OVL_BA1_UV(i)); |
| 322 | SR(OVL_FIR2(OMAP_DSS_VIDEO2)); | 251 | SR(OVL_FIR2(i)); |
| 323 | SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | 252 | SR(OVL_ACCU2_0(i)); |
| 324 | SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | 253 | SR(OVL_ACCU2_1(i)); |
| 325 | 254 | ||
| 326 | for (i = 0; i < 8; i++) | 255 | for (j = 0; j < 8; j++) |
| 327 | SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); | 256 | SR(OVL_FIR_COEF_H2(i, j)); |
| 328 | 257 | ||
| 329 | for (i = 0; i < 8; i++) | 258 | for (j = 0; j < 8; j++) |
| 330 | SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | 259 | SR(OVL_FIR_COEF_HV2(i, j)); |
| 331 | 260 | ||
| 332 | for (i = 0; i < 8; i++) | 261 | for (j = 0; j < 8; j++) |
| 333 | SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); | 262 | SR(OVL_FIR_COEF_V2(i, j)); |
| 263 | } | ||
| 264 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 265 | SR(OVL_ATTRIBUTES2(i)); | ||
| 334 | } | 266 | } |
| 335 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 336 | SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
| 337 | |||
| 338 | if (dss_has_feature(FEAT_PRELOAD)) | ||
| 339 | SR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
| 340 | 267 | ||
| 341 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 268 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
| 342 | SR(DIVISOR); | 269 | SR(DIVISOR); |
| @@ -349,7 +276,7 @@ static void dispc_save_context(void) | |||
| 349 | 276 | ||
| 350 | static void dispc_restore_context(void) | 277 | static void dispc_restore_context(void) |
| 351 | { | 278 | { |
| 352 | int i, ctx; | 279 | int i, j, ctx; |
| 353 | 280 | ||
| 354 | DSSDBG("dispc_restore_context\n"); | 281 | DSSDBG("dispc_restore_context\n"); |
| 355 | 282 | ||
| @@ -367,165 +294,89 @@ static void dispc_restore_context(void) | |||
| 367 | /*RR(IRQENABLE);*/ | 294 | /*RR(IRQENABLE);*/ |
| 368 | /*RR(CONTROL);*/ | 295 | /*RR(CONTROL);*/ |
| 369 | RR(CONFIG); | 296 | RR(CONFIG); |
| 370 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
| 371 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 372 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
| 373 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 374 | RR(LINE_NUMBER); | 297 | RR(LINE_NUMBER); |
| 375 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD)); | 298 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || |
| 376 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD)); | 299 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) |
| 377 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD)); | ||
| 378 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD)); | ||
| 379 | if (dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
| 380 | RR(GLOBAL_ALPHA); | 300 | RR(GLOBAL_ALPHA); |
| 381 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); | 301 | if (dss_has_feature(FEAT_MGR_LCD2)) |
| 382 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); | ||
| 383 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
| 384 | RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 385 | RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 386 | RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 387 | RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2)); | ||
| 388 | RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2)); | ||
| 389 | RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); | ||
| 390 | RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2)); | ||
| 391 | RR(CONFIG2); | 302 | RR(CONFIG2); |
| 392 | } | ||
| 393 | |||
| 394 | RR(OVL_BA0(OMAP_DSS_GFX)); | ||
| 395 | RR(OVL_BA1(OMAP_DSS_GFX)); | ||
| 396 | RR(OVL_POSITION(OMAP_DSS_GFX)); | ||
| 397 | RR(OVL_SIZE(OMAP_DSS_GFX)); | ||
| 398 | RR(OVL_ATTRIBUTES(OMAP_DSS_GFX)); | ||
| 399 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); | ||
| 400 | RR(OVL_ROW_INC(OMAP_DSS_GFX)); | ||
| 401 | RR(OVL_PIXEL_INC(OMAP_DSS_GFX)); | ||
| 402 | RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | ||
| 403 | RR(OVL_TABLE_BA(OMAP_DSS_GFX)); | ||
| 404 | |||
| 405 | 303 | ||
| 406 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | 304 | for (i = 0; i < dss_feat_get_num_mgrs(); i++) { |
| 407 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | 305 | RR(DEFAULT_COLOR(i)); |
| 408 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | 306 | RR(TRANS_COLOR(i)); |
| 307 | RR(SIZE_MGR(i)); | ||
| 308 | if (i == OMAP_DSS_CHANNEL_DIGIT) | ||
| 309 | continue; | ||
| 310 | RR(TIMING_H(i)); | ||
| 311 | RR(TIMING_V(i)); | ||
| 312 | RR(POL_FREQ(i)); | ||
| 313 | RR(DIVISORo(i)); | ||
| 409 | 314 | ||
| 410 | if (dss_has_feature(FEAT_CPR)) { | 315 | RR(DATA_CYCLE1(i)); |
| 411 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | 316 | RR(DATA_CYCLE2(i)); |
| 412 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | 317 | RR(DATA_CYCLE3(i)); |
| 413 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
| 414 | } | ||
| 415 | if (dss_has_feature(FEAT_MGR_LCD2)) { | ||
| 416 | RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | ||
| 417 | RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | ||
| 418 | RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | ||
| 419 | 318 | ||
| 420 | if (dss_has_feature(FEAT_CPR)) { | 319 | if (dss_has_feature(FEAT_CPR)) { |
| 421 | RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | 320 | RR(CPR_COEF_R(i)); |
| 422 | RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | 321 | RR(CPR_COEF_G(i)); |
| 423 | RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | 322 | RR(CPR_COEF_B(i)); |
| 424 | } | 323 | } |
| 425 | } | 324 | } |
| 426 | 325 | ||
| 427 | if (dss_has_feature(FEAT_PRELOAD)) | 326 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { |
| 428 | RR(OVL_PRELOAD(OMAP_DSS_GFX)); | 327 | RR(OVL_BA0(i)); |
| 429 | 328 | RR(OVL_BA1(i)); | |
| 430 | /* VID1 */ | 329 | RR(OVL_POSITION(i)); |
| 431 | RR(OVL_BA0(OMAP_DSS_VIDEO1)); | 330 | RR(OVL_SIZE(i)); |
| 432 | RR(OVL_BA1(OMAP_DSS_VIDEO1)); | 331 | RR(OVL_ATTRIBUTES(i)); |
| 433 | RR(OVL_POSITION(OMAP_DSS_VIDEO1)); | 332 | RR(OVL_FIFO_THRESHOLD(i)); |
| 434 | RR(OVL_SIZE(OMAP_DSS_VIDEO1)); | 333 | RR(OVL_ROW_INC(i)); |
| 435 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); | 334 | RR(OVL_PIXEL_INC(i)); |
| 436 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); | 335 | if (dss_has_feature(FEAT_PRELOAD)) |
| 437 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO1)); | 336 | RR(OVL_PRELOAD(i)); |
| 438 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); | 337 | if (i == OMAP_DSS_GFX) { |
| 439 | RR(OVL_FIR(OMAP_DSS_VIDEO1)); | 338 | RR(OVL_WINDOW_SKIP(i)); |
| 440 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); | 339 | RR(OVL_TABLE_BA(i)); |
| 441 | RR(OVL_ACCU0(OMAP_DSS_VIDEO1)); | 340 | continue; |
| 442 | RR(OVL_ACCU1(OMAP_DSS_VIDEO1)); | 341 | } |
| 443 | 342 | RR(OVL_FIR(i)); | |
| 444 | for (i = 0; i < 8; i++) | 343 | RR(OVL_PICTURE_SIZE(i)); |
| 445 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i)); | 344 | RR(OVL_ACCU0(i)); |
| 446 | 345 | RR(OVL_ACCU1(i)); | |
| 447 | for (i = 0; i < 8; i++) | ||
| 448 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i)); | ||
| 449 | |||
| 450 | for (i = 0; i < 5; i++) | ||
| 451 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i)); | ||
| 452 | |||
| 453 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
| 454 | for (i = 0; i < 8; i++) | ||
| 455 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i)); | ||
| 456 | } | ||
| 457 | |||
| 458 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
| 459 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO1)); | ||
| 460 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO1)); | ||
| 461 | RR(OVL_FIR2(OMAP_DSS_VIDEO1)); | ||
| 462 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1)); | ||
| 463 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | ||
| 464 | |||
| 465 | for (i = 0; i < 8; i++) | ||
| 466 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i)); | ||
| 467 | |||
| 468 | for (i = 0; i < 8; i++) | ||
| 469 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i)); | ||
| 470 | |||
| 471 | for (i = 0; i < 8; i++) | ||
| 472 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i)); | ||
| 473 | } | ||
| 474 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 475 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
| 476 | |||
| 477 | if (dss_has_feature(FEAT_PRELOAD)) | ||
| 478 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
| 479 | |||
| 480 | /* VID2 */ | ||
| 481 | RR(OVL_BA0(OMAP_DSS_VIDEO2)); | ||
| 482 | RR(OVL_BA1(OMAP_DSS_VIDEO2)); | ||
| 483 | RR(OVL_POSITION(OMAP_DSS_VIDEO2)); | ||
| 484 | RR(OVL_SIZE(OMAP_DSS_VIDEO2)); | ||
| 485 | RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); | ||
| 486 | RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); | ||
| 487 | RR(OVL_ROW_INC(OMAP_DSS_VIDEO2)); | ||
| 488 | RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); | ||
| 489 | RR(OVL_FIR(OMAP_DSS_VIDEO2)); | ||
| 490 | RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); | ||
| 491 | RR(OVL_ACCU0(OMAP_DSS_VIDEO2)); | ||
| 492 | RR(OVL_ACCU1(OMAP_DSS_VIDEO2)); | ||
| 493 | 346 | ||
| 494 | for (i = 0; i < 8; i++) | 347 | for (j = 0; j < 8; j++) |
| 495 | RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i)); | 348 | RR(OVL_FIR_COEF_H(i, j)); |
| 496 | 349 | ||
| 497 | for (i = 0; i < 8; i++) | 350 | for (j = 0; j < 8; j++) |
| 498 | RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i)); | 351 | RR(OVL_FIR_COEF_HV(i, j)); |
| 499 | 352 | ||
| 500 | for (i = 0; i < 5; i++) | 353 | for (j = 0; j < 5; j++) |
| 501 | RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i)); | 354 | RR(OVL_CONV_COEF(i, j)); |
| 502 | 355 | ||
| 503 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | 356 | if (dss_has_feature(FEAT_FIR_COEF_V)) { |
| 504 | for (i = 0; i < 8; i++) | 357 | for (j = 0; j < 8; j++) |
| 505 | RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i)); | 358 | RR(OVL_FIR_COEF_V(i, j)); |
| 506 | } | 359 | } |
| 507 | 360 | ||
| 508 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | 361 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
| 509 | RR(OVL_BA0_UV(OMAP_DSS_VIDEO2)); | 362 | RR(OVL_BA0_UV(i)); |
| 510 | RR(OVL_BA1_UV(OMAP_DSS_VIDEO2)); | 363 | RR(OVL_BA1_UV(i)); |
| 511 | RR(OVL_FIR2(OMAP_DSS_VIDEO2)); | 364 | RR(OVL_FIR2(i)); |
| 512 | RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | 365 | RR(OVL_ACCU2_0(i)); |
| 513 | RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | 366 | RR(OVL_ACCU2_1(i)); |
| 514 | 367 | ||
| 515 | for (i = 0; i < 8; i++) | 368 | for (j = 0; j < 8; j++) |
| 516 | RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i)); | 369 | RR(OVL_FIR_COEF_H2(i, j)); |
| 517 | 370 | ||
| 518 | for (i = 0; i < 8; i++) | 371 | for (j = 0; j < 8; j++) |
| 519 | RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i)); | 372 | RR(OVL_FIR_COEF_HV2(i, j)); |
| 520 | 373 | ||
| 521 | for (i = 0; i < 8; i++) | 374 | for (j = 0; j < 8; j++) |
| 522 | RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i)); | 375 | RR(OVL_FIR_COEF_V2(i, j)); |
| 376 | } | ||
| 377 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 378 | RR(OVL_ATTRIBUTES2(i)); | ||
| 523 | } | 379 | } |
| 524 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 525 | RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
| 526 | |||
| 527 | if (dss_has_feature(FEAT_PRELOAD)) | ||
| 528 | RR(OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
| 529 | 380 | ||
| 530 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | 381 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) |
| 531 | RR(DIVISOR); | 382 | RR(DIVISOR); |
| @@ -570,13 +421,28 @@ void dispc_runtime_put(void) | |||
| 570 | WARN_ON(r < 0); | 421 | WARN_ON(r < 0); |
| 571 | } | 422 | } |
| 572 | 423 | ||
| 424 | static inline bool dispc_mgr_is_lcd(enum omap_channel channel) | ||
| 425 | { | ||
| 426 | if (channel == OMAP_DSS_CHANNEL_LCD || | ||
| 427 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
| 428 | return true; | ||
| 429 | else | ||
| 430 | return false; | ||
| 431 | } | ||
| 432 | |||
| 433 | static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel) | ||
| 434 | { | ||
| 435 | struct omap_overlay_manager *mgr = | ||
| 436 | omap_dss_get_overlay_manager(channel); | ||
| 573 | 437 | ||
| 574 | bool dispc_go_busy(enum omap_channel channel) | 438 | return mgr ? mgr->device : NULL; |
| 439 | } | ||
| 440 | |||
| 441 | bool dispc_mgr_go_busy(enum omap_channel channel) | ||
| 575 | { | 442 | { |
| 576 | int bit; | 443 | int bit; |
| 577 | 444 | ||
| 578 | if (channel == OMAP_DSS_CHANNEL_LCD || | 445 | if (dispc_mgr_is_lcd(channel)) |
| 579 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
| 580 | bit = 5; /* GOLCD */ | 446 | bit = 5; /* GOLCD */ |
| 581 | else | 447 | else |
| 582 | bit = 6; /* GODIGIT */ | 448 | bit = 6; /* GODIGIT */ |
| @@ -587,13 +453,12 @@ bool dispc_go_busy(enum omap_channel channel) | |||
| 587 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; | 453 | return REG_GET(DISPC_CONTROL, bit, bit) == 1; |
| 588 | } | 454 | } |
| 589 | 455 | ||
| 590 | void dispc_go(enum omap_channel channel) | 456 | void dispc_mgr_go(enum omap_channel channel) |
| 591 | { | 457 | { |
| 592 | int bit; | 458 | int bit; |
| 593 | bool enable_bit, go_bit; | 459 | bool enable_bit, go_bit; |
| 594 | 460 | ||
| 595 | if (channel == OMAP_DSS_CHANNEL_LCD || | 461 | if (dispc_mgr_is_lcd(channel)) |
| 596 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
| 597 | bit = 0; /* LCDENABLE */ | 462 | bit = 0; /* LCDENABLE */ |
| 598 | else | 463 | else |
| 599 | bit = 1; /* DIGITALENABLE */ | 464 | bit = 1; /* DIGITALENABLE */ |
| @@ -607,8 +472,7 @@ void dispc_go(enum omap_channel channel) | |||
| 607 | if (!enable_bit) | 472 | if (!enable_bit) |
| 608 | return; | 473 | return; |
| 609 | 474 | ||
| 610 | if (channel == OMAP_DSS_CHANNEL_LCD || | 475 | if (dispc_mgr_is_lcd(channel)) |
| 611 | channel == OMAP_DSS_CHANNEL_LCD2) | ||
| 612 | bit = 5; /* GOLCD */ | 476 | bit = 5; /* GOLCD */ |
| 613 | else | 477 | else |
| 614 | bit = 6; /* GODIGIT */ | 478 | bit = 6; /* GODIGIT */ |
| @@ -632,43 +496,44 @@ void dispc_go(enum omap_channel channel) | |||
| 632 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); | 496 | REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); |
| 633 | } | 497 | } |
| 634 | 498 | ||
| 635 | static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) | 499 | static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) |
| 636 | { | 500 | { |
| 637 | dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); | 501 | dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); |
| 638 | } | 502 | } |
| 639 | 503 | ||
| 640 | static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) | 504 | static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value) |
| 641 | { | 505 | { |
| 642 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); | 506 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); |
| 643 | } | 507 | } |
| 644 | 508 | ||
| 645 | static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) | 509 | static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value) |
| 646 | { | 510 | { |
| 647 | dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); | 511 | dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); |
| 648 | } | 512 | } |
| 649 | 513 | ||
| 650 | static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value) | 514 | static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value) |
| 651 | { | 515 | { |
| 652 | BUG_ON(plane == OMAP_DSS_GFX); | 516 | BUG_ON(plane == OMAP_DSS_GFX); |
| 653 | 517 | ||
| 654 | dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); | 518 | dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); |
| 655 | } | 519 | } |
| 656 | 520 | ||
| 657 | static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value) | 521 | static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg, |
| 522 | u32 value) | ||
| 658 | { | 523 | { |
| 659 | BUG_ON(plane == OMAP_DSS_GFX); | 524 | BUG_ON(plane == OMAP_DSS_GFX); |
| 660 | 525 | ||
| 661 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); | 526 | dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); |
| 662 | } | 527 | } |
| 663 | 528 | ||
| 664 | static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value) | 529 | static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value) |
| 665 | { | 530 | { |
| 666 | BUG_ON(plane == OMAP_DSS_GFX); | 531 | BUG_ON(plane == OMAP_DSS_GFX); |
| 667 | 532 | ||
| 668 | dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); | 533 | dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); |
| 669 | } | 534 | } |
| 670 | 535 | ||
| 671 | static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | 536 | static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup, |
| 672 | int vscaleup, int five_taps, | 537 | int vscaleup, int five_taps, |
| 673 | enum omap_color_component color_comp) | 538 | enum omap_color_component color_comp) |
| 674 | { | 539 | { |
| @@ -769,11 +634,11 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
| 769 | | FLD_VAL(v_coef[i].vc2, 31, 24); | 634 | | FLD_VAL(v_coef[i].vc2, 31, 24); |
| 770 | 635 | ||
| 771 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { | 636 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { |
| 772 | _dispc_write_firh_reg(plane, i, h); | 637 | dispc_ovl_write_firh_reg(plane, i, h); |
| 773 | _dispc_write_firhv_reg(plane, i, hv); | 638 | dispc_ovl_write_firhv_reg(plane, i, hv); |
| 774 | } else { | 639 | } else { |
| 775 | _dispc_write_firh2_reg(plane, i, h); | 640 | dispc_ovl_write_firh2_reg(plane, i, h); |
| 776 | _dispc_write_firhv2_reg(plane, i, hv); | 641 | dispc_ovl_write_firhv2_reg(plane, i, hv); |
| 777 | } | 642 | } |
| 778 | 643 | ||
| 779 | } | 644 | } |
| @@ -784,15 +649,16 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, | |||
| 784 | v = FLD_VAL(v_coef[i].vc00, 7, 0) | 649 | v = FLD_VAL(v_coef[i].vc00, 7, 0) |
| 785 | | FLD_VAL(v_coef[i].vc22, 15, 8); | 650 | | FLD_VAL(v_coef[i].vc22, 15, 8); |
| 786 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) | 651 | if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) |
| 787 | _dispc_write_firv_reg(plane, i, v); | 652 | dispc_ovl_write_firv_reg(plane, i, v); |
| 788 | else | 653 | else |
| 789 | _dispc_write_firv2_reg(plane, i, v); | 654 | dispc_ovl_write_firv2_reg(plane, i, v); |
| 790 | } | 655 | } |
| 791 | } | 656 | } |
| 792 | } | 657 | } |
| 793 | 658 | ||
| 794 | static void _dispc_setup_color_conv_coef(void) | 659 | static void _dispc_setup_color_conv_coef(void) |
| 795 | { | 660 | { |
| 661 | int i; | ||
| 796 | const struct color_conv_coef { | 662 | const struct color_conv_coef { |
| 797 | int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; | 663 | int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; |
| 798 | int full_range; | 664 | int full_range; |
| @@ -806,65 +672,54 @@ static void _dispc_setup_color_conv_coef(void) | |||
| 806 | 672 | ||
| 807 | ct = &ctbl_bt601_5; | 673 | ct = &ctbl_bt601_5; |
| 808 | 674 | ||
| 809 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0), | 675 | for (i = 1; i < dss_feat_get_num_ovls(); i++) { |
| 810 | CVAL(ct->rcr, ct->ry)); | 676 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0), |
| 811 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1), | 677 | CVAL(ct->rcr, ct->ry)); |
| 812 | CVAL(ct->gy, ct->rcb)); | 678 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1), |
| 813 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2), | 679 | CVAL(ct->gy, ct->rcb)); |
| 814 | CVAL(ct->gcb, ct->gcr)); | 680 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2), |
| 815 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3), | 681 | CVAL(ct->gcb, ct->gcr)); |
| 816 | CVAL(ct->bcr, ct->by)); | 682 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3), |
| 817 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4), | 683 | CVAL(ct->bcr, ct->by)); |
| 818 | CVAL(0, ct->bcb)); | 684 | dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4), |
| 819 | 685 | CVAL(0, ct->bcb)); | |
| 820 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0), | ||
| 821 | CVAL(ct->rcr, ct->ry)); | ||
| 822 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1), | ||
| 823 | CVAL(ct->gy, ct->rcb)); | ||
| 824 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2), | ||
| 825 | CVAL(ct->gcb, ct->gcr)); | ||
| 826 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3), | ||
| 827 | CVAL(ct->bcr, ct->by)); | ||
| 828 | dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4), | ||
| 829 | CVAL(0, ct->bcb)); | ||
| 830 | 686 | ||
| 831 | #undef CVAL | 687 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range, |
| 688 | 11, 11); | ||
| 689 | } | ||
| 832 | 690 | ||
| 833 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1), | 691 | #undef CVAL |
| 834 | ct->full_range, 11, 11); | ||
| 835 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2), | ||
| 836 | ct->full_range, 11, 11); | ||
| 837 | } | 692 | } |
| 838 | 693 | ||
| 839 | 694 | ||
| 840 | static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) | 695 | static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) |
| 841 | { | 696 | { |
| 842 | dispc_write_reg(DISPC_OVL_BA0(plane), paddr); | 697 | dispc_write_reg(DISPC_OVL_BA0(plane), paddr); |
| 843 | } | 698 | } |
| 844 | 699 | ||
| 845 | static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) | 700 | static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr) |
| 846 | { | 701 | { |
| 847 | dispc_write_reg(DISPC_OVL_BA1(plane), paddr); | 702 | dispc_write_reg(DISPC_OVL_BA1(plane), paddr); |
| 848 | } | 703 | } |
| 849 | 704 | ||
| 850 | static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr) | 705 | static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr) |
| 851 | { | 706 | { |
| 852 | dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); | 707 | dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); |
| 853 | } | 708 | } |
| 854 | 709 | ||
| 855 | static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr) | 710 | static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr) |
| 856 | { | 711 | { |
| 857 | dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); | 712 | dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); |
| 858 | } | 713 | } |
| 859 | 714 | ||
| 860 | static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) | 715 | static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) |
| 861 | { | 716 | { |
| 862 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); | 717 | u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); |
| 863 | 718 | ||
| 864 | dispc_write_reg(DISPC_OVL_POSITION(plane), val); | 719 | dispc_write_reg(DISPC_OVL_POSITION(plane), val); |
| 865 | } | 720 | } |
| 866 | 721 | ||
| 867 | static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) | 722 | static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) |
| 868 | { | 723 | { |
| 869 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); | 724 | u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); |
| 870 | 725 | ||
| @@ -874,7 +729,7 @@ static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) | |||
| 874 | dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); | 729 | dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); |
| 875 | } | 730 | } |
| 876 | 731 | ||
| 877 | static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | 732 | static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) |
| 878 | { | 733 | { |
| 879 | u32 val; | 734 | u32 val; |
| 880 | 735 | ||
| @@ -885,44 +740,61 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) | |||
| 885 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); | 740 | dispc_write_reg(DISPC_OVL_SIZE(plane), val); |
| 886 | } | 741 | } |
| 887 | 742 | ||
| 888 | static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable) | 743 | static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) |
| 889 | { | 744 | { |
| 890 | if (!dss_has_feature(FEAT_PRE_MULT_ALPHA)) | 745 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
| 746 | |||
| 747 | if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) | ||
| 891 | return; | 748 | return; |
| 892 | 749 | ||
| 893 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 750 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); |
| 894 | plane == OMAP_DSS_VIDEO1) | 751 | } |
| 752 | |||
| 753 | static void dispc_ovl_enable_zorder_planes(void) | ||
| 754 | { | ||
| 755 | int i; | ||
| 756 | |||
| 757 | if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) | ||
| 895 | return; | 758 | return; |
| 896 | 759 | ||
| 897 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); | 760 | for (i = 0; i < dss_feat_get_num_ovls(); i++) |
| 761 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); | ||
| 898 | } | 762 | } |
| 899 | 763 | ||
| 900 | static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | 764 | static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) |
| 901 | { | 765 | { |
| 902 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 766 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
| 767 | |||
| 768 | if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) | ||
| 903 | return; | 769 | return; |
| 904 | 770 | ||
| 905 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 771 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); |
| 906 | plane == OMAP_DSS_VIDEO1) | 772 | } |
| 773 | |||
| 774 | static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | ||
| 775 | { | ||
| 776 | static const unsigned shifts[] = { 0, 8, 16, 24, }; | ||
| 777 | int shift; | ||
| 778 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | ||
| 779 | |||
| 780 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) | ||
| 907 | return; | 781 | return; |
| 908 | 782 | ||
| 909 | if (plane == OMAP_DSS_GFX) | 783 | shift = shifts[plane]; |
| 910 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); | 784 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift); |
| 911 | else if (plane == OMAP_DSS_VIDEO2) | ||
| 912 | REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); | ||
| 913 | } | 785 | } |
| 914 | 786 | ||
| 915 | static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) | 787 | static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc) |
| 916 | { | 788 | { |
| 917 | dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); | 789 | dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); |
| 918 | } | 790 | } |
| 919 | 791 | ||
| 920 | static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) | 792 | static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc) |
| 921 | { | 793 | { |
| 922 | dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); | 794 | dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); |
| 923 | } | 795 | } |
| 924 | 796 | ||
| 925 | static void _dispc_set_color_mode(enum omap_plane plane, | 797 | static void dispc_ovl_set_color_mode(enum omap_plane plane, |
| 926 | enum omap_color_mode color_mode) | 798 | enum omap_color_mode color_mode) |
| 927 | { | 799 | { |
| 928 | u32 m = 0; | 800 | u32 m = 0; |
| @@ -1003,7 +875,7 @@ static void _dispc_set_color_mode(enum omap_plane plane, | |||
| 1003 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); | 875 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); |
| 1004 | } | 876 | } |
| 1005 | 877 | ||
| 1006 | void dispc_set_channel_out(enum omap_plane plane, | 878 | static void dispc_ovl_set_channel_out(enum omap_plane plane, |
| 1007 | enum omap_channel channel) | 879 | enum omap_channel channel) |
| 1008 | { | 880 | { |
| 1009 | int shift; | 881 | int shift; |
| @@ -1016,6 +888,7 @@ void dispc_set_channel_out(enum omap_plane plane, | |||
| 1016 | break; | 888 | break; |
| 1017 | case OMAP_DSS_VIDEO1: | 889 | case OMAP_DSS_VIDEO1: |
| 1018 | case OMAP_DSS_VIDEO2: | 890 | case OMAP_DSS_VIDEO2: |
| 891 | case OMAP_DSS_VIDEO3: | ||
| 1019 | shift = 16; | 892 | shift = 16; |
| 1020 | break; | 893 | break; |
| 1021 | default: | 894 | default: |
| @@ -1050,24 +923,13 @@ void dispc_set_channel_out(enum omap_plane plane, | |||
| 1050 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); | 923 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
| 1051 | } | 924 | } |
| 1052 | 925 | ||
| 1053 | static void dispc_set_burst_size(enum omap_plane plane, | 926 | static void dispc_ovl_set_burst_size(enum omap_plane plane, |
| 1054 | enum omap_burst_size burst_size) | 927 | enum omap_burst_size burst_size) |
| 1055 | { | 928 | { |
| 929 | static const unsigned shifts[] = { 6, 14, 14, 14, }; | ||
| 1056 | int shift; | 930 | int shift; |
| 1057 | 931 | ||
| 1058 | switch (plane) { | 932 | shift = shifts[plane]; |
| 1059 | case OMAP_DSS_GFX: | ||
| 1060 | shift = 6; | ||
| 1061 | break; | ||
| 1062 | case OMAP_DSS_VIDEO1: | ||
| 1063 | case OMAP_DSS_VIDEO2: | ||
| 1064 | shift = 14; | ||
| 1065 | break; | ||
| 1066 | default: | ||
| 1067 | BUG(); | ||
| 1068 | return; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); | 933 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); |
| 1072 | } | 934 | } |
| 1073 | 935 | ||
| @@ -1078,10 +940,10 @@ static void dispc_configure_burst_sizes(void) | |||
| 1078 | 940 | ||
| 1079 | /* Configure burst size always to maximum size */ | 941 | /* Configure burst size always to maximum size */ |
| 1080 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) | 942 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) |
| 1081 | dispc_set_burst_size(i, burst_size); | 943 | dispc_ovl_set_burst_size(i, burst_size); |
| 1082 | } | 944 | } |
| 1083 | 945 | ||
| 1084 | u32 dispc_get_burst_size(enum omap_plane plane) | 946 | u32 dispc_ovl_get_burst_size(enum omap_plane plane) |
| 1085 | { | 947 | { |
| 1086 | unsigned unit = dss_feat_get_burst_size_unit(); | 948 | unsigned unit = dss_feat_get_burst_size_unit(); |
| 1087 | /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ | 949 | /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ |
| @@ -1102,7 +964,7 @@ void dispc_enable_gamma_table(bool enable) | |||
| 1102 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); | 964 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); |
| 1103 | } | 965 | } |
| 1104 | 966 | ||
| 1105 | void dispc_enable_cpr(enum omap_channel channel, bool enable) | 967 | void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) |
| 1106 | { | 968 | { |
| 1107 | u16 reg; | 969 | u16 reg; |
| 1108 | 970 | ||
| @@ -1116,12 +978,12 @@ void dispc_enable_cpr(enum omap_channel channel, bool enable) | |||
| 1116 | REG_FLD_MOD(reg, enable, 15, 15); | 978 | REG_FLD_MOD(reg, enable, 15, 15); |
| 1117 | } | 979 | } |
| 1118 | 980 | ||
| 1119 | void dispc_set_cpr_coef(enum omap_channel channel, | 981 | void dispc_mgr_set_cpr_coef(enum omap_channel channel, |
| 1120 | struct omap_dss_cpr_coefs *coefs) | 982 | struct omap_dss_cpr_coefs *coefs) |
| 1121 | { | 983 | { |
| 1122 | u32 coef_r, coef_g, coef_b; | 984 | u32 coef_r, coef_g, coef_b; |
| 1123 | 985 | ||
| 1124 | if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2) | 986 | if (!dispc_mgr_is_lcd(channel)) |
| 1125 | return; | 987 | return; |
| 1126 | 988 | ||
| 1127 | coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | | 989 | coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | |
| @@ -1136,7 +998,7 @@ void dispc_set_cpr_coef(enum omap_channel channel, | |||
| 1136 | dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); | 998 | dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); |
| 1137 | } | 999 | } |
| 1138 | 1000 | ||
| 1139 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | 1001 | static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable) |
| 1140 | { | 1002 | { |
| 1141 | u32 val; | 1003 | u32 val; |
| 1142 | 1004 | ||
| @@ -1147,19 +1009,16 @@ static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | |||
| 1147 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); | 1009 | dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); |
| 1148 | } | 1010 | } |
| 1149 | 1011 | ||
| 1150 | void dispc_enable_replication(enum omap_plane plane, bool enable) | 1012 | static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) |
| 1151 | { | 1013 | { |
| 1152 | int bit; | 1014 | static const unsigned shifts[] = { 5, 10, 10, 10 }; |
| 1153 | 1015 | int shift; | |
| 1154 | if (plane == OMAP_DSS_GFX) | ||
| 1155 | bit = 5; | ||
| 1156 | else | ||
| 1157 | bit = 10; | ||
| 1158 | 1016 | ||
| 1159 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); | 1017 | shift = shifts[plane]; |
| 1018 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); | ||
| 1160 | } | 1019 | } |
| 1161 | 1020 | ||
| 1162 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height) | 1021 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height) |
| 1163 | { | 1022 | { |
| 1164 | u32 val; | 1023 | u32 val; |
| 1165 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); | 1024 | BUG_ON((width > (1 << 11)) || (height > (1 << 11))); |
| @@ -1186,19 +1045,20 @@ static void dispc_read_plane_fifo_sizes(void) | |||
| 1186 | 1045 | ||
| 1187 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); | 1046 | dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); |
| 1188 | 1047 | ||
| 1189 | for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { | 1048 | for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) { |
| 1190 | size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); | 1049 | size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); |
| 1191 | size *= unit; | 1050 | size *= unit; |
| 1192 | dispc.fifo_size[plane] = size; | 1051 | dispc.fifo_size[plane] = size; |
| 1193 | } | 1052 | } |
| 1194 | } | 1053 | } |
| 1195 | 1054 | ||
| 1196 | u32 dispc_get_plane_fifo_size(enum omap_plane plane) | 1055 | u32 dispc_ovl_get_fifo_size(enum omap_plane plane) |
| 1197 | { | 1056 | { |
| 1198 | return dispc.fifo_size[plane]; | 1057 | return dispc.fifo_size[plane]; |
| 1199 | } | 1058 | } |
| 1200 | 1059 | ||
| 1201 | void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) | 1060 | static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, |
| 1061 | u32 high) | ||
| 1202 | { | 1062 | { |
| 1203 | u8 hi_start, hi_end, lo_start, lo_end; | 1063 | u8 hi_start, hi_end, lo_start, lo_end; |
| 1204 | u32 unit; | 1064 | u32 unit; |
| @@ -1233,7 +1093,7 @@ void dispc_enable_fifomerge(bool enable) | |||
| 1233 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); | 1093 | REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); |
| 1234 | } | 1094 | } |
| 1235 | 1095 | ||
| 1236 | static void _dispc_set_fir(enum omap_plane plane, | 1096 | static void dispc_ovl_set_fir(enum omap_plane plane, |
| 1237 | int hinc, int vinc, | 1097 | int hinc, int vinc, |
| 1238 | enum omap_color_component color_comp) | 1098 | enum omap_color_component color_comp) |
| 1239 | { | 1099 | { |
| @@ -1256,7 +1116,7 @@ static void _dispc_set_fir(enum omap_plane plane, | |||
| 1256 | } | 1116 | } |
| 1257 | } | 1117 | } |
| 1258 | 1118 | ||
| 1259 | static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | 1119 | static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) |
| 1260 | { | 1120 | { |
| 1261 | u32 val; | 1121 | u32 val; |
| 1262 | u8 hor_start, hor_end, vert_start, vert_end; | 1122 | u8 hor_start, hor_end, vert_start, vert_end; |
| @@ -1270,7 +1130,7 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | |||
| 1270 | dispc_write_reg(DISPC_OVL_ACCU0(plane), val); | 1130 | dispc_write_reg(DISPC_OVL_ACCU0(plane), val); |
| 1271 | } | 1131 | } |
| 1272 | 1132 | ||
| 1273 | static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | 1133 | static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) |
| 1274 | { | 1134 | { |
| 1275 | u32 val; | 1135 | u32 val; |
| 1276 | u8 hor_start, hor_end, vert_start, vert_end; | 1136 | u8 hor_start, hor_end, vert_start, vert_end; |
| @@ -1284,7 +1144,8 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | |||
| 1284 | dispc_write_reg(DISPC_OVL_ACCU1(plane), val); | 1144 | dispc_write_reg(DISPC_OVL_ACCU1(plane), val); |
| 1285 | } | 1145 | } |
| 1286 | 1146 | ||
| 1287 | static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) | 1147 | static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu, |
| 1148 | int vaccu) | ||
| 1288 | { | 1149 | { |
| 1289 | u32 val; | 1150 | u32 val; |
| 1290 | 1151 | ||
| @@ -1292,7 +1153,8 @@ static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu) | |||
| 1292 | dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); | 1153 | dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); |
| 1293 | } | 1154 | } |
| 1294 | 1155 | ||
| 1295 | static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) | 1156 | static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu, |
| 1157 | int vaccu) | ||
| 1296 | { | 1158 | { |
| 1297 | u32 val; | 1159 | u32 val; |
| 1298 | 1160 | ||
| @@ -1300,7 +1162,7 @@ static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu) | |||
| 1300 | dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); | 1162 | dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); |
| 1301 | } | 1163 | } |
| 1302 | 1164 | ||
| 1303 | static void _dispc_set_scale_param(enum omap_plane plane, | 1165 | static void dispc_ovl_set_scale_param(enum omap_plane plane, |
| 1304 | u16 orig_width, u16 orig_height, | 1166 | u16 orig_width, u16 orig_height, |
| 1305 | u16 out_width, u16 out_height, | 1167 | u16 out_width, u16 out_height, |
| 1306 | bool five_taps, u8 rotation, | 1168 | bool five_taps, u8 rotation, |
| @@ -1312,15 +1174,16 @@ static void _dispc_set_scale_param(enum omap_plane plane, | |||
| 1312 | hscaleup = orig_width <= out_width; | 1174 | hscaleup = orig_width <= out_width; |
| 1313 | vscaleup = orig_height <= out_height; | 1175 | vscaleup = orig_height <= out_height; |
| 1314 | 1176 | ||
| 1315 | _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp); | 1177 | dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps, |
| 1178 | color_comp); | ||
| 1316 | 1179 | ||
| 1317 | fir_hinc = 1024 * orig_width / out_width; | 1180 | fir_hinc = 1024 * orig_width / out_width; |
| 1318 | fir_vinc = 1024 * orig_height / out_height; | 1181 | fir_vinc = 1024 * orig_height / out_height; |
| 1319 | 1182 | ||
| 1320 | _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp); | 1183 | dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); |
| 1321 | } | 1184 | } |
| 1322 | 1185 | ||
| 1323 | static void _dispc_set_scaling_common(enum omap_plane plane, | 1186 | static void dispc_ovl_set_scaling_common(enum omap_plane plane, |
| 1324 | u16 orig_width, u16 orig_height, | 1187 | u16 orig_width, u16 orig_height, |
| 1325 | u16 out_width, u16 out_height, | 1188 | u16 out_width, u16 out_height, |
| 1326 | bool ilace, bool five_taps, | 1189 | bool ilace, bool five_taps, |
| @@ -1331,7 +1194,7 @@ static void _dispc_set_scaling_common(enum omap_plane plane, | |||
| 1331 | int accu1 = 0; | 1194 | int accu1 = 0; |
| 1332 | u32 l; | 1195 | u32 l; |
| 1333 | 1196 | ||
| 1334 | _dispc_set_scale_param(plane, orig_width, orig_height, | 1197 | dispc_ovl_set_scale_param(plane, orig_width, orig_height, |
| 1335 | out_width, out_height, five_taps, | 1198 | out_width, out_height, five_taps, |
| 1336 | rotation, DISPC_COLOR_COMPONENT_RGB_Y); | 1199 | rotation, DISPC_COLOR_COMPONENT_RGB_Y); |
| 1337 | l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); | 1200 | l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); |
| @@ -1370,11 +1233,11 @@ static void _dispc_set_scaling_common(enum omap_plane plane, | |||
| 1370 | } | 1233 | } |
| 1371 | } | 1234 | } |
| 1372 | 1235 | ||
| 1373 | _dispc_set_vid_accu0(plane, 0, accu0); | 1236 | dispc_ovl_set_vid_accu0(plane, 0, accu0); |
| 1374 | _dispc_set_vid_accu1(plane, 0, accu1); | 1237 | dispc_ovl_set_vid_accu1(plane, 0, accu1); |
| 1375 | } | 1238 | } |
| 1376 | 1239 | ||
| 1377 | static void _dispc_set_scaling_uv(enum omap_plane plane, | 1240 | static void dispc_ovl_set_scaling_uv(enum omap_plane plane, |
| 1378 | u16 orig_width, u16 orig_height, | 1241 | u16 orig_width, u16 orig_height, |
| 1379 | u16 out_width, u16 out_height, | 1242 | u16 out_width, u16 out_height, |
| 1380 | bool ilace, bool five_taps, | 1243 | bool ilace, bool five_taps, |
| @@ -1422,7 +1285,7 @@ static void _dispc_set_scaling_uv(enum omap_plane plane, | |||
| 1422 | if (out_height != orig_height) | 1285 | if (out_height != orig_height) |
| 1423 | scale_y = true; | 1286 | scale_y = true; |
| 1424 | 1287 | ||
| 1425 | _dispc_set_scale_param(plane, orig_width, orig_height, | 1288 | dispc_ovl_set_scale_param(plane, orig_width, orig_height, |
| 1426 | out_width, out_height, five_taps, | 1289 | out_width, out_height, five_taps, |
| 1427 | rotation, DISPC_COLOR_COMPONENT_UV); | 1290 | rotation, DISPC_COLOR_COMPONENT_UV); |
| 1428 | 1291 | ||
| @@ -1433,11 +1296,11 @@ static void _dispc_set_scaling_uv(enum omap_plane plane, | |||
| 1433 | /* set V scaling */ | 1296 | /* set V scaling */ |
| 1434 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); | 1297 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); |
| 1435 | 1298 | ||
| 1436 | _dispc_set_vid_accu2_0(plane, 0x80, 0); | 1299 | dispc_ovl_set_vid_accu2_0(plane, 0x80, 0); |
| 1437 | _dispc_set_vid_accu2_1(plane, 0x80, 0); | 1300 | dispc_ovl_set_vid_accu2_1(plane, 0x80, 0); |
| 1438 | } | 1301 | } |
| 1439 | 1302 | ||
| 1440 | static void _dispc_set_scaling(enum omap_plane plane, | 1303 | static void dispc_ovl_set_scaling(enum omap_plane plane, |
| 1441 | u16 orig_width, u16 orig_height, | 1304 | u16 orig_width, u16 orig_height, |
| 1442 | u16 out_width, u16 out_height, | 1305 | u16 out_width, u16 out_height, |
| 1443 | bool ilace, bool five_taps, | 1306 | bool ilace, bool five_taps, |
| @@ -1446,14 +1309,14 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
| 1446 | { | 1309 | { |
| 1447 | BUG_ON(plane == OMAP_DSS_GFX); | 1310 | BUG_ON(plane == OMAP_DSS_GFX); |
| 1448 | 1311 | ||
| 1449 | _dispc_set_scaling_common(plane, | 1312 | dispc_ovl_set_scaling_common(plane, |
| 1450 | orig_width, orig_height, | 1313 | orig_width, orig_height, |
| 1451 | out_width, out_height, | 1314 | out_width, out_height, |
| 1452 | ilace, five_taps, | 1315 | ilace, five_taps, |
| 1453 | fieldmode, color_mode, | 1316 | fieldmode, color_mode, |
| 1454 | rotation); | 1317 | rotation); |
| 1455 | 1318 | ||
| 1456 | _dispc_set_scaling_uv(plane, | 1319 | dispc_ovl_set_scaling_uv(plane, |
| 1457 | orig_width, orig_height, | 1320 | orig_width, orig_height, |
| 1458 | out_width, out_height, | 1321 | out_width, out_height, |
| 1459 | ilace, five_taps, | 1322 | ilace, five_taps, |
| @@ -1461,7 +1324,7 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
| 1461 | rotation); | 1324 | rotation); |
| 1462 | } | 1325 | } |
| 1463 | 1326 | ||
| 1464 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1327 | static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
| 1465 | bool mirroring, enum omap_color_mode color_mode) | 1328 | bool mirroring, enum omap_color_mode color_mode) |
| 1466 | { | 1329 | { |
| 1467 | bool row_repeat = false; | 1330 | bool row_repeat = false; |
| @@ -1789,12 +1652,11 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, | |||
| 1789 | enum omap_color_mode color_mode) | 1652 | enum omap_color_mode color_mode) |
| 1790 | { | 1653 | { |
| 1791 | u32 fclk = 0; | 1654 | u32 fclk = 0; |
| 1792 | /* FIXME venc pclk? */ | 1655 | u64 tmp, pclk = dispc_mgr_pclk_rate(channel); |
| 1793 | u64 tmp, pclk = dispc_pclk_rate(channel); | ||
| 1794 | 1656 | ||
| 1795 | if (height > out_height) { | 1657 | if (height > out_height) { |
| 1796 | /* FIXME get real display PPL */ | 1658 | struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); |
| 1797 | unsigned int ppl = 800; | 1659 | unsigned int ppl = dssdev->panel.timings.x_res; |
| 1798 | 1660 | ||
| 1799 | tmp = pclk * height * out_width; | 1661 | tmp = pclk * height * out_width; |
| 1800 | do_div(tmp, 2 * out_height * ppl); | 1662 | do_div(tmp, 2 * out_height * ppl); |
| @@ -1846,114 +1708,120 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width, | |||
| 1846 | else | 1708 | else |
| 1847 | vf = 1; | 1709 | vf = 1; |
| 1848 | 1710 | ||
| 1849 | /* FIXME venc pclk? */ | 1711 | return dispc_mgr_pclk_rate(channel) * vf * hf; |
| 1850 | return dispc_pclk_rate(channel) * vf * hf; | ||
| 1851 | } | 1712 | } |
| 1852 | 1713 | ||
| 1853 | int dispc_setup_plane(enum omap_plane plane, | 1714 | static int dispc_ovl_calc_scaling(enum omap_plane plane, |
| 1854 | u32 paddr, u16 screen_width, | 1715 | enum omap_channel channel, u16 width, u16 height, |
| 1855 | u16 pos_x, u16 pos_y, | ||
| 1856 | u16 width, u16 height, | ||
| 1857 | u16 out_width, u16 out_height, | 1716 | u16 out_width, u16 out_height, |
| 1858 | enum omap_color_mode color_mode, | 1717 | enum omap_color_mode color_mode, bool *five_taps) |
| 1859 | bool ilace, | 1718 | { |
| 1860 | enum omap_dss_rotation_type rotation_type, | 1719 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); |
| 1861 | u8 rotation, bool mirror, | 1720 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
| 1862 | u8 global_alpha, u8 pre_mult_alpha, | 1721 | unsigned long fclk = 0; |
| 1863 | enum omap_channel channel, u32 puv_addr) | ||
| 1864 | { | ||
| 1865 | const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; | ||
| 1866 | bool five_taps = 0; | ||
| 1867 | bool fieldmode = 0; | ||
| 1868 | int cconv = 0; | ||
| 1869 | unsigned offset0, offset1; | ||
| 1870 | s32 row_inc; | ||
| 1871 | s32 pix_inc; | ||
| 1872 | u16 frame_height = height; | ||
| 1873 | unsigned int field_offset = 0; | ||
| 1874 | 1722 | ||
| 1875 | DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " | 1723 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { |
| 1876 | "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n", | 1724 | if (width != out_width || height != out_height) |
| 1877 | plane, paddr, screen_width, pos_x, pos_y, | 1725 | return -EINVAL; |
| 1878 | width, height, | 1726 | else |
| 1879 | out_width, out_height, | 1727 | return 0; |
| 1880 | ilace, color_mode, | 1728 | } |
| 1881 | rotation, mirror, channel); | ||
| 1882 | 1729 | ||
| 1883 | if (paddr == 0) | 1730 | if (out_width < width / maxdownscale || |
| 1731 | out_width > width * 8) | ||
| 1884 | return -EINVAL; | 1732 | return -EINVAL; |
| 1885 | 1733 | ||
| 1886 | if (ilace && height == out_height) | 1734 | if (out_height < height / maxdownscale || |
| 1887 | fieldmode = 1; | 1735 | out_height > height * 8) |
| 1736 | return -EINVAL; | ||
| 1888 | 1737 | ||
| 1889 | if (ilace) { | 1738 | /* Must use 5-tap filter? */ |
| 1890 | if (fieldmode) | 1739 | *five_taps = height > out_height * 2; |
| 1891 | height /= 2; | ||
| 1892 | pos_y /= 2; | ||
| 1893 | out_height /= 2; | ||
| 1894 | 1740 | ||
| 1895 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " | 1741 | if (!*five_taps) { |
| 1896 | "out_height %d\n", | 1742 | fclk = calc_fclk(channel, width, height, out_width, |
| 1897 | height, pos_y, out_height); | 1743 | out_height); |
| 1744 | |||
| 1745 | /* Try 5-tap filter if 3-tap fclk is too high */ | ||
| 1746 | if (cpu_is_omap34xx() && height > out_height && | ||
| 1747 | fclk > dispc_fclk_rate()) | ||
| 1748 | *five_taps = true; | ||
| 1898 | } | 1749 | } |
| 1899 | 1750 | ||
| 1900 | if (!dss_feat_color_mode_supported(plane, color_mode)) | 1751 | if (width > (2048 >> *five_taps)) { |
| 1752 | DSSERR("failed to set up scaling, fclk too low\n"); | ||
| 1901 | return -EINVAL; | 1753 | return -EINVAL; |
| 1754 | } | ||
| 1902 | 1755 | ||
| 1903 | if (plane == OMAP_DSS_GFX) { | 1756 | if (*five_taps) |
| 1904 | if (width != out_width || height != out_height) | 1757 | fclk = calc_fclk_five_taps(channel, width, height, |
| 1905 | return -EINVAL; | 1758 | out_width, out_height, color_mode); |
| 1906 | } else { | ||
| 1907 | /* video plane */ | ||
| 1908 | 1759 | ||
| 1909 | unsigned long fclk = 0; | 1760 | DSSDBG("required fclk rate = %lu Hz\n", fclk); |
| 1761 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | ||
| 1910 | 1762 | ||
| 1911 | if (out_width < width / maxdownscale || | 1763 | if (!fclk || fclk > dispc_fclk_rate()) { |
| 1912 | out_width > width * 8) | 1764 | DSSERR("failed to set up scaling, " |
| 1913 | return -EINVAL; | 1765 | "required fclk rate = %lu Hz, " |
| 1766 | "current fclk rate = %lu Hz\n", | ||
| 1767 | fclk, dispc_fclk_rate()); | ||
| 1768 | return -EINVAL; | ||
| 1769 | } | ||
| 1914 | 1770 | ||
| 1915 | if (out_height < height / maxdownscale || | 1771 | return 0; |
| 1916 | out_height > height * 8) | 1772 | } |
| 1917 | return -EINVAL; | ||
| 1918 | 1773 | ||
| 1919 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 1774 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, |
| 1920 | color_mode == OMAP_DSS_COLOR_UYVY || | 1775 | bool ilace, enum omap_channel channel, bool replication, |
| 1921 | color_mode == OMAP_DSS_COLOR_NV12) | 1776 | u32 fifo_low, u32 fifo_high) |
| 1922 | cconv = 1; | 1777 | { |
| 1778 | struct omap_overlay *ovl = omap_dss_get_overlay(plane); | ||
| 1779 | bool five_taps = false; | ||
| 1780 | bool fieldmode = 0; | ||
| 1781 | int r, cconv = 0; | ||
| 1782 | unsigned offset0, offset1; | ||
| 1783 | s32 row_inc; | ||
| 1784 | s32 pix_inc; | ||
| 1785 | u16 frame_height = oi->height; | ||
| 1786 | unsigned int field_offset = 0; | ||
| 1923 | 1787 | ||
| 1924 | /* Must use 5-tap filter? */ | 1788 | DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " |
| 1925 | five_taps = height > out_height * 2; | 1789 | "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " |
| 1790 | "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr, | ||
| 1791 | oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, | ||
| 1792 | oi->out_width, oi->out_height, oi->color_mode, oi->rotation, | ||
| 1793 | oi->mirror, ilace, channel, replication, fifo_low, fifo_high); | ||
| 1926 | 1794 | ||
| 1927 | if (!five_taps) { | 1795 | if (oi->paddr == 0) |
| 1928 | fclk = calc_fclk(channel, width, height, out_width, | 1796 | return -EINVAL; |
| 1929 | out_height); | ||
| 1930 | 1797 | ||
| 1931 | /* Try 5-tap filter if 3-tap fclk is too high */ | 1798 | if (ilace && oi->height == oi->out_height) |
| 1932 | if (cpu_is_omap34xx() && height > out_height && | 1799 | fieldmode = 1; |
| 1933 | fclk > dispc_fclk_rate()) | ||
| 1934 | five_taps = true; | ||
| 1935 | } | ||
| 1936 | 1800 | ||
| 1937 | if (width > (2048 >> five_taps)) { | 1801 | if (ilace) { |
| 1938 | DSSERR("failed to set up scaling, fclk too low\n"); | 1802 | if (fieldmode) |
| 1939 | return -EINVAL; | 1803 | oi->height /= 2; |
| 1940 | } | 1804 | oi->pos_y /= 2; |
| 1805 | oi->out_height /= 2; | ||
| 1941 | 1806 | ||
| 1942 | if (five_taps) | 1807 | DSSDBG("adjusting for ilace: height %d, pos_y %d, " |
| 1943 | fclk = calc_fclk_five_taps(channel, width, height, | 1808 | "out_height %d\n", |
| 1944 | out_width, out_height, color_mode); | 1809 | oi->height, oi->pos_y, oi->out_height); |
| 1810 | } | ||
| 1945 | 1811 | ||
| 1946 | DSSDBG("required fclk rate = %lu Hz\n", fclk); | 1812 | if (!dss_feat_color_mode_supported(plane, oi->color_mode)) |
| 1947 | DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); | 1813 | return -EINVAL; |
| 1948 | 1814 | ||
| 1949 | if (!fclk || fclk > dispc_fclk_rate()) { | 1815 | r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, |
| 1950 | DSSERR("failed to set up scaling, " | 1816 | oi->out_width, oi->out_height, oi->color_mode, |
| 1951 | "required fclk rate = %lu Hz, " | 1817 | &five_taps); |
| 1952 | "current fclk rate = %lu Hz\n", | 1818 | if (r) |
| 1953 | fclk, dispc_fclk_rate()); | 1819 | return r; |
| 1954 | return -EINVAL; | 1820 | |
| 1955 | } | 1821 | if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || |
| 1956 | } | 1822 | oi->color_mode == OMAP_DSS_COLOR_UYVY || |
| 1823 | oi->color_mode == OMAP_DSS_COLOR_NV12) | ||
| 1824 | cconv = 1; | ||
| 1957 | 1825 | ||
| 1958 | if (ilace && !fieldmode) { | 1826 | if (ilace && !fieldmode) { |
| 1959 | /* | 1827 | /* |
| @@ -1963,69 +1831,76 @@ int dispc_setup_plane(enum omap_plane plane, | |||
| 1963 | * so the integer part must be added to the base address of the | 1831 | * so the integer part must be added to the base address of the |
| 1964 | * bottom field. | 1832 | * bottom field. |
| 1965 | */ | 1833 | */ |
| 1966 | if (!height || height == out_height) | 1834 | if (!oi->height || oi->height == oi->out_height) |
| 1967 | field_offset = 0; | 1835 | field_offset = 0; |
| 1968 | else | 1836 | else |
| 1969 | field_offset = height / out_height / 2; | 1837 | field_offset = oi->height / oi->out_height / 2; |
| 1970 | } | 1838 | } |
| 1971 | 1839 | ||
| 1972 | /* Fields are independent but interleaved in memory. */ | 1840 | /* Fields are independent but interleaved in memory. */ |
| 1973 | if (fieldmode) | 1841 | if (fieldmode) |
| 1974 | field_offset = 1; | 1842 | field_offset = 1; |
| 1975 | 1843 | ||
| 1976 | if (rotation_type == OMAP_DSS_ROT_DMA) | 1844 | if (oi->rotation_type == OMAP_DSS_ROT_DMA) |
| 1977 | calc_dma_rotation_offset(rotation, mirror, | 1845 | calc_dma_rotation_offset(oi->rotation, oi->mirror, |
| 1978 | screen_width, width, frame_height, color_mode, | 1846 | oi->screen_width, oi->width, frame_height, |
| 1979 | fieldmode, field_offset, | 1847 | oi->color_mode, fieldmode, field_offset, |
| 1980 | &offset0, &offset1, &row_inc, &pix_inc); | 1848 | &offset0, &offset1, &row_inc, &pix_inc); |
| 1981 | else | 1849 | else |
| 1982 | calc_vrfb_rotation_offset(rotation, mirror, | 1850 | calc_vrfb_rotation_offset(oi->rotation, oi->mirror, |
| 1983 | screen_width, width, frame_height, color_mode, | 1851 | oi->screen_width, oi->width, frame_height, |
| 1984 | fieldmode, field_offset, | 1852 | oi->color_mode, fieldmode, field_offset, |
| 1985 | &offset0, &offset1, &row_inc, &pix_inc); | 1853 | &offset0, &offset1, &row_inc, &pix_inc); |
| 1986 | 1854 | ||
| 1987 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", | 1855 | DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", |
| 1988 | offset0, offset1, row_inc, pix_inc); | 1856 | offset0, offset1, row_inc, pix_inc); |
| 1989 | 1857 | ||
| 1990 | _dispc_set_color_mode(plane, color_mode); | 1858 | dispc_ovl_set_color_mode(plane, oi->color_mode); |
| 1991 | 1859 | ||
| 1992 | _dispc_set_plane_ba0(plane, paddr + offset0); | 1860 | dispc_ovl_set_ba0(plane, oi->paddr + offset0); |
| 1993 | _dispc_set_plane_ba1(plane, paddr + offset1); | 1861 | dispc_ovl_set_ba1(plane, oi->paddr + offset1); |
| 1994 | 1862 | ||
| 1995 | if (OMAP_DSS_COLOR_NV12 == color_mode) { | 1863 | if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { |
| 1996 | _dispc_set_plane_ba0_uv(plane, puv_addr + offset0); | 1864 | dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); |
| 1997 | _dispc_set_plane_ba1_uv(plane, puv_addr + offset1); | 1865 | dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); |
| 1998 | } | 1866 | } |
| 1999 | 1867 | ||
| 2000 | 1868 | ||
| 2001 | _dispc_set_row_inc(plane, row_inc); | 1869 | dispc_ovl_set_row_inc(plane, row_inc); |
| 2002 | _dispc_set_pix_inc(plane, pix_inc); | 1870 | dispc_ovl_set_pix_inc(plane, pix_inc); |
| 2003 | 1871 | ||
| 2004 | DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, | 1872 | DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, |
| 2005 | out_width, out_height); | 1873 | oi->height, oi->out_width, oi->out_height); |
| 2006 | 1874 | ||
| 2007 | _dispc_set_plane_pos(plane, pos_x, pos_y); | 1875 | dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); |
| 2008 | 1876 | ||
| 2009 | _dispc_set_pic_size(plane, width, height); | 1877 | dispc_ovl_set_pic_size(plane, oi->width, oi->height); |
| 2010 | 1878 | ||
| 2011 | if (plane != OMAP_DSS_GFX) { | 1879 | if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { |
| 2012 | _dispc_set_scaling(plane, width, height, | 1880 | dispc_ovl_set_scaling(plane, oi->width, oi->height, |
| 2013 | out_width, out_height, | 1881 | oi->out_width, oi->out_height, |
| 2014 | ilace, five_taps, fieldmode, | 1882 | ilace, five_taps, fieldmode, |
| 2015 | color_mode, rotation); | 1883 | oi->color_mode, oi->rotation); |
| 2016 | _dispc_set_vid_size(plane, out_width, out_height); | 1884 | dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height); |
| 2017 | _dispc_set_vid_color_conv(plane, cconv); | 1885 | dispc_ovl_set_vid_color_conv(plane, cconv); |
| 2018 | } | 1886 | } |
| 2019 | 1887 | ||
| 2020 | _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); | 1888 | dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, |
| 1889 | oi->color_mode); | ||
| 1890 | |||
| 1891 | dispc_ovl_set_zorder(plane, oi->zorder); | ||
| 1892 | dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); | ||
| 1893 | dispc_ovl_setup_global_alpha(plane, oi->global_alpha); | ||
| 2021 | 1894 | ||
| 2022 | _dispc_set_pre_mult_alpha(plane, pre_mult_alpha); | 1895 | dispc_ovl_set_channel_out(plane, channel); |
| 2023 | _dispc_setup_global_alpha(plane, global_alpha); | 1896 | |
| 1897 | dispc_ovl_enable_replication(plane, replication); | ||
| 1898 | dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high); | ||
| 2024 | 1899 | ||
| 2025 | return 0; | 1900 | return 0; |
| 2026 | } | 1901 | } |
| 2027 | 1902 | ||
| 2028 | int dispc_enable_plane(enum omap_plane plane, bool enable) | 1903 | int dispc_ovl_enable(enum omap_plane plane, bool enable) |
| 2029 | { | 1904 | { |
| 2030 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); | 1905 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); |
| 2031 | 1906 | ||
| @@ -2048,7 +1923,7 @@ static void _enable_lcd_out(enum omap_channel channel, bool enable) | |||
| 2048 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); | 1923 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); |
| 2049 | } | 1924 | } |
| 2050 | 1925 | ||
| 2051 | static void dispc_enable_lcd_out(enum omap_channel channel, bool enable) | 1926 | static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) |
| 2052 | { | 1927 | { |
| 2053 | struct completion frame_done_completion; | 1928 | struct completion frame_done_completion; |
| 2054 | bool is_on; | 1929 | bool is_on; |
| @@ -2095,14 +1970,19 @@ static void _enable_digit_out(bool enable) | |||
| 2095 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); | 1970 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); |
| 2096 | } | 1971 | } |
| 2097 | 1972 | ||
| 2098 | static void dispc_enable_digit_out(bool enable) | 1973 | static void dispc_mgr_enable_digit_out(bool enable) |
| 2099 | { | 1974 | { |
| 2100 | struct completion frame_done_completion; | 1975 | struct completion frame_done_completion; |
| 2101 | int r; | 1976 | enum dss_hdmi_venc_clk_source_select src; |
| 1977 | int r, i; | ||
| 1978 | u32 irq_mask; | ||
| 1979 | int num_irqs; | ||
| 2102 | 1980 | ||
| 2103 | if (REG_GET(DISPC_CONTROL, 1, 1) == enable) | 1981 | if (REG_GET(DISPC_CONTROL, 1, 1) == enable) |
| 2104 | return; | 1982 | return; |
| 2105 | 1983 | ||
| 1984 | src = dss_get_hdmi_venc_clk_source(); | ||
| 1985 | |||
| 2106 | if (enable) { | 1986 | if (enable) { |
| 2107 | unsigned long flags; | 1987 | unsigned long flags; |
| 2108 | /* When we enable digit output, we'll get an extra digit | 1988 | /* When we enable digit output, we'll get an extra digit |
| @@ -2119,43 +1999,47 @@ static void dispc_enable_digit_out(bool enable) | |||
| 2119 | * wait for the extra sync losts */ | 1999 | * wait for the extra sync losts */ |
| 2120 | init_completion(&frame_done_completion); | 2000 | init_completion(&frame_done_completion); |
| 2121 | 2001 | ||
| 2002 | if (src == DSS_HDMI_M_PCLK && enable == false) { | ||
| 2003 | irq_mask = DISPC_IRQ_FRAMEDONETV; | ||
| 2004 | num_irqs = 1; | ||
| 2005 | } else { | ||
| 2006 | irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; | ||
| 2007 | /* XXX I understand from TRM that we should only wait for the | ||
| 2008 | * current field to complete. But it seems we have to wait for | ||
| 2009 | * both fields */ | ||
| 2010 | num_irqs = 2; | ||
| 2011 | } | ||
| 2012 | |||
| 2122 | r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, | 2013 | r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, |
| 2123 | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); | 2014 | irq_mask); |
| 2124 | if (r) | 2015 | if (r) |
| 2125 | DSSERR("failed to register EVSYNC isr\n"); | 2016 | DSSERR("failed to register %x isr\n", irq_mask); |
| 2126 | 2017 | ||
| 2127 | _enable_digit_out(enable); | 2018 | _enable_digit_out(enable); |
| 2128 | 2019 | ||
| 2129 | /* XXX I understand from TRM that we should only wait for the | 2020 | for (i = 0; i < num_irqs; ++i) { |
| 2130 | * current field to complete. But it seems we have to wait | 2021 | if (!wait_for_completion_timeout(&frame_done_completion, |
| 2131 | * for both fields */ | 2022 | msecs_to_jiffies(100))) |
| 2132 | if (!wait_for_completion_timeout(&frame_done_completion, | 2023 | DSSERR("timeout waiting for digit out to %s\n", |
| 2133 | msecs_to_jiffies(100))) | 2024 | enable ? "start" : "stop"); |
| 2134 | DSSERR("timeout waiting for EVSYNC\n"); | 2025 | } |
| 2135 | |||
| 2136 | if (!wait_for_completion_timeout(&frame_done_completion, | ||
| 2137 | msecs_to_jiffies(100))) | ||
| 2138 | DSSERR("timeout waiting for EVSYNC\n"); | ||
| 2139 | 2026 | ||
| 2140 | r = omap_dispc_unregister_isr(dispc_disable_isr, | 2027 | r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion, |
| 2141 | &frame_done_completion, | 2028 | irq_mask); |
| 2142 | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); | ||
| 2143 | if (r) | 2029 | if (r) |
| 2144 | DSSERR("failed to unregister EVSYNC isr\n"); | 2030 | DSSERR("failed to unregister %x isr\n", irq_mask); |
| 2145 | 2031 | ||
| 2146 | if (enable) { | 2032 | if (enable) { |
| 2147 | unsigned long flags; | 2033 | unsigned long flags; |
| 2148 | spin_lock_irqsave(&dispc.irq_lock, flags); | 2034 | spin_lock_irqsave(&dispc.irq_lock, flags); |
| 2149 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 2035 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT; |
| 2150 | if (dss_has_feature(FEAT_MGR_LCD2)) | ||
| 2151 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | ||
| 2152 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); | 2036 | dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); |
| 2153 | _omap_dispc_set_irqs(); | 2037 | _omap_dispc_set_irqs(); |
| 2154 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 2038 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
| 2155 | } | 2039 | } |
| 2156 | } | 2040 | } |
| 2157 | 2041 | ||
| 2158 | bool dispc_is_channel_enabled(enum omap_channel channel) | 2042 | bool dispc_mgr_is_enabled(enum omap_channel channel) |
| 2159 | { | 2043 | { |
| 2160 | if (channel == OMAP_DSS_CHANNEL_LCD) | 2044 | if (channel == OMAP_DSS_CHANNEL_LCD) |
| 2161 | return !!REG_GET(DISPC_CONTROL, 0, 0); | 2045 | return !!REG_GET(DISPC_CONTROL, 0, 0); |
| @@ -2167,13 +2051,12 @@ bool dispc_is_channel_enabled(enum omap_channel channel) | |||
| 2167 | BUG(); | 2051 | BUG(); |
| 2168 | } | 2052 | } |
| 2169 | 2053 | ||
| 2170 | void dispc_enable_channel(enum omap_channel channel, bool enable) | 2054 | void dispc_mgr_enable(enum omap_channel channel, bool enable) |
| 2171 | { | 2055 | { |
| 2172 | if (channel == OMAP_DSS_CHANNEL_LCD || | 2056 | if (dispc_mgr_is_lcd(channel)) |
| 2173 | channel == OMAP_DSS_CHANNEL_LCD2) | 2057 | dispc_mgr_enable_lcd_out(channel, enable); |
| 2174 | dispc_enable_lcd_out(channel, enable); | ||
| 2175 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) | 2058 | else if (channel == OMAP_DSS_CHANNEL_DIGIT) |
| 2176 | dispc_enable_digit_out(enable); | 2059 | dispc_mgr_enable_digit_out(enable); |
| 2177 | else | 2060 | else |
| 2178 | BUG(); | 2061 | BUG(); |
| 2179 | } | 2062 | } |
| @@ -2202,7 +2085,7 @@ void dispc_pck_free_enable(bool enable) | |||
| 2202 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); | 2085 | REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); |
| 2203 | } | 2086 | } |
| 2204 | 2087 | ||
| 2205 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) | 2088 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) |
| 2206 | { | 2089 | { |
| 2207 | if (channel == OMAP_DSS_CHANNEL_LCD2) | 2090 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
| 2208 | REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); | 2091 | REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16); |
| @@ -2211,7 +2094,7 @@ void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable) | |||
| 2211 | } | 2094 | } |
| 2212 | 2095 | ||
| 2213 | 2096 | ||
| 2214 | void dispc_set_lcd_display_type(enum omap_channel channel, | 2097 | void dispc_mgr_set_lcd_display_type(enum omap_channel channel, |
| 2215 | enum omap_lcd_display_type type) | 2098 | enum omap_lcd_display_type type) |
| 2216 | { | 2099 | { |
| 2217 | int mode; | 2100 | int mode; |
| @@ -2242,12 +2125,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode) | |||
| 2242 | } | 2125 | } |
| 2243 | 2126 | ||
| 2244 | 2127 | ||
| 2245 | void dispc_set_default_color(enum omap_channel channel, u32 color) | 2128 | void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) |
| 2246 | { | 2129 | { |
| 2247 | dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); | 2130 | dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); |
| 2248 | } | 2131 | } |
| 2249 | 2132 | ||
| 2250 | u32 dispc_get_default_color(enum omap_channel channel) | 2133 | u32 dispc_mgr_get_default_color(enum omap_channel channel) |
| 2251 | { | 2134 | { |
| 2252 | u32 l; | 2135 | u32 l; |
| 2253 | 2136 | ||
| @@ -2260,7 +2143,7 @@ u32 dispc_get_default_color(enum omap_channel channel) | |||
| 2260 | return l; | 2143 | return l; |
| 2261 | } | 2144 | } |
| 2262 | 2145 | ||
| 2263 | void dispc_set_trans_key(enum omap_channel ch, | 2146 | void dispc_mgr_set_trans_key(enum omap_channel ch, |
| 2264 | enum omap_dss_trans_key_type type, | 2147 | enum omap_dss_trans_key_type type, |
| 2265 | u32 trans_key) | 2148 | u32 trans_key) |
| 2266 | { | 2149 | { |
| @@ -2274,7 +2157,7 @@ void dispc_set_trans_key(enum omap_channel ch, | |||
| 2274 | dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); | 2157 | dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); |
| 2275 | } | 2158 | } |
| 2276 | 2159 | ||
| 2277 | void dispc_get_trans_key(enum omap_channel ch, | 2160 | void dispc_mgr_get_trans_key(enum omap_channel ch, |
| 2278 | enum omap_dss_trans_key_type *type, | 2161 | enum omap_dss_trans_key_type *type, |
| 2279 | u32 *trans_key) | 2162 | u32 *trans_key) |
| 2280 | { | 2163 | { |
| @@ -2293,7 +2176,7 @@ void dispc_get_trans_key(enum omap_channel ch, | |||
| 2293 | *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); | 2176 | *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); |
| 2294 | } | 2177 | } |
| 2295 | 2178 | ||
| 2296 | void dispc_enable_trans_key(enum omap_channel ch, bool enable) | 2179 | void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) |
| 2297 | { | 2180 | { |
| 2298 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2181 | if (ch == OMAP_DSS_CHANNEL_LCD) |
| 2299 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); | 2182 | REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); |
| @@ -2302,39 +2185,36 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable) | |||
| 2302 | else /* OMAP_DSS_CHANNEL_LCD2 */ | 2185 | else /* OMAP_DSS_CHANNEL_LCD2 */ |
| 2303 | REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); | 2186 | REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); |
| 2304 | } | 2187 | } |
| 2305 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) | 2188 | |
| 2189 | void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) | ||
| 2306 | { | 2190 | { |
| 2307 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 2191 | if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) |
| 2308 | return; | 2192 | return; |
| 2309 | 2193 | ||
| 2310 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2194 | if (ch == OMAP_DSS_CHANNEL_LCD) |
| 2311 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); | 2195 | REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); |
| 2312 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2196 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
| 2313 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); | 2197 | REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); |
| 2314 | else /* OMAP_DSS_CHANNEL_LCD2 */ | ||
| 2315 | REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18); | ||
| 2316 | } | 2198 | } |
| 2317 | bool dispc_alpha_blending_enabled(enum omap_channel ch) | 2199 | |
| 2200 | bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch) | ||
| 2318 | { | 2201 | { |
| 2319 | bool enabled; | 2202 | bool enabled; |
| 2320 | 2203 | ||
| 2321 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 2204 | if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) |
| 2322 | return false; | 2205 | return false; |
| 2323 | 2206 | ||
| 2324 | if (ch == OMAP_DSS_CHANNEL_LCD) | 2207 | if (ch == OMAP_DSS_CHANNEL_LCD) |
| 2325 | enabled = REG_GET(DISPC_CONFIG, 18, 18); | 2208 | enabled = REG_GET(DISPC_CONFIG, 18, 18); |
| 2326 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) | 2209 | else if (ch == OMAP_DSS_CHANNEL_DIGIT) |
| 2327 | enabled = REG_GET(DISPC_CONFIG, 19, 19); | 2210 | enabled = REG_GET(DISPC_CONFIG, 19, 19); |
| 2328 | else if (ch == OMAP_DSS_CHANNEL_LCD2) | ||
| 2329 | enabled = REG_GET(DISPC_CONFIG2, 18, 18); | ||
| 2330 | else | 2211 | else |
| 2331 | BUG(); | 2212 | BUG(); |
| 2332 | 2213 | ||
| 2333 | return enabled; | 2214 | return enabled; |
| 2334 | } | 2215 | } |
| 2335 | 2216 | ||
| 2336 | 2217 | bool dispc_mgr_trans_key_enabled(enum omap_channel ch) | |
| 2337 | bool dispc_trans_key_enabled(enum omap_channel ch) | ||
| 2338 | { | 2218 | { |
| 2339 | bool enabled; | 2219 | bool enabled; |
| 2340 | 2220 | ||
| @@ -2351,7 +2231,7 @@ bool dispc_trans_key_enabled(enum omap_channel ch) | |||
| 2351 | } | 2231 | } |
| 2352 | 2232 | ||
| 2353 | 2233 | ||
| 2354 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) | 2234 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) |
| 2355 | { | 2235 | { |
| 2356 | int code; | 2236 | int code; |
| 2357 | 2237 | ||
| @@ -2379,46 +2259,41 @@ void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines) | |||
| 2379 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); | 2259 | REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); |
| 2380 | } | 2260 | } |
| 2381 | 2261 | ||
| 2382 | void dispc_set_parallel_interface_mode(enum omap_channel channel, | 2262 | void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode) |
| 2383 | enum omap_parallel_interface_mode mode) | ||
| 2384 | { | 2263 | { |
| 2385 | u32 l; | 2264 | u32 l; |
| 2386 | int stallmode; | 2265 | int gpout0, gpout1; |
| 2387 | int gpout0 = 1; | ||
| 2388 | int gpout1; | ||
| 2389 | 2266 | ||
| 2390 | switch (mode) { | 2267 | switch (mode) { |
| 2391 | case OMAP_DSS_PARALLELMODE_BYPASS: | 2268 | case DSS_IO_PAD_MODE_RESET: |
| 2392 | stallmode = 0; | 2269 | gpout0 = 0; |
| 2393 | gpout1 = 1; | 2270 | gpout1 = 0; |
| 2394 | break; | 2271 | break; |
| 2395 | 2272 | case DSS_IO_PAD_MODE_RFBI: | |
| 2396 | case OMAP_DSS_PARALLELMODE_RFBI: | 2273 | gpout0 = 1; |
| 2397 | stallmode = 1; | ||
| 2398 | gpout1 = 0; | 2274 | gpout1 = 0; |
| 2399 | break; | 2275 | break; |
| 2400 | 2276 | case DSS_IO_PAD_MODE_BYPASS: | |
| 2401 | case OMAP_DSS_PARALLELMODE_DSI: | 2277 | gpout0 = 1; |
| 2402 | stallmode = 1; | ||
| 2403 | gpout1 = 1; | 2278 | gpout1 = 1; |
| 2404 | break; | 2279 | break; |
| 2405 | |||
| 2406 | default: | 2280 | default: |
| 2407 | BUG(); | 2281 | BUG(); |
| 2408 | return; | 2282 | return; |
| 2409 | } | 2283 | } |
| 2410 | 2284 | ||
| 2411 | if (channel == OMAP_DSS_CHANNEL_LCD2) { | 2285 | l = dispc_read_reg(DISPC_CONTROL); |
| 2412 | l = dispc_read_reg(DISPC_CONTROL2); | 2286 | l = FLD_MOD(l, gpout0, 15, 15); |
| 2413 | l = FLD_MOD(l, stallmode, 11, 11); | 2287 | l = FLD_MOD(l, gpout1, 16, 16); |
| 2414 | dispc_write_reg(DISPC_CONTROL2, l); | 2288 | dispc_write_reg(DISPC_CONTROL, l); |
| 2415 | } else { | 2289 | } |
| 2416 | l = dispc_read_reg(DISPC_CONTROL); | 2290 | |
| 2417 | l = FLD_MOD(l, stallmode, 11, 11); | 2291 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) |
| 2418 | l = FLD_MOD(l, gpout0, 15, 15); | 2292 | { |
| 2419 | l = FLD_MOD(l, gpout1, 16, 16); | 2293 | if (channel == OMAP_DSS_CHANNEL_LCD2) |
| 2420 | dispc_write_reg(DISPC_CONTROL, l); | 2294 | REG_FLD_MOD(DISPC_CONTROL2, enable, 11, 11); |
| 2421 | } | 2295 | else |
| 2296 | REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); | ||
| 2422 | } | 2297 | } |
| 2423 | 2298 | ||
| 2424 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2299 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, |
| @@ -2452,7 +2327,7 @@ bool dispc_lcd_timings_ok(struct omap_video_timings *timings) | |||
| 2452 | timings->vfp, timings->vbp); | 2327 | timings->vfp, timings->vbp); |
| 2453 | } | 2328 | } |
| 2454 | 2329 | ||
| 2455 | static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, | 2330 | static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, |
| 2456 | int hfp, int hbp, int vsw, int vfp, int vbp) | 2331 | int hfp, int hbp, int vsw, int vfp, int vbp) |
| 2457 | { | 2332 | { |
| 2458 | u32 timing_h, timing_v; | 2333 | u32 timing_h, timing_v; |
| @@ -2476,7 +2351,7 @@ static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw, | |||
| 2476 | } | 2351 | } |
| 2477 | 2352 | ||
| 2478 | /* change name to mode? */ | 2353 | /* change name to mode? */ |
| 2479 | void dispc_set_lcd_timings(enum omap_channel channel, | 2354 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, |
| 2480 | struct omap_video_timings *timings) | 2355 | struct omap_video_timings *timings) |
| 2481 | { | 2356 | { |
| 2482 | unsigned xtot, ytot; | 2357 | unsigned xtot, ytot; |
| @@ -2487,11 +2362,11 @@ void dispc_set_lcd_timings(enum omap_channel channel, | |||
| 2487 | timings->vfp, timings->vbp)) | 2362 | timings->vfp, timings->vbp)) |
| 2488 | BUG(); | 2363 | BUG(); |
| 2489 | 2364 | ||
| 2490 | _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp, | 2365 | _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, |
| 2491 | timings->hbp, timings->vsw, timings->vfp, | 2366 | timings->hbp, timings->vsw, timings->vfp, |
| 2492 | timings->vbp); | 2367 | timings->vbp); |
| 2493 | 2368 | ||
| 2494 | dispc_set_lcd_size(channel, timings->x_res, timings->y_res); | 2369 | dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res); |
| 2495 | 2370 | ||
| 2496 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; | 2371 | xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; |
| 2497 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; | 2372 | ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; |
| @@ -2509,17 +2384,17 @@ void dispc_set_lcd_timings(enum omap_channel channel, | |||
| 2509 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); | 2384 | DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); |
| 2510 | } | 2385 | } |
| 2511 | 2386 | ||
| 2512 | static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | 2387 | static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, |
| 2513 | u16 pck_div) | 2388 | u16 pck_div) |
| 2514 | { | 2389 | { |
| 2515 | BUG_ON(lck_div < 1); | 2390 | BUG_ON(lck_div < 1); |
| 2516 | BUG_ON(pck_div < 2); | 2391 | BUG_ON(pck_div < 1); |
| 2517 | 2392 | ||
| 2518 | dispc_write_reg(DISPC_DIVISORo(channel), | 2393 | dispc_write_reg(DISPC_DIVISORo(channel), |
| 2519 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2394 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
| 2520 | } | 2395 | } |
| 2521 | 2396 | ||
| 2522 | static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, | 2397 | static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, |
| 2523 | int *pck_div) | 2398 | int *pck_div) |
| 2524 | { | 2399 | { |
| 2525 | u32 l; | 2400 | u32 l; |
| @@ -2552,7 +2427,7 @@ unsigned long dispc_fclk_rate(void) | |||
| 2552 | return r; | 2427 | return r; |
| 2553 | } | 2428 | } |
| 2554 | 2429 | ||
| 2555 | unsigned long dispc_lclk_rate(enum omap_channel channel) | 2430 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) |
| 2556 | { | 2431 | { |
| 2557 | struct platform_device *dsidev; | 2432 | struct platform_device *dsidev; |
| 2558 | int lcd; | 2433 | int lcd; |
| @@ -2582,19 +2457,34 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) | |||
| 2582 | return r / lcd; | 2457 | return r / lcd; |
| 2583 | } | 2458 | } |
| 2584 | 2459 | ||
| 2585 | unsigned long dispc_pclk_rate(enum omap_channel channel) | 2460 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) |
| 2586 | { | 2461 | { |
| 2587 | int pcd; | ||
| 2588 | unsigned long r; | 2462 | unsigned long r; |
| 2589 | u32 l; | ||
| 2590 | 2463 | ||
| 2591 | l = dispc_read_reg(DISPC_DIVISORo(channel)); | 2464 | if (dispc_mgr_is_lcd(channel)) { |
| 2465 | int pcd; | ||
| 2466 | u32 l; | ||
| 2592 | 2467 | ||
| 2593 | pcd = FLD_GET(l, 7, 0); | 2468 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
| 2594 | 2469 | ||
| 2595 | r = dispc_lclk_rate(channel); | 2470 | pcd = FLD_GET(l, 7, 0); |
| 2596 | 2471 | ||
| 2597 | return r / pcd; | 2472 | r = dispc_mgr_lclk_rate(channel); |
| 2473 | |||
| 2474 | return r / pcd; | ||
| 2475 | } else { | ||
| 2476 | struct omap_dss_device *dssdev = | ||
| 2477 | dispc_mgr_get_device(channel); | ||
| 2478 | |||
| 2479 | switch (dssdev->type) { | ||
| 2480 | case OMAP_DISPLAY_TYPE_VENC: | ||
| 2481 | return venc_get_pixel_clock(); | ||
| 2482 | case OMAP_DISPLAY_TYPE_HDMI: | ||
| 2483 | return hdmi_get_pixel_clock(); | ||
| 2484 | default: | ||
| 2485 | BUG(); | ||
| 2486 | } | ||
| 2487 | } | ||
| 2598 | } | 2488 | } |
| 2599 | 2489 | ||
| 2600 | void dispc_dump_clocks(struct seq_file *s) | 2490 | void dispc_dump_clocks(struct seq_file *s) |
| @@ -2631,12 +2521,12 @@ void dispc_dump_clocks(struct seq_file *s) | |||
| 2631 | dss_get_generic_clk_source_name(lcd_clk_src), | 2521 | dss_get_generic_clk_source_name(lcd_clk_src), |
| 2632 | dss_feat_get_clk_source_name(lcd_clk_src)); | 2522 | dss_feat_get_clk_source_name(lcd_clk_src)); |
| 2633 | 2523 | ||
| 2634 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); | 2524 | dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); |
| 2635 | 2525 | ||
| 2636 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2526 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
| 2637 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); | 2527 | dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd); |
| 2638 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | 2528 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", |
| 2639 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); | 2529 | dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd); |
| 2640 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2530 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
| 2641 | seq_printf(s, "- LCD2 -\n"); | 2531 | seq_printf(s, "- LCD2 -\n"); |
| 2642 | 2532 | ||
| @@ -2646,12 +2536,12 @@ void dispc_dump_clocks(struct seq_file *s) | |||
| 2646 | dss_get_generic_clk_source_name(lcd_clk_src), | 2536 | dss_get_generic_clk_source_name(lcd_clk_src), |
| 2647 | dss_feat_get_clk_source_name(lcd_clk_src)); | 2537 | dss_feat_get_clk_source_name(lcd_clk_src)); |
| 2648 | 2538 | ||
| 2649 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); | 2539 | dispc_mgr_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); |
| 2650 | 2540 | ||
| 2651 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2541 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
| 2652 | dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); | 2542 | dispc_mgr_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd); |
| 2653 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", | 2543 | seq_printf(s, "pck\t\t%-16lupck div\t%u\n", |
| 2654 | dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); | 2544 | dispc_mgr_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd); |
| 2655 | } | 2545 | } |
| 2656 | 2546 | ||
| 2657 | dispc_runtime_put(); | 2547 | dispc_runtime_put(); |
| @@ -2692,6 +2582,10 @@ void dispc_dump_irqs(struct seq_file *s) | |||
| 2692 | PIS(VID1_END_WIN); | 2582 | PIS(VID1_END_WIN); |
| 2693 | PIS(VID2_FIFO_UNDERFLOW); | 2583 | PIS(VID2_FIFO_UNDERFLOW); |
| 2694 | PIS(VID2_END_WIN); | 2584 | PIS(VID2_END_WIN); |
| 2585 | if (dss_feat_get_num_ovls() > 3) { | ||
| 2586 | PIS(VID3_FIFO_UNDERFLOW); | ||
| 2587 | PIS(VID3_END_WIN); | ||
| 2588 | } | ||
| 2695 | PIS(SYNC_LOST); | 2589 | PIS(SYNC_LOST); |
| 2696 | PIS(SYNC_LOST_DIGIT); | 2590 | PIS(SYNC_LOST_DIGIT); |
| 2697 | PIS(WAKEUP); | 2591 | PIS(WAKEUP); |
| @@ -2707,11 +2601,26 @@ void dispc_dump_irqs(struct seq_file *s) | |||
| 2707 | 2601 | ||
| 2708 | void dispc_dump_regs(struct seq_file *s) | 2602 | void dispc_dump_regs(struct seq_file *s) |
| 2709 | { | 2603 | { |
| 2604 | int i, j; | ||
| 2605 | const char *mgr_names[] = { | ||
| 2606 | [OMAP_DSS_CHANNEL_LCD] = "LCD", | ||
| 2607 | [OMAP_DSS_CHANNEL_DIGIT] = "TV", | ||
| 2608 | [OMAP_DSS_CHANNEL_LCD2] = "LCD2", | ||
| 2609 | }; | ||
| 2610 | const char *ovl_names[] = { | ||
| 2611 | [OMAP_DSS_GFX] = "GFX", | ||
| 2612 | [OMAP_DSS_VIDEO1] = "VID1", | ||
| 2613 | [OMAP_DSS_VIDEO2] = "VID2", | ||
| 2614 | [OMAP_DSS_VIDEO3] = "VID3", | ||
| 2615 | }; | ||
| 2616 | const char **p_names; | ||
| 2617 | |||
| 2710 | #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) | 2618 | #define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) |
| 2711 | 2619 | ||
| 2712 | if (dispc_runtime_get()) | 2620 | if (dispc_runtime_get()) |
| 2713 | return; | 2621 | return; |
| 2714 | 2622 | ||
| 2623 | /* DISPC common registers */ | ||
| 2715 | DUMPREG(DISPC_REVISION); | 2624 | DUMPREG(DISPC_REVISION); |
| 2716 | DUMPREG(DISPC_SYSCONFIG); | 2625 | DUMPREG(DISPC_SYSCONFIG); |
| 2717 | DUMPREG(DISPC_SYSSTATUS); | 2626 | DUMPREG(DISPC_SYSSTATUS); |
| @@ -2720,247 +2629,139 @@ void dispc_dump_regs(struct seq_file *s) | |||
| 2720 | DUMPREG(DISPC_CONTROL); | 2629 | DUMPREG(DISPC_CONTROL); |
| 2721 | DUMPREG(DISPC_CONFIG); | 2630 | DUMPREG(DISPC_CONFIG); |
| 2722 | DUMPREG(DISPC_CAPABLE); | 2631 | DUMPREG(DISPC_CAPABLE); |
| 2723 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
| 2724 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 2725 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD)); | ||
| 2726 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 2727 | DUMPREG(DISPC_LINE_STATUS); | 2632 | DUMPREG(DISPC_LINE_STATUS); |
| 2728 | DUMPREG(DISPC_LINE_NUMBER); | 2633 | DUMPREG(DISPC_LINE_NUMBER); |
| 2729 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD)); | 2634 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || |
| 2730 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD)); | 2635 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) |
| 2731 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD)); | ||
| 2732 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD)); | ||
| 2733 | if (dss_has_feature(FEAT_GLOBAL_ALPHA)) | ||
| 2734 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2636 | DUMPREG(DISPC_GLOBAL_ALPHA); |
| 2735 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT)); | ||
| 2736 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD)); | ||
| 2737 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2637 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
| 2738 | DUMPREG(DISPC_CONTROL2); | 2638 | DUMPREG(DISPC_CONTROL2); |
| 2739 | DUMPREG(DISPC_CONFIG2); | 2639 | DUMPREG(DISPC_CONFIG2); |
| 2740 | DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2741 | DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2742 | DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2743 | DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2744 | DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2745 | DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2746 | DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2)); | ||
| 2747 | } | ||
| 2748 | |||
| 2749 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX)); | ||
| 2750 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX)); | ||
| 2751 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX)); | ||
| 2752 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX)); | ||
| 2753 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX)); | ||
| 2754 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX)); | ||
| 2755 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX)); | ||
| 2756 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX)); | ||
| 2757 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX)); | ||
| 2758 | DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX)); | ||
| 2759 | DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX)); | ||
| 2760 | |||
| 2761 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD)); | ||
| 2762 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD)); | ||
| 2763 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD)); | ||
| 2764 | |||
| 2765 | if (dss_has_feature(FEAT_CPR)) { | ||
| 2766 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD)); | ||
| 2767 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD)); | ||
| 2768 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD)); | ||
| 2769 | } | 2640 | } |
| 2770 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2641 | |
| 2771 | DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2)); | 2642 | #undef DUMPREG |
| 2772 | DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2)); | 2643 | |
| 2773 | DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2)); | 2644 | #define DISPC_REG(i, name) name(i) |
| 2645 | #define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \ | ||
| 2646 | 48 - strlen(#r) - strlen(p_names[i]), " ", \ | ||
| 2647 | dispc_read_reg(DISPC_REG(i, r))) | ||
| 2648 | |||
| 2649 | p_names = mgr_names; | ||
| 2650 | |||
| 2651 | /* DISPC channel specific registers */ | ||
| 2652 | for (i = 0; i < dss_feat_get_num_mgrs(); i++) { | ||
| 2653 | DUMPREG(i, DISPC_DEFAULT_COLOR); | ||
| 2654 | DUMPREG(i, DISPC_TRANS_COLOR); | ||
| 2655 | DUMPREG(i, DISPC_SIZE_MGR); | ||
| 2656 | |||
| 2657 | if (i == OMAP_DSS_CHANNEL_DIGIT) | ||
| 2658 | continue; | ||
| 2659 | |||
| 2660 | DUMPREG(i, DISPC_DEFAULT_COLOR); | ||
| 2661 | DUMPREG(i, DISPC_TRANS_COLOR); | ||
| 2662 | DUMPREG(i, DISPC_TIMING_H); | ||
| 2663 | DUMPREG(i, DISPC_TIMING_V); | ||
| 2664 | DUMPREG(i, DISPC_POL_FREQ); | ||
| 2665 | DUMPREG(i, DISPC_DIVISORo); | ||
| 2666 | DUMPREG(i, DISPC_SIZE_MGR); | ||
| 2667 | |||
| 2668 | DUMPREG(i, DISPC_DATA_CYCLE1); | ||
| 2669 | DUMPREG(i, DISPC_DATA_CYCLE2); | ||
| 2670 | DUMPREG(i, DISPC_DATA_CYCLE3); | ||
| 2774 | 2671 | ||
| 2775 | if (dss_has_feature(FEAT_CPR)) { | 2672 | if (dss_has_feature(FEAT_CPR)) { |
| 2776 | DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2)); | 2673 | DUMPREG(i, DISPC_CPR_COEF_R); |
| 2777 | DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2)); | 2674 | DUMPREG(i, DISPC_CPR_COEF_G); |
| 2778 | DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2)); | 2675 | DUMPREG(i, DISPC_CPR_COEF_B); |
| 2676 | } | ||
| 2677 | } | ||
| 2678 | |||
| 2679 | p_names = ovl_names; | ||
| 2680 | |||
| 2681 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { | ||
| 2682 | DUMPREG(i, DISPC_OVL_BA0); | ||
| 2683 | DUMPREG(i, DISPC_OVL_BA1); | ||
| 2684 | DUMPREG(i, DISPC_OVL_POSITION); | ||
| 2685 | DUMPREG(i, DISPC_OVL_SIZE); | ||
| 2686 | DUMPREG(i, DISPC_OVL_ATTRIBUTES); | ||
| 2687 | DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD); | ||
| 2688 | DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS); | ||
| 2689 | DUMPREG(i, DISPC_OVL_ROW_INC); | ||
| 2690 | DUMPREG(i, DISPC_OVL_PIXEL_INC); | ||
| 2691 | if (dss_has_feature(FEAT_PRELOAD)) | ||
| 2692 | DUMPREG(i, DISPC_OVL_PRELOAD); | ||
| 2693 | |||
| 2694 | if (i == OMAP_DSS_GFX) { | ||
| 2695 | DUMPREG(i, DISPC_OVL_WINDOW_SKIP); | ||
| 2696 | DUMPREG(i, DISPC_OVL_TABLE_BA); | ||
| 2697 | continue; | ||
| 2698 | } | ||
| 2699 | |||
| 2700 | DUMPREG(i, DISPC_OVL_FIR); | ||
| 2701 | DUMPREG(i, DISPC_OVL_PICTURE_SIZE); | ||
| 2702 | DUMPREG(i, DISPC_OVL_ACCU0); | ||
| 2703 | DUMPREG(i, DISPC_OVL_ACCU1); | ||
| 2704 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
| 2705 | DUMPREG(i, DISPC_OVL_BA0_UV); | ||
| 2706 | DUMPREG(i, DISPC_OVL_BA1_UV); | ||
| 2707 | DUMPREG(i, DISPC_OVL_FIR2); | ||
| 2708 | DUMPREG(i, DISPC_OVL_ACCU2_0); | ||
| 2709 | DUMPREG(i, DISPC_OVL_ACCU2_1); | ||
| 2779 | } | 2710 | } |
| 2711 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 2712 | DUMPREG(i, DISPC_OVL_ATTRIBUTES2); | ||
| 2713 | if (dss_has_feature(FEAT_PRELOAD)) | ||
| 2714 | DUMPREG(i, DISPC_OVL_PRELOAD); | ||
| 2780 | } | 2715 | } |
| 2781 | 2716 | ||
| 2782 | if (dss_has_feature(FEAT_PRELOAD)) | 2717 | #undef DISPC_REG |
| 2783 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX)); | 2718 | #undef DUMPREG |
| 2784 | 2719 | ||
| 2785 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1)); | 2720 | #define DISPC_REG(plane, name, i) name(plane, i) |
| 2786 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1)); | 2721 | #define DUMPREG(plane, name, i) \ |
| 2787 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1)); | 2722 | seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \ |
| 2788 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1)); | 2723 | 46 - strlen(#name) - strlen(p_names[plane]), " ", \ |
| 2789 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1)); | 2724 | dispc_read_reg(DISPC_REG(plane, name, i))) |
| 2790 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1)); | 2725 | |
| 2791 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1)); | 2726 | /* Video pipeline coefficient registers */ |
| 2792 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1)); | 2727 | |
| 2793 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1)); | 2728 | /* start from OMAP_DSS_VIDEO1 */ |
| 2794 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1)); | 2729 | for (i = 1; i < dss_feat_get_num_ovls(); i++) { |
| 2795 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1)); | 2730 | for (j = 0; j < 8; j++) |
| 2796 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1)); | 2731 | DUMPREG(i, DISPC_OVL_FIR_COEF_H, j); |
| 2797 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1)); | 2732 | |
| 2798 | 2733 | for (j = 0; j < 8; j++) | |
| 2799 | DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2)); | 2734 | DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j); |
| 2800 | DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2)); | 2735 | |
| 2801 | DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2)); | 2736 | for (j = 0; j < 5; j++) |
| 2802 | DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2)); | 2737 | DUMPREG(i, DISPC_OVL_CONV_COEF, j); |
| 2803 | DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2)); | 2738 | |
| 2804 | DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2)); | 2739 | if (dss_has_feature(FEAT_FIR_COEF_V)) { |
| 2805 | DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2)); | 2740 | for (j = 0; j < 8; j++) |
| 2806 | DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2)); | 2741 | DUMPREG(i, DISPC_OVL_FIR_COEF_V, j); |
| 2807 | DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2)); | 2742 | } |
| 2808 | DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2)); | 2743 | |
| 2809 | DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2)); | 2744 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { |
| 2810 | DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2)); | 2745 | for (j = 0; j < 8; j++) |
| 2811 | DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2)); | 2746 | DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j); |
| 2812 | 2747 | ||
| 2813 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0)); | 2748 | for (j = 0; j < 8; j++) |
| 2814 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1)); | 2749 | DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j); |
| 2815 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2)); | 2750 | |
| 2816 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3)); | 2751 | for (j = 0; j < 8; j++) |
| 2817 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4)); | 2752 | DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j); |
| 2818 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5)); | 2753 | } |
| 2819 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6)); | ||
| 2820 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7)); | ||
| 2821 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0)); | ||
| 2822 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1)); | ||
| 2823 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2)); | ||
| 2824 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3)); | ||
| 2825 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4)); | ||
| 2826 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5)); | ||
| 2827 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6)); | ||
| 2828 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7)); | ||
| 2829 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0)); | ||
| 2830 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1)); | ||
| 2831 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2)); | ||
| 2832 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3)); | ||
| 2833 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4)); | ||
| 2834 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
| 2835 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0)); | ||
| 2836 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1)); | ||
| 2837 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2)); | ||
| 2838 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3)); | ||
| 2839 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4)); | ||
| 2840 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5)); | ||
| 2841 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6)); | ||
| 2842 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7)); | ||
| 2843 | } | ||
| 2844 | |||
| 2845 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
| 2846 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1)); | ||
| 2847 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1)); | ||
| 2848 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1)); | ||
| 2849 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1)); | ||
| 2850 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1)); | ||
| 2851 | |||
| 2852 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0)); | ||
| 2853 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1)); | ||
| 2854 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2)); | ||
| 2855 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3)); | ||
| 2856 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4)); | ||
| 2857 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5)); | ||
| 2858 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6)); | ||
| 2859 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7)); | ||
| 2860 | |||
| 2861 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0)); | ||
| 2862 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1)); | ||
| 2863 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2)); | ||
| 2864 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3)); | ||
| 2865 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4)); | ||
| 2866 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5)); | ||
| 2867 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6)); | ||
| 2868 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7)); | ||
| 2869 | |||
| 2870 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0)); | ||
| 2871 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1)); | ||
| 2872 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2)); | ||
| 2873 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3)); | ||
| 2874 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4)); | ||
| 2875 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5)); | ||
| 2876 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6)); | ||
| 2877 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7)); | ||
| 2878 | } | ||
| 2879 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 2880 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1)); | ||
| 2881 | |||
| 2882 | |||
| 2883 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0)); | ||
| 2884 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1)); | ||
| 2885 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2)); | ||
| 2886 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3)); | ||
| 2887 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4)); | ||
| 2888 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5)); | ||
| 2889 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6)); | ||
| 2890 | DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7)); | ||
| 2891 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0)); | ||
| 2892 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1)); | ||
| 2893 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2)); | ||
| 2894 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3)); | ||
| 2895 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4)); | ||
| 2896 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5)); | ||
| 2897 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6)); | ||
| 2898 | DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7)); | ||
| 2899 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0)); | ||
| 2900 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1)); | ||
| 2901 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2)); | ||
| 2902 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3)); | ||
| 2903 | DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4)); | ||
| 2904 | |||
| 2905 | if (dss_has_feature(FEAT_FIR_COEF_V)) { | ||
| 2906 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0)); | ||
| 2907 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1)); | ||
| 2908 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2)); | ||
| 2909 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3)); | ||
| 2910 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4)); | ||
| 2911 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5)); | ||
| 2912 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6)); | ||
| 2913 | DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7)); | ||
| 2914 | } | ||
| 2915 | |||
| 2916 | if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { | ||
| 2917 | DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2)); | ||
| 2918 | DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2)); | ||
| 2919 | DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2)); | ||
| 2920 | DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2)); | ||
| 2921 | DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2)); | ||
| 2922 | |||
| 2923 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0)); | ||
| 2924 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1)); | ||
| 2925 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2)); | ||
| 2926 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3)); | ||
| 2927 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4)); | ||
| 2928 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5)); | ||
| 2929 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6)); | ||
| 2930 | DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7)); | ||
| 2931 | |||
| 2932 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0)); | ||
| 2933 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1)); | ||
| 2934 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2)); | ||
| 2935 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3)); | ||
| 2936 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4)); | ||
| 2937 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5)); | ||
| 2938 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6)); | ||
| 2939 | DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7)); | ||
| 2940 | |||
| 2941 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0)); | ||
| 2942 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1)); | ||
| 2943 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2)); | ||
| 2944 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3)); | ||
| 2945 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4)); | ||
| 2946 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5)); | ||
| 2947 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6)); | ||
| 2948 | DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7)); | ||
| 2949 | } | ||
| 2950 | if (dss_has_feature(FEAT_ATTR2)) | ||
| 2951 | DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2)); | ||
| 2952 | |||
| 2953 | if (dss_has_feature(FEAT_PRELOAD)) { | ||
| 2954 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1)); | ||
| 2955 | DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2)); | ||
| 2956 | } | 2754 | } |
| 2957 | 2755 | ||
| 2958 | dispc_runtime_put(); | 2756 | dispc_runtime_put(); |
| 2757 | |||
| 2758 | #undef DISPC_REG | ||
| 2959 | #undef DUMPREG | 2759 | #undef DUMPREG |
| 2960 | } | 2760 | } |
| 2961 | 2761 | ||
| 2962 | static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, | 2762 | static void _dispc_mgr_set_pol_freq(enum omap_channel channel, bool onoff, |
| 2963 | bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb) | 2763 | bool rf, bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, |
| 2764 | u8 acb) | ||
| 2964 | { | 2765 | { |
| 2965 | u32 l = 0; | 2766 | u32 l = 0; |
| 2966 | 2767 | ||
| @@ -2979,10 +2780,10 @@ static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf, | |||
| 2979 | dispc_write_reg(DISPC_POL_FREQ(channel), l); | 2780 | dispc_write_reg(DISPC_POL_FREQ(channel), l); |
| 2980 | } | 2781 | } |
| 2981 | 2782 | ||
| 2982 | void dispc_set_pol_freq(enum omap_channel channel, | 2783 | void dispc_mgr_set_pol_freq(enum omap_channel channel, |
| 2983 | enum omap_panel_config config, u8 acbi, u8 acb) | 2784 | enum omap_panel_config config, u8 acbi, u8 acb) |
| 2984 | { | 2785 | { |
| 2985 | _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, | 2786 | _dispc_mgr_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0, |
| 2986 | (config & OMAP_DSS_LCD_RF) != 0, | 2787 | (config & OMAP_DSS_LCD_RF) != 0, |
| 2987 | (config & OMAP_DSS_LCD_IEO) != 0, | 2788 | (config & OMAP_DSS_LCD_IEO) != 0, |
| 2988 | (config & OMAP_DSS_LCD_IPC) != 0, | 2789 | (config & OMAP_DSS_LCD_IPC) != 0, |
| @@ -2995,11 +2796,17 @@ void dispc_set_pol_freq(enum omap_channel channel, | |||
| 2995 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 2796 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
| 2996 | struct dispc_clock_info *cinfo) | 2797 | struct dispc_clock_info *cinfo) |
| 2997 | { | 2798 | { |
| 2998 | u16 pcd_min = is_tft ? 2 : 3; | 2799 | u16 pcd_min, pcd_max; |
| 2999 | unsigned long best_pck; | 2800 | unsigned long best_pck; |
| 3000 | u16 best_ld, cur_ld; | 2801 | u16 best_ld, cur_ld; |
| 3001 | u16 best_pd, cur_pd; | 2802 | u16 best_pd, cur_pd; |
| 3002 | 2803 | ||
| 2804 | pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); | ||
| 2805 | pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); | ||
| 2806 | |||
| 2807 | if (!is_tft) | ||
| 2808 | pcd_min = 3; | ||
| 2809 | |||
| 3003 | best_pck = 0; | 2810 | best_pck = 0; |
| 3004 | best_ld = 0; | 2811 | best_ld = 0; |
| 3005 | best_pd = 0; | 2812 | best_pd = 0; |
| @@ -3007,7 +2814,7 @@ void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | |||
| 3007 | for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { | 2814 | for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { |
| 3008 | unsigned long lck = fck / cur_ld; | 2815 | unsigned long lck = fck / cur_ld; |
| 3009 | 2816 | ||
| 3010 | for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { | 2817 | for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { |
| 3011 | unsigned long pck = lck / cur_pd; | 2818 | unsigned long pck = lck / cur_pd; |
| 3012 | long old_delta = abs(best_pck - req_pck); | 2819 | long old_delta = abs(best_pck - req_pck); |
| 3013 | long new_delta = abs(pck - req_pck); | 2820 | long new_delta = abs(pck - req_pck); |
| @@ -3042,7 +2849,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
| 3042 | { | 2849 | { |
| 3043 | if (cinfo->lck_div > 255 || cinfo->lck_div == 0) | 2850 | if (cinfo->lck_div > 255 || cinfo->lck_div == 0) |
| 3044 | return -EINVAL; | 2851 | return -EINVAL; |
| 3045 | if (cinfo->pck_div < 2 || cinfo->pck_div > 255) | 2852 | if (cinfo->pck_div < 1 || cinfo->pck_div > 255) |
| 3046 | return -EINVAL; | 2853 | return -EINVAL; |
| 3047 | 2854 | ||
| 3048 | cinfo->lck = dispc_fclk_rate / cinfo->lck_div; | 2855 | cinfo->lck = dispc_fclk_rate / cinfo->lck_div; |
| @@ -3051,18 +2858,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | |||
| 3051 | return 0; | 2858 | return 0; |
| 3052 | } | 2859 | } |
| 3053 | 2860 | ||
| 3054 | int dispc_set_clock_div(enum omap_channel channel, | 2861 | int dispc_mgr_set_clock_div(enum omap_channel channel, |
| 3055 | struct dispc_clock_info *cinfo) | 2862 | struct dispc_clock_info *cinfo) |
| 3056 | { | 2863 | { |
| 3057 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); | 2864 | DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); |
| 3058 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); | 2865 | DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); |
| 3059 | 2866 | ||
| 3060 | dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); | 2867 | dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); |
| 3061 | 2868 | ||
| 3062 | return 0; | 2869 | return 0; |
| 3063 | } | 2870 | } |
| 3064 | 2871 | ||
| 3065 | int dispc_get_clock_div(enum omap_channel channel, | 2872 | int dispc_mgr_get_clock_div(enum omap_channel channel, |
| 3066 | struct dispc_clock_info *cinfo) | 2873 | struct dispc_clock_info *cinfo) |
| 3067 | { | 2874 | { |
| 3068 | unsigned long fck; | 2875 | unsigned long fck; |
| @@ -3207,6 +3014,8 @@ static void print_irq_status(u32 status) | |||
| 3207 | PIS(OCP_ERR); | 3014 | PIS(OCP_ERR); |
| 3208 | PIS(VID1_FIFO_UNDERFLOW); | 3015 | PIS(VID1_FIFO_UNDERFLOW); |
| 3209 | PIS(VID2_FIFO_UNDERFLOW); | 3016 | PIS(VID2_FIFO_UNDERFLOW); |
| 3017 | if (dss_feat_get_num_ovls() > 3) | ||
| 3018 | PIS(VID3_FIFO_UNDERFLOW); | ||
| 3210 | PIS(SYNC_LOST); | 3019 | PIS(SYNC_LOST); |
| 3211 | PIS(SYNC_LOST_DIGIT); | 3020 | PIS(SYNC_LOST_DIGIT); |
| 3212 | if (dss_has_feature(FEAT_MGR_LCD2)) | 3021 | if (dss_has_feature(FEAT_MGR_LCD2)) |
| @@ -3300,178 +3109,72 @@ static void dispc_error_worker(struct work_struct *work) | |||
| 3300 | int i; | 3109 | int i; |
| 3301 | u32 errors; | 3110 | u32 errors; |
| 3302 | unsigned long flags; | 3111 | unsigned long flags; |
| 3112 | static const unsigned fifo_underflow_bits[] = { | ||
| 3113 | DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
| 3114 | DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
| 3115 | DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
| 3116 | DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
| 3117 | }; | ||
| 3118 | |||
| 3119 | static const unsigned sync_lost_bits[] = { | ||
| 3120 | DISPC_IRQ_SYNC_LOST, | ||
| 3121 | DISPC_IRQ_SYNC_LOST_DIGIT, | ||
| 3122 | DISPC_IRQ_SYNC_LOST2, | ||
| 3123 | }; | ||
| 3303 | 3124 | ||
| 3304 | spin_lock_irqsave(&dispc.irq_lock, flags); | 3125 | spin_lock_irqsave(&dispc.irq_lock, flags); |
| 3305 | errors = dispc.error_irqs; | 3126 | errors = dispc.error_irqs; |
| 3306 | dispc.error_irqs = 0; | 3127 | dispc.error_irqs = 0; |
| 3307 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 3128 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
| 3308 | 3129 | ||
| 3309 | if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { | 3130 | dispc_runtime_get(); |
| 3310 | DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); | ||
| 3311 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
| 3312 | struct omap_overlay *ovl; | ||
| 3313 | ovl = omap_dss_get_overlay(i); | ||
| 3314 | |||
| 3315 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 3316 | continue; | ||
| 3317 | |||
| 3318 | if (ovl->id == 0) { | ||
| 3319 | dispc_enable_plane(ovl->id, 0); | ||
| 3320 | dispc_go(ovl->manager->id); | ||
| 3321 | mdelay(50); | ||
| 3322 | break; | ||
| 3323 | } | ||
| 3324 | } | ||
| 3325 | } | ||
| 3326 | |||
| 3327 | if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { | ||
| 3328 | DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); | ||
| 3329 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
| 3330 | struct omap_overlay *ovl; | ||
| 3331 | ovl = omap_dss_get_overlay(i); | ||
| 3332 | |||
| 3333 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 3334 | continue; | ||
| 3335 | |||
| 3336 | if (ovl->id == 1) { | ||
| 3337 | dispc_enable_plane(ovl->id, 0); | ||
| 3338 | dispc_go(ovl->manager->id); | ||
| 3339 | mdelay(50); | ||
| 3340 | break; | ||
| 3341 | } | ||
| 3342 | } | ||
| 3343 | } | ||
| 3344 | |||
| 3345 | if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { | ||
| 3346 | DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); | ||
| 3347 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
| 3348 | struct omap_overlay *ovl; | ||
| 3349 | ovl = omap_dss_get_overlay(i); | ||
| 3350 | |||
| 3351 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 3352 | continue; | ||
| 3353 | 3131 | ||
| 3354 | if (ovl->id == 2) { | 3132 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { |
| 3355 | dispc_enable_plane(ovl->id, 0); | 3133 | struct omap_overlay *ovl; |
| 3356 | dispc_go(ovl->manager->id); | 3134 | unsigned bit; |
| 3357 | mdelay(50); | ||
| 3358 | break; | ||
| 3359 | } | ||
| 3360 | } | ||
| 3361 | } | ||
| 3362 | |||
| 3363 | if (errors & DISPC_IRQ_SYNC_LOST) { | ||
| 3364 | struct omap_overlay_manager *manager = NULL; | ||
| 3365 | bool enable = false; | ||
| 3366 | 3135 | ||
| 3367 | DSSERR("SYNC_LOST, disabling LCD\n"); | 3136 | ovl = omap_dss_get_overlay(i); |
| 3137 | bit = fifo_underflow_bits[i]; | ||
| 3368 | 3138 | ||
| 3369 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3139 | if (bit & errors) { |
| 3370 | struct omap_overlay_manager *mgr; | 3140 | DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n", |
| 3371 | mgr = omap_dss_get_overlay_manager(i); | 3141 | ovl->name); |
| 3372 | 3142 | dispc_ovl_enable(ovl->id, false); | |
| 3373 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) { | 3143 | dispc_mgr_go(ovl->manager->id); |
| 3374 | manager = mgr; | ||
| 3375 | enable = mgr->device->state == | ||
| 3376 | OMAP_DSS_DISPLAY_ACTIVE; | ||
| 3377 | mgr->device->driver->disable(mgr->device); | ||
| 3378 | break; | ||
| 3379 | } | ||
| 3380 | } | ||
| 3381 | |||
| 3382 | if (manager) { | ||
| 3383 | struct omap_dss_device *dssdev = manager->device; | ||
| 3384 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
| 3385 | struct omap_overlay *ovl; | ||
| 3386 | ovl = omap_dss_get_overlay(i); | ||
| 3387 | |||
| 3388 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 3389 | continue; | ||
| 3390 | |||
| 3391 | if (ovl->id != 0 && ovl->manager == manager) | ||
| 3392 | dispc_enable_plane(ovl->id, 0); | ||
| 3393 | } | ||
| 3394 | |||
| 3395 | dispc_go(manager->id); | ||
| 3396 | mdelay(50); | 3144 | mdelay(50); |
| 3397 | if (enable) | ||
| 3398 | dssdev->driver->enable(dssdev); | ||
| 3399 | } | 3145 | } |
| 3400 | } | 3146 | } |
| 3401 | 3147 | ||
| 3402 | if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { | 3148 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
| 3403 | struct omap_overlay_manager *manager = NULL; | 3149 | struct omap_overlay_manager *mgr; |
| 3404 | bool enable = false; | 3150 | unsigned bit; |
| 3405 | 3151 | ||
| 3406 | DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); | 3152 | mgr = omap_dss_get_overlay_manager(i); |
| 3153 | bit = sync_lost_bits[i]; | ||
| 3407 | 3154 | ||
| 3408 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3155 | if (bit & errors) { |
| 3409 | struct omap_overlay_manager *mgr; | 3156 | struct omap_dss_device *dssdev = mgr->device; |
| 3410 | mgr = omap_dss_get_overlay_manager(i); | 3157 | bool enable; |
| 3411 | 3158 | ||
| 3412 | if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { | 3159 | DSSERR("SYNC_LOST on channel %s, restarting the output " |
| 3413 | manager = mgr; | 3160 | "with video overlays disabled\n", |
| 3414 | enable = mgr->device->state == | 3161 | mgr->name); |
| 3415 | OMAP_DSS_DISPLAY_ACTIVE; | ||
| 3416 | mgr->device->driver->disable(mgr->device); | ||
| 3417 | break; | ||
| 3418 | } | ||
| 3419 | } | ||
| 3420 | 3162 | ||
| 3421 | if (manager) { | 3163 | enable = dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; |
| 3422 | struct omap_dss_device *dssdev = manager->device; | 3164 | dssdev->driver->disable(dssdev); |
| 3423 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | ||
| 3424 | struct omap_overlay *ovl; | ||
| 3425 | ovl = omap_dss_get_overlay(i); | ||
| 3426 | |||
| 3427 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 3428 | continue; | ||
| 3429 | |||
| 3430 | if (ovl->id != 0 && ovl->manager == manager) | ||
| 3431 | dispc_enable_plane(ovl->id, 0); | ||
| 3432 | } | ||
| 3433 | 3165 | ||
| 3434 | dispc_go(manager->id); | ||
| 3435 | mdelay(50); | ||
| 3436 | if (enable) | ||
| 3437 | dssdev->driver->enable(dssdev); | ||
| 3438 | } | ||
| 3439 | } | ||
| 3440 | |||
| 3441 | if (errors & DISPC_IRQ_SYNC_LOST2) { | ||
| 3442 | struct omap_overlay_manager *manager = NULL; | ||
| 3443 | bool enable = false; | ||
| 3444 | |||
| 3445 | DSSERR("SYNC_LOST for LCD2, disabling LCD2\n"); | ||
| 3446 | |||
| 3447 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | ||
| 3448 | struct omap_overlay_manager *mgr; | ||
| 3449 | mgr = omap_dss_get_overlay_manager(i); | ||
| 3450 | |||
| 3451 | if (mgr->id == OMAP_DSS_CHANNEL_LCD2) { | ||
| 3452 | manager = mgr; | ||
| 3453 | enable = mgr->device->state == | ||
| 3454 | OMAP_DSS_DISPLAY_ACTIVE; | ||
| 3455 | mgr->device->driver->disable(mgr->device); | ||
| 3456 | break; | ||
| 3457 | } | ||
| 3458 | } | ||
| 3459 | |||
| 3460 | if (manager) { | ||
| 3461 | struct omap_dss_device *dssdev = manager->device; | ||
| 3462 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { | 3166 | for (i = 0; i < omap_dss_get_num_overlays(); ++i) { |
| 3463 | struct omap_overlay *ovl; | 3167 | struct omap_overlay *ovl; |
| 3464 | ovl = omap_dss_get_overlay(i); | 3168 | ovl = omap_dss_get_overlay(i); |
| 3465 | 3169 | ||
| 3466 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | 3170 | if (ovl->id != OMAP_DSS_GFX && |
| 3467 | continue; | 3171 | ovl->manager == mgr) |
| 3468 | 3172 | dispc_ovl_enable(ovl->id, false); | |
| 3469 | if (ovl->id != 0 && ovl->manager == manager) | ||
| 3470 | dispc_enable_plane(ovl->id, 0); | ||
| 3471 | } | 3173 | } |
| 3472 | 3174 | ||
| 3473 | dispc_go(manager->id); | 3175 | dispc_mgr_go(mgr->id); |
| 3474 | mdelay(50); | 3176 | mdelay(50); |
| 3177 | |||
| 3475 | if (enable) | 3178 | if (enable) |
| 3476 | dssdev->driver->enable(dssdev); | 3179 | dssdev->driver->enable(dssdev); |
| 3477 | } | 3180 | } |
| @@ -3482,9 +3185,7 @@ static void dispc_error_worker(struct work_struct *work) | |||
| 3482 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 3185 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { |
| 3483 | struct omap_overlay_manager *mgr; | 3186 | struct omap_overlay_manager *mgr; |
| 3484 | mgr = omap_dss_get_overlay_manager(i); | 3187 | mgr = omap_dss_get_overlay_manager(i); |
| 3485 | 3188 | mgr->device->driver->disable(mgr->device); | |
| 3486 | if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) | ||
| 3487 | mgr->device->driver->disable(mgr->device); | ||
| 3488 | } | 3189 | } |
| 3489 | } | 3190 | } |
| 3490 | 3191 | ||
| @@ -3492,6 +3193,8 @@ static void dispc_error_worker(struct work_struct *work) | |||
| 3492 | dispc.irq_error_mask |= errors; | 3193 | dispc.irq_error_mask |= errors; |
| 3493 | _omap_dispc_set_irqs(); | 3194 | _omap_dispc_set_irqs(); |
| 3494 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 3195 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
| 3196 | |||
| 3197 | dispc_runtime_put(); | ||
| 3495 | } | 3198 | } |
| 3496 | 3199 | ||
| 3497 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) | 3200 | int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) |
| @@ -3586,6 +3289,8 @@ static void _omap_dispc_initialize_irq(void) | |||
| 3586 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; | 3289 | dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; |
| 3587 | if (dss_has_feature(FEAT_MGR_LCD2)) | 3290 | if (dss_has_feature(FEAT_MGR_LCD2)) |
| 3588 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; | 3291 | dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2; |
| 3292 | if (dss_feat_get_num_ovls() > 3) | ||
| 3293 | dispc.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW; | ||
| 3589 | 3294 | ||
| 3590 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, | 3295 | /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, |
| 3591 | * so clear it */ | 3296 | * so clear it */ |
| @@ -3635,6 +3340,8 @@ static void _omap_dispc_initial_config(void) | |||
| 3635 | dispc_read_plane_fifo_sizes(); | 3340 | dispc_read_plane_fifo_sizes(); |
| 3636 | 3341 | ||
| 3637 | dispc_configure_burst_sizes(); | 3342 | dispc_configure_burst_sizes(); |
| 3343 | |||
| 3344 | dispc_ovl_enable_zorder_planes(); | ||
| 3638 | } | 3345 | } |
| 3639 | 3346 | ||
| 3640 | /* DISPC HW IP initialisation */ | 3347 | /* DISPC HW IP initialisation */ |
| @@ -3734,7 +3441,6 @@ static int omap_dispchw_remove(struct platform_device *pdev) | |||
| 3734 | static int dispc_runtime_suspend(struct device *dev) | 3441 | static int dispc_runtime_suspend(struct device *dev) |
| 3735 | { | 3442 | { |
| 3736 | dispc_save_context(); | 3443 | dispc_save_context(); |
| 3737 | clk_disable(dispc.dss_clk); | ||
| 3738 | dss_runtime_put(); | 3444 | dss_runtime_put(); |
| 3739 | 3445 | ||
| 3740 | return 0; | 3446 | return 0; |
| @@ -3748,7 +3454,6 @@ static int dispc_runtime_resume(struct device *dev) | |||
| 3748 | if (r < 0) | 3454 | if (r < 0) |
| 3749 | return r; | 3455 | return r; |
| 3750 | 3456 | ||
| 3751 | clk_enable(dispc.dss_clk); | ||
| 3752 | dispc_restore_context(); | 3457 | dispc_restore_context(); |
| 3753 | 3458 | ||
| 3754 | return 0; | 3459 | return 0; |
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 6c9ee0a0efb3..c06efc38983e 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h | |||
| @@ -291,6 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane) | |||
| 291 | return 0x00BC; | 291 | return 0x00BC; |
| 292 | case OMAP_DSS_VIDEO2: | 292 | case OMAP_DSS_VIDEO2: |
| 293 | return 0x014C; | 293 | return 0x014C; |
| 294 | case OMAP_DSS_VIDEO3: | ||
| 295 | return 0x0300; | ||
| 294 | default: | 296 | default: |
| 295 | BUG(); | 297 | BUG(); |
| 296 | } | 298 | } |
| @@ -304,6 +306,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) | |||
| 304 | case OMAP_DSS_VIDEO1: | 306 | case OMAP_DSS_VIDEO1: |
| 305 | case OMAP_DSS_VIDEO2: | 307 | case OMAP_DSS_VIDEO2: |
| 306 | return 0x0000; | 308 | return 0x0000; |
| 309 | case OMAP_DSS_VIDEO3: | ||
| 310 | return 0x0008; | ||
| 307 | default: | 311 | default: |
| 308 | BUG(); | 312 | BUG(); |
| 309 | } | 313 | } |
| @@ -316,6 +320,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) | |||
| 316 | case OMAP_DSS_VIDEO1: | 320 | case OMAP_DSS_VIDEO1: |
| 317 | case OMAP_DSS_VIDEO2: | 321 | case OMAP_DSS_VIDEO2: |
| 318 | return 0x0004; | 322 | return 0x0004; |
| 323 | case OMAP_DSS_VIDEO3: | ||
| 324 | return 0x000C; | ||
| 319 | default: | 325 | default: |
| 320 | BUG(); | 326 | BUG(); |
| 321 | } | 327 | } |
| @@ -330,6 +336,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) | |||
| 330 | return 0x0544; | 336 | return 0x0544; |
| 331 | case OMAP_DSS_VIDEO2: | 337 | case OMAP_DSS_VIDEO2: |
| 332 | return 0x04BC; | 338 | return 0x04BC; |
| 339 | case OMAP_DSS_VIDEO3: | ||
| 340 | return 0x0310; | ||
| 333 | default: | 341 | default: |
| 334 | BUG(); | 342 | BUG(); |
| 335 | } | 343 | } |
| @@ -344,6 +352,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) | |||
| 344 | return 0x0548; | 352 | return 0x0548; |
| 345 | case OMAP_DSS_VIDEO2: | 353 | case OMAP_DSS_VIDEO2: |
| 346 | return 0x04C0; | 354 | return 0x04C0; |
| 355 | case OMAP_DSS_VIDEO3: | ||
| 356 | return 0x0314; | ||
| 347 | default: | 357 | default: |
| 348 | BUG(); | 358 | BUG(); |
| 349 | } | 359 | } |
| @@ -356,6 +366,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) | |||
| 356 | case OMAP_DSS_VIDEO1: | 366 | case OMAP_DSS_VIDEO1: |
| 357 | case OMAP_DSS_VIDEO2: | 367 | case OMAP_DSS_VIDEO2: |
| 358 | return 0x0008; | 368 | return 0x0008; |
| 369 | case OMAP_DSS_VIDEO3: | ||
| 370 | return 0x009C; | ||
| 359 | default: | 371 | default: |
| 360 | BUG(); | 372 | BUG(); |
| 361 | } | 373 | } |
| @@ -368,6 +380,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) | |||
| 368 | case OMAP_DSS_VIDEO1: | 380 | case OMAP_DSS_VIDEO1: |
| 369 | case OMAP_DSS_VIDEO2: | 381 | case OMAP_DSS_VIDEO2: |
| 370 | return 0x000C; | 382 | return 0x000C; |
| 383 | case OMAP_DSS_VIDEO3: | ||
| 384 | return 0x00A8; | ||
| 371 | default: | 385 | default: |
| 372 | BUG(); | 386 | BUG(); |
| 373 | } | 387 | } |
| @@ -381,6 +395,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) | |||
| 381 | case OMAP_DSS_VIDEO1: | 395 | case OMAP_DSS_VIDEO1: |
| 382 | case OMAP_DSS_VIDEO2: | 396 | case OMAP_DSS_VIDEO2: |
| 383 | return 0x0010; | 397 | return 0x0010; |
| 398 | case OMAP_DSS_VIDEO3: | ||
| 399 | return 0x0070; | ||
| 384 | default: | 400 | default: |
| 385 | BUG(); | 401 | BUG(); |
| 386 | } | 402 | } |
| @@ -395,6 +411,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) | |||
| 395 | return 0x0568; | 411 | return 0x0568; |
| 396 | case OMAP_DSS_VIDEO2: | 412 | case OMAP_DSS_VIDEO2: |
| 397 | return 0x04DC; | 413 | return 0x04DC; |
| 414 | case OMAP_DSS_VIDEO3: | ||
| 415 | return 0x032C; | ||
| 398 | default: | 416 | default: |
| 399 | BUG(); | 417 | BUG(); |
| 400 | } | 418 | } |
| @@ -408,6 +426,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) | |||
| 408 | case OMAP_DSS_VIDEO1: | 426 | case OMAP_DSS_VIDEO1: |
| 409 | case OMAP_DSS_VIDEO2: | 427 | case OMAP_DSS_VIDEO2: |
| 410 | return 0x0014; | 428 | return 0x0014; |
| 429 | case OMAP_DSS_VIDEO3: | ||
| 430 | return 0x008C; | ||
| 411 | default: | 431 | default: |
| 412 | BUG(); | 432 | BUG(); |
| 413 | } | 433 | } |
| @@ -421,6 +441,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) | |||
| 421 | case OMAP_DSS_VIDEO1: | 441 | case OMAP_DSS_VIDEO1: |
| 422 | case OMAP_DSS_VIDEO2: | 442 | case OMAP_DSS_VIDEO2: |
| 423 | return 0x0018; | 443 | return 0x0018; |
| 444 | case OMAP_DSS_VIDEO3: | ||
| 445 | return 0x0088; | ||
| 424 | default: | 446 | default: |
| 425 | BUG(); | 447 | BUG(); |
| 426 | } | 448 | } |
| @@ -434,6 +456,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) | |||
| 434 | case OMAP_DSS_VIDEO1: | 456 | case OMAP_DSS_VIDEO1: |
| 435 | case OMAP_DSS_VIDEO2: | 457 | case OMAP_DSS_VIDEO2: |
| 436 | return 0x001C; | 458 | return 0x001C; |
| 459 | case OMAP_DSS_VIDEO3: | ||
| 460 | return 0x00A4; | ||
| 437 | default: | 461 | default: |
| 438 | BUG(); | 462 | BUG(); |
| 439 | } | 463 | } |
| @@ -447,6 +471,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) | |||
| 447 | case OMAP_DSS_VIDEO1: | 471 | case OMAP_DSS_VIDEO1: |
| 448 | case OMAP_DSS_VIDEO2: | 472 | case OMAP_DSS_VIDEO2: |
| 449 | return 0x0020; | 473 | return 0x0020; |
| 474 | case OMAP_DSS_VIDEO3: | ||
| 475 | return 0x0098; | ||
| 450 | default: | 476 | default: |
| 451 | BUG(); | 477 | BUG(); |
| 452 | } | 478 | } |
| @@ -459,6 +485,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) | |||
| 459 | return 0x0034; | 485 | return 0x0034; |
| 460 | case OMAP_DSS_VIDEO1: | 486 | case OMAP_DSS_VIDEO1: |
| 461 | case OMAP_DSS_VIDEO2: | 487 | case OMAP_DSS_VIDEO2: |
| 488 | case OMAP_DSS_VIDEO3: | ||
| 462 | BUG(); | 489 | BUG(); |
| 463 | default: | 490 | default: |
| 464 | BUG(); | 491 | BUG(); |
| @@ -472,6 +499,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) | |||
| 472 | return 0x0038; | 499 | return 0x0038; |
| 473 | case OMAP_DSS_VIDEO1: | 500 | case OMAP_DSS_VIDEO1: |
| 474 | case OMAP_DSS_VIDEO2: | 501 | case OMAP_DSS_VIDEO2: |
| 502 | case OMAP_DSS_VIDEO3: | ||
| 475 | BUG(); | 503 | BUG(); |
| 476 | default: | 504 | default: |
| 477 | BUG(); | 505 | BUG(); |
| @@ -486,6 +514,8 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) | |||
| 486 | case OMAP_DSS_VIDEO1: | 514 | case OMAP_DSS_VIDEO1: |
| 487 | case OMAP_DSS_VIDEO2: | 515 | case OMAP_DSS_VIDEO2: |
| 488 | return 0x0024; | 516 | return 0x0024; |
| 517 | case OMAP_DSS_VIDEO3: | ||
| 518 | return 0x0090; | ||
| 489 | default: | 519 | default: |
| 490 | BUG(); | 520 | BUG(); |
| 491 | } | 521 | } |
| @@ -500,6 +530,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) | |||
| 500 | return 0x0580; | 530 | return 0x0580; |
| 501 | case OMAP_DSS_VIDEO2: | 531 | case OMAP_DSS_VIDEO2: |
| 502 | return 0x055C; | 532 | return 0x055C; |
| 533 | case OMAP_DSS_VIDEO3: | ||
| 534 | return 0x0424; | ||
| 503 | default: | 535 | default: |
| 504 | BUG(); | 536 | BUG(); |
| 505 | } | 537 | } |
| @@ -513,6 +545,8 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) | |||
| 513 | case OMAP_DSS_VIDEO1: | 545 | case OMAP_DSS_VIDEO1: |
| 514 | case OMAP_DSS_VIDEO2: | 546 | case OMAP_DSS_VIDEO2: |
| 515 | return 0x0028; | 547 | return 0x0028; |
| 548 | case OMAP_DSS_VIDEO3: | ||
| 549 | return 0x0094; | ||
| 516 | default: | 550 | default: |
| 517 | BUG(); | 551 | BUG(); |
| 518 | } | 552 | } |
| @@ -527,6 +561,8 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) | |||
| 527 | case OMAP_DSS_VIDEO1: | 561 | case OMAP_DSS_VIDEO1: |
| 528 | case OMAP_DSS_VIDEO2: | 562 | case OMAP_DSS_VIDEO2: |
| 529 | return 0x002C; | 563 | return 0x002C; |
| 564 | case OMAP_DSS_VIDEO3: | ||
| 565 | return 0x0000; | ||
| 530 | default: | 566 | default: |
| 531 | BUG(); | 567 | BUG(); |
| 532 | } | 568 | } |
| @@ -541,6 +577,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) | |||
| 541 | return 0x0584; | 577 | return 0x0584; |
| 542 | case OMAP_DSS_VIDEO2: | 578 | case OMAP_DSS_VIDEO2: |
| 543 | return 0x0560; | 579 | return 0x0560; |
| 580 | case OMAP_DSS_VIDEO3: | ||
| 581 | return 0x0428; | ||
| 544 | default: | 582 | default: |
| 545 | BUG(); | 583 | BUG(); |
| 546 | } | 584 | } |
| @@ -554,6 +592,8 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) | |||
| 554 | case OMAP_DSS_VIDEO1: | 592 | case OMAP_DSS_VIDEO1: |
| 555 | case OMAP_DSS_VIDEO2: | 593 | case OMAP_DSS_VIDEO2: |
| 556 | return 0x0030; | 594 | return 0x0030; |
| 595 | case OMAP_DSS_VIDEO3: | ||
| 596 | return 0x0004; | ||
| 557 | default: | 597 | default: |
| 558 | BUG(); | 598 | BUG(); |
| 559 | } | 599 | } |
| @@ -568,6 +608,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) | |||
| 568 | return 0x0588; | 608 | return 0x0588; |
| 569 | case OMAP_DSS_VIDEO2: | 609 | case OMAP_DSS_VIDEO2: |
| 570 | return 0x0564; | 610 | return 0x0564; |
| 611 | case OMAP_DSS_VIDEO3: | ||
| 612 | return 0x042C; | ||
| 571 | default: | 613 | default: |
| 572 | BUG(); | 614 | BUG(); |
| 573 | } | 615 | } |
| @@ -582,6 +624,8 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) | |||
| 582 | case OMAP_DSS_VIDEO1: | 624 | case OMAP_DSS_VIDEO1: |
| 583 | case OMAP_DSS_VIDEO2: | 625 | case OMAP_DSS_VIDEO2: |
| 584 | return 0x0034 + i * 0x8; | 626 | return 0x0034 + i * 0x8; |
| 627 | case OMAP_DSS_VIDEO3: | ||
| 628 | return 0x0010 + i * 0x8; | ||
| 585 | default: | 629 | default: |
| 586 | BUG(); | 630 | BUG(); |
| 587 | } | 631 | } |
| @@ -597,6 +641,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) | |||
| 597 | return 0x058C + i * 0x8; | 641 | return 0x058C + i * 0x8; |
| 598 | case OMAP_DSS_VIDEO2: | 642 | case OMAP_DSS_VIDEO2: |
| 599 | return 0x0568 + i * 0x8; | 643 | return 0x0568 + i * 0x8; |
| 644 | case OMAP_DSS_VIDEO3: | ||
| 645 | return 0x0430 + i * 0x8; | ||
| 600 | default: | 646 | default: |
| 601 | BUG(); | 647 | BUG(); |
| 602 | } | 648 | } |
| @@ -611,6 +657,8 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) | |||
| 611 | case OMAP_DSS_VIDEO1: | 657 | case OMAP_DSS_VIDEO1: |
| 612 | case OMAP_DSS_VIDEO2: | 658 | case OMAP_DSS_VIDEO2: |
| 613 | return 0x0038 + i * 0x8; | 659 | return 0x0038 + i * 0x8; |
| 660 | case OMAP_DSS_VIDEO3: | ||
| 661 | return 0x0014 + i * 0x8; | ||
| 614 | default: | 662 | default: |
| 615 | BUG(); | 663 | BUG(); |
| 616 | } | 664 | } |
| @@ -626,6 +674,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) | |||
| 626 | return 0x0590 + i * 8; | 674 | return 0x0590 + i * 8; |
| 627 | case OMAP_DSS_VIDEO2: | 675 | case OMAP_DSS_VIDEO2: |
| 628 | return 0x056C + i * 0x8; | 676 | return 0x056C + i * 0x8; |
| 677 | case OMAP_DSS_VIDEO3: | ||
| 678 | return 0x0434 + i * 0x8; | ||
| 629 | default: | 679 | default: |
| 630 | BUG(); | 680 | BUG(); |
| 631 | } | 681 | } |
| @@ -639,6 +689,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) | |||
| 639 | BUG(); | 689 | BUG(); |
| 640 | case OMAP_DSS_VIDEO1: | 690 | case OMAP_DSS_VIDEO1: |
| 641 | case OMAP_DSS_VIDEO2: | 691 | case OMAP_DSS_VIDEO2: |
| 692 | case OMAP_DSS_VIDEO3: | ||
| 642 | return 0x0074 + i * 0x4; | 693 | return 0x0074 + i * 0x4; |
| 643 | default: | 694 | default: |
| 644 | BUG(); | 695 | BUG(); |
| @@ -655,6 +706,8 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) | |||
| 655 | return 0x0124 + i * 0x4; | 706 | return 0x0124 + i * 0x4; |
| 656 | case OMAP_DSS_VIDEO2: | 707 | case OMAP_DSS_VIDEO2: |
| 657 | return 0x00B4 + i * 0x4; | 708 | return 0x00B4 + i * 0x4; |
| 709 | case OMAP_DSS_VIDEO3: | ||
| 710 | return 0x0050 + i * 0x4; | ||
| 658 | default: | 711 | default: |
| 659 | BUG(); | 712 | BUG(); |
| 660 | } | 713 | } |
| @@ -670,6 +723,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) | |||
| 670 | return 0x05CC + i * 0x4; | 723 | return 0x05CC + i * 0x4; |
| 671 | case OMAP_DSS_VIDEO2: | 724 | case OMAP_DSS_VIDEO2: |
| 672 | return 0x05A8 + i * 0x4; | 725 | return 0x05A8 + i * 0x4; |
| 726 | case OMAP_DSS_VIDEO3: | ||
| 727 | return 0x0470 + i * 0x4; | ||
| 673 | default: | 728 | default: |
| 674 | BUG(); | 729 | BUG(); |
| 675 | } | 730 | } |
| @@ -684,6 +739,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) | |||
| 684 | return 0x0174; | 739 | return 0x0174; |
| 685 | case OMAP_DSS_VIDEO2: | 740 | case OMAP_DSS_VIDEO2: |
| 686 | return 0x00E8; | 741 | return 0x00E8; |
| 742 | case OMAP_DSS_VIDEO3: | ||
| 743 | return 0x00A0; | ||
| 687 | default: | 744 | default: |
| 688 | BUG(); | 745 | BUG(); |
| 689 | } | 746 | } |
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 94495e45ec5a..be331dc5a61b 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
| @@ -45,14 +45,13 @@ static ssize_t display_enabled_store(struct device *dev, | |||
| 45 | const char *buf, size_t size) | 45 | const char *buf, size_t size) |
| 46 | { | 46 | { |
| 47 | struct omap_dss_device *dssdev = to_dss_device(dev); | 47 | struct omap_dss_device *dssdev = to_dss_device(dev); |
| 48 | int r, enabled; | 48 | int r; |
| 49 | bool enabled; | ||
| 49 | 50 | ||
| 50 | r = kstrtoint(buf, 0, &enabled); | 51 | r = strtobool(buf, &enabled); |
| 51 | if (r) | 52 | if (r) |
| 52 | return r; | 53 | return r; |
| 53 | 54 | ||
| 54 | enabled = !!enabled; | ||
| 55 | |||
| 56 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { | 55 | if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) { |
| 57 | if (enabled) { | 56 | if (enabled) { |
| 58 | r = dssdev->driver->enable(dssdev); | 57 | r = dssdev->driver->enable(dssdev); |
| @@ -79,17 +78,16 @@ static ssize_t display_tear_store(struct device *dev, | |||
| 79 | struct device_attribute *attr, const char *buf, size_t size) | 78 | struct device_attribute *attr, const char *buf, size_t size) |
| 80 | { | 79 | { |
| 81 | struct omap_dss_device *dssdev = to_dss_device(dev); | 80 | struct omap_dss_device *dssdev = to_dss_device(dev); |
| 82 | int te, r; | 81 | int r; |
| 82 | bool te; | ||
| 83 | 83 | ||
| 84 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) | 84 | if (!dssdev->driver->enable_te || !dssdev->driver->get_te) |
| 85 | return -ENOENT; | 85 | return -ENOENT; |
| 86 | 86 | ||
| 87 | r = kstrtoint(buf, 0, &te); | 87 | r = strtobool(buf, &te); |
| 88 | if (r) | 88 | if (r) |
| 89 | return r; | 89 | return r; |
| 90 | 90 | ||
| 91 | te = !!te; | ||
| 92 | |||
| 93 | r = dssdev->driver->enable_te(dssdev, te); | 91 | r = dssdev->driver->enable_te(dssdev, te); |
| 94 | if (r) | 92 | if (r) |
| 95 | return r; | 93 | return r; |
| @@ -195,17 +193,16 @@ static ssize_t display_mirror_store(struct device *dev, | |||
| 195 | struct device_attribute *attr, const char *buf, size_t size) | 193 | struct device_attribute *attr, const char *buf, size_t size) |
| 196 | { | 194 | { |
| 197 | struct omap_dss_device *dssdev = to_dss_device(dev); | 195 | struct omap_dss_device *dssdev = to_dss_device(dev); |
| 198 | int mirror, r; | 196 | int r; |
| 197 | bool mirror; | ||
| 199 | 198 | ||
| 200 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) | 199 | if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror) |
| 201 | return -ENOENT; | 200 | return -ENOENT; |
| 202 | 201 | ||
| 203 | r = kstrtoint(buf, 0, &mirror); | 202 | r = strtobool(buf, &mirror); |
| 204 | if (r) | 203 | if (r) |
| 205 | return r; | 204 | return r; |
| 206 | 205 | ||
| 207 | mirror = !!mirror; | ||
| 208 | |||
| 209 | r = dssdev->driver->set_mirror(dssdev, mirror); | 206 | r = dssdev->driver->set_mirror(dssdev, mirror); |
| 210 | if (r) | 207 | if (r) |
| 211 | return r; | 208 | return r; |
| @@ -302,11 +299,15 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
| 302 | return 16; | 299 | return 16; |
| 303 | 300 | ||
| 304 | case OMAP_DISPLAY_TYPE_DBI: | 301 | case OMAP_DISPLAY_TYPE_DBI: |
| 305 | case OMAP_DISPLAY_TYPE_DSI: | ||
| 306 | if (dssdev->ctrl.pixel_size == 24) | 302 | if (dssdev->ctrl.pixel_size == 24) |
| 307 | return 24; | 303 | return 24; |
| 308 | else | 304 | else |
| 309 | return 16; | 305 | return 16; |
| 306 | case OMAP_DISPLAY_TYPE_DSI: | ||
| 307 | if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) | ||
| 308 | return 24; | ||
| 309 | else | ||
| 310 | return 16; | ||
| 310 | case OMAP_DISPLAY_TYPE_VENC: | 311 | case OMAP_DISPLAY_TYPE_VENC: |
| 311 | case OMAP_DISPLAY_TYPE_SDI: | 312 | case OMAP_DISPLAY_TYPE_SDI: |
| 312 | case OMAP_DISPLAY_TYPE_HDMI: | 313 | case OMAP_DISPLAY_TYPE_HDMI: |
| @@ -342,9 +343,11 @@ bool dss_use_replication(struct omap_dss_device *dssdev, | |||
| 342 | bpp = 24; | 343 | bpp = 24; |
| 343 | break; | 344 | break; |
| 344 | case OMAP_DISPLAY_TYPE_DBI: | 345 | case OMAP_DISPLAY_TYPE_DBI: |
| 345 | case OMAP_DISPLAY_TYPE_DSI: | ||
| 346 | bpp = dssdev->ctrl.pixel_size; | 346 | bpp = dssdev->ctrl.pixel_size; |
| 347 | break; | 347 | break; |
| 348 | case OMAP_DISPLAY_TYPE_DSI: | ||
| 349 | bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
| 350 | break; | ||
| 348 | default: | 351 | default: |
| 349 | BUG(); | 352 | BUG(); |
| 350 | } | 353 | } |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index f053b180ecd7..976ac23dcd0c 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
| 27 | #include <linux/export.h> | ||
| 27 | #include <linux/err.h> | 28 | #include <linux/err.h> |
| 28 | #include <linux/errno.h> | 29 | #include <linux/errno.h> |
| 29 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
| @@ -82,9 +83,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
| 82 | 83 | ||
| 83 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); | 84 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
| 84 | 85 | ||
| 85 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 86 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
| 86 | if (r) | 87 | if (r) { |
| 88 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | ||
| 87 | return r; | 89 | return r; |
| 90 | } | ||
| 88 | 91 | ||
| 89 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; | 92 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
| 90 | *lck_div = dispc_cinfo.lck_div; | 93 | *lck_div = dispc_cinfo.lck_div; |
| @@ -109,7 +112,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
| 109 | if (r) | 112 | if (r) |
| 110 | return r; | 113 | return r; |
| 111 | 114 | ||
| 112 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 115 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
| 113 | if (r) | 116 | if (r) |
| 114 | return r; | 117 | return r; |
| 115 | 118 | ||
| @@ -129,7 +132,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
| 129 | bool is_tft; | 132 | bool is_tft; |
| 130 | int r = 0; | 133 | int r = 0; |
| 131 | 134 | ||
| 132 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 135 | dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
| 133 | dssdev->panel.acbi, dssdev->panel.acb); | 136 | dssdev->panel.acbi, dssdev->panel.acb); |
| 134 | 137 | ||
| 135 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 138 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
| @@ -153,7 +156,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
| 153 | t->pixel_clock = pck; | 156 | t->pixel_clock = pck; |
| 154 | } | 157 | } |
| 155 | 158 | ||
| 156 | dispc_set_lcd_timings(dssdev->manager->id, t); | 159 | dispc_mgr_set_lcd_timings(dssdev->manager->id, t); |
| 157 | 160 | ||
| 158 | return 0; | 161 | return 0; |
| 159 | } | 162 | } |
| @@ -164,11 +167,12 @@ static void dpi_basic_init(struct omap_dss_device *dssdev) | |||
| 164 | 167 | ||
| 165 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 168 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
| 166 | 169 | ||
| 167 | dispc_set_parallel_interface_mode(dssdev->manager->id, | 170 | dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); |
| 168 | OMAP_DSS_PARALLELMODE_BYPASS); | 171 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); |
| 169 | dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? | 172 | |
| 173 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, is_tft ? | ||
| 170 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); | 174 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); |
| 171 | dispc_set_tft_data_lines(dssdev->manager->id, | 175 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, |
| 172 | dssdev->phy.dpi.data_lines); | 176 | dssdev->phy.dpi.data_lines); |
| 173 | } | 177 | } |
| 174 | 178 | ||
| @@ -176,6 +180,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
| 176 | { | 180 | { |
| 177 | int r; | 181 | int r; |
| 178 | 182 | ||
| 183 | if (dssdev->manager == NULL) { | ||
| 184 | DSSERR("failed to enable display: no manager\n"); | ||
| 185 | return -ENODEV; | ||
| 186 | } | ||
| 187 | |||
| 179 | r = omap_dss_start_device(dssdev); | 188 | r = omap_dss_start_device(dssdev); |
| 180 | if (r) { | 189 | if (r) { |
| 181 | DSSERR("failed to start device\n"); | 190 | DSSERR("failed to start device\n"); |
| @@ -277,7 +286,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev, | |||
| 277 | } | 286 | } |
| 278 | 287 | ||
| 279 | dpi_set_mode(dssdev); | 288 | dpi_set_mode(dssdev); |
| 280 | dispc_go(dssdev->manager->id); | 289 | dispc_mgr_go(dssdev->manager->id); |
| 281 | 290 | ||
| 282 | dispc_runtime_put(); | 291 | dispc_runtime_put(); |
| 283 | dss_runtime_put(); | 292 | dss_runtime_put(); |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 7adbbeb84334..5abf8e7e7456 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
| 29 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
| 30 | #include <linux/module.h> | ||
| 30 | #include <linux/semaphore.h> | 31 | #include <linux/semaphore.h> |
| 31 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
| 32 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
| @@ -39,6 +40,7 @@ | |||
| 39 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
| 40 | 41 | ||
| 41 | #include <video/omapdss.h> | 42 | #include <video/omapdss.h> |
| 43 | #include <video/mipi_display.h> | ||
| 42 | #include <plat/clock.h> | 44 | #include <plat/clock.h> |
| 43 | 45 | ||
| 44 | #include "dss.h" | 46 | #include "dss.h" |
| @@ -131,7 +133,7 @@ struct dsi_reg { u16 idx; }; | |||
| 131 | #define DSI_IRQ_TA_TIMEOUT (1 << 20) | 133 | #define DSI_IRQ_TA_TIMEOUT (1 << 20) |
| 132 | #define DSI_IRQ_ERROR_MASK \ | 134 | #define DSI_IRQ_ERROR_MASK \ |
| 133 | (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ | 135 | (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ |
| 134 | DSI_IRQ_TA_TIMEOUT) | 136 | DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) |
| 135 | #define DSI_IRQ_CHANNEL_MASK 0xf | 137 | #define DSI_IRQ_CHANNEL_MASK 0xf |
| 136 | 138 | ||
| 137 | /* Virtual channel interrupts */ | 139 | /* Virtual channel interrupts */ |
| @@ -198,18 +200,6 @@ struct dsi_reg { u16 idx; }; | |||
| 198 | DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ | 200 | DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ |
| 199 | DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) | 201 | DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) |
| 200 | 202 | ||
| 201 | #define DSI_DT_DCS_SHORT_WRITE_0 0x05 | ||
| 202 | #define DSI_DT_DCS_SHORT_WRITE_1 0x15 | ||
| 203 | #define DSI_DT_DCS_READ 0x06 | ||
| 204 | #define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37 | ||
| 205 | #define DSI_DT_NULL_PACKET 0x09 | ||
| 206 | #define DSI_DT_DCS_LONG_WRITE 0x39 | ||
| 207 | |||
| 208 | #define DSI_DT_RX_ACK_WITH_ERR 0x02 | ||
| 209 | #define DSI_DT_RX_DCS_LONG_READ 0x1c | ||
| 210 | #define DSI_DT_RX_SHORT_READ_1 0x21 | ||
| 211 | #define DSI_DT_RX_SHORT_READ_2 0x22 | ||
| 212 | |||
| 213 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); | 203 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
| 214 | 204 | ||
| 215 | #define DSI_MAX_NR_ISRS 2 | 205 | #define DSI_MAX_NR_ISRS 2 |
| @@ -228,9 +218,9 @@ enum fifo_size { | |||
| 228 | DSI_FIFO_SIZE_128 = 4, | 218 | DSI_FIFO_SIZE_128 = 4, |
| 229 | }; | 219 | }; |
| 230 | 220 | ||
| 231 | enum dsi_vc_mode { | 221 | enum dsi_vc_source { |
| 232 | DSI_VC_MODE_L4 = 0, | 222 | DSI_VC_SOURCE_L4 = 0, |
| 233 | DSI_VC_MODE_VP, | 223 | DSI_VC_SOURCE_VP, |
| 234 | }; | 224 | }; |
| 235 | 225 | ||
| 236 | enum dsi_lane { | 226 | enum dsi_lane { |
| @@ -274,7 +264,8 @@ struct dsi_data { | |||
| 274 | struct clk *dss_clk; | 264 | struct clk *dss_clk; |
| 275 | struct clk *sys_clk; | 265 | struct clk *sys_clk; |
| 276 | 266 | ||
| 277 | void (*dsi_mux_pads)(bool enable); | 267 | int (*enable_pads)(int dsi_id, unsigned lane_mask); |
| 268 | void (*disable_pads)(int dsi_id, unsigned lane_mask); | ||
| 278 | 269 | ||
| 279 | struct dsi_clock_info current_cinfo; | 270 | struct dsi_clock_info current_cinfo; |
| 280 | 271 | ||
| @@ -282,7 +273,7 @@ struct dsi_data { | |||
| 282 | struct regulator *vdds_dsi_reg; | 273 | struct regulator *vdds_dsi_reg; |
| 283 | 274 | ||
| 284 | struct { | 275 | struct { |
| 285 | enum dsi_vc_mode mode; | 276 | enum dsi_vc_source source; |
| 286 | struct omap_dss_device *dssdev; | 277 | struct omap_dss_device *dssdev; |
| 287 | enum fifo_size fifo_size; | 278 | enum fifo_size fifo_size; |
| 288 | int vc_id; | 279 | int vc_id; |
| @@ -368,14 +359,9 @@ struct platform_device *dsi_get_dsidev_from_id(int module) | |||
| 368 | return dsi_pdev_map[module]; | 359 | return dsi_pdev_map[module]; |
| 369 | } | 360 | } |
| 370 | 361 | ||
| 371 | static int dsi_get_dsidev_id(struct platform_device *dsidev) | 362 | static inline int dsi_get_dsidev_id(struct platform_device *dsidev) |
| 372 | { | 363 | { |
| 373 | /* TEMP: Pass 0 as the dsi module index till the time the dsi platform | 364 | return dsidev->id; |
| 374 | * device names aren't changed to the form "omapdss_dsi.0", | ||
| 375 | * "omapdss_dsi.1" and so on */ | ||
| 376 | BUG_ON(dsidev->id != -1); | ||
| 377 | |||
| 378 | return 0; | ||
| 379 | } | 365 | } |
| 380 | 366 | ||
| 381 | static inline void dsi_write_reg(struct platform_device *dsidev, | 367 | static inline void dsi_write_reg(struct platform_device *dsidev, |
| @@ -437,6 +423,21 @@ static inline int wait_for_bit_change(struct platform_device *dsidev, | |||
| 437 | return value; | 423 | return value; |
| 438 | } | 424 | } |
| 439 | 425 | ||
| 426 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | ||
| 427 | { | ||
| 428 | switch (fmt) { | ||
| 429 | case OMAP_DSS_DSI_FMT_RGB888: | ||
| 430 | case OMAP_DSS_DSI_FMT_RGB666: | ||
| 431 | return 24; | ||
| 432 | case OMAP_DSS_DSI_FMT_RGB666_PACKED: | ||
| 433 | return 18; | ||
| 434 | case OMAP_DSS_DSI_FMT_RGB565: | ||
| 435 | return 16; | ||
| 436 | default: | ||
| 437 | BUG(); | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 440 | #ifdef DEBUG | 441 | #ifdef DEBUG |
| 441 | static void dsi_perf_mark_setup(struct platform_device *dsidev) | 442 | static void dsi_perf_mark_setup(struct platform_device *dsidev) |
| 442 | { | 443 | { |
| @@ -453,6 +454,7 @@ static void dsi_perf_mark_start(struct platform_device *dsidev) | |||
| 453 | static void dsi_perf_show(struct platform_device *dsidev, const char *name) | 454 | static void dsi_perf_show(struct platform_device *dsidev, const char *name) |
| 454 | { | 455 | { |
| 455 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 456 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 457 | struct omap_dss_device *dssdev = dsi->update_region.device; | ||
| 456 | ktime_t t, setup_time, trans_time; | 458 | ktime_t t, setup_time, trans_time; |
| 457 | u32 total_bytes; | 459 | u32 total_bytes; |
| 458 | u32 setup_us, trans_us, total_us; | 460 | u32 setup_us, trans_us, total_us; |
| @@ -476,7 +478,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) | |||
| 476 | 478 | ||
| 477 | total_bytes = dsi->update_region.w * | 479 | total_bytes = dsi->update_region.w * |
| 478 | dsi->update_region.h * | 480 | dsi->update_region.h * |
| 479 | dsi->update_region.device->ctrl.pixel_size / 8; | 481 | dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; |
| 480 | 482 | ||
| 481 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " | 483 | printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " |
| 482 | "%u bytes, %u kbytes/sec\n", | 484 | "%u bytes, %u kbytes/sec\n", |
| @@ -1287,7 +1289,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
| 1287 | * with DSS_SYS_CLK source also */ | 1289 | * with DSS_SYS_CLK source also */ |
| 1288 | cinfo->highfreq = 0; | 1290 | cinfo->highfreq = 0; |
| 1289 | } else { | 1291 | } else { |
| 1290 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); | 1292 | cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id); |
| 1291 | 1293 | ||
| 1292 | if (cinfo->clkin < 32000000) | 1294 | if (cinfo->clkin < 32000000) |
| 1293 | cinfo->highfreq = 0; | 1295 | cinfo->highfreq = 0; |
| @@ -2360,6 +2362,24 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) | |||
| 2360 | return 0; | 2362 | return 0; |
| 2361 | } | 2363 | } |
| 2362 | 2364 | ||
| 2365 | static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) | ||
| 2366 | { | ||
| 2367 | unsigned lanes = 0; | ||
| 2368 | |||
| 2369 | if (dssdev->phy.dsi.clk_lane != 0) | ||
| 2370 | lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); | ||
| 2371 | if (dssdev->phy.dsi.data1_lane != 0) | ||
| 2372 | lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); | ||
| 2373 | if (dssdev->phy.dsi.data2_lane != 0) | ||
| 2374 | lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1); | ||
| 2375 | if (dssdev->phy.dsi.data3_lane != 0) | ||
| 2376 | lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1); | ||
| 2377 | if (dssdev->phy.dsi.data4_lane != 0) | ||
| 2378 | lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1); | ||
| 2379 | |||
| 2380 | return lanes; | ||
| 2381 | } | ||
| 2382 | |||
| 2363 | static int dsi_cio_init(struct omap_dss_device *dssdev) | 2383 | static int dsi_cio_init(struct omap_dss_device *dssdev) |
| 2364 | { | 2384 | { |
| 2365 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 2385 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| @@ -2370,8 +2390,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
| 2370 | 2390 | ||
| 2371 | DSSDBGF(); | 2391 | DSSDBGF(); |
| 2372 | 2392 | ||
| 2373 | if (dsi->dsi_mux_pads) | 2393 | r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); |
| 2374 | dsi->dsi_mux_pads(true); | 2394 | if (r) |
| 2395 | return r; | ||
| 2375 | 2396 | ||
| 2376 | dsi_enable_scp_clk(dsidev); | 2397 | dsi_enable_scp_clk(dsidev); |
| 2377 | 2398 | ||
| @@ -2452,6 +2473,12 @@ static int dsi_cio_init(struct omap_dss_device *dssdev) | |||
| 2452 | 2473 | ||
| 2453 | dsi_cio_timings(dsidev); | 2474 | dsi_cio_timings(dsidev); |
| 2454 | 2475 | ||
| 2476 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
| 2477 | /* DDR_CLK_ALWAYS_ON */ | ||
| 2478 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, | ||
| 2479 | dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); | ||
| 2480 | } | ||
| 2481 | |||
| 2455 | dsi->ulps_enabled = false; | 2482 | dsi->ulps_enabled = false; |
| 2456 | 2483 | ||
| 2457 | DSSDBG("CIO init done\n"); | 2484 | DSSDBG("CIO init done\n"); |
| @@ -2467,19 +2494,21 @@ err_cio_pwr: | |||
| 2467 | dsi_cio_disable_lane_override(dsidev); | 2494 | dsi_cio_disable_lane_override(dsidev); |
| 2468 | err_scp_clk_dom: | 2495 | err_scp_clk_dom: |
| 2469 | dsi_disable_scp_clk(dsidev); | 2496 | dsi_disable_scp_clk(dsidev); |
| 2470 | if (dsi->dsi_mux_pads) | 2497 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); |
| 2471 | dsi->dsi_mux_pads(false); | ||
| 2472 | return r; | 2498 | return r; |
| 2473 | } | 2499 | } |
| 2474 | 2500 | ||
| 2475 | static void dsi_cio_uninit(struct platform_device *dsidev) | 2501 | static void dsi_cio_uninit(struct omap_dss_device *dssdev) |
| 2476 | { | 2502 | { |
| 2503 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 2477 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 2504 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 2478 | 2505 | ||
| 2506 | /* DDR_CLK_ALWAYS_ON */ | ||
| 2507 | REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); | ||
| 2508 | |||
| 2479 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); | 2509 | dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); |
| 2480 | dsi_disable_scp_clk(dsidev); | 2510 | dsi_disable_scp_clk(dsidev); |
| 2481 | if (dsi->dsi_mux_pads) | 2511 | dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); |
| 2482 | dsi->dsi_mux_pads(false); | ||
| 2483 | } | 2512 | } |
| 2484 | 2513 | ||
| 2485 | static void dsi_config_tx_fifo(struct platform_device *dsidev, | 2514 | static void dsi_config_tx_fifo(struct platform_device *dsidev, |
| @@ -2669,10 +2698,10 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel) | |||
| 2669 | if (!dsi_vc_is_enabled(dsidev, channel)) | 2698 | if (!dsi_vc_is_enabled(dsidev, channel)) |
| 2670 | return 0; | 2699 | return 0; |
| 2671 | 2700 | ||
| 2672 | switch (dsi->vc[channel].mode) { | 2701 | switch (dsi->vc[channel].source) { |
| 2673 | case DSI_VC_MODE_VP: | 2702 | case DSI_VC_SOURCE_VP: |
| 2674 | return dsi_sync_vc_vp(dsidev, channel); | 2703 | return dsi_sync_vc_vp(dsidev, channel); |
| 2675 | case DSI_VC_MODE_L4: | 2704 | case DSI_VC_SOURCE_L4: |
| 2676 | return dsi_sync_vc_l4(dsidev, channel); | 2705 | return dsi_sync_vc_l4(dsidev, channel); |
| 2677 | default: | 2706 | default: |
| 2678 | BUG(); | 2707 | BUG(); |
| @@ -2726,43 +2755,12 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) | |||
| 2726 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); | 2755 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); |
| 2727 | } | 2756 | } |
| 2728 | 2757 | ||
| 2729 | static int dsi_vc_config_l4(struct platform_device *dsidev, int channel) | 2758 | static int dsi_vc_config_source(struct platform_device *dsidev, int channel, |
| 2759 | enum dsi_vc_source source) | ||
| 2730 | { | 2760 | { |
| 2731 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 2761 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 2732 | 2762 | ||
| 2733 | if (dsi->vc[channel].mode == DSI_VC_MODE_L4) | 2763 | if (dsi->vc[channel].source == source) |
| 2734 | return 0; | ||
| 2735 | |||
| 2736 | DSSDBGF("%d", channel); | ||
| 2737 | |||
| 2738 | dsi_sync_vc(dsidev, channel); | ||
| 2739 | |||
| 2740 | dsi_vc_enable(dsidev, channel, 0); | ||
| 2741 | |||
| 2742 | /* VC_BUSY */ | ||
| 2743 | if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { | ||
| 2744 | DSSERR("vc(%d) busy when trying to config for L4\n", channel); | ||
| 2745 | return -EIO; | ||
| 2746 | } | ||
| 2747 | |||
| 2748 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */ | ||
| 2749 | |||
| 2750 | /* DCS_CMD_ENABLE */ | ||
| 2751 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | ||
| 2752 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30); | ||
| 2753 | |||
| 2754 | dsi_vc_enable(dsidev, channel, 1); | ||
| 2755 | |||
| 2756 | dsi->vc[channel].mode = DSI_VC_MODE_L4; | ||
| 2757 | |||
| 2758 | return 0; | ||
| 2759 | } | ||
| 2760 | |||
| 2761 | static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) | ||
| 2762 | { | ||
| 2763 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
| 2764 | |||
| 2765 | if (dsi->vc[channel].mode == DSI_VC_MODE_VP) | ||
| 2766 | return 0; | 2764 | return 0; |
| 2767 | 2765 | ||
| 2768 | DSSDBGF("%d", channel); | 2766 | DSSDBGF("%d", channel); |
| @@ -2777,21 +2775,22 @@ static int dsi_vc_config_vp(struct platform_device *dsidev, int channel) | |||
| 2777 | return -EIO; | 2775 | return -EIO; |
| 2778 | } | 2776 | } |
| 2779 | 2777 | ||
| 2780 | /* SOURCE, 1 = video port */ | 2778 | /* SOURCE, 0 = L4, 1 = video port */ |
| 2781 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1); | 2779 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1); |
| 2782 | 2780 | ||
| 2783 | /* DCS_CMD_ENABLE */ | 2781 | /* DCS_CMD_ENABLE */ |
| 2784 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) | 2782 | if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { |
| 2785 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30); | 2783 | bool enable = source == DSI_VC_SOURCE_VP; |
| 2784 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30); | ||
| 2785 | } | ||
| 2786 | 2786 | ||
| 2787 | dsi_vc_enable(dsidev, channel, 1); | 2787 | dsi_vc_enable(dsidev, channel, 1); |
| 2788 | 2788 | ||
| 2789 | dsi->vc[channel].mode = DSI_VC_MODE_VP; | 2789 | dsi->vc[channel].source = source; |
| 2790 | 2790 | ||
| 2791 | return 0; | 2791 | return 0; |
| 2792 | } | 2792 | } |
| 2793 | 2793 | ||
| 2794 | |||
| 2795 | void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, | 2794 | void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, |
| 2796 | bool enable) | 2795 | bool enable) |
| 2797 | { | 2796 | { |
| @@ -2810,6 +2809,10 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, | |||
| 2810 | dsi_if_enable(dsidev, 1); | 2809 | dsi_if_enable(dsidev, 1); |
| 2811 | 2810 | ||
| 2812 | dsi_force_tx_stop_mode_io(dsidev); | 2811 | dsi_force_tx_stop_mode_io(dsidev); |
| 2812 | |||
| 2813 | /* start the DDR clock by sending a NULL packet */ | ||
| 2814 | if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) | ||
| 2815 | dsi_vc_send_null(dssdev, channel); | ||
| 2813 | } | 2816 | } |
| 2814 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); | 2817 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); |
| 2815 | 2818 | ||
| @@ -2873,16 +2876,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev, | |||
| 2873 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); | 2876 | val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); |
| 2874 | DSSERR("\trawval %#08x\n", val); | 2877 | DSSERR("\trawval %#08x\n", val); |
| 2875 | dt = FLD_GET(val, 5, 0); | 2878 | dt = FLD_GET(val, 5, 0); |
| 2876 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 2879 | if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) { |
| 2877 | u16 err = FLD_GET(val, 23, 8); | 2880 | u16 err = FLD_GET(val, 23, 8); |
| 2878 | dsi_show_rx_ack_with_err(err); | 2881 | dsi_show_rx_ack_with_err(err); |
| 2879 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 2882 | } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) { |
| 2880 | DSSERR("\tDCS short response, 1 byte: %#x\n", | 2883 | DSSERR("\tDCS short response, 1 byte: %#x\n", |
| 2881 | FLD_GET(val, 23, 8)); | 2884 | FLD_GET(val, 23, 8)); |
| 2882 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 2885 | } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) { |
| 2883 | DSSERR("\tDCS short response, 2 byte: %#x\n", | 2886 | DSSERR("\tDCS short response, 2 byte: %#x\n", |
| 2884 | FLD_GET(val, 23, 8)); | 2887 | FLD_GET(val, 23, 8)); |
| 2885 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 2888 | } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) { |
| 2886 | DSSERR("\tDCS long response, len %d\n", | 2889 | DSSERR("\tDCS long response, len %d\n", |
| 2887 | FLD_GET(val, 23, 8)); | 2890 | FLD_GET(val, 23, 8)); |
| 2888 | dsi_vc_flush_long_data(dsidev, channel); | 2891 | dsi_vc_flush_long_data(dsidev, channel); |
| @@ -3007,7 +3010,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel, | |||
| 3007 | return -EINVAL; | 3010 | return -EINVAL; |
| 3008 | } | 3011 | } |
| 3009 | 3012 | ||
| 3010 | dsi_vc_config_l4(dsidev, channel); | 3013 | dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4); |
| 3011 | 3014 | ||
| 3012 | dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); | 3015 | dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); |
| 3013 | 3016 | ||
| @@ -3066,7 +3069,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel, | |||
| 3066 | channel, | 3069 | channel, |
| 3067 | data_type, data & 0xff, (data >> 8) & 0xff); | 3070 | data_type, data & 0xff, (data >> 8) & 0xff); |
| 3068 | 3071 | ||
| 3069 | dsi_vc_config_l4(dsidev, channel); | 3072 | dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4); |
| 3070 | 3073 | ||
| 3071 | if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { | 3074 | if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { |
| 3072 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); | 3075 | DSSERR("ERROR FIFO FULL, aborting transfer\n"); |
| @@ -3085,44 +3088,66 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel, | |||
| 3085 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) | 3088 | int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) |
| 3086 | { | 3089 | { |
| 3087 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3090 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 3088 | u8 nullpkg[] = {0, 0, 0, 0}; | ||
| 3089 | 3091 | ||
| 3090 | return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg, | 3092 | return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL, |
| 3091 | 4, 0); | 3093 | 0, 0); |
| 3092 | } | 3094 | } |
| 3093 | EXPORT_SYMBOL(dsi_vc_send_null); | 3095 | EXPORT_SYMBOL(dsi_vc_send_null); |
| 3094 | 3096 | ||
| 3095 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, | 3097 | static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, |
| 3096 | u8 *data, int len) | 3098 | int channel, u8 *data, int len, enum dss_dsi_content_type type) |
| 3097 | { | 3099 | { |
| 3098 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3100 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 3099 | int r; | 3101 | int r; |
| 3100 | 3102 | ||
| 3101 | BUG_ON(len == 0); | 3103 | if (len == 0) { |
| 3102 | 3104 | BUG_ON(type == DSS_DSI_CONTENT_DCS); | |
| 3103 | if (len == 1) { | 3105 | r = dsi_vc_send_short(dsidev, channel, |
| 3104 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0, | 3106 | MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0); |
| 3105 | data[0], 0); | 3107 | } else if (len == 1) { |
| 3108 | r = dsi_vc_send_short(dsidev, channel, | ||
| 3109 | type == DSS_DSI_CONTENT_GENERIC ? | ||
| 3110 | MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM : | ||
| 3111 | MIPI_DSI_DCS_SHORT_WRITE, data[0], 0); | ||
| 3106 | } else if (len == 2) { | 3112 | } else if (len == 2) { |
| 3107 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1, | 3113 | r = dsi_vc_send_short(dsidev, channel, |
| 3114 | type == DSS_DSI_CONTENT_GENERIC ? | ||
| 3115 | MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM : | ||
| 3116 | MIPI_DSI_DCS_SHORT_WRITE_PARAM, | ||
| 3108 | data[0] | (data[1] << 8), 0); | 3117 | data[0] | (data[1] << 8), 0); |
| 3109 | } else { | 3118 | } else { |
| 3110 | /* 0x39 = DCS Long Write */ | 3119 | r = dsi_vc_send_long(dsidev, channel, |
| 3111 | r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE, | 3120 | type == DSS_DSI_CONTENT_GENERIC ? |
| 3112 | data, len, 0); | 3121 | MIPI_DSI_GENERIC_LONG_WRITE : |
| 3122 | MIPI_DSI_DCS_LONG_WRITE, data, len, 0); | ||
| 3113 | } | 3123 | } |
| 3114 | 3124 | ||
| 3115 | return r; | 3125 | return r; |
| 3116 | } | 3126 | } |
| 3127 | |||
| 3128 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, | ||
| 3129 | u8 *data, int len) | ||
| 3130 | { | ||
| 3131 | return dsi_vc_write_nosync_common(dssdev, channel, data, len, | ||
| 3132 | DSS_DSI_CONTENT_DCS); | ||
| 3133 | } | ||
| 3117 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); | 3134 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); |
| 3118 | 3135 | ||
| 3119 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | 3136 | int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, |
| 3120 | int len) | 3137 | u8 *data, int len) |
| 3138 | { | ||
| 3139 | return dsi_vc_write_nosync_common(dssdev, channel, data, len, | ||
| 3140 | DSS_DSI_CONTENT_GENERIC); | ||
| 3141 | } | ||
| 3142 | EXPORT_SYMBOL(dsi_vc_generic_write_nosync); | ||
| 3143 | |||
| 3144 | static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel, | ||
| 3145 | u8 *data, int len, enum dss_dsi_content_type type) | ||
| 3121 | { | 3146 | { |
| 3122 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3147 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 3123 | int r; | 3148 | int r; |
| 3124 | 3149 | ||
| 3125 | r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len); | 3150 | r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); |
| 3126 | if (r) | 3151 | if (r) |
| 3127 | goto err; | 3152 | goto err; |
| 3128 | 3153 | ||
| @@ -3140,18 +3165,39 @@ int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | |||
| 3140 | 3165 | ||
| 3141 | return 0; | 3166 | return 0; |
| 3142 | err: | 3167 | err: |
| 3143 | DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n", | 3168 | DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n", |
| 3144 | channel, data[0], len); | 3169 | channel, data[0], len); |
| 3145 | return r; | 3170 | return r; |
| 3146 | } | 3171 | } |
| 3172 | |||
| 3173 | int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data, | ||
| 3174 | int len) | ||
| 3175 | { | ||
| 3176 | return dsi_vc_write_common(dssdev, channel, data, len, | ||
| 3177 | DSS_DSI_CONTENT_DCS); | ||
| 3178 | } | ||
| 3147 | EXPORT_SYMBOL(dsi_vc_dcs_write); | 3179 | EXPORT_SYMBOL(dsi_vc_dcs_write); |
| 3148 | 3180 | ||
| 3181 | int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data, | ||
| 3182 | int len) | ||
| 3183 | { | ||
| 3184 | return dsi_vc_write_common(dssdev, channel, data, len, | ||
| 3185 | DSS_DSI_CONTENT_GENERIC); | ||
| 3186 | } | ||
| 3187 | EXPORT_SYMBOL(dsi_vc_generic_write); | ||
| 3188 | |||
| 3149 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) | 3189 | int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) |
| 3150 | { | 3190 | { |
| 3151 | return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); | 3191 | return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); |
| 3152 | } | 3192 | } |
| 3153 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); | 3193 | EXPORT_SYMBOL(dsi_vc_dcs_write_0); |
| 3154 | 3194 | ||
| 3195 | int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel) | ||
| 3196 | { | ||
| 3197 | return dsi_vc_generic_write(dssdev, channel, NULL, 0); | ||
| 3198 | } | ||
| 3199 | EXPORT_SYMBOL(dsi_vc_generic_write_0); | ||
| 3200 | |||
| 3155 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3201 | int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, |
| 3156 | u8 param) | 3202 | u8 param) |
| 3157 | { | 3203 | { |
| @@ -3162,25 +3208,87 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
| 3162 | } | 3208 | } |
| 3163 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); | 3209 | EXPORT_SYMBOL(dsi_vc_dcs_write_1); |
| 3164 | 3210 | ||
| 3165 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3211 | int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, |
| 3166 | u8 *buf, int buflen) | 3212 | u8 param) |
| 3213 | { | ||
| 3214 | return dsi_vc_generic_write(dssdev, channel, ¶m, 1); | ||
| 3215 | } | ||
| 3216 | EXPORT_SYMBOL(dsi_vc_generic_write_1); | ||
| 3217 | |||
| 3218 | int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel, | ||
| 3219 | u8 param1, u8 param2) | ||
| 3220 | { | ||
| 3221 | u8 buf[2]; | ||
| 3222 | buf[0] = param1; | ||
| 3223 | buf[1] = param2; | ||
| 3224 | return dsi_vc_generic_write(dssdev, channel, buf, 2); | ||
| 3225 | } | ||
| 3226 | EXPORT_SYMBOL(dsi_vc_generic_write_2); | ||
| 3227 | |||
| 3228 | static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, | ||
| 3229 | int channel, u8 dcs_cmd) | ||
| 3167 | { | 3230 | { |
| 3168 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3231 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 3169 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3232 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 3170 | u32 val; | ||
| 3171 | u8 dt; | ||
| 3172 | int r; | 3233 | int r; |
| 3173 | 3234 | ||
| 3174 | if (dsi->debug_read) | 3235 | if (dsi->debug_read) |
| 3175 | DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd); | 3236 | DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n", |
| 3237 | channel, dcs_cmd); | ||
| 3176 | 3238 | ||
| 3177 | r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0); | 3239 | r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0); |
| 3178 | if (r) | 3240 | if (r) { |
| 3179 | goto err; | 3241 | DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)" |
| 3242 | " failed\n", channel, dcs_cmd); | ||
| 3243 | return r; | ||
| 3244 | } | ||
| 3180 | 3245 | ||
| 3181 | r = dsi_vc_send_bta_sync(dssdev, channel); | 3246 | return 0; |
| 3182 | if (r) | 3247 | } |
| 3183 | goto err; | 3248 | |
| 3249 | static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, | ||
| 3250 | int channel, u8 *reqdata, int reqlen) | ||
| 3251 | { | ||
| 3252 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3253 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
| 3254 | u16 data; | ||
| 3255 | u8 data_type; | ||
| 3256 | int r; | ||
| 3257 | |||
| 3258 | if (dsi->debug_read) | ||
| 3259 | DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n", | ||
| 3260 | channel, reqlen); | ||
| 3261 | |||
| 3262 | if (reqlen == 0) { | ||
| 3263 | data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; | ||
| 3264 | data = 0; | ||
| 3265 | } else if (reqlen == 1) { | ||
| 3266 | data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; | ||
| 3267 | data = reqdata[0]; | ||
| 3268 | } else if (reqlen == 2) { | ||
| 3269 | data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; | ||
| 3270 | data = reqdata[0] | (reqdata[1] << 8); | ||
| 3271 | } else { | ||
| 3272 | BUG(); | ||
| 3273 | } | ||
| 3274 | |||
| 3275 | r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); | ||
| 3276 | if (r) { | ||
| 3277 | DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)" | ||
| 3278 | " failed\n", channel, reqlen); | ||
| 3279 | return r; | ||
| 3280 | } | ||
| 3281 | |||
| 3282 | return 0; | ||
| 3283 | } | ||
| 3284 | |||
| 3285 | static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, | ||
| 3286 | u8 *buf, int buflen, enum dss_dsi_content_type type) | ||
| 3287 | { | ||
| 3288 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
| 3289 | u32 val; | ||
| 3290 | u8 dt; | ||
| 3291 | int r; | ||
| 3184 | 3292 | ||
| 3185 | /* RX_FIFO_NOT_EMPTY */ | 3293 | /* RX_FIFO_NOT_EMPTY */ |
| 3186 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { | 3294 | if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { |
| @@ -3193,16 +3301,20 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
| 3193 | if (dsi->debug_read) | 3301 | if (dsi->debug_read) |
| 3194 | DSSDBG("\theader: %08x\n", val); | 3302 | DSSDBG("\theader: %08x\n", val); |
| 3195 | dt = FLD_GET(val, 5, 0); | 3303 | dt = FLD_GET(val, 5, 0); |
| 3196 | if (dt == DSI_DT_RX_ACK_WITH_ERR) { | 3304 | if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) { |
| 3197 | u16 err = FLD_GET(val, 23, 8); | 3305 | u16 err = FLD_GET(val, 23, 8); |
| 3198 | dsi_show_rx_ack_with_err(err); | 3306 | dsi_show_rx_ack_with_err(err); |
| 3199 | r = -EIO; | 3307 | r = -EIO; |
| 3200 | goto err; | 3308 | goto err; |
| 3201 | 3309 | ||
| 3202 | } else if (dt == DSI_DT_RX_SHORT_READ_1) { | 3310 | } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? |
| 3311 | MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE : | ||
| 3312 | MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) { | ||
| 3203 | u8 data = FLD_GET(val, 15, 8); | 3313 | u8 data = FLD_GET(val, 15, 8); |
| 3204 | if (dsi->debug_read) | 3314 | if (dsi->debug_read) |
| 3205 | DSSDBG("\tDCS short response, 1 byte: %02x\n", data); | 3315 | DSSDBG("\t%s short response, 1 byte: %02x\n", |
| 3316 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : | ||
| 3317 | "DCS", data); | ||
| 3206 | 3318 | ||
| 3207 | if (buflen < 1) { | 3319 | if (buflen < 1) { |
| 3208 | r = -EIO; | 3320 | r = -EIO; |
| @@ -3212,10 +3324,14 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
| 3212 | buf[0] = data; | 3324 | buf[0] = data; |
| 3213 | 3325 | ||
| 3214 | return 1; | 3326 | return 1; |
| 3215 | } else if (dt == DSI_DT_RX_SHORT_READ_2) { | 3327 | } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? |
| 3328 | MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE : | ||
| 3329 | MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) { | ||
| 3216 | u16 data = FLD_GET(val, 23, 8); | 3330 | u16 data = FLD_GET(val, 23, 8); |
| 3217 | if (dsi->debug_read) | 3331 | if (dsi->debug_read) |
| 3218 | DSSDBG("\tDCS short response, 2 byte: %04x\n", data); | 3332 | DSSDBG("\t%s short response, 2 byte: %04x\n", |
| 3333 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : | ||
| 3334 | "DCS", data); | ||
| 3219 | 3335 | ||
| 3220 | if (buflen < 2) { | 3336 | if (buflen < 2) { |
| 3221 | r = -EIO; | 3337 | r = -EIO; |
| @@ -3226,11 +3342,15 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
| 3226 | buf[1] = (data >> 8) & 0xff; | 3342 | buf[1] = (data >> 8) & 0xff; |
| 3227 | 3343 | ||
| 3228 | return 2; | 3344 | return 2; |
| 3229 | } else if (dt == DSI_DT_RX_DCS_LONG_READ) { | 3345 | } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? |
| 3346 | MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE : | ||
| 3347 | MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) { | ||
| 3230 | int w; | 3348 | int w; |
| 3231 | int len = FLD_GET(val, 23, 8); | 3349 | int len = FLD_GET(val, 23, 8); |
| 3232 | if (dsi->debug_read) | 3350 | if (dsi->debug_read) |
| 3233 | DSSDBG("\tDCS long response, len %d\n", len); | 3351 | DSSDBG("\t%s long response, len %d\n", |
| 3352 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : | ||
| 3353 | "DCS", len); | ||
| 3234 | 3354 | ||
| 3235 | if (len > buflen) { | 3355 | if (len > buflen) { |
| 3236 | r = -EIO; | 3356 | r = -EIO; |
| @@ -3266,58 +3386,126 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | |||
| 3266 | 3386 | ||
| 3267 | BUG(); | 3387 | BUG(); |
| 3268 | err: | 3388 | err: |
| 3269 | DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", | 3389 | DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, |
| 3270 | channel, dcs_cmd); | 3390 | type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); |
| 3391 | |||
| 3271 | return r; | 3392 | return r; |
| 3393 | } | ||
| 3272 | 3394 | ||
| 3395 | int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | ||
| 3396 | u8 *buf, int buflen) | ||
| 3397 | { | ||
| 3398 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3399 | int r; | ||
| 3400 | |||
| 3401 | r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); | ||
| 3402 | if (r) | ||
| 3403 | goto err; | ||
| 3404 | |||
| 3405 | r = dsi_vc_send_bta_sync(dssdev, channel); | ||
| 3406 | if (r) | ||
| 3407 | goto err; | ||
| 3408 | |||
| 3409 | r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, | ||
| 3410 | DSS_DSI_CONTENT_DCS); | ||
| 3411 | if (r < 0) | ||
| 3412 | goto err; | ||
| 3413 | |||
| 3414 | if (r != buflen) { | ||
| 3415 | r = -EIO; | ||
| 3416 | goto err; | ||
| 3417 | } | ||
| 3418 | |||
| 3419 | return 0; | ||
| 3420 | err: | ||
| 3421 | DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd); | ||
| 3422 | return r; | ||
| 3273 | } | 3423 | } |
| 3274 | EXPORT_SYMBOL(dsi_vc_dcs_read); | 3424 | EXPORT_SYMBOL(dsi_vc_dcs_read); |
| 3275 | 3425 | ||
| 3276 | int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3426 | static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel, |
| 3277 | u8 *data) | 3427 | u8 *reqdata, int reqlen, u8 *buf, int buflen) |
| 3278 | { | 3428 | { |
| 3429 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3279 | int r; | 3430 | int r; |
| 3280 | 3431 | ||
| 3281 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1); | 3432 | r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); |
| 3433 | if (r) | ||
| 3434 | return r; | ||
| 3435 | |||
| 3436 | r = dsi_vc_send_bta_sync(dssdev, channel); | ||
| 3437 | if (r) | ||
| 3438 | return r; | ||
| 3282 | 3439 | ||
| 3440 | r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen, | ||
| 3441 | DSS_DSI_CONTENT_GENERIC); | ||
| 3283 | if (r < 0) | 3442 | if (r < 0) |
| 3284 | return r; | 3443 | return r; |
| 3285 | 3444 | ||
| 3286 | if (r != 1) | 3445 | if (r != buflen) { |
| 3287 | return -EIO; | 3446 | r = -EIO; |
| 3447 | return r; | ||
| 3448 | } | ||
| 3288 | 3449 | ||
| 3289 | return 0; | 3450 | return 0; |
| 3290 | } | 3451 | } |
| 3291 | EXPORT_SYMBOL(dsi_vc_dcs_read_1); | ||
| 3292 | 3452 | ||
| 3293 | int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, | 3453 | int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, |
| 3294 | u8 *data1, u8 *data2) | 3454 | int buflen) |
| 3295 | { | 3455 | { |
| 3296 | u8 buf[2]; | ||
| 3297 | int r; | 3456 | int r; |
| 3298 | 3457 | ||
| 3299 | r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2); | 3458 | r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen); |
| 3459 | if (r) { | ||
| 3460 | DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel); | ||
| 3461 | return r; | ||
| 3462 | } | ||
| 3300 | 3463 | ||
| 3301 | if (r < 0) | 3464 | return 0; |
| 3465 | } | ||
| 3466 | EXPORT_SYMBOL(dsi_vc_generic_read_0); | ||
| 3467 | |||
| 3468 | int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, | ||
| 3469 | u8 *buf, int buflen) | ||
| 3470 | { | ||
| 3471 | int r; | ||
| 3472 | |||
| 3473 | r = dsi_vc_generic_read(dssdev, channel, ¶m, 1, buf, buflen); | ||
| 3474 | if (r) { | ||
| 3475 | DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel); | ||
| 3302 | return r; | 3476 | return r; |
| 3477 | } | ||
| 3303 | 3478 | ||
| 3304 | if (r != 2) | 3479 | return 0; |
| 3305 | return -EIO; | 3480 | } |
| 3481 | EXPORT_SYMBOL(dsi_vc_generic_read_1); | ||
| 3306 | 3482 | ||
| 3307 | *data1 = buf[0]; | 3483 | int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel, |
| 3308 | *data2 = buf[1]; | 3484 | u8 param1, u8 param2, u8 *buf, int buflen) |
| 3485 | { | ||
| 3486 | int r; | ||
| 3487 | u8 reqdata[2]; | ||
| 3488 | |||
| 3489 | reqdata[0] = param1; | ||
| 3490 | reqdata[1] = param2; | ||
| 3491 | |||
| 3492 | r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen); | ||
| 3493 | if (r) { | ||
| 3494 | DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel); | ||
| 3495 | return r; | ||
| 3496 | } | ||
| 3309 | 3497 | ||
| 3310 | return 0; | 3498 | return 0; |
| 3311 | } | 3499 | } |
| 3312 | EXPORT_SYMBOL(dsi_vc_dcs_read_2); | 3500 | EXPORT_SYMBOL(dsi_vc_generic_read_2); |
| 3313 | 3501 | ||
| 3314 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, | 3502 | int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, |
| 3315 | u16 len) | 3503 | u16 len) |
| 3316 | { | 3504 | { |
| 3317 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3505 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 3318 | 3506 | ||
| 3319 | return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE, | 3507 | return dsi_vc_send_short(dsidev, channel, |
| 3320 | len, 0); | 3508 | MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0); |
| 3321 | } | 3509 | } |
| 3322 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); | 3510 | EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); |
| 3323 | 3511 | ||
| @@ -3508,6 +3696,75 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev, | |||
| 3508 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", | 3696 | ticks, x4 ? " x4" : "", x16 ? " x16" : "", |
| 3509 | (total_ticks * 1000) / (fck / 1000 / 1000)); | 3697 | (total_ticks * 1000) / (fck / 1000 / 1000)); |
| 3510 | } | 3698 | } |
| 3699 | |||
| 3700 | static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) | ||
| 3701 | { | ||
| 3702 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3703 | int num_line_buffers; | ||
| 3704 | |||
| 3705 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
| 3706 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
| 3707 | unsigned line_buf_size = dsi_get_line_buf_size(dsidev); | ||
| 3708 | struct omap_video_timings *timings = &dssdev->panel.timings; | ||
| 3709 | /* | ||
| 3710 | * Don't use line buffers if width is greater than the video | ||
| 3711 | * port's line buffer size | ||
| 3712 | */ | ||
| 3713 | if (line_buf_size <= timings->x_res * bpp / 8) | ||
| 3714 | num_line_buffers = 0; | ||
| 3715 | else | ||
| 3716 | num_line_buffers = 2; | ||
| 3717 | } else { | ||
| 3718 | /* Use maximum number of line buffers in command mode */ | ||
| 3719 | num_line_buffers = 2; | ||
| 3720 | } | ||
| 3721 | |||
| 3722 | /* LINE_BUFFER */ | ||
| 3723 | REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); | ||
| 3724 | } | ||
| 3725 | |||
| 3726 | static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) | ||
| 3727 | { | ||
| 3728 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3729 | int de_pol = dssdev->panel.dsi_vm_data.vp_de_pol; | ||
| 3730 | int hsync_pol = dssdev->panel.dsi_vm_data.vp_hsync_pol; | ||
| 3731 | int vsync_pol = dssdev->panel.dsi_vm_data.vp_vsync_pol; | ||
| 3732 | bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; | ||
| 3733 | bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; | ||
| 3734 | u32 r; | ||
| 3735 | |||
| 3736 | r = dsi_read_reg(dsidev, DSI_CTRL); | ||
| 3737 | r = FLD_MOD(r, de_pol, 9, 9); /* VP_DE_POL */ | ||
| 3738 | r = FLD_MOD(r, hsync_pol, 10, 10); /* VP_HSYNC_POL */ | ||
| 3739 | r = FLD_MOD(r, vsync_pol, 11, 11); /* VP_VSYNC_POL */ | ||
| 3740 | r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ | ||
| 3741 | r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ | ||
| 3742 | r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ | ||
| 3743 | r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ | ||
| 3744 | dsi_write_reg(dsidev, DSI_CTRL, r); | ||
| 3745 | } | ||
| 3746 | |||
| 3747 | static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) | ||
| 3748 | { | ||
| 3749 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3750 | int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; | ||
| 3751 | int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; | ||
| 3752 | int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; | ||
| 3753 | int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; | ||
| 3754 | u32 r; | ||
| 3755 | |||
| 3756 | /* | ||
| 3757 | * 0 = TX FIFO packets sent or LPS in corresponding blanking periods | ||
| 3758 | * 1 = Long blanking packets are sent in corresponding blanking periods | ||
| 3759 | */ | ||
| 3760 | r = dsi_read_reg(dsidev, DSI_CTRL); | ||
| 3761 | r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */ | ||
| 3762 | r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */ | ||
| 3763 | r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */ | ||
| 3764 | r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */ | ||
| 3765 | dsi_write_reg(dsidev, DSI_CTRL, r); | ||
| 3766 | } | ||
| 3767 | |||
| 3511 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3768 | static int dsi_proto_config(struct omap_dss_device *dssdev) |
| 3512 | { | 3769 | { |
| 3513 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3770 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| @@ -3530,7 +3787,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
| 3530 | dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); | 3787 | dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); |
| 3531 | dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); | 3788 | dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); |
| 3532 | 3789 | ||
| 3533 | switch (dssdev->ctrl.pixel_size) { | 3790 | switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { |
| 3534 | case 16: | 3791 | case 16: |
| 3535 | buswidth = 0; | 3792 | buswidth = 0; |
| 3536 | break; | 3793 | break; |
| @@ -3551,7 +3808,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
| 3551 | r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ | 3808 | r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ |
| 3552 | r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ | 3809 | r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ |
| 3553 | r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ | 3810 | r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ |
| 3554 | r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */ | ||
| 3555 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ | 3811 | r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ |
| 3556 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ | 3812 | r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ |
| 3557 | if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { | 3813 | if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { |
| @@ -3562,6 +3818,13 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
| 3562 | 3818 | ||
| 3563 | dsi_write_reg(dsidev, DSI_CTRL, r); | 3819 | dsi_write_reg(dsidev, DSI_CTRL, r); |
| 3564 | 3820 | ||
| 3821 | dsi_config_vp_num_line_buffers(dssdev); | ||
| 3822 | |||
| 3823 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
| 3824 | dsi_config_vp_sync_events(dssdev); | ||
| 3825 | dsi_config_blanking_modes(dssdev); | ||
| 3826 | } | ||
| 3827 | |||
| 3565 | dsi_vc_initial_config(dsidev, 0); | 3828 | dsi_vc_initial_config(dsidev, 0); |
| 3566 | dsi_vc_initial_config(dsidev, 1); | 3829 | dsi_vc_initial_config(dsidev, 1); |
| 3567 | dsi_vc_initial_config(dsidev, 2); | 3830 | dsi_vc_initial_config(dsidev, 2); |
| @@ -3580,6 +3843,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
| 3580 | unsigned ddr_clk_pre, ddr_clk_post; | 3843 | unsigned ddr_clk_pre, ddr_clk_post; |
| 3581 | unsigned enter_hs_mode_lat, exit_hs_mode_lat; | 3844 | unsigned enter_hs_mode_lat, exit_hs_mode_lat; |
| 3582 | unsigned ths_eot; | 3845 | unsigned ths_eot; |
| 3846 | int ndl = dsi_get_num_data_lanes_dssdev(dssdev); | ||
| 3583 | u32 r; | 3847 | u32 r; |
| 3584 | 3848 | ||
| 3585 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); | 3849 | r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); |
| @@ -3602,7 +3866,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
| 3602 | /* min 60ns + 52*UI */ | 3866 | /* min 60ns + 52*UI */ |
| 3603 | tclk_post = ns2ddr(dsidev, 60) + 26; | 3867 | tclk_post = ns2ddr(dsidev, 60) + 26; |
| 3604 | 3868 | ||
| 3605 | ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev)); | 3869 | ths_eot = DIV_ROUND_UP(4, ndl); |
| 3606 | 3870 | ||
| 3607 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, | 3871 | ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, |
| 3608 | 4); | 3872 | 4); |
| @@ -3632,162 +3896,114 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev) | |||
| 3632 | 3896 | ||
| 3633 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", | 3897 | DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", |
| 3634 | enter_hs_mode_lat, exit_hs_mode_lat); | 3898 | enter_hs_mode_lat, exit_hs_mode_lat); |
| 3635 | } | ||
| 3636 | |||
| 3637 | |||
| 3638 | #define DSI_DECL_VARS \ | ||
| 3639 | int __dsi_cb = 0; u32 __dsi_cv = 0; | ||
| 3640 | 3899 | ||
| 3641 | #define DSI_FLUSH(dsidev, ch) \ | 3900 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { |
| 3642 | if (__dsi_cb > 0) { \ | 3901 | /* TODO: Implement a video mode check_timings function */ |
| 3643 | /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \ | 3902 | int hsa = dssdev->panel.dsi_vm_data.hsa; |
| 3644 | dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \ | 3903 | int hfp = dssdev->panel.dsi_vm_data.hfp; |
| 3645 | __dsi_cb = __dsi_cv = 0; \ | 3904 | int hbp = dssdev->panel.dsi_vm_data.hbp; |
| 3905 | int vsa = dssdev->panel.dsi_vm_data.vsa; | ||
| 3906 | int vfp = dssdev->panel.dsi_vm_data.vfp; | ||
| 3907 | int vbp = dssdev->panel.dsi_vm_data.vbp; | ||
| 3908 | int window_sync = dssdev->panel.dsi_vm_data.window_sync; | ||
| 3909 | bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; | ||
| 3910 | struct omap_video_timings *timings = &dssdev->panel.timings; | ||
| 3911 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
| 3912 | int tl, t_he, width_bytes; | ||
| 3913 | |||
| 3914 | t_he = hsync_end ? | ||
| 3915 | ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; | ||
| 3916 | |||
| 3917 | width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8); | ||
| 3918 | |||
| 3919 | /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */ | ||
| 3920 | tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp + | ||
| 3921 | DIV_ROUND_UP(width_bytes + 6, ndl) + hbp; | ||
| 3922 | |||
| 3923 | DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp, | ||
| 3924 | hfp, hsync_end ? hsa : 0, tl); | ||
| 3925 | DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp, | ||
| 3926 | vsa, timings->y_res); | ||
| 3927 | |||
| 3928 | r = dsi_read_reg(dsidev, DSI_VM_TIMING1); | ||
| 3929 | r = FLD_MOD(r, hbp, 11, 0); /* HBP */ | ||
| 3930 | r = FLD_MOD(r, hfp, 23, 12); /* HFP */ | ||
| 3931 | r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */ | ||
| 3932 | dsi_write_reg(dsidev, DSI_VM_TIMING1, r); | ||
| 3933 | |||
| 3934 | r = dsi_read_reg(dsidev, DSI_VM_TIMING2); | ||
| 3935 | r = FLD_MOD(r, vbp, 7, 0); /* VBP */ | ||
| 3936 | r = FLD_MOD(r, vfp, 15, 8); /* VFP */ | ||
| 3937 | r = FLD_MOD(r, vsa, 23, 16); /* VSA */ | ||
| 3938 | r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */ | ||
| 3939 | dsi_write_reg(dsidev, DSI_VM_TIMING2, r); | ||
| 3940 | |||
| 3941 | r = dsi_read_reg(dsidev, DSI_VM_TIMING3); | ||
| 3942 | r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */ | ||
| 3943 | r = FLD_MOD(r, tl, 31, 16); /* TL */ | ||
| 3944 | dsi_write_reg(dsidev, DSI_VM_TIMING3, r); | ||
| 3646 | } | 3945 | } |
| 3946 | } | ||
| 3647 | 3947 | ||
| 3648 | #define DSI_PUSH(dsidev, ch, data) \ | 3948 | int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel) |
| 3649 | do { \ | ||
| 3650 | __dsi_cv |= (data) << (__dsi_cb * 8); \ | ||
| 3651 | /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \ | ||
| 3652 | if (++__dsi_cb > 3) \ | ||
| 3653 | DSI_FLUSH(dsidev, ch); \ | ||
| 3654 | } while (0) | ||
| 3655 | |||
| 3656 | static int dsi_update_screen_l4(struct omap_dss_device *dssdev, | ||
| 3657 | int x, int y, int w, int h) | ||
| 3658 | { | 3949 | { |
| 3659 | /* Note: supports only 24bit colors in 32bit container */ | ||
| 3660 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 3950 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
| 3661 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3951 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); |
| 3662 | int first = 1; | 3952 | u8 data_type; |
| 3663 | int fifo_stalls = 0; | 3953 | u16 word_count; |
| 3664 | int max_dsi_packet_size; | ||
| 3665 | int max_data_per_packet; | ||
| 3666 | int max_pixels_per_packet; | ||
| 3667 | int pixels_left; | ||
| 3668 | int bytespp = dssdev->ctrl.pixel_size / 8; | ||
| 3669 | int scr_width; | ||
| 3670 | u32 __iomem *data; | ||
| 3671 | int start_offset; | ||
| 3672 | int horiz_inc; | ||
| 3673 | int current_x; | ||
| 3674 | struct omap_overlay *ovl; | ||
| 3675 | |||
| 3676 | debug_irq = 0; | ||
| 3677 | |||
| 3678 | DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n", | ||
| 3679 | x, y, w, h); | ||
| 3680 | 3954 | ||
| 3681 | ovl = dssdev->manager->overlays[0]; | 3955 | switch (dssdev->panel.dsi_pix_fmt) { |
| 3682 | 3956 | case OMAP_DSS_DSI_FMT_RGB888: | |
| 3683 | if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U) | 3957 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; |
| 3684 | return -EINVAL; | 3958 | break; |
| 3685 | 3959 | case OMAP_DSS_DSI_FMT_RGB666: | |
| 3686 | if (dssdev->ctrl.pixel_size != 24) | 3960 | data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; |
| 3687 | return -EINVAL; | 3961 | break; |
| 3688 | 3962 | case OMAP_DSS_DSI_FMT_RGB666_PACKED: | |
| 3689 | scr_width = ovl->info.screen_width; | 3963 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; |
| 3690 | data = ovl->info.vaddr; | 3964 | break; |
| 3691 | 3965 | case OMAP_DSS_DSI_FMT_RGB565: | |
| 3692 | start_offset = scr_width * y + x; | 3966 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
| 3693 | horiz_inc = scr_width - w; | 3967 | break; |
| 3694 | current_x = x; | 3968 | default: |
| 3695 | 3969 | BUG(); | |
| 3696 | /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes | 3970 | }; |
| 3697 | * in fifo */ | ||
| 3698 | |||
| 3699 | /* When using CPU, max long packet size is TX buffer size */ | ||
| 3700 | max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4; | ||
| 3701 | |||
| 3702 | /* we seem to get better perf if we divide the tx fifo to half, | ||
| 3703 | and while the other half is being sent, we fill the other half | ||
| 3704 | max_dsi_packet_size /= 2; */ | ||
| 3705 | |||
| 3706 | max_data_per_packet = max_dsi_packet_size - 4 - 1; | ||
| 3707 | |||
| 3708 | max_pixels_per_packet = max_data_per_packet / bytespp; | ||
| 3709 | |||
| 3710 | DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet); | ||
| 3711 | |||
| 3712 | pixels_left = w * h; | ||
| 3713 | 3971 | ||
| 3714 | DSSDBG("total pixels %d\n", pixels_left); | 3972 | dsi_if_enable(dsidev, false); |
| 3973 | dsi_vc_enable(dsidev, channel, false); | ||
| 3715 | 3974 | ||
| 3716 | data += start_offset; | 3975 | /* MODE, 1 = video mode */ |
| 3976 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); | ||
| 3717 | 3977 | ||
| 3718 | while (pixels_left > 0) { | 3978 | word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); |
| 3719 | /* 0x2c = write_memory_start */ | ||
| 3720 | /* 0x3c = write_memory_continue */ | ||
| 3721 | u8 dcs_cmd = first ? 0x2c : 0x3c; | ||
| 3722 | int pixels; | ||
| 3723 | DSI_DECL_VARS; | ||
| 3724 | first = 0; | ||
| 3725 | 3979 | ||
| 3726 | #if 1 | 3980 | dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); |
| 3727 | /* using fifo not empty */ | ||
| 3728 | /* TX_FIFO_NOT_EMPTY */ | ||
| 3729 | while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) { | ||
| 3730 | fifo_stalls++; | ||
| 3731 | if (fifo_stalls > 0xfffff) { | ||
| 3732 | DSSERR("fifo stalls overflow, pixels left %d\n", | ||
| 3733 | pixels_left); | ||
| 3734 | dsi_if_enable(dsidev, 0); | ||
| 3735 | return -EIO; | ||
| 3736 | } | ||
| 3737 | udelay(1); | ||
| 3738 | } | ||
| 3739 | #elif 1 | ||
| 3740 | /* using fifo emptiness */ | ||
| 3741 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 < | ||
| 3742 | max_dsi_packet_size) { | ||
| 3743 | fifo_stalls++; | ||
| 3744 | if (fifo_stalls > 0xfffff) { | ||
| 3745 | DSSERR("fifo stalls overflow, pixels left %d\n", | ||
| 3746 | pixels_left); | ||
| 3747 | dsi_if_enable(dsidev, 0); | ||
| 3748 | return -EIO; | ||
| 3749 | } | ||
| 3750 | } | ||
| 3751 | #else | ||
| 3752 | while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, | ||
| 3753 | 7, 0) + 1) * 4 == 0) { | ||
| 3754 | fifo_stalls++; | ||
| 3755 | if (fifo_stalls > 0xfffff) { | ||
| 3756 | DSSERR("fifo stalls overflow, pixels left %d\n", | ||
| 3757 | pixels_left); | ||
| 3758 | dsi_if_enable(dsidev, 0); | ||
| 3759 | return -EIO; | ||
| 3760 | } | ||
| 3761 | } | ||
| 3762 | #endif | ||
| 3763 | pixels = min(max_pixels_per_packet, pixels_left); | ||
| 3764 | 3981 | ||
| 3765 | pixels_left -= pixels; | 3982 | dsi_vc_enable(dsidev, channel, true); |
| 3983 | dsi_if_enable(dsidev, true); | ||
| 3766 | 3984 | ||
| 3767 | dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE, | 3985 | dssdev->manager->enable(dssdev->manager); |
| 3768 | 1 + pixels * bytespp, 0); | ||
| 3769 | 3986 | ||
| 3770 | DSI_PUSH(dsidev, 0, dcs_cmd); | 3987 | return 0; |
| 3988 | } | ||
| 3989 | EXPORT_SYMBOL(dsi_video_mode_enable); | ||
| 3771 | 3990 | ||
| 3772 | while (pixels-- > 0) { | 3991 | void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) |
| 3773 | u32 pix = __raw_readl(data++); | 3992 | { |
| 3993 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
| 3774 | 3994 | ||
| 3775 | DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff); | 3995 | dsi_if_enable(dsidev, false); |
| 3776 | DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff); | 3996 | dsi_vc_enable(dsidev, channel, false); |
| 3777 | DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff); | ||
| 3778 | 3997 | ||
| 3779 | current_x++; | 3998 | /* MODE, 0 = command mode */ |
| 3780 | if (current_x == x+w) { | 3999 | REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); |
| 3781 | current_x = x; | ||
| 3782 | data += horiz_inc; | ||
| 3783 | } | ||
| 3784 | } | ||
| 3785 | 4000 | ||
| 3786 | DSI_FLUSH(dsidev, 0); | 4001 | dsi_vc_enable(dsidev, channel, true); |
| 3787 | } | 4002 | dsi_if_enable(dsidev, true); |
| 3788 | 4003 | ||
| 3789 | return 0; | 4004 | dssdev->manager->disable(dssdev->manager); |
| 3790 | } | 4005 | } |
| 4006 | EXPORT_SYMBOL(dsi_video_mode_disable); | ||
| 3791 | 4007 | ||
| 3792 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | 4008 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, |
| 3793 | u16 x, u16 y, u16 w, u16 h) | 4009 | u16 x, u16 y, u16 w, u16 h) |
| @@ -3808,9 +4024,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
| 3808 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", | 4024 | DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", |
| 3809 | x, y, w, h); | 4025 | x, y, w, h); |
| 3810 | 4026 | ||
| 3811 | dsi_vc_config_vp(dsidev, channel); | 4027 | dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); |
| 3812 | 4028 | ||
| 3813 | bytespp = dssdev->ctrl.pixel_size / 8; | 4029 | bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; |
| 3814 | bytespl = w * bytespp; | 4030 | bytespl = w * bytespp; |
| 3815 | bytespf = bytespl * h; | 4031 | bytespf = bytespl * h; |
| 3816 | 4032 | ||
| @@ -3831,7 +4047,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | |||
| 3831 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ | 4047 | l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ |
| 3832 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); | 4048 | dsi_write_reg(dsidev, DSI_VC_TE(channel), l); |
| 3833 | 4049 | ||
| 3834 | dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE, | 4050 | dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE, |
| 3835 | packet_len, 0); | 4051 | packet_len, 0); |
| 3836 | 4052 | ||
| 3837 | if (dsi->te_enabled) | 4053 | if (dsi->te_enabled) |
| @@ -3956,11 +4172,9 @@ int omap_dsi_prepare_update(struct omap_dss_device *dssdev, | |||
| 3956 | 4172 | ||
| 3957 | dsi_perf_mark_setup(dsidev); | 4173 | dsi_perf_mark_setup(dsidev); |
| 3958 | 4174 | ||
| 3959 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 4175 | dss_setup_partial_planes(dssdev, x, y, w, h, |
| 3960 | dss_setup_partial_planes(dssdev, x, y, w, h, | 4176 | enlarge_update_area); |
| 3961 | enlarge_update_area); | 4177 | dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); |
| 3962 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); | ||
| 3963 | } | ||
| 3964 | 4178 | ||
| 3965 | return 0; | 4179 | return 0; |
| 3966 | } | 4180 | } |
| @@ -3982,27 +4196,16 @@ int omap_dsi_update(struct omap_dss_device *dssdev, | |||
| 3982 | * see rather obscure HW error happening, as DSS halts. */ | 4196 | * see rather obscure HW error happening, as DSS halts. */ |
| 3983 | BUG_ON(x % 2 == 1); | 4197 | BUG_ON(x % 2 == 1); |
| 3984 | 4198 | ||
| 3985 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 4199 | dsi->framedone_callback = callback; |
| 3986 | dsi->framedone_callback = callback; | 4200 | dsi->framedone_data = data; |
| 3987 | dsi->framedone_data = data; | ||
| 3988 | |||
| 3989 | dsi->update_region.x = x; | ||
| 3990 | dsi->update_region.y = y; | ||
| 3991 | dsi->update_region.w = w; | ||
| 3992 | dsi->update_region.h = h; | ||
| 3993 | dsi->update_region.device = dssdev; | ||
| 3994 | |||
| 3995 | dsi_update_screen_dispc(dssdev, x, y, w, h); | ||
| 3996 | } else { | ||
| 3997 | int r; | ||
| 3998 | 4201 | ||
| 3999 | r = dsi_update_screen_l4(dssdev, x, y, w, h); | 4202 | dsi->update_region.x = x; |
| 4000 | if (r) | 4203 | dsi->update_region.y = y; |
| 4001 | return r; | 4204 | dsi->update_region.w = w; |
| 4205 | dsi->update_region.h = h; | ||
| 4206 | dsi->update_region.device = dssdev; | ||
| 4002 | 4207 | ||
| 4003 | dsi_perf_show(dsidev, "L4"); | 4208 | dsi_update_screen_dispc(dssdev, x, y, w, h); |
| 4004 | callback(0, data); | ||
| 4005 | } | ||
| 4006 | 4209 | ||
| 4007 | return 0; | 4210 | return 0; |
| 4008 | } | 4211 | } |
| @@ -4013,28 +4216,9 @@ EXPORT_SYMBOL(omap_dsi_update); | |||
| 4013 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | 4216 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) |
| 4014 | { | 4217 | { |
| 4015 | int r; | 4218 | int r; |
| 4016 | u32 irq; | ||
| 4017 | |||
| 4018 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | ||
| 4019 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
| 4020 | 4219 | ||
| 4021 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev, | 4220 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { |
| 4022 | irq); | 4221 | u32 irq; |
| 4023 | if (r) { | ||
| 4024 | DSSERR("can't get FRAMEDONE irq\n"); | ||
| 4025 | return r; | ||
| 4026 | } | ||
| 4027 | |||
| 4028 | dispc_set_lcd_display_type(dssdev->manager->id, | ||
| 4029 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
| 4030 | |||
| 4031 | dispc_set_parallel_interface_mode(dssdev->manager->id, | ||
| 4032 | OMAP_DSS_PARALLELMODE_DSI); | ||
| 4033 | dispc_enable_fifohandcheck(dssdev->manager->id, 1); | ||
| 4034 | |||
| 4035 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); | ||
| 4036 | |||
| 4037 | { | ||
| 4038 | struct omap_video_timings timings = { | 4222 | struct omap_video_timings timings = { |
| 4039 | .hsw = 1, | 4223 | .hsw = 1, |
| 4040 | .hfp = 1, | 4224 | .hfp = 1, |
| @@ -4044,21 +4228,46 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
| 4044 | .vbp = 0, | 4228 | .vbp = 0, |
| 4045 | }; | 4229 | }; |
| 4046 | 4230 | ||
| 4047 | dispc_set_lcd_timings(dssdev->manager->id, &timings); | 4231 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? |
| 4232 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | ||
| 4233 | |||
| 4234 | r = omap_dispc_register_isr(dsi_framedone_irq_callback, | ||
| 4235 | (void *) dssdev, irq); | ||
| 4236 | if (r) { | ||
| 4237 | DSSERR("can't get FRAMEDONE irq\n"); | ||
| 4238 | return r; | ||
| 4239 | } | ||
| 4240 | |||
| 4241 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); | ||
| 4242 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); | ||
| 4243 | |||
| 4244 | dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); | ||
| 4245 | } else { | ||
| 4246 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); | ||
| 4247 | dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); | ||
| 4248 | |||
| 4249 | dispc_mgr_set_lcd_timings(dssdev->manager->id, | ||
| 4250 | &dssdev->panel.timings); | ||
| 4048 | } | 4251 | } |
| 4049 | 4252 | ||
| 4253 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, | ||
| 4254 | OMAP_DSS_LCD_DISPLAY_TFT); | ||
| 4255 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, | ||
| 4256 | dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)); | ||
| 4050 | return 0; | 4257 | return 0; |
| 4051 | } | 4258 | } |
| 4052 | 4259 | ||
| 4053 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4260 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) |
| 4054 | { | 4261 | { |
| 4055 | u32 irq; | 4262 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { |
| 4263 | u32 irq; | ||
| 4056 | 4264 | ||
| 4057 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? | 4265 | irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? |
| 4058 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; | 4266 | DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; |
| 4059 | 4267 | ||
| 4060 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev, | 4268 | omap_dispc_unregister_isr(dsi_framedone_irq_callback, |
| 4061 | irq); | 4269 | (void *) dssdev, irq); |
| 4270 | } | ||
| 4062 | } | 4271 | } |
| 4063 | 4272 | ||
| 4064 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4273 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) |
| @@ -4106,7 +4315,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
| 4106 | return r; | 4315 | return r; |
| 4107 | } | 4316 | } |
| 4108 | 4317 | ||
| 4109 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 4318 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
| 4110 | if (r) { | 4319 | if (r) { |
| 4111 | DSSERR("Failed to set dispc clocks\n"); | 4320 | DSSERR("Failed to set dispc clocks\n"); |
| 4112 | return r; | 4321 | return r; |
| @@ -4166,10 +4375,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
| 4166 | 4375 | ||
| 4167 | return 0; | 4376 | return 0; |
| 4168 | err3: | 4377 | err3: |
| 4169 | dsi_cio_uninit(dsidev); | 4378 | dsi_cio_uninit(dssdev); |
| 4170 | err2: | 4379 | err2: |
| 4171 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4380 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
| 4172 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4381 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); |
| 4382 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); | ||
| 4383 | |||
| 4173 | err1: | 4384 | err1: |
| 4174 | dsi_pll_uninit(dsidev, true); | 4385 | dsi_pll_uninit(dsidev, true); |
| 4175 | err0: | 4386 | err0: |
| @@ -4195,7 +4406,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
| 4195 | 4406 | ||
| 4196 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); | 4407 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
| 4197 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); | 4408 | dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); |
| 4198 | dsi_cio_uninit(dsidev); | 4409 | dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); |
| 4410 | dsi_cio_uninit(dssdev); | ||
| 4199 | dsi_pll_uninit(dsidev, disconnect_lanes); | 4411 | dsi_pll_uninit(dsidev, disconnect_lanes); |
| 4200 | } | 4412 | } |
| 4201 | 4413 | ||
| @@ -4211,6 +4423,12 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
| 4211 | 4423 | ||
| 4212 | mutex_lock(&dsi->lock); | 4424 | mutex_lock(&dsi->lock); |
| 4213 | 4425 | ||
| 4426 | if (dssdev->manager == NULL) { | ||
| 4427 | DSSERR("failed to enable display: no manager\n"); | ||
| 4428 | r = -ENODEV; | ||
| 4429 | goto err_start_dev; | ||
| 4430 | } | ||
| 4431 | |||
| 4214 | r = omap_dss_start_device(dssdev); | 4432 | r = omap_dss_start_device(dssdev); |
| 4215 | if (r) { | 4433 | if (r) { |
| 4216 | DSSERR("failed to start device\n"); | 4434 | DSSERR("failed to start device\n"); |
| @@ -4307,9 +4525,10 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
| 4307 | 4525 | ||
| 4308 | DSSDBG("DSI init\n"); | 4526 | DSSDBG("DSI init\n"); |
| 4309 | 4527 | ||
| 4310 | /* XXX these should be figured out dynamically */ | 4528 | if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { |
| 4311 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 4529 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
| 4312 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 4530 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
| 4531 | } | ||
| 4313 | 4532 | ||
| 4314 | if (dsi->vdds_dsi_reg == NULL) { | 4533 | if (dsi->vdds_dsi_reg == NULL) { |
| 4315 | struct regulator *vdds_dsi; | 4534 | struct regulator *vdds_dsi; |
| @@ -4435,10 +4654,7 @@ static int dsi_get_clocks(struct platform_device *dsidev) | |||
| 4435 | 4654 | ||
| 4436 | dsi->dss_clk = clk; | 4655 | dsi->dss_clk = clk; |
| 4437 | 4656 | ||
| 4438 | if (cpu_is_omap34xx() || cpu_is_omap3630()) | 4657 | clk = clk_get(&dsidev->dev, "sys_clk"); |
| 4439 | clk = clk_get(&dsidev->dev, "dss2_alwon_fck"); | ||
| 4440 | else | ||
| 4441 | clk = clk_get(&dsidev->dev, "sys_clk"); | ||
| 4442 | if (IS_ERR(clk)) { | 4658 | if (IS_ERR(clk)) { |
| 4443 | DSSERR("can't get sys_clk\n"); | 4659 | DSSERR("can't get sys_clk\n"); |
| 4444 | clk_put(dsi->dss_clk); | 4660 | clk_put(dsi->dss_clk); |
| @@ -4462,7 +4678,7 @@ static void dsi_put_clocks(struct platform_device *dsidev) | |||
| 4462 | } | 4678 | } |
| 4463 | 4679 | ||
| 4464 | /* DSI1 HW IP initialisation */ | 4680 | /* DSI1 HW IP initialisation */ |
| 4465 | static int omap_dsi1hw_probe(struct platform_device *dsidev) | 4681 | static int omap_dsihw_probe(struct platform_device *dsidev) |
| 4466 | { | 4682 | { |
| 4467 | struct omap_display_platform_data *dss_plat_data; | 4683 | struct omap_display_platform_data *dss_plat_data; |
| 4468 | struct omap_dss_board_info *board_info; | 4684 | struct omap_dss_board_info *board_info; |
| @@ -4483,7 +4699,8 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) | |||
| 4483 | 4699 | ||
| 4484 | dss_plat_data = dsidev->dev.platform_data; | 4700 | dss_plat_data = dsidev->dev.platform_data; |
| 4485 | board_info = dss_plat_data->board_data; | 4701 | board_info = dss_plat_data->board_data; |
| 4486 | dsi->dsi_mux_pads = board_info->dsi_mux_pads; | 4702 | dsi->enable_pads = board_info->dsi_enable_pads; |
| 4703 | dsi->disable_pads = board_info->dsi_disable_pads; | ||
| 4487 | 4704 | ||
| 4488 | spin_lock_init(&dsi->irq_lock); | 4705 | spin_lock_init(&dsi->irq_lock); |
| 4489 | spin_lock_init(&dsi->errors_lock); | 4706 | spin_lock_init(&dsi->errors_lock); |
| @@ -4539,7 +4756,7 @@ static int omap_dsi1hw_probe(struct platform_device *dsidev) | |||
| 4539 | 4756 | ||
| 4540 | /* DSI VCs initialization */ | 4757 | /* DSI VCs initialization */ |
| 4541 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { | 4758 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { |
| 4542 | dsi->vc[i].mode = DSI_VC_MODE_L4; | 4759 | dsi->vc[i].source = DSI_VC_SOURCE_L4; |
| 4543 | dsi->vc[i].dssdev = NULL; | 4760 | dsi->vc[i].dssdev = NULL; |
| 4544 | dsi->vc[i].vc_id = 0; | 4761 | dsi->vc[i].vc_id = 0; |
| 4545 | } | 4762 | } |
| @@ -4572,7 +4789,7 @@ err_alloc: | |||
| 4572 | return r; | 4789 | return r; |
| 4573 | } | 4790 | } |
| 4574 | 4791 | ||
| 4575 | static int omap_dsi1hw_remove(struct platform_device *dsidev) | 4792 | static int omap_dsihw_remove(struct platform_device *dsidev) |
| 4576 | { | 4793 | { |
| 4577 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4794 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
| 4578 | 4795 | ||
| @@ -4602,10 +4819,6 @@ static int omap_dsi1hw_remove(struct platform_device *dsidev) | |||
| 4602 | 4819 | ||
| 4603 | static int dsi_runtime_suspend(struct device *dev) | 4820 | static int dsi_runtime_suspend(struct device *dev) |
| 4604 | { | 4821 | { |
| 4605 | struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); | ||
| 4606 | |||
| 4607 | clk_disable(dsi->dss_clk); | ||
| 4608 | |||
| 4609 | dispc_runtime_put(); | 4822 | dispc_runtime_put(); |
| 4610 | dss_runtime_put(); | 4823 | dss_runtime_put(); |
| 4611 | 4824 | ||
| @@ -4614,7 +4827,6 @@ static int dsi_runtime_suspend(struct device *dev) | |||
| 4614 | 4827 | ||
| 4615 | static int dsi_runtime_resume(struct device *dev) | 4828 | static int dsi_runtime_resume(struct device *dev) |
| 4616 | { | 4829 | { |
| 4617 | struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev)); | ||
| 4618 | int r; | 4830 | int r; |
| 4619 | 4831 | ||
| 4620 | r = dss_runtime_get(); | 4832 | r = dss_runtime_get(); |
| @@ -4625,8 +4837,6 @@ static int dsi_runtime_resume(struct device *dev) | |||
| 4625 | if (r) | 4837 | if (r) |
| 4626 | goto err_get_dispc; | 4838 | goto err_get_dispc; |
| 4627 | 4839 | ||
| 4628 | clk_enable(dsi->dss_clk); | ||
| 4629 | |||
| 4630 | return 0; | 4840 | return 0; |
| 4631 | 4841 | ||
| 4632 | err_get_dispc: | 4842 | err_get_dispc: |
| @@ -4640,11 +4850,11 @@ static const struct dev_pm_ops dsi_pm_ops = { | |||
| 4640 | .runtime_resume = dsi_runtime_resume, | 4850 | .runtime_resume = dsi_runtime_resume, |
| 4641 | }; | 4851 | }; |
| 4642 | 4852 | ||
| 4643 | static struct platform_driver omap_dsi1hw_driver = { | 4853 | static struct platform_driver omap_dsihw_driver = { |
| 4644 | .probe = omap_dsi1hw_probe, | 4854 | .probe = omap_dsihw_probe, |
| 4645 | .remove = omap_dsi1hw_remove, | 4855 | .remove = omap_dsihw_remove, |
| 4646 | .driver = { | 4856 | .driver = { |
| 4647 | .name = "omapdss_dsi1", | 4857 | .name = "omapdss_dsi", |
| 4648 | .owner = THIS_MODULE, | 4858 | .owner = THIS_MODULE, |
| 4649 | .pm = &dsi_pm_ops, | 4859 | .pm = &dsi_pm_ops, |
| 4650 | }, | 4860 | }, |
| @@ -4652,10 +4862,10 @@ static struct platform_driver omap_dsi1hw_driver = { | |||
| 4652 | 4862 | ||
| 4653 | int dsi_init_platform_driver(void) | 4863 | int dsi_init_platform_driver(void) |
| 4654 | { | 4864 | { |
| 4655 | return platform_driver_register(&omap_dsi1hw_driver); | 4865 | return platform_driver_register(&omap_dsihw_driver); |
| 4656 | } | 4866 | } |
| 4657 | 4867 | ||
| 4658 | void dsi_uninit_platform_driver(void) | 4868 | void dsi_uninit_platform_driver(void) |
| 4659 | { | 4869 | { |
| 4660 | return platform_driver_unregister(&omap_dsi1hw_driver); | 4870 | return platform_driver_unregister(&omap_dsihw_driver); |
| 4661 | } | 4871 | } |
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 0f9c3a6457a5..17033457ee89 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
| 27 | #include <linux/export.h> | ||
| 27 | #include <linux/err.h> | 28 | #include <linux/err.h> |
| 28 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 29 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
| @@ -639,6 +640,17 @@ void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) | |||
| 639 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ | 640 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ |
| 640 | } | 641 | } |
| 641 | 642 | ||
| 643 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) | ||
| 644 | { | ||
| 645 | enum omap_display_type displays; | ||
| 646 | |||
| 647 | displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); | ||
| 648 | if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) | ||
| 649 | return DSS_VENC_TV_CLK; | ||
| 650 | |||
| 651 | return REG_GET(DSS_CONTROL, 15, 15); | ||
| 652 | } | ||
| 653 | |||
| 642 | static int dss_get_clocks(void) | 654 | static int dss_get_clocks(void) |
| 643 | { | 655 | { |
| 644 | struct clk *clk; | 656 | struct clk *clk; |
| @@ -691,11 +703,6 @@ static void dss_put_clocks(void) | |||
| 691 | clk_put(dss.dss_clk); | 703 | clk_put(dss.dss_clk); |
| 692 | } | 704 | } |
| 693 | 705 | ||
| 694 | struct clk *dss_get_ick(void) | ||
| 695 | { | ||
| 696 | return clk_get(&dss.pdev->dev, "ick"); | ||
| 697 | } | ||
| 698 | |||
| 699 | int dss_runtime_get(void) | 706 | int dss_runtime_get(void) |
| 700 | { | 707 | { |
| 701 | int r; | 708 | int r; |
| @@ -824,13 +831,11 @@ static int omap_dsshw_remove(struct platform_device *pdev) | |||
| 824 | static int dss_runtime_suspend(struct device *dev) | 831 | static int dss_runtime_suspend(struct device *dev) |
| 825 | { | 832 | { |
| 826 | dss_save_context(); | 833 | dss_save_context(); |
| 827 | clk_disable(dss.dss_clk); | ||
| 828 | return 0; | 834 | return 0; |
| 829 | } | 835 | } |
| 830 | 836 | ||
| 831 | static int dss_runtime_resume(struct device *dev) | 837 | static int dss_runtime_resume(struct device *dev) |
| 832 | { | 838 | { |
| 833 | clk_enable(dss.dss_clk); | ||
| 834 | dss_restore_context(); | 839 | dss_restore_context(); |
| 835 | return 0; | 840 | return 0; |
| 836 | } | 841 | } |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 9c94b1152c20..6308fc59fc9e 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
| @@ -97,10 +97,10 @@ extern unsigned int dss_debug; | |||
| 97 | #define FLD_MOD(orig, val, start, end) \ | 97 | #define FLD_MOD(orig, val, start, end) \ |
| 98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) | 98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) |
| 99 | 99 | ||
| 100 | enum omap_parallel_interface_mode { | 100 | enum dss_io_pad_mode { |
| 101 | OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */ | 101 | DSS_IO_PAD_MODE_RESET, |
| 102 | OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */ | 102 | DSS_IO_PAD_MODE_RFBI, |
| 103 | OMAP_DSS_PARALLELMODE_DSI, | 103 | DSS_IO_PAD_MODE_BYPASS, |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | enum dss_hdmi_venc_clk_source_select { | 106 | enum dss_hdmi_venc_clk_source_select { |
| @@ -108,6 +108,11 @@ enum dss_hdmi_venc_clk_source_select { | |||
| 108 | DSS_HDMI_M_PCLK = 1, | 108 | DSS_HDMI_M_PCLK = 1, |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | enum dss_dsi_content_type { | ||
| 112 | DSS_DSI_CONTENT_DCS, | ||
| 113 | DSS_DSI_CONTENT_GENERIC, | ||
| 114 | }; | ||
| 115 | |||
| 111 | struct dss_clock_info { | 116 | struct dss_clock_info { |
| 112 | /* rates that we get with dividers below */ | 117 | /* rates that we get with dividers below */ |
| 113 | unsigned long fck; | 118 | unsigned long fck; |
| @@ -150,16 +155,6 @@ struct dsi_clock_info { | |||
| 150 | bool use_sys_clk; | 155 | bool use_sys_clk; |
| 151 | }; | 156 | }; |
| 152 | 157 | ||
| 153 | /* HDMI PLL structure */ | ||
| 154 | struct hdmi_pll_info { | ||
| 155 | u16 regn; | ||
| 156 | u16 regm; | ||
| 157 | u32 regmf; | ||
| 158 | u16 regm2; | ||
| 159 | u16 regsd; | ||
| 160 | u16 dcofreq; | ||
| 161 | }; | ||
| 162 | |||
| 163 | struct seq_file; | 158 | struct seq_file; |
| 164 | struct platform_device; | 159 | struct platform_device; |
| 165 | 160 | ||
| @@ -209,9 +204,8 @@ void dss_uninit_platform_driver(void); | |||
| 209 | int dss_runtime_get(void); | 204 | int dss_runtime_get(void); |
| 210 | void dss_runtime_put(void); | 205 | void dss_runtime_put(void); |
| 211 | 206 | ||
| 212 | struct clk *dss_get_ick(void); | ||
| 213 | |||
| 214 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 207 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
| 208 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | ||
| 215 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 209 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
| 216 | void dss_dump_clocks(struct seq_file *s); | 210 | void dss_dump_clocks(struct seq_file *s); |
| 217 | 211 | ||
| @@ -279,6 +273,8 @@ void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir, | |||
| 279 | 273 | ||
| 280 | int dsi_init_display(struct omap_dss_device *display); | 274 | int dsi_init_display(struct omap_dss_device *display); |
| 281 | void dsi_irq_handler(void); | 275 | void dsi_irq_handler(void); |
| 276 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | ||
| 277 | |||
| 282 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); | 278 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
| 283 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 279 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
| 284 | struct dsi_clock_info *cinfo); | 280 | struct dsi_clock_info *cinfo); |
| @@ -309,6 +305,11 @@ static inline int dsi_runtime_get(struct platform_device *dsidev) | |||
| 309 | static inline void dsi_runtime_put(struct platform_device *dsidev) | 305 | static inline void dsi_runtime_put(struct platform_device *dsidev) |
| 310 | { | 306 | { |
| 311 | } | 307 | } |
| 308 | static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | ||
| 309 | { | ||
| 310 | WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__); | ||
| 311 | return 0; | ||
| 312 | } | ||
| 312 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) | 313 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) |
| 313 | { | 314 | { |
| 314 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); | 315 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); |
| @@ -385,90 +386,71 @@ void dispc_disable_sidle(void); | |||
| 385 | void dispc_lcd_enable_signal_polarity(bool act_high); | 386 | void dispc_lcd_enable_signal_polarity(bool act_high); |
| 386 | void dispc_lcd_enable_signal(bool enable); | 387 | void dispc_lcd_enable_signal(bool enable); |
| 387 | void dispc_pck_free_enable(bool enable); | 388 | void dispc_pck_free_enable(bool enable); |
| 388 | void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable); | ||
| 389 | |||
| 390 | void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height); | ||
| 391 | void dispc_set_digit_size(u16 width, u16 height); | 389 | void dispc_set_digit_size(u16 width, u16 height); |
| 392 | u32 dispc_get_plane_fifo_size(enum omap_plane plane); | ||
| 393 | void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); | ||
| 394 | void dispc_enable_fifomerge(bool enable); | 390 | void dispc_enable_fifomerge(bool enable); |
| 395 | u32 dispc_get_burst_size(enum omap_plane plane); | ||
| 396 | void dispc_enable_cpr(enum omap_channel channel, bool enable); | ||
| 397 | void dispc_set_cpr_coef(enum omap_channel channel, | ||
| 398 | struct omap_dss_cpr_coefs *coefs); | ||
| 399 | |||
| 400 | void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr); | ||
| 401 | void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr); | ||
| 402 | void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y); | ||
| 403 | void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); | ||
| 404 | void dispc_set_channel_out(enum omap_plane plane, | ||
| 405 | enum omap_channel channel_out); | ||
| 406 | |||
| 407 | void dispc_enable_gamma_table(bool enable); | 391 | void dispc_enable_gamma_table(bool enable); |
| 408 | int dispc_setup_plane(enum omap_plane plane, | ||
| 409 | u32 paddr, u16 screen_width, | ||
| 410 | u16 pos_x, u16 pos_y, | ||
| 411 | u16 width, u16 height, | ||
| 412 | u16 out_width, u16 out_height, | ||
| 413 | enum omap_color_mode color_mode, | ||
| 414 | bool ilace, | ||
| 415 | enum omap_dss_rotation_type rotation_type, | ||
| 416 | u8 rotation, bool mirror, | ||
| 417 | u8 global_alpha, u8 pre_mult_alpha, | ||
| 418 | enum omap_channel channel, | ||
| 419 | u32 puv_addr); | ||
| 420 | |||
| 421 | bool dispc_go_busy(enum omap_channel channel); | ||
| 422 | void dispc_go(enum omap_channel channel); | ||
| 423 | void dispc_enable_channel(enum omap_channel channel, bool enable); | ||
| 424 | bool dispc_is_channel_enabled(enum omap_channel channel); | ||
| 425 | int dispc_enable_plane(enum omap_plane plane, bool enable); | ||
| 426 | void dispc_enable_replication(enum omap_plane plane, bool enable); | ||
| 427 | |||
| 428 | void dispc_set_parallel_interface_mode(enum omap_channel channel, | ||
| 429 | enum omap_parallel_interface_mode mode); | ||
| 430 | void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines); | ||
| 431 | void dispc_set_lcd_display_type(enum omap_channel channel, | ||
| 432 | enum omap_lcd_display_type type); | ||
| 433 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 392 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
| 434 | 393 | ||
| 435 | void dispc_set_default_color(enum omap_channel channel, u32 color); | ||
| 436 | u32 dispc_get_default_color(enum omap_channel channel); | ||
| 437 | void dispc_set_trans_key(enum omap_channel ch, | ||
| 438 | enum omap_dss_trans_key_type type, | ||
| 439 | u32 trans_key); | ||
| 440 | void dispc_get_trans_key(enum omap_channel ch, | ||
| 441 | enum omap_dss_trans_key_type *type, | ||
| 442 | u32 *trans_key); | ||
| 443 | void dispc_enable_trans_key(enum omap_channel ch, bool enable); | ||
| 444 | void dispc_enable_alpha_blending(enum omap_channel ch, bool enable); | ||
| 445 | bool dispc_trans_key_enabled(enum omap_channel ch); | ||
| 446 | bool dispc_alpha_blending_enabled(enum omap_channel ch); | ||
| 447 | |||
| 448 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); | 394 | bool dispc_lcd_timings_ok(struct omap_video_timings *timings); |
| 449 | void dispc_set_lcd_timings(enum omap_channel channel, | ||
| 450 | struct omap_video_timings *timings); | ||
| 451 | unsigned long dispc_fclk_rate(void); | 395 | unsigned long dispc_fclk_rate(void); |
| 452 | unsigned long dispc_lclk_rate(enum omap_channel channel); | ||
| 453 | unsigned long dispc_pclk_rate(enum omap_channel channel); | ||
| 454 | void dispc_set_pol_freq(enum omap_channel channel, | ||
| 455 | enum omap_panel_config config, u8 acbi, u8 acb); | ||
| 456 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, | 396 | void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, |
| 457 | struct dispc_clock_info *cinfo); | 397 | struct dispc_clock_info *cinfo); |
| 458 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 398 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, |
| 459 | struct dispc_clock_info *cinfo); | 399 | struct dispc_clock_info *cinfo); |
| 460 | int dispc_set_clock_div(enum omap_channel channel, | 400 | |
| 401 | |||
| 402 | u32 dispc_ovl_get_fifo_size(enum omap_plane plane); | ||
| 403 | u32 dispc_ovl_get_burst_size(enum omap_plane plane); | ||
| 404 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | ||
| 405 | bool ilace, enum omap_channel channel, bool replication, | ||
| 406 | u32 fifo_low, u32 fifo_high); | ||
| 407 | int dispc_ovl_enable(enum omap_plane plane, bool enable); | ||
| 408 | |||
| 409 | |||
| 410 | void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); | ||
| 411 | void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); | ||
| 412 | void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable); | ||
| 413 | void dispc_mgr_set_cpr_coef(enum omap_channel channel, | ||
| 414 | struct omap_dss_cpr_coefs *coefs); | ||
| 415 | bool dispc_mgr_go_busy(enum omap_channel channel); | ||
| 416 | void dispc_mgr_go(enum omap_channel channel); | ||
| 417 | void dispc_mgr_enable(enum omap_channel channel, bool enable); | ||
| 418 | bool dispc_mgr_is_channel_enabled(enum omap_channel channel); | ||
| 419 | void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); | ||
| 420 | void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable); | ||
| 421 | void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); | ||
| 422 | void dispc_mgr_set_lcd_display_type(enum omap_channel channel, | ||
| 423 | enum omap_lcd_display_type type); | ||
| 424 | void dispc_mgr_set_default_color(enum omap_channel channel, u32 color); | ||
| 425 | u32 dispc_mgr_get_default_color(enum omap_channel channel); | ||
| 426 | void dispc_mgr_set_trans_key(enum omap_channel ch, | ||
| 427 | enum omap_dss_trans_key_type type, | ||
| 428 | u32 trans_key); | ||
| 429 | void dispc_mgr_get_trans_key(enum omap_channel ch, | ||
| 430 | enum omap_dss_trans_key_type *type, | ||
| 431 | u32 *trans_key); | ||
| 432 | void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable); | ||
| 433 | void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable); | ||
| 434 | bool dispc_mgr_trans_key_enabled(enum omap_channel ch); | ||
| 435 | bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch); | ||
| 436 | void dispc_mgr_set_lcd_timings(enum omap_channel channel, | ||
| 437 | struct omap_video_timings *timings); | ||
| 438 | void dispc_mgr_set_pol_freq(enum omap_channel channel, | ||
| 439 | enum omap_panel_config config, u8 acbi, u8 acb); | ||
| 440 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); | ||
| 441 | unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); | ||
| 442 | int dispc_mgr_set_clock_div(enum omap_channel channel, | ||
| 461 | struct dispc_clock_info *cinfo); | 443 | struct dispc_clock_info *cinfo); |
| 462 | int dispc_get_clock_div(enum omap_channel channel, | 444 | int dispc_mgr_get_clock_div(enum omap_channel channel, |
| 463 | struct dispc_clock_info *cinfo); | 445 | struct dispc_clock_info *cinfo); |
| 464 | 446 | ||
| 465 | |||
| 466 | /* VENC */ | 447 | /* VENC */ |
| 467 | #ifdef CONFIG_OMAP2_DSS_VENC | 448 | #ifdef CONFIG_OMAP2_DSS_VENC |
| 468 | int venc_init_platform_driver(void); | 449 | int venc_init_platform_driver(void); |
| 469 | void venc_uninit_platform_driver(void); | 450 | void venc_uninit_platform_driver(void); |
| 470 | void venc_dump_regs(struct seq_file *s); | 451 | void venc_dump_regs(struct seq_file *s); |
| 471 | int venc_init_display(struct omap_dss_device *display); | 452 | int venc_init_display(struct omap_dss_device *display); |
| 453 | unsigned long venc_get_pixel_clock(void); | ||
| 472 | #else | 454 | #else |
| 473 | static inline int venc_init_platform_driver(void) | 455 | static inline int venc_init_platform_driver(void) |
| 474 | { | 456 | { |
| @@ -477,6 +459,11 @@ static inline int venc_init_platform_driver(void) | |||
| 477 | static inline void venc_uninit_platform_driver(void) | 459 | static inline void venc_uninit_platform_driver(void) |
| 478 | { | 460 | { |
| 479 | } | 461 | } |
| 462 | static inline unsigned long venc_get_pixel_clock(void) | ||
| 463 | { | ||
| 464 | WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__); | ||
| 465 | return 0; | ||
| 466 | } | ||
| 480 | #endif | 467 | #endif |
| 481 | 468 | ||
| 482 | /* HDMI */ | 469 | /* HDMI */ |
| @@ -484,6 +471,8 @@ static inline void venc_uninit_platform_driver(void) | |||
| 484 | int hdmi_init_platform_driver(void); | 471 | int hdmi_init_platform_driver(void); |
| 485 | void hdmi_uninit_platform_driver(void); | 472 | void hdmi_uninit_platform_driver(void); |
| 486 | int hdmi_init_display(struct omap_dss_device *dssdev); | 473 | int hdmi_init_display(struct omap_dss_device *dssdev); |
| 474 | unsigned long hdmi_get_pixel_clock(void); | ||
| 475 | void hdmi_dump_regs(struct seq_file *s); | ||
| 487 | #else | 476 | #else |
| 488 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) | 477 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) |
| 489 | { | 478 | { |
| @@ -496,12 +485,19 @@ static inline int hdmi_init_platform_driver(void) | |||
| 496 | static inline void hdmi_uninit_platform_driver(void) | 485 | static inline void hdmi_uninit_platform_driver(void) |
| 497 | { | 486 | { |
| 498 | } | 487 | } |
| 488 | static inline unsigned long hdmi_get_pixel_clock(void) | ||
| 489 | { | ||
| 490 | WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__); | ||
| 491 | return 0; | ||
| 492 | } | ||
| 499 | #endif | 493 | #endif |
| 500 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | 494 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); |
| 501 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | 495 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); |
| 502 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); | 496 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); |
| 503 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 497 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
| 504 | struct omap_video_timings *timings); | 498 | struct omap_video_timings *timings); |
| 499 | int omapdss_hdmi_read_edid(u8 *buf, int len); | ||
| 500 | bool omapdss_hdmi_detect(void); | ||
| 505 | int hdmi_panel_init(void); | 501 | int hdmi_panel_init(void); |
| 506 | void hdmi_panel_exit(void); | 502 | void hdmi_panel_exit(void); |
| 507 | 503 | ||
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index b415c4ee621d..b402699168a5 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
| @@ -47,6 +47,7 @@ struct omap_dss_features { | |||
| 47 | const int num_ovls; | 47 | const int num_ovls; |
| 48 | const enum omap_display_type *supported_displays; | 48 | const enum omap_display_type *supported_displays; |
| 49 | const enum omap_color_mode *supported_color_modes; | 49 | const enum omap_color_mode *supported_color_modes; |
| 50 | const enum omap_overlay_caps *overlay_caps; | ||
| 50 | const char * const *clksrc_names; | 51 | const char * const *clksrc_names; |
| 51 | const struct dss_param_range *dss_params; | 52 | const struct dss_param_range *dss_params; |
| 52 | 53 | ||
| @@ -209,6 +210,68 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = { | |||
| 209 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | 210 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | |
| 210 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | 211 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | |
| 211 | OMAP_DSS_COLOR_RGBX32, | 212 | OMAP_DSS_COLOR_RGBX32, |
| 213 | |||
| 214 | /* OMAP_DSS_VIDEO3 */ | ||
| 215 | OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | | ||
| 216 | OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 | | ||
| 217 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 | | ||
| 218 | OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U | | ||
| 219 | OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY | | ||
| 220 | OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | | ||
| 221 | OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | | ||
| 222 | OMAP_DSS_COLOR_RGBX32, | ||
| 223 | }; | ||
| 224 | |||
| 225 | static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { | ||
| 226 | /* OMAP_DSS_GFX */ | ||
| 227 | 0, | ||
| 228 | |||
| 229 | /* OMAP_DSS_VIDEO1 */ | ||
| 230 | OMAP_DSS_OVL_CAP_SCALE, | ||
| 231 | |||
| 232 | /* OMAP_DSS_VIDEO2 */ | ||
| 233 | OMAP_DSS_OVL_CAP_SCALE, | ||
| 234 | }; | ||
| 235 | |||
| 236 | static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { | ||
| 237 | /* OMAP_DSS_GFX */ | ||
| 238 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, | ||
| 239 | |||
| 240 | /* OMAP_DSS_VIDEO1 */ | ||
| 241 | OMAP_DSS_OVL_CAP_SCALE, | ||
| 242 | |||
| 243 | /* OMAP_DSS_VIDEO2 */ | ||
| 244 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, | ||
| 245 | }; | ||
| 246 | |||
| 247 | static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { | ||
| 248 | /* OMAP_DSS_GFX */ | ||
| 249 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, | ||
| 250 | |||
| 251 | /* OMAP_DSS_VIDEO1 */ | ||
| 252 | OMAP_DSS_OVL_CAP_SCALE, | ||
| 253 | |||
| 254 | /* OMAP_DSS_VIDEO2 */ | ||
| 255 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
| 256 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, | ||
| 257 | }; | ||
| 258 | |||
| 259 | static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { | ||
| 260 | /* OMAP_DSS_GFX */ | ||
| 261 | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | | ||
| 262 | OMAP_DSS_OVL_CAP_ZORDER, | ||
| 263 | |||
| 264 | /* OMAP_DSS_VIDEO1 */ | ||
| 265 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
| 266 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, | ||
| 267 | |||
| 268 | /* OMAP_DSS_VIDEO2 */ | ||
| 269 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
| 270 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, | ||
| 271 | |||
| 272 | /* OMAP_DSS_VIDEO3 */ | ||
| 273 | OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | | ||
| 274 | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, | ||
| 212 | }; | 275 | }; |
| 213 | 276 | ||
| 214 | static const char * const omap2_dss_clk_source_names[] = { | 277 | static const char * const omap2_dss_clk_source_names[] = { |
| @@ -233,32 +296,38 @@ static const char * const omap4_dss_clk_source_names[] = { | |||
| 233 | 296 | ||
| 234 | static const struct dss_param_range omap2_dss_param_range[] = { | 297 | static const struct dss_param_range omap2_dss_param_range[] = { |
| 235 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | 298 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, |
| 299 | [FEAT_PARAM_DSS_PCD] = { 2, 255 }, | ||
| 236 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, | 300 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, |
| 237 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, | 301 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, |
| 238 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, | 302 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, |
| 239 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, | 303 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, |
| 240 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, | 304 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, |
| 241 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, | 305 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, |
| 306 | [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, | ||
| 242 | }; | 307 | }; |
| 243 | 308 | ||
| 244 | static const struct dss_param_range omap3_dss_param_range[] = { | 309 | static const struct dss_param_range omap3_dss_param_range[] = { |
| 245 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | 310 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, |
| 311 | [FEAT_PARAM_DSS_PCD] = { 1, 255 }, | ||
| 246 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, | 312 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, |
| 247 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, | 313 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, |
| 248 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, | 314 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, |
| 249 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, | 315 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, |
| 250 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, | 316 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, |
| 251 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, | 317 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, |
| 318 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | ||
| 252 | }; | 319 | }; |
| 253 | 320 | ||
| 254 | static const struct dss_param_range omap4_dss_param_range[] = { | 321 | static const struct dss_param_range omap4_dss_param_range[] = { |
| 255 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, | 322 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, |
| 323 | [FEAT_PARAM_DSS_PCD] = { 1, 255 }, | ||
| 256 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, | 324 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, |
| 257 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, | 325 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, |
| 258 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, | 326 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, |
| 259 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, | 327 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, |
| 260 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, | 328 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, |
| 261 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | 329 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, |
| 330 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | ||
| 262 | }; | 331 | }; |
| 263 | 332 | ||
| 264 | /* OMAP2 DSS Features */ | 333 | /* OMAP2 DSS Features */ |
| @@ -275,6 +344,7 @@ static const struct omap_dss_features omap2_dss_features = { | |||
| 275 | .num_ovls = 3, | 344 | .num_ovls = 3, |
| 276 | .supported_displays = omap2_dss_supported_displays, | 345 | .supported_displays = omap2_dss_supported_displays, |
| 277 | .supported_color_modes = omap2_dss_supported_color_modes, | 346 | .supported_color_modes = omap2_dss_supported_color_modes, |
| 347 | .overlay_caps = omap2_dss_overlay_caps, | ||
| 278 | .clksrc_names = omap2_dss_clk_source_names, | 348 | .clksrc_names = omap2_dss_clk_source_names, |
| 279 | .dss_params = omap2_dss_param_range, | 349 | .dss_params = omap2_dss_param_range, |
| 280 | .buffer_size_unit = 1, | 350 | .buffer_size_unit = 1, |
| @@ -287,18 +357,19 @@ static const struct omap_dss_features omap3430_dss_features = { | |||
| 287 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 357 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
| 288 | 358 | ||
| 289 | .has_feature = | 359 | .has_feature = |
| 290 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 360 | FEAT_LCDENABLEPOL | |
| 291 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 361 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
| 292 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | | 362 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | |
| 293 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | | 363 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF | |
| 294 | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | | 364 | FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC | |
| 295 | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | | 365 | FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD | |
| 296 | FEAT_FIR_COEF_V, | 366 | FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, |
| 297 | 367 | ||
| 298 | .num_mgrs = 2, | 368 | .num_mgrs = 2, |
| 299 | .num_ovls = 3, | 369 | .num_ovls = 3, |
| 300 | .supported_displays = omap3430_dss_supported_displays, | 370 | .supported_displays = omap3430_dss_supported_displays, |
| 301 | .supported_color_modes = omap3_dss_supported_color_modes, | 371 | .supported_color_modes = omap3_dss_supported_color_modes, |
| 372 | .overlay_caps = omap3430_dss_overlay_caps, | ||
| 302 | .clksrc_names = omap3_dss_clk_source_names, | 373 | .clksrc_names = omap3_dss_clk_source_names, |
| 303 | .dss_params = omap3_dss_param_range, | 374 | .dss_params = omap3_dss_param_range, |
| 304 | .buffer_size_unit = 1, | 375 | .buffer_size_unit = 1, |
| @@ -310,18 +381,19 @@ static const struct omap_dss_features omap3630_dss_features = { | |||
| 310 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 381 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), |
| 311 | 382 | ||
| 312 | .has_feature = | 383 | .has_feature = |
| 313 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 384 | FEAT_LCDENABLEPOL | |
| 314 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 385 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
| 315 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | | 386 | FEAT_FUNCGATED | |
| 316 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | 387 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | |
| 317 | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | | 388 | FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG | |
| 318 | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | | 389 | FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD | |
| 319 | FEAT_FIR_COEF_V, | 390 | FEAT_FIR_COEF_V | FEAT_ALPHA_FIXED_ZORDER, |
| 320 | 391 | ||
| 321 | .num_mgrs = 2, | 392 | .num_mgrs = 2, |
| 322 | .num_ovls = 3, | 393 | .num_ovls = 3, |
| 323 | .supported_displays = omap3630_dss_supported_displays, | 394 | .supported_displays = omap3630_dss_supported_displays, |
| 324 | .supported_color_modes = omap3_dss_supported_color_modes, | 395 | .supported_color_modes = omap3_dss_supported_color_modes, |
| 396 | .overlay_caps = omap3630_dss_overlay_caps, | ||
| 325 | .clksrc_names = omap3_dss_clk_source_names, | 397 | .clksrc_names = omap3_dss_clk_source_names, |
| 326 | .dss_params = omap3_dss_param_range, | 398 | .dss_params = omap3_dss_param_range, |
| 327 | .buffer_size_unit = 1, | 399 | .buffer_size_unit = 1, |
| @@ -335,17 +407,18 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = { | |||
| 335 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | 407 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
| 336 | 408 | ||
| 337 | .has_feature = | 409 | .has_feature = |
| 338 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 410 | FEAT_MGR_LCD2 | |
| 339 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
| 340 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | 411 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | |
| 341 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | 412 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | |
| 342 | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | | 413 | FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | |
| 343 | FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V, | 414 | FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V | |
| 415 | FEAT_ALPHA_FREE_ZORDER, | ||
| 344 | 416 | ||
| 345 | .num_mgrs = 3, | 417 | .num_mgrs = 3, |
| 346 | .num_ovls = 3, | 418 | .num_ovls = 4, |
| 347 | .supported_displays = omap4_dss_supported_displays, | 419 | .supported_displays = omap4_dss_supported_displays, |
| 348 | .supported_color_modes = omap4_dss_supported_color_modes, | 420 | .supported_color_modes = omap4_dss_supported_color_modes, |
| 421 | .overlay_caps = omap4_dss_overlay_caps, | ||
| 349 | .clksrc_names = omap4_dss_clk_source_names, | 422 | .clksrc_names = omap4_dss_clk_source_names, |
| 350 | .dss_params = omap4_dss_param_range, | 423 | .dss_params = omap4_dss_param_range, |
| 351 | .buffer_size_unit = 16, | 424 | .buffer_size_unit = 16, |
| @@ -358,24 +431,50 @@ static const struct omap_dss_features omap4_dss_features = { | |||
| 358 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), | 431 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
| 359 | 432 | ||
| 360 | .has_feature = | 433 | .has_feature = |
| 361 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 434 | FEAT_MGR_LCD2 | |
| 362 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | | ||
| 363 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | | 435 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC | |
| 364 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | | 436 | FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH | |
| 365 | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | | 437 | FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE | |
| 366 | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | | 438 | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR | |
| 367 | FEAT_PRELOAD | FEAT_FIR_COEF_V, | 439 | FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER, |
| 368 | 440 | ||
| 369 | .num_mgrs = 3, | 441 | .num_mgrs = 3, |
| 370 | .num_ovls = 3, | 442 | .num_ovls = 4, |
| 371 | .supported_displays = omap4_dss_supported_displays, | 443 | .supported_displays = omap4_dss_supported_displays, |
| 372 | .supported_color_modes = omap4_dss_supported_color_modes, | 444 | .supported_color_modes = omap4_dss_supported_color_modes, |
| 445 | .overlay_caps = omap4_dss_overlay_caps, | ||
| 373 | .clksrc_names = omap4_dss_clk_source_names, | 446 | .clksrc_names = omap4_dss_clk_source_names, |
| 374 | .dss_params = omap4_dss_param_range, | 447 | .dss_params = omap4_dss_param_range, |
| 375 | .buffer_size_unit = 16, | 448 | .buffer_size_unit = 16, |
| 376 | .burst_size_unit = 16, | 449 | .burst_size_unit = 16, |
| 377 | }; | 450 | }; |
| 378 | 451 | ||
| 452 | #if defined(CONFIG_OMAP4_DSS_HDMI) | ||
| 453 | /* HDMI OMAP4 Functions*/ | ||
| 454 | static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { | ||
| 455 | |||
| 456 | .video_configure = ti_hdmi_4xxx_basic_configure, | ||
| 457 | .phy_enable = ti_hdmi_4xxx_phy_enable, | ||
| 458 | .phy_disable = ti_hdmi_4xxx_phy_disable, | ||
| 459 | .read_edid = ti_hdmi_4xxx_read_edid, | ||
| 460 | .detect = ti_hdmi_4xxx_detect, | ||
| 461 | .pll_enable = ti_hdmi_4xxx_pll_enable, | ||
| 462 | .pll_disable = ti_hdmi_4xxx_pll_disable, | ||
| 463 | .video_enable = ti_hdmi_4xxx_wp_video_start, | ||
| 464 | .dump_wrapper = ti_hdmi_4xxx_wp_dump, | ||
| 465 | .dump_core = ti_hdmi_4xxx_core_dump, | ||
| 466 | .dump_pll = ti_hdmi_4xxx_pll_dump, | ||
| 467 | .dump_phy = ti_hdmi_4xxx_phy_dump, | ||
| 468 | |||
| 469 | }; | ||
| 470 | |||
| 471 | void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data) | ||
| 472 | { | ||
| 473 | if (cpu_is_omap44xx()) | ||
| 474 | ip_data->ops = &omap4_hdmi_functions; | ||
| 475 | } | ||
| 476 | #endif | ||
| 477 | |||
| 379 | /* Functions returning values related to a DSS feature */ | 478 | /* Functions returning values related to a DSS feature */ |
| 380 | int dss_feat_get_num_mgrs(void) | 479 | int dss_feat_get_num_mgrs(void) |
| 381 | { | 480 | { |
| @@ -407,6 +506,11 @@ enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) | |||
| 407 | return omap_current_dss_features->supported_color_modes[plane]; | 506 | return omap_current_dss_features->supported_color_modes[plane]; |
| 408 | } | 507 | } |
| 409 | 508 | ||
| 509 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) | ||
| 510 | { | ||
| 511 | return omap_current_dss_features->overlay_caps[plane]; | ||
| 512 | } | ||
| 513 | |||
| 410 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 514 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
| 411 | enum omap_color_mode color_mode) | 515 | enum omap_color_mode color_mode) |
| 412 | { | 516 | { |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b7398cbcda5f..6a6c05dd45ce 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
| @@ -20,16 +20,17 @@ | |||
| 20 | #ifndef __OMAP2_DSS_FEATURES_H | 20 | #ifndef __OMAP2_DSS_FEATURES_H |
| 21 | #define __OMAP2_DSS_FEATURES_H | 21 | #define __OMAP2_DSS_FEATURES_H |
| 22 | 22 | ||
| 23 | #if defined(CONFIG_OMAP4_DSS_HDMI) | ||
| 24 | #include "ti_hdmi.h" | ||
| 25 | #endif | ||
| 26 | |||
| 23 | #define MAX_DSS_MANAGERS 3 | 27 | #define MAX_DSS_MANAGERS 3 |
| 24 | #define MAX_DSS_OVERLAYS 3 | 28 | #define MAX_DSS_OVERLAYS 4 |
| 25 | #define MAX_DSS_LCD_MANAGERS 2 | 29 | #define MAX_DSS_LCD_MANAGERS 2 |
| 26 | #define MAX_NUM_DSI 2 | 30 | #define MAX_NUM_DSI 2 |
| 27 | 31 | ||
| 28 | /* DSS has feature id */ | 32 | /* DSS has feature id */ |
| 29 | enum dss_feat_id { | 33 | enum dss_feat_id { |
| 30 | FEAT_GLOBAL_ALPHA = 1 << 0, | ||
| 31 | FEAT_GLOBAL_ALPHA_VID1 = 1 << 1, | ||
| 32 | FEAT_PRE_MULT_ALPHA = 1 << 2, | ||
| 33 | FEAT_LCDENABLEPOL = 1 << 3, | 34 | FEAT_LCDENABLEPOL = 1 << 3, |
| 34 | FEAT_LCDENABLESIGNAL = 1 << 4, | 35 | FEAT_LCDENABLESIGNAL = 1 << 4, |
| 35 | FEAT_PCKFREEENABLE = 1 << 5, | 36 | FEAT_PCKFREEENABLE = 1 << 5, |
| @@ -55,6 +56,8 @@ enum dss_feat_id { | |||
| 55 | FEAT_CPR = 1 << 23, | 56 | FEAT_CPR = 1 << 23, |
| 56 | FEAT_PRELOAD = 1 << 24, | 57 | FEAT_PRELOAD = 1 << 24, |
| 57 | FEAT_FIR_COEF_V = 1 << 25, | 58 | FEAT_FIR_COEF_V = 1 << 25, |
| 59 | FEAT_ALPHA_FIXED_ZORDER = 1 << 26, | ||
| 60 | FEAT_ALPHA_FREE_ZORDER = 1 << 27, | ||
| 58 | }; | 61 | }; |
| 59 | 62 | ||
| 60 | /* DSS register field id */ | 63 | /* DSS register field id */ |
| @@ -75,12 +78,14 @@ enum dss_feat_reg_field { | |||
| 75 | 78 | ||
| 76 | enum dss_range_param { | 79 | enum dss_range_param { |
| 77 | FEAT_PARAM_DSS_FCK, | 80 | FEAT_PARAM_DSS_FCK, |
| 81 | FEAT_PARAM_DSS_PCD, | ||
| 78 | FEAT_PARAM_DSIPLL_REGN, | 82 | FEAT_PARAM_DSIPLL_REGN, |
| 79 | FEAT_PARAM_DSIPLL_REGM, | 83 | FEAT_PARAM_DSIPLL_REGM, |
| 80 | FEAT_PARAM_DSIPLL_REGM_DISPC, | 84 | FEAT_PARAM_DSIPLL_REGM_DISPC, |
| 81 | FEAT_PARAM_DSIPLL_REGM_DSI, | 85 | FEAT_PARAM_DSIPLL_REGM_DSI, |
| 82 | FEAT_PARAM_DSIPLL_FINT, | 86 | FEAT_PARAM_DSIPLL_FINT, |
| 83 | FEAT_PARAM_DSIPLL_LPDIV, | 87 | FEAT_PARAM_DSIPLL_LPDIV, |
| 88 | FEAT_PARAM_DOWNSCALE, | ||
| 84 | }; | 89 | }; |
| 85 | 90 | ||
| 86 | /* DSS Feature Functions */ | 91 | /* DSS Feature Functions */ |
| @@ -90,6 +95,7 @@ unsigned long dss_feat_get_param_min(enum dss_range_param param); | |||
| 90 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | 95 | unsigned long dss_feat_get_param_max(enum dss_range_param param); |
| 91 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | 96 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); |
| 92 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 97 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
| 98 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); | ||
| 93 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 99 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
| 94 | enum omap_color_mode color_mode); | 100 | enum omap_color_mode color_mode); |
| 95 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); | 101 | const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); |
| @@ -100,4 +106,7 @@ u32 dss_feat_get_burst_size_unit(void); /* in bytes */ | |||
| 100 | bool dss_has_feature(enum dss_feat_id id); | 106 | bool dss_has_feature(enum dss_feat_id id); |
| 101 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 107 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
| 102 | void dss_features_init(void); | 108 | void dss_features_init(void); |
| 109 | #if defined(CONFIG_OMAP4_DSS_HDMI) | ||
| 110 | void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data); | ||
| 111 | #endif | ||
| 103 | #endif | 112 | #endif |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 256f27a9064a..3262f0f1fa35 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
| @@ -37,26 +37,41 @@ | |||
| 37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 37 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
| 38 | #include <sound/soc.h> | 38 | #include <sound/soc.h> |
| 39 | #include <sound/pcm_params.h> | 39 | #include <sound/pcm_params.h> |
| 40 | #include "ti_hdmi_4xxx_ip.h" | ||
| 40 | #endif | 41 | #endif |
| 41 | 42 | ||
| 43 | #include "ti_hdmi.h" | ||
| 42 | #include "dss.h" | 44 | #include "dss.h" |
| 43 | #include "hdmi.h" | ||
| 44 | #include "dss_features.h" | 45 | #include "dss_features.h" |
| 45 | 46 | ||
| 47 | #define HDMI_WP 0x0 | ||
| 48 | #define HDMI_CORE_SYS 0x400 | ||
| 49 | #define HDMI_CORE_AV 0x900 | ||
| 50 | #define HDMI_PLLCTRL 0x200 | ||
| 51 | #define HDMI_PHY 0x300 | ||
| 52 | |||
| 53 | /* HDMI EDID Length move this */ | ||
| 54 | #define HDMI_EDID_MAX_LENGTH 256 | ||
| 55 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
| 56 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
| 57 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
| 58 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
| 59 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
| 60 | |||
| 61 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
| 62 | |||
| 63 | #define HDMI_DEFAULT_REGN 16 | ||
| 64 | #define HDMI_DEFAULT_REGM2 1 | ||
| 65 | |||
| 46 | static struct { | 66 | static struct { |
| 47 | struct mutex lock; | 67 | struct mutex lock; |
| 48 | struct omap_display_platform_data *pdata; | 68 | struct omap_display_platform_data *pdata; |
| 49 | struct platform_device *pdev; | 69 | struct platform_device *pdev; |
| 50 | void __iomem *base_wp; /* HDMI wrapper */ | 70 | struct hdmi_ip_data ip_data; |
| 51 | int code; | 71 | int code; |
| 52 | int mode; | 72 | int mode; |
| 53 | u8 edid[HDMI_EDID_MAX_LENGTH]; | ||
| 54 | u8 edid_set; | ||
| 55 | bool custom_set; | ||
| 56 | struct hdmi_config cfg; | ||
| 57 | 73 | ||
| 58 | struct clk *sys_clk; | 74 | struct clk *sys_clk; |
| 59 | struct clk *hdmi_clk; | ||
| 60 | } hdmi; | 75 | } hdmi; |
| 61 | 76 | ||
| 62 | /* | 77 | /* |
| @@ -144,30 +159,6 @@ static const int code_vesa[85] = { | |||
| 144 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | 159 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, |
| 145 | -1, 27, 28, -1, 33}; | 160 | -1, 27, 28, -1, 33}; |
| 146 | 161 | ||
| 147 | static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; | ||
| 148 | |||
| 149 | static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) | ||
| 150 | { | ||
| 151 | __raw_writel(val, hdmi.base_wp + idx.idx); | ||
| 152 | } | ||
| 153 | |||
| 154 | static inline u32 hdmi_read_reg(const struct hdmi_reg idx) | ||
| 155 | { | ||
| 156 | return __raw_readl(hdmi.base_wp + idx.idx); | ||
| 157 | } | ||
| 158 | |||
| 159 | static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, | ||
| 160 | int b2, int b1, u32 val) | ||
| 161 | { | ||
| 162 | u32 t = 0; | ||
| 163 | while (val != REG_GET(idx, b2, b1)) { | ||
| 164 | udelay(1); | ||
| 165 | if (t++ > 10000) | ||
| 166 | return !val; | ||
| 167 | } | ||
| 168 | return val; | ||
| 169 | } | ||
| 170 | |||
| 171 | static int hdmi_runtime_get(void) | 162 | static int hdmi_runtime_get(void) |
| 172 | { | 163 | { |
| 173 | int r; | 164 | int r; |
| @@ -193,304 +184,7 @@ int hdmi_init_display(struct omap_dss_device *dssdev) | |||
| 193 | { | 184 | { |
| 194 | DSSDBG("init_display\n"); | 185 | DSSDBG("init_display\n"); |
| 195 | 186 | ||
| 196 | return 0; | 187 | dss_init_hdmi_ip_ops(&hdmi.ip_data); |
| 197 | } | ||
| 198 | |||
| 199 | static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, | ||
| 200 | struct hdmi_pll_info *fmt, u16 sd) | ||
| 201 | { | ||
| 202 | u32 r; | ||
| 203 | |||
| 204 | /* PLL start always use manual mode */ | ||
| 205 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
| 206 | |||
| 207 | r = hdmi_read_reg(PLLCTRL_CFG1); | ||
| 208 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
| 209 | r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ | ||
| 210 | |||
| 211 | hdmi_write_reg(PLLCTRL_CFG1, r); | ||
| 212 | |||
| 213 | r = hdmi_read_reg(PLLCTRL_CFG2); | ||
| 214 | |||
| 215 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
| 216 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
| 217 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
| 218 | |||
| 219 | if (dcofreq) { | ||
| 220 | /* divider programming for frequency beyond 1000Mhz */ | ||
| 221 | REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); | ||
| 222 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
| 223 | } else { | ||
| 224 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
| 225 | } | ||
| 226 | |||
| 227 | hdmi_write_reg(PLLCTRL_CFG2, r); | ||
| 228 | |||
| 229 | r = hdmi_read_reg(PLLCTRL_CFG4); | ||
| 230 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
| 231 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
| 232 | |||
| 233 | hdmi_write_reg(PLLCTRL_CFG4, r); | ||
| 234 | |||
| 235 | /* go now */ | ||
| 236 | REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
| 237 | |||
| 238 | /* wait for bit change */ | ||
| 239 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { | ||
| 240 | DSSERR("PLL GO bit not set\n"); | ||
| 241 | return -ETIMEDOUT; | ||
| 242 | } | ||
| 243 | |||
| 244 | /* Wait till the lock bit is set in PLL status */ | ||
| 245 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
| 246 | DSSWARN("cannot lock PLL\n"); | ||
| 247 | DSSWARN("CFG1 0x%x\n", | ||
| 248 | hdmi_read_reg(PLLCTRL_CFG1)); | ||
| 249 | DSSWARN("CFG2 0x%x\n", | ||
| 250 | hdmi_read_reg(PLLCTRL_CFG2)); | ||
| 251 | DSSWARN("CFG4 0x%x\n", | ||
| 252 | hdmi_read_reg(PLLCTRL_CFG4)); | ||
| 253 | return -ETIMEDOUT; | ||
| 254 | } | ||
| 255 | |||
| 256 | DSSDBG("PLL locked!\n"); | ||
| 257 | |||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | |||
| 261 | /* PHY_PWR_CMD */ | ||
| 262 | static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) | ||
| 263 | { | ||
| 264 | /* Command for power control of HDMI PHY */ | ||
| 265 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); | ||
| 266 | |||
| 267 | /* Status of the power control of HDMI PHY */ | ||
| 268 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
| 269 | DSSERR("Failed to set PHY power mode to %d\n", val); | ||
| 270 | return -ETIMEDOUT; | ||
| 271 | } | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* PLL_PWR_CMD */ | ||
| 277 | static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) | ||
| 278 | { | ||
| 279 | /* Command for power control of HDMI PLL */ | ||
| 280 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); | ||
| 281 | |||
| 282 | /* wait till PHY_PWR_STATUS is set */ | ||
| 283 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { | ||
| 284 | DSSERR("Failed to set PHY_PWR_STATUS\n"); | ||
| 285 | return -ETIMEDOUT; | ||
| 286 | } | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | static int hdmi_pll_reset(void) | ||
| 292 | { | ||
| 293 | /* SYSRESET controlled by power FSM */ | ||
| 294 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
| 295 | |||
| 296 | /* READ 0x0 reset is in progress */ | ||
| 297 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
| 298 | DSSERR("Failed to sysreset PLL\n"); | ||
| 299 | return -ETIMEDOUT; | ||
| 300 | } | ||
| 301 | |||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | static int hdmi_phy_init(void) | ||
| 306 | { | ||
| 307 | u16 r = 0; | ||
| 308 | |||
| 309 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); | ||
| 310 | if (r) | ||
| 311 | return r; | ||
| 312 | |||
| 313 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); | ||
| 314 | if (r) | ||
| 315 | return r; | ||
| 316 | |||
| 317 | /* | ||
| 318 | * Read address 0 in order to get the SCP reset done completed | ||
| 319 | * Dummy access performed to make sure reset is done | ||
| 320 | */ | ||
| 321 | hdmi_read_reg(HDMI_TXPHY_TX_CTRL); | ||
| 322 | |||
| 323 | /* | ||
| 324 | * Write to phy address 0 to configure the clock | ||
| 325 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
| 326 | */ | ||
| 327 | REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
| 328 | |||
| 329 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
| 330 | hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
| 331 | |||
| 332 | /* Setup max LDO voltage */ | ||
| 333 | REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
| 334 | |||
| 335 | /* Write to phy address 3 to change the polarity control */ | ||
| 336 | REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
| 337 | |||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | static int hdmi_pll_program(struct hdmi_pll_info *fmt) | ||
| 342 | { | ||
| 343 | u16 r = 0; | ||
| 344 | enum hdmi_clk_refsel refsel; | ||
| 345 | |||
| 346 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
| 347 | if (r) | ||
| 348 | return r; | ||
| 349 | |||
| 350 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
| 351 | if (r) | ||
| 352 | return r; | ||
| 353 | |||
| 354 | r = hdmi_pll_reset(); | ||
| 355 | if (r) | ||
| 356 | return r; | ||
| 357 | |||
| 358 | refsel = HDMI_REFSEL_SYSCLK; | ||
| 359 | |||
| 360 | r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); | ||
| 361 | if (r) | ||
| 362 | return r; | ||
| 363 | |||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | |||
| 367 | static void hdmi_phy_off(void) | ||
| 368 | { | ||
| 369 | hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); | ||
| 370 | } | ||
| 371 | |||
| 372 | static int hdmi_core_ddc_edid(u8 *pedid, int ext) | ||
| 373 | { | ||
| 374 | u32 i, j; | ||
| 375 | char checksum = 0; | ||
| 376 | u32 offset = 0; | ||
| 377 | |||
| 378 | /* Turn on CLK for DDC */ | ||
| 379 | REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
| 380 | |||
| 381 | /* | ||
| 382 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | ||
| 383 | * right shifted values( The behavior is not consistent and seen only | ||
| 384 | * with some TV's) | ||
| 385 | */ | ||
| 386 | usleep_range(800, 1000); | ||
| 387 | |||
| 388 | if (!ext) { | ||
| 389 | /* Clk SCL Devices */ | ||
| 390 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
| 391 | |||
| 392 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
| 393 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
| 394 | 4, 4, 0) != 0) { | ||
| 395 | DSSERR("Failed to program DDC\n"); | ||
| 396 | return -ETIMEDOUT; | ||
| 397 | } | ||
| 398 | |||
| 399 | /* Clear FIFO */ | ||
| 400 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
| 401 | |||
| 402 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
| 403 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
| 404 | 4, 4, 0) != 0) { | ||
| 405 | DSSERR("Failed to program DDC\n"); | ||
| 406 | return -ETIMEDOUT; | ||
| 407 | } | ||
| 408 | |||
| 409 | } else { | ||
| 410 | if (ext % 2 != 0) | ||
| 411 | offset = 0x80; | ||
| 412 | } | ||
| 413 | |||
| 414 | /* Load Segment Address Register */ | ||
| 415 | REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | ||
| 416 | |||
| 417 | /* Load Slave Address Register */ | ||
| 418 | REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
| 419 | |||
| 420 | /* Load Offset Address Register */ | ||
| 421 | REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
| 422 | |||
| 423 | /* Load Byte Count */ | ||
| 424 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
| 425 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
| 426 | |||
| 427 | /* Set DDC_CMD */ | ||
| 428 | if (ext) | ||
| 429 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
| 430 | else | ||
| 431 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
| 432 | |||
| 433 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
| 434 | if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
| 435 | DSSWARN("I2C Bus Low?\n"); | ||
| 436 | return -EIO; | ||
| 437 | } | ||
| 438 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
| 439 | if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
| 440 | DSSWARN("I2C No Ack\n"); | ||
| 441 | return -EIO; | ||
| 442 | } | ||
| 443 | |||
| 444 | i = ext * 128; | ||
| 445 | j = 0; | ||
| 446 | while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
| 447 | (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
| 448 | j < 128) { | ||
| 449 | |||
| 450 | if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | ||
| 451 | /* FIFO not empty */ | ||
| 452 | pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); | ||
| 453 | j++; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | for (j = 0; j < 128; j++) | ||
| 458 | checksum += pedid[j]; | ||
| 459 | |||
| 460 | if (checksum != 0) { | ||
| 461 | DSSERR("E-EDID checksum failed!!\n"); | ||
| 462 | return -EIO; | ||
| 463 | } | ||
| 464 | |||
| 465 | return 0; | ||
| 466 | } | ||
| 467 | |||
| 468 | static int read_edid(u8 *pedid, u16 max_length) | ||
| 469 | { | ||
| 470 | int r = 0, n = 0, i = 0; | ||
| 471 | int max_ext_blocks = (max_length / 128) - 1; | ||
| 472 | |||
| 473 | r = hdmi_core_ddc_edid(pedid, 0); | ||
| 474 | if (r) { | ||
| 475 | return r; | ||
| 476 | } else { | ||
| 477 | n = pedid[0x7e]; | ||
| 478 | |||
| 479 | /* | ||
| 480 | * README: need to comply with max_length set by the caller. | ||
| 481 | * Better implementation should be to allocate necessary | ||
| 482 | * memory to store EDID according to nb_block field found | ||
| 483 | * in first block | ||
| 484 | */ | ||
| 485 | if (n > max_ext_blocks) | ||
| 486 | n = max_ext_blocks; | ||
| 487 | |||
| 488 | for (i = 1; i <= n; i++) { | ||
| 489 | r = hdmi_core_ddc_edid(pedid, i); | ||
| 490 | if (r) | ||
| 491 | return r; | ||
| 492 | } | ||
| 493 | } | ||
| 494 | return 0; | 188 | return 0; |
| 495 | } | 189 | } |
| 496 | 190 | ||
| @@ -518,7 +212,7 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | |||
| 518 | { | 212 | { |
| 519 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | 213 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; |
| 520 | int timing_vsync = 0, timing_hsync = 0; | 214 | int timing_vsync = 0, timing_hsync = 0; |
| 521 | struct omap_video_timings temp; | 215 | struct hdmi_video_timings temp; |
| 522 | struct hdmi_cm cm = {-1}; | 216 | struct hdmi_cm cm = {-1}; |
| 523 | DSSDBG("hdmi_get_code\n"); | 217 | DSSDBG("hdmi_get_code\n"); |
| 524 | 218 | ||
| @@ -556,500 +250,6 @@ static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | |||
| 556 | return cm; | 250 | return cm; |
| 557 | } | 251 | } |
| 558 | 252 | ||
| 559 | static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , | ||
| 560 | struct omap_video_timings *timings) | ||
| 561 | { | ||
| 562 | /* X and Y resolution */ | ||
| 563 | timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | | ||
| 564 | edid[current_descriptor_addrs + 2]); | ||
| 565 | timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | | ||
| 566 | edid[current_descriptor_addrs + 5]); | ||
| 567 | |||
| 568 | timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | | ||
| 569 | edid[current_descriptor_addrs]); | ||
| 570 | |||
| 571 | timings->pixel_clock = 10 * timings->pixel_clock; | ||
| 572 | |||
| 573 | /* HORIZONTAL FRONT PORCH */ | ||
| 574 | timings->hfp = edid[current_descriptor_addrs + 8] | | ||
| 575 | ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); | ||
| 576 | /* HORIZONTAL SYNC WIDTH */ | ||
| 577 | timings->hsw = edid[current_descriptor_addrs + 9] | | ||
| 578 | ((edid[current_descriptor_addrs + 11] & 0x30) << 4); | ||
| 579 | /* HORIZONTAL BACK PORCH */ | ||
| 580 | timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | | ||
| 581 | edid[current_descriptor_addrs + 3]) - | ||
| 582 | (timings->hfp + timings->hsw); | ||
| 583 | /* VERTICAL FRONT PORCH */ | ||
| 584 | timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | | ||
| 585 | ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); | ||
| 586 | /* VERTICAL SYNC WIDTH */ | ||
| 587 | timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | | ||
| 588 | ((edid[current_descriptor_addrs + 11] & 0x03) << 4); | ||
| 589 | /* VERTICAL BACK PORCH */ | ||
| 590 | timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | | ||
| 591 | edid[current_descriptor_addrs + 6]) - | ||
| 592 | (timings->vfp + timings->vsw); | ||
| 593 | |||
| 594 | } | ||
| 595 | |||
| 596 | /* Description : This function gets the resolution information from EDID */ | ||
| 597 | static void get_edid_timing_data(u8 *edid) | ||
| 598 | { | ||
| 599 | u8 count; | ||
| 600 | u16 current_descriptor_addrs; | ||
| 601 | struct hdmi_cm cm; | ||
| 602 | struct omap_video_timings edid_timings; | ||
| 603 | |||
| 604 | /* search block 0, there are 4 DTDs arranged in priority order */ | ||
| 605 | for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { | ||
| 606 | current_descriptor_addrs = | ||
| 607 | EDID_DESCRIPTOR_BLOCK0_ADDRESS + | ||
| 608 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
| 609 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
| 610 | edid, &edid_timings); | ||
| 611 | cm = hdmi_get_code(&edid_timings); | ||
| 612 | DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", | ||
| 613 | count, cm.code, cm.mode); | ||
| 614 | if (cm.code == -1) { | ||
| 615 | continue; | ||
| 616 | } else { | ||
| 617 | hdmi.code = cm.code; | ||
| 618 | hdmi.mode = cm.mode; | ||
| 619 | DSSDBG("code = %d , mode = %d\n", | ||
| 620 | hdmi.code, hdmi.mode); | ||
| 621 | return; | ||
| 622 | } | ||
| 623 | } | ||
| 624 | if (edid[0x7e] != 0x00) { | ||
| 625 | for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; | ||
| 626 | count++) { | ||
| 627 | current_descriptor_addrs = | ||
| 628 | EDID_DESCRIPTOR_BLOCK1_ADDRESS + | ||
| 629 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
| 630 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
| 631 | edid, &edid_timings); | ||
| 632 | cm = hdmi_get_code(&edid_timings); | ||
| 633 | DSSDBG("Block1[%d] value matches code = %d, mode = %d", | ||
| 634 | count, cm.code, cm.mode); | ||
| 635 | if (cm.code == -1) { | ||
| 636 | continue; | ||
| 637 | } else { | ||
| 638 | hdmi.code = cm.code; | ||
| 639 | hdmi.mode = cm.mode; | ||
| 640 | DSSDBG("code = %d , mode = %d\n", | ||
| 641 | hdmi.code, hdmi.mode); | ||
| 642 | return; | ||
| 643 | } | ||
| 644 | } | ||
| 645 | } | ||
| 646 | |||
| 647 | DSSINFO("no valid timing found , falling back to VGA\n"); | ||
| 648 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
| 649 | hdmi.mode = HDMI_DVI; | ||
| 650 | } | ||
| 651 | |||
| 652 | static void hdmi_read_edid(struct omap_video_timings *dp) | ||
| 653 | { | ||
| 654 | int ret = 0, code; | ||
| 655 | |||
| 656 | memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); | ||
| 657 | |||
| 658 | if (!hdmi.edid_set) | ||
| 659 | ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); | ||
| 660 | |||
| 661 | if (!ret) { | ||
| 662 | if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { | ||
| 663 | /* search for timings of default resolution */ | ||
| 664 | get_edid_timing_data(hdmi.edid); | ||
| 665 | hdmi.edid_set = true; | ||
| 666 | } | ||
| 667 | } else { | ||
| 668 | DSSWARN("failed to read E-EDID\n"); | ||
| 669 | } | ||
| 670 | |||
| 671 | if (!hdmi.edid_set) { | ||
| 672 | DSSINFO("fallback to VGA\n"); | ||
| 673 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
| 674 | hdmi.mode = HDMI_DVI; | ||
| 675 | } | ||
| 676 | |||
| 677 | code = get_timings_index(); | ||
| 678 | |||
| 679 | *dp = cea_vesa_timings[code].timings; | ||
| 680 | } | ||
| 681 | |||
| 682 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
| 683 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
| 684 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
| 685 | { | ||
| 686 | DSSDBG("Enter hdmi_core_init\n"); | ||
| 687 | |||
| 688 | /* video core */ | ||
| 689 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
| 690 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
| 691 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
| 692 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
| 693 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
| 694 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
| 695 | |||
| 696 | /* info frame */ | ||
| 697 | avi_cfg->db1_format = 0; | ||
| 698 | avi_cfg->db1_active_info = 0; | ||
| 699 | avi_cfg->db1_bar_info_dv = 0; | ||
| 700 | avi_cfg->db1_scan_info = 0; | ||
| 701 | avi_cfg->db2_colorimetry = 0; | ||
| 702 | avi_cfg->db2_aspect_ratio = 0; | ||
| 703 | avi_cfg->db2_active_fmt_ar = 0; | ||
| 704 | avi_cfg->db3_itc = 0; | ||
| 705 | avi_cfg->db3_ec = 0; | ||
| 706 | avi_cfg->db3_q_range = 0; | ||
| 707 | avi_cfg->db3_nup_scaling = 0; | ||
| 708 | avi_cfg->db4_videocode = 0; | ||
| 709 | avi_cfg->db5_pixel_repeat = 0; | ||
| 710 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
| 711 | avi_cfg->db8_9_line_sofbottom = 0; | ||
| 712 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
| 713 | avi_cfg->db12_13_pixel_sofright = 0; | ||
| 714 | |||
| 715 | /* packet enable and repeat */ | ||
| 716 | repeat_cfg->audio_pkt = 0; | ||
| 717 | repeat_cfg->audio_pkt_repeat = 0; | ||
| 718 | repeat_cfg->avi_infoframe = 0; | ||
| 719 | repeat_cfg->avi_infoframe_repeat = 0; | ||
| 720 | repeat_cfg->gen_cntrl_pkt = 0; | ||
| 721 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
| 722 | repeat_cfg->generic_pkt = 0; | ||
| 723 | repeat_cfg->generic_pkt_repeat = 0; | ||
| 724 | } | ||
| 725 | |||
| 726 | static void hdmi_core_powerdown_disable(void) | ||
| 727 | { | ||
| 728 | DSSDBG("Enter hdmi_core_powerdown_disable\n"); | ||
| 729 | REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
| 730 | } | ||
| 731 | |||
| 732 | static void hdmi_core_swreset_release(void) | ||
| 733 | { | ||
| 734 | DSSDBG("Enter hdmi_core_swreset_release\n"); | ||
| 735 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
| 736 | } | ||
| 737 | |||
| 738 | static void hdmi_core_swreset_assert(void) | ||
| 739 | { | ||
| 740 | DSSDBG("Enter hdmi_core_swreset_assert\n"); | ||
| 741 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
| 742 | } | ||
| 743 | |||
| 744 | /* DSS_HDMI_CORE_VIDEO_CONFIG */ | ||
| 745 | static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) | ||
| 746 | { | ||
| 747 | u32 r = 0; | ||
| 748 | |||
| 749 | /* sys_ctrl1 default configuration not tunable */ | ||
| 750 | r = hdmi_read_reg(HDMI_CORE_CTRL1); | ||
| 751 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
| 752 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
| 753 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
| 754 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
| 755 | hdmi_write_reg(HDMI_CORE_CTRL1, r); | ||
| 756 | |||
| 757 | REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
| 758 | |||
| 759 | /* Vid_Mode */ | ||
| 760 | r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); | ||
| 761 | |||
| 762 | /* dither truncation configuration */ | ||
| 763 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
| 764 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
| 765 | r = FLD_MOD(r, 1, 5, 5); | ||
| 766 | } else { | ||
| 767 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
| 768 | r = FLD_MOD(r, 0, 5, 5); | ||
| 769 | } | ||
| 770 | hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); | ||
| 771 | |||
| 772 | /* HDMI_Ctrl */ | ||
| 773 | r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); | ||
| 774 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
| 775 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
| 776 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
| 777 | hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); | ||
| 778 | |||
| 779 | /* TMDS_CTRL */ | ||
| 780 | REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, | ||
| 781 | cfg->tclk_sel_clkmult, 6, 5); | ||
| 782 | } | ||
| 783 | |||
| 784 | static void hdmi_core_aux_infoframe_avi_config( | ||
| 785 | struct hdmi_core_infoframe_avi info_avi) | ||
| 786 | { | ||
| 787 | u32 val; | ||
| 788 | char sum = 0, checksum = 0; | ||
| 789 | |||
| 790 | sum += 0x82 + 0x002 + 0x00D; | ||
| 791 | hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
| 792 | hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); | ||
| 793 | hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
| 794 | |||
| 795 | val = (info_avi.db1_format << 5) | | ||
| 796 | (info_avi.db1_active_info << 4) | | ||
| 797 | (info_avi.db1_bar_info_dv << 2) | | ||
| 798 | (info_avi.db1_scan_info); | ||
| 799 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
| 800 | sum += val; | ||
| 801 | |||
| 802 | val = (info_avi.db2_colorimetry << 6) | | ||
| 803 | (info_avi.db2_aspect_ratio << 4) | | ||
| 804 | (info_avi.db2_active_fmt_ar); | ||
| 805 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
| 806 | sum += val; | ||
| 807 | |||
| 808 | val = (info_avi.db3_itc << 7) | | ||
| 809 | (info_avi.db3_ec << 4) | | ||
| 810 | (info_avi.db3_q_range << 2) | | ||
| 811 | (info_avi.db3_nup_scaling); | ||
| 812 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
| 813 | sum += val; | ||
| 814 | |||
| 815 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); | ||
| 816 | sum += info_avi.db4_videocode; | ||
| 817 | |||
| 818 | val = info_avi.db5_pixel_repeat; | ||
| 819 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
| 820 | sum += val; | ||
| 821 | |||
| 822 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
| 823 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
| 824 | sum += val; | ||
| 825 | |||
| 826 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
| 827 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
| 828 | sum += val; | ||
| 829 | |||
| 830 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
| 831 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
| 832 | sum += val; | ||
| 833 | |||
| 834 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
| 835 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
| 836 | sum += val; | ||
| 837 | |||
| 838 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
| 839 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
| 840 | sum += val; | ||
| 841 | |||
| 842 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
| 843 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
| 844 | sum += val; | ||
| 845 | |||
| 846 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
| 847 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
| 848 | sum += val; | ||
| 849 | |||
| 850 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
| 851 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
| 852 | sum += val; | ||
| 853 | |||
| 854 | checksum = 0x100 - sum; | ||
| 855 | hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
| 856 | } | ||
| 857 | |||
| 858 | static void hdmi_core_av_packet_config( | ||
| 859 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
| 860 | { | ||
| 861 | /* enable/repeat the infoframe */ | ||
| 862 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, | ||
| 863 | (repeat_cfg.audio_pkt << 5) | | ||
| 864 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
| 865 | (repeat_cfg.avi_infoframe << 1) | | ||
| 866 | (repeat_cfg.avi_infoframe_repeat)); | ||
| 867 | |||
| 868 | /* enable/repeat the packet */ | ||
| 869 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, | ||
| 870 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
| 871 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
| 872 | (repeat_cfg.generic_pkt << 1) | | ||
| 873 | (repeat_cfg.generic_pkt_repeat)); | ||
| 874 | } | ||
| 875 | |||
| 876 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
| 877 | struct hdmi_video_format *video_fmt, | ||
| 878 | struct hdmi_video_interface *video_int) | ||
| 879 | { | ||
| 880 | DSSDBG("Enter hdmi_wp_init\n"); | ||
| 881 | |||
| 882 | timings->hbp = 0; | ||
| 883 | timings->hfp = 0; | ||
| 884 | timings->hsw = 0; | ||
| 885 | timings->vbp = 0; | ||
| 886 | timings->vfp = 0; | ||
| 887 | timings->vsw = 0; | ||
| 888 | |||
| 889 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
| 890 | video_fmt->y_res = 0; | ||
| 891 | video_fmt->x_res = 0; | ||
| 892 | |||
| 893 | video_int->vsp = 0; | ||
| 894 | video_int->hsp = 0; | ||
| 895 | |||
| 896 | video_int->interlacing = 0; | ||
| 897 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
| 898 | |||
| 899 | } | ||
| 900 | |||
| 901 | static void hdmi_wp_video_start(bool start) | ||
| 902 | { | ||
| 903 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
| 904 | } | ||
| 905 | |||
| 906 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
| 907 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
| 908 | { | ||
| 909 | DSSDBG("Enter hdmi_wp_video_init_format\n"); | ||
| 910 | |||
| 911 | video_fmt->y_res = param->timings.timings.y_res; | ||
| 912 | video_fmt->x_res = param->timings.timings.x_res; | ||
| 913 | |||
| 914 | timings->hbp = param->timings.timings.hbp; | ||
| 915 | timings->hfp = param->timings.timings.hfp; | ||
| 916 | timings->hsw = param->timings.timings.hsw; | ||
| 917 | timings->vbp = param->timings.timings.vbp; | ||
| 918 | timings->vfp = param->timings.timings.vfp; | ||
| 919 | timings->vsw = param->timings.timings.vsw; | ||
| 920 | } | ||
| 921 | |||
| 922 | static void hdmi_wp_video_config_format( | ||
| 923 | struct hdmi_video_format *video_fmt) | ||
| 924 | { | ||
| 925 | u32 l = 0; | ||
| 926 | |||
| 927 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); | ||
| 928 | |||
| 929 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
| 930 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
| 931 | hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); | ||
| 932 | } | ||
| 933 | |||
| 934 | static void hdmi_wp_video_config_interface( | ||
| 935 | struct hdmi_video_interface *video_int) | ||
| 936 | { | ||
| 937 | u32 r; | ||
| 938 | DSSDBG("Enter hdmi_wp_video_config_interface\n"); | ||
| 939 | |||
| 940 | r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); | ||
| 941 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
| 942 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
| 943 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
| 944 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
| 945 | hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); | ||
| 946 | } | ||
| 947 | |||
| 948 | static void hdmi_wp_video_config_timing( | ||
| 949 | struct omap_video_timings *timings) | ||
| 950 | { | ||
| 951 | u32 timing_h = 0; | ||
| 952 | u32 timing_v = 0; | ||
| 953 | |||
| 954 | DSSDBG("Enter hdmi_wp_video_config_timing\n"); | ||
| 955 | |||
| 956 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
| 957 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
| 958 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
| 959 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
| 960 | |||
| 961 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
| 962 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
| 963 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
| 964 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
| 965 | } | ||
| 966 | |||
| 967 | static void hdmi_basic_configure(struct hdmi_config *cfg) | ||
| 968 | { | ||
| 969 | /* HDMI */ | ||
| 970 | struct omap_video_timings video_timing; | ||
| 971 | struct hdmi_video_format video_format; | ||
| 972 | struct hdmi_video_interface video_interface; | ||
| 973 | /* HDMI core */ | ||
| 974 | struct hdmi_core_infoframe_avi avi_cfg; | ||
| 975 | struct hdmi_core_video_config v_core_cfg; | ||
| 976 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
| 977 | |||
| 978 | hdmi_wp_init(&video_timing, &video_format, | ||
| 979 | &video_interface); | ||
| 980 | |||
| 981 | hdmi_core_init(&v_core_cfg, | ||
| 982 | &avi_cfg, | ||
| 983 | &repeat_cfg); | ||
| 984 | |||
| 985 | hdmi_wp_video_init_format(&video_format, | ||
| 986 | &video_timing, cfg); | ||
| 987 | |||
| 988 | hdmi_wp_video_config_timing(&video_timing); | ||
| 989 | |||
| 990 | /* video config */ | ||
| 991 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
| 992 | |||
| 993 | hdmi_wp_video_config_format(&video_format); | ||
| 994 | |||
| 995 | video_interface.vsp = cfg->timings.vsync_pol; | ||
| 996 | video_interface.hsp = cfg->timings.hsync_pol; | ||
| 997 | video_interface.interlacing = cfg->interlace; | ||
| 998 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
| 999 | |||
| 1000 | hdmi_wp_video_config_interface(&video_interface); | ||
| 1001 | |||
| 1002 | /* | ||
| 1003 | * configure core video part | ||
| 1004 | * set software reset in the core | ||
| 1005 | */ | ||
| 1006 | hdmi_core_swreset_assert(); | ||
| 1007 | |||
| 1008 | /* power down off */ | ||
| 1009 | hdmi_core_powerdown_disable(); | ||
| 1010 | |||
| 1011 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
| 1012 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
| 1013 | |||
| 1014 | hdmi_core_video_config(&v_core_cfg); | ||
| 1015 | |||
| 1016 | /* release software reset in the core */ | ||
| 1017 | hdmi_core_swreset_release(); | ||
| 1018 | |||
| 1019 | /* | ||
| 1020 | * configure packet | ||
| 1021 | * info frame video see doc CEA861-D page 65 | ||
| 1022 | */ | ||
| 1023 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
| 1024 | avi_cfg.db1_active_info = | ||
| 1025 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
| 1026 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
| 1027 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
| 1028 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
| 1029 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
| 1030 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
| 1031 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
| 1032 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
| 1033 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
| 1034 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
| 1035 | avi_cfg.db4_videocode = cfg->cm.code; | ||
| 1036 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
| 1037 | avi_cfg.db6_7_line_eoftop = 0; | ||
| 1038 | avi_cfg.db8_9_line_sofbottom = 0; | ||
| 1039 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
| 1040 | avi_cfg.db12_13_pixel_sofright = 0; | ||
| 1041 | |||
| 1042 | hdmi_core_aux_infoframe_avi_config(avi_cfg); | ||
| 1043 | |||
| 1044 | /* enable/repeat the infoframe */ | ||
| 1045 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
| 1046 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
| 1047 | /* wakeup */ | ||
| 1048 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
| 1049 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
| 1050 | hdmi_core_av_packet_config(repeat_cfg); | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | static void update_hdmi_timings(struct hdmi_config *cfg, | 253 | static void update_hdmi_timings(struct hdmi_config *cfg, |
| 1054 | struct omap_video_timings *timings, int code) | 254 | struct omap_video_timings *timings, int code) |
| 1055 | { | 255 | { |
| @@ -1066,6 +266,12 @@ static void update_hdmi_timings(struct hdmi_config *cfg, | |||
| 1066 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | 266 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; |
| 1067 | } | 267 | } |
| 1068 | 268 | ||
| 269 | unsigned long hdmi_get_pixel_clock(void) | ||
| 270 | { | ||
| 271 | /* HDMI Pixel Clock in Mhz */ | ||
| 272 | return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000; | ||
| 273 | } | ||
| 274 | |||
| 1069 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | 275 | static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, |
| 1070 | struct hdmi_pll_info *pi) | 276 | struct hdmi_pll_info *pi) |
| 1071 | { | 277 | { |
| @@ -1077,15 +283,23 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
| 1077 | * Input clock is predivided by N + 1 | 283 | * Input clock is predivided by N + 1 |
| 1078 | * out put of which is reference clk | 284 | * out put of which is reference clk |
| 1079 | */ | 285 | */ |
| 1080 | pi->regn = dssdev->clocks.hdmi.regn; | 286 | if (dssdev->clocks.hdmi.regn == 0) |
| 1081 | refclk = clkin / (pi->regn + 1); | 287 | pi->regn = HDMI_DEFAULT_REGN; |
| 288 | else | ||
| 289 | pi->regn = dssdev->clocks.hdmi.regn; | ||
| 290 | |||
| 291 | refclk = clkin / pi->regn; | ||
| 1082 | 292 | ||
| 1083 | /* | 293 | /* |
| 1084 | * multiplier is pixel_clk/ref_clk | 294 | * multiplier is pixel_clk/ref_clk |
| 1085 | * Multiplying by 100 to avoid fractional part removal | 295 | * Multiplying by 100 to avoid fractional part removal |
| 1086 | */ | 296 | */ |
| 1087 | pi->regm = (phy * 100 / (refclk)) / 100; | 297 | pi->regm = (phy * 100 / (refclk)) / 100; |
| 1088 | pi->regm2 = dssdev->clocks.hdmi.regm2; | 298 | |
| 299 | if (dssdev->clocks.hdmi.regm2 == 0) | ||
| 300 | pi->regm2 = HDMI_DEFAULT_REGM2; | ||
| 301 | else | ||
| 302 | pi->regm2 = dssdev->clocks.hdmi.regm2; | ||
| 1089 | 303 | ||
| 1090 | /* | 304 | /* |
| 1091 | * fractional multiplier is remainder of the difference between | 305 | * fractional multiplier is remainder of the difference between |
| @@ -1100,7 +314,10 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
| 1100 | * is greater than 1000MHz | 314 | * is greater than 1000MHz |
| 1101 | */ | 315 | */ |
| 1102 | pi->dcofreq = phy > 1000 * 100; | 316 | pi->dcofreq = phy > 1000 * 100; |
| 1103 | pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10; | 317 | pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; |
| 318 | |||
| 319 | /* Set the reference clock to sysclk reference */ | ||
| 320 | pi->refsel = HDMI_REFSEL_SYSCLK; | ||
| 1104 | 321 | ||
| 1105 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | 322 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); |
| 1106 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | 323 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); |
| @@ -1109,7 +326,6 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
| 1109 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 326 | static int hdmi_power_on(struct omap_dss_device *dssdev) |
| 1110 | { | 327 | { |
| 1111 | int r, code = 0; | 328 | int r, code = 0; |
| 1112 | struct hdmi_pll_info pll_data; | ||
| 1113 | struct omap_video_timings *p; | 329 | struct omap_video_timings *p; |
| 1114 | unsigned long phy; | 330 | unsigned long phy; |
| 1115 | 331 | ||
| @@ -1117,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
| 1117 | if (r) | 333 | if (r) |
| 1118 | return r; | 334 | return r; |
| 1119 | 335 | ||
| 1120 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | 336 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); |
| 1121 | 337 | ||
| 1122 | p = &dssdev->panel.timings; | 338 | p = &dssdev->panel.timings; |
| 1123 | 339 | ||
| @@ -1125,36 +341,31 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
| 1125 | dssdev->panel.timings.x_res, | 341 | dssdev->panel.timings.x_res, |
| 1126 | dssdev->panel.timings.y_res); | 342 | dssdev->panel.timings.y_res); |
| 1127 | 343 | ||
| 1128 | if (!hdmi.custom_set) { | ||
| 1129 | DSSDBG("Read EDID as no EDID is not set on poweron\n"); | ||
| 1130 | hdmi_read_edid(p); | ||
| 1131 | } | ||
| 1132 | code = get_timings_index(); | 344 | code = get_timings_index(); |
| 1133 | dssdev->panel.timings = cea_vesa_timings[code].timings; | 345 | update_hdmi_timings(&hdmi.ip_data.cfg, p, code); |
| 1134 | update_hdmi_timings(&hdmi.cfg, p, code); | ||
| 1135 | 346 | ||
| 1136 | phy = p->pixel_clock; | 347 | phy = p->pixel_clock; |
| 1137 | 348 | ||
| 1138 | hdmi_compute_pll(dssdev, phy, &pll_data); | 349 | hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); |
| 1139 | 350 | ||
| 1140 | hdmi_wp_video_start(0); | 351 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); |
| 1141 | 352 | ||
| 1142 | /* config the PLL and PHY first */ | 353 | /* config the PLL and PHY hdmi_set_pll_pwrfirst */ |
| 1143 | r = hdmi_pll_program(&pll_data); | 354 | r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); |
| 1144 | if (r) { | 355 | if (r) { |
| 1145 | DSSDBG("Failed to lock PLL\n"); | 356 | DSSDBG("Failed to lock PLL\n"); |
| 1146 | goto err; | 357 | goto err; |
| 1147 | } | 358 | } |
| 1148 | 359 | ||
| 1149 | r = hdmi_phy_init(); | 360 | r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); |
| 1150 | if (r) { | 361 | if (r) { |
| 1151 | DSSDBG("Failed to start PHY\n"); | 362 | DSSDBG("Failed to start PHY\n"); |
| 1152 | goto err; | 363 | goto err; |
| 1153 | } | 364 | } |
| 1154 | 365 | ||
| 1155 | hdmi.cfg.cm.mode = hdmi.mode; | 366 | hdmi.ip_data.cfg.cm.mode = hdmi.mode; |
| 1156 | hdmi.cfg.cm.code = hdmi.code; | 367 | hdmi.ip_data.cfg.cm.code = hdmi.code; |
| 1157 | hdmi_basic_configure(&hdmi.cfg); | 368 | hdmi.ip_data.ops->video_configure(&hdmi.ip_data); |
| 1158 | 369 | ||
| 1159 | /* Make selection of HDMI in DSS */ | 370 | /* Make selection of HDMI in DSS */ |
| 1160 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | 371 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); |
| @@ -1174,9 +385,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev) | |||
| 1174 | dispc_set_digit_size(dssdev->panel.timings.x_res, | 385 | dispc_set_digit_size(dssdev->panel.timings.x_res, |
| 1175 | dssdev->panel.timings.y_res); | 386 | dssdev->panel.timings.y_res); |
| 1176 | 387 | ||
| 1177 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); | 388 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); |
| 1178 | 389 | ||
| 1179 | hdmi_wp_video_start(1); | 390 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1); |
| 1180 | 391 | ||
| 1181 | return 0; | 392 | return 0; |
| 1182 | err: | 393 | err: |
| @@ -1186,14 +397,12 @@ err: | |||
| 1186 | 397 | ||
| 1187 | static void hdmi_power_off(struct omap_dss_device *dssdev) | 398 | static void hdmi_power_off(struct omap_dss_device *dssdev) |
| 1188 | { | 399 | { |
| 1189 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | 400 | dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); |
| 1190 | 401 | ||
| 1191 | hdmi_wp_video_start(0); | 402 | hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); |
| 1192 | hdmi_phy_off(); | 403 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
| 1193 | hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | 404 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
| 1194 | hdmi_runtime_put(); | 405 | hdmi_runtime_put(); |
| 1195 | |||
| 1196 | hdmi.edid_set = 0; | ||
| 1197 | } | 406 | } |
| 1198 | 407 | ||
| 1199 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 408 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
| @@ -1203,7 +412,6 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | |||
| 1203 | 412 | ||
| 1204 | cm = hdmi_get_code(timings); | 413 | cm = hdmi_get_code(timings); |
| 1205 | if (cm.code == -1) { | 414 | if (cm.code == -1) { |
| 1206 | DSSERR("Invalid timing entered\n"); | ||
| 1207 | return -EINVAL; | 415 | return -EINVAL; |
| 1208 | } | 416 | } |
| 1209 | 417 | ||
| @@ -1215,12 +423,69 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | |||
| 1215 | { | 423 | { |
| 1216 | struct hdmi_cm cm; | 424 | struct hdmi_cm cm; |
| 1217 | 425 | ||
| 1218 | hdmi.custom_set = 1; | ||
| 1219 | cm = hdmi_get_code(&dssdev->panel.timings); | 426 | cm = hdmi_get_code(&dssdev->panel.timings); |
| 1220 | hdmi.code = cm.code; | 427 | hdmi.code = cm.code; |
| 1221 | hdmi.mode = cm.mode; | 428 | hdmi.mode = cm.mode; |
| 1222 | omapdss_hdmi_display_enable(dssdev); | 429 | |
| 1223 | hdmi.custom_set = 0; | 430 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
| 431 | int r; | ||
| 432 | |||
| 433 | hdmi_power_off(dssdev); | ||
| 434 | |||
| 435 | r = hdmi_power_on(dssdev); | ||
| 436 | if (r) | ||
| 437 | DSSERR("failed to power on device\n"); | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 441 | void hdmi_dump_regs(struct seq_file *s) | ||
| 442 | { | ||
| 443 | mutex_lock(&hdmi.lock); | ||
| 444 | |||
| 445 | if (hdmi_runtime_get()) | ||
| 446 | return; | ||
| 447 | |||
| 448 | hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); | ||
| 449 | hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); | ||
| 450 | hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s); | ||
| 451 | hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s); | ||
| 452 | |||
| 453 | hdmi_runtime_put(); | ||
| 454 | mutex_unlock(&hdmi.lock); | ||
| 455 | } | ||
| 456 | |||
| 457 | int omapdss_hdmi_read_edid(u8 *buf, int len) | ||
| 458 | { | ||
| 459 | int r; | ||
| 460 | |||
| 461 | mutex_lock(&hdmi.lock); | ||
| 462 | |||
| 463 | r = hdmi_runtime_get(); | ||
| 464 | BUG_ON(r); | ||
| 465 | |||
| 466 | r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len); | ||
| 467 | |||
| 468 | hdmi_runtime_put(); | ||
| 469 | mutex_unlock(&hdmi.lock); | ||
| 470 | |||
| 471 | return r; | ||
| 472 | } | ||
| 473 | |||
| 474 | bool omapdss_hdmi_detect(void) | ||
| 475 | { | ||
| 476 | int r; | ||
| 477 | |||
| 478 | mutex_lock(&hdmi.lock); | ||
| 479 | |||
| 480 | r = hdmi_runtime_get(); | ||
| 481 | BUG_ON(r); | ||
| 482 | |||
| 483 | r = hdmi.ip_data.ops->detect(&hdmi.ip_data); | ||
| 484 | |||
| 485 | hdmi_runtime_put(); | ||
| 486 | mutex_unlock(&hdmi.lock); | ||
| 487 | |||
| 488 | return r == 1; | ||
| 1224 | } | 489 | } |
| 1225 | 490 | ||
| 1226 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | 491 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) |
| @@ -1231,6 +496,12 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | |||
| 1231 | 496 | ||
| 1232 | mutex_lock(&hdmi.lock); | 497 | mutex_lock(&hdmi.lock); |
| 1233 | 498 | ||
| 499 | if (dssdev->manager == NULL) { | ||
| 500 | DSSERR("failed to enable display: no manager\n"); | ||
| 501 | r = -ENODEV; | ||
| 502 | goto err0; | ||
| 503 | } | ||
| 504 | |||
| 1234 | r = omap_dss_start_device(dssdev); | 505 | r = omap_dss_start_device(dssdev); |
| 1235 | if (r) { | 506 | if (r) { |
| 1236 | DSSERR("failed to start device\n"); | 507 | DSSERR("failed to start device\n"); |
| @@ -1282,219 +553,9 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | |||
| 1282 | 553 | ||
| 1283 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 554 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
| 1284 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | 555 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
| 1285 | static void hdmi_wp_audio_config_format( | ||
| 1286 | struct hdmi_audio_format *aud_fmt) | ||
| 1287 | { | ||
| 1288 | u32 r; | ||
| 1289 | |||
| 1290 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
| 1291 | |||
| 1292 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG); | ||
| 1293 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
| 1294 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
| 1295 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
| 1296 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
| 1297 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
| 1298 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
| 1299 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
| 1300 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
| 1301 | hdmi_write_reg(HDMI_WP_AUDIO_CFG, r); | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma) | ||
| 1305 | { | ||
| 1306 | u32 r; | ||
| 1307 | |||
| 1308 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
| 1309 | |||
| 1310 | r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2); | ||
| 1311 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
| 1312 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
| 1313 | hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r); | ||
| 1314 | |||
| 1315 | r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL); | ||
| 1316 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
| 1317 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
| 1318 | hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r); | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg) | ||
| 1322 | { | ||
| 1323 | u32 r; | ||
| 1324 | |||
| 1325 | /* audio clock recovery parameters */ | ||
| 1326 | r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL); | ||
| 1327 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
| 1328 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
| 1329 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
| 1330 | hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r); | ||
| 1331 | |||
| 1332 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
| 1333 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
| 1334 | REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
| 1335 | |||
| 1336 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
| 1337 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
| 1338 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
| 1339 | REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
| 1340 | } else { | ||
| 1341 | /* | ||
| 1342 | * HDMI IP uses this configuration to divide the MCLK to | ||
| 1343 | * update CTS value. | ||
| 1344 | */ | ||
| 1345 | REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
| 1346 | |||
| 1347 | /* Configure clock for audio packets */ | ||
| 1348 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
| 1349 | cfg->aud_par_busclk, 7, 0); | ||
| 1350 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
| 1351 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
| 1352 | REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
| 1353 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
| 1357 | REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1); | ||
| 1358 | |||
| 1359 | /* I2S parameters */ | ||
| 1360 | REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0); | ||
| 1361 | |||
| 1362 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL); | ||
| 1363 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
| 1364 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
| 1365 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
| 1366 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
| 1367 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
| 1368 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
| 1369 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
| 1370 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
| 1371 | hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
| 1372 | |||
| 1373 | r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5); | ||
| 1374 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
| 1375 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
| 1376 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
| 1377 | hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r); | ||
| 1378 | |||
| 1379 | REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0); | ||
| 1380 | |||
| 1381 | /* Audio channels and mode parameters */ | ||
| 1382 | REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
| 1383 | r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE); | ||
| 1384 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
| 1385 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
| 1386 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
| 1387 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
| 1388 | hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r); | ||
| 1389 | } | ||
| 1390 | |||
| 1391 | static void hdmi_core_audio_infoframe_config( | ||
| 1392 | struct hdmi_core_infoframe_audio *info_aud) | ||
| 1393 | { | ||
| 1394 | u8 val; | ||
| 1395 | u8 sum = 0, checksum = 0; | ||
| 1396 | |||
| 1397 | /* | ||
| 1398 | * Set audio info frame type, version and length as | ||
| 1399 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
| 1400 | * Checksum calculation is defined in Section 5.3.5. | ||
| 1401 | */ | ||
| 1402 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
| 1403 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
| 1404 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
| 1405 | sum += 0x84 + 0x001 + 0x00a; | ||
| 1406 | |||
| 1407 | val = (info_aud->db1_coding_type << 4) | ||
| 1408 | | (info_aud->db1_channel_count - 1); | ||
| 1409 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
| 1410 | sum += val; | ||
| 1411 | |||
| 1412 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
| 1413 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
| 1414 | sum += val; | ||
| 1415 | |||
| 1416 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
| 1417 | |||
| 1418 | val = info_aud->db4_channel_alloc; | ||
| 1419 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
| 1420 | sum += val; | ||
| 1421 | |||
| 1422 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
| 1423 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
| 1424 | sum += val; | ||
| 1425 | |||
| 1426 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
| 1427 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
| 1428 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
| 1429 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
| 1430 | hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
| 1431 | 556 | ||
| 1432 | checksum = 0x100 - sum; | 557 | static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data, |
| 1433 | hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum); | 558 | struct snd_pcm_substream *substream, |
| 1434 | |||
| 1435 | /* | ||
| 1436 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
| 1437 | * is available. | ||
| 1438 | */ | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts) | ||
| 1442 | { | ||
| 1443 | u32 r; | ||
| 1444 | u32 deep_color = 0; | ||
| 1445 | u32 pclk = hdmi.cfg.timings.timings.pixel_clock; | ||
| 1446 | |||
| 1447 | if (n == NULL || cts == NULL) | ||
| 1448 | return -EINVAL; | ||
| 1449 | /* | ||
| 1450 | * Obtain current deep color configuration. This needed | ||
| 1451 | * to calculate the TMDS clock based on the pixel clock. | ||
| 1452 | */ | ||
| 1453 | r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0); | ||
| 1454 | switch (r) { | ||
| 1455 | case 1: /* No deep color selected */ | ||
| 1456 | deep_color = 100; | ||
| 1457 | break; | ||
| 1458 | case 2: /* 10-bit deep color selected */ | ||
| 1459 | deep_color = 125; | ||
| 1460 | break; | ||
| 1461 | case 3: /* 12-bit deep color selected */ | ||
| 1462 | deep_color = 150; | ||
| 1463 | break; | ||
| 1464 | default: | ||
| 1465 | return -EINVAL; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | switch (sample_freq) { | ||
| 1469 | case 32000: | ||
| 1470 | if ((deep_color == 125) && ((pclk == 54054) | ||
| 1471 | || (pclk == 74250))) | ||
| 1472 | *n = 8192; | ||
| 1473 | else | ||
| 1474 | *n = 4096; | ||
| 1475 | break; | ||
| 1476 | case 44100: | ||
| 1477 | *n = 6272; | ||
| 1478 | break; | ||
| 1479 | case 48000: | ||
| 1480 | if ((deep_color == 125) && ((pclk == 54054) | ||
| 1481 | || (pclk == 74250))) | ||
| 1482 | *n = 8192; | ||
| 1483 | else | ||
| 1484 | *n = 6144; | ||
| 1485 | break; | ||
| 1486 | default: | ||
| 1487 | *n = 0; | ||
| 1488 | return -EINVAL; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
| 1492 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
| 1493 | |||
| 1494 | return 0; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | ||
| 1498 | struct snd_pcm_hw_params *params, | 559 | struct snd_pcm_hw_params *params, |
| 1499 | struct snd_soc_dai *dai) | 560 | struct snd_soc_dai *dai) |
| 1500 | { | 561 | { |
| @@ -1548,7 +609,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
| 1548 | return -EINVAL; | 609 | return -EINVAL; |
| 1549 | } | 610 | } |
| 1550 | 611 | ||
| 1551 | err = hdmi_config_audio_acr(params_rate(params), &n, &cts); | 612 | err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts); |
| 1552 | if (err < 0) | 613 | if (err < 0) |
| 1553 | return err; | 614 | return err; |
| 1554 | 615 | ||
| @@ -1564,8 +625,8 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
| 1564 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; | 625 | audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; |
| 1565 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ | 626 | audio_dma.fifo_threshold = 0x20; /* in number of samples */ |
| 1566 | 627 | ||
| 1567 | hdmi_wp_audio_config_dma(&audio_dma); | 628 | hdmi_wp_audio_config_dma(ip_data, &audio_dma); |
| 1568 | hdmi_wp_audio_config_format(&audio_format); | 629 | hdmi_wp_audio_config_format(ip_data, &audio_format); |
| 1569 | 630 | ||
| 1570 | /* | 631 | /* |
| 1571 | * I2S config | 632 | * I2S config |
| @@ -1609,7 +670,7 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
| 1609 | /* Use parallel audio interface */ | 670 | /* Use parallel audio interface */ |
| 1610 | core_cfg.en_parallel_aud_input = true; | 671 | core_cfg.en_parallel_aud_input = true; |
| 1611 | 672 | ||
| 1612 | hdmi_core_audio_config(&core_cfg); | 673 | hdmi_core_audio_config(ip_data, &core_cfg); |
| 1613 | 674 | ||
| 1614 | /* | 675 | /* |
| 1615 | * Configure packet | 676 | * Configure packet |
| @@ -1623,36 +684,10 @@ static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, | |||
| 1623 | aud_if_cfg.db5_downmix_inh = false; | 684 | aud_if_cfg.db5_downmix_inh = false; |
| 1624 | aud_if_cfg.db5_lsv = 0; | 685 | aud_if_cfg.db5_lsv = 0; |
| 1625 | 686 | ||
| 1626 | hdmi_core_audio_infoframe_config(&aud_if_cfg); | 687 | hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg); |
| 1627 | return 0; | 688 | return 0; |
| 1628 | } | 689 | } |
| 1629 | 690 | ||
| 1630 | static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, | ||
| 1631 | struct snd_soc_dai *dai) | ||
| 1632 | { | ||
| 1633 | int err = 0; | ||
| 1634 | switch (cmd) { | ||
| 1635 | case SNDRV_PCM_TRIGGER_START: | ||
| 1636 | case SNDRV_PCM_TRIGGER_RESUME: | ||
| 1637 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
| 1638 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
| 1639 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
| 1640 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
| 1641 | break; | ||
| 1642 | |||
| 1643 | case SNDRV_PCM_TRIGGER_STOP: | ||
| 1644 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
| 1645 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
| 1646 | REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
| 1647 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
| 1648 | REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
| 1649 | break; | ||
| 1650 | default: | ||
| 1651 | err = -EINVAL; | ||
| 1652 | } | ||
| 1653 | return err; | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, | 691 | static int hdmi_audio_startup(struct snd_pcm_substream *substream, |
| 1657 | struct snd_soc_dai *dai) | 692 | struct snd_soc_dai *dai) |
| 1658 | { | 693 | { |
| @@ -1698,15 +733,6 @@ static int hdmi_get_clocks(struct platform_device *pdev) | |||
| 1698 | 733 | ||
| 1699 | hdmi.sys_clk = clk; | 734 | hdmi.sys_clk = clk; |
| 1700 | 735 | ||
| 1701 | clk = clk_get(&pdev->dev, "dss_48mhz_clk"); | ||
| 1702 | if (IS_ERR(clk)) { | ||
| 1703 | DSSERR("can't get hdmi_clk\n"); | ||
| 1704 | clk_put(hdmi.sys_clk); | ||
| 1705 | return PTR_ERR(clk); | ||
| 1706 | } | ||
| 1707 | |||
| 1708 | hdmi.hdmi_clk = clk; | ||
| 1709 | |||
| 1710 | return 0; | 736 | return 0; |
| 1711 | } | 737 | } |
| 1712 | 738 | ||
| @@ -1714,8 +740,6 @@ static void hdmi_put_clocks(void) | |||
| 1714 | { | 740 | { |
| 1715 | if (hdmi.sys_clk) | 741 | if (hdmi.sys_clk) |
| 1716 | clk_put(hdmi.sys_clk); | 742 | clk_put(hdmi.sys_clk); |
| 1717 | if (hdmi.hdmi_clk) | ||
| 1718 | clk_put(hdmi.hdmi_clk); | ||
| 1719 | } | 743 | } |
| 1720 | 744 | ||
| 1721 | /* HDMI HW IP initialisation */ | 745 | /* HDMI HW IP initialisation */ |
| @@ -1736,20 +760,26 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev) | |||
| 1736 | } | 760 | } |
| 1737 | 761 | ||
| 1738 | /* Base address taken from platform */ | 762 | /* Base address taken from platform */ |
| 1739 | hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); | 763 | hdmi.ip_data.base_wp = ioremap(hdmi_mem->start, |
| 1740 | if (!hdmi.base_wp) { | 764 | resource_size(hdmi_mem)); |
| 765 | if (!hdmi.ip_data.base_wp) { | ||
| 1741 | DSSERR("can't ioremap WP\n"); | 766 | DSSERR("can't ioremap WP\n"); |
| 1742 | return -ENOMEM; | 767 | return -ENOMEM; |
| 1743 | } | 768 | } |
| 1744 | 769 | ||
| 1745 | r = hdmi_get_clocks(pdev); | 770 | r = hdmi_get_clocks(pdev); |
| 1746 | if (r) { | 771 | if (r) { |
| 1747 | iounmap(hdmi.base_wp); | 772 | iounmap(hdmi.ip_data.base_wp); |
| 1748 | return r; | 773 | return r; |
| 1749 | } | 774 | } |
| 1750 | 775 | ||
| 1751 | pm_runtime_enable(&pdev->dev); | 776 | pm_runtime_enable(&pdev->dev); |
| 1752 | 777 | ||
| 778 | hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; | ||
| 779 | hdmi.ip_data.core_av_offset = HDMI_CORE_AV; | ||
| 780 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; | ||
| 781 | hdmi.ip_data.phy_offset = HDMI_PHY; | ||
| 782 | |||
| 1753 | hdmi_panel_init(); | 783 | hdmi_panel_init(); |
| 1754 | 784 | ||
| 1755 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | 785 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
| @@ -1779,14 +809,13 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev) | |||
| 1779 | 809 | ||
| 1780 | hdmi_put_clocks(); | 810 | hdmi_put_clocks(); |
| 1781 | 811 | ||
| 1782 | iounmap(hdmi.base_wp); | 812 | iounmap(hdmi.ip_data.base_wp); |
| 1783 | 813 | ||
| 1784 | return 0; | 814 | return 0; |
| 1785 | } | 815 | } |
| 1786 | 816 | ||
| 1787 | static int hdmi_runtime_suspend(struct device *dev) | 817 | static int hdmi_runtime_suspend(struct device *dev) |
| 1788 | { | 818 | { |
| 1789 | clk_disable(hdmi.hdmi_clk); | ||
| 1790 | clk_disable(hdmi.sys_clk); | 819 | clk_disable(hdmi.sys_clk); |
| 1791 | 820 | ||
| 1792 | dispc_runtime_put(); | 821 | dispc_runtime_put(); |
| @@ -1809,7 +838,6 @@ static int hdmi_runtime_resume(struct device *dev) | |||
| 1809 | 838 | ||
| 1810 | 839 | ||
| 1811 | clk_enable(hdmi.sys_clk); | 840 | clk_enable(hdmi.sys_clk); |
| 1812 | clk_enable(hdmi.hdmi_clk); | ||
| 1813 | 841 | ||
| 1814 | return 0; | 842 | return 0; |
| 1815 | 843 | ||
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_panel.c index 7d4f2bd7c506..533d5dc634d2 100644 --- a/drivers/video/omap2/dss/hdmi_omap4_panel.c +++ b/drivers/video/omap2/dss/hdmi_panel.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * hdmi_omap4_panel.c | 2 | * hdmi_panel.c |
| 3 | * | 3 | * |
| 4 | * HDMI library support functions for TI OMAP4 processors. | 4 | * HDMI library support functions for TI OMAP4 processors. |
| 5 | * | 5 | * |
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <video/omapdss.h> | 27 | #include <video/omapdss.h> |
| 28 | #include <linux/slab.h> | ||
| 28 | 29 | ||
| 29 | #include "dss.h" | 30 | #include "dss.h" |
| 30 | 31 | ||
| @@ -40,13 +41,7 @@ static int hdmi_panel_probe(struct omap_dss_device *dssdev) | |||
| 40 | dssdev->panel.config = OMAP_DSS_LCD_TFT | | 41 | dssdev->panel.config = OMAP_DSS_LCD_TFT | |
| 41 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; | 42 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; |
| 42 | 43 | ||
| 43 | /* | 44 | dssdev->panel.timings = (struct omap_video_timings){640, 480, 25175, 96, 16, 48, 2 , 11, 31}; |
| 44 | * Initialize the timings to 640 * 480 | ||
| 45 | * This is only for framebuffer update not for TV timing setting | ||
| 46 | * Setting TV timing will be done only on enable | ||
| 47 | */ | ||
| 48 | dssdev->panel.timings.x_res = 640; | ||
| 49 | dssdev->panel.timings.y_res = 480; | ||
| 50 | 45 | ||
| 51 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", | 46 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", |
| 52 | dssdev->panel.timings.x_res, | 47 | dssdev->panel.timings.x_res, |
| @@ -161,12 +156,7 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev, | |||
| 161 | mutex_lock(&hdmi.hdmi_lock); | 156 | mutex_lock(&hdmi.hdmi_lock); |
| 162 | 157 | ||
| 163 | dssdev->panel.timings = *timings; | 158 | dssdev->panel.timings = *timings; |
| 164 | 159 | omapdss_hdmi_display_set_timing(dssdev); | |
| 165 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
| 166 | /* turn the hdmi off and on to get new timings to use */ | ||
| 167 | omapdss_hdmi_display_disable(dssdev); | ||
| 168 | omapdss_hdmi_display_set_timing(dssdev); | ||
| 169 | } | ||
| 170 | 160 | ||
| 171 | mutex_unlock(&hdmi.hdmi_lock); | 161 | mutex_unlock(&hdmi.hdmi_lock); |
| 172 | } | 162 | } |
| @@ -181,12 +171,54 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev, | |||
| 181 | mutex_lock(&hdmi.hdmi_lock); | 171 | mutex_lock(&hdmi.hdmi_lock); |
| 182 | 172 | ||
| 183 | r = omapdss_hdmi_display_check_timing(dssdev, timings); | 173 | r = omapdss_hdmi_display_check_timing(dssdev, timings); |
| 184 | if (r) { | 174 | |
| 185 | DSSERR("Timing cannot be applied\n"); | 175 | mutex_unlock(&hdmi.hdmi_lock); |
| 186 | goto err; | 176 | return r; |
| 177 | } | ||
| 178 | |||
| 179 | static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len) | ||
| 180 | { | ||
| 181 | int r; | ||
| 182 | |||
| 183 | mutex_lock(&hdmi.hdmi_lock); | ||
| 184 | |||
| 185 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
| 186 | r = omapdss_hdmi_display_enable(dssdev); | ||
| 187 | if (r) | ||
| 188 | goto err; | ||
| 189 | } | ||
| 190 | |||
| 191 | r = omapdss_hdmi_read_edid(buf, len); | ||
| 192 | |||
| 193 | if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || | ||
| 194 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) | ||
| 195 | omapdss_hdmi_display_disable(dssdev); | ||
| 196 | err: | ||
| 197 | mutex_unlock(&hdmi.hdmi_lock); | ||
| 198 | |||
| 199 | return r; | ||
| 200 | } | ||
| 201 | |||
| 202 | static bool hdmi_detect(struct omap_dss_device *dssdev) | ||
| 203 | { | ||
| 204 | int r; | ||
| 205 | |||
| 206 | mutex_lock(&hdmi.hdmi_lock); | ||
| 207 | |||
| 208 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
| 209 | r = omapdss_hdmi_display_enable(dssdev); | ||
| 210 | if (r) | ||
| 211 | goto err; | ||
| 187 | } | 212 | } |
| 213 | |||
| 214 | r = omapdss_hdmi_detect(); | ||
| 215 | |||
| 216 | if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED || | ||
| 217 | dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) | ||
| 218 | omapdss_hdmi_display_disable(dssdev); | ||
| 188 | err: | 219 | err: |
| 189 | mutex_unlock(&hdmi.hdmi_lock); | 220 | mutex_unlock(&hdmi.hdmi_lock); |
| 221 | |||
| 190 | return r; | 222 | return r; |
| 191 | } | 223 | } |
| 192 | 224 | ||
| @@ -200,6 +232,8 @@ static struct omap_dss_driver hdmi_driver = { | |||
| 200 | .get_timings = hdmi_get_timings, | 232 | .get_timings = hdmi_get_timings, |
| 201 | .set_timings = hdmi_set_timings, | 233 | .set_timings = hdmi_set_timings, |
| 202 | .check_timings = hdmi_check_timings, | 234 | .check_timings = hdmi_check_timings, |
| 235 | .read_edid = hdmi_read_edid, | ||
| 236 | .detect = hdmi_detect, | ||
| 203 | .driver = { | 237 | .driver = { |
| 204 | .name = "hdmi_panel", | 238 | .name = "hdmi_panel", |
| 205 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 13d72d5c714b..6e63845cc7d7 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
| @@ -106,7 +106,7 @@ put_device: | |||
| 106 | static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, | 106 | static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, |
| 107 | char *buf) | 107 | char *buf) |
| 108 | { | 108 | { |
| 109 | return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color); | 109 | return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, | 112 | static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, |
| @@ -116,8 +116,9 @@ static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, | |||
| 116 | u32 color; | 116 | u32 color; |
| 117 | int r; | 117 | int r; |
| 118 | 118 | ||
| 119 | if (sscanf(buf, "%d", &color) != 1) | 119 | r = kstrtouint(buf, 0, &color); |
| 120 | return -EINVAL; | 120 | if (r) |
| 121 | return r; | ||
| 121 | 122 | ||
| 122 | mgr->get_manager_info(mgr, &info); | 123 | mgr->get_manager_info(mgr, &info); |
| 123 | 124 | ||
| @@ -184,7 +185,7 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr, | |||
| 184 | static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, | 185 | static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, |
| 185 | char *buf) | 186 | char *buf) |
| 186 | { | 187 | { |
| 187 | return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key); | 188 | return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key); |
| 188 | } | 189 | } |
| 189 | 190 | ||
| 190 | static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, | 191 | static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, |
| @@ -194,8 +195,9 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, | |||
| 194 | u32 key_value; | 195 | u32 key_value; |
| 195 | int r; | 196 | int r; |
| 196 | 197 | ||
| 197 | if (sscanf(buf, "%d", &key_value) != 1) | 198 | r = kstrtouint(buf, 0, &key_value); |
| 198 | return -EINVAL; | 199 | if (r) |
| 200 | return r; | ||
| 199 | 201 | ||
| 200 | mgr->get_manager_info(mgr, &info); | 202 | mgr->get_manager_info(mgr, &info); |
| 201 | 203 | ||
| @@ -222,15 +224,16 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, | |||
| 222 | const char *buf, size_t size) | 224 | const char *buf, size_t size) |
| 223 | { | 225 | { |
| 224 | struct omap_overlay_manager_info info; | 226 | struct omap_overlay_manager_info info; |
| 225 | int enable; | 227 | bool enable; |
| 226 | int r; | 228 | int r; |
| 227 | 229 | ||
| 228 | if (sscanf(buf, "%d", &enable) != 1) | 230 | r = strtobool(buf, &enable); |
| 229 | return -EINVAL; | 231 | if (r) |
| 232 | return r; | ||
| 230 | 233 | ||
| 231 | mgr->get_manager_info(mgr, &info); | 234 | mgr->get_manager_info(mgr, &info); |
| 232 | 235 | ||
| 233 | info.trans_enabled = enable ? true : false; | 236 | info.trans_enabled = enable; |
| 234 | 237 | ||
| 235 | r = mgr->set_manager_info(mgr, &info); | 238 | r = mgr->set_manager_info(mgr, &info); |
| 236 | if (r) | 239 | if (r) |
| @@ -246,7 +249,10 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, | |||
| 246 | static ssize_t manager_alpha_blending_enabled_show( | 249 | static ssize_t manager_alpha_blending_enabled_show( |
| 247 | struct omap_overlay_manager *mgr, char *buf) | 250 | struct omap_overlay_manager *mgr, char *buf) |
| 248 | { | 251 | { |
| 249 | return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled); | 252 | WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); |
| 253 | |||
| 254 | return snprintf(buf, PAGE_SIZE, "%d\n", | ||
| 255 | mgr->info.partial_alpha_enabled); | ||
| 250 | } | 256 | } |
| 251 | 257 | ||
| 252 | static ssize_t manager_alpha_blending_enabled_store( | 258 | static ssize_t manager_alpha_blending_enabled_store( |
| @@ -254,15 +260,18 @@ static ssize_t manager_alpha_blending_enabled_store( | |||
| 254 | const char *buf, size_t size) | 260 | const char *buf, size_t size) |
| 255 | { | 261 | { |
| 256 | struct omap_overlay_manager_info info; | 262 | struct omap_overlay_manager_info info; |
| 257 | int enable; | 263 | bool enable; |
| 258 | int r; | 264 | int r; |
| 259 | 265 | ||
| 260 | if (sscanf(buf, "%d", &enable) != 1) | 266 | WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); |
| 261 | return -EINVAL; | 267 | |
| 268 | r = strtobool(buf, &enable); | ||
| 269 | if (r) | ||
| 270 | return r; | ||
| 262 | 271 | ||
| 263 | mgr->get_manager_info(mgr, &info); | 272 | mgr->get_manager_info(mgr, &info); |
| 264 | 273 | ||
| 265 | info.alpha_enabled = enable ? true : false; | 274 | info.partial_alpha_enabled = enable; |
| 266 | 275 | ||
| 267 | r = mgr->set_manager_info(mgr, &info); | 276 | r = mgr->set_manager_info(mgr, &info); |
| 268 | if (r) | 277 | if (r) |
| @@ -285,19 +294,16 @@ static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, | |||
| 285 | const char *buf, size_t size) | 294 | const char *buf, size_t size) |
| 286 | { | 295 | { |
| 287 | struct omap_overlay_manager_info info; | 296 | struct omap_overlay_manager_info info; |
| 288 | int v; | ||
| 289 | int r; | 297 | int r; |
| 290 | bool enable; | 298 | bool enable; |
| 291 | 299 | ||
| 292 | if (!dss_has_feature(FEAT_CPR)) | 300 | if (!dss_has_feature(FEAT_CPR)) |
| 293 | return -ENODEV; | 301 | return -ENODEV; |
| 294 | 302 | ||
| 295 | r = kstrtoint(buf, 0, &v); | 303 | r = strtobool(buf, &enable); |
| 296 | if (r) | 304 | if (r) |
| 297 | return r; | 305 | return r; |
| 298 | 306 | ||
| 299 | enable = !!v; | ||
| 300 | |||
| 301 | mgr->get_manager_info(mgr, &info); | 307 | mgr->get_manager_info(mgr, &info); |
| 302 | 308 | ||
| 303 | if (info.cpr_enable == enable) | 309 | if (info.cpr_enable == enable) |
| @@ -586,6 +592,13 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr) | |||
| 586 | return -EINVAL; | 592 | return -EINVAL; |
| 587 | } | 593 | } |
| 588 | 594 | ||
| 595 | /* | ||
| 596 | * Don't allow currently enabled displays to have the overlay manager | ||
| 597 | * pulled out from underneath them | ||
| 598 | */ | ||
| 599 | if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) | ||
| 600 | return -EINVAL; | ||
| 601 | |||
| 589 | mgr->device->manager = NULL; | 602 | mgr->device->manager = NULL; |
| 590 | mgr->device = NULL; | 603 | mgr->device = NULL; |
| 591 | mgr->device_changed = true; | 604 | mgr->device_changed = true; |
| @@ -801,7 +814,7 @@ static int configure_overlay(enum omap_plane plane) | |||
| 801 | { | 814 | { |
| 802 | struct overlay_cache_data *c; | 815 | struct overlay_cache_data *c; |
| 803 | struct manager_cache_data *mc; | 816 | struct manager_cache_data *mc; |
| 804 | struct omap_overlay_info *oi; | 817 | struct omap_overlay_info *oi, new_oi; |
| 805 | struct omap_overlay_manager_info *mi; | 818 | struct omap_overlay_manager_info *mi; |
| 806 | u16 outw, outh; | 819 | u16 outw, outh; |
| 807 | u16 x, y, w, h; | 820 | u16 x, y, w, h; |
| @@ -815,7 +828,7 @@ static int configure_overlay(enum omap_plane plane) | |||
| 815 | oi = &c->info; | 828 | oi = &c->info; |
| 816 | 829 | ||
| 817 | if (!c->enabled) { | 830 | if (!c->enabled) { |
| 818 | dispc_enable_plane(plane, 0); | 831 | dispc_ovl_enable(plane, 0); |
| 819 | return 0; | 832 | return 0; |
| 820 | } | 833 | } |
| 821 | 834 | ||
| @@ -843,7 +856,7 @@ static int configure_overlay(enum omap_plane plane) | |||
| 843 | /* If the overlay is outside the update region, disable it */ | 856 | /* If the overlay is outside the update region, disable it */ |
| 844 | if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, | 857 | if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, |
| 845 | x, y, outw, outh)) { | 858 | x, y, outw, outh)) { |
| 846 | dispc_enable_plane(plane, 0); | 859 | dispc_ovl_enable(plane, 0); |
| 847 | return 0; | 860 | return 0; |
| 848 | } | 861 | } |
| 849 | 862 | ||
| @@ -921,34 +934,27 @@ static int configure_overlay(enum omap_plane plane) | |||
| 921 | } | 934 | } |
| 922 | } | 935 | } |
| 923 | 936 | ||
| 924 | r = dispc_setup_plane(plane, | 937 | new_oi = *oi; |
| 925 | paddr, | 938 | |
| 926 | oi->screen_width, | 939 | /* update new_oi members which could have been possibly updated */ |
| 927 | x, y, | 940 | new_oi.pos_x = x; |
| 928 | w, h, | 941 | new_oi.pos_y = y; |
| 929 | outw, outh, | 942 | new_oi.width = w; |
| 930 | oi->color_mode, | 943 | new_oi.height = h; |
| 931 | c->ilace, | 944 | new_oi.out_width = outw; |
| 932 | oi->rotation_type, | 945 | new_oi.out_height = outh; |
| 933 | oi->rotation, | 946 | new_oi.paddr = paddr; |
| 934 | oi->mirror, | ||
| 935 | oi->global_alpha, | ||
| 936 | oi->pre_mult_alpha, | ||
| 937 | c->channel, | ||
| 938 | oi->p_uv_addr); | ||
| 939 | 947 | ||
| 948 | r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel, | ||
| 949 | c->replication, c->fifo_low, c->fifo_high); | ||
| 940 | if (r) { | 950 | if (r) { |
| 941 | /* this shouldn't happen */ | 951 | /* this shouldn't happen */ |
| 942 | DSSERR("dispc_setup_plane failed for ovl %d\n", plane); | 952 | DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); |
| 943 | dispc_enable_plane(plane, 0); | 953 | dispc_ovl_enable(plane, 0); |
| 944 | return r; | 954 | return r; |
| 945 | } | 955 | } |
| 946 | 956 | ||
| 947 | dispc_enable_replication(plane, c->replication); | 957 | dispc_ovl_enable(plane, 1); |
| 948 | |||
| 949 | dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high); | ||
| 950 | |||
| 951 | dispc_enable_plane(plane, 1); | ||
| 952 | 958 | ||
| 953 | return 0; | 959 | return 0; |
| 954 | } | 960 | } |
| @@ -962,13 +968,13 @@ static void configure_manager(enum omap_channel channel) | |||
| 962 | /* picking info from the cache */ | 968 | /* picking info from the cache */ |
| 963 | mi = &dss_cache.manager_cache[channel].info; | 969 | mi = &dss_cache.manager_cache[channel].info; |
| 964 | 970 | ||
| 965 | dispc_set_default_color(channel, mi->default_color); | 971 | dispc_mgr_set_default_color(channel, mi->default_color); |
| 966 | dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key); | 972 | dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key); |
| 967 | dispc_enable_trans_key(channel, mi->trans_enabled); | 973 | dispc_mgr_enable_trans_key(channel, mi->trans_enabled); |
| 968 | dispc_enable_alpha_blending(channel, mi->alpha_enabled); | 974 | dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled); |
| 969 | if (dss_has_feature(FEAT_CPR)) { | 975 | if (dss_has_feature(FEAT_CPR)) { |
| 970 | dispc_enable_cpr(channel, mi->cpr_enable); | 976 | dispc_mgr_enable_cpr(channel, mi->cpr_enable); |
| 971 | dispc_set_cpr_coef(channel, &mi->cpr_coefs); | 977 | dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs); |
| 972 | } | 978 | } |
| 973 | } | 979 | } |
| 974 | 980 | ||
| @@ -992,7 +998,7 @@ static int configure_dispc(void) | |||
| 992 | busy = false; | 998 | busy = false; |
| 993 | 999 | ||
| 994 | for (i = 0; i < num_mgrs; i++) { | 1000 | for (i = 0; i < num_mgrs; i++) { |
| 995 | mgr_busy[i] = dispc_go_busy(i); | 1001 | mgr_busy[i] = dispc_mgr_go_busy(i); |
| 996 | mgr_go[i] = false; | 1002 | mgr_go[i] = false; |
| 997 | } | 1003 | } |
| 998 | 1004 | ||
| @@ -1053,7 +1059,7 @@ static int configure_dispc(void) | |||
| 1053 | * always be turned off after frame, and new settings will be | 1059 | * always be turned off after frame, and new settings will be |
| 1054 | * taken in to use at next update */ | 1060 | * taken in to use at next update */ |
| 1055 | if (!mc->manual_update) | 1061 | if (!mc->manual_update) |
| 1056 | dispc_go(i); | 1062 | dispc_mgr_go(i); |
| 1057 | } | 1063 | } |
| 1058 | 1064 | ||
| 1059 | if (busy) | 1065 | if (busy) |
| @@ -1258,7 +1264,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
| 1258 | u32 irq_mask; | 1264 | u32 irq_mask; |
| 1259 | 1265 | ||
| 1260 | for (i = 0; i < num_mgrs; i++) | 1266 | for (i = 0; i < num_mgrs; i++) |
| 1261 | mgr_busy[i] = dispc_go_busy(i); | 1267 | mgr_busy[i] = dispc_mgr_go_busy(i); |
| 1262 | 1268 | ||
| 1263 | spin_lock(&dss_cache.lock); | 1269 | spin_lock(&dss_cache.lock); |
| 1264 | 1270 | ||
| @@ -1280,7 +1286,7 @@ static void dss_apply_irq_handler(void *data, u32 mask) | |||
| 1280 | 1286 | ||
| 1281 | /* re-read busy flags */ | 1287 | /* re-read busy flags */ |
| 1282 | for (i = 0; i < num_mgrs; i++) | 1288 | for (i = 0; i < num_mgrs; i++) |
| 1283 | mgr_busy[i] = dispc_go_busy(i); | 1289 | mgr_busy[i] = dispc_mgr_go_busy(i); |
| 1284 | 1290 | ||
| 1285 | /* keep running as long as there are busy managers, so that | 1291 | /* keep running as long as there are busy managers, so that |
| 1286 | * we can collect overlay-applied information */ | 1292 | * we can collect overlay-applied information */ |
| @@ -1326,11 +1332,13 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
| 1326 | 1332 | ||
| 1327 | ovl = omap_dss_get_overlay(i); | 1333 | ovl = omap_dss_get_overlay(i); |
| 1328 | 1334 | ||
| 1329 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 1330 | continue; | ||
| 1331 | |||
| 1332 | oc = &dss_cache.overlay_cache[ovl->id]; | 1335 | oc = &dss_cache.overlay_cache[ovl->id]; |
| 1333 | 1336 | ||
| 1337 | if (ovl->manager_changed) { | ||
| 1338 | ovl->manager_changed = false; | ||
| 1339 | ovl->info_dirty = true; | ||
| 1340 | } | ||
| 1341 | |||
| 1334 | if (!overlay_enabled(ovl)) { | 1342 | if (!overlay_enabled(ovl)) { |
| 1335 | if (oc->enabled) { | 1343 | if (oc->enabled) { |
| 1336 | oc->enabled = false; | 1344 | oc->enabled = false; |
| @@ -1375,9 +1383,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
| 1375 | list_for_each_entry(mgr, &manager_list, list) { | 1383 | list_for_each_entry(mgr, &manager_list, list) { |
| 1376 | struct omap_dss_device *dssdev; | 1384 | struct omap_dss_device *dssdev; |
| 1377 | 1385 | ||
| 1378 | if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC)) | ||
| 1379 | continue; | ||
| 1380 | |||
| 1381 | mc = &dss_cache.manager_cache[mgr->id]; | 1386 | mc = &dss_cache.manager_cache[mgr->id]; |
| 1382 | 1387 | ||
| 1383 | if (mgr->device_changed) { | 1388 | if (mgr->device_changed) { |
| @@ -1423,9 +1428,6 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
| 1423 | 1428 | ||
| 1424 | ovl = omap_dss_get_overlay(i); | 1429 | ovl = omap_dss_get_overlay(i); |
| 1425 | 1430 | ||
| 1426 | if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) | ||
| 1427 | continue; | ||
| 1428 | |||
| 1429 | oc = &dss_cache.overlay_cache[ovl->id]; | 1431 | oc = &dss_cache.overlay_cache[ovl->id]; |
| 1430 | 1432 | ||
| 1431 | if (!oc->enabled) | 1433 | if (!oc->enabled) |
| @@ -1433,11 +1435,11 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
| 1433 | 1435 | ||
| 1434 | dssdev = ovl->manager->device; | 1436 | dssdev = ovl->manager->device; |
| 1435 | 1437 | ||
| 1436 | size = dispc_get_plane_fifo_size(ovl->id); | 1438 | size = dispc_ovl_get_fifo_size(ovl->id); |
| 1437 | if (use_fifomerge) | 1439 | if (use_fifomerge) |
| 1438 | size *= 3; | 1440 | size *= 3; |
| 1439 | 1441 | ||
| 1440 | burst_size = dispc_get_burst_size(ovl->id); | 1442 | burst_size = dispc_ovl_get_burst_size(ovl->id); |
| 1441 | 1443 | ||
| 1442 | switch (dssdev->type) { | 1444 | switch (dssdev->type) { |
| 1443 | case OMAP_DISPLAY_TYPE_DPI: | 1445 | case OMAP_DISPLAY_TYPE_DPI: |
| @@ -1484,12 +1486,17 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
| 1484 | 1486 | ||
| 1485 | static int dss_check_manager(struct omap_overlay_manager *mgr) | 1487 | static int dss_check_manager(struct omap_overlay_manager *mgr) |
| 1486 | { | 1488 | { |
| 1487 | /* OMAP supports only graphics source transparency color key and alpha | 1489 | if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { |
| 1488 | * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */ | 1490 | /* |
| 1489 | 1491 | * OMAP3 supports only graphics source transparency color key | |
| 1490 | if (mgr->info.alpha_enabled && mgr->info.trans_enabled && | 1492 | * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 |
| 1491 | mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) | 1493 | * Alpha Mode |
| 1492 | return -EINVAL; | 1494 | */ |
| 1495 | if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled | ||
| 1496 | && mgr->info.trans_key_type != | ||
| 1497 | OMAP_DSS_COLOR_KEY_GFX_DST) | ||
| 1498 | return -EINVAL; | ||
| 1499 | } | ||
| 1493 | 1500 | ||
| 1494 | return 0; | 1501 | return 0; |
| 1495 | } | 1502 | } |
| @@ -1522,13 +1529,13 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr, | |||
| 1522 | 1529 | ||
| 1523 | static int dss_mgr_enable(struct omap_overlay_manager *mgr) | 1530 | static int dss_mgr_enable(struct omap_overlay_manager *mgr) |
| 1524 | { | 1531 | { |
| 1525 | dispc_enable_channel(mgr->id, 1); | 1532 | dispc_mgr_enable(mgr->id, 1); |
| 1526 | return 0; | 1533 | return 0; |
| 1527 | } | 1534 | } |
| 1528 | 1535 | ||
| 1529 | static int dss_mgr_disable(struct omap_overlay_manager *mgr) | 1536 | static int dss_mgr_disable(struct omap_overlay_manager *mgr) |
| 1530 | { | 1537 | { |
| 1531 | dispc_enable_channel(mgr->id, 0); | 1538 | dispc_mgr_enable(mgr->id, 0); |
| 1532 | return 0; | 1539 | return 0; |
| 1533 | } | 1540 | } |
| 1534 | 1541 | ||
| @@ -1580,7 +1587,7 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
| 1580 | mgr->enable = &dss_mgr_enable; | 1587 | mgr->enable = &dss_mgr_enable; |
| 1581 | mgr->disable = &dss_mgr_disable; | 1588 | mgr->disable = &dss_mgr_disable; |
| 1582 | 1589 | ||
| 1583 | mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC; | 1590 | mgr->caps = 0; |
| 1584 | mgr->supported_displays = | 1591 | mgr->supported_displays = |
| 1585 | dss_feat_get_supported_displays(mgr->id); | 1592 | dss_feat_get_supported_displays(mgr->id); |
| 1586 | 1593 | ||
| @@ -1597,42 +1604,6 @@ int dss_init_overlay_managers(struct platform_device *pdev) | |||
| 1597 | } | 1604 | } |
| 1598 | } | 1605 | } |
| 1599 | 1606 | ||
| 1600 | #ifdef L4_EXAMPLE | ||
| 1601 | { | ||
| 1602 | int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr) | ||
| 1603 | { | ||
| 1604 | DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name); | ||
| 1605 | |||
| 1606 | return 0; | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | struct omap_overlay_manager *mgr; | ||
| 1610 | mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); | ||
| 1611 | |||
| 1612 | BUG_ON(mgr == NULL); | ||
| 1613 | |||
| 1614 | mgr->name = "l4"; | ||
| 1615 | mgr->supported_displays = | ||
| 1616 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI; | ||
| 1617 | |||
| 1618 | mgr->set_device = &omap_dss_set_device; | ||
| 1619 | mgr->unset_device = &omap_dss_unset_device; | ||
| 1620 | mgr->apply = &omap_dss_mgr_apply_l4; | ||
| 1621 | mgr->set_manager_info = &omap_dss_mgr_set_info; | ||
| 1622 | mgr->get_manager_info = &omap_dss_mgr_get_info; | ||
| 1623 | |||
| 1624 | dss_overlay_setup_l4_manager(mgr); | ||
| 1625 | |||
| 1626 | omap_dss_add_overlay_manager(mgr); | ||
| 1627 | |||
| 1628 | r = kobject_init_and_add(&mgr->kobj, &manager_ktype, | ||
| 1629 | &pdev->dev.kobj, "managerl4"); | ||
| 1630 | |||
| 1631 | if (r) | ||
| 1632 | DSSERR("failed to create sysfs file\n"); | ||
| 1633 | } | ||
| 1634 | #endif | ||
| 1635 | |||
| 1636 | return 0; | 1607 | return 0; |
| 1637 | } | 1608 | } |
| 1638 | 1609 | ||
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index c84380c53c39..ab8e40e48759 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
| @@ -211,16 +211,17 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) | |||
| 211 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, | 211 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, |
| 212 | size_t size) | 212 | size_t size) |
| 213 | { | 213 | { |
| 214 | int r, enable; | 214 | int r; |
| 215 | bool enable; | ||
| 215 | struct omap_overlay_info info; | 216 | struct omap_overlay_info info; |
| 216 | 217 | ||
| 217 | ovl->get_overlay_info(ovl, &info); | 218 | ovl->get_overlay_info(ovl, &info); |
| 218 | 219 | ||
| 219 | r = kstrtoint(buf, 0, &enable); | 220 | r = strtobool(buf, &enable); |
| 220 | if (r) | 221 | if (r) |
| 221 | return r; | 222 | return r; |
| 222 | 223 | ||
| 223 | info.enabled = !!enable; | 224 | info.enabled = enable; |
| 224 | 225 | ||
| 225 | r = ovl->set_overlay_info(ovl, &info); | 226 | r = ovl->set_overlay_info(ovl, &info); |
| 226 | if (r) | 227 | if (r) |
| @@ -248,7 +249,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
| 248 | u8 alpha; | 249 | u8 alpha; |
| 249 | struct omap_overlay_info info; | 250 | struct omap_overlay_info info; |
| 250 | 251 | ||
| 251 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA)) | 252 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) |
| 252 | return -ENODEV; | 253 | return -ENODEV; |
| 253 | 254 | ||
| 254 | r = kstrtou8(buf, 0, &alpha); | 255 | r = kstrtou8(buf, 0, &alpha); |
| @@ -257,14 +258,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | |||
| 257 | 258 | ||
| 258 | ovl->get_overlay_info(ovl, &info); | 259 | ovl->get_overlay_info(ovl, &info); |
| 259 | 260 | ||
| 260 | /* Video1 plane does not support global alpha | 261 | info.global_alpha = alpha; |
| 261 | * to always make it 255 completely opaque | ||
| 262 | */ | ||
| 263 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | ||
| 264 | ovl->id == OMAP_DSS_VIDEO1) | ||
| 265 | info.global_alpha = 255; | ||
| 266 | else | ||
| 267 | info.global_alpha = alpha; | ||
| 268 | 262 | ||
| 269 | r = ovl->set_overlay_info(ovl, &info); | 263 | r = ovl->set_overlay_info(ovl, &info); |
| 270 | if (r) | 264 | if (r) |
| @@ -293,20 +287,52 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | |||
| 293 | u8 alpha; | 287 | u8 alpha; |
| 294 | struct omap_overlay_info info; | 288 | struct omap_overlay_info info; |
| 295 | 289 | ||
| 290 | if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) | ||
| 291 | return -ENODEV; | ||
| 292 | |||
| 296 | r = kstrtou8(buf, 0, &alpha); | 293 | r = kstrtou8(buf, 0, &alpha); |
| 297 | if (r) | 294 | if (r) |
| 298 | return r; | 295 | return r; |
| 299 | 296 | ||
| 300 | ovl->get_overlay_info(ovl, &info); | 297 | ovl->get_overlay_info(ovl, &info); |
| 301 | 298 | ||
| 302 | /* only GFX and Video2 plane support pre alpha multiplied | 299 | info.pre_mult_alpha = alpha; |
| 303 | * set zero for Video1 plane | 300 | |
| 304 | */ | 301 | r = ovl->set_overlay_info(ovl, &info); |
| 305 | if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) && | 302 | if (r) |
| 306 | ovl->id == OMAP_DSS_VIDEO1) | 303 | return r; |
| 307 | info.pre_mult_alpha = 0; | 304 | |
| 308 | else | 305 | if (ovl->manager) { |
| 309 | info.pre_mult_alpha = alpha; | 306 | r = ovl->manager->apply(ovl->manager); |
| 307 | if (r) | ||
| 308 | return r; | ||
| 309 | } | ||
| 310 | |||
| 311 | return size; | ||
| 312 | } | ||
| 313 | |||
| 314 | static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) | ||
| 315 | { | ||
| 316 | return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder); | ||
| 317 | } | ||
| 318 | |||
| 319 | static ssize_t overlay_zorder_store(struct omap_overlay *ovl, | ||
| 320 | const char *buf, size_t size) | ||
| 321 | { | ||
| 322 | int r; | ||
| 323 | u8 zorder; | ||
| 324 | struct omap_overlay_info info; | ||
| 325 | |||
| 326 | if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) | ||
| 327 | return -ENODEV; | ||
| 328 | |||
| 329 | r = kstrtou8(buf, 0, &zorder); | ||
| 330 | if (r) | ||
| 331 | return r; | ||
| 332 | |||
| 333 | ovl->get_overlay_info(ovl, &info); | ||
| 334 | |||
| 335 | info.zorder = zorder; | ||
| 310 | 336 | ||
| 311 | r = ovl->set_overlay_info(ovl, &info); | 337 | r = ovl->set_overlay_info(ovl, &info); |
| 312 | if (r) | 338 | if (r) |
| @@ -347,6 +373,8 @@ static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | |||
| 347 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | 373 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, |
| 348 | overlay_pre_mult_alpha_show, | 374 | overlay_pre_mult_alpha_show, |
| 349 | overlay_pre_mult_alpha_store); | 375 | overlay_pre_mult_alpha_store); |
| 376 | static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, | ||
| 377 | overlay_zorder_show, overlay_zorder_store); | ||
| 350 | 378 | ||
| 351 | static struct attribute *overlay_sysfs_attrs[] = { | 379 | static struct attribute *overlay_sysfs_attrs[] = { |
| 352 | &overlay_attr_name.attr, | 380 | &overlay_attr_name.attr, |
| @@ -358,6 +386,7 @@ static struct attribute *overlay_sysfs_attrs[] = { | |||
| 358 | &overlay_attr_enabled.attr, | 386 | &overlay_attr_enabled.attr, |
| 359 | &overlay_attr_global_alpha.attr, | 387 | &overlay_attr_global_alpha.attr, |
| 360 | &overlay_attr_pre_mult_alpha.attr, | 388 | &overlay_attr_pre_mult_alpha.attr, |
| 389 | &overlay_attr_zorder.attr, | ||
| 361 | NULL | 390 | NULL |
| 362 | }; | 391 | }; |
| 363 | 392 | ||
| @@ -407,6 +436,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) | |||
| 407 | struct omap_overlay_info *info; | 436 | struct omap_overlay_info *info; |
| 408 | u16 outw, outh; | 437 | u16 outw, outh; |
| 409 | u16 dw, dh; | 438 | u16 dw, dh; |
| 439 | int i; | ||
| 410 | 440 | ||
| 411 | if (!dssdev) | 441 | if (!dssdev) |
| 412 | return 0; | 442 | return 0; |
| @@ -462,6 +492,31 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) | |||
| 462 | return -EINVAL; | 492 | return -EINVAL; |
| 463 | } | 493 | } |
| 464 | 494 | ||
| 495 | if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) { | ||
| 496 | if (info->zorder < 0 || info->zorder > 3) { | ||
| 497 | DSSERR("zorder out of range: %d\n", | ||
| 498 | info->zorder); | ||
| 499 | return -EINVAL; | ||
| 500 | } | ||
| 501 | /* | ||
| 502 | * Check that zorder doesn't match with zorder of any other | ||
| 503 | * overlay which is enabled and is also connected to the same | ||
| 504 | * manager | ||
| 505 | */ | ||
| 506 | for (i = 0; i < omap_dss_get_num_overlays(); i++) { | ||
| 507 | struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i); | ||
| 508 | |||
| 509 | if (tmp_ovl->id != ovl->id && | ||
| 510 | tmp_ovl->manager == ovl->manager && | ||
| 511 | tmp_ovl->info.enabled == true && | ||
| 512 | tmp_ovl->info.zorder == info->zorder) { | ||
| 513 | DSSERR("%s and %s have same zorder: %d\n", | ||
| 514 | ovl->name, tmp_ovl->name, info->zorder); | ||
| 515 | return -EINVAL; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | } | ||
| 519 | |||
| 465 | return 0; | 520 | return 0; |
| 466 | } | 521 | } |
| 467 | 522 | ||
| @@ -516,6 +571,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
| 516 | } | 571 | } |
| 517 | 572 | ||
| 518 | ovl->manager = mgr; | 573 | ovl->manager = mgr; |
| 574 | ovl->manager_changed = true; | ||
| 519 | 575 | ||
| 520 | /* XXX: When there is an overlay on a DSI manual update display, and | 576 | /* XXX: When there is an overlay on a DSI manual update display, and |
| 521 | * the overlay is first disabled, then moved to tv, and enabled, we | 577 | * the overlay is first disabled, then moved to tv, and enabled, we |
| @@ -529,15 +585,12 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
| 529 | * Userspace workaround for this is to update the LCD after disabling | 585 | * Userspace workaround for this is to update the LCD after disabling |
| 530 | * the overlay, but before moving the overlay to TV. | 586 | * the overlay, but before moving the overlay to TV. |
| 531 | */ | 587 | */ |
| 532 | dispc_set_channel_out(ovl->id, mgr->id); | ||
| 533 | 588 | ||
| 534 | return 0; | 589 | return 0; |
| 535 | } | 590 | } |
| 536 | 591 | ||
| 537 | static int omap_dss_unset_manager(struct omap_overlay *ovl) | 592 | static int omap_dss_unset_manager(struct omap_overlay *ovl) |
| 538 | { | 593 | { |
| 539 | int r; | ||
| 540 | |||
| 541 | if (!ovl->manager) { | 594 | if (!ovl->manager) { |
| 542 | DSSERR("failed to detach overlay: manager not set\n"); | 595 | DSSERR("failed to detach overlay: manager not set\n"); |
| 543 | return -EINVAL; | 596 | return -EINVAL; |
| @@ -548,11 +601,8 @@ static int omap_dss_unset_manager(struct omap_overlay *ovl) | |||
| 548 | return -EINVAL; | 601 | return -EINVAL; |
| 549 | } | 602 | } |
| 550 | 603 | ||
| 551 | r = ovl->wait_for_go(ovl); | ||
| 552 | if (r) | ||
| 553 | return r; | ||
| 554 | |||
| 555 | ovl->manager = NULL; | 604 | ovl->manager = NULL; |
| 605 | ovl->manager_changed = true; | ||
| 556 | 606 | ||
| 557 | return 0; | 607 | return 0; |
| 558 | } | 608 | } |
| @@ -618,22 +668,29 @@ void dss_init_overlays(struct platform_device *pdev) | |||
| 618 | case 0: | 668 | case 0: |
| 619 | ovl->name = "gfx"; | 669 | ovl->name = "gfx"; |
| 620 | ovl->id = OMAP_DSS_GFX; | 670 | ovl->id = OMAP_DSS_GFX; |
| 621 | ovl->caps = OMAP_DSS_OVL_CAP_DISPC; | ||
| 622 | ovl->info.global_alpha = 255; | 671 | ovl->info.global_alpha = 255; |
| 672 | ovl->info.zorder = 0; | ||
| 623 | break; | 673 | break; |
| 624 | case 1: | 674 | case 1: |
| 625 | ovl->name = "vid1"; | 675 | ovl->name = "vid1"; |
| 626 | ovl->id = OMAP_DSS_VIDEO1; | 676 | ovl->id = OMAP_DSS_VIDEO1; |
| 627 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | | ||
| 628 | OMAP_DSS_OVL_CAP_DISPC; | ||
| 629 | ovl->info.global_alpha = 255; | 677 | ovl->info.global_alpha = 255; |
| 678 | ovl->info.zorder = | ||
| 679 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0; | ||
| 630 | break; | 680 | break; |
| 631 | case 2: | 681 | case 2: |
| 632 | ovl->name = "vid2"; | 682 | ovl->name = "vid2"; |
| 633 | ovl->id = OMAP_DSS_VIDEO2; | 683 | ovl->id = OMAP_DSS_VIDEO2; |
| 634 | ovl->caps = OMAP_DSS_OVL_CAP_SCALE | | ||
| 635 | OMAP_DSS_OVL_CAP_DISPC; | ||
| 636 | ovl->info.global_alpha = 255; | 684 | ovl->info.global_alpha = 255; |
| 685 | ovl->info.zorder = | ||
| 686 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; | ||
| 687 | break; | ||
| 688 | case 3: | ||
| 689 | ovl->name = "vid3"; | ||
| 690 | ovl->id = OMAP_DSS_VIDEO3; | ||
| 691 | ovl->info.global_alpha = 255; | ||
| 692 | ovl->info.zorder = | ||
| 693 | dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0; | ||
| 637 | break; | 694 | break; |
| 638 | } | 695 | } |
| 639 | 696 | ||
| @@ -643,6 +700,7 @@ void dss_init_overlays(struct platform_device *pdev) | |||
| 643 | ovl->get_overlay_info = &dss_ovl_get_overlay_info; | 700 | ovl->get_overlay_info = &dss_ovl_get_overlay_info; |
| 644 | ovl->wait_for_go = &dss_ovl_wait_for_go; | 701 | ovl->wait_for_go = &dss_ovl_wait_for_go; |
| 645 | 702 | ||
| 703 | ovl->caps = dss_feat_get_overlay_caps(ovl->id); | ||
| 646 | ovl->supported_modes = | 704 | ovl->supported_modes = |
| 647 | dss_feat_get_supported_color_modes(ovl->id); | 705 | dss_feat_get_supported_color_modes(ovl->id); |
| 648 | 706 | ||
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 39f4c597026a..1130c608a561 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
| 27 | #include <linux/export.h> | ||
| 27 | #include <linux/vmalloc.h> | 28 | #include <linux/vmalloc.h> |
| 28 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
| 29 | #include <linux/io.h> | 30 | #include <linux/io.h> |
| @@ -309,9 +310,9 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | |||
| 309 | 310 | ||
| 310 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); | 311 | DSSDBG("rfbi_transfer_area %dx%d\n", width, height); |
| 311 | 312 | ||
| 312 | dispc_set_lcd_size(dssdev->manager->id, width, height); | 313 | dispc_mgr_set_lcd_size(dssdev->manager->id, width, height); |
| 313 | 314 | ||
| 314 | dispc_enable_channel(dssdev->manager->id, true); | 315 | dispc_mgr_enable(dssdev->manager->id, true); |
| 315 | 316 | ||
| 316 | rfbi.framedone_callback = callback; | 317 | rfbi.framedone_callback = callback; |
| 317 | rfbi.framedone_callback_data = data; | 318 | rfbi.framedone_callback_data = data; |
| @@ -783,10 +784,8 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | |||
| 783 | if (*w == 0 || *h == 0) | 784 | if (*w == 0 || *h == 0) |
| 784 | return -EINVAL; | 785 | return -EINVAL; |
| 785 | 786 | ||
| 786 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 787 | dss_setup_partial_planes(dssdev, x, y, w, h, true); |
| 787 | dss_setup_partial_planes(dssdev, x, y, w, h, true); | 788 | dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); |
| 788 | dispc_set_lcd_size(dssdev->manager->id, *w, *h); | ||
| 789 | } | ||
| 790 | 789 | ||
| 791 | return 0; | 790 | return 0; |
| 792 | } | 791 | } |
| @@ -796,22 +795,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev, | |||
| 796 | u16 x, u16 y, u16 w, u16 h, | 795 | u16 x, u16 y, u16 w, u16 h, |
| 797 | void (*callback)(void *), void *data) | 796 | void (*callback)(void *), void *data) |
| 798 | { | 797 | { |
| 799 | if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { | 798 | rfbi_transfer_area(dssdev, w, h, callback, data); |
| 800 | rfbi_transfer_area(dssdev, w, h, callback, data); | ||
| 801 | } else { | ||
| 802 | struct omap_overlay *ovl; | ||
| 803 | void __iomem *addr; | ||
| 804 | int scr_width; | ||
| 805 | |||
| 806 | ovl = dssdev->manager->overlays[0]; | ||
| 807 | scr_width = ovl->info.screen_width; | ||
| 808 | addr = ovl->info.vaddr; | ||
| 809 | |||
| 810 | omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); | ||
| 811 | |||
| 812 | callback(data); | ||
| 813 | } | ||
| 814 | |||
| 815 | return 0; | 799 | return 0; |
| 816 | } | 800 | } |
| 817 | EXPORT_SYMBOL(omap_rfbi_update); | 801 | EXPORT_SYMBOL(omap_rfbi_update); |
| @@ -860,6 +844,11 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
| 860 | { | 844 | { |
| 861 | int r; | 845 | int r; |
| 862 | 846 | ||
| 847 | if (dssdev->manager == NULL) { | ||
| 848 | DSSERR("failed to enable display: no manager\n"); | ||
| 849 | return -ENODEV; | ||
| 850 | } | ||
| 851 | |||
| 863 | r = rfbi_runtime_get(); | 852 | r = rfbi_runtime_get(); |
| 864 | if (r) | 853 | if (r) |
| 865 | return r; | 854 | return r; |
| @@ -877,13 +866,13 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | |||
| 877 | goto err1; | 866 | goto err1; |
| 878 | } | 867 | } |
| 879 | 868 | ||
| 880 | dispc_set_lcd_display_type(dssdev->manager->id, | 869 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, |
| 881 | OMAP_DSS_LCD_DISPLAY_TFT); | 870 | OMAP_DSS_LCD_DISPLAY_TFT); |
| 882 | 871 | ||
| 883 | dispc_set_parallel_interface_mode(dssdev->manager->id, | 872 | dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_RFBI); |
| 884 | OMAP_DSS_PARALLELMODE_RFBI); | 873 | dispc_mgr_enable_stallmode(dssdev->manager->id, true); |
| 885 | 874 | ||
| 886 | dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); | 875 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); |
| 887 | 876 | ||
| 888 | rfbi_configure(dssdev->phy.rfbi.channel, | 877 | rfbi_configure(dssdev->phy.rfbi.channel, |
| 889 | dssdev->ctrl.pixel_size, | 878 | dssdev->ctrl.pixel_size, |
| @@ -952,10 +941,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev) | |||
| 952 | 941 | ||
| 953 | msleep(10); | 942 | msleep(10); |
| 954 | 943 | ||
| 955 | if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630()) | 944 | clk = clk_get(&pdev->dev, "ick"); |
| 956 | clk = dss_get_ick(); | ||
| 957 | else | ||
| 958 | clk = clk_get(&pdev->dev, "ick"); | ||
| 959 | if (IS_ERR(clk)) { | 945 | if (IS_ERR(clk)) { |
| 960 | DSSERR("can't get ick\n"); | 946 | DSSERR("can't get ick\n"); |
| 961 | r = PTR_ERR(clk); | 947 | r = PTR_ERR(clk); |
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 3a688c871a45..40305ad7841e 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
| 25 | #include <linux/regulator/consumer.h> | 25 | #include <linux/regulator/consumer.h> |
| 26 | #include <linux/export.h> | ||
| 26 | 27 | ||
| 27 | #include <video/omapdss.h> | 28 | #include <video/omapdss.h> |
| 28 | #include "dss.h" | 29 | #include "dss.h" |
| @@ -35,13 +36,13 @@ static struct { | |||
| 35 | static void sdi_basic_init(struct omap_dss_device *dssdev) | 36 | static void sdi_basic_init(struct omap_dss_device *dssdev) |
| 36 | 37 | ||
| 37 | { | 38 | { |
| 38 | dispc_set_parallel_interface_mode(dssdev->manager->id, | 39 | dispc_mgr_set_io_pad_mode(DSS_IO_PAD_MODE_BYPASS); |
| 39 | OMAP_DSS_PARALLELMODE_BYPASS); | 40 | dispc_mgr_enable_stallmode(dssdev->manager->id, false); |
| 40 | 41 | ||
| 41 | dispc_set_lcd_display_type(dssdev->manager->id, | 42 | dispc_mgr_set_lcd_display_type(dssdev->manager->id, |
| 42 | OMAP_DSS_LCD_DISPLAY_TFT); | 43 | OMAP_DSS_LCD_DISPLAY_TFT); |
| 43 | 44 | ||
| 44 | dispc_set_tft_data_lines(dssdev->manager->id, 24); | 45 | dispc_mgr_set_tft_data_lines(dssdev->manager->id, 24); |
| 45 | dispc_lcd_enable_signal_polarity(1); | 46 | dispc_lcd_enable_signal_polarity(1); |
| 46 | } | 47 | } |
| 47 | 48 | ||
| @@ -55,6 +56,11 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
| 55 | unsigned long pck; | 56 | unsigned long pck; |
| 56 | int r; | 57 | int r; |
| 57 | 58 | ||
| 59 | if (dssdev->manager == NULL) { | ||
| 60 | DSSERR("failed to enable display: no manager\n"); | ||
| 61 | return -ENODEV; | ||
| 62 | } | ||
| 63 | |||
| 58 | r = omap_dss_start_device(dssdev); | 64 | r = omap_dss_start_device(dssdev); |
| 59 | if (r) { | 65 | if (r) { |
| 60 | DSSERR("failed to start device\n"); | 66 | DSSERR("failed to start device\n"); |
| @@ -78,7 +84,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
| 78 | /* 15.5.9.1.2 */ | 84 | /* 15.5.9.1.2 */ |
| 79 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; | 85 | dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; |
| 80 | 86 | ||
| 81 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 87 | dispc_mgr_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
| 82 | dssdev->panel.acbi, dssdev->panel.acb); | 88 | dssdev->panel.acbi, dssdev->panel.acb); |
| 83 | 89 | ||
| 84 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | 90 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, |
| @@ -101,13 +107,13 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
| 101 | } | 107 | } |
| 102 | 108 | ||
| 103 | 109 | ||
| 104 | dispc_set_lcd_timings(dssdev->manager->id, t); | 110 | dispc_mgr_set_lcd_timings(dssdev->manager->id, t); |
| 105 | 111 | ||
| 106 | r = dss_set_clock_div(&dss_cinfo); | 112 | r = dss_set_clock_div(&dss_cinfo); |
| 107 | if (r) | 113 | if (r) |
| 108 | goto err_set_dss_clock_div; | 114 | goto err_set_dss_clock_div; |
| 109 | 115 | ||
| 110 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 116 | r = dispc_mgr_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
| 111 | if (r) | 117 | if (r) |
| 112 | goto err_set_dispc_clock_div; | 118 | goto err_set_dispc_clock_div; |
| 113 | 119 | ||
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h new file mode 100644 index 000000000000..2c3443dabb14 --- /dev/null +++ b/drivers/video/omap2/dss/ti_hdmi.h | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | /* | ||
| 2 | * ti_hdmi.h | ||
| 3 | * | ||
| 4 | * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License version 2 as published by | ||
| 10 | * the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 15 | * more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License along with | ||
| 18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _TI_HDMI_H | ||
| 22 | #define _TI_HDMI_H | ||
| 23 | |||
| 24 | struct hdmi_ip_data; | ||
| 25 | |||
| 26 | enum hdmi_pll_pwr { | ||
| 27 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
| 28 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
| 29 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
| 30 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
| 31 | }; | ||
| 32 | |||
| 33 | enum hdmi_core_hdmi_dvi { | ||
| 34 | HDMI_DVI = 0, | ||
| 35 | HDMI_HDMI = 1 | ||
| 36 | }; | ||
| 37 | |||
| 38 | enum hdmi_clk_refsel { | ||
| 39 | HDMI_REFSEL_PCLK = 0, | ||
| 40 | HDMI_REFSEL_REF1 = 1, | ||
| 41 | HDMI_REFSEL_REF2 = 2, | ||
| 42 | HDMI_REFSEL_SYSCLK = 3 | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct hdmi_video_timings { | ||
| 46 | u16 x_res; | ||
| 47 | u16 y_res; | ||
| 48 | /* Unit: KHz */ | ||
| 49 | u32 pixel_clock; | ||
| 50 | u16 hsw; | ||
| 51 | u16 hfp; | ||
| 52 | u16 hbp; | ||
| 53 | u16 vsw; | ||
| 54 | u16 vfp; | ||
| 55 | u16 vbp; | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* HDMI timing structure */ | ||
| 59 | struct hdmi_timings { | ||
| 60 | struct hdmi_video_timings timings; | ||
| 61 | int vsync_pol; | ||
| 62 | int hsync_pol; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct hdmi_cm { | ||
| 66 | int code; | ||
| 67 | int mode; | ||
| 68 | }; | ||
| 69 | |||
| 70 | struct hdmi_config { | ||
| 71 | struct hdmi_timings timings; | ||
| 72 | u16 interlace; | ||
| 73 | struct hdmi_cm cm; | ||
| 74 | }; | ||
| 75 | |||
| 76 | /* HDMI PLL structure */ | ||
| 77 | struct hdmi_pll_info { | ||
| 78 | u16 regn; | ||
| 79 | u16 regm; | ||
| 80 | u32 regmf; | ||
| 81 | u16 regm2; | ||
| 82 | u16 regsd; | ||
| 83 | u16 dcofreq; | ||
| 84 | enum hdmi_clk_refsel refsel; | ||
| 85 | }; | ||
| 86 | |||
| 87 | struct ti_hdmi_ip_ops { | ||
| 88 | |||
| 89 | void (*video_configure)(struct hdmi_ip_data *ip_data); | ||
| 90 | |||
| 91 | int (*phy_enable)(struct hdmi_ip_data *ip_data); | ||
| 92 | |||
| 93 | void (*phy_disable)(struct hdmi_ip_data *ip_data); | ||
| 94 | |||
| 95 | int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len); | ||
| 96 | |||
| 97 | bool (*detect)(struct hdmi_ip_data *ip_data); | ||
| 98 | |||
| 99 | int (*pll_enable)(struct hdmi_ip_data *ip_data); | ||
| 100 | |||
| 101 | void (*pll_disable)(struct hdmi_ip_data *ip_data); | ||
| 102 | |||
| 103 | void (*video_enable)(struct hdmi_ip_data *ip_data, bool start); | ||
| 104 | |||
| 105 | void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 106 | |||
| 107 | void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 108 | |||
| 109 | void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 110 | |||
| 111 | void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 112 | |||
| 113 | }; | ||
| 114 | |||
| 115 | struct hdmi_ip_data { | ||
| 116 | void __iomem *base_wp; /* HDMI wrapper */ | ||
| 117 | unsigned long core_sys_offset; | ||
| 118 | unsigned long core_av_offset; | ||
| 119 | unsigned long pll_offset; | ||
| 120 | unsigned long phy_offset; | ||
| 121 | const struct ti_hdmi_ip_ops *ops; | ||
| 122 | struct hdmi_config cfg; | ||
| 123 | struct hdmi_pll_info pll_data; | ||
| 124 | }; | ||
| 125 | int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data); | ||
| 126 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); | ||
| 127 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); | ||
| 128 | bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); | ||
| 129 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); | ||
| 130 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); | ||
| 131 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); | ||
| 132 | void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); | ||
| 133 | void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 134 | void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 135 | void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 136 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); | ||
| 137 | |||
| 138 | #endif | ||
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c new file mode 100644 index 000000000000..e1a6ce518af6 --- /dev/null +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c | |||
| @@ -0,0 +1,1239 @@ | |||
| 1 | /* | ||
| 2 | * ti_hdmi_4xxx_ip.c | ||
| 3 | * | ||
| 4 | * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library | ||
| 5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 6 | * Authors: Yong Zhi | ||
| 7 | * Mythri pk <mythripk@ti.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License version 2 as published by | ||
| 11 | * the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 16 | * more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU General Public License along with | ||
| 19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/err.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/mutex.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | #include <linux/string.h> | ||
| 30 | #include <linux/seq_file.h> | ||
| 31 | |||
| 32 | #include "ti_hdmi_4xxx_ip.h" | ||
| 33 | #include "dss.h" | ||
| 34 | |||
| 35 | static inline void hdmi_write_reg(void __iomem *base_addr, | ||
| 36 | const u16 idx, u32 val) | ||
| 37 | { | ||
| 38 | __raw_writel(val, base_addr + idx); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline u32 hdmi_read_reg(void __iomem *base_addr, | ||
| 42 | const u16 idx) | ||
| 43 | { | ||
| 44 | return __raw_readl(base_addr + idx); | ||
| 45 | } | ||
| 46 | |||
| 47 | static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data) | ||
| 48 | { | ||
| 49 | return ip_data->base_wp; | ||
| 50 | } | ||
| 51 | |||
| 52 | static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data) | ||
| 53 | { | ||
| 54 | return ip_data->base_wp + ip_data->phy_offset; | ||
| 55 | } | ||
| 56 | |||
| 57 | static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data) | ||
| 58 | { | ||
| 59 | return ip_data->base_wp + ip_data->pll_offset; | ||
| 60 | } | ||
| 61 | |||
| 62 | static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data) | ||
| 63 | { | ||
| 64 | return ip_data->base_wp + ip_data->core_av_offset; | ||
| 65 | } | ||
| 66 | |||
| 67 | static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data) | ||
| 68 | { | ||
| 69 | return ip_data->base_wp + ip_data->core_sys_offset; | ||
| 70 | } | ||
| 71 | |||
| 72 | static inline int hdmi_wait_for_bit_change(void __iomem *base_addr, | ||
| 73 | const u16 idx, | ||
| 74 | int b2, int b1, u32 val) | ||
| 75 | { | ||
| 76 | u32 t = 0; | ||
| 77 | while (val != REG_GET(base_addr, idx, b2, b1)) { | ||
| 78 | udelay(1); | ||
| 79 | if (t++ > 10000) | ||
| 80 | return !val; | ||
| 81 | } | ||
| 82 | return val; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int hdmi_pll_init(struct hdmi_ip_data *ip_data) | ||
| 86 | { | ||
| 87 | u32 r; | ||
| 88 | void __iomem *pll_base = hdmi_pll_base(ip_data); | ||
| 89 | struct hdmi_pll_info *fmt = &ip_data->pll_data; | ||
| 90 | |||
| 91 | /* PLL start always use manual mode */ | ||
| 92 | REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
| 93 | |||
| 94 | r = hdmi_read_reg(pll_base, PLLCTRL_CFG1); | ||
| 95 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
| 96 | r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */ | ||
| 97 | |||
| 98 | hdmi_write_reg(pll_base, PLLCTRL_CFG1, r); | ||
| 99 | |||
| 100 | r = hdmi_read_reg(pll_base, PLLCTRL_CFG2); | ||
| 101 | |||
| 102 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
| 103 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
| 104 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
| 105 | r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */ | ||
| 106 | |||
| 107 | if (fmt->dcofreq) { | ||
| 108 | /* divider programming for frequency beyond 1000Mhz */ | ||
| 109 | REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10); | ||
| 110 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
| 111 | } else { | ||
| 112 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
| 113 | } | ||
| 114 | |||
| 115 | hdmi_write_reg(pll_base, PLLCTRL_CFG2, r); | ||
| 116 | |||
| 117 | r = hdmi_read_reg(pll_base, PLLCTRL_CFG4); | ||
| 118 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
| 119 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
| 120 | |||
| 121 | hdmi_write_reg(pll_base, PLLCTRL_CFG4, r); | ||
| 122 | |||
| 123 | /* go now */ | ||
| 124 | REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
| 125 | |||
| 126 | /* wait for bit change */ | ||
| 127 | if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO, | ||
| 128 | 0, 0, 1) != 1) { | ||
| 129 | pr_err("PLL GO bit not set\n"); | ||
| 130 | return -ETIMEDOUT; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* Wait till the lock bit is set in PLL status */ | ||
| 134 | if (hdmi_wait_for_bit_change(pll_base, | ||
| 135 | PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
| 136 | pr_err("cannot lock PLL\n"); | ||
| 137 | pr_err("CFG1 0x%x\n", | ||
| 138 | hdmi_read_reg(pll_base, PLLCTRL_CFG1)); | ||
| 139 | pr_err("CFG2 0x%x\n", | ||
| 140 | hdmi_read_reg(pll_base, PLLCTRL_CFG2)); | ||
| 141 | pr_err("CFG4 0x%x\n", | ||
| 142 | hdmi_read_reg(pll_base, PLLCTRL_CFG4)); | ||
| 143 | return -ETIMEDOUT; | ||
| 144 | } | ||
| 145 | |||
| 146 | pr_debug("PLL locked!\n"); | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* PHY_PWR_CMD */ | ||
| 152 | static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val) | ||
| 153 | { | ||
| 154 | /* Command for power control of HDMI PHY */ | ||
| 155 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6); | ||
| 156 | |||
| 157 | /* Status of the power control of HDMI PHY */ | ||
| 158 | if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), | ||
| 159 | HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
| 160 | pr_err("Failed to set PHY power mode to %d\n", val); | ||
| 161 | return -ETIMEDOUT; | ||
| 162 | } | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | /* PLL_PWR_CMD */ | ||
| 168 | static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val) | ||
| 169 | { | ||
| 170 | /* Command for power control of HDMI PLL */ | ||
| 171 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2); | ||
| 172 | |||
| 173 | /* wait till PHY_PWR_STATUS is set */ | ||
| 174 | if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, | ||
| 175 | 1, 0, val) != val) { | ||
| 176 | pr_err("Failed to set PLL_PWR_STATUS\n"); | ||
| 177 | return -ETIMEDOUT; | ||
| 178 | } | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | static int hdmi_pll_reset(struct hdmi_ip_data *ip_data) | ||
| 184 | { | ||
| 185 | /* SYSRESET controlled by power FSM */ | ||
| 186 | REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
| 187 | |||
| 188 | /* READ 0x0 reset is in progress */ | ||
| 189 | if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data), | ||
| 190 | PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
| 191 | pr_err("Failed to sysreset PLL\n"); | ||
| 192 | return -ETIMEDOUT; | ||
| 193 | } | ||
| 194 | |||
| 195 | return 0; | ||
| 196 | } | ||
| 197 | |||
| 198 | int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data) | ||
| 199 | { | ||
| 200 | u16 r = 0; | ||
| 201 | |||
| 202 | r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); | ||
| 203 | if (r) | ||
| 204 | return r; | ||
| 205 | |||
| 206 | r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
| 207 | if (r) | ||
| 208 | return r; | ||
| 209 | |||
| 210 | r = hdmi_pll_reset(ip_data); | ||
| 211 | if (r) | ||
| 212 | return r; | ||
| 213 | |||
| 214 | r = hdmi_pll_init(ip_data); | ||
| 215 | if (r) | ||
| 216 | return r; | ||
| 217 | |||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data) | ||
| 222 | { | ||
| 223 | hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF); | ||
| 224 | } | ||
| 225 | |||
| 226 | int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data) | ||
| 227 | { | ||
| 228 | u16 r = 0; | ||
| 229 | void __iomem *phy_base = hdmi_phy_base(ip_data); | ||
| 230 | |||
| 231 | r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON); | ||
| 232 | if (r) | ||
| 233 | return r; | ||
| 234 | |||
| 235 | r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON); | ||
| 236 | if (r) | ||
| 237 | return r; | ||
| 238 | |||
| 239 | /* | ||
| 240 | * Read address 0 in order to get the SCP reset done completed | ||
| 241 | * Dummy access performed to make sure reset is done | ||
| 242 | */ | ||
| 243 | hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL); | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Write to phy address 0 to configure the clock | ||
| 247 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
| 248 | */ | ||
| 249 | REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
| 250 | |||
| 251 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
| 252 | hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
| 253 | |||
| 254 | /* Setup max LDO voltage */ | ||
| 255 | REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
| 256 | |||
| 257 | /* Write to phy address 3 to change the polarity control */ | ||
| 258 | REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data) | ||
| 264 | { | ||
| 265 | hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); | ||
| 266 | } | ||
| 267 | |||
| 268 | static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data) | ||
| 269 | { | ||
| 270 | void __iomem *base = hdmi_core_sys_base(ip_data); | ||
| 271 | |||
| 272 | /* Turn on CLK for DDC */ | ||
| 273 | REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
| 274 | |||
| 275 | /* IN_PROG */ | ||
| 276 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) { | ||
| 277 | /* Abort transaction */ | ||
| 278 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0); | ||
| 279 | /* IN_PROG */ | ||
| 280 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
| 281 | 4, 4, 0) != 0) { | ||
| 282 | DSSERR("Timeout aborting DDC transaction\n"); | ||
| 283 | return -ETIMEDOUT; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | /* Clk SCL Devices */ | ||
| 288 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
| 289 | |||
| 290 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
| 291 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
| 292 | 4, 4, 0) != 0) { | ||
| 293 | DSSERR("Timeout starting SCL clock\n"); | ||
| 294 | return -ETIMEDOUT; | ||
| 295 | } | ||
| 296 | |||
| 297 | /* Clear FIFO */ | ||
| 298 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
| 299 | |||
| 300 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
| 301 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
| 302 | 4, 4, 0) != 0) { | ||
| 303 | DSSERR("Timeout clearing DDC fifo\n"); | ||
| 304 | return -ETIMEDOUT; | ||
| 305 | } | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data, | ||
| 311 | u8 *pedid, int ext) | ||
| 312 | { | ||
| 313 | void __iomem *base = hdmi_core_sys_base(ip_data); | ||
| 314 | u32 i; | ||
| 315 | char checksum; | ||
| 316 | u32 offset = 0; | ||
| 317 | |||
| 318 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
| 319 | if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS, | ||
| 320 | 4, 4, 0) != 0) { | ||
| 321 | DSSERR("Timeout waiting DDC to be ready\n"); | ||
| 322 | return -ETIMEDOUT; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (ext % 2 != 0) | ||
| 326 | offset = 0x80; | ||
| 327 | |||
| 328 | /* Load Segment Address Register */ | ||
| 329 | REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0); | ||
| 330 | |||
| 331 | /* Load Slave Address Register */ | ||
| 332 | REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
| 333 | |||
| 334 | /* Load Offset Address Register */ | ||
| 335 | REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
| 336 | |||
| 337 | /* Load Byte Count */ | ||
| 338 | REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
| 339 | REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
| 340 | |||
| 341 | /* Set DDC_CMD */ | ||
| 342 | if (ext) | ||
| 343 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
| 344 | else | ||
| 345 | REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
| 346 | |||
| 347 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
| 348 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
| 349 | pr_err("I2C Bus Low?\n"); | ||
| 350 | return -EIO; | ||
| 351 | } | ||
| 352 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
| 353 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
| 354 | pr_err("I2C No Ack\n"); | ||
| 355 | return -EIO; | ||
| 356 | } | ||
| 357 | |||
| 358 | for (i = 0; i < 0x80; ++i) { | ||
| 359 | int t; | ||
| 360 | |||
| 361 | /* IN_PROG */ | ||
| 362 | if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) { | ||
| 363 | DSSERR("operation stopped when reading edid\n"); | ||
| 364 | return -EIO; | ||
| 365 | } | ||
| 366 | |||
| 367 | t = 0; | ||
| 368 | /* FIFO_EMPTY */ | ||
| 369 | while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) { | ||
| 370 | if (t++ > 10000) { | ||
| 371 | DSSERR("timeout reading edid\n"); | ||
| 372 | return -ETIMEDOUT; | ||
| 373 | } | ||
| 374 | udelay(1); | ||
| 375 | } | ||
| 376 | |||
| 377 | pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0); | ||
| 378 | } | ||
| 379 | |||
| 380 | checksum = 0; | ||
| 381 | for (i = 0; i < 0x80; ++i) | ||
| 382 | checksum += pedid[i]; | ||
| 383 | |||
| 384 | if (checksum != 0) { | ||
| 385 | pr_err("E-EDID checksum failed!!\n"); | ||
| 386 | return -EIO; | ||
| 387 | } | ||
| 388 | |||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, | ||
| 393 | u8 *edid, int len) | ||
| 394 | { | ||
| 395 | int r, l; | ||
| 396 | |||
| 397 | if (len < 128) | ||
| 398 | return -EINVAL; | ||
| 399 | |||
| 400 | r = hdmi_core_ddc_init(ip_data); | ||
| 401 | if (r) | ||
| 402 | return r; | ||
| 403 | |||
| 404 | r = hdmi_core_ddc_edid(ip_data, edid, 0); | ||
| 405 | if (r) | ||
| 406 | return r; | ||
| 407 | |||
| 408 | l = 128; | ||
| 409 | |||
| 410 | if (len >= 128 * 2 && edid[0x7e] > 0) { | ||
| 411 | r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1); | ||
| 412 | if (r) | ||
| 413 | return r; | ||
| 414 | l += 128; | ||
| 415 | } | ||
| 416 | |||
| 417 | return l; | ||
| 418 | } | ||
| 419 | |||
| 420 | bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data) | ||
| 421 | { | ||
| 422 | int r; | ||
| 423 | |||
| 424 | void __iomem *base = hdmi_core_sys_base(ip_data); | ||
| 425 | |||
| 426 | /* HPD */ | ||
| 427 | r = REG_GET(base, HDMI_CORE_SYS_SYS_STAT, 1, 1); | ||
| 428 | |||
| 429 | return r == 1; | ||
| 430 | } | ||
| 431 | |||
| 432 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
| 433 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
| 434 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
| 435 | { | ||
| 436 | pr_debug("Enter hdmi_core_init\n"); | ||
| 437 | |||
| 438 | /* video core */ | ||
| 439 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
| 440 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
| 441 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
| 442 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
| 443 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
| 444 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
| 445 | |||
| 446 | /* info frame */ | ||
| 447 | avi_cfg->db1_format = 0; | ||
| 448 | avi_cfg->db1_active_info = 0; | ||
| 449 | avi_cfg->db1_bar_info_dv = 0; | ||
| 450 | avi_cfg->db1_scan_info = 0; | ||
| 451 | avi_cfg->db2_colorimetry = 0; | ||
| 452 | avi_cfg->db2_aspect_ratio = 0; | ||
| 453 | avi_cfg->db2_active_fmt_ar = 0; | ||
| 454 | avi_cfg->db3_itc = 0; | ||
| 455 | avi_cfg->db3_ec = 0; | ||
| 456 | avi_cfg->db3_q_range = 0; | ||
| 457 | avi_cfg->db3_nup_scaling = 0; | ||
| 458 | avi_cfg->db4_videocode = 0; | ||
| 459 | avi_cfg->db5_pixel_repeat = 0; | ||
| 460 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
| 461 | avi_cfg->db8_9_line_sofbottom = 0; | ||
| 462 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
| 463 | avi_cfg->db12_13_pixel_sofright = 0; | ||
| 464 | |||
| 465 | /* packet enable and repeat */ | ||
| 466 | repeat_cfg->audio_pkt = 0; | ||
| 467 | repeat_cfg->audio_pkt_repeat = 0; | ||
| 468 | repeat_cfg->avi_infoframe = 0; | ||
| 469 | repeat_cfg->avi_infoframe_repeat = 0; | ||
| 470 | repeat_cfg->gen_cntrl_pkt = 0; | ||
| 471 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
| 472 | repeat_cfg->generic_pkt = 0; | ||
| 473 | repeat_cfg->generic_pkt_repeat = 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data) | ||
| 477 | { | ||
| 478 | pr_debug("Enter hdmi_core_powerdown_disable\n"); | ||
| 479 | REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
| 480 | } | ||
| 481 | |||
| 482 | static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data) | ||
| 483 | { | ||
| 484 | pr_debug("Enter hdmi_core_swreset_release\n"); | ||
| 485 | REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
| 486 | } | ||
| 487 | |||
| 488 | static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data) | ||
| 489 | { | ||
| 490 | pr_debug("Enter hdmi_core_swreset_assert\n"); | ||
| 491 | REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
| 492 | } | ||
| 493 | |||
| 494 | /* HDMI_CORE_VIDEO_CONFIG */ | ||
| 495 | static void hdmi_core_video_config(struct hdmi_ip_data *ip_data, | ||
| 496 | struct hdmi_core_video_config *cfg) | ||
| 497 | { | ||
| 498 | u32 r = 0; | ||
| 499 | void __iomem *core_sys_base = hdmi_core_sys_base(ip_data); | ||
| 500 | |||
| 501 | /* sys_ctrl1 default configuration not tunable */ | ||
| 502 | r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1); | ||
| 503 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
| 504 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
| 505 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
| 506 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
| 507 | hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r); | ||
| 508 | |||
| 509 | REG_FLD_MOD(core_sys_base, | ||
| 510 | HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
| 511 | |||
| 512 | /* Vid_Mode */ | ||
| 513 | r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE); | ||
| 514 | |||
| 515 | /* dither truncation configuration */ | ||
| 516 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
| 517 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
| 518 | r = FLD_MOD(r, 1, 5, 5); | ||
| 519 | } else { | ||
| 520 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
| 521 | r = FLD_MOD(r, 0, 5, 5); | ||
| 522 | } | ||
| 523 | hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r); | ||
| 524 | |||
| 525 | /* HDMI_Ctrl */ | ||
| 526 | r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL); | ||
| 527 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
| 528 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
| 529 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
| 530 | hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r); | ||
| 531 | |||
| 532 | /* TMDS_CTRL */ | ||
| 533 | REG_FLD_MOD(core_sys_base, | ||
| 534 | HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5); | ||
| 535 | } | ||
| 536 | |||
| 537 | static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data, | ||
| 538 | struct hdmi_core_infoframe_avi info_avi) | ||
| 539 | { | ||
| 540 | u32 val; | ||
| 541 | char sum = 0, checksum = 0; | ||
| 542 | void __iomem *av_base = hdmi_av_base(ip_data); | ||
| 543 | |||
| 544 | sum += 0x82 + 0x002 + 0x00D; | ||
| 545 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
| 546 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002); | ||
| 547 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
| 548 | |||
| 549 | val = (info_avi.db1_format << 5) | | ||
| 550 | (info_avi.db1_active_info << 4) | | ||
| 551 | (info_avi.db1_bar_info_dv << 2) | | ||
| 552 | (info_avi.db1_scan_info); | ||
| 553 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
| 554 | sum += val; | ||
| 555 | |||
| 556 | val = (info_avi.db2_colorimetry << 6) | | ||
| 557 | (info_avi.db2_aspect_ratio << 4) | | ||
| 558 | (info_avi.db2_active_fmt_ar); | ||
| 559 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
| 560 | sum += val; | ||
| 561 | |||
| 562 | val = (info_avi.db3_itc << 7) | | ||
| 563 | (info_avi.db3_ec << 4) | | ||
| 564 | (info_avi.db3_q_range << 2) | | ||
| 565 | (info_avi.db3_nup_scaling); | ||
| 566 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
| 567 | sum += val; | ||
| 568 | |||
| 569 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3), | ||
| 570 | info_avi.db4_videocode); | ||
| 571 | sum += info_avi.db4_videocode; | ||
| 572 | |||
| 573 | val = info_avi.db5_pixel_repeat; | ||
| 574 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
| 575 | sum += val; | ||
| 576 | |||
| 577 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
| 578 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
| 579 | sum += val; | ||
| 580 | |||
| 581 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
| 582 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
| 583 | sum += val; | ||
| 584 | |||
| 585 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
| 586 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
| 587 | sum += val; | ||
| 588 | |||
| 589 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
| 590 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
| 591 | sum += val; | ||
| 592 | |||
| 593 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
| 594 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
| 595 | sum += val; | ||
| 596 | |||
| 597 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
| 598 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
| 599 | sum += val; | ||
| 600 | |||
| 601 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
| 602 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
| 603 | sum += val; | ||
| 604 | |||
| 605 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
| 606 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
| 607 | sum += val; | ||
| 608 | |||
| 609 | checksum = 0x100 - sum; | ||
| 610 | hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
| 611 | } | ||
| 612 | |||
| 613 | static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data, | ||
| 614 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
| 615 | { | ||
| 616 | /* enable/repeat the infoframe */ | ||
| 617 | hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1, | ||
| 618 | (repeat_cfg.audio_pkt << 5) | | ||
| 619 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
| 620 | (repeat_cfg.avi_infoframe << 1) | | ||
| 621 | (repeat_cfg.avi_infoframe_repeat)); | ||
| 622 | |||
| 623 | /* enable/repeat the packet */ | ||
| 624 | hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2, | ||
| 625 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
| 626 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
| 627 | (repeat_cfg.generic_pkt << 1) | | ||
| 628 | (repeat_cfg.generic_pkt_repeat)); | ||
| 629 | } | ||
| 630 | |||
| 631 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
| 632 | struct hdmi_video_format *video_fmt, | ||
| 633 | struct hdmi_video_interface *video_int) | ||
| 634 | { | ||
| 635 | pr_debug("Enter hdmi_wp_init\n"); | ||
| 636 | |||
| 637 | timings->hbp = 0; | ||
| 638 | timings->hfp = 0; | ||
| 639 | timings->hsw = 0; | ||
| 640 | timings->vbp = 0; | ||
| 641 | timings->vfp = 0; | ||
| 642 | timings->vsw = 0; | ||
| 643 | |||
| 644 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
| 645 | video_fmt->y_res = 0; | ||
| 646 | video_fmt->x_res = 0; | ||
| 647 | |||
| 648 | video_int->vsp = 0; | ||
| 649 | video_int->hsp = 0; | ||
| 650 | |||
| 651 | video_int->interlacing = 0; | ||
| 652 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
| 653 | |||
| 654 | } | ||
| 655 | |||
| 656 | void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) | ||
| 657 | { | ||
| 658 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
| 659 | } | ||
| 660 | |||
| 661 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
| 662 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
| 663 | { | ||
| 664 | pr_debug("Enter hdmi_wp_video_init_format\n"); | ||
| 665 | |||
| 666 | video_fmt->y_res = param->timings.timings.y_res; | ||
| 667 | video_fmt->x_res = param->timings.timings.x_res; | ||
| 668 | |||
| 669 | timings->hbp = param->timings.timings.hbp; | ||
| 670 | timings->hfp = param->timings.timings.hfp; | ||
| 671 | timings->hsw = param->timings.timings.hsw; | ||
| 672 | timings->vbp = param->timings.timings.vbp; | ||
| 673 | timings->vfp = param->timings.timings.vfp; | ||
| 674 | timings->vsw = param->timings.timings.vsw; | ||
| 675 | } | ||
| 676 | |||
| 677 | static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data, | ||
| 678 | struct hdmi_video_format *video_fmt) | ||
| 679 | { | ||
| 680 | u32 l = 0; | ||
| 681 | |||
| 682 | REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, | ||
| 683 | video_fmt->packing_mode, 10, 8); | ||
| 684 | |||
| 685 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
| 686 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
| 687 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l); | ||
| 688 | } | ||
| 689 | |||
| 690 | static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data, | ||
| 691 | struct hdmi_video_interface *video_int) | ||
| 692 | { | ||
| 693 | u32 r; | ||
| 694 | pr_debug("Enter hdmi_wp_video_config_interface\n"); | ||
| 695 | |||
| 696 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG); | ||
| 697 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
| 698 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
| 699 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
| 700 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
| 701 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r); | ||
| 702 | } | ||
| 703 | |||
| 704 | static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data, | ||
| 705 | struct omap_video_timings *timings) | ||
| 706 | { | ||
| 707 | u32 timing_h = 0; | ||
| 708 | u32 timing_v = 0; | ||
| 709 | |||
| 710 | pr_debug("Enter hdmi_wp_video_config_timing\n"); | ||
| 711 | |||
| 712 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
| 713 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
| 714 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
| 715 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
| 716 | |||
| 717 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
| 718 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
| 719 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
| 720 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
| 721 | } | ||
| 722 | |||
| 723 | void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data) | ||
| 724 | { | ||
| 725 | /* HDMI */ | ||
| 726 | struct omap_video_timings video_timing; | ||
| 727 | struct hdmi_video_format video_format; | ||
| 728 | struct hdmi_video_interface video_interface; | ||
| 729 | /* HDMI core */ | ||
| 730 | struct hdmi_core_infoframe_avi avi_cfg; | ||
| 731 | struct hdmi_core_video_config v_core_cfg; | ||
| 732 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
| 733 | struct hdmi_config *cfg = &ip_data->cfg; | ||
| 734 | |||
| 735 | hdmi_wp_init(&video_timing, &video_format, | ||
| 736 | &video_interface); | ||
| 737 | |||
| 738 | hdmi_core_init(&v_core_cfg, | ||
| 739 | &avi_cfg, | ||
| 740 | &repeat_cfg); | ||
| 741 | |||
| 742 | hdmi_wp_video_init_format(&video_format, &video_timing, cfg); | ||
| 743 | |||
| 744 | hdmi_wp_video_config_timing(ip_data, &video_timing); | ||
| 745 | |||
| 746 | /* video config */ | ||
| 747 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
| 748 | |||
| 749 | hdmi_wp_video_config_format(ip_data, &video_format); | ||
| 750 | |||
| 751 | video_interface.vsp = cfg->timings.vsync_pol; | ||
| 752 | video_interface.hsp = cfg->timings.hsync_pol; | ||
| 753 | video_interface.interlacing = cfg->interlace; | ||
| 754 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
| 755 | |||
| 756 | hdmi_wp_video_config_interface(ip_data, &video_interface); | ||
| 757 | |||
| 758 | /* | ||
| 759 | * configure core video part | ||
| 760 | * set software reset in the core | ||
| 761 | */ | ||
| 762 | hdmi_core_swreset_assert(ip_data); | ||
| 763 | |||
| 764 | /* power down off */ | ||
| 765 | hdmi_core_powerdown_disable(ip_data); | ||
| 766 | |||
| 767 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
| 768 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
| 769 | |||
| 770 | hdmi_core_video_config(ip_data, &v_core_cfg); | ||
| 771 | |||
| 772 | /* release software reset in the core */ | ||
| 773 | hdmi_core_swreset_release(ip_data); | ||
| 774 | |||
| 775 | /* | ||
| 776 | * configure packet | ||
| 777 | * info frame video see doc CEA861-D page 65 | ||
| 778 | */ | ||
| 779 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
| 780 | avi_cfg.db1_active_info = | ||
| 781 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
| 782 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
| 783 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
| 784 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
| 785 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
| 786 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
| 787 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
| 788 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
| 789 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
| 790 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
| 791 | avi_cfg.db4_videocode = cfg->cm.code; | ||
| 792 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
| 793 | avi_cfg.db6_7_line_eoftop = 0; | ||
| 794 | avi_cfg.db8_9_line_sofbottom = 0; | ||
| 795 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
| 796 | avi_cfg.db12_13_pixel_sofright = 0; | ||
| 797 | |||
| 798 | hdmi_core_aux_infoframe_avi_config(ip_data, avi_cfg); | ||
| 799 | |||
| 800 | /* enable/repeat the infoframe */ | ||
| 801 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
| 802 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
| 803 | /* wakeup */ | ||
| 804 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
| 805 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
| 806 | hdmi_core_av_packet_config(ip_data, repeat_cfg); | ||
| 807 | } | ||
| 808 | |||
| 809 | void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
| 810 | { | ||
| 811 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
| 812 | hdmi_read_reg(hdmi_wp_base(ip_data), r)) | ||
| 813 | |||
| 814 | DUMPREG(HDMI_WP_REVISION); | ||
| 815 | DUMPREG(HDMI_WP_SYSCONFIG); | ||
| 816 | DUMPREG(HDMI_WP_IRQSTATUS_RAW); | ||
| 817 | DUMPREG(HDMI_WP_IRQSTATUS); | ||
| 818 | DUMPREG(HDMI_WP_PWR_CTRL); | ||
| 819 | DUMPREG(HDMI_WP_IRQENABLE_SET); | ||
| 820 | DUMPREG(HDMI_WP_VIDEO_CFG); | ||
| 821 | DUMPREG(HDMI_WP_VIDEO_SIZE); | ||
| 822 | DUMPREG(HDMI_WP_VIDEO_TIMING_H); | ||
| 823 | DUMPREG(HDMI_WP_VIDEO_TIMING_V); | ||
| 824 | DUMPREG(HDMI_WP_WP_CLK); | ||
| 825 | DUMPREG(HDMI_WP_AUDIO_CFG); | ||
| 826 | DUMPREG(HDMI_WP_AUDIO_CFG2); | ||
| 827 | DUMPREG(HDMI_WP_AUDIO_CTRL); | ||
| 828 | DUMPREG(HDMI_WP_AUDIO_DATA); | ||
| 829 | } | ||
| 830 | |||
| 831 | void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
| 832 | { | ||
| 833 | #define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
| 834 | hdmi_read_reg(hdmi_pll_base(ip_data), r)) | ||
| 835 | |||
| 836 | DUMPPLL(PLLCTRL_PLL_CONTROL); | ||
| 837 | DUMPPLL(PLLCTRL_PLL_STATUS); | ||
| 838 | DUMPPLL(PLLCTRL_PLL_GO); | ||
| 839 | DUMPPLL(PLLCTRL_CFG1); | ||
| 840 | DUMPPLL(PLLCTRL_CFG2); | ||
| 841 | DUMPPLL(PLLCTRL_CFG3); | ||
| 842 | DUMPPLL(PLLCTRL_CFG4); | ||
| 843 | } | ||
| 844 | |||
| 845 | void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
| 846 | { | ||
| 847 | int i; | ||
| 848 | |||
| 849 | #define CORE_REG(i, name) name(i) | ||
| 850 | #define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
| 851 | hdmi_read_reg(hdmi_pll_base(ip_data), r)) | ||
| 852 | #define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ | ||
| 853 | (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ | ||
| 854 | hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r))) | ||
| 855 | |||
| 856 | DUMPCORE(HDMI_CORE_SYS_VND_IDL); | ||
| 857 | DUMPCORE(HDMI_CORE_SYS_DEV_IDL); | ||
| 858 | DUMPCORE(HDMI_CORE_SYS_DEV_IDH); | ||
| 859 | DUMPCORE(HDMI_CORE_SYS_DEV_REV); | ||
| 860 | DUMPCORE(HDMI_CORE_SYS_SRST); | ||
| 861 | DUMPCORE(HDMI_CORE_CTRL1); | ||
| 862 | DUMPCORE(HDMI_CORE_SYS_SYS_STAT); | ||
| 863 | DUMPCORE(HDMI_CORE_SYS_VID_ACEN); | ||
| 864 | DUMPCORE(HDMI_CORE_SYS_VID_MODE); | ||
| 865 | DUMPCORE(HDMI_CORE_SYS_INTR_STATE); | ||
| 866 | DUMPCORE(HDMI_CORE_SYS_INTR1); | ||
| 867 | DUMPCORE(HDMI_CORE_SYS_INTR2); | ||
| 868 | DUMPCORE(HDMI_CORE_SYS_INTR3); | ||
| 869 | DUMPCORE(HDMI_CORE_SYS_INTR4); | ||
| 870 | DUMPCORE(HDMI_CORE_SYS_UMASK1); | ||
| 871 | DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); | ||
| 872 | DUMPCORE(HDMI_CORE_SYS_DE_DLY); | ||
| 873 | DUMPCORE(HDMI_CORE_SYS_DE_CTRL); | ||
| 874 | DUMPCORE(HDMI_CORE_SYS_DE_TOP); | ||
| 875 | DUMPCORE(HDMI_CORE_SYS_DE_CNTL); | ||
| 876 | DUMPCORE(HDMI_CORE_SYS_DE_CNTH); | ||
| 877 | DUMPCORE(HDMI_CORE_SYS_DE_LINL); | ||
| 878 | DUMPCORE(HDMI_CORE_SYS_DE_LINH_1); | ||
| 879 | |||
| 880 | DUMPCORE(HDMI_CORE_DDC_CMD); | ||
| 881 | DUMPCORE(HDMI_CORE_DDC_STATUS); | ||
| 882 | DUMPCORE(HDMI_CORE_DDC_ADDR); | ||
| 883 | DUMPCORE(HDMI_CORE_DDC_OFFSET); | ||
| 884 | DUMPCORE(HDMI_CORE_DDC_COUNT1); | ||
| 885 | DUMPCORE(HDMI_CORE_DDC_COUNT2); | ||
| 886 | DUMPCORE(HDMI_CORE_DDC_DATA); | ||
| 887 | DUMPCORE(HDMI_CORE_DDC_SEGM); | ||
| 888 | |||
| 889 | DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); | ||
| 890 | DUMPCORE(HDMI_CORE_AV_DPD); | ||
| 891 | DUMPCORE(HDMI_CORE_AV_PB_CTRL1); | ||
| 892 | DUMPCORE(HDMI_CORE_AV_PB_CTRL2); | ||
| 893 | DUMPCORE(HDMI_CORE_AV_AVI_TYPE); | ||
| 894 | DUMPCORE(HDMI_CORE_AV_AVI_VERS); | ||
| 895 | DUMPCORE(HDMI_CORE_AV_AVI_LEN); | ||
| 896 | DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); | ||
| 897 | |||
| 898 | for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) | ||
| 899 | DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE); | ||
| 900 | |||
| 901 | for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) | ||
| 902 | DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE); | ||
| 903 | |||
| 904 | for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) | ||
| 905 | DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE); | ||
| 906 | |||
| 907 | for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) | ||
| 908 | DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE); | ||
| 909 | |||
| 910 | for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) | ||
| 911 | DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE); | ||
| 912 | |||
| 913 | for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) | ||
| 914 | DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE); | ||
| 915 | |||
| 916 | DUMPCORE(HDMI_CORE_AV_ACR_CTRL); | ||
| 917 | DUMPCORE(HDMI_CORE_AV_FREQ_SVAL); | ||
| 918 | DUMPCORE(HDMI_CORE_AV_N_SVAL1); | ||
| 919 | DUMPCORE(HDMI_CORE_AV_N_SVAL2); | ||
| 920 | DUMPCORE(HDMI_CORE_AV_N_SVAL3); | ||
| 921 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL1); | ||
| 922 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL2); | ||
| 923 | DUMPCORE(HDMI_CORE_AV_CTS_SVAL3); | ||
| 924 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL1); | ||
| 925 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL2); | ||
| 926 | DUMPCORE(HDMI_CORE_AV_CTS_HVAL3); | ||
| 927 | DUMPCORE(HDMI_CORE_AV_AUD_MODE); | ||
| 928 | DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL); | ||
| 929 | DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS); | ||
| 930 | DUMPCORE(HDMI_CORE_AV_SWAP_I2S); | ||
| 931 | DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH); | ||
| 932 | DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP); | ||
| 933 | DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL); | ||
| 934 | DUMPCORE(HDMI_CORE_AV_I2S_CHST0); | ||
| 935 | DUMPCORE(HDMI_CORE_AV_I2S_CHST1); | ||
| 936 | DUMPCORE(HDMI_CORE_AV_I2S_CHST2); | ||
| 937 | DUMPCORE(HDMI_CORE_AV_I2S_CHST4); | ||
| 938 | DUMPCORE(HDMI_CORE_AV_I2S_CHST5); | ||
| 939 | DUMPCORE(HDMI_CORE_AV_ASRC); | ||
| 940 | DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN); | ||
| 941 | DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); | ||
| 942 | DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT); | ||
| 943 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1); | ||
| 944 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2); | ||
| 945 | DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3); | ||
| 946 | DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL); | ||
| 947 | DUMPCORE(HDMI_CORE_AV_DPD); | ||
| 948 | DUMPCORE(HDMI_CORE_AV_PB_CTRL1); | ||
| 949 | DUMPCORE(HDMI_CORE_AV_PB_CTRL2); | ||
| 950 | DUMPCORE(HDMI_CORE_AV_AVI_TYPE); | ||
| 951 | DUMPCORE(HDMI_CORE_AV_AVI_VERS); | ||
| 952 | DUMPCORE(HDMI_CORE_AV_AVI_LEN); | ||
| 953 | DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); | ||
| 954 | DUMPCORE(HDMI_CORE_AV_SPD_TYPE); | ||
| 955 | DUMPCORE(HDMI_CORE_AV_SPD_VERS); | ||
| 956 | DUMPCORE(HDMI_CORE_AV_SPD_LEN); | ||
| 957 | DUMPCORE(HDMI_CORE_AV_SPD_CHSUM); | ||
| 958 | DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE); | ||
| 959 | DUMPCORE(HDMI_CORE_AV_AUDIO_VERS); | ||
| 960 | DUMPCORE(HDMI_CORE_AV_AUDIO_LEN); | ||
| 961 | DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM); | ||
| 962 | DUMPCORE(HDMI_CORE_AV_MPEG_TYPE); | ||
| 963 | DUMPCORE(HDMI_CORE_AV_MPEG_VERS); | ||
| 964 | DUMPCORE(HDMI_CORE_AV_MPEG_LEN); | ||
| 965 | DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM); | ||
| 966 | DUMPCORE(HDMI_CORE_AV_CP_BYTE1); | ||
| 967 | DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID); | ||
| 968 | } | ||
| 969 | |||
| 970 | void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) | ||
| 971 | { | ||
| 972 | #define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ | ||
| 973 | hdmi_read_reg(hdmi_phy_base(ip_data), r)) | ||
| 974 | |||
| 975 | DUMPPHY(HDMI_TXPHY_TX_CTRL); | ||
| 976 | DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); | ||
| 977 | DUMPPHY(HDMI_TXPHY_POWER_CTRL); | ||
| 978 | DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); | ||
| 979 | } | ||
| 980 | |||
| 981 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
| 982 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 983 | void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | ||
| 984 | struct hdmi_audio_format *aud_fmt) | ||
| 985 | { | ||
| 986 | u32 r; | ||
| 987 | |||
| 988 | DSSDBG("Enter hdmi_wp_audio_config_format\n"); | ||
| 989 | |||
| 990 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG); | ||
| 991 | r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); | ||
| 992 | r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); | ||
| 993 | r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); | ||
| 994 | r = FLD_MOD(r, aud_fmt->type, 4, 4); | ||
| 995 | r = FLD_MOD(r, aud_fmt->justification, 3, 3); | ||
| 996 | r = FLD_MOD(r, aud_fmt->sample_order, 2, 2); | ||
| 997 | r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1); | ||
| 998 | r = FLD_MOD(r, aud_fmt->sample_size, 0, 0); | ||
| 999 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | ||
| 1003 | struct hdmi_audio_dma *aud_dma) | ||
| 1004 | { | ||
| 1005 | u32 r; | ||
| 1006 | |||
| 1007 | DSSDBG("Enter hdmi_wp_audio_config_dma\n"); | ||
| 1008 | |||
| 1009 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2); | ||
| 1010 | r = FLD_MOD(r, aud_dma->transfer_size, 15, 8); | ||
| 1011 | r = FLD_MOD(r, aud_dma->block_size, 7, 0); | ||
| 1012 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r); | ||
| 1013 | |||
| 1014 | r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL); | ||
| 1015 | r = FLD_MOD(r, aud_dma->mode, 9, 9); | ||
| 1016 | r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0); | ||
| 1017 | hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | ||
| 1021 | struct hdmi_core_audio_config *cfg) | ||
| 1022 | { | ||
| 1023 | u32 r; | ||
| 1024 | void __iomem *av_base = hdmi_av_base(ip_data); | ||
| 1025 | |||
| 1026 | /* audio clock recovery parameters */ | ||
| 1027 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL); | ||
| 1028 | r = FLD_MOD(r, cfg->use_mclk, 2, 2); | ||
| 1029 | r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1); | ||
| 1030 | r = FLD_MOD(r, cfg->cts_mode, 0, 0); | ||
| 1031 | hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r); | ||
| 1032 | |||
| 1033 | REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0); | ||
| 1034 | REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0); | ||
| 1035 | REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0); | ||
| 1036 | |||
| 1037 | if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) { | ||
| 1038 | REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0); | ||
| 1039 | REG_FLD_MOD(av_base, | ||
| 1040 | HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0); | ||
| 1041 | REG_FLD_MOD(av_base, | ||
| 1042 | HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0); | ||
| 1043 | } else { | ||
| 1044 | /* | ||
| 1045 | * HDMI IP uses this configuration to divide the MCLK to | ||
| 1046 | * update CTS value. | ||
| 1047 | */ | ||
| 1048 | REG_FLD_MOD(av_base, | ||
| 1049 | HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0); | ||
| 1050 | |||
| 1051 | /* Configure clock for audio packets */ | ||
| 1052 | REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1, | ||
| 1053 | cfg->aud_par_busclk, 7, 0); | ||
| 1054 | REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2, | ||
| 1055 | (cfg->aud_par_busclk >> 8), 7, 0); | ||
| 1056 | REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3, | ||
| 1057 | (cfg->aud_par_busclk >> 16), 7, 0); | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | /* Override of SPDIF sample frequency with value in I2S_CHST4 */ | ||
| 1061 | REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, | ||
| 1062 | cfg->fs_override, 1, 1); | ||
| 1063 | |||
| 1064 | /* I2S parameters */ | ||
| 1065 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4, | ||
| 1066 | cfg->freq_sample, 3, 0); | ||
| 1067 | |||
| 1068 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); | ||
| 1069 | r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7); | ||
| 1070 | r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); | ||
| 1071 | r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5); | ||
| 1072 | r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); | ||
| 1073 | r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3); | ||
| 1074 | r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); | ||
| 1075 | r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); | ||
| 1076 | r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); | ||
| 1077 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); | ||
| 1078 | |||
| 1079 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5); | ||
| 1080 | r = FLD_MOD(r, cfg->freq_sample, 7, 4); | ||
| 1081 | r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1); | ||
| 1082 | r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0); | ||
| 1083 | hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r); | ||
| 1084 | |||
| 1085 | REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, | ||
| 1086 | cfg->i2s_cfg.in_length_bits, 3, 0); | ||
| 1087 | |||
| 1088 | /* Audio channels and mode parameters */ | ||
| 1089 | REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1); | ||
| 1090 | r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE); | ||
| 1091 | r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4); | ||
| 1092 | r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3); | ||
| 1093 | r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); | ||
| 1094 | r = FLD_MOD(r, cfg->en_spdif, 1, 1); | ||
| 1095 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | ||
| 1099 | struct hdmi_core_infoframe_audio *info_aud) | ||
| 1100 | { | ||
| 1101 | u8 val; | ||
| 1102 | u8 sum = 0, checksum = 0; | ||
| 1103 | void __iomem *av_base = hdmi_av_base(ip_data); | ||
| 1104 | |||
| 1105 | /* | ||
| 1106 | * Set audio info frame type, version and length as | ||
| 1107 | * described in HDMI 1.4a Section 8.2.2 specification. | ||
| 1108 | * Checksum calculation is defined in Section 5.3.5. | ||
| 1109 | */ | ||
| 1110 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84); | ||
| 1111 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01); | ||
| 1112 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); | ||
| 1113 | sum += 0x84 + 0x001 + 0x00a; | ||
| 1114 | |||
| 1115 | val = (info_aud->db1_coding_type << 4) | ||
| 1116 | | (info_aud->db1_channel_count - 1); | ||
| 1117 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val); | ||
| 1118 | sum += val; | ||
| 1119 | |||
| 1120 | val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; | ||
| 1121 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val); | ||
| 1122 | sum += val; | ||
| 1123 | |||
| 1124 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00); | ||
| 1125 | |||
| 1126 | val = info_aud->db4_channel_alloc; | ||
| 1127 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val); | ||
| 1128 | sum += val; | ||
| 1129 | |||
| 1130 | val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); | ||
| 1131 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val); | ||
| 1132 | sum += val; | ||
| 1133 | |||
| 1134 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); | ||
| 1135 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); | ||
| 1136 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00); | ||
| 1137 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00); | ||
| 1138 | hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00); | ||
| 1139 | |||
| 1140 | checksum = 0x100 - sum; | ||
| 1141 | hdmi_write_reg(av_base, | ||
| 1142 | HDMI_CORE_AV_AUDIO_CHSUM, checksum); | ||
| 1143 | |||
| 1144 | /* | ||
| 1145 | * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing | ||
| 1146 | * is available. | ||
| 1147 | */ | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, | ||
| 1151 | u32 sample_freq, u32 *n, u32 *cts) | ||
| 1152 | { | ||
| 1153 | u32 r; | ||
| 1154 | u32 deep_color = 0; | ||
| 1155 | u32 pclk = ip_data->cfg.timings.timings.pixel_clock; | ||
| 1156 | |||
| 1157 | if (n == NULL || cts == NULL) | ||
| 1158 | return -EINVAL; | ||
| 1159 | /* | ||
| 1160 | * Obtain current deep color configuration. This needed | ||
| 1161 | * to calculate the TMDS clock based on the pixel clock. | ||
| 1162 | */ | ||
| 1163 | r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0); | ||
| 1164 | switch (r) { | ||
| 1165 | case 1: /* No deep color selected */ | ||
| 1166 | deep_color = 100; | ||
| 1167 | break; | ||
| 1168 | case 2: /* 10-bit deep color selected */ | ||
| 1169 | deep_color = 125; | ||
| 1170 | break; | ||
| 1171 | case 3: /* 12-bit deep color selected */ | ||
| 1172 | deep_color = 150; | ||
| 1173 | break; | ||
| 1174 | default: | ||
| 1175 | return -EINVAL; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | switch (sample_freq) { | ||
| 1179 | case 32000: | ||
| 1180 | if ((deep_color == 125) && ((pclk == 54054) | ||
| 1181 | || (pclk == 74250))) | ||
| 1182 | *n = 8192; | ||
| 1183 | else | ||
| 1184 | *n = 4096; | ||
| 1185 | break; | ||
| 1186 | case 44100: | ||
| 1187 | *n = 6272; | ||
| 1188 | break; | ||
| 1189 | case 48000: | ||
| 1190 | if ((deep_color == 125) && ((pclk == 54054) | ||
| 1191 | || (pclk == 74250))) | ||
| 1192 | *n = 8192; | ||
| 1193 | else | ||
| 1194 | *n = 6144; | ||
| 1195 | break; | ||
| 1196 | default: | ||
| 1197 | *n = 0; | ||
| 1198 | return -EINVAL; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ | ||
| 1202 | *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); | ||
| 1203 | |||
| 1204 | return 0; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, | ||
| 1208 | struct snd_pcm_substream *substream, int cmd, | ||
| 1209 | struct snd_soc_dai *dai) | ||
| 1210 | { | ||
| 1211 | int err = 0; | ||
| 1212 | switch (cmd) { | ||
| 1213 | case SNDRV_PCM_TRIGGER_START: | ||
| 1214 | case SNDRV_PCM_TRIGGER_RESUME: | ||
| 1215 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
| 1216 | REG_FLD_MOD(hdmi_av_base(ip_data), | ||
| 1217 | HDMI_CORE_AV_AUD_MODE, 1, 0, 0); | ||
| 1218 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
| 1219 | HDMI_WP_AUDIO_CTRL, 1, 31, 31); | ||
| 1220 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
| 1221 | HDMI_WP_AUDIO_CTRL, 1, 30, 30); | ||
| 1222 | break; | ||
| 1223 | |||
| 1224 | case SNDRV_PCM_TRIGGER_STOP: | ||
| 1225 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
| 1226 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
| 1227 | REG_FLD_MOD(hdmi_av_base(ip_data), | ||
| 1228 | HDMI_CORE_AV_AUD_MODE, 0, 0, 0); | ||
| 1229 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
| 1230 | HDMI_WP_AUDIO_CTRL, 0, 30, 30); | ||
| 1231 | REG_FLD_MOD(hdmi_wp_base(ip_data), | ||
| 1232 | HDMI_WP_AUDIO_CTRL, 0, 31, 31); | ||
| 1233 | break; | ||
| 1234 | default: | ||
| 1235 | err = -EINVAL; | ||
| 1236 | } | ||
| 1237 | return err; | ||
| 1238 | } | ||
| 1239 | #endif | ||
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h index c885f9cb0659..204095632d27 100644 --- a/drivers/video/omap2/dss/hdmi.h +++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * hdmi.h | 2 | * ti_hdmi_4xxx_ip.h |
| 3 | * | 3 | * |
| 4 | * HDMI driver definition for TI OMAP4 processors. | 4 | * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | 6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ |
| 7 | * | 7 | * |
| @@ -18,202 +18,177 @@ | |||
| 18 | * this program. If not, see <http://www.gnu.org/licenses/>. | 18 | * this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #ifndef _OMAP4_DSS_HDMI_H_ | 21 | #ifndef _HDMI_TI_4xxx_H_ |
| 22 | #define _OMAP4_DSS_HDMI_H_ | 22 | #define _HDMI_TI_4xxx_H_ |
| 23 | 23 | ||
| 24 | #include <linux/string.h> | 24 | #include <linux/string.h> |
| 25 | #include <video/omapdss.h> | 25 | #include <video/omapdss.h> |
| 26 | 26 | #include "ti_hdmi.h" | |
| 27 | #define HDMI_WP 0x0 | 27 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ |
| 28 | #define HDMI_CORE_SYS 0x400 | 28 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) |
| 29 | #define HDMI_CORE_AV 0x900 | 29 | #include <sound/soc.h> |
| 30 | #define HDMI_PLLCTRL 0x200 | 30 | #include <sound/pcm_params.h> |
| 31 | #define HDMI_PHY 0x300 | 31 | #endif |
| 32 | |||
| 33 | struct hdmi_reg { u16 idx; }; | ||
| 34 | |||
| 35 | #define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) | ||
| 36 | 32 | ||
| 37 | /* HDMI Wrapper */ | 33 | /* HDMI Wrapper */ |
| 38 | #define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) | 34 | |
| 39 | 35 | #define HDMI_WP_REVISION 0x0 | |
| 40 | #define HDMI_WP_REVISION HDMI_WP_REG(0x0) | 36 | #define HDMI_WP_SYSCONFIG 0x10 |
| 41 | #define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) | 37 | #define HDMI_WP_IRQSTATUS_RAW 0x24 |
| 42 | #define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) | 38 | #define HDMI_WP_IRQSTATUS 0x28 |
| 43 | #define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) | 39 | #define HDMI_WP_PWR_CTRL 0x40 |
| 44 | #define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) | 40 | #define HDMI_WP_IRQENABLE_SET 0x2C |
| 45 | #define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) | 41 | #define HDMI_WP_VIDEO_CFG 0x50 |
| 46 | #define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) | 42 | #define HDMI_WP_VIDEO_SIZE 0x60 |
| 47 | #define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) | 43 | #define HDMI_WP_VIDEO_TIMING_H 0x68 |
| 48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) | 44 | #define HDMI_WP_VIDEO_TIMING_V 0x6C |
| 49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) | 45 | #define HDMI_WP_WP_CLK 0x70 |
| 50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) | 46 | #define HDMI_WP_AUDIO_CFG 0x80 |
| 51 | #define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80) | 47 | #define HDMI_WP_AUDIO_CFG2 0x84 |
| 52 | #define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84) | 48 | #define HDMI_WP_AUDIO_CTRL 0x88 |
| 53 | #define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88) | 49 | #define HDMI_WP_AUDIO_DATA 0x8C |
| 54 | #define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C) | ||
| 55 | 50 | ||
| 56 | /* HDMI IP Core System */ | 51 | /* HDMI IP Core System */ |
| 57 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) | 52 | |
| 58 | 53 | #define HDMI_CORE_SYS_VND_IDL 0x0 | |
| 59 | #define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) | 54 | #define HDMI_CORE_SYS_DEV_IDL 0x8 |
| 60 | #define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) | 55 | #define HDMI_CORE_SYS_DEV_IDH 0xC |
| 61 | #define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) | 56 | #define HDMI_CORE_SYS_DEV_REV 0x10 |
| 62 | #define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) | 57 | #define HDMI_CORE_SYS_SRST 0x14 |
| 63 | #define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) | 58 | #define HDMI_CORE_CTRL1 0x20 |
| 64 | #define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) | 59 | #define HDMI_CORE_SYS_SYS_STAT 0x24 |
| 65 | #define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) | 60 | #define HDMI_CORE_SYS_VID_ACEN 0x124 |
| 66 | #define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) | 61 | #define HDMI_CORE_SYS_VID_MODE 0x128 |
| 67 | #define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) | 62 | #define HDMI_CORE_SYS_INTR_STATE 0x1C0 |
| 68 | #define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) | 63 | #define HDMI_CORE_SYS_INTR1 0x1C4 |
| 69 | #define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) | 64 | #define HDMI_CORE_SYS_INTR2 0x1C8 |
| 70 | #define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) | 65 | #define HDMI_CORE_SYS_INTR3 0x1CC |
| 71 | #define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) | 66 | #define HDMI_CORE_SYS_INTR4 0x1D0 |
| 72 | #define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) | 67 | #define HDMI_CORE_SYS_UMASK1 0x1D4 |
| 73 | #define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) | 68 | #define HDMI_CORE_SYS_TMDS_CTRL 0x208 |
| 74 | #define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) | 69 | #define HDMI_CORE_SYS_DE_DLY 0xC8 |
| 75 | #define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) | 70 | #define HDMI_CORE_SYS_DE_CTRL 0xCC |
| 76 | #define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) | 71 | #define HDMI_CORE_SYS_DE_TOP 0xD0 |
| 77 | #define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) | 72 | #define HDMI_CORE_SYS_DE_CNTL 0xD8 |
| 78 | #define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) | 73 | #define HDMI_CORE_SYS_DE_CNTH 0xDC |
| 79 | #define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) | 74 | #define HDMI_CORE_SYS_DE_LINL 0xE0 |
| 80 | #define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) | 75 | #define HDMI_CORE_SYS_DE_LINH_1 0xE4 |
| 81 | #define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) | ||
| 82 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 | 76 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 |
| 83 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 | 77 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 |
| 84 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 | 78 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 |
| 85 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 | 79 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 |
| 86 | 80 | ||
| 87 | /* HDMI DDC E-DID */ | 81 | /* HDMI DDC E-DID */ |
| 88 | #define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) | 82 | #define HDMI_CORE_DDC_CMD 0x3CC |
| 89 | #define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) | 83 | #define HDMI_CORE_DDC_STATUS 0x3C8 |
| 90 | #define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) | 84 | #define HDMI_CORE_DDC_ADDR 0x3B4 |
| 91 | #define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) | 85 | #define HDMI_CORE_DDC_OFFSET 0x3BC |
| 92 | #define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) | 86 | #define HDMI_CORE_DDC_COUNT1 0x3C0 |
| 93 | #define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) | 87 | #define HDMI_CORE_DDC_COUNT2 0x3C4 |
| 94 | #define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) | 88 | #define HDMI_CORE_DDC_DATA 0x3D0 |
| 95 | #define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) | 89 | #define HDMI_CORE_DDC_SEGM 0x3B8 |
| 96 | 90 | ||
| 97 | /* HDMI IP Core Audio Video */ | 91 | /* HDMI IP Core Audio Video */ |
| 98 | #define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) | 92 | |
| 99 | 93 | #define HDMI_CORE_AV_HDMI_CTRL 0xBC | |
| 100 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | 94 | #define HDMI_CORE_AV_DPD 0xF4 |
| 101 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | 95 | #define HDMI_CORE_AV_PB_CTRL1 0xF8 |
| 102 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | 96 | #define HDMI_CORE_AV_PB_CTRL2 0xFC |
| 103 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | 97 | #define HDMI_CORE_AV_AVI_TYPE 0x100 |
| 104 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | 98 | #define HDMI_CORE_AV_AVI_VERS 0x104 |
| 105 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | 99 | #define HDMI_CORE_AV_AVI_LEN 0x108 |
| 106 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | 100 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C |
| 107 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | 101 | #define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110) |
| 108 | #define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) | 102 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15 |
| 109 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) | 103 | #define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190) |
| 110 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) | 104 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27 |
| 111 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | 105 | #define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210) |
| 112 | #define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210) | 106 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10 |
| 113 | #define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10) | 107 | #define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290) |
| 114 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) | 108 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27 |
| 115 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | 109 | #define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300) |
| 116 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) | 110 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31 |
| 117 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | 111 | #define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380) |
| 118 | #define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) | 112 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31 |
| 119 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | 113 | #define HDMI_CORE_AV_ACR_CTRL 0x4 |
| 120 | #define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) | 114 | #define HDMI_CORE_AV_FREQ_SVAL 0x8 |
| 121 | #define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) | 115 | #define HDMI_CORE_AV_N_SVAL1 0xC |
| 122 | #define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) | 116 | #define HDMI_CORE_AV_N_SVAL2 0x10 |
| 123 | #define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) | 117 | #define HDMI_CORE_AV_N_SVAL3 0x14 |
| 124 | #define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) | 118 | #define HDMI_CORE_AV_CTS_SVAL1 0x18 |
| 125 | #define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) | 119 | #define HDMI_CORE_AV_CTS_SVAL2 0x1C |
| 126 | #define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) | 120 | #define HDMI_CORE_AV_CTS_SVAL3 0x20 |
| 127 | #define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) | 121 | #define HDMI_CORE_AV_CTS_HVAL1 0x24 |
| 128 | #define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) | 122 | #define HDMI_CORE_AV_CTS_HVAL2 0x28 |
| 129 | #define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) | 123 | #define HDMI_CORE_AV_CTS_HVAL3 0x2C |
| 130 | #define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) | 124 | #define HDMI_CORE_AV_AUD_MODE 0x50 |
| 131 | #define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) | 125 | #define HDMI_CORE_AV_SPDIF_CTRL 0x54 |
| 132 | #define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) | 126 | #define HDMI_CORE_AV_HW_SPDIF_FS 0x60 |
| 133 | #define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) | 127 | #define HDMI_CORE_AV_SWAP_I2S 0x64 |
| 134 | #define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) | 128 | #define HDMI_CORE_AV_SPDIF_ERTH 0x6C |
| 135 | #define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) | 129 | #define HDMI_CORE_AV_I2S_IN_MAP 0x70 |
| 136 | #define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) | 130 | #define HDMI_CORE_AV_I2S_IN_CTRL 0x74 |
| 137 | #define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) | 131 | #define HDMI_CORE_AV_I2S_CHST0 0x78 |
| 138 | #define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) | 132 | #define HDMI_CORE_AV_I2S_CHST1 0x7C |
| 139 | #define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) | 133 | #define HDMI_CORE_AV_I2S_CHST2 0x80 |
| 140 | #define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) | 134 | #define HDMI_CORE_AV_I2S_CHST4 0x84 |
| 141 | #define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) | 135 | #define HDMI_CORE_AV_I2S_CHST5 0x88 |
| 142 | #define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) | 136 | #define HDMI_CORE_AV_ASRC 0x8C |
| 143 | #define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) | 137 | #define HDMI_CORE_AV_I2S_IN_LEN 0x90 |
| 144 | #define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) | 138 | #define HDMI_CORE_AV_HDMI_CTRL 0xBC |
| 145 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | 139 | #define HDMI_CORE_AV_AUDO_TXSTAT 0xC0 |
| 146 | #define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) | 140 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC |
| 147 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) | 141 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0 |
| 148 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) | 142 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4 |
| 149 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) | 143 | #define HDMI_CORE_AV_TEST_TXCTRL 0xF0 |
| 150 | #define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) | 144 | #define HDMI_CORE_AV_DPD 0xF4 |
| 151 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | 145 | #define HDMI_CORE_AV_PB_CTRL1 0xF8 |
| 152 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | 146 | #define HDMI_CORE_AV_PB_CTRL2 0xFC |
| 153 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | 147 | #define HDMI_CORE_AV_AVI_TYPE 0x100 |
| 154 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | 148 | #define HDMI_CORE_AV_AVI_VERS 0x104 |
| 155 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | 149 | #define HDMI_CORE_AV_AVI_LEN 0x108 |
| 156 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | 150 | #define HDMI_CORE_AV_AVI_CHSUM 0x10C |
| 157 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | 151 | #define HDMI_CORE_AV_SPD_TYPE 0x180 |
| 158 | #define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) | 152 | #define HDMI_CORE_AV_SPD_VERS 0x184 |
| 159 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) | 153 | #define HDMI_CORE_AV_SPD_LEN 0x188 |
| 160 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) | 154 | #define HDMI_CORE_AV_SPD_CHSUM 0x18C |
| 161 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) | 155 | #define HDMI_CORE_AV_AUDIO_TYPE 0x200 |
| 162 | #define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200) | 156 | #define HDMI_CORE_AV_AUDIO_VERS 0x204 |
| 163 | #define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204) | 157 | #define HDMI_CORE_AV_AUDIO_LEN 0x208 |
| 164 | #define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208) | 158 | #define HDMI_CORE_AV_AUDIO_CHSUM 0x20C |
| 165 | #define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C) | 159 | #define HDMI_CORE_AV_MPEG_TYPE 0x280 |
| 166 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) | 160 | #define HDMI_CORE_AV_MPEG_VERS 0x284 |
| 167 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) | 161 | #define HDMI_CORE_AV_MPEG_LEN 0x288 |
| 168 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) | 162 | #define HDMI_CORE_AV_MPEG_CHSUM 0x28C |
| 169 | #define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) | 163 | #define HDMI_CORE_AV_CP_BYTE1 0x37C |
| 170 | #define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) | 164 | #define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC |
| 171 | #define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) | ||
| 172 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 | 165 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 |
| 173 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 | 166 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 |
| 174 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 | 167 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 |
| 175 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 | 168 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 |
| 176 | 169 | ||
| 177 | /* PLL */ | 170 | /* PLL */ |
| 178 | #define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) | ||
| 179 | 171 | ||
| 180 | #define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) | 172 | #define PLLCTRL_PLL_CONTROL 0x0 |
| 181 | #define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) | 173 | #define PLLCTRL_PLL_STATUS 0x4 |
| 182 | #define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) | 174 | #define PLLCTRL_PLL_GO 0x8 |
| 183 | #define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) | 175 | #define PLLCTRL_CFG1 0xC |
| 184 | #define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) | 176 | #define PLLCTRL_CFG2 0x10 |
| 185 | #define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) | 177 | #define PLLCTRL_CFG3 0x14 |
| 186 | #define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) | 178 | #define PLLCTRL_CFG4 0x20 |
| 187 | 179 | ||
| 188 | /* HDMI PHY */ | 180 | /* HDMI PHY */ |
| 189 | #define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) | ||
| 190 | |||
| 191 | #define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) | ||
| 192 | #define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) | ||
| 193 | #define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) | ||
| 194 | #define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) | ||
| 195 | |||
| 196 | /* HDMI EDID Length */ | ||
| 197 | #define HDMI_EDID_MAX_LENGTH 256 | ||
| 198 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
| 199 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
| 200 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
| 201 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
| 202 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
| 203 | 181 | ||
| 204 | #define OMAP_HDMI_TIMINGS_NB 34 | 182 | #define HDMI_TXPHY_TX_CTRL 0x0 |
| 183 | #define HDMI_TXPHY_DIGITAL_CTRL 0x4 | ||
| 184 | #define HDMI_TXPHY_POWER_CTRL 0x8 | ||
| 185 | #define HDMI_TXPHY_PAD_CFG_CTRL 0xC | ||
| 205 | 186 | ||
| 206 | #define REG_FLD_MOD(idx, val, start, end) \ | 187 | #define REG_FLD_MOD(base, idx, val, start, end) \ |
| 207 | hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) | 188 | hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\ |
| 208 | #define REG_GET(idx, start, end) \ | 189 | val, start, end)) |
| 209 | FLD_GET(hdmi_read_reg(idx), start, end) | 190 | #define REG_GET(base, idx, start, end) \ |
| 210 | 191 | FLD_GET(hdmi_read_reg(base, idx), start, end) | |
| 211 | /* HDMI timing structure */ | ||
| 212 | struct hdmi_timings { | ||
| 213 | struct omap_video_timings timings; | ||
| 214 | int vsync_pol; | ||
| 215 | int hsync_pol; | ||
| 216 | }; | ||
| 217 | 192 | ||
| 218 | enum hdmi_phy_pwr { | 193 | enum hdmi_phy_pwr { |
| 219 | HDMI_PHYPWRCMD_OFF = 0, | 194 | HDMI_PHYPWRCMD_OFF = 0, |
| @@ -221,20 +196,6 @@ enum hdmi_phy_pwr { | |||
| 221 | HDMI_PHYPWRCMD_TXON = 2 | 196 | HDMI_PHYPWRCMD_TXON = 2 |
| 222 | }; | 197 | }; |
| 223 | 198 | ||
| 224 | enum hdmi_pll_pwr { | ||
| 225 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
| 226 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
| 227 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
| 228 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
| 229 | }; | ||
| 230 | |||
| 231 | enum hdmi_clk_refsel { | ||
| 232 | HDMI_REFSEL_PCLK = 0, | ||
| 233 | HDMI_REFSEL_REF1 = 1, | ||
| 234 | HDMI_REFSEL_REF2 = 2, | ||
| 235 | HDMI_REFSEL_SYSCLK = 3 | ||
| 236 | }; | ||
| 237 | |||
| 238 | enum hdmi_core_inputbus_width { | 199 | enum hdmi_core_inputbus_width { |
| 239 | HDMI_INPUT_8BIT = 0, | 200 | HDMI_INPUT_8BIT = 0, |
| 240 | HDMI_INPUT_10BIT = 1, | 201 | HDMI_INPUT_10BIT = 1, |
| @@ -263,11 +224,6 @@ enum hdmi_core_packet_mode { | |||
| 263 | HDMI_PACKETMODE48BITPERPIXEL = 7 | 224 | HDMI_PACKETMODE48BITPERPIXEL = 7 |
| 264 | }; | 225 | }; |
| 265 | 226 | ||
| 266 | enum hdmi_core_hdmi_dvi { | ||
| 267 | HDMI_DVI = 0, | ||
| 268 | HDMI_HDMI = 1 | ||
| 269 | }; | ||
| 270 | |||
| 271 | enum hdmi_core_tclkselclkmult { | 227 | enum hdmi_core_tclkselclkmult { |
| 272 | HDMI_FPLL05IDCK = 0, | 228 | HDMI_FPLL05IDCK = 0, |
| 273 | HDMI_FPLL10IDCK = 1, | 229 | HDMI_FPLL10IDCK = 1, |
| @@ -495,40 +451,40 @@ struct hdmi_core_video_config { | |||
| 495 | * details about infoframe databytes | 451 | * details about infoframe databytes |
| 496 | */ | 452 | */ |
| 497 | struct hdmi_core_infoframe_avi { | 453 | struct hdmi_core_infoframe_avi { |
| 454 | /* Y0, Y1 rgb,yCbCr */ | ||
| 498 | u8 db1_format; | 455 | u8 db1_format; |
| 499 | /* Y0, Y1 rgb,yCbCr */ | 456 | /* A0 Active information Present */ |
| 500 | u8 db1_active_info; | 457 | u8 db1_active_info; |
| 501 | /* A0 Active information Present */ | 458 | /* B0, B1 Bar info data valid */ |
| 502 | u8 db1_bar_info_dv; | 459 | u8 db1_bar_info_dv; |
| 503 | /* B0, B1 Bar info data valid */ | 460 | /* S0, S1 scan information */ |
| 504 | u8 db1_scan_info; | 461 | u8 db1_scan_info; |
| 505 | /* S0, S1 scan information */ | 462 | /* C0, C1 colorimetry */ |
| 506 | u8 db2_colorimetry; | 463 | u8 db2_colorimetry; |
| 507 | /* C0, C1 colorimetry */ | 464 | /* M0, M1 Aspect ratio (4:3, 16:9) */ |
| 508 | u8 db2_aspect_ratio; | 465 | u8 db2_aspect_ratio; |
| 509 | /* M0, M1 Aspect ratio (4:3, 16:9) */ | 466 | /* R0...R3 Active format aspect ratio */ |
| 510 | u8 db2_active_fmt_ar; | 467 | u8 db2_active_fmt_ar; |
| 511 | /* R0...R3 Active format aspect ratio */ | 468 | /* ITC IT content. */ |
| 512 | u8 db3_itc; | 469 | u8 db3_itc; |
| 513 | /* ITC IT content. */ | 470 | /* EC0, EC1, EC2 Extended colorimetry */ |
| 514 | u8 db3_ec; | 471 | u8 db3_ec; |
| 515 | /* EC0, EC1, EC2 Extended colorimetry */ | 472 | /* Q1, Q0 Quantization range */ |
| 516 | u8 db3_q_range; | 473 | u8 db3_q_range; |
| 517 | /* Q1, Q0 Quantization range */ | 474 | /* SC1, SC0 Non-uniform picture scaling */ |
| 518 | u8 db3_nup_scaling; | 475 | u8 db3_nup_scaling; |
| 519 | /* SC1, SC0 Non-uniform picture scaling */ | 476 | /* VIC0..6 Video format identification */ |
| 520 | u8 db4_videocode; | 477 | u8 db4_videocode; |
| 521 | /* VIC0..6 Video format identification */ | 478 | /* PR0..PR3 Pixel repetition factor */ |
| 522 | u8 db5_pixel_repeat; | 479 | u8 db5_pixel_repeat; |
| 523 | /* PR0..PR3 Pixel repetition factor */ | 480 | /* Line number end of top bar */ |
| 524 | u16 db6_7_line_eoftop; | 481 | u16 db6_7_line_eoftop; |
| 525 | /* Line number end of top bar */ | 482 | /* Line number start of bottom bar */ |
| 526 | u16 db8_9_line_sofbottom; | 483 | u16 db8_9_line_sofbottom; |
| 527 | /* Line number start of bottom bar */ | 484 | /* Pixel number end of left bar */ |
| 528 | u16 db10_11_pixel_eofleft; | 485 | u16 db10_11_pixel_eofleft; |
| 529 | /* Pixel number end of left bar */ | 486 | /* Pixel number start of right bar */ |
| 530 | u16 db12_13_pixel_sofright; | 487 | u16 db12_13_pixel_sofright; |
| 531 | /* Pixel number start of right bar */ | ||
| 532 | }; | 488 | }; |
| 533 | /* | 489 | /* |
| 534 | * Refer to section 8.2 in HDMI 1.3 specification for | 490 | * Refer to section 8.2 in HDMI 1.3 specification for |
| @@ -568,17 +524,6 @@ struct hdmi_video_interface { | |||
| 568 | int tm; /* Timing mode */ | 524 | int tm; /* Timing mode */ |
| 569 | }; | 525 | }; |
| 570 | 526 | ||
| 571 | struct hdmi_cm { | ||
| 572 | int code; | ||
| 573 | int mode; | ||
| 574 | }; | ||
| 575 | |||
| 576 | struct hdmi_config { | ||
| 577 | struct hdmi_timings timings; | ||
| 578 | u16 interlace; | ||
| 579 | struct hdmi_cm cm; | ||
| 580 | }; | ||
| 581 | |||
| 582 | struct hdmi_audio_format { | 527 | struct hdmi_audio_format { |
| 583 | enum hdmi_stereo_channels stereo_channels; | 528 | enum hdmi_stereo_channels stereo_channels; |
| 584 | u8 active_chnnls_msk; | 529 | u8 active_chnnls_msk; |
| @@ -628,4 +573,21 @@ struct hdmi_core_audio_config { | |||
| 628 | bool en_parallel_aud_input; | 573 | bool en_parallel_aud_input; |
| 629 | bool en_spdif; | 574 | bool en_spdif; |
| 630 | }; | 575 | }; |
| 576 | |||
| 577 | #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ | ||
| 578 | defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) | ||
| 579 | int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, | ||
| 580 | struct snd_pcm_substream *substream, int cmd, | ||
| 581 | struct snd_soc_dai *dai); | ||
| 582 | int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, | ||
| 583 | u32 sample_freq, u32 *n, u32 *cts); | ||
| 584 | void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, | ||
| 585 | struct hdmi_core_infoframe_audio *info_aud); | ||
| 586 | void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, | ||
| 587 | struct hdmi_core_audio_config *cfg); | ||
| 588 | void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, | ||
| 589 | struct hdmi_audio_dma *aud_dma); | ||
| 590 | void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data, | ||
| 591 | struct hdmi_audio_format *aud_fmt); | ||
| 592 | #endif | ||
| 631 | #endif | 593 | #endif |
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 173c66430dad..7533458ba4d2 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
| @@ -295,7 +295,6 @@ static struct { | |||
| 295 | u32 wss_data; | 295 | u32 wss_data; |
| 296 | struct regulator *vdda_dac_reg; | 296 | struct regulator *vdda_dac_reg; |
| 297 | 297 | ||
| 298 | struct clk *tv_clk; | ||
| 299 | struct clk *tv_dac_clk; | 298 | struct clk *tv_dac_clk; |
| 300 | } venc; | 299 | } venc; |
| 301 | 300 | ||
| @@ -464,9 +463,11 @@ static void venc_power_off(struct omap_dss_device *dssdev) | |||
| 464 | regulator_disable(venc.vdda_dac_reg); | 463 | regulator_disable(venc.vdda_dac_reg); |
| 465 | } | 464 | } |
| 466 | 465 | ||
| 467 | 466 | unsigned long venc_get_pixel_clock(void) | |
| 468 | 467 | { | |
| 469 | 468 | /* VENC Pixel Clock in Mhz */ | |
| 469 | return 13500000; | ||
| 470 | } | ||
| 470 | 471 | ||
| 471 | /* driver */ | 472 | /* driver */ |
| 472 | static int venc_panel_probe(struct omap_dss_device *dssdev) | 473 | static int venc_panel_probe(struct omap_dss_device *dssdev) |
| @@ -732,22 +733,10 @@ static int venc_get_clocks(struct platform_device *pdev) | |||
| 732 | { | 733 | { |
| 733 | struct clk *clk; | 734 | struct clk *clk; |
| 734 | 735 | ||
| 735 | clk = clk_get(&pdev->dev, "fck"); | ||
| 736 | if (IS_ERR(clk)) { | ||
| 737 | DSSERR("can't get fck\n"); | ||
| 738 | return PTR_ERR(clk); | ||
| 739 | } | ||
| 740 | |||
| 741 | venc.tv_clk = clk; | ||
| 742 | |||
| 743 | if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { | 736 | if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { |
| 744 | if (cpu_is_omap34xx() || cpu_is_omap3630()) | 737 | clk = clk_get(&pdev->dev, "tv_dac_clk"); |
| 745 | clk = clk_get(&pdev->dev, "dss_96m_fck"); | ||
| 746 | else | ||
| 747 | clk = clk_get(&pdev->dev, "tv_dac_clk"); | ||
| 748 | if (IS_ERR(clk)) { | 738 | if (IS_ERR(clk)) { |
| 749 | DSSERR("can't get tv_dac_clk\n"); | 739 | DSSERR("can't get tv_dac_clk\n"); |
| 750 | clk_put(venc.tv_clk); | ||
| 751 | return PTR_ERR(clk); | 740 | return PTR_ERR(clk); |
| 752 | } | 741 | } |
| 753 | } else { | 742 | } else { |
| @@ -761,8 +750,6 @@ static int venc_get_clocks(struct platform_device *pdev) | |||
| 761 | 750 | ||
| 762 | static void venc_put_clocks(void) | 751 | static void venc_put_clocks(void) |
| 763 | { | 752 | { |
| 764 | if (venc.tv_clk) | ||
| 765 | clk_put(venc.tv_clk); | ||
| 766 | if (venc.tv_dac_clk) | 753 | if (venc.tv_dac_clk) |
| 767 | clk_put(venc.tv_dac_clk); | 754 | clk_put(venc.tv_dac_clk); |
| 768 | } | 755 | } |
| @@ -838,7 +825,6 @@ static int venc_runtime_suspend(struct device *dev) | |||
| 838 | { | 825 | { |
| 839 | if (venc.tv_dac_clk) | 826 | if (venc.tv_dac_clk) |
| 840 | clk_disable(venc.tv_dac_clk); | 827 | clk_disable(venc.tv_dac_clk); |
| 841 | clk_disable(venc.tv_clk); | ||
| 842 | 828 | ||
| 843 | dispc_runtime_put(); | 829 | dispc_runtime_put(); |
| 844 | dss_runtime_put(); | 830 | dss_runtime_put(); |
| @@ -858,7 +844,6 @@ static int venc_runtime_resume(struct device *dev) | |||
| 858 | if (r < 0) | 844 | if (r < 0) |
| 859 | goto err_get_dispc; | 845 | goto err_get_dispc; |
| 860 | 846 | ||
| 861 | clk_enable(venc.tv_clk); | ||
| 862 | if (venc.tv_dac_clk) | 847 | if (venc.tv_dac_clk) |
| 863 | clk_enable(venc.tv_dac_clk); | 848 | clk_enable(venc.tv_dac_clk); |
| 864 | 849 | ||
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index aa33386c81ff..83d3fe7ec9ae 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | menuconfig FB_OMAP2 | 1 | menuconfig FB_OMAP2 |
| 2 | tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ frame buffer support" |
| 3 | depends on FB && OMAP2_DSS | 3 | depends on FB && OMAP2_DSS |
| 4 | 4 | ||
| 5 | select OMAP2_VRAM | 5 | select OMAP2_VRAM |
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 6b1ac23dbbd3..df7bcce5b107 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
| 28 | #include <linux/omapfb.h> | 28 | #include <linux/omapfb.h> |
| 29 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
| 30 | #include <linux/export.h> | ||
| 30 | 31 | ||
| 31 | #include <video/omapdss.h> | 32 | #include <video/omapdss.h> |
| 32 | #include <plat/vrfb.h> | 33 | #include <plat/vrfb.h> |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 602b71a92d3c..70aa47de7146 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
| @@ -808,19 +808,15 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var, | |||
| 808 | static void omapfb_calc_addr(const struct omapfb_info *ofbi, | 808 | static void omapfb_calc_addr(const struct omapfb_info *ofbi, |
| 809 | const struct fb_var_screeninfo *var, | 809 | const struct fb_var_screeninfo *var, |
| 810 | const struct fb_fix_screeninfo *fix, | 810 | const struct fb_fix_screeninfo *fix, |
| 811 | int rotation, u32 *paddr, void __iomem **vaddr) | 811 | int rotation, u32 *paddr) |
| 812 | { | 812 | { |
| 813 | u32 data_start_p; | 813 | u32 data_start_p; |
| 814 | void __iomem *data_start_v; | ||
| 815 | int offset; | 814 | int offset; |
| 816 | 815 | ||
| 817 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { | 816 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
| 818 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); | 817 | data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); |
| 819 | data_start_v = NULL; | 818 | else |
| 820 | } else { | ||
| 821 | data_start_p = omapfb_get_region_paddr(ofbi); | 819 | data_start_p = omapfb_get_region_paddr(ofbi); |
| 822 | data_start_v = omapfb_get_region_vaddr(ofbi); | ||
| 823 | } | ||
| 824 | 820 | ||
| 825 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) | 821 | if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) |
| 826 | offset = calc_rotation_offset_vrfb(var, fix, rotation); | 822 | offset = calc_rotation_offset_vrfb(var, fix, rotation); |
| @@ -828,16 +824,14 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi, | |||
| 828 | offset = calc_rotation_offset_dma(var, fix, rotation); | 824 | offset = calc_rotation_offset_dma(var, fix, rotation); |
| 829 | 825 | ||
| 830 | data_start_p += offset; | 826 | data_start_p += offset; |
| 831 | data_start_v += offset; | ||
| 832 | 827 | ||
| 833 | if (offset) | 828 | if (offset) |
| 834 | DBG("offset %d, %d = %d\n", | 829 | DBG("offset %d, %d = %d\n", |
| 835 | var->xoffset, var->yoffset, offset); | 830 | var->xoffset, var->yoffset, offset); |
| 836 | 831 | ||
| 837 | DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v); | 832 | DBG("paddr %x\n", data_start_p); |
| 838 | 833 | ||
| 839 | *paddr = data_start_p; | 834 | *paddr = data_start_p; |
| 840 | *vaddr = data_start_v; | ||
| 841 | } | 835 | } |
| 842 | 836 | ||
| 843 | /* setup overlay according to the fb */ | 837 | /* setup overlay according to the fb */ |
| @@ -850,7 +844,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
| 850 | struct fb_fix_screeninfo *fix = &fbi->fix; | 844 | struct fb_fix_screeninfo *fix = &fbi->fix; |
| 851 | enum omap_color_mode mode = 0; | 845 | enum omap_color_mode mode = 0; |
| 852 | u32 data_start_p = 0; | 846 | u32 data_start_p = 0; |
| 853 | void __iomem *data_start_v = NULL; | ||
| 854 | struct omap_overlay_info info; | 847 | struct omap_overlay_info info; |
| 855 | int xres, yres; | 848 | int xres, yres; |
| 856 | int screen_width; | 849 | int screen_width; |
| @@ -880,8 +873,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
| 880 | } | 873 | } |
| 881 | 874 | ||
| 882 | if (ofbi->region->size) | 875 | if (ofbi->region->size) |
| 883 | omapfb_calc_addr(ofbi, var, fix, rotation, | 876 | omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p); |
| 884 | &data_start_p, &data_start_v); | ||
| 885 | 877 | ||
| 886 | r = fb_mode_to_dss_mode(var, &mode); | 878 | r = fb_mode_to_dss_mode(var, &mode); |
| 887 | if (r) { | 879 | if (r) { |
| @@ -910,7 +902,6 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, | |||
| 910 | mirror = ofbi->mirror; | 902 | mirror = ofbi->mirror; |
| 911 | 903 | ||
| 912 | info.paddr = data_start_p; | 904 | info.paddr = data_start_p; |
| 913 | info.vaddr = data_start_v; | ||
| 914 | info.screen_width = screen_width; | 905 | info.screen_width = screen_width; |
| 915 | info.width = xres; | 906 | info.width = xres; |
| 916 | info.height = yres; | 907 | info.height = yres; |
| @@ -2276,6 +2267,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) | |||
| 2276 | return r; | 2267 | return r; |
| 2277 | } | 2268 | } |
| 2278 | 2269 | ||
| 2270 | static void fb_videomode_to_omap_timings(struct fb_videomode *m, | ||
| 2271 | struct omap_video_timings *t) | ||
| 2272 | { | ||
| 2273 | t->x_res = m->xres; | ||
| 2274 | t->y_res = m->yres; | ||
| 2275 | t->pixel_clock = PICOS2KHZ(m->pixclock); | ||
| 2276 | t->hsw = m->hsync_len; | ||
| 2277 | t->hfp = m->right_margin; | ||
| 2278 | t->hbp = m->left_margin; | ||
| 2279 | t->vsw = m->vsync_len; | ||
| 2280 | t->vfp = m->lower_margin; | ||
| 2281 | t->vbp = m->upper_margin; | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | static int omapfb_find_best_mode(struct omap_dss_device *display, | ||
| 2285 | struct omap_video_timings *timings) | ||
| 2286 | { | ||
| 2287 | struct fb_monspecs *specs; | ||
| 2288 | u8 *edid; | ||
| 2289 | int r, i, best_xres, best_idx, len; | ||
| 2290 | |||
| 2291 | if (!display->driver->read_edid) | ||
| 2292 | return -ENODEV; | ||
| 2293 | |||
| 2294 | len = 0x80 * 2; | ||
| 2295 | edid = kmalloc(len, GFP_KERNEL); | ||
| 2296 | |||
| 2297 | r = display->driver->read_edid(display, edid, len); | ||
| 2298 | if (r < 0) | ||
| 2299 | goto err1; | ||
| 2300 | |||
| 2301 | specs = kzalloc(sizeof(*specs), GFP_KERNEL); | ||
| 2302 | |||
| 2303 | fb_edid_to_monspecs(edid, specs); | ||
| 2304 | |||
| 2305 | if (edid[126] > 0) | ||
| 2306 | fb_edid_add_monspecs(edid + 0x80, specs); | ||
| 2307 | |||
| 2308 | best_xres = 0; | ||
| 2309 | best_idx = -1; | ||
| 2310 | |||
| 2311 | for (i = 0; i < specs->modedb_len; ++i) { | ||
| 2312 | struct fb_videomode *m; | ||
| 2313 | struct omap_video_timings t; | ||
| 2314 | |||
| 2315 | m = &specs->modedb[i]; | ||
| 2316 | |||
| 2317 | if (m->pixclock == 0) | ||
| 2318 | continue; | ||
| 2319 | |||
| 2320 | /* skip repeated pixel modes */ | ||
| 2321 | if (m->xres == 2880 || m->xres == 1440) | ||
| 2322 | continue; | ||
| 2323 | |||
| 2324 | fb_videomode_to_omap_timings(m, &t); | ||
| 2325 | |||
| 2326 | r = display->driver->check_timings(display, &t); | ||
| 2327 | if (r == 0 && best_xres < m->xres) { | ||
| 2328 | best_xres = m->xres; | ||
| 2329 | best_idx = i; | ||
| 2330 | } | ||
| 2331 | } | ||
| 2332 | |||
| 2333 | if (best_xres == 0) { | ||
| 2334 | r = -ENOENT; | ||
| 2335 | goto err2; | ||
| 2336 | } | ||
| 2337 | |||
| 2338 | fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings); | ||
| 2339 | |||
| 2340 | r = 0; | ||
| 2341 | |||
| 2342 | err2: | ||
| 2343 | fb_destroy_modedb(specs->modedb); | ||
| 2344 | kfree(specs); | ||
| 2345 | err1: | ||
| 2346 | kfree(edid); | ||
| 2347 | |||
| 2348 | return r; | ||
| 2349 | } | ||
| 2350 | |||
| 2279 | static int omapfb_init_display(struct omapfb2_device *fbdev, | 2351 | static int omapfb_init_display(struct omapfb2_device *fbdev, |
| 2280 | struct omap_dss_device *dssdev) | 2352 | struct omap_dss_device *dssdev) |
| 2281 | { | 2353 | { |
| @@ -2373,8 +2445,10 @@ static int omapfb_probe(struct platform_device *pdev) | |||
| 2373 | omap_dss_get_device(dssdev); | 2445 | omap_dss_get_device(dssdev); |
| 2374 | 2446 | ||
| 2375 | if (!dssdev->driver) { | 2447 | if (!dssdev->driver) { |
| 2376 | dev_err(&pdev->dev, "no driver for display\n"); | 2448 | dev_warn(&pdev->dev, "no driver for display: %s\n", |
| 2377 | r = -ENODEV; | 2449 | dssdev->name); |
| 2450 | omap_dss_put_device(dssdev); | ||
| 2451 | continue; | ||
| 2378 | } | 2452 | } |
| 2379 | 2453 | ||
| 2380 | d = &fbdev->displays[fbdev->num_displays++]; | 2454 | d = &fbdev->displays[fbdev->num_displays++]; |
| @@ -2402,9 +2476,27 @@ static int omapfb_probe(struct platform_device *pdev) | |||
| 2402 | for (i = 0; i < fbdev->num_managers; i++) | 2476 | for (i = 0; i < fbdev->num_managers; i++) |
| 2403 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); | 2477 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); |
| 2404 | 2478 | ||
| 2479 | /* gfx overlay should be the default one. find a display | ||
| 2480 | * connected to that, and use it as default display */ | ||
| 2481 | ovl = omap_dss_get_overlay(0); | ||
| 2482 | if (ovl->manager && ovl->manager->device) { | ||
| 2483 | def_display = ovl->manager->device; | ||
| 2484 | } else { | ||
| 2485 | dev_warn(&pdev->dev, "cannot find default display\n"); | ||
| 2486 | def_display = NULL; | ||
| 2487 | } | ||
| 2488 | |||
| 2405 | if (def_mode && strlen(def_mode) > 0) { | 2489 | if (def_mode && strlen(def_mode) > 0) { |
| 2406 | if (omapfb_parse_def_modes(fbdev)) | 2490 | if (omapfb_parse_def_modes(fbdev)) |
| 2407 | dev_warn(&pdev->dev, "cannot parse default modes\n"); | 2491 | dev_warn(&pdev->dev, "cannot parse default modes\n"); |
| 2492 | } else if (def_display && def_display->driver->set_timings && | ||
| 2493 | def_display->driver->check_timings) { | ||
| 2494 | struct omap_video_timings t; | ||
| 2495 | |||
| 2496 | r = omapfb_find_best_mode(def_display, &t); | ||
| 2497 | |||
| 2498 | if (r == 0) | ||
| 2499 | def_display->driver->set_timings(def_display, &t); | ||
| 2408 | } | 2500 | } |
| 2409 | 2501 | ||
| 2410 | r = omapfb_create_framebuffers(fbdev); | 2502 | r = omapfb_create_framebuffers(fbdev); |
| @@ -2421,16 +2513,6 @@ static int omapfb_probe(struct platform_device *pdev) | |||
| 2421 | 2513 | ||
| 2422 | DBG("mgr->apply'ed\n"); | 2514 | DBG("mgr->apply'ed\n"); |
| 2423 | 2515 | ||
| 2424 | /* gfx overlay should be the default one. find a display | ||
| 2425 | * connected to that, and use it as default display */ | ||
| 2426 | ovl = omap_dss_get_overlay(0); | ||
| 2427 | if (ovl->manager && ovl->manager->device) { | ||
| 2428 | def_display = ovl->manager->device; | ||
| 2429 | } else { | ||
| 2430 | dev_warn(&pdev->dev, "cannot find default display\n"); | ||
| 2431 | def_display = NULL; | ||
| 2432 | } | ||
| 2433 | |||
| 2434 | if (def_display) { | 2516 | if (def_display) { |
| 2435 | r = omapfb_init_display(fbdev, def_display); | 2517 | r = omapfb_init_display(fbdev, def_display); |
| 2436 | if (r) { | 2518 | if (r) { |
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c index 153bf1aceebc..1694d5148f32 100644 --- a/drivers/video/omap2/omapfb/omapfb-sysfs.c +++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c | |||
| @@ -104,16 +104,14 @@ static ssize_t store_mirror(struct device *dev, | |||
| 104 | { | 104 | { |
| 105 | struct fb_info *fbi = dev_get_drvdata(dev); | 105 | struct fb_info *fbi = dev_get_drvdata(dev); |
| 106 | struct omapfb_info *ofbi = FB2OFB(fbi); | 106 | struct omapfb_info *ofbi = FB2OFB(fbi); |
| 107 | int mirror; | 107 | bool mirror; |
| 108 | int r; | 108 | int r; |
| 109 | struct fb_var_screeninfo new_var; | 109 | struct fb_var_screeninfo new_var; |
| 110 | 110 | ||
| 111 | r = kstrtoint(buf, 0, &mirror); | 111 | r = strtobool(buf, &mirror); |
| 112 | if (r) | 112 | if (r) |
| 113 | return r; | 113 | return r; |
| 114 | 114 | ||
| 115 | mirror = !!mirror; | ||
| 116 | |||
| 117 | if (!lock_fb_info(fbi)) | 115 | if (!lock_fb_info(fbi)) |
| 118 | return -ENODEV; | 116 | return -ENODEV; |
| 119 | 117 | ||
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index f27ae16ead2e..ae3caa6755c2 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c | |||
| @@ -490,7 +490,7 @@ static int platinum_var_to_par(struct fb_var_screeninfo *var, | |||
| 490 | 490 | ||
| 491 | 491 | ||
| 492 | /* | 492 | /* |
| 493 | * Parse user speficied options (`video=platinumfb:') | 493 | * Parse user specified options (`video=platinumfb:') |
| 494 | */ | 494 | */ |
| 495 | static int __init platinumfb_setup(char *options) | 495 | static int __init platinumfb_setup(char *options) |
| 496 | { | 496 | { |
| @@ -683,7 +683,7 @@ static struct platform_driver platinum_driver = | |||
| 683 | .of_match_table = platinumfb_match, | 683 | .of_match_table = platinumfb_match, |
| 684 | }, | 684 | }, |
| 685 | .probe = platinumfb_probe, | 685 | .probe = platinumfb_probe, |
| 686 | .remove = platinumfb_remove, | 686 | .remove = __devexit_p(platinumfb_remove), |
| 687 | }; | 687 | }; |
| 688 | 688 | ||
| 689 | static int __init platinumfb_init(void) | 689 | static int __init platinumfb_init(void) |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 27f93aab6ddc..dc7bfa91e57a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
| @@ -973,8 +973,8 @@ static int pm2fb_pan_display(struct fb_var_screeninfo *var, | |||
| 973 | { | 973 | { |
| 974 | struct pm2fb_par *p = info->par; | 974 | struct pm2fb_par *p = info->par; |
| 975 | u32 base; | 975 | u32 base; |
| 976 | u32 depth = (var->bits_per_pixel + 7) & ~7; | 976 | u32 depth = (info->var.bits_per_pixel + 7) & ~7; |
| 977 | u32 xres = (var->xres + 31) & ~31; | 977 | u32 xres = (info->var.xres + 31) & ~31; |
| 978 | 978 | ||
| 979 | depth = (depth > 32) ? 32 : depth; | 979 | depth = (depth > 32) ? 32 : depth; |
| 980 | base = to3264(var->yoffset * xres + var->xoffset, depth, 1); | 980 | base = to3264(var->yoffset * xres + var->xoffset, depth, 1); |
| @@ -1773,7 +1773,7 @@ MODULE_DEVICE_TABLE(pci, pm2fb_id_table); | |||
| 1773 | 1773 | ||
| 1774 | #ifndef MODULE | 1774 | #ifndef MODULE |
| 1775 | /** | 1775 | /** |
| 1776 | * Parse user speficied options. | 1776 | * Parse user specified options. |
| 1777 | * | 1777 | * |
| 1778 | * This is, comma-separated options following `video=pm2fb:'. | 1778 | * This is, comma-separated options following `video=pm2fb:'. |
| 1779 | */ | 1779 | */ |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 6666f45a2f8c..6632ee5ecb7e 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
| @@ -1147,9 +1147,9 @@ static int pm3fb_pan_display(struct fb_var_screeninfo *var, | |||
| 1147 | struct fb_info *info) | 1147 | struct fb_info *info) |
| 1148 | { | 1148 | { |
| 1149 | struct pm3_par *par = info->par; | 1149 | struct pm3_par *par = info->par; |
| 1150 | const u32 xres = (var->xres + 31) & ~31; | 1150 | const u32 xres = (info->var.xres + 31) & ~31; |
| 1151 | 1151 | ||
| 1152 | par->base = pm3fb_shift_bpp(var->bits_per_pixel, | 1152 | par->base = pm3fb_shift_bpp(info->var.bits_per_pixel, |
| 1153 | (var->yoffset * xres) | 1153 | (var->yoffset * xres) |
| 1154 | + var->xoffset); | 1154 | + var->xoffset); |
| 1155 | PM3_WAIT(par, 1); | 1155 | PM3_WAIT(par, 1); |
| @@ -1525,7 +1525,7 @@ static int __init pm3fb_setup(char *options) | |||
| 1525 | { | 1525 | { |
| 1526 | char *this_opt; | 1526 | char *this_opt; |
| 1527 | 1527 | ||
| 1528 | /* Parse user speficied options (`video=pm3fb:') */ | 1528 | /* Parse user specified options (`video=pm3fb:') */ |
| 1529 | if (!options || !*options) | 1529 | if (!options || !*options) |
| 1530 | return 0; | 1530 | return 0; |
| 1531 | 1531 | ||
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c index 5ec4f2d439c9..50e00395240f 100644 --- a/drivers/video/pnx4008/sdum.c +++ b/drivers/video/pnx4008/sdum.c | |||
| @@ -30,7 +30,7 @@ | |||
| 30 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
| 31 | #include <linux/gfp.h> | 31 | #include <linux/gfp.h> |
| 32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
| 33 | #include <mach/gpio.h> | 33 | #include <asm/gpio.h> |
| 34 | 34 | ||
| 35 | #include "sdum.h" | 35 | #include "sdum.h" |
| 36 | #include "fbcommon.h" | 36 | #include "fbcommon.h" |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 65560a1a0439..213fbbcf613b 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
| @@ -1082,7 +1082,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
| 1082 | } | 1082 | } |
| 1083 | 1083 | ||
| 1084 | retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, | 1084 | retval = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, |
| 1085 | IRQF_DISABLED, DEVICE_NAME, &dev->core); | 1085 | 0, DEVICE_NAME, &dev->core); |
| 1086 | if (retval) { | 1086 | if (retval) { |
| 1087 | dev_err(&dev->core, "%s: request_irq failed %d\n", __func__, | 1087 | dev_err(&dev->core, "%s: request_irq failed %d\n", __func__, |
| 1088 | retval); | 1088 | retval); |
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c index 0283c7021090..1ed8b366618d 100644 --- a/drivers/video/pxa3xx-gcu.c +++ b/drivers/video/pxa3xx-gcu.c | |||
| @@ -31,8 +31,6 @@ | |||
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/version.h> | ||
| 35 | |||
| 36 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 37 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
| 38 | #include <linux/miscdevice.h> | 36 | #include <linux/miscdevice.h> |
| @@ -678,7 +676,7 @@ pxa3xx_gcu_probe(struct platform_device *dev) | |||
| 678 | } | 676 | } |
| 679 | 677 | ||
| 680 | ret = request_irq(irq, pxa3xx_gcu_handle_irq, | 678 | ret = request_irq(irq, pxa3xx_gcu_handle_irq, |
| 681 | IRQF_DISABLED, DRV_NAME, priv); | 679 | 0, DRV_NAME, priv); |
| 682 | if (ret) { | 680 | if (ret) { |
| 683 | dev_err(&dev->dev, "request_irq failed\n"); | 681 | dev_err(&dev->dev, "request_irq failed\n"); |
| 684 | ret = -EBUSY; | 682 | ret = -EBUSY; |
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 0f4e8c942f9e..1d1e4f175e78 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c | |||
| @@ -1309,16 +1309,6 @@ static int pxafb_smart_init(struct pxafb_info *fbi) | |||
| 1309 | return 0; | 1309 | return 0; |
| 1310 | } | 1310 | } |
| 1311 | #else | 1311 | #else |
| 1312 | int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int n_cmds) | ||
| 1313 | { | ||
| 1314 | return 0; | ||
| 1315 | } | ||
| 1316 | |||
| 1317 | int pxafb_smart_flush(struct fb_info *info) | ||
| 1318 | { | ||
| 1319 | return 0; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; } | 1312 | static inline int pxafb_smart_init(struct pxafb_info *fbi) { return 0; } |
| 1323 | #endif /* CONFIG_FB_PXA_SMARTPANEL */ | 1313 | #endif /* CONFIG_FB_PXA_SMARTPANEL */ |
| 1324 | 1314 | ||
| @@ -2191,7 +2181,7 @@ static int __devinit pxafb_probe(struct platform_device *dev) | |||
| 2191 | goto failed_free_mem; | 2181 | goto failed_free_mem; |
| 2192 | } | 2182 | } |
| 2193 | 2183 | ||
| 2194 | ret = request_irq(irq, pxafb_handle_irq, IRQF_DISABLED, "LCD", fbi); | 2184 | ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi); |
| 2195 | if (ret) { | 2185 | if (ret) { |
| 2196 | dev_err(&dev->dev, "request_irq failed: %d\n", ret); | 2186 | dev_err(&dev->dev, "request_irq failed: %d\n", ret); |
| 2197 | ret = -EBUSY; | 2187 | ret = -EBUSY; |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 4aecf213c9be..0753b1cfcb8b 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
| @@ -81,6 +81,7 @@ struct s3c_fb; | |||
| 81 | * @palette: Address of palette memory, or 0 if none. | 81 | * @palette: Address of palette memory, or 0 if none. |
| 82 | * @has_prtcon: Set if has PRTCON register. | 82 | * @has_prtcon: Set if has PRTCON register. |
| 83 | * @has_shadowcon: Set if has SHADOWCON register. | 83 | * @has_shadowcon: Set if has SHADOWCON register. |
| 84 | * @has_clksel: Set if VIDCON0 register has CLKSEL bit. | ||
| 84 | */ | 85 | */ |
| 85 | struct s3c_fb_variant { | 86 | struct s3c_fb_variant { |
| 86 | unsigned int is_2443:1; | 87 | unsigned int is_2443:1; |
| @@ -98,6 +99,7 @@ struct s3c_fb_variant { | |||
| 98 | 99 | ||
| 99 | unsigned int has_prtcon:1; | 100 | unsigned int has_prtcon:1; |
| 100 | unsigned int has_shadowcon:1; | 101 | unsigned int has_shadowcon:1; |
| 102 | unsigned int has_clksel:1; | ||
| 101 | }; | 103 | }; |
| 102 | 104 | ||
| 103 | /** | 105 | /** |
| @@ -186,6 +188,7 @@ struct s3c_fb_vsync { | |||
| 186 | * @dev: The device that we bound to, for printing, etc. | 188 | * @dev: The device that we bound to, for printing, etc. |
| 187 | * @regs_res: The resource we claimed for the IO registers. | 189 | * @regs_res: The resource we claimed for the IO registers. |
| 188 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | 190 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. |
| 191 | * @lcd_clk: The clk (sclk) feeding pixclk. | ||
| 189 | * @regs: The mapped hardware registers. | 192 | * @regs: The mapped hardware registers. |
| 190 | * @variant: Variant information for this hardware. | 193 | * @variant: Variant information for this hardware. |
| 191 | * @enabled: A bitmask of enabled hardware windows. | 194 | * @enabled: A bitmask of enabled hardware windows. |
| @@ -200,6 +203,7 @@ struct s3c_fb { | |||
| 200 | struct device *dev; | 203 | struct device *dev; |
| 201 | struct resource *regs_res; | 204 | struct resource *regs_res; |
| 202 | struct clk *bus_clk; | 205 | struct clk *bus_clk; |
| 206 | struct clk *lcd_clk; | ||
| 203 | void __iomem *regs; | 207 | void __iomem *regs; |
| 204 | struct s3c_fb_variant variant; | 208 | struct s3c_fb_variant variant; |
| 205 | 209 | ||
| @@ -336,10 +340,15 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, | |||
| 336 | */ | 340 | */ |
| 337 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) | 341 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) |
| 338 | { | 342 | { |
| 339 | unsigned long clk = clk_get_rate(sfb->bus_clk); | 343 | unsigned long clk; |
| 340 | unsigned long long tmp; | 344 | unsigned long long tmp; |
| 341 | unsigned int result; | 345 | unsigned int result; |
| 342 | 346 | ||
| 347 | if (sfb->variant.has_clksel) | ||
| 348 | clk = clk_get_rate(sfb->bus_clk); | ||
| 349 | else | ||
| 350 | clk = clk_get_rate(sfb->lcd_clk); | ||
| 351 | |||
| 343 | tmp = (unsigned long long)clk; | 352 | tmp = (unsigned long long)clk; |
| 344 | tmp *= pixclk; | 353 | tmp *= pixclk; |
| 345 | 354 | ||
| @@ -883,7 +892,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var, | |||
| 883 | } | 892 | } |
| 884 | } | 893 | } |
| 885 | /* Offset in bytes to the end of the displayed area */ | 894 | /* Offset in bytes to the end of the displayed area */ |
| 886 | end_boff = start_boff + var->yres * info->fix.line_length; | 895 | end_boff = start_boff + info->var.yres * info->fix.line_length; |
| 887 | 896 | ||
| 888 | /* Temporarily turn off per-vsync update from shadow registers until | 897 | /* Temporarily turn off per-vsync update from shadow registers until |
| 889 | * both start and end addresses are updated to prevent corruption */ | 898 | * both start and end addresses are updated to prevent corruption */ |
| @@ -1354,13 +1363,24 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
| 1354 | 1363 | ||
| 1355 | clk_enable(sfb->bus_clk); | 1364 | clk_enable(sfb->bus_clk); |
| 1356 | 1365 | ||
| 1366 | if (!sfb->variant.has_clksel) { | ||
| 1367 | sfb->lcd_clk = clk_get(dev, "sclk_fimd"); | ||
| 1368 | if (IS_ERR(sfb->lcd_clk)) { | ||
| 1369 | dev_err(dev, "failed to get lcd clock\n"); | ||
| 1370 | ret = PTR_ERR(sfb->lcd_clk); | ||
| 1371 | goto err_bus_clk; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | clk_enable(sfb->lcd_clk); | ||
| 1375 | } | ||
| 1376 | |||
| 1357 | pm_runtime_enable(sfb->dev); | 1377 | pm_runtime_enable(sfb->dev); |
| 1358 | 1378 | ||
| 1359 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1379 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1360 | if (!res) { | 1380 | if (!res) { |
| 1361 | dev_err(dev, "failed to find registers\n"); | 1381 | dev_err(dev, "failed to find registers\n"); |
| 1362 | ret = -ENOENT; | 1382 | ret = -ENOENT; |
| 1363 | goto err_clk; | 1383 | goto err_lcd_clk; |
| 1364 | } | 1384 | } |
| 1365 | 1385 | ||
| 1366 | sfb->regs_res = request_mem_region(res->start, resource_size(res), | 1386 | sfb->regs_res = request_mem_region(res->start, resource_size(res), |
| @@ -1368,7 +1388,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev) | |||
| 1368 | if (!sfb->regs_res) { | 1388 | if (!sfb->regs_res) { |
| 1369 | dev_err(dev, "failed to claim register region\n"); | 1389 | dev_err(dev, "failed to claim register region\n"); |
| 1370 | ret = -ENOENT; | 1390 | ret = -ENOENT; |
| 1371 | goto err_clk; | 1391 | goto err_lcd_clk; |
| 1372 | } | 1392 | } |
| 1373 | 1393 | ||
| 1374 | sfb->regs = ioremap(res->start, resource_size(res)); | 1394 | sfb->regs = ioremap(res->start, resource_size(res)); |
| @@ -1450,7 +1470,13 @@ err_ioremap: | |||
| 1450 | err_req_region: | 1470 | err_req_region: |
| 1451 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); | 1471 | release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); |
| 1452 | 1472 | ||
| 1453 | err_clk: | 1473 | err_lcd_clk: |
| 1474 | if (!sfb->variant.has_clksel) { | ||
| 1475 | clk_disable(sfb->lcd_clk); | ||
| 1476 | clk_put(sfb->lcd_clk); | ||
| 1477 | } | ||
| 1478 | |||
| 1479 | err_bus_clk: | ||
| 1454 | clk_disable(sfb->bus_clk); | 1480 | clk_disable(sfb->bus_clk); |
| 1455 | clk_put(sfb->bus_clk); | 1481 | clk_put(sfb->bus_clk); |
| 1456 | 1482 | ||
| @@ -1481,6 +1507,11 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
| 1481 | 1507 | ||
| 1482 | iounmap(sfb->regs); | 1508 | iounmap(sfb->regs); |
| 1483 | 1509 | ||
| 1510 | if (!sfb->variant.has_clksel) { | ||
| 1511 | clk_disable(sfb->lcd_clk); | ||
| 1512 | clk_put(sfb->lcd_clk); | ||
| 1513 | } | ||
| 1514 | |||
| 1484 | clk_disable(sfb->bus_clk); | 1515 | clk_disable(sfb->bus_clk); |
| 1485 | clk_put(sfb->bus_clk); | 1516 | clk_put(sfb->bus_clk); |
| 1486 | 1517 | ||
| @@ -1510,6 +1541,9 @@ static int s3c_fb_suspend(struct device *dev) | |||
| 1510 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | 1541 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); |
| 1511 | } | 1542 | } |
| 1512 | 1543 | ||
| 1544 | if (!sfb->variant.has_clksel) | ||
| 1545 | clk_disable(sfb->lcd_clk); | ||
| 1546 | |||
| 1513 | clk_disable(sfb->bus_clk); | 1547 | clk_disable(sfb->bus_clk); |
| 1514 | return 0; | 1548 | return 0; |
| 1515 | } | 1549 | } |
| @@ -1524,6 +1558,9 @@ static int s3c_fb_resume(struct device *dev) | |||
| 1524 | 1558 | ||
| 1525 | clk_enable(sfb->bus_clk); | 1559 | clk_enable(sfb->bus_clk); |
| 1526 | 1560 | ||
| 1561 | if (!sfb->variant.has_clksel) | ||
| 1562 | clk_enable(sfb->lcd_clk); | ||
| 1563 | |||
| 1527 | /* setup gpio and output polarity controls */ | 1564 | /* setup gpio and output polarity controls */ |
| 1528 | pd->setup_gpio(); | 1565 | pd->setup_gpio(); |
| 1529 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1566 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
| @@ -1569,6 +1606,9 @@ static int s3c_fb_runtime_suspend(struct device *dev) | |||
| 1569 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | 1606 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); |
| 1570 | } | 1607 | } |
| 1571 | 1608 | ||
| 1609 | if (!sfb->variant.has_clksel) | ||
| 1610 | clk_disable(sfb->lcd_clk); | ||
| 1611 | |||
| 1572 | clk_disable(sfb->bus_clk); | 1612 | clk_disable(sfb->bus_clk); |
| 1573 | return 0; | 1613 | return 0; |
| 1574 | } | 1614 | } |
| @@ -1583,6 +1623,9 @@ static int s3c_fb_runtime_resume(struct device *dev) | |||
| 1583 | 1623 | ||
| 1584 | clk_enable(sfb->bus_clk); | 1624 | clk_enable(sfb->bus_clk); |
| 1585 | 1625 | ||
| 1626 | if (!sfb->variant.has_clksel) | ||
| 1627 | clk_enable(sfb->lcd_clk); | ||
| 1628 | |||
| 1586 | /* setup gpio and output polarity controls */ | 1629 | /* setup gpio and output polarity controls */ |
| 1587 | pd->setup_gpio(); | 1630 | pd->setup_gpio(); |
| 1588 | writel(pd->vidcon1, sfb->regs + VIDCON1); | 1631 | writel(pd->vidcon1, sfb->regs + VIDCON1); |
| @@ -1755,6 +1798,7 @@ static struct s3c_fb_driverdata s3c_fb_data_64xx = { | |||
| 1755 | }, | 1798 | }, |
| 1756 | 1799 | ||
| 1757 | .has_prtcon = 1, | 1800 | .has_prtcon = 1, |
| 1801 | .has_clksel = 1, | ||
| 1758 | }, | 1802 | }, |
| 1759 | .win[0] = &s3c_fb_data_64xx_wins[0], | 1803 | .win[0] = &s3c_fb_data_64xx_wins[0], |
| 1760 | .win[1] = &s3c_fb_data_64xx_wins[1], | 1804 | .win[1] = &s3c_fb_data_64xx_wins[1], |
| @@ -1785,6 +1829,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = { | |||
| 1785 | }, | 1829 | }, |
| 1786 | 1830 | ||
| 1787 | .has_prtcon = 1, | 1831 | .has_prtcon = 1, |
| 1832 | .has_clksel = 1, | ||
| 1788 | }, | 1833 | }, |
| 1789 | .win[0] = &s3c_fb_data_s5p_wins[0], | 1834 | .win[0] = &s3c_fb_data_s5p_wins[0], |
| 1790 | .win[1] = &s3c_fb_data_s5p_wins[1], | 1835 | .win[1] = &s3c_fb_data_s5p_wins[1], |
| @@ -1815,6 +1860,37 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = { | |||
| 1815 | }, | 1860 | }, |
| 1816 | 1861 | ||
| 1817 | .has_shadowcon = 1, | 1862 | .has_shadowcon = 1, |
| 1863 | .has_clksel = 1, | ||
| 1864 | }, | ||
| 1865 | .win[0] = &s3c_fb_data_s5p_wins[0], | ||
| 1866 | .win[1] = &s3c_fb_data_s5p_wins[1], | ||
| 1867 | .win[2] = &s3c_fb_data_s5p_wins[2], | ||
| 1868 | .win[3] = &s3c_fb_data_s5p_wins[3], | ||
| 1869 | .win[4] = &s3c_fb_data_s5p_wins[4], | ||
| 1870 | }; | ||
| 1871 | |||
| 1872 | static struct s3c_fb_driverdata s3c_fb_data_exynos4 = { | ||
| 1873 | .variant = { | ||
| 1874 | .nr_windows = 5, | ||
| 1875 | .vidtcon = VIDTCON0, | ||
| 1876 | .wincon = WINCON(0), | ||
| 1877 | .winmap = WINxMAP(0), | ||
| 1878 | .keycon = WKEYCON, | ||
| 1879 | .osd = VIDOSD_BASE, | ||
| 1880 | .osd_stride = 16, | ||
| 1881 | .buf_start = VIDW_BUF_START(0), | ||
| 1882 | .buf_size = VIDW_BUF_SIZE(0), | ||
| 1883 | .buf_end = VIDW_BUF_END(0), | ||
| 1884 | |||
| 1885 | .palette = { | ||
| 1886 | [0] = 0x2400, | ||
| 1887 | [1] = 0x2800, | ||
| 1888 | [2] = 0x2c00, | ||
| 1889 | [3] = 0x3000, | ||
| 1890 | [4] = 0x3400, | ||
| 1891 | }, | ||
| 1892 | |||
| 1893 | .has_shadowcon = 1, | ||
| 1818 | }, | 1894 | }, |
| 1819 | .win[0] = &s3c_fb_data_s5p_wins[0], | 1895 | .win[0] = &s3c_fb_data_s5p_wins[0], |
| 1820 | .win[1] = &s3c_fb_data_s5p_wins[1], | 1896 | .win[1] = &s3c_fb_data_s5p_wins[1], |
| @@ -1843,6 +1919,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = { | |||
| 1843 | [0] = 0x400, | 1919 | [0] = 0x400, |
| 1844 | [1] = 0x800, | 1920 | [1] = 0x800, |
| 1845 | }, | 1921 | }, |
| 1922 | .has_clksel = 1, | ||
| 1846 | }, | 1923 | }, |
| 1847 | .win[0] = &(struct s3c_fb_win_variant) { | 1924 | .win[0] = &(struct s3c_fb_win_variant) { |
| 1848 | .palette_sz = 256, | 1925 | .palette_sz = 256, |
| @@ -1859,6 +1936,30 @@ static struct s3c_fb_driverdata s3c_fb_data_s3c2443 = { | |||
| 1859 | }, | 1936 | }, |
| 1860 | }; | 1937 | }; |
| 1861 | 1938 | ||
| 1939 | static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = { | ||
| 1940 | .variant = { | ||
| 1941 | .nr_windows = 3, | ||
| 1942 | .vidtcon = VIDTCON0, | ||
| 1943 | .wincon = WINCON(0), | ||
| 1944 | .winmap = WINxMAP(0), | ||
| 1945 | .keycon = WKEYCON, | ||
| 1946 | .osd = VIDOSD_BASE, | ||
| 1947 | .osd_stride = 16, | ||
| 1948 | .buf_start = VIDW_BUF_START(0), | ||
| 1949 | .buf_size = VIDW_BUF_SIZE(0), | ||
| 1950 | .buf_end = VIDW_BUF_END(0), | ||
| 1951 | |||
| 1952 | .palette = { | ||
| 1953 | [0] = 0x2400, | ||
| 1954 | [1] = 0x2800, | ||
| 1955 | [2] = 0x2c00, | ||
| 1956 | }, | ||
| 1957 | }, | ||
| 1958 | .win[0] = &s3c_fb_data_s5p_wins[0], | ||
| 1959 | .win[1] = &s3c_fb_data_s5p_wins[1], | ||
| 1960 | .win[2] = &s3c_fb_data_s5p_wins[2], | ||
| 1961 | }; | ||
| 1962 | |||
| 1862 | static struct platform_device_id s3c_fb_driver_ids[] = { | 1963 | static struct platform_device_id s3c_fb_driver_ids[] = { |
| 1863 | { | 1964 | { |
| 1864 | .name = "s3c-fb", | 1965 | .name = "s3c-fb", |
| @@ -1870,8 +1971,14 @@ static struct platform_device_id s3c_fb_driver_ids[] = { | |||
| 1870 | .name = "s5pv210-fb", | 1971 | .name = "s5pv210-fb", |
| 1871 | .driver_data = (unsigned long)&s3c_fb_data_s5pv210, | 1972 | .driver_data = (unsigned long)&s3c_fb_data_s5pv210, |
| 1872 | }, { | 1973 | }, { |
| 1974 | .name = "exynos4-fb", | ||
| 1975 | .driver_data = (unsigned long)&s3c_fb_data_exynos4, | ||
| 1976 | }, { | ||
| 1873 | .name = "s3c2443-fb", | 1977 | .name = "s3c2443-fb", |
| 1874 | .driver_data = (unsigned long)&s3c_fb_data_s3c2443, | 1978 | .driver_data = (unsigned long)&s3c_fb_data_s3c2443, |
| 1979 | }, { | ||
| 1980 | .name = "s5p64x0-fb", | ||
| 1981 | .driver_data = (unsigned long)&s3c_fb_data_s5p64x0, | ||
| 1875 | }, | 1982 | }, |
| 1876 | {}, | 1983 | {}, |
| 1877 | }; | 1984 | }; |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 0aa13761de6e..ee4c0df217f7 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
| @@ -767,7 +767,6 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
| 767 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, | 767 | static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, |
| 768 | unsigned long val, void *data) | 768 | unsigned long val, void *data) |
| 769 | { | 769 | { |
| 770 | struct cpufreq_freqs *freqs = data; | ||
| 771 | struct s3c2410fb_info *info; | 770 | struct s3c2410fb_info *info; |
| 772 | struct fb_info *fbinfo; | 771 | struct fb_info *fbinfo; |
| 773 | long delta_f; | 772 | long delta_f; |
| @@ -911,7 +910,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev, | |||
| 911 | for (i = 0; i < 256; i++) | 910 | for (i = 0; i < 256; i++) |
| 912 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; | 911 | info->palette_buffer[i] = PALETTE_BUFF_CLEAR; |
| 913 | 912 | ||
| 914 | ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); | 913 | ret = request_irq(irq, s3c2410fb_irq, 0, pdev->name, info); |
| 915 | if (ret) { | 914 | if (ret) { |
| 916 | dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); | 915 | dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); |
| 917 | ret = -EBUSY; | 916 | ret = -EBUSY; |
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 4ca5d0c8fe84..946a949f4c7d 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
| @@ -1019,12 +1019,13 @@ static int s3fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 1019 | unsigned int offset; | 1019 | unsigned int offset; |
| 1020 | 1020 | ||
| 1021 | /* Calculate the offset */ | 1021 | /* Calculate the offset */ |
| 1022 | if (var->bits_per_pixel == 0) { | 1022 | if (info->var.bits_per_pixel == 0) { |
| 1023 | offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2); | 1023 | offset = (var->yoffset / 16) * (info->var.xres_virtual / 2) |
| 1024 | + (var->xoffset / 2); | ||
| 1024 | offset = offset >> 2; | 1025 | offset = offset >> 2; |
| 1025 | } else { | 1026 | } else { |
| 1026 | offset = (var->yoffset * info->fix.line_length) + | 1027 | offset = (var->yoffset * info->fix.line_length) + |
| 1027 | (var->xoffset * var->bits_per_pixel / 8); | 1028 | (var->xoffset * info->var.bits_per_pixel / 8); |
| 1028 | offset = offset >> 2; | 1029 | offset = offset >> 2; |
| 1029 | } | 1030 | } |
| 1030 | 1031 | ||
| @@ -1504,7 +1505,7 @@ static struct pci_driver s3fb_pci_driver = { | |||
| 1504 | .resume = s3_pci_resume, | 1505 | .resume = s3_pci_resume, |
| 1505 | }; | 1506 | }; |
| 1506 | 1507 | ||
| 1507 | /* Parse user speficied options */ | 1508 | /* Parse user specified options */ |
| 1508 | 1509 | ||
| 1509 | #ifndef MODULE | 1510 | #ifndef MODULE |
| 1510 | static int __init s3fb_setup(char *options) | 1511 | static int __init s3fb_setup(char *options) |
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index e8b76d65a070..98d55d0e2da5 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c | |||
| @@ -1457,8 +1457,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev) | |||
| 1457 | if (ret) | 1457 | if (ret) |
| 1458 | goto failed; | 1458 | goto failed; |
| 1459 | 1459 | ||
| 1460 | ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED, | 1460 | ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi); |
| 1461 | "LCD", fbi); | ||
| 1462 | if (ret) { | 1461 | if (ret) { |
| 1463 | printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); | 1462 | printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); |
| 1464 | goto failed; | 1463 | goto failed; |
diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c index bbcc055d3bb7..bfefa6234cf0 100644 --- a/drivers/video/savage/savagefb_accel.c +++ b/drivers/video/savage/savagefb_accel.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/string.h> | 12 | #include <linux/string.h> |
| 13 | #include <linux/fb.h> | 13 | #include <linux/fb.h> |
| 14 | #include <linux/module.h> | ||
| 14 | 15 | ||
| 15 | #include "savagefb.h" | 16 | #include "savagefb.h" |
| 16 | 17 | ||
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 4de541ca9c52..beb495044b24 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c | |||
| @@ -1477,15 +1477,9 @@ static void savagefb_set_par_int(struct savagefb_par *par, struct savage_reg *r | |||
| 1477 | vgaHWProtect(par, 0); | 1477 | vgaHWProtect(par, 0); |
| 1478 | } | 1478 | } |
| 1479 | 1479 | ||
| 1480 | static void savagefb_update_start(struct savagefb_par *par, | 1480 | static void savagefb_update_start(struct savagefb_par *par, int base) |
| 1481 | struct fb_var_screeninfo *var) | ||
| 1482 | { | 1481 | { |
| 1483 | int base; | 1482 | /* program the start address registers */ |
| 1484 | |||
| 1485 | base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1)) | ||
| 1486 | * ((var->bits_per_pixel+7) / 8)) >> 2; | ||
| 1487 | |||
| 1488 | /* now program the start address registers */ | ||
| 1489 | vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); | 1483 | vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par); |
| 1490 | vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); | 1484 | vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par); |
| 1491 | vga_out8(0x3d4, 0x69, par); | 1485 | vga_out8(0x3d4, 0x69, par); |
| @@ -1550,8 +1544,12 @@ static int savagefb_pan_display(struct fb_var_screeninfo *var, | |||
| 1550 | struct fb_info *info) | 1544 | struct fb_info *info) |
| 1551 | { | 1545 | { |
| 1552 | struct savagefb_par *par = info->par; | 1546 | struct savagefb_par *par = info->par; |
| 1547 | int base; | ||
| 1548 | |||
| 1549 | base = (var->yoffset * info->fix.line_length | ||
| 1550 | + (var->xoffset & ~1) * ((info->var.bits_per_pixel+7) / 8)) >> 2; | ||
| 1553 | 1551 | ||
| 1554 | savagefb_update_start(par, var); | 1552 | savagefb_update_start(par, base); |
| 1555 | return 0; | 1553 | return 0; |
| 1556 | } | 1554 | } |
| 1557 | 1555 | ||
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c index 24640c8458ab..72ee96bc6b3e 100644 --- a/drivers/video/sh_mipi_dsi.c +++ b/drivers/video/sh_mipi_dsi.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
| 19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
| 20 | #include <linux/module.h> | ||
| 20 | 21 | ||
| 21 | #include <video/mipi_display.h> | 22 | #include <video/mipi_display.h> |
| 22 | #include <video/sh_mipi_dsi.h> | 23 | #include <video/sh_mipi_dsi.h> |
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 7d54e2c612f7..647ba984f00f 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
| @@ -1111,6 +1111,7 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate, | |||
| 1111 | static void sh_hdmi_edid_work_fn(struct work_struct *work) | 1111 | static void sh_hdmi_edid_work_fn(struct work_struct *work) |
| 1112 | { | 1112 | { |
| 1113 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); | 1113 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); |
| 1114 | struct fb_info *info; | ||
| 1114 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; | 1115 | struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; |
| 1115 | struct sh_mobile_lcdc_chan *ch; | 1116 | struct sh_mobile_lcdc_chan *ch; |
| 1116 | int ret; | 1117 | int ret; |
| @@ -1123,8 +1124,9 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
| 1123 | 1124 | ||
| 1124 | mutex_lock(&hdmi->mutex); | 1125 | mutex_lock(&hdmi->mutex); |
| 1125 | 1126 | ||
| 1127 | info = hdmi->info; | ||
| 1128 | |||
| 1126 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { | 1129 | if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { |
| 1127 | struct fb_info *info = hdmi->info; | ||
| 1128 | unsigned long parent_rate = 0, hdmi_rate; | 1130 | unsigned long parent_rate = 0, hdmi_rate; |
| 1129 | 1131 | ||
| 1130 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); | 1132 | ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate); |
| @@ -1148,42 +1150,45 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
| 1148 | 1150 | ||
| 1149 | ch = info->par; | 1151 | ch = info->par; |
| 1150 | 1152 | ||
| 1151 | console_lock(); | 1153 | if (lock_fb_info(info)) { |
| 1154 | console_lock(); | ||
| 1152 | 1155 | ||
| 1153 | /* HDMI plug in */ | 1156 | /* HDMI plug in */ |
| 1154 | if (!sh_hdmi_must_reconfigure(hdmi) && | 1157 | if (!sh_hdmi_must_reconfigure(hdmi) && |
| 1155 | info->state == FBINFO_STATE_RUNNING) { | 1158 | info->state == FBINFO_STATE_RUNNING) { |
| 1156 | /* | 1159 | /* |
| 1157 | * First activation with the default monitor - just turn | 1160 | * First activation with the default monitor - just turn |
| 1158 | * on, if we run a resume here, the logo disappears | 1161 | * on, if we run a resume here, the logo disappears |
| 1159 | */ | 1162 | */ |
| 1160 | if (lock_fb_info(info)) { | ||
| 1161 | info->var.width = hdmi->var.width; | 1163 | info->var.width = hdmi->var.width; |
| 1162 | info->var.height = hdmi->var.height; | 1164 | info->var.height = hdmi->var.height; |
| 1163 | sh_hdmi_display_on(hdmi, info); | 1165 | sh_hdmi_display_on(hdmi, info); |
| 1164 | unlock_fb_info(info); | 1166 | } else { |
| 1167 | /* New monitor or have to wake up */ | ||
| 1168 | fb_set_suspend(info, 0); | ||
| 1165 | } | 1169 | } |
| 1166 | } else { | ||
| 1167 | /* New monitor or have to wake up */ | ||
| 1168 | fb_set_suspend(info, 0); | ||
| 1169 | } | ||
| 1170 | 1170 | ||
| 1171 | console_unlock(); | 1171 | console_unlock(); |
| 1172 | unlock_fb_info(info); | ||
| 1173 | } | ||
| 1172 | } else { | 1174 | } else { |
| 1173 | ret = 0; | 1175 | ret = 0; |
| 1174 | if (!hdmi->info) | 1176 | if (!info) |
| 1175 | goto out; | 1177 | goto out; |
| 1176 | 1178 | ||
| 1177 | hdmi->monspec.modedb_len = 0; | 1179 | hdmi->monspec.modedb_len = 0; |
| 1178 | fb_destroy_modedb(hdmi->monspec.modedb); | 1180 | fb_destroy_modedb(hdmi->monspec.modedb); |
| 1179 | hdmi->monspec.modedb = NULL; | 1181 | hdmi->monspec.modedb = NULL; |
| 1180 | 1182 | ||
| 1181 | console_lock(); | 1183 | if (lock_fb_info(info)) { |
| 1184 | console_lock(); | ||
| 1182 | 1185 | ||
| 1183 | /* HDMI disconnect */ | 1186 | /* HDMI disconnect */ |
| 1184 | fb_set_suspend(hdmi->info, 1); | 1187 | fb_set_suspend(info, 1); |
| 1185 | 1188 | ||
| 1186 | console_unlock(); | 1189 | console_unlock(); |
| 1190 | unlock_fb_info(info); | ||
| 1191 | } | ||
| 1187 | } | 1192 | } |
| 1188 | 1193 | ||
| 1189 | out: | 1194 | out: |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index b048417247e8..facffc254976 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
| @@ -23,40 +23,16 @@ | |||
| 23 | #include <linux/console.h> | 23 | #include <linux/console.h> |
| 24 | #include <linux/backlight.h> | 24 | #include <linux/backlight.h> |
| 25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
| 26 | #include <linux/module.h> | ||
| 26 | #include <video/sh_mobile_lcdc.h> | 27 | #include <video/sh_mobile_lcdc.h> |
| 28 | #include <video/sh_mobile_meram.h> | ||
| 27 | #include <linux/atomic.h> | 29 | #include <linux/atomic.h> |
| 28 | 30 | ||
| 29 | #include "sh_mobile_lcdcfb.h" | 31 | #include "sh_mobile_lcdcfb.h" |
| 30 | #include "sh_mobile_meram.h" | ||
| 31 | 32 | ||
| 32 | #define SIDE_B_OFFSET 0x1000 | 33 | #define SIDE_B_OFFSET 0x1000 |
| 33 | #define MIRROR_OFFSET 0x2000 | 34 | #define MIRROR_OFFSET 0x2000 |
| 34 | 35 | ||
| 35 | /* shared registers */ | ||
| 36 | #define _LDDCKR 0x410 | ||
| 37 | #define _LDDCKSTPR 0x414 | ||
| 38 | #define _LDINTR 0x468 | ||
| 39 | #define _LDSR 0x46c | ||
| 40 | #define _LDCNT1R 0x470 | ||
| 41 | #define _LDCNT2R 0x474 | ||
| 42 | #define _LDRCNTR 0x478 | ||
| 43 | #define _LDDDSR 0x47c | ||
| 44 | #define _LDDWD0R 0x800 | ||
| 45 | #define _LDDRDR 0x840 | ||
| 46 | #define _LDDWAR 0x900 | ||
| 47 | #define _LDDRAR 0x904 | ||
| 48 | |||
| 49 | /* shared registers and their order for context save/restore */ | ||
| 50 | static int lcdc_shared_regs[] = { | ||
| 51 | _LDDCKR, | ||
| 52 | _LDDCKSTPR, | ||
| 53 | _LDINTR, | ||
| 54 | _LDDDSR, | ||
| 55 | _LDCNT1R, | ||
| 56 | _LDCNT2R, | ||
| 57 | }; | ||
| 58 | #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs) | ||
| 59 | |||
| 60 | #define MAX_XRES 1920 | 36 | #define MAX_XRES 1920 |
| 61 | #define MAX_YRES 1080 | 37 | #define MAX_YRES 1080 |
| 62 | 38 | ||
| @@ -98,22 +74,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { | |||
| 98 | [LDPMR] = 0x63c, | 74 | [LDPMR] = 0x63c, |
| 99 | }; | 75 | }; |
| 100 | 76 | ||
| 101 | #define START_LCDC 0x00000001 | ||
| 102 | #define LCDC_RESET 0x00000100 | ||
| 103 | #define DISPLAY_BEU 0x00000008 | ||
| 104 | #define LCDC_ENABLE 0x00000001 | ||
| 105 | #define LDINTR_FE 0x00000400 | ||
| 106 | #define LDINTR_VSE 0x00000200 | ||
| 107 | #define LDINTR_VEE 0x00000100 | ||
| 108 | #define LDINTR_FS 0x00000004 | ||
| 109 | #define LDINTR_VSS 0x00000002 | ||
| 110 | #define LDINTR_VES 0x00000001 | ||
| 111 | #define LDRCNTR_SRS 0x00020000 | ||
| 112 | #define LDRCNTR_SRC 0x00010000 | ||
| 113 | #define LDRCNTR_MRS 0x00000002 | ||
| 114 | #define LDRCNTR_MRC 0x00000001 | ||
| 115 | #define LDSR_MRS 0x00000100 | ||
| 116 | |||
| 117 | static const struct fb_videomode default_720p = { | 77 | static const struct fb_videomode default_720p = { |
| 118 | .name = "HDMI 720p", | 78 | .name = "HDMI 720p", |
| 119 | .xres = 1280, | 79 | .xres = 1280, |
| @@ -141,7 +101,6 @@ struct sh_mobile_lcdc_priv { | |||
| 141 | unsigned long lddckr; | 101 | unsigned long lddckr; |
| 142 | struct sh_mobile_lcdc_chan ch[2]; | 102 | struct sh_mobile_lcdc_chan ch[2]; |
| 143 | struct notifier_block notifier; | 103 | struct notifier_block notifier; |
| 144 | unsigned long saved_shared_regs[NR_SHARED_REGS]; | ||
| 145 | int started; | 104 | int started; |
| 146 | int forced_bpp; /* 2 channel LCDC must share bpp setting */ | 105 | int forced_bpp; /* 2 channel LCDC must share bpp setting */ |
| 147 | struct sh_mobile_meram_info *meram_dev; | 106 | struct sh_mobile_meram_info *meram_dev; |
| @@ -218,33 +177,36 @@ static void lcdc_sys_write_index(void *handle, unsigned long data) | |||
| 218 | { | 177 | { |
| 219 | struct sh_mobile_lcdc_chan *ch = handle; | 178 | struct sh_mobile_lcdc_chan *ch = handle; |
| 220 | 179 | ||
| 221 | lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); | 180 | lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT); |
| 222 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 181 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
| 223 | lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | 182 | lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | |
| 224 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 183 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); |
| 184 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); | ||
| 225 | } | 185 | } |
| 226 | 186 | ||
| 227 | static void lcdc_sys_write_data(void *handle, unsigned long data) | 187 | static void lcdc_sys_write_data(void *handle, unsigned long data) |
| 228 | { | 188 | { |
| 229 | struct sh_mobile_lcdc_chan *ch = handle; | 189 | struct sh_mobile_lcdc_chan *ch = handle; |
| 230 | 190 | ||
| 231 | lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); | 191 | lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW); |
| 232 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 192 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
| 233 | lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | 193 | lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | |
| 234 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 194 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); |
| 195 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); | ||
| 235 | } | 196 | } |
| 236 | 197 | ||
| 237 | static unsigned long lcdc_sys_read_data(void *handle) | 198 | static unsigned long lcdc_sys_read_data(void *handle) |
| 238 | { | 199 | { |
| 239 | struct sh_mobile_lcdc_chan *ch = handle; | 200 | struct sh_mobile_lcdc_chan *ch = handle; |
| 240 | 201 | ||
| 241 | lcdc_write(ch->lcdc, _LDDRDR, 0x01000000); | 202 | lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR); |
| 242 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 203 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
| 243 | lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | 204 | lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA | |
| 205 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); | ||
| 244 | udelay(1); | 206 | udelay(1); |
| 245 | lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); | 207 | lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); |
| 246 | 208 | ||
| 247 | return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff; | 209 | return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; |
| 248 | } | 210 | } |
| 249 | 211 | ||
| 250 | struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { | 212 | struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { |
| @@ -256,18 +218,22 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { | |||
| 256 | static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) | 218 | static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) |
| 257 | { | 219 | { |
| 258 | if (atomic_inc_and_test(&priv->hw_usecnt)) { | 220 | if (atomic_inc_and_test(&priv->hw_usecnt)) { |
| 259 | pm_runtime_get_sync(priv->dev); | ||
| 260 | if (priv->dot_clk) | 221 | if (priv->dot_clk) |
| 261 | clk_enable(priv->dot_clk); | 222 | clk_enable(priv->dot_clk); |
| 223 | pm_runtime_get_sync(priv->dev); | ||
| 224 | if (priv->meram_dev && priv->meram_dev->pdev) | ||
| 225 | pm_runtime_get_sync(&priv->meram_dev->pdev->dev); | ||
| 262 | } | 226 | } |
| 263 | } | 227 | } |
| 264 | 228 | ||
| 265 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) | 229 | static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) |
| 266 | { | 230 | { |
| 267 | if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { | 231 | if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { |
| 232 | if (priv->meram_dev && priv->meram_dev->pdev) | ||
| 233 | pm_runtime_put_sync(&priv->meram_dev->pdev->dev); | ||
| 234 | pm_runtime_put(priv->dev); | ||
| 268 | if (priv->dot_clk) | 235 | if (priv->dot_clk) |
| 269 | clk_disable(priv->dot_clk); | 236 | clk_disable(priv->dot_clk); |
| 270 | pm_runtime_put(priv->dev); | ||
| 271 | } | 237 | } |
| 272 | } | 238 | } |
| 273 | 239 | ||
| @@ -319,13 +285,13 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info, | |||
| 319 | if (bcfg->start_transfer) | 285 | if (bcfg->start_transfer) |
| 320 | bcfg->start_transfer(bcfg->board_data, ch, | 286 | bcfg->start_transfer(bcfg->board_data, ch, |
| 321 | &sh_mobile_lcdc_sys_bus_ops); | 287 | &sh_mobile_lcdc_sys_bus_ops); |
| 322 | lcdc_write_chan(ch, LDSM2R, 1); | 288 | lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); |
| 323 | dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); | 289 | dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); |
| 324 | } else { | 290 | } else { |
| 325 | if (bcfg->start_transfer) | 291 | if (bcfg->start_transfer) |
| 326 | bcfg->start_transfer(bcfg->board_data, ch, | 292 | bcfg->start_transfer(bcfg->board_data, ch, |
| 327 | &sh_mobile_lcdc_sys_bus_ops); | 293 | &sh_mobile_lcdc_sys_bus_ops); |
| 328 | lcdc_write_chan(ch, LDSM2R, 1); | 294 | lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); |
| 329 | } | 295 | } |
| 330 | } | 296 | } |
| 331 | 297 | ||
| @@ -341,22 +307,16 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) | |||
| 341 | { | 307 | { |
| 342 | struct sh_mobile_lcdc_priv *priv = data; | 308 | struct sh_mobile_lcdc_priv *priv = data; |
| 343 | struct sh_mobile_lcdc_chan *ch; | 309 | struct sh_mobile_lcdc_chan *ch; |
| 344 | unsigned long tmp; | ||
| 345 | unsigned long ldintr; | 310 | unsigned long ldintr; |
| 346 | int is_sub; | 311 | int is_sub; |
| 347 | int k; | 312 | int k; |
| 348 | 313 | ||
| 349 | /* acknowledge interrupt */ | 314 | /* Acknowledge interrupts and disable further VSYNC End IRQs. */ |
| 350 | ldintr = tmp = lcdc_read(priv, _LDINTR); | 315 | ldintr = lcdc_read(priv, _LDINTR); |
| 351 | /* | 316 | lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE); |
| 352 | * disable further VSYNC End IRQs, preserve all other enabled IRQs, | ||
| 353 | * write 0 to bits 0-6 to ack all triggered IRQs. | ||
| 354 | */ | ||
| 355 | tmp &= 0xffffff00 & ~LDINTR_VEE; | ||
| 356 | lcdc_write(priv, _LDINTR, tmp); | ||
| 357 | 317 | ||
| 358 | /* figure out if this interrupt is for main or sub lcd */ | 318 | /* figure out if this interrupt is for main or sub lcd */ |
| 359 | is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; | 319 | is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0; |
| 360 | 320 | ||
| 361 | /* wake up channel and disable clocks */ | 321 | /* wake up channel and disable clocks */ |
| 362 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 322 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| @@ -365,7 +325,7 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) | |||
| 365 | if (!ch->enabled) | 325 | if (!ch->enabled) |
| 366 | continue; | 326 | continue; |
| 367 | 327 | ||
| 368 | /* Frame Start */ | 328 | /* Frame End */ |
| 369 | if (ldintr & LDINTR_FS) { | 329 | if (ldintr & LDINTR_FS) { |
| 370 | if (is_sub == lcdc_chan_is_sublcd(ch)) { | 330 | if (is_sub == lcdc_chan_is_sublcd(ch)) { |
| 371 | ch->frame_end = 1; | 331 | ch->frame_end = 1; |
| @@ -391,16 +351,17 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, | |||
| 391 | 351 | ||
| 392 | /* start or stop the lcdc */ | 352 | /* start or stop the lcdc */ |
| 393 | if (start) | 353 | if (start) |
| 394 | lcdc_write(priv, _LDCNT2R, tmp | START_LCDC); | 354 | lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO); |
| 395 | else | 355 | else |
| 396 | lcdc_write(priv, _LDCNT2R, tmp & ~START_LCDC); | 356 | lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO); |
| 397 | 357 | ||
| 398 | /* wait until power is applied/stopped on all channels */ | 358 | /* wait until power is applied/stopped on all channels */ |
| 399 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) | 359 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) |
| 400 | if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) | 360 | if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) |
| 401 | while (1) { | 361 | while (1) { |
| 402 | tmp = lcdc_read_chan(&priv->ch[k], LDPMR) & 3; | 362 | tmp = lcdc_read_chan(&priv->ch[k], LDPMR) |
| 403 | if (start && tmp == 3) | 363 | & LDPMR_LPS; |
| 364 | if (start && tmp == LDPMR_LPS) | ||
| 404 | break; | 365 | break; |
| 405 | if (!start && tmp == 0) | 366 | if (!start && tmp == 0) |
| 406 | break; | 367 | break; |
| @@ -418,13 +379,13 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | |||
| 418 | u32 tmp; | 379 | u32 tmp; |
| 419 | 380 | ||
| 420 | tmp = ch->ldmt1r_value; | 381 | tmp = ch->ldmt1r_value; |
| 421 | tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28; | 382 | tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; |
| 422 | tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27; | 383 | tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; |
| 423 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0; | 384 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; |
| 424 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0; | 385 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; |
| 425 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0; | 386 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; |
| 426 | tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0; | 387 | tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; |
| 427 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0; | 388 | tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; |
| 428 | lcdc_write_chan(ch, LDMT1R, tmp); | 389 | lcdc_write_chan(ch, LDMT1R, tmp); |
| 429 | 390 | ||
| 430 | /* setup SYS bus */ | 391 | /* setup SYS bus */ |
| @@ -463,242 +424,239 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) | |||
| 463 | lcdc_write_chan(ch, LDHAJR, tmp); | 424 | lcdc_write_chan(ch, LDHAJR, tmp); |
| 464 | } | 425 | } |
| 465 | 426 | ||
| 466 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | 427 | /* |
| 428 | * __sh_mobile_lcdc_start - Configure and tart the LCDC | ||
| 429 | * @priv: LCDC device | ||
| 430 | * | ||
| 431 | * Configure all enabled channels and start the LCDC device. All external | ||
| 432 | * devices (clocks, MERAM, panels, ...) are not touched by this function. | ||
| 433 | */ | ||
| 434 | static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) | ||
| 467 | { | 435 | { |
| 468 | struct sh_mobile_lcdc_chan *ch; | 436 | struct sh_mobile_lcdc_chan *ch; |
| 469 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
| 470 | unsigned long tmp; | 437 | unsigned long tmp; |
| 471 | int bpp = 0; | 438 | int bpp = 0; |
| 472 | unsigned long ldddsr; | 439 | int k, m; |
| 473 | int k, m, ret; | ||
| 474 | 440 | ||
| 475 | /* enable clocks before accessing the hardware */ | 441 | /* Enable LCDC channels. Read data from external memory, avoid using the |
| 476 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 442 | * BEU for now. |
| 477 | if (priv->ch[k].enabled) { | 443 | */ |
| 478 | sh_mobile_lcdc_clk_on(priv); | 444 | lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled); |
| 479 | if (!bpp) | ||
| 480 | bpp = priv->ch[k].info->var.bits_per_pixel; | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | /* reset */ | ||
| 485 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LCDC_RESET); | ||
| 486 | lcdc_wait_bit(priv, _LDCNT2R, LCDC_RESET, 0); | ||
| 487 | |||
| 488 | /* enable LCDC channels */ | ||
| 489 | tmp = lcdc_read(priv, _LDCNT2R); | ||
| 490 | tmp |= priv->ch[0].enabled; | ||
| 491 | tmp |= priv->ch[1].enabled; | ||
| 492 | lcdc_write(priv, _LDCNT2R, tmp); | ||
| 493 | |||
| 494 | /* read data from external memory, avoid using the BEU for now */ | ||
| 495 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) & ~DISPLAY_BEU); | ||
| 496 | 445 | ||
| 497 | /* stop the lcdc first */ | 446 | /* Stop the LCDC first and disable all interrupts. */ |
| 498 | sh_mobile_lcdc_start_stop(priv, 0); | 447 | sh_mobile_lcdc_start_stop(priv, 0); |
| 448 | lcdc_write(priv, _LDINTR, 0); | ||
| 499 | 449 | ||
| 500 | /* configure clocks */ | 450 | /* Configure power supply, dot clocks and start them. */ |
| 501 | tmp = priv->lddckr; | 451 | tmp = priv->lddckr; |
| 502 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 452 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| 503 | ch = &priv->ch[k]; | 453 | ch = &priv->ch[k]; |
| 504 | 454 | if (!ch->enabled) | |
| 505 | if (!priv->ch[k].enabled) | ||
| 506 | continue; | 455 | continue; |
| 507 | 456 | ||
| 457 | if (!bpp) | ||
| 458 | bpp = ch->info->var.bits_per_pixel; | ||
| 459 | |||
| 460 | /* Power supply */ | ||
| 461 | lcdc_write_chan(ch, LDPMR, 0); | ||
| 462 | |||
| 508 | m = ch->cfg.clock_divider; | 463 | m = ch->cfg.clock_divider; |
| 509 | if (!m) | 464 | if (!m) |
| 510 | continue; | 465 | continue; |
| 511 | 466 | ||
| 512 | if (m == 1) | 467 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider |
| 513 | m = 1 << 6; | 468 | * denominator. |
| 514 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); | 469 | */ |
| 515 | |||
| 516 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider denominator */ | ||
| 517 | lcdc_write_chan(ch, LDDCKPAT1R, 0); | 470 | lcdc_write_chan(ch, LDDCKPAT1R, 0); |
| 518 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); | 471 | lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); |
| 472 | |||
| 473 | if (m == 1) | ||
| 474 | m = LDDCKR_MOSEL; | ||
| 475 | tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); | ||
| 519 | } | 476 | } |
| 520 | 477 | ||
| 521 | lcdc_write(priv, _LDDCKR, tmp); | 478 | lcdc_write(priv, _LDDCKR, tmp); |
| 522 | |||
| 523 | /* start dotclock again */ | ||
| 524 | lcdc_write(priv, _LDDCKSTPR, 0); | 479 | lcdc_write(priv, _LDDCKSTPR, 0); |
| 525 | lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); | 480 | lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); |
| 526 | 481 | ||
| 527 | /* interrupts are disabled to begin with */ | 482 | /* Setup geometry, format, frame buffer memory and operation mode. */ |
| 528 | lcdc_write(priv, _LDINTR, 0); | ||
| 529 | |||
| 530 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 483 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| 531 | ch = &priv->ch[k]; | 484 | ch = &priv->ch[k]; |
| 532 | |||
| 533 | if (!ch->enabled) | 485 | if (!ch->enabled) |
| 534 | continue; | 486 | continue; |
| 535 | 487 | ||
| 536 | sh_mobile_lcdc_geometry(ch); | 488 | sh_mobile_lcdc_geometry(ch); |
| 537 | 489 | ||
| 538 | /* power supply */ | ||
| 539 | lcdc_write_chan(ch, LDPMR, 0); | ||
| 540 | |||
| 541 | board_cfg = &ch->cfg.board_cfg; | ||
| 542 | if (board_cfg->setup_sys) { | ||
| 543 | ret = board_cfg->setup_sys(board_cfg->board_data, | ||
| 544 | ch, &sh_mobile_lcdc_sys_bus_ops); | ||
| 545 | if (ret) | ||
| 546 | return ret; | ||
| 547 | } | ||
| 548 | } | ||
| 549 | |||
| 550 | /* word and long word swap */ | ||
| 551 | ldddsr = lcdc_read(priv, _LDDDSR); | ||
| 552 | if (priv->ch[0].info->var.nonstd) | ||
| 553 | lcdc_write(priv, _LDDDSR, ldddsr | 7); | ||
| 554 | else { | ||
| 555 | switch (bpp) { | ||
| 556 | case 16: | ||
| 557 | lcdc_write(priv, _LDDDSR, ldddsr | 6); | ||
| 558 | break; | ||
| 559 | case 24: | ||
| 560 | lcdc_write(priv, _LDDDSR, ldddsr | 7); | ||
| 561 | break; | ||
| 562 | case 32: | ||
| 563 | lcdc_write(priv, _LDDDSR, ldddsr | 4); | ||
| 564 | break; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | |||
| 568 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | ||
| 569 | unsigned long base_addr_y; | ||
| 570 | unsigned long base_addr_c = 0; | ||
| 571 | int pitch; | ||
| 572 | ch = &priv->ch[k]; | ||
| 573 | |||
| 574 | if (!priv->ch[k].enabled) | ||
| 575 | continue; | ||
| 576 | |||
| 577 | /* set bpp format in PKF[4:0] */ | ||
| 578 | tmp = lcdc_read_chan(ch, LDDFR); | ||
| 579 | tmp &= ~0x0003031f; | ||
| 580 | if (ch->info->var.nonstd) { | 490 | if (ch->info->var.nonstd) { |
| 581 | tmp |= (ch->info->var.nonstd << 16); | 491 | tmp = (ch->info->var.nonstd << 16); |
| 582 | switch (ch->info->var.bits_per_pixel) { | 492 | switch (ch->info->var.bits_per_pixel) { |
| 583 | case 12: | 493 | case 12: |
| 494 | tmp |= LDDFR_YF_420; | ||
| 584 | break; | 495 | break; |
| 585 | case 16: | 496 | case 16: |
| 586 | tmp |= (0x1 << 8); | 497 | tmp |= LDDFR_YF_422; |
| 587 | break; | 498 | break; |
| 588 | case 24: | 499 | case 24: |
| 589 | tmp |= (0x2 << 8); | 500 | default: |
| 501 | tmp |= LDDFR_YF_444; | ||
| 590 | break; | 502 | break; |
| 591 | } | 503 | } |
| 592 | } else { | 504 | } else { |
| 593 | switch (ch->info->var.bits_per_pixel) { | 505 | switch (ch->info->var.bits_per_pixel) { |
| 594 | case 16: | 506 | case 16: |
| 595 | tmp |= 0x03; | 507 | tmp = LDDFR_PKF_RGB16; |
| 596 | break; | 508 | break; |
| 597 | case 24: | 509 | case 24: |
| 598 | tmp |= 0x0b; | 510 | tmp = LDDFR_PKF_RGB24; |
| 599 | break; | 511 | break; |
| 600 | case 32: | 512 | case 32: |
| 513 | default: | ||
| 514 | tmp = LDDFR_PKF_ARGB32; | ||
| 601 | break; | 515 | break; |
| 602 | } | 516 | } |
| 603 | } | 517 | } |
| 518 | |||
| 604 | lcdc_write_chan(ch, LDDFR, tmp); | 519 | lcdc_write_chan(ch, LDDFR, tmp); |
| 520 | lcdc_write_chan(ch, LDMLSR, ch->pitch); | ||
| 521 | lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); | ||
| 522 | if (ch->info->var.nonstd) | ||
| 523 | lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); | ||
| 605 | 524 | ||
| 606 | base_addr_y = ch->info->fix.smem_start; | 525 | /* When using deferred I/O mode, configure the LCDC for one-shot |
| 607 | base_addr_c = base_addr_y + | 526 | * operation and enable the frame end interrupt. Otherwise use |
| 608 | ch->info->var.xres * | 527 | * continuous read mode. |
| 609 | ch->info->var.yres_virtual; | 528 | */ |
| 610 | pitch = ch->info->fix.line_length; | 529 | if (ch->ldmt1r_value & LDMT1R_IFM && |
| 530 | ch->cfg.sys_bus_cfg.deferred_io_msec) { | ||
| 531 | lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); | ||
| 532 | lcdc_write(priv, _LDINTR, LDINTR_FE); | ||
| 533 | } else { | ||
| 534 | lcdc_write_chan(ch, LDSM1R, 0); | ||
| 535 | } | ||
| 536 | } | ||
| 611 | 537 | ||
| 612 | /* test if we can enable meram */ | 538 | /* Word and long word swap. */ |
| 613 | if (ch->cfg.meram_cfg && priv->meram_dev && | 539 | if (priv->ch[0].info->var.nonstd) |
| 614 | priv->meram_dev->ops) { | 540 | tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; |
| 615 | struct sh_mobile_meram_cfg *cfg; | 541 | else { |
| 616 | struct sh_mobile_meram_info *mdev; | 542 | switch (bpp) { |
| 617 | unsigned long icb_addr_y, icb_addr_c; | 543 | case 16: |
| 618 | int icb_pitch; | 544 | tmp = LDDDSR_LS | LDDDSR_WS; |
| 619 | int pf; | 545 | break; |
| 546 | case 24: | ||
| 547 | tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; | ||
| 548 | break; | ||
| 549 | case 32: | ||
| 550 | default: | ||
| 551 | tmp = LDDDSR_LS; | ||
| 552 | break; | ||
| 553 | } | ||
| 554 | } | ||
| 555 | lcdc_write(priv, _LDDDSR, tmp); | ||
| 620 | 556 | ||
| 621 | cfg = ch->cfg.meram_cfg; | 557 | /* Enable the display output. */ |
| 622 | mdev = priv->meram_dev; | 558 | lcdc_write(priv, _LDCNT1R, LDCNT1R_DE); |
| 623 | /* we need to de-init configured ICBs before we | 559 | sh_mobile_lcdc_start_stop(priv, 1); |
| 624 | * we can re-initialize them. | 560 | priv->started = 1; |
| 625 | */ | 561 | } |
| 626 | if (ch->meram_enabled) | ||
| 627 | mdev->ops->meram_unregister(mdev, cfg); | ||
| 628 | 562 | ||
| 629 | ch->meram_enabled = 0; | 563 | static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) |
| 564 | { | ||
| 565 | struct sh_mobile_meram_info *mdev = priv->meram_dev; | ||
| 566 | struct sh_mobile_lcdc_board_cfg *board_cfg; | ||
| 567 | struct sh_mobile_lcdc_chan *ch; | ||
| 568 | unsigned long tmp; | ||
| 569 | int ret; | ||
| 570 | int k; | ||
| 630 | 571 | ||
| 631 | if (ch->info->var.nonstd) { | 572 | /* enable clocks before accessing the hardware */ |
| 632 | if (ch->info->var.bits_per_pixel == 24) | 573 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| 633 | pf = SH_MOBILE_MERAM_PF_NV24; | 574 | if (priv->ch[k].enabled) |
| 634 | else | 575 | sh_mobile_lcdc_clk_on(priv); |
| 635 | pf = SH_MOBILE_MERAM_PF_NV; | 576 | } |
| 636 | } else { | ||
| 637 | pf = SH_MOBILE_MERAM_PF_RGB; | ||
| 638 | } | ||
| 639 | 577 | ||
| 640 | ret = mdev->ops->meram_register(mdev, cfg, pitch, | 578 | /* reset */ |
| 641 | ch->info->var.yres, | 579 | lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR); |
| 642 | pf, | 580 | lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); |
| 643 | base_addr_y, | ||
| 644 | base_addr_c, | ||
| 645 | &icb_addr_y, | ||
| 646 | &icb_addr_c, | ||
| 647 | &icb_pitch); | ||
| 648 | if (!ret) { | ||
| 649 | /* set LDSA1R value */ | ||
| 650 | base_addr_y = icb_addr_y; | ||
| 651 | pitch = icb_pitch; | ||
| 652 | |||
| 653 | /* set LDSA2R value if required */ | ||
| 654 | if (base_addr_c) | ||
| 655 | base_addr_c = icb_addr_c; | ||
| 656 | |||
| 657 | ch->meram_enabled = 1; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | 581 | ||
| 661 | /* point out our frame buffer */ | 582 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| 662 | lcdc_write_chan(ch, LDSA1R, base_addr_y); | 583 | ch = &priv->ch[k]; |
| 663 | if (ch->info->var.nonstd) | ||
| 664 | lcdc_write_chan(ch, LDSA2R, base_addr_c); | ||
| 665 | 584 | ||
| 666 | /* set line size */ | 585 | if (!ch->enabled) |
| 667 | lcdc_write_chan(ch, LDMLSR, pitch); | 586 | continue; |
| 668 | 587 | ||
| 669 | /* setup deferred io if SYS bus */ | 588 | board_cfg = &ch->cfg.board_cfg; |
| 670 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; | 589 | if (board_cfg->setup_sys) { |
| 671 | if (ch->ldmt1r_value & (1 << 12) && tmp) { | 590 | ret = board_cfg->setup_sys(board_cfg->board_data, ch, |
| 672 | ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; | 591 | &sh_mobile_lcdc_sys_bus_ops); |
| 673 | ch->defio.delay = msecs_to_jiffies(tmp); | 592 | if (ret) |
| 674 | ch->info->fbdefio = &ch->defio; | 593 | return ret; |
| 675 | fb_deferred_io_init(ch->info); | 594 | } |
| 595 | } | ||
| 676 | 596 | ||
| 677 | /* one-shot mode */ | 597 | /* Compute frame buffer base address and pitch for each channel. */ |
| 678 | lcdc_write_chan(ch, LDSM1R, 1); | 598 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| 599 | struct sh_mobile_meram_cfg *cfg; | ||
| 600 | int pixelformat; | ||
| 679 | 601 | ||
| 680 | /* enable "Frame End Interrupt Enable" bit */ | 602 | ch = &priv->ch[k]; |
| 681 | lcdc_write(priv, _LDINTR, LDINTR_FE); | 603 | if (!ch->enabled) |
| 604 | continue; | ||
| 682 | 605 | ||
| 683 | } else { | 606 | ch->base_addr_y = ch->info->fix.smem_start; |
| 684 | /* continuous read mode */ | 607 | ch->base_addr_c = ch->base_addr_y |
| 685 | lcdc_write_chan(ch, LDSM1R, 0); | 608 | + ch->info->var.xres |
| 609 | * ch->info->var.yres_virtual; | ||
| 610 | ch->pitch = ch->info->fix.line_length; | ||
| 611 | |||
| 612 | /* Enable MERAM if possible. */ | ||
| 613 | cfg = ch->cfg.meram_cfg; | ||
| 614 | if (mdev == NULL || mdev->ops == NULL || cfg == NULL) | ||
| 615 | continue; | ||
| 616 | |||
| 617 | /* we need to de-init configured ICBs before we can | ||
| 618 | * re-initialize them. | ||
| 619 | */ | ||
| 620 | if (ch->meram_enabled) { | ||
| 621 | mdev->ops->meram_unregister(mdev, cfg); | ||
| 622 | ch->meram_enabled = 0; | ||
| 686 | } | 623 | } |
| 624 | |||
| 625 | if (!ch->info->var.nonstd) | ||
| 626 | pixelformat = SH_MOBILE_MERAM_PF_RGB; | ||
| 627 | else if (ch->info->var.bits_per_pixel == 24) | ||
| 628 | pixelformat = SH_MOBILE_MERAM_PF_NV24; | ||
| 629 | else | ||
| 630 | pixelformat = SH_MOBILE_MERAM_PF_NV; | ||
| 631 | |||
| 632 | ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, | ||
| 633 | ch->info->var.yres, pixelformat, | ||
| 634 | ch->base_addr_y, ch->base_addr_c, | ||
| 635 | &ch->base_addr_y, &ch->base_addr_c, | ||
| 636 | &ch->pitch); | ||
| 637 | if (!ret) | ||
| 638 | ch->meram_enabled = 1; | ||
| 687 | } | 639 | } |
| 688 | 640 | ||
| 689 | /* display output */ | 641 | /* Start the LCDC. */ |
| 690 | lcdc_write(priv, _LDCNT1R, LCDC_ENABLE); | 642 | __sh_mobile_lcdc_start(priv); |
| 691 | 643 | ||
| 692 | /* start the lcdc */ | 644 | /* Setup deferred I/O, tell the board code to enable the panels, and |
| 693 | sh_mobile_lcdc_start_stop(priv, 1); | 645 | * turn backlight on. |
| 694 | priv->started = 1; | 646 | */ |
| 695 | |||
| 696 | /* tell the board code to enable the panel */ | ||
| 697 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { | 647 | for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { |
| 698 | ch = &priv->ch[k]; | 648 | ch = &priv->ch[k]; |
| 699 | if (!ch->enabled) | 649 | if (!ch->enabled) |
| 700 | continue; | 650 | continue; |
| 701 | 651 | ||
| 652 | tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; | ||
| 653 | if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { | ||
| 654 | ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; | ||
| 655 | ch->defio.delay = msecs_to_jiffies(tmp); | ||
| 656 | ch->info->fbdefio = &ch->defio; | ||
| 657 | fb_deferred_io_init(ch->info); | ||
| 658 | } | ||
| 659 | |||
| 702 | board_cfg = &ch->cfg.board_cfg; | 660 | board_cfg = &ch->cfg.board_cfg; |
| 703 | if (board_cfg->display_on && try_module_get(board_cfg->owner)) { | 661 | if (board_cfg->display_on && try_module_get(board_cfg->owner)) { |
| 704 | board_cfg->display_on(board_cfg->board_data, ch->info); | 662 | board_cfg->display_on(board_cfg->board_data, ch->info); |
| @@ -776,42 +734,42 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) | |||
| 776 | 734 | ||
| 777 | static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) | 735 | static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) |
| 778 | { | 736 | { |
| 779 | int ifm, miftyp; | 737 | int interface_type = ch->cfg.interface_type; |
| 780 | 738 | ||
| 781 | switch (ch->cfg.interface_type) { | 739 | switch (interface_type) { |
| 782 | case RGB8: ifm = 0; miftyp = 0; break; | 740 | case RGB8: |
| 783 | case RGB9: ifm = 0; miftyp = 4; break; | 741 | case RGB9: |
| 784 | case RGB12A: ifm = 0; miftyp = 5; break; | 742 | case RGB12A: |
| 785 | case RGB12B: ifm = 0; miftyp = 6; break; | 743 | case RGB12B: |
| 786 | case RGB16: ifm = 0; miftyp = 7; break; | 744 | case RGB16: |
| 787 | case RGB18: ifm = 0; miftyp = 10; break; | 745 | case RGB18: |
| 788 | case RGB24: ifm = 0; miftyp = 11; break; | 746 | case RGB24: |
| 789 | case SYS8A: ifm = 1; miftyp = 0; break; | 747 | case SYS8A: |
| 790 | case SYS8B: ifm = 1; miftyp = 1; break; | 748 | case SYS8B: |
| 791 | case SYS8C: ifm = 1; miftyp = 2; break; | 749 | case SYS8C: |
| 792 | case SYS8D: ifm = 1; miftyp = 3; break; | 750 | case SYS8D: |
| 793 | case SYS9: ifm = 1; miftyp = 4; break; | 751 | case SYS9: |
| 794 | case SYS12: ifm = 1; miftyp = 5; break; | 752 | case SYS12: |
| 795 | case SYS16A: ifm = 1; miftyp = 7; break; | 753 | case SYS16A: |
| 796 | case SYS16B: ifm = 1; miftyp = 8; break; | 754 | case SYS16B: |
| 797 | case SYS16C: ifm = 1; miftyp = 9; break; | 755 | case SYS16C: |
| 798 | case SYS18: ifm = 1; miftyp = 10; break; | 756 | case SYS18: |
| 799 | case SYS24: ifm = 1; miftyp = 11; break; | 757 | case SYS24: |
| 800 | default: goto bad; | 758 | break; |
| 759 | default: | ||
| 760 | return -EINVAL; | ||
| 801 | } | 761 | } |
| 802 | 762 | ||
| 803 | /* SUBLCD only supports SYS interface */ | 763 | /* SUBLCD only supports SYS interface */ |
| 804 | if (lcdc_chan_is_sublcd(ch)) { | 764 | if (lcdc_chan_is_sublcd(ch)) { |
| 805 | if (ifm == 0) | 765 | if (!(interface_type & LDMT1R_IFM)) |
| 806 | goto bad; | 766 | return -EINVAL; |
| 807 | else | 767 | |
| 808 | ifm = 0; | 768 | interface_type &= ~LDMT1R_IFM; |
| 809 | } | 769 | } |
| 810 | 770 | ||
| 811 | ch->ldmt1r_value = (ifm << 12) | miftyp; | 771 | ch->ldmt1r_value = interface_type; |
| 812 | return 0; | 772 | return 0; |
| 813 | bad: | ||
| 814 | return -EINVAL; | ||
| 815 | } | 773 | } |
| 816 | 774 | ||
| 817 | static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, | 775 | static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, |
| @@ -819,18 +777,24 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, | |||
| 819 | struct sh_mobile_lcdc_priv *priv) | 777 | struct sh_mobile_lcdc_priv *priv) |
| 820 | { | 778 | { |
| 821 | char *str; | 779 | char *str; |
| 822 | int icksel; | ||
| 823 | 780 | ||
| 824 | switch (clock_source) { | 781 | switch (clock_source) { |
| 825 | case LCDC_CLK_BUS: str = "bus_clk"; icksel = 0; break; | 782 | case LCDC_CLK_BUS: |
| 826 | case LCDC_CLK_PERIPHERAL: str = "peripheral_clk"; icksel = 1; break; | 783 | str = "bus_clk"; |
| 827 | case LCDC_CLK_EXTERNAL: str = NULL; icksel = 2; break; | 784 | priv->lddckr = LDDCKR_ICKSEL_BUS; |
| 785 | break; | ||
| 786 | case LCDC_CLK_PERIPHERAL: | ||
| 787 | str = "peripheral_clk"; | ||
| 788 | priv->lddckr = LDDCKR_ICKSEL_MIPI; | ||
| 789 | break; | ||
| 790 | case LCDC_CLK_EXTERNAL: | ||
| 791 | str = NULL; | ||
| 792 | priv->lddckr = LDDCKR_ICKSEL_HDMI; | ||
| 793 | break; | ||
| 828 | default: | 794 | default: |
| 829 | return -EINVAL; | 795 | return -EINVAL; |
| 830 | } | 796 | } |
| 831 | 797 | ||
| 832 | priv->lddckr = icksel << 16; | ||
| 833 | |||
| 834 | if (str) { | 798 | if (str) { |
| 835 | priv->dot_clk = clk_get(&pdev->dev, str); | 799 | priv->dot_clk = clk_get(&pdev->dev, str); |
| 836 | if (IS_ERR(priv->dot_clk)) { | 800 | if (IS_ERR(priv->dot_clk)) { |
| @@ -914,12 +878,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, | |||
| 914 | unsigned long base_addr_y, base_addr_c; | 878 | unsigned long base_addr_y, base_addr_c; |
| 915 | unsigned long c_offset; | 879 | unsigned long c_offset; |
| 916 | 880 | ||
| 917 | if (!var->nonstd) | 881 | if (!info->var.nonstd) |
| 918 | new_pan_offset = (var->yoffset * info->fix.line_length) + | 882 | new_pan_offset = var->yoffset * info->fix.line_length |
| 919 | (var->xoffset * (info->var.bits_per_pixel / 8)); | 883 | + var->xoffset * (info->var.bits_per_pixel / 8); |
| 920 | else | 884 | else |
| 921 | new_pan_offset = (var->yoffset * info->fix.line_length) + | 885 | new_pan_offset = var->yoffset * info->fix.line_length |
| 922 | (var->xoffset); | 886 | + var->xoffset; |
| 923 | 887 | ||
| 924 | if (new_pan_offset == ch->pan_offset) | 888 | if (new_pan_offset == ch->pan_offset) |
| 925 | return 0; /* No change, do nothing */ | 889 | return 0; /* No change, do nothing */ |
| @@ -928,44 +892,40 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var, | |||
| 928 | 892 | ||
| 929 | /* Set the source address for the next refresh */ | 893 | /* Set the source address for the next refresh */ |
| 930 | base_addr_y = ch->dma_handle + new_pan_offset; | 894 | base_addr_y = ch->dma_handle + new_pan_offset; |
| 931 | if (var->nonstd) { | 895 | if (info->var.nonstd) { |
| 932 | /* Set y offset */ | 896 | /* Set y offset */ |
| 933 | c_offset = (var->yoffset * | 897 | c_offset = var->yoffset * info->fix.line_length |
| 934 | info->fix.line_length * | 898 | * (info->var.bits_per_pixel - 8) / 8; |
| 935 | (info->var.bits_per_pixel - 8)) / 8; | 899 | base_addr_c = ch->dma_handle |
| 936 | base_addr_c = ch->dma_handle + var->xres * var->yres_virtual + | 900 | + info->var.xres * info->var.yres_virtual |
| 937 | c_offset; | 901 | + c_offset; |
| 938 | /* Set x offset */ | 902 | /* Set x offset */ |
| 939 | if (info->var.bits_per_pixel == 24) | 903 | if (info->var.bits_per_pixel == 24) |
| 940 | base_addr_c += 2 * var->xoffset; | 904 | base_addr_c += 2 * var->xoffset; |
| 941 | else | 905 | else |
| 942 | base_addr_c += var->xoffset; | 906 | base_addr_c += var->xoffset; |
| 943 | } else | 907 | } |
| 944 | base_addr_c = 0; | ||
| 945 | 908 | ||
| 946 | if (!ch->meram_enabled) { | 909 | if (ch->meram_enabled) { |
| 947 | lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); | ||
| 948 | if (base_addr_c) | ||
| 949 | lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); | ||
| 950 | } else { | ||
| 951 | struct sh_mobile_meram_cfg *cfg; | 910 | struct sh_mobile_meram_cfg *cfg; |
| 952 | struct sh_mobile_meram_info *mdev; | 911 | struct sh_mobile_meram_info *mdev; |
| 953 | unsigned long icb_addr_y, icb_addr_c; | ||
| 954 | int ret; | 912 | int ret; |
| 955 | 913 | ||
| 956 | cfg = ch->cfg.meram_cfg; | 914 | cfg = ch->cfg.meram_cfg; |
| 957 | mdev = priv->meram_dev; | 915 | mdev = priv->meram_dev; |
| 958 | ret = mdev->ops->meram_update(mdev, cfg, | 916 | ret = mdev->ops->meram_update(mdev, cfg, |
| 959 | base_addr_y, base_addr_c, | 917 | base_addr_y, base_addr_c, |
| 960 | &icb_addr_y, &icb_addr_c); | 918 | &base_addr_y, &base_addr_c); |
| 961 | if (ret) | 919 | if (ret) |
| 962 | return ret; | 920 | return ret; |
| 921 | } | ||
| 963 | 922 | ||
| 964 | lcdc_write_chan_mirror(ch, LDSA1R, icb_addr_y); | 923 | ch->base_addr_y = base_addr_y; |
| 965 | if (icb_addr_c) | 924 | ch->base_addr_c = base_addr_c; |
| 966 | lcdc_write_chan_mirror(ch, LDSA2R, icb_addr_c); | ||
| 967 | 925 | ||
| 968 | } | 926 | lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); |
| 927 | if (info->var.nonstd) | ||
| 928 | lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); | ||
| 969 | 929 | ||
| 970 | if (lcdc_chan_is_sublcd(ch)) | 930 | if (lcdc_chan_is_sublcd(ch)) |
| 971 | lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); | 931 | lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); |
| @@ -985,9 +945,11 @@ static int sh_mobile_wait_for_vsync(struct fb_info *info) | |||
| 985 | unsigned long ldintr; | 945 | unsigned long ldintr; |
| 986 | int ret; | 946 | int ret; |
| 987 | 947 | ||
| 988 | /* Enable VSync End interrupt */ | 948 | /* Enable VSync End interrupt and be careful not to acknowledge any |
| 949 | * pending interrupt. | ||
| 950 | */ | ||
| 989 | ldintr = lcdc_read(ch->lcdc, _LDINTR); | 951 | ldintr = lcdc_read(ch->lcdc, _LDINTR); |
| 990 | ldintr |= LDINTR_VEE; | 952 | ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK; |
| 991 | lcdc_write(ch->lcdc, _LDINTR, ldintr); | 953 | lcdc_write(ch->lcdc, _LDINTR, ldintr); |
| 992 | 954 | ||
| 993 | ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, | 955 | ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, |
| @@ -1037,11 +999,6 @@ static void sh_mobile_fb_reconfig(struct fb_info *info) | |||
| 1037 | /* Couldn't reconfigure, hopefully, can continue as before */ | 999 | /* Couldn't reconfigure, hopefully, can continue as before */ |
| 1038 | return; | 1000 | return; |
| 1039 | 1001 | ||
| 1040 | if (info->var.nonstd) | ||
| 1041 | info->fix.line_length = mode1.xres; | ||
| 1042 | else | ||
| 1043 | info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8); | ||
| 1044 | |||
| 1045 | /* | 1002 | /* |
| 1046 | * fb_set_var() calls the notifier change internally, only if | 1003 | * fb_set_var() calls the notifier change internally, only if |
| 1047 | * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a | 1004 | * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a |
| @@ -1094,30 +1051,126 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in | |||
| 1094 | { | 1051 | { |
| 1095 | struct sh_mobile_lcdc_chan *ch = info->par; | 1052 | struct sh_mobile_lcdc_chan *ch = info->par; |
| 1096 | struct sh_mobile_lcdc_priv *p = ch->lcdc; | 1053 | struct sh_mobile_lcdc_priv *p = ch->lcdc; |
| 1054 | unsigned int best_dist = (unsigned int)-1; | ||
| 1055 | unsigned int best_xres = 0; | ||
| 1056 | unsigned int best_yres = 0; | ||
| 1057 | unsigned int i; | ||
| 1097 | 1058 | ||
| 1098 | if (var->xres > MAX_XRES || var->yres > MAX_YRES || | 1059 | if (var->xres > MAX_XRES || var->yres > MAX_YRES) |
| 1099 | var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) { | ||
| 1100 | dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %lukHz!\n", | ||
| 1101 | var->left_margin, var->xres, var->right_margin, var->hsync_len, | ||
| 1102 | var->upper_margin, var->yres, var->lower_margin, var->vsync_len, | ||
| 1103 | PICOS2KHZ(var->pixclock)); | ||
| 1104 | return -EINVAL; | 1060 | return -EINVAL; |
| 1061 | |||
| 1062 | /* If board code provides us with a list of available modes, make sure | ||
| 1063 | * we use one of them. Find the mode closest to the requested one. The | ||
| 1064 | * distance between two modes is defined as the size of the | ||
| 1065 | * non-overlapping parts of the two rectangles. | ||
| 1066 | */ | ||
| 1067 | for (i = 0; i < ch->cfg.num_cfg; ++i) { | ||
| 1068 | const struct fb_videomode *mode = &ch->cfg.lcd_cfg[i]; | ||
| 1069 | unsigned int dist; | ||
| 1070 | |||
| 1071 | /* We can only round up. */ | ||
| 1072 | if (var->xres > mode->xres || var->yres > mode->yres) | ||
| 1073 | continue; | ||
| 1074 | |||
| 1075 | dist = var->xres * var->yres + mode->xres * mode->yres | ||
| 1076 | - 2 * min(var->xres, mode->xres) | ||
| 1077 | * min(var->yres, mode->yres); | ||
| 1078 | |||
| 1079 | if (dist < best_dist) { | ||
| 1080 | best_xres = mode->xres; | ||
| 1081 | best_yres = mode->yres; | ||
| 1082 | best_dist = dist; | ||
| 1083 | } | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /* If no available mode can be used, return an error. */ | ||
| 1087 | if (ch->cfg.num_cfg != 0) { | ||
| 1088 | if (best_dist == (unsigned int)-1) | ||
| 1089 | return -EINVAL; | ||
| 1090 | |||
| 1091 | var->xres = best_xres; | ||
| 1092 | var->yres = best_yres; | ||
| 1105 | } | 1093 | } |
| 1106 | 1094 | ||
| 1095 | /* Make sure the virtual resolution is at least as big as the visible | ||
| 1096 | * resolution. | ||
| 1097 | */ | ||
| 1098 | if (var->xres_virtual < var->xres) | ||
| 1099 | var->xres_virtual = var->xres; | ||
| 1100 | if (var->yres_virtual < var->yres) | ||
| 1101 | var->yres_virtual = var->yres; | ||
| 1102 | |||
| 1103 | if (var->bits_per_pixel <= 16) { /* RGB 565 */ | ||
| 1104 | var->bits_per_pixel = 16; | ||
| 1105 | var->red.offset = 11; | ||
| 1106 | var->red.length = 5; | ||
| 1107 | var->green.offset = 5; | ||
| 1108 | var->green.length = 6; | ||
| 1109 | var->blue.offset = 0; | ||
| 1110 | var->blue.length = 5; | ||
| 1111 | var->transp.offset = 0; | ||
| 1112 | var->transp.length = 0; | ||
| 1113 | } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ | ||
| 1114 | var->bits_per_pixel = 24; | ||
| 1115 | var->red.offset = 16; | ||
| 1116 | var->red.length = 8; | ||
| 1117 | var->green.offset = 8; | ||
| 1118 | var->green.length = 8; | ||
| 1119 | var->blue.offset = 0; | ||
| 1120 | var->blue.length = 8; | ||
| 1121 | var->transp.offset = 0; | ||
| 1122 | var->transp.length = 0; | ||
| 1123 | } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ | ||
| 1124 | var->bits_per_pixel = 32; | ||
| 1125 | var->red.offset = 16; | ||
| 1126 | var->red.length = 8; | ||
| 1127 | var->green.offset = 8; | ||
| 1128 | var->green.length = 8; | ||
| 1129 | var->blue.offset = 0; | ||
| 1130 | var->blue.length = 8; | ||
| 1131 | var->transp.offset = 24; | ||
| 1132 | var->transp.length = 8; | ||
| 1133 | } else | ||
| 1134 | return -EINVAL; | ||
| 1135 | |||
| 1136 | var->red.msb_right = 0; | ||
| 1137 | var->green.msb_right = 0; | ||
| 1138 | var->blue.msb_right = 0; | ||
| 1139 | var->transp.msb_right = 0; | ||
| 1140 | |||
| 1141 | /* Make sure we don't exceed our allocated memory. */ | ||
| 1142 | if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > | ||
| 1143 | info->fix.smem_len) | ||
| 1144 | return -EINVAL; | ||
| 1145 | |||
| 1107 | /* only accept the forced_bpp for dual channel configurations */ | 1146 | /* only accept the forced_bpp for dual channel configurations */ |
| 1108 | if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) | 1147 | if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) |
| 1109 | return -EINVAL; | 1148 | return -EINVAL; |
| 1110 | 1149 | ||
| 1111 | switch (var->bits_per_pixel) { | 1150 | return 0; |
| 1112 | case 16: /* PKF[4:0] = 00011 - RGB 565 */ | 1151 | } |
| 1113 | case 24: /* PKF[4:0] = 01011 - RGB 888 */ | 1152 | |
| 1114 | case 32: /* PKF[4:0] = 00000 - RGBA 888 */ | 1153 | static int sh_mobile_set_par(struct fb_info *info) |
| 1115 | break; | 1154 | { |
| 1116 | default: | 1155 | struct sh_mobile_lcdc_chan *ch = info->par; |
| 1117 | return -EINVAL; | 1156 | u32 line_length = info->fix.line_length; |
| 1157 | int ret; | ||
| 1158 | |||
| 1159 | sh_mobile_lcdc_stop(ch->lcdc); | ||
| 1160 | |||
| 1161 | if (info->var.nonstd) | ||
| 1162 | info->fix.line_length = info->var.xres; | ||
| 1163 | else | ||
| 1164 | info->fix.line_length = info->var.xres | ||
| 1165 | * info->var.bits_per_pixel / 8; | ||
| 1166 | |||
| 1167 | ret = sh_mobile_lcdc_start(ch->lcdc); | ||
| 1168 | if (ret < 0) { | ||
| 1169 | dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); | ||
| 1170 | info->fix.line_length = line_length; | ||
| 1118 | } | 1171 | } |
| 1119 | 1172 | ||
| 1120 | return 0; | 1173 | return ret; |
| 1121 | } | 1174 | } |
| 1122 | 1175 | ||
| 1123 | /* | 1176 | /* |
| @@ -1177,6 +1230,7 @@ static struct fb_ops sh_mobile_lcdc_ops = { | |||
| 1177 | .fb_open = sh_mobile_open, | 1230 | .fb_open = sh_mobile_open, |
| 1178 | .fb_release = sh_mobile_release, | 1231 | .fb_release = sh_mobile_release, |
| 1179 | .fb_check_var = sh_mobile_check_var, | 1232 | .fb_check_var = sh_mobile_check_var, |
| 1233 | .fb_set_par = sh_mobile_set_par, | ||
| 1180 | }; | 1234 | }; |
| 1181 | 1235 | ||
| 1182 | static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) | 1236 | static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) |
| @@ -1238,66 +1292,6 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev) | |||
| 1238 | backlight_device_unregister(bdev); | 1292 | backlight_device_unregister(bdev); |
| 1239 | } | 1293 | } |
| 1240 | 1294 | ||
| 1241 | static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp, | ||
| 1242 | int nonstd) | ||
| 1243 | { | ||
| 1244 | if (nonstd) { | ||
| 1245 | switch (bpp) { | ||
| 1246 | case 12: | ||
| 1247 | case 16: | ||
| 1248 | case 24: | ||
| 1249 | var->bits_per_pixel = bpp; | ||
| 1250 | var->nonstd = nonstd; | ||
| 1251 | return 0; | ||
| 1252 | default: | ||
| 1253 | return -EINVAL; | ||
| 1254 | } | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | switch (bpp) { | ||
| 1258 | case 16: /* PKF[4:0] = 00011 - RGB 565 */ | ||
| 1259 | var->red.offset = 11; | ||
| 1260 | var->red.length = 5; | ||
| 1261 | var->green.offset = 5; | ||
| 1262 | var->green.length = 6; | ||
| 1263 | var->blue.offset = 0; | ||
| 1264 | var->blue.length = 5; | ||
| 1265 | var->transp.offset = 0; | ||
| 1266 | var->transp.length = 0; | ||
| 1267 | break; | ||
| 1268 | |||
| 1269 | case 24: /* PKF[4:0] = 01011 - RGB 888 */ | ||
| 1270 | var->red.offset = 16; | ||
| 1271 | var->red.length = 8; | ||
| 1272 | var->green.offset = 8; | ||
| 1273 | var->green.length = 8; | ||
| 1274 | var->blue.offset = 0; | ||
| 1275 | var->blue.length = 8; | ||
| 1276 | var->transp.offset = 0; | ||
| 1277 | var->transp.length = 0; | ||
| 1278 | break; | ||
| 1279 | |||
| 1280 | case 32: /* PKF[4:0] = 00000 - RGBA 888 */ | ||
| 1281 | var->red.offset = 16; | ||
| 1282 | var->red.length = 8; | ||
| 1283 | var->green.offset = 8; | ||
| 1284 | var->green.length = 8; | ||
| 1285 | var->blue.offset = 0; | ||
| 1286 | var->blue.length = 8; | ||
| 1287 | var->transp.offset = 24; | ||
| 1288 | var->transp.length = 8; | ||
| 1289 | break; | ||
| 1290 | default: | ||
| 1291 | return -EINVAL; | ||
| 1292 | } | ||
| 1293 | var->bits_per_pixel = bpp; | ||
| 1294 | var->red.msb_right = 0; | ||
| 1295 | var->green.msb_right = 0; | ||
| 1296 | var->blue.msb_right = 0; | ||
| 1297 | var->transp.msb_right = 0; | ||
| 1298 | return 0; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | static int sh_mobile_lcdc_suspend(struct device *dev) | 1295 | static int sh_mobile_lcdc_suspend(struct device *dev) |
| 1302 | { | 1296 | { |
| 1303 | struct platform_device *pdev = to_platform_device(dev); | 1297 | struct platform_device *pdev = to_platform_device(dev); |
| @@ -1316,47 +1310,20 @@ static int sh_mobile_lcdc_resume(struct device *dev) | |||
| 1316 | static int sh_mobile_lcdc_runtime_suspend(struct device *dev) | 1310 | static int sh_mobile_lcdc_runtime_suspend(struct device *dev) |
| 1317 | { | 1311 | { |
| 1318 | struct platform_device *pdev = to_platform_device(dev); | 1312 | struct platform_device *pdev = to_platform_device(dev); |
| 1319 | struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); | 1313 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); |
| 1320 | struct sh_mobile_lcdc_chan *ch; | ||
| 1321 | int k, n; | ||
| 1322 | |||
| 1323 | /* save per-channel registers */ | ||
| 1324 | for (k = 0; k < ARRAY_SIZE(p->ch); k++) { | ||
| 1325 | ch = &p->ch[k]; | ||
| 1326 | if (!ch->enabled) | ||
| 1327 | continue; | ||
| 1328 | for (n = 0; n < NR_CH_REGS; n++) | ||
| 1329 | ch->saved_ch_regs[n] = lcdc_read_chan(ch, n); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | /* save shared registers */ | ||
| 1333 | for (n = 0; n < NR_SHARED_REGS; n++) | ||
| 1334 | p->saved_shared_regs[n] = lcdc_read(p, lcdc_shared_regs[n]); | ||
| 1335 | 1314 | ||
| 1336 | /* turn off LCDC hardware */ | 1315 | /* turn off LCDC hardware */ |
| 1337 | lcdc_write(p, _LDCNT1R, 0); | 1316 | lcdc_write(priv, _LDCNT1R, 0); |
| 1317 | |||
| 1338 | return 0; | 1318 | return 0; |
| 1339 | } | 1319 | } |
| 1340 | 1320 | ||
| 1341 | static int sh_mobile_lcdc_runtime_resume(struct device *dev) | 1321 | static int sh_mobile_lcdc_runtime_resume(struct device *dev) |
| 1342 | { | 1322 | { |
| 1343 | struct platform_device *pdev = to_platform_device(dev); | 1323 | struct platform_device *pdev = to_platform_device(dev); |
| 1344 | struct sh_mobile_lcdc_priv *p = platform_get_drvdata(pdev); | 1324 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); |
| 1345 | struct sh_mobile_lcdc_chan *ch; | ||
| 1346 | int k, n; | ||
| 1347 | |||
| 1348 | /* restore per-channel registers */ | ||
| 1349 | for (k = 0; k < ARRAY_SIZE(p->ch); k++) { | ||
| 1350 | ch = &p->ch[k]; | ||
| 1351 | if (!ch->enabled) | ||
| 1352 | continue; | ||
| 1353 | for (n = 0; n < NR_CH_REGS; n++) | ||
| 1354 | lcdc_write_chan(ch, n, ch->saved_ch_regs[n]); | ||
| 1355 | } | ||
| 1356 | 1325 | ||
| 1357 | /* restore shared registers */ | 1326 | __sh_mobile_lcdc_start(priv); |
| 1358 | for (n = 0; n < NR_SHARED_REGS; n++) | ||
| 1359 | lcdc_write(p, lcdc_shared_regs[n], p->saved_shared_regs[n]); | ||
| 1360 | 1327 | ||
| 1361 | return 0; | 1328 | return 0; |
| 1362 | } | 1329 | } |
| @@ -1408,17 +1375,187 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb, | |||
| 1408 | return NOTIFY_OK; | 1375 | return NOTIFY_OK; |
| 1409 | } | 1376 | } |
| 1410 | 1377 | ||
| 1411 | static int sh_mobile_lcdc_remove(struct platform_device *pdev); | 1378 | static int sh_mobile_lcdc_remove(struct platform_device *pdev) |
| 1379 | { | ||
| 1380 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); | ||
| 1381 | struct fb_info *info; | ||
| 1382 | int i; | ||
| 1412 | 1383 | ||
| 1413 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | 1384 | fb_unregister_client(&priv->notifier); |
| 1385 | |||
| 1386 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | ||
| 1387 | if (priv->ch[i].info && priv->ch[i].info->dev) | ||
| 1388 | unregister_framebuffer(priv->ch[i].info); | ||
| 1389 | |||
| 1390 | sh_mobile_lcdc_stop(priv); | ||
| 1391 | |||
| 1392 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
| 1393 | info = priv->ch[i].info; | ||
| 1394 | |||
| 1395 | if (!info || !info->device) | ||
| 1396 | continue; | ||
| 1397 | |||
| 1398 | if (priv->ch[i].sglist) | ||
| 1399 | vfree(priv->ch[i].sglist); | ||
| 1400 | |||
| 1401 | if (info->screen_base) | ||
| 1402 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
| 1403 | info->screen_base, | ||
| 1404 | priv->ch[i].dma_handle); | ||
| 1405 | fb_dealloc_cmap(&info->cmap); | ||
| 1406 | framebuffer_release(info); | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
| 1410 | if (priv->ch[i].bl) | ||
| 1411 | sh_mobile_lcdc_bl_remove(priv->ch[i].bl); | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | if (priv->dot_clk) | ||
| 1415 | clk_put(priv->dot_clk); | ||
| 1416 | |||
| 1417 | if (priv->dev) | ||
| 1418 | pm_runtime_disable(priv->dev); | ||
| 1419 | |||
| 1420 | if (priv->base) | ||
| 1421 | iounmap(priv->base); | ||
| 1422 | |||
| 1423 | if (priv->irq) | ||
| 1424 | free_irq(priv->irq, priv); | ||
| 1425 | kfree(priv); | ||
| 1426 | return 0; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch, | ||
| 1430 | struct device *dev) | ||
| 1414 | { | 1431 | { |
| 1432 | struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; | ||
| 1433 | const struct fb_videomode *max_mode; | ||
| 1434 | const struct fb_videomode *mode; | ||
| 1435 | struct fb_var_screeninfo *var; | ||
| 1415 | struct fb_info *info; | 1436 | struct fb_info *info; |
| 1416 | struct sh_mobile_lcdc_priv *priv; | 1437 | unsigned int max_size; |
| 1438 | int num_cfg; | ||
| 1439 | void *buf; | ||
| 1440 | int ret; | ||
| 1441 | int i; | ||
| 1442 | |||
| 1443 | mutex_init(&ch->open_lock); | ||
| 1444 | |||
| 1445 | /* Allocate the frame buffer device. */ | ||
| 1446 | ch->info = framebuffer_alloc(0, dev); | ||
| 1447 | if (!ch->info) { | ||
| 1448 | dev_err(dev, "unable to allocate fb_info\n"); | ||
| 1449 | return -ENOMEM; | ||
| 1450 | } | ||
| 1451 | |||
| 1452 | info = ch->info; | ||
| 1453 | info->fbops = &sh_mobile_lcdc_ops; | ||
| 1454 | info->par = ch; | ||
| 1455 | info->pseudo_palette = &ch->pseudo_palette; | ||
| 1456 | info->flags = FBINFO_FLAG_DEFAULT; | ||
| 1457 | |||
| 1458 | /* Iterate through the modes to validate them and find the highest | ||
| 1459 | * resolution. | ||
| 1460 | */ | ||
| 1461 | max_mode = NULL; | ||
| 1462 | max_size = 0; | ||
| 1463 | |||
| 1464 | for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) { | ||
| 1465 | unsigned int size = mode->yres * mode->xres; | ||
| 1466 | |||
| 1467 | /* NV12 buffers must have even number of lines */ | ||
| 1468 | if ((cfg->nonstd) && cfg->bpp == 12 && | ||
| 1469 | (mode->yres & 0x1)) { | ||
| 1470 | dev_err(dev, "yres must be multiple of 2 for YCbCr420 " | ||
| 1471 | "mode.\n"); | ||
| 1472 | return -EINVAL; | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | if (size > max_size) { | ||
| 1476 | max_mode = mode; | ||
| 1477 | max_size = size; | ||
| 1478 | } | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | if (!max_size) | ||
| 1482 | max_size = MAX_XRES * MAX_YRES; | ||
| 1483 | else | ||
| 1484 | dev_dbg(dev, "Found largest videomode %ux%u\n", | ||
| 1485 | max_mode->xres, max_mode->yres); | ||
| 1486 | |||
| 1487 | /* Initialize fixed screen information. Restrict pan to 2 lines steps | ||
| 1488 | * for NV12. | ||
| 1489 | */ | ||
| 1490 | info->fix = sh_mobile_lcdc_fix; | ||
| 1491 | info->fix.smem_len = max_size * 2 * cfg->bpp / 8; | ||
| 1492 | if (cfg->nonstd && cfg->bpp == 12) | ||
| 1493 | info->fix.ypanstep = 2; | ||
| 1494 | |||
| 1495 | /* Create the mode list. */ | ||
| 1496 | if (cfg->lcd_cfg == NULL) { | ||
| 1497 | mode = &default_720p; | ||
| 1498 | num_cfg = 1; | ||
| 1499 | } else { | ||
| 1500 | mode = cfg->lcd_cfg; | ||
| 1501 | num_cfg = cfg->num_cfg; | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | fb_videomode_to_modelist(mode, num_cfg, &info->modelist); | ||
| 1505 | |||
| 1506 | /* Initialize variable screen information using the first mode as | ||
| 1507 | * default. The default Y virtual resolution is twice the panel size to | ||
| 1508 | * allow for double-buffering. | ||
| 1509 | */ | ||
| 1510 | var = &info->var; | ||
| 1511 | fb_videomode_to_var(var, mode); | ||
| 1512 | var->bits_per_pixel = cfg->bpp; | ||
| 1513 | var->width = cfg->lcd_size_cfg.width; | ||
| 1514 | var->height = cfg->lcd_size_cfg.height; | ||
| 1515 | var->yres_virtual = var->yres * 2; | ||
| 1516 | var->activate = FB_ACTIVATE_NOW; | ||
| 1517 | |||
| 1518 | ret = sh_mobile_check_var(var, info); | ||
| 1519 | if (ret) | ||
| 1520 | return ret; | ||
| 1521 | |||
| 1522 | /* Allocate frame buffer memory and color map. */ | ||
| 1523 | buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle, | ||
| 1524 | GFP_KERNEL); | ||
| 1525 | if (!buf) { | ||
| 1526 | dev_err(dev, "unable to allocate buffer\n"); | ||
| 1527 | return -ENOMEM; | ||
| 1528 | } | ||
| 1529 | |||
| 1530 | ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | ||
| 1531 | if (ret < 0) { | ||
| 1532 | dev_err(dev, "unable to allocate cmap\n"); | ||
| 1533 | dma_free_coherent(dev, info->fix.smem_len, | ||
| 1534 | buf, ch->dma_handle); | ||
| 1535 | return ret; | ||
| 1536 | } | ||
| 1537 | |||
| 1538 | info->fix.smem_start = ch->dma_handle; | ||
| 1539 | if (var->nonstd) | ||
| 1540 | info->fix.line_length = var->xres; | ||
| 1541 | else | ||
| 1542 | info->fix.line_length = var->xres * (cfg->bpp / 8); | ||
| 1543 | |||
| 1544 | info->screen_base = buf; | ||
| 1545 | info->device = dev; | ||
| 1546 | ch->display_var = *var; | ||
| 1547 | |||
| 1548 | return 0; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | ||
| 1552 | { | ||
| 1417 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; | 1553 | struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; |
| 1554 | struct sh_mobile_lcdc_priv *priv; | ||
| 1418 | struct resource *res; | 1555 | struct resource *res; |
| 1556 | int num_channels; | ||
| 1419 | int error; | 1557 | int error; |
| 1420 | void *buf; | 1558 | int i; |
| 1421 | int i, j; | ||
| 1422 | 1559 | ||
| 1423 | if (!pdata) { | 1560 | if (!pdata) { |
| 1424 | dev_err(&pdev->dev, "no platform data defined\n"); | 1561 | dev_err(&pdev->dev, "no platform data defined\n"); |
| @@ -1440,7 +1577,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1440 | 1577 | ||
| 1441 | platform_set_drvdata(pdev, priv); | 1578 | platform_set_drvdata(pdev, priv); |
| 1442 | 1579 | ||
| 1443 | error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, | 1580 | error = request_irq(i, sh_mobile_lcdc_irq, 0, |
| 1444 | dev_name(&pdev->dev), priv); | 1581 | dev_name(&pdev->dev), priv); |
| 1445 | if (error) { | 1582 | if (error) { |
| 1446 | dev_err(&pdev->dev, "unable to request irq\n"); | 1583 | dev_err(&pdev->dev, "unable to request irq\n"); |
| @@ -1450,9 +1587,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1450 | priv->irq = i; | 1587 | priv->irq = i; |
| 1451 | atomic_set(&priv->hw_usecnt, -1); | 1588 | atomic_set(&priv->hw_usecnt, -1); |
| 1452 | 1589 | ||
| 1453 | j = 0; | 1590 | for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { |
| 1454 | for (i = 0; i < ARRAY_SIZE(pdata->ch); i++) { | 1591 | struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; |
| 1455 | struct sh_mobile_lcdc_chan *ch = priv->ch + j; | ||
| 1456 | 1592 | ||
| 1457 | ch->lcdc = priv; | 1593 | ch->lcdc = priv; |
| 1458 | memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); | 1594 | memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); |
| @@ -1472,26 +1608,26 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1472 | 1608 | ||
| 1473 | switch (pdata->ch[i].chan) { | 1609 | switch (pdata->ch[i].chan) { |
| 1474 | case LCDC_CHAN_MAINLCD: | 1610 | case LCDC_CHAN_MAINLCD: |
| 1475 | ch->enabled = 1 << 1; | 1611 | ch->enabled = LDCNT2R_ME; |
| 1476 | ch->reg_offs = lcdc_offs_mainlcd; | 1612 | ch->reg_offs = lcdc_offs_mainlcd; |
| 1477 | j++; | 1613 | num_channels++; |
| 1478 | break; | 1614 | break; |
| 1479 | case LCDC_CHAN_SUBLCD: | 1615 | case LCDC_CHAN_SUBLCD: |
| 1480 | ch->enabled = 1 << 2; | 1616 | ch->enabled = LDCNT2R_SE; |
| 1481 | ch->reg_offs = lcdc_offs_sublcd; | 1617 | ch->reg_offs = lcdc_offs_sublcd; |
| 1482 | j++; | 1618 | num_channels++; |
| 1483 | break; | 1619 | break; |
| 1484 | } | 1620 | } |
| 1485 | } | 1621 | } |
| 1486 | 1622 | ||
| 1487 | if (!j) { | 1623 | if (!num_channels) { |
| 1488 | dev_err(&pdev->dev, "no channels defined\n"); | 1624 | dev_err(&pdev->dev, "no channels defined\n"); |
| 1489 | error = -EINVAL; | 1625 | error = -EINVAL; |
| 1490 | goto err1; | 1626 | goto err1; |
| 1491 | } | 1627 | } |
| 1492 | 1628 | ||
| 1493 | /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ | 1629 | /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ |
| 1494 | if (j == 2) | 1630 | if (num_channels == 2) |
| 1495 | priv->forced_bpp = pdata->ch[0].bpp; | 1631 | priv->forced_bpp = pdata->ch[0].bpp; |
| 1496 | 1632 | ||
| 1497 | priv->base = ioremap_nocache(res->start, resource_size(res)); | 1633 | priv->base = ioremap_nocache(res->start, resource_size(res)); |
| @@ -1506,125 +1642,23 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1506 | 1642 | ||
| 1507 | priv->meram_dev = pdata->meram_dev; | 1643 | priv->meram_dev = pdata->meram_dev; |
| 1508 | 1644 | ||
| 1509 | for (i = 0; i < j; i++) { | 1645 | for (i = 0; i < num_channels; i++) { |
| 1510 | struct fb_var_screeninfo *var; | ||
| 1511 | const struct fb_videomode *lcd_cfg, *max_cfg = NULL; | ||
| 1512 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1646 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
| 1513 | struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; | ||
| 1514 | const struct fb_videomode *mode = cfg->lcd_cfg; | ||
| 1515 | unsigned long max_size = 0; | ||
| 1516 | int k; | ||
| 1517 | int num_cfg; | ||
| 1518 | |||
| 1519 | ch->info = framebuffer_alloc(0, &pdev->dev); | ||
| 1520 | if (!ch->info) { | ||
| 1521 | dev_err(&pdev->dev, "unable to allocate fb_info\n"); | ||
| 1522 | error = -ENOMEM; | ||
| 1523 | break; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | info = ch->info; | ||
| 1527 | var = &info->var; | ||
| 1528 | info->fbops = &sh_mobile_lcdc_ops; | ||
| 1529 | info->par = ch; | ||
| 1530 | |||
| 1531 | mutex_init(&ch->open_lock); | ||
| 1532 | |||
| 1533 | for (k = 0, lcd_cfg = mode; | ||
| 1534 | k < cfg->num_cfg && lcd_cfg; | ||
| 1535 | k++, lcd_cfg++) { | ||
| 1536 | unsigned long size = lcd_cfg->yres * lcd_cfg->xres; | ||
| 1537 | /* NV12 buffers must have even number of lines */ | ||
| 1538 | if ((cfg->nonstd) && cfg->bpp == 12 && | ||
| 1539 | (lcd_cfg->yres & 0x1)) { | ||
| 1540 | dev_err(&pdev->dev, "yres must be multiple of 2" | ||
| 1541 | " for YCbCr420 mode.\n"); | ||
| 1542 | error = -EINVAL; | ||
| 1543 | goto err1; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | if (size > max_size) { | ||
| 1547 | max_cfg = lcd_cfg; | ||
| 1548 | max_size = size; | ||
| 1549 | } | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | if (!mode) | ||
| 1553 | max_size = MAX_XRES * MAX_YRES; | ||
| 1554 | else if (max_cfg) | ||
| 1555 | dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n", | ||
| 1556 | max_cfg->xres, max_cfg->yres); | ||
| 1557 | 1647 | ||
| 1558 | info->fix = sh_mobile_lcdc_fix; | 1648 | error = sh_mobile_lcdc_channel_init(ch, &pdev->dev); |
| 1559 | info->fix.smem_len = max_size * 2 * cfg->bpp / 8; | ||
| 1560 | |||
| 1561 | /* Only pan in 2 line steps for NV12 */ | ||
| 1562 | if (cfg->nonstd && cfg->bpp == 12) | ||
| 1563 | info->fix.ypanstep = 2; | ||
| 1564 | |||
| 1565 | if (!mode) { | ||
| 1566 | mode = &default_720p; | ||
| 1567 | num_cfg = 1; | ||
| 1568 | } else { | ||
| 1569 | num_cfg = cfg->num_cfg; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | fb_videomode_to_modelist(mode, num_cfg, &info->modelist); | ||
| 1573 | |||
| 1574 | fb_videomode_to_var(var, mode); | ||
| 1575 | var->width = cfg->lcd_size_cfg.width; | ||
| 1576 | var->height = cfg->lcd_size_cfg.height; | ||
| 1577 | /* Default Y virtual resolution is 2x panel size */ | ||
| 1578 | var->yres_virtual = var->yres * 2; | ||
| 1579 | var->activate = FB_ACTIVATE_NOW; | ||
| 1580 | |||
| 1581 | error = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd); | ||
| 1582 | if (error) | 1649 | if (error) |
| 1583 | break; | 1650 | goto err1; |
| 1584 | |||
| 1585 | buf = dma_alloc_coherent(&pdev->dev, info->fix.smem_len, | ||
| 1586 | &ch->dma_handle, GFP_KERNEL); | ||
| 1587 | if (!buf) { | ||
| 1588 | dev_err(&pdev->dev, "unable to allocate buffer\n"); | ||
| 1589 | error = -ENOMEM; | ||
| 1590 | break; | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | info->pseudo_palette = &ch->pseudo_palette; | ||
| 1594 | info->flags = FBINFO_FLAG_DEFAULT; | ||
| 1595 | |||
| 1596 | error = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); | ||
| 1597 | if (error < 0) { | ||
| 1598 | dev_err(&pdev->dev, "unable to allocate cmap\n"); | ||
| 1599 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
| 1600 | buf, ch->dma_handle); | ||
| 1601 | break; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | info->fix.smem_start = ch->dma_handle; | ||
| 1605 | if (var->nonstd) | ||
| 1606 | info->fix.line_length = var->xres; | ||
| 1607 | else | ||
| 1608 | info->fix.line_length = var->xres * (cfg->bpp / 8); | ||
| 1609 | |||
| 1610 | info->screen_base = buf; | ||
| 1611 | info->device = &pdev->dev; | ||
| 1612 | ch->display_var = *var; | ||
| 1613 | } | 1651 | } |
| 1614 | 1652 | ||
| 1615 | if (error) | ||
| 1616 | goto err1; | ||
| 1617 | |||
| 1618 | error = sh_mobile_lcdc_start(priv); | 1653 | error = sh_mobile_lcdc_start(priv); |
| 1619 | if (error) { | 1654 | if (error) { |
| 1620 | dev_err(&pdev->dev, "unable to start hardware\n"); | 1655 | dev_err(&pdev->dev, "unable to start hardware\n"); |
| 1621 | goto err1; | 1656 | goto err1; |
| 1622 | } | 1657 | } |
| 1623 | 1658 | ||
| 1624 | for (i = 0; i < j; i++) { | 1659 | for (i = 0; i < num_channels; i++) { |
| 1625 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; | 1660 | struct sh_mobile_lcdc_chan *ch = priv->ch + i; |
| 1626 | 1661 | struct fb_info *info = ch->info; | |
| 1627 | info = ch->info; | ||
| 1628 | 1662 | ||
| 1629 | if (info->fbdefio) { | 1663 | if (info->fbdefio) { |
| 1630 | ch->sglist = vmalloc(sizeof(struct scatterlist) * | 1664 | ch->sglist = vmalloc(sizeof(struct scatterlist) * |
| @@ -1665,57 +1699,6 @@ err1: | |||
| 1665 | return error; | 1699 | return error; |
| 1666 | } | 1700 | } |
| 1667 | 1701 | ||
| 1668 | static int sh_mobile_lcdc_remove(struct platform_device *pdev) | ||
| 1669 | { | ||
| 1670 | struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); | ||
| 1671 | struct fb_info *info; | ||
| 1672 | int i; | ||
| 1673 | |||
| 1674 | fb_unregister_client(&priv->notifier); | ||
| 1675 | |||
| 1676 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | ||
| 1677 | if (priv->ch[i].info && priv->ch[i].info->dev) | ||
| 1678 | unregister_framebuffer(priv->ch[i].info); | ||
| 1679 | |||
| 1680 | sh_mobile_lcdc_stop(priv); | ||
| 1681 | |||
| 1682 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
| 1683 | info = priv->ch[i].info; | ||
| 1684 | |||
| 1685 | if (!info || !info->device) | ||
| 1686 | continue; | ||
| 1687 | |||
| 1688 | if (priv->ch[i].sglist) | ||
| 1689 | vfree(priv->ch[i].sglist); | ||
| 1690 | |||
| 1691 | if (info->screen_base) | ||
| 1692 | dma_free_coherent(&pdev->dev, info->fix.smem_len, | ||
| 1693 | info->screen_base, | ||
| 1694 | priv->ch[i].dma_handle); | ||
| 1695 | fb_dealloc_cmap(&info->cmap); | ||
| 1696 | framebuffer_release(info); | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { | ||
| 1700 | if (priv->ch[i].bl) | ||
| 1701 | sh_mobile_lcdc_bl_remove(priv->ch[i].bl); | ||
| 1702 | } | ||
| 1703 | |||
| 1704 | if (priv->dot_clk) | ||
| 1705 | clk_put(priv->dot_clk); | ||
| 1706 | |||
| 1707 | if (priv->dev) | ||
| 1708 | pm_runtime_disable(priv->dev); | ||
| 1709 | |||
| 1710 | if (priv->base) | ||
| 1711 | iounmap(priv->base); | ||
| 1712 | |||
| 1713 | if (priv->irq) | ||
| 1714 | free_irq(priv->irq, priv); | ||
| 1715 | kfree(priv); | ||
| 1716 | return 0; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | static struct platform_driver sh_mobile_lcdc_driver = { | 1702 | static struct platform_driver sh_mobile_lcdc_driver = { |
| 1720 | .driver = { | 1703 | .driver = { |
| 1721 | .name = "sh_mobile_lcdc_fb", | 1704 | .name = "sh_mobile_lcdc_fb", |
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index aeed6687e6a7..a58a0f38848b 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h | |||
| @@ -18,6 +18,13 @@ struct sh_mobile_lcdc_priv; | |||
| 18 | struct fb_info; | 18 | struct fb_info; |
| 19 | struct backlight_device; | 19 | struct backlight_device; |
| 20 | 20 | ||
| 21 | /* | ||
| 22 | * struct sh_mobile_lcdc_chan - LCDC display channel | ||
| 23 | * | ||
| 24 | * @base_addr_y: Frame buffer viewport base address (luma component) | ||
| 25 | * @base_addr_c: Frame buffer viewport base address (chroma component) | ||
| 26 | * @pitch: Frame buffer line pitch | ||
| 27 | */ | ||
| 21 | struct sh_mobile_lcdc_chan { | 28 | struct sh_mobile_lcdc_chan { |
| 22 | struct sh_mobile_lcdc_priv *lcdc; | 29 | struct sh_mobile_lcdc_priv *lcdc; |
| 23 | unsigned long *reg_offs; | 30 | unsigned long *reg_offs; |
| @@ -25,7 +32,6 @@ struct sh_mobile_lcdc_chan { | |||
| 25 | unsigned long enabled; /* ME and SE in LDCNT2R */ | 32 | unsigned long enabled; /* ME and SE in LDCNT2R */ |
| 26 | struct sh_mobile_lcdc_chan_cfg cfg; | 33 | struct sh_mobile_lcdc_chan_cfg cfg; |
| 27 | u32 pseudo_palette[PALETTE_NR]; | 34 | u32 pseudo_palette[PALETTE_NR]; |
| 28 | unsigned long saved_ch_regs[NR_CH_REGS]; | ||
| 29 | struct fb_info *info; | 35 | struct fb_info *info; |
| 30 | struct backlight_device *bl; | 36 | struct backlight_device *bl; |
| 31 | dma_addr_t dma_handle; | 37 | dma_addr_t dma_handle; |
| @@ -40,6 +46,10 @@ struct sh_mobile_lcdc_chan { | |||
| 40 | int blank_status; | 46 | int blank_status; |
| 41 | struct mutex open_lock; /* protects the use counter */ | 47 | struct mutex open_lock; /* protects the use counter */ |
| 42 | int meram_enabled; | 48 | int meram_enabled; |
| 49 | |||
| 50 | unsigned long base_addr_y; | ||
| 51 | unsigned long base_addr_c; | ||
| 52 | unsigned int pitch; | ||
| 43 | }; | 53 | }; |
| 44 | 54 | ||
| 45 | #endif | 55 | #endif |
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c index cc7d7329dc15..4d63490209cd 100644 --- a/drivers/video/sh_mobile_meram.c +++ b/drivers/video/sh_mobile_meram.c | |||
| @@ -12,29 +12,103 @@ | |||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
| 15 | #include <linux/pm_runtime.h> | ||
| 15 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 18 | 19 | #include <video/sh_mobile_meram.h> | |
| 19 | #include "sh_mobile_meram.h" | ||
| 20 | 20 | ||
| 21 | /* meram registers */ | 21 | /* meram registers */ |
| 22 | #define MExxCTL 0x0 | 22 | #define MEVCR1 0x4 |
| 23 | #define MExxBSIZE 0x4 | 23 | #define MEVCR1_RST (1 << 31) |
| 24 | #define MExxMNCF 0x8 | 24 | #define MEVCR1_WD (1 << 30) |
| 25 | #define MExxSARA 0x10 | 25 | #define MEVCR1_AMD1 (1 << 29) |
| 26 | #define MExxSARB 0x14 | 26 | #define MEVCR1_AMD0 (1 << 28) |
| 27 | #define MExxSBSIZE 0x18 | 27 | #define MEQSEL1 0x40 |
| 28 | 28 | #define MEQSEL2 0x44 | |
| 29 | #define MERAM_MExxCTL_VAL(ctl, next_icb, addr) \ | 29 | |
| 30 | ((ctl) | (((next_icb) & 0x1f) << 11) | (((addr) & 0x7ff) << 16)) | 30 | #define MExxCTL 0x400 |
| 31 | #define MERAM_MExxBSIZE_VAL(a, b, c) \ | 31 | #define MExxCTL_BV (1 << 31) |
| 32 | (((a) << 28) | ((b) << 16) | (c)) | 32 | #define MExxCTL_BSZ_SHIFT 28 |
| 33 | 33 | #define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT) | |
| 34 | #define MEVCR1 0x4 | 34 | #define MExxCTL_MSAR_SHIFT 16 |
| 35 | #define MEACTS 0x10 | 35 | #define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT) |
| 36 | #define MEQSEL1 0x40 | 36 | #define MExxCTL_NXT_SHIFT 11 |
| 37 | #define MEQSEL2 0x44 | 37 | #define MExxCTL_WD1 (1 << 10) |
| 38 | #define MExxCTL_WD0 (1 << 9) | ||
| 39 | #define MExxCTL_WS (1 << 8) | ||
| 40 | #define MExxCTL_CB (1 << 7) | ||
| 41 | #define MExxCTL_WBF (1 << 6) | ||
| 42 | #define MExxCTL_WF (1 << 5) | ||
| 43 | #define MExxCTL_RF (1 << 4) | ||
| 44 | #define MExxCTL_CM (1 << 3) | ||
| 45 | #define MExxCTL_MD_READ (1 << 0) | ||
| 46 | #define MExxCTL_MD_WRITE (2 << 0) | ||
| 47 | #define MExxCTL_MD_ICB_WB (3 << 0) | ||
| 48 | #define MExxCTL_MD_ICB (4 << 0) | ||
| 49 | #define MExxCTL_MD_FB (7 << 0) | ||
| 50 | #define MExxCTL_MD_MASK (7 << 0) | ||
| 51 | #define MExxBSIZE 0x404 | ||
| 52 | #define MExxBSIZE_RCNT_SHIFT 28 | ||
| 53 | #define MExxBSIZE_YSZM1_SHIFT 16 | ||
| 54 | #define MExxBSIZE_XSZM1_SHIFT 0 | ||
| 55 | #define MExxMNCF 0x408 | ||
| 56 | #define MExxMNCF_KWBNM_SHIFT 28 | ||
| 57 | #define MExxMNCF_KRBNM_SHIFT 24 | ||
| 58 | #define MExxMNCF_BNM_SHIFT 16 | ||
| 59 | #define MExxMNCF_XBV (1 << 15) | ||
| 60 | #define MExxMNCF_CPL_YCBCR444 (1 << 12) | ||
| 61 | #define MExxMNCF_CPL_YCBCR420 (2 << 12) | ||
| 62 | #define MExxMNCF_CPL_YCBCR422 (3 << 12) | ||
| 63 | #define MExxMNCF_CPL_MSK (3 << 12) | ||
| 64 | #define MExxMNCF_BL (1 << 2) | ||
| 65 | #define MExxMNCF_LNM_SHIFT 0 | ||
| 66 | #define MExxSARA 0x410 | ||
| 67 | #define MExxSARB 0x414 | ||
| 68 | #define MExxSBSIZE 0x418 | ||
| 69 | #define MExxSBSIZE_HDV (1 << 31) | ||
| 70 | #define MExxSBSIZE_HSZ16 (0 << 28) | ||
| 71 | #define MExxSBSIZE_HSZ32 (1 << 28) | ||
| 72 | #define MExxSBSIZE_HSZ64 (2 << 28) | ||
| 73 | #define MExxSBSIZE_HSZ128 (3 << 28) | ||
| 74 | #define MExxSBSIZE_SBSIZZ_SHIFT 0 | ||
| 75 | |||
| 76 | #define MERAM_MExxCTL_VAL(next, addr) \ | ||
| 77 | ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \ | ||
| 78 | (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK)) | ||
| 79 | #define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \ | ||
| 80 | (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \ | ||
| 81 | ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ | ||
| 82 | ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) | ||
| 83 | |||
| 84 | #define SH_MOBILE_MERAM_ICB_NUM 32 | ||
| 85 | |||
| 86 | static unsigned long common_regs[] = { | ||
| 87 | MEVCR1, | ||
| 88 | MEQSEL1, | ||
| 89 | MEQSEL2, | ||
| 90 | }; | ||
| 91 | #define CMN_REGS_SIZE ARRAY_SIZE(common_regs) | ||
| 92 | |||
| 93 | static unsigned long icb_regs[] = { | ||
| 94 | MExxCTL, | ||
| 95 | MExxBSIZE, | ||
| 96 | MExxMNCF, | ||
| 97 | MExxSARA, | ||
| 98 | MExxSARB, | ||
| 99 | MExxSBSIZE, | ||
| 100 | }; | ||
| 101 | #define ICB_REGS_SIZE ARRAY_SIZE(icb_regs) | ||
| 102 | |||
| 103 | struct sh_mobile_meram_priv { | ||
| 104 | void __iomem *base; | ||
| 105 | struct mutex lock; | ||
| 106 | unsigned long used_icb; | ||
| 107 | int used_meram_cache_regions; | ||
| 108 | unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM]; | ||
| 109 | unsigned long cmn_saved_regs[CMN_REGS_SIZE]; | ||
| 110 | unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM]; | ||
| 111 | }; | ||
| 38 | 112 | ||
| 39 | /* settings */ | 113 | /* settings */ |
| 40 | #define MERAM_SEC_LINE 15 | 114 | #define MERAM_SEC_LINE 15 |
| @@ -44,8 +118,7 @@ | |||
| 44 | * MERAM/ICB access functions | 118 | * MERAM/ICB access functions |
| 45 | */ | 119 | */ |
| 46 | 120 | ||
| 47 | #define MERAM_ICB_OFFSET(base, idx, off) \ | 121 | #define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) |
| 48 | ((base) + (0x400 + ((idx) * 0x20) + (off))) | ||
| 49 | 122 | ||
| 50 | static inline void meram_write_icb(void __iomem *base, int idx, int off, | 123 | static inline void meram_write_icb(void __iomem *base, int idx, int off, |
| 51 | unsigned long val) | 124 | unsigned long val) |
| @@ -280,17 +353,18 @@ static int meram_init(struct sh_mobile_meram_priv *priv, | |||
| 280 | /* | 353 | /* |
| 281 | * Set MERAM for framebuffer | 354 | * Set MERAM for framebuffer |
| 282 | * | 355 | * |
| 283 | * 0x70f: WD = 0x3, WS=0x1, CM=0x1, MD=FB mode | ||
| 284 | * we also chain the cache_icb and the marker_icb. | 356 | * we also chain the cache_icb and the marker_icb. |
| 285 | * we also split the allocated MERAM buffer between two ICBs. | 357 | * we also split the allocated MERAM buffer between two ICBs. |
| 286 | */ | 358 | */ |
| 287 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, | 359 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, |
| 288 | MERAM_MExxCTL_VAL(0x70f, icb->marker_icb, | 360 | MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) | |
| 289 | icb->meram_offset)); | 361 | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | |
| 362 | MExxCTL_MD_FB); | ||
| 290 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, | 363 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, |
| 291 | MERAM_MExxCTL_VAL(0x70f, icb->cache_icb, | 364 | MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset + |
| 292 | icb->meram_offset + | 365 | icb->meram_size / 2) | |
| 293 | icb->meram_size / 2)); | 366 | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | |
| 367 | MExxCTL_MD_FB); | ||
| 294 | 368 | ||
| 295 | return 0; | 369 | return 0; |
| 296 | } | 370 | } |
| @@ -299,8 +373,10 @@ static void meram_deinit(struct sh_mobile_meram_priv *priv, | |||
| 299 | struct sh_mobile_meram_icb *icb) | 373 | struct sh_mobile_meram_icb *icb) |
| 300 | { | 374 | { |
| 301 | /* disable ICB */ | 375 | /* disable ICB */ |
| 302 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 0); | 376 | meram_write_icb(priv->base, icb->cache_icb, MExxCTL, |
| 303 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 0); | 377 | MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); |
| 378 | meram_write_icb(priv->base, icb->marker_icb, MExxCTL, | ||
| 379 | MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); | ||
| 304 | icb->cache_unit = 0; | 380 | icb->cache_unit = 0; |
| 305 | } | 381 | } |
| 306 | 382 | ||
| @@ -337,24 +413,22 @@ static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, | |||
| 337 | xres, yres, (!pixelformat) ? "yuv" : "rgb", | 413 | xres, yres, (!pixelformat) ? "yuv" : "rgb", |
| 338 | base_addr_y, base_addr_c); | 414 | base_addr_y, base_addr_c); |
| 339 | 415 | ||
| 340 | mutex_lock(&priv->lock); | ||
| 341 | |||
| 342 | /* we can't handle wider than 8192px */ | 416 | /* we can't handle wider than 8192px */ |
| 343 | if (xres > 8192) { | 417 | if (xres > 8192) { |
| 344 | dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); | 418 | dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); |
| 345 | error = -EINVAL; | 419 | return -EINVAL; |
| 346 | goto err; | ||
| 347 | } | ||
| 348 | |||
| 349 | if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) { | ||
| 350 | dev_err(&pdev->dev, "no more ICB available."); | ||
| 351 | error = -EINVAL; | ||
| 352 | goto err; | ||
| 353 | } | 420 | } |
| 354 | 421 | ||
| 355 | /* do we have at least one ICB config? */ | 422 | /* do we have at least one ICB config? */ |
| 356 | if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { | 423 | if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) { |
| 357 | dev_err(&pdev->dev, "at least one ICB is required."); | 424 | dev_err(&pdev->dev, "at least one ICB is required."); |
| 425 | return -EINVAL; | ||
| 426 | } | ||
| 427 | |||
| 428 | mutex_lock(&priv->lock); | ||
| 429 | |||
| 430 | if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) { | ||
| 431 | dev_err(&pdev->dev, "no more ICB available."); | ||
| 358 | error = -EINVAL; | 432 | error = -EINVAL; |
| 359 | goto err; | 433 | goto err; |
| 360 | } | 434 | } |
| @@ -460,6 +534,57 @@ static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, | |||
| 460 | return 0; | 534 | return 0; |
| 461 | } | 535 | } |
| 462 | 536 | ||
| 537 | static int sh_mobile_meram_runtime_suspend(struct device *dev) | ||
| 538 | { | ||
| 539 | struct platform_device *pdev = to_platform_device(dev); | ||
| 540 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | ||
| 541 | int k, j; | ||
| 542 | |||
| 543 | for (k = 0; k < CMN_REGS_SIZE; k++) | ||
| 544 | priv->cmn_saved_regs[k] = meram_read_reg(priv->base, | ||
| 545 | common_regs[k]); | ||
| 546 | |||
| 547 | for (j = 0; j < 32; j++) { | ||
| 548 | if (!test_bit(j, &priv->used_icb)) | ||
| 549 | continue; | ||
| 550 | for (k = 0; k < ICB_REGS_SIZE; k++) { | ||
| 551 | priv->icb_saved_regs[j * ICB_REGS_SIZE + k] = | ||
| 552 | meram_read_icb(priv->base, j, icb_regs[k]); | ||
| 553 | /* Reset ICB on resume */ | ||
| 554 | if (icb_regs[k] == MExxCTL) | ||
| 555 | priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |= | ||
| 556 | MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF; | ||
| 557 | } | ||
| 558 | } | ||
| 559 | return 0; | ||
| 560 | } | ||
| 561 | |||
| 562 | static int sh_mobile_meram_runtime_resume(struct device *dev) | ||
| 563 | { | ||
| 564 | struct platform_device *pdev = to_platform_device(dev); | ||
| 565 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | ||
| 566 | int k, j; | ||
| 567 | |||
| 568 | for (j = 0; j < 32; j++) { | ||
| 569 | if (!test_bit(j, &priv->used_icb)) | ||
| 570 | continue; | ||
| 571 | for (k = 0; k < ICB_REGS_SIZE; k++) { | ||
| 572 | meram_write_icb(priv->base, j, icb_regs[k], | ||
| 573 | priv->icb_saved_regs[j * ICB_REGS_SIZE + k]); | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | for (k = 0; k < CMN_REGS_SIZE; k++) | ||
| 578 | meram_write_reg(priv->base, common_regs[k], | ||
| 579 | priv->cmn_saved_regs[k]); | ||
| 580 | return 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = { | ||
| 584 | .runtime_suspend = sh_mobile_meram_runtime_suspend, | ||
| 585 | .runtime_resume = sh_mobile_meram_runtime_resume, | ||
| 586 | }; | ||
| 587 | |||
| 463 | static struct sh_mobile_meram_ops sh_mobile_meram_ops = { | 588 | static struct sh_mobile_meram_ops sh_mobile_meram_ops = { |
| 464 | .module = THIS_MODULE, | 589 | .module = THIS_MODULE, |
| 465 | .meram_register = sh_mobile_meram_register, | 590 | .meram_register = sh_mobile_meram_register, |
| @@ -513,7 +638,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) | |||
| 513 | 638 | ||
| 514 | /* initialize ICB addressing mode */ | 639 | /* initialize ICB addressing mode */ |
| 515 | if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) | 640 | if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) |
| 516 | meram_write_reg(priv->base, MEVCR1, 1 << 29); | 641 | meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1); |
| 642 | |||
| 643 | pm_runtime_enable(&pdev->dev); | ||
| 517 | 644 | ||
| 518 | dev_info(&pdev->dev, "sh_mobile_meram initialized."); | 645 | dev_info(&pdev->dev, "sh_mobile_meram initialized."); |
| 519 | 646 | ||
| @@ -530,6 +657,8 @@ static int sh_mobile_meram_remove(struct platform_device *pdev) | |||
| 530 | { | 657 | { |
| 531 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); | 658 | struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); |
| 532 | 659 | ||
| 660 | pm_runtime_disable(&pdev->dev); | ||
| 661 | |||
| 533 | if (priv->base) | 662 | if (priv->base) |
| 534 | iounmap(priv->base); | 663 | iounmap(priv->base); |
| 535 | 664 | ||
| @@ -544,6 +673,7 @@ static struct platform_driver sh_mobile_meram_driver = { | |||
| 544 | .driver = { | 673 | .driver = { |
| 545 | .name = "sh_mobile_meram", | 674 | .name = "sh_mobile_meram", |
| 546 | .owner = THIS_MODULE, | 675 | .owner = THIS_MODULE, |
| 676 | .pm = &sh_mobile_meram_dev_pm_ops, | ||
| 547 | }, | 677 | }, |
| 548 | .probe = sh_mobile_meram_probe, | 678 | .probe = sh_mobile_meram_probe, |
| 549 | .remove = sh_mobile_meram_remove, | 679 | .remove = sh_mobile_meram_remove, |
diff --git a/drivers/video/sh_mobile_meram.h b/drivers/video/sh_mobile_meram.h deleted file mode 100644 index 82c54fbce8bd..000000000000 --- a/drivers/video/sh_mobile_meram.h +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | #ifndef __sh_mobile_meram_h__ | ||
| 2 | #define __sh_mobile_meram_h__ | ||
| 3 | |||
| 4 | #include <linux/mutex.h> | ||
| 5 | #include <video/sh_mobile_meram.h> | ||
| 6 | |||
| 7 | /* | ||
| 8 | * MERAM private | ||
| 9 | */ | ||
| 10 | |||
| 11 | #define MERAM_ICB_Y 0x1 | ||
| 12 | #define MERAM_ICB_C 0x2 | ||
| 13 | |||
| 14 | /* MERAM cache size */ | ||
| 15 | #define SH_MOBILE_MERAM_ICB_NUM 32 | ||
| 16 | |||
| 17 | #define SH_MOBILE_MERAM_CACHE_OFFSET(p) ((p) >> 16) | ||
| 18 | #define SH_MOBILE_MERAM_CACHE_SIZE(p) ((p) & 0xffff) | ||
| 19 | |||
| 20 | struct sh_mobile_meram_priv { | ||
| 21 | void __iomem *base; | ||
| 22 | struct mutex lock; | ||
| 23 | unsigned long used_icb; | ||
| 24 | int used_meram_cache_regions; | ||
| 25 | unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM]; | ||
| 26 | }; | ||
| 27 | |||
| 28 | int sh_mobile_meram_alloc_icb(const struct sh_mobile_meram_cfg *cfg, | ||
| 29 | int xres, | ||
| 30 | int yres, | ||
| 31 | unsigned int base_addr, | ||
| 32 | int yuv_mode, | ||
| 33 | int *marker_icb, | ||
| 34 | int *out_pitch); | ||
| 35 | |||
| 36 | void sh_mobile_meram_free_icb(int marker_icb); | ||
| 37 | |||
| 38 | #define SH_MOBILE_MERAM_START(ind, ab) \ | ||
| 39 | (0xC0000000 | ((ab & 0x1) << 23) | ((ind & 0x1F) << 24)) | ||
| 40 | |||
| 41 | #endif /* !__sh_mobile_meram_h__ */ | ||
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 75259845933d..078ca2167d6f 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
| @@ -1333,19 +1333,14 @@ sisfb_set_base_CRT2(struct sis_video_info *ivideo, unsigned int base) | |||
| 1333 | } | 1333 | } |
| 1334 | 1334 | ||
| 1335 | static int | 1335 | static int |
| 1336 | sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) | 1336 | sisfb_pan_var(struct sis_video_info *ivideo, struct fb_info *info, |
| 1337 | struct fb_var_screeninfo *var) | ||
| 1337 | { | 1338 | { |
| 1338 | if(var->xoffset > (var->xres_virtual - var->xres)) { | 1339 | ivideo->current_base = var->yoffset * info->var.xres_virtual |
| 1339 | return -EINVAL; | 1340 | + var->xoffset; |
| 1340 | } | ||
| 1341 | if(var->yoffset > (var->yres_virtual - var->yres)) { | ||
| 1342 | return -EINVAL; | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | ivideo->current_base = (var->yoffset * var->xres_virtual) + var->xoffset; | ||
| 1346 | 1341 | ||
| 1347 | /* calculate base bpp dep. */ | 1342 | /* calculate base bpp dep. */ |
| 1348 | switch(var->bits_per_pixel) { | 1343 | switch (info->var.bits_per_pixel) { |
| 1349 | case 32: | 1344 | case 32: |
| 1350 | break; | 1345 | break; |
| 1351 | case 16: | 1346 | case 16: |
| @@ -1635,20 +1630,15 @@ sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) | |||
| 1635 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; | 1630 | struct sis_video_info *ivideo = (struct sis_video_info *)info->par; |
| 1636 | int err; | 1631 | int err; |
| 1637 | 1632 | ||
| 1638 | if(var->xoffset > (var->xres_virtual - var->xres)) | 1633 | if (var->vmode & FB_VMODE_YWRAP) |
| 1639 | return -EINVAL; | ||
| 1640 | |||
| 1641 | if(var->yoffset > (var->yres_virtual - var->yres)) | ||
| 1642 | return -EINVAL; | ||
| 1643 | |||
| 1644 | if(var->vmode & FB_VMODE_YWRAP) | ||
| 1645 | return -EINVAL; | 1634 | return -EINVAL; |
| 1646 | 1635 | ||
| 1647 | if(var->xoffset + info->var.xres > info->var.xres_virtual || | 1636 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
| 1648 | var->yoffset + info->var.yres > info->var.yres_virtual) | 1637 | var->yoffset + info->var.yres > info->var.yres_virtual) |
| 1649 | return -EINVAL; | 1638 | return -EINVAL; |
| 1650 | 1639 | ||
| 1651 | if((err = sisfb_pan_var(ivideo, var)) < 0) | 1640 | err = sisfb_pan_var(ivideo, info, var); |
| 1641 | if (err < 0) | ||
| 1652 | return err; | 1642 | return err; |
| 1653 | 1643 | ||
| 1654 | info->var.xoffset = var->xoffset; | 1644 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 89158bc71da2..30f7a815a62b 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
| @@ -989,7 +989,7 @@ static struct platform_device *xxxfb_device; | |||
| 989 | */ | 989 | */ |
| 990 | int __init xxxfb_setup(char *options) | 990 | int __init xxxfb_setup(char *options) |
| 991 | { | 991 | { |
| 992 | /* Parse user speficied options (`video=xxxfb:') */ | 992 | /* Parse user specified options (`video=xxxfb:') */ |
| 993 | } | 993 | } |
| 994 | #endif /* MODULE */ | 994 | #endif /* MODULE */ |
| 995 | 995 | ||
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 6294dca95500..a78254cf8e83 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
| @@ -582,7 +582,7 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var, | |||
| 582 | { | 582 | { |
| 583 | struct sm501fb_par *par = info->par; | 583 | struct sm501fb_par *par = info->par; |
| 584 | struct sm501fb_info *fbi = par->info; | 584 | struct sm501fb_info *fbi = par->info; |
| 585 | unsigned int bytes_pixel = var->bits_per_pixel / 8; | 585 | unsigned int bytes_pixel = info->var.bits_per_pixel / 8; |
| 586 | unsigned long reg; | 586 | unsigned long reg; |
| 587 | unsigned long xoffs; | 587 | unsigned long xoffs; |
| 588 | 588 | ||
| @@ -614,10 +614,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var, | |||
| 614 | struct sm501fb_info *fbi = par->info; | 614 | struct sm501fb_info *fbi = par->info; |
| 615 | unsigned long reg; | 615 | unsigned long reg; |
| 616 | 616 | ||
| 617 | reg = var->xoffset | (var->xres_virtual << 16); | 617 | reg = var->xoffset | (info->var.xres_virtual << 16); |
| 618 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); | 618 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); |
| 619 | 619 | ||
| 620 | reg = var->yoffset | (var->yres_virtual << 16); | 620 | reg = var->yoffset | (info->var.yres_virtual << 16); |
| 621 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); | 621 | smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); |
| 622 | 622 | ||
| 623 | sm501fb_sync_regs(fbi); | 623 | sm501fb_sync_regs(fbi); |
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c new file mode 100644 index 000000000000..aaccffac67ab --- /dev/null +++ b/drivers/video/smscufx.c | |||
| @@ -0,0 +1,1994 @@ | |||
| 1 | /* | ||
| 2 | * smscufx.c -- Framebuffer driver for SMSC UFX USB controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011 Steve Glendinning <steve.glendinning@smsc.com> | ||
| 5 | * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it> | ||
| 6 | * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> | ||
| 7 | * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> | ||
| 8 | * | ||
| 9 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 10 | * License v2. See the file COPYING in the main directory of this archive for | ||
| 11 | * more details. | ||
| 12 | * | ||
| 13 | * Based on udlfb, with work from Florian Echtler, Henrik Bjerregaard Pedersen, | ||
| 14 | * and others. | ||
| 15 | * | ||
| 16 | * Works well with Bernie Thompson's X DAMAGE patch to xf86-video-fbdev | ||
| 17 | * available from http://git.plugable.com | ||
| 18 | * | ||
| 19 | * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven, | ||
| 20 | * usb-skeleton by GregKH. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 24 | |||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/usb.h> | ||
| 29 | #include <linux/uaccess.h> | ||
| 30 | #include <linux/mm.h> | ||
| 31 | #include <linux/fb.h> | ||
| 32 | #include <linux/vmalloc.h> | ||
| 33 | #include <linux/slab.h> | ||
| 34 | #include <linux/delay.h> | ||
| 35 | #include "edid.h" | ||
| 36 | |||
| 37 | #define check_warn(status, fmt, args...) \ | ||
| 38 | ({ if (status < 0) pr_warn(fmt, ##args); }) | ||
| 39 | |||
| 40 | #define check_warn_return(status, fmt, args...) \ | ||
| 41 | ({ if (status < 0) { pr_warn(fmt, ##args); return status; } }) | ||
| 42 | |||
| 43 | #define check_warn_goto_error(status, fmt, args...) \ | ||
| 44 | ({ if (status < 0) { pr_warn(fmt, ##args); goto error; } }) | ||
| 45 | |||
| 46 | #define all_bits_set(x, bits) (((x) & (bits)) == (bits)) | ||
| 47 | |||
| 48 | #define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0 | ||
| 49 | #define USB_VENDOR_REQUEST_READ_REGISTER 0xA1 | ||
| 50 | |||
| 51 | /* | ||
| 52 | * TODO: Propose standard fb.h ioctl for reporting damage, | ||
| 53 | * using _IOWR() and one of the existing area structs from fb.h | ||
| 54 | * Consider these ioctls deprecated, but they're still used by the | ||
| 55 | * DisplayLink X server as yet - need both to be modified in tandem | ||
| 56 | * when new ioctl(s) are ready. | ||
| 57 | */ | ||
| 58 | #define UFX_IOCTL_RETURN_EDID (0xAD) | ||
| 59 | #define UFX_IOCTL_REPORT_DAMAGE (0xAA) | ||
| 60 | |||
| 61 | /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ | ||
| 62 | #define BULK_SIZE (512) | ||
| 63 | #define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE) | ||
| 64 | #define WRITES_IN_FLIGHT (4) | ||
| 65 | |||
| 66 | #define GET_URB_TIMEOUT (HZ) | ||
| 67 | #define FREE_URB_TIMEOUT (HZ*2) | ||
| 68 | |||
| 69 | #define BPP 2 | ||
| 70 | |||
| 71 | #define UFX_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ | ||
| 72 | #define UFX_DEFIO_WRITE_DISABLE (HZ*60) /* "disable" with long delay */ | ||
| 73 | |||
| 74 | struct dloarea { | ||
| 75 | int x, y; | ||
| 76 | int w, h; | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct urb_node { | ||
| 80 | struct list_head entry; | ||
| 81 | struct ufx_data *dev; | ||
| 82 | struct delayed_work release_urb_work; | ||
| 83 | struct urb *urb; | ||
| 84 | }; | ||
| 85 | |||
| 86 | struct urb_list { | ||
| 87 | struct list_head list; | ||
| 88 | spinlock_t lock; | ||
| 89 | struct semaphore limit_sem; | ||
| 90 | int available; | ||
| 91 | int count; | ||
| 92 | size_t size; | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct ufx_data { | ||
| 96 | struct usb_device *udev; | ||
| 97 | struct device *gdev; /* &udev->dev */ | ||
| 98 | struct fb_info *info; | ||
| 99 | struct urb_list urbs; | ||
| 100 | struct kref kref; | ||
| 101 | int fb_count; | ||
| 102 | bool virtualized; /* true when physical usb device not present */ | ||
| 103 | struct delayed_work free_framebuffer_work; | ||
| 104 | atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ | ||
| 105 | atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ | ||
| 106 | u8 *edid; /* null until we read edid from hw or get from sysfs */ | ||
| 107 | size_t edid_size; | ||
| 108 | u32 pseudo_palette[256]; | ||
| 109 | }; | ||
| 110 | |||
| 111 | static struct fb_fix_screeninfo ufx_fix = { | ||
| 112 | .id = "smscufx", | ||
| 113 | .type = FB_TYPE_PACKED_PIXELS, | ||
| 114 | .visual = FB_VISUAL_TRUECOLOR, | ||
| 115 | .xpanstep = 0, | ||
| 116 | .ypanstep = 0, | ||
| 117 | .ywrapstep = 0, | ||
| 118 | .accel = FB_ACCEL_NONE, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const u32 smscufx_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | ||
| 122 | FBINFO_VIRTFB | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT | | ||
| 123 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; | ||
| 124 | |||
| 125 | static struct usb_device_id id_table[] = { | ||
| 126 | {USB_DEVICE(0x0424, 0x9d00),}, | ||
| 127 | {USB_DEVICE(0x0424, 0x9d01),}, | ||
| 128 | {}, | ||
| 129 | }; | ||
| 130 | MODULE_DEVICE_TABLE(usb, id_table); | ||
| 131 | |||
| 132 | /* module options */ | ||
| 133 | static int console; /* Optionally allow fbcon to consume first framebuffer */ | ||
| 134 | static int fb_defio = true; /* Optionally enable fb_defio mmap support */ | ||
| 135 | |||
| 136 | /* ufx keeps a list of urbs for efficient bulk transfers */ | ||
| 137 | static void ufx_urb_completion(struct urb *urb); | ||
| 138 | static struct urb *ufx_get_urb(struct ufx_data *dev); | ||
| 139 | static int ufx_submit_urb(struct ufx_data *dev, struct urb * urb, size_t len); | ||
| 140 | static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size); | ||
| 141 | static void ufx_free_urb_list(struct ufx_data *dev); | ||
| 142 | |||
| 143 | /* reads a control register */ | ||
| 144 | static int ufx_reg_read(struct ufx_data *dev, u32 index, u32 *data) | ||
| 145 | { | ||
| 146 | u32 *buf = kmalloc(4, GFP_KERNEL); | ||
| 147 | int ret; | ||
| 148 | |||
| 149 | BUG_ON(!dev); | ||
| 150 | |||
| 151 | if (!buf) | ||
| 152 | return -ENOMEM; | ||
| 153 | |||
| 154 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
| 155 | USB_VENDOR_REQUEST_READ_REGISTER, | ||
| 156 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 157 | 00, index, buf, 4, USB_CTRL_GET_TIMEOUT); | ||
| 158 | |||
| 159 | le32_to_cpus(buf); | ||
| 160 | *data = *buf; | ||
| 161 | kfree(buf); | ||
| 162 | |||
| 163 | if (unlikely(ret < 0)) | ||
| 164 | pr_warn("Failed to read register index 0x%08x\n", index); | ||
| 165 | |||
| 166 | return ret; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* writes a control register */ | ||
| 170 | static int ufx_reg_write(struct ufx_data *dev, u32 index, u32 data) | ||
| 171 | { | ||
| 172 | u32 *buf = kmalloc(4, GFP_KERNEL); | ||
| 173 | int ret; | ||
| 174 | |||
| 175 | BUG_ON(!dev); | ||
| 176 | |||
| 177 | if (!buf) | ||
| 178 | return -ENOMEM; | ||
| 179 | |||
| 180 | *buf = data; | ||
| 181 | cpu_to_le32s(buf); | ||
| 182 | |||
| 183 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
| 184 | USB_VENDOR_REQUEST_WRITE_REGISTER, | ||
| 185 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 186 | 00, index, buf, 4, USB_CTRL_SET_TIMEOUT); | ||
| 187 | |||
| 188 | kfree(buf); | ||
| 189 | |||
| 190 | if (unlikely(ret < 0)) | ||
| 191 | pr_warn("Failed to write register index 0x%08x with value " | ||
| 192 | "0x%08x\n", index, data); | ||
| 193 | |||
| 194 | return ret; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int ufx_reg_clear_and_set_bits(struct ufx_data *dev, u32 index, | ||
| 198 | u32 bits_to_clear, u32 bits_to_set) | ||
| 199 | { | ||
| 200 | u32 data; | ||
| 201 | int status = ufx_reg_read(dev, index, &data); | ||
| 202 | check_warn_return(status, "ufx_reg_clear_and_set_bits error reading " | ||
| 203 | "0x%x", index); | ||
| 204 | |||
| 205 | data &= (~bits_to_clear); | ||
| 206 | data |= bits_to_set; | ||
| 207 | |||
| 208 | status = ufx_reg_write(dev, index, data); | ||
| 209 | check_warn_return(status, "ufx_reg_clear_and_set_bits error writing " | ||
| 210 | "0x%x", index); | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int ufx_reg_set_bits(struct ufx_data *dev, u32 index, u32 bits) | ||
| 216 | { | ||
| 217 | return ufx_reg_clear_and_set_bits(dev, index, 0, bits); | ||
| 218 | } | ||
| 219 | |||
| 220 | static int ufx_reg_clear_bits(struct ufx_data *dev, u32 index, u32 bits) | ||
| 221 | { | ||
| 222 | return ufx_reg_clear_and_set_bits(dev, index, bits, 0); | ||
| 223 | } | ||
| 224 | |||
| 225 | static int ufx_lite_reset(struct ufx_data *dev) | ||
| 226 | { | ||
| 227 | int status; | ||
| 228 | u32 value; | ||
| 229 | |||
| 230 | status = ufx_reg_write(dev, 0x3008, 0x00000001); | ||
| 231 | check_warn_return(status, "ufx_lite_reset error writing 0x3008"); | ||
| 232 | |||
| 233 | status = ufx_reg_read(dev, 0x3008, &value); | ||
| 234 | check_warn_return(status, "ufx_lite_reset error reading 0x3008"); | ||
| 235 | |||
| 236 | return (value == 0) ? 0 : -EIO; | ||
| 237 | } | ||
| 238 | |||
| 239 | /* If display is unblanked, then blank it */ | ||
| 240 | static int ufx_blank(struct ufx_data *dev, bool wait) | ||
| 241 | { | ||
| 242 | u32 dc_ctrl, dc_sts; | ||
| 243 | int i; | ||
| 244 | |||
| 245 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 246 | check_warn_return(status, "ufx_blank error reading 0x2004"); | ||
| 247 | |||
| 248 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
| 249 | check_warn_return(status, "ufx_blank error reading 0x2000"); | ||
| 250 | |||
| 251 | /* return success if display is already blanked */ | ||
| 252 | if ((dc_sts & 0x00000100) || (dc_ctrl & 0x00000100)) | ||
| 253 | return 0; | ||
| 254 | |||
| 255 | /* request the DC to blank the display */ | ||
| 256 | dc_ctrl |= 0x00000100; | ||
| 257 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
| 258 | check_warn_return(status, "ufx_blank error writing 0x2000"); | ||
| 259 | |||
| 260 | /* return success immediately if we don't have to wait */ | ||
| 261 | if (!wait) | ||
| 262 | return 0; | ||
| 263 | |||
| 264 | for (i = 0; i < 250; i++) { | ||
| 265 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 266 | check_warn_return(status, "ufx_blank error reading 0x2004"); | ||
| 267 | |||
| 268 | if (dc_sts & 0x00000100) | ||
| 269 | return 0; | ||
| 270 | } | ||
| 271 | |||
| 272 | /* timed out waiting for display to blank */ | ||
| 273 | return -EIO; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* If display is blanked, then unblank it */ | ||
| 277 | static int ufx_unblank(struct ufx_data *dev, bool wait) | ||
| 278 | { | ||
| 279 | u32 dc_ctrl, dc_sts; | ||
| 280 | int i; | ||
| 281 | |||
| 282 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 283 | check_warn_return(status, "ufx_unblank error reading 0x2004"); | ||
| 284 | |||
| 285 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
| 286 | check_warn_return(status, "ufx_unblank error reading 0x2000"); | ||
| 287 | |||
| 288 | /* return success if display is already unblanked */ | ||
| 289 | if (((dc_sts & 0x00000100) == 0) || ((dc_ctrl & 0x00000100) == 0)) | ||
| 290 | return 0; | ||
| 291 | |||
| 292 | /* request the DC to unblank the display */ | ||
| 293 | dc_ctrl &= ~0x00000100; | ||
| 294 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
| 295 | check_warn_return(status, "ufx_unblank error writing 0x2000"); | ||
| 296 | |||
| 297 | /* return success immediately if we don't have to wait */ | ||
| 298 | if (!wait) | ||
| 299 | return 0; | ||
| 300 | |||
| 301 | for (i = 0; i < 250; i++) { | ||
| 302 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 303 | check_warn_return(status, "ufx_unblank error reading 0x2004"); | ||
| 304 | |||
| 305 | if ((dc_sts & 0x00000100) == 0) | ||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* timed out waiting for display to unblank */ | ||
| 310 | return -EIO; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* If display is enabled, then disable it */ | ||
| 314 | static int ufx_disable(struct ufx_data *dev, bool wait) | ||
| 315 | { | ||
| 316 | u32 dc_ctrl, dc_sts; | ||
| 317 | int i; | ||
| 318 | |||
| 319 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 320 | check_warn_return(status, "ufx_disable error reading 0x2004"); | ||
| 321 | |||
| 322 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
| 323 | check_warn_return(status, "ufx_disable error reading 0x2000"); | ||
| 324 | |||
| 325 | /* return success if display is already disabled */ | ||
| 326 | if (((dc_sts & 0x00000001) == 0) || ((dc_ctrl & 0x00000001) == 0)) | ||
| 327 | return 0; | ||
| 328 | |||
| 329 | /* request the DC to disable the display */ | ||
| 330 | dc_ctrl &= ~(0x00000001); | ||
| 331 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
| 332 | check_warn_return(status, "ufx_disable error writing 0x2000"); | ||
| 333 | |||
| 334 | /* return success immediately if we don't have to wait */ | ||
| 335 | if (!wait) | ||
| 336 | return 0; | ||
| 337 | |||
| 338 | for (i = 0; i < 250; i++) { | ||
| 339 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 340 | check_warn_return(status, "ufx_disable error reading 0x2004"); | ||
| 341 | |||
| 342 | if ((dc_sts & 0x00000001) == 0) | ||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | /* timed out waiting for display to disable */ | ||
| 347 | return -EIO; | ||
| 348 | } | ||
| 349 | |||
| 350 | /* If display is disabled, then enable it */ | ||
| 351 | static int ufx_enable(struct ufx_data *dev, bool wait) | ||
| 352 | { | ||
| 353 | u32 dc_ctrl, dc_sts; | ||
| 354 | int i; | ||
| 355 | |||
| 356 | int status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 357 | check_warn_return(status, "ufx_enable error reading 0x2004"); | ||
| 358 | |||
| 359 | status = ufx_reg_read(dev, 0x2000, &dc_ctrl); | ||
| 360 | check_warn_return(status, "ufx_enable error reading 0x2000"); | ||
| 361 | |||
| 362 | /* return success if display is already enabled */ | ||
| 363 | if ((dc_sts & 0x00000001) || (dc_ctrl & 0x00000001)) | ||
| 364 | return 0; | ||
| 365 | |||
| 366 | /* request the DC to enable the display */ | ||
| 367 | dc_ctrl |= 0x00000001; | ||
| 368 | status = ufx_reg_write(dev, 0x2000, dc_ctrl); | ||
| 369 | check_warn_return(status, "ufx_enable error writing 0x2000"); | ||
| 370 | |||
| 371 | /* return success immediately if we don't have to wait */ | ||
| 372 | if (!wait) | ||
| 373 | return 0; | ||
| 374 | |||
| 375 | for (i = 0; i < 250; i++) { | ||
| 376 | status = ufx_reg_read(dev, 0x2004, &dc_sts); | ||
| 377 | check_warn_return(status, "ufx_enable error reading 0x2004"); | ||
| 378 | |||
| 379 | if (dc_sts & 0x00000001) | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | /* timed out waiting for display to enable */ | ||
| 384 | return -EIO; | ||
| 385 | } | ||
| 386 | |||
| 387 | static int ufx_config_sys_clk(struct ufx_data *dev) | ||
| 388 | { | ||
| 389 | int status = ufx_reg_write(dev, 0x700C, 0x8000000F); | ||
| 390 | check_warn_return(status, "error writing 0x700C"); | ||
| 391 | |||
| 392 | status = ufx_reg_write(dev, 0x7014, 0x0010024F); | ||
| 393 | check_warn_return(status, "error writing 0x7014"); | ||
| 394 | |||
| 395 | status = ufx_reg_write(dev, 0x7010, 0x00000000); | ||
| 396 | check_warn_return(status, "error writing 0x7010"); | ||
| 397 | |||
| 398 | status = ufx_reg_clear_bits(dev, 0x700C, 0x0000000A); | ||
| 399 | check_warn_return(status, "error clearing PLL1 bypass in 0x700C"); | ||
| 400 | msleep(1); | ||
| 401 | |||
| 402 | status = ufx_reg_clear_bits(dev, 0x700C, 0x80000000); | ||
| 403 | check_warn_return(status, "error clearing output gate in 0x700C"); | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static int ufx_config_ddr2(struct ufx_data *dev) | ||
| 409 | { | ||
| 410 | int status, i = 0; | ||
| 411 | u32 tmp; | ||
| 412 | |||
| 413 | status = ufx_reg_write(dev, 0x0004, 0x001F0F77); | ||
| 414 | check_warn_return(status, "error writing 0x0004"); | ||
| 415 | |||
| 416 | status = ufx_reg_write(dev, 0x0008, 0xFFF00000); | ||
| 417 | check_warn_return(status, "error writing 0x0008"); | ||
| 418 | |||
| 419 | status = ufx_reg_write(dev, 0x000C, 0x0FFF2222); | ||
| 420 | check_warn_return(status, "error writing 0x000C"); | ||
| 421 | |||
| 422 | status = ufx_reg_write(dev, 0x0010, 0x00030814); | ||
| 423 | check_warn_return(status, "error writing 0x0010"); | ||
| 424 | |||
| 425 | status = ufx_reg_write(dev, 0x0014, 0x00500019); | ||
| 426 | check_warn_return(status, "error writing 0x0014"); | ||
| 427 | |||
| 428 | status = ufx_reg_write(dev, 0x0018, 0x020D0F15); | ||
| 429 | check_warn_return(status, "error writing 0x0018"); | ||
| 430 | |||
| 431 | status = ufx_reg_write(dev, 0x001C, 0x02532305); | ||
| 432 | check_warn_return(status, "error writing 0x001C"); | ||
| 433 | |||
| 434 | status = ufx_reg_write(dev, 0x0020, 0x0B030905); | ||
| 435 | check_warn_return(status, "error writing 0x0020"); | ||
| 436 | |||
| 437 | status = ufx_reg_write(dev, 0x0024, 0x00000827); | ||
| 438 | check_warn_return(status, "error writing 0x0024"); | ||
| 439 | |||
| 440 | status = ufx_reg_write(dev, 0x0028, 0x00000000); | ||
| 441 | check_warn_return(status, "error writing 0x0028"); | ||
| 442 | |||
| 443 | status = ufx_reg_write(dev, 0x002C, 0x00000042); | ||
| 444 | check_warn_return(status, "error writing 0x002C"); | ||
| 445 | |||
| 446 | status = ufx_reg_write(dev, 0x0030, 0x09520000); | ||
| 447 | check_warn_return(status, "error writing 0x0030"); | ||
| 448 | |||
| 449 | status = ufx_reg_write(dev, 0x0034, 0x02223314); | ||
| 450 | check_warn_return(status, "error writing 0x0034"); | ||
| 451 | |||
| 452 | status = ufx_reg_write(dev, 0x0038, 0x00430043); | ||
| 453 | check_warn_return(status, "error writing 0x0038"); | ||
| 454 | |||
| 455 | status = ufx_reg_write(dev, 0x003C, 0xF00F000F); | ||
| 456 | check_warn_return(status, "error writing 0x003C"); | ||
| 457 | |||
| 458 | status = ufx_reg_write(dev, 0x0040, 0xF380F00F); | ||
| 459 | check_warn_return(status, "error writing 0x0040"); | ||
| 460 | |||
| 461 | status = ufx_reg_write(dev, 0x0044, 0xF00F0496); | ||
| 462 | check_warn_return(status, "error writing 0x0044"); | ||
| 463 | |||
| 464 | status = ufx_reg_write(dev, 0x0048, 0x03080406); | ||
| 465 | check_warn_return(status, "error writing 0x0048"); | ||
| 466 | |||
| 467 | status = ufx_reg_write(dev, 0x004C, 0x00001000); | ||
| 468 | check_warn_return(status, "error writing 0x004C"); | ||
| 469 | |||
| 470 | status = ufx_reg_write(dev, 0x005C, 0x00000007); | ||
| 471 | check_warn_return(status, "error writing 0x005C"); | ||
| 472 | |||
| 473 | status = ufx_reg_write(dev, 0x0100, 0x54F00012); | ||
| 474 | check_warn_return(status, "error writing 0x0100"); | ||
| 475 | |||
| 476 | status = ufx_reg_write(dev, 0x0104, 0x00004012); | ||
| 477 | check_warn_return(status, "error writing 0x0104"); | ||
| 478 | |||
| 479 | status = ufx_reg_write(dev, 0x0118, 0x40404040); | ||
| 480 | check_warn_return(status, "error writing 0x0118"); | ||
| 481 | |||
| 482 | status = ufx_reg_write(dev, 0x0000, 0x00000001); | ||
| 483 | check_warn_return(status, "error writing 0x0000"); | ||
| 484 | |||
| 485 | while (i++ < 500) { | ||
| 486 | status = ufx_reg_read(dev, 0x0000, &tmp); | ||
| 487 | check_warn_return(status, "error reading 0x0000"); | ||
| 488 | |||
| 489 | if (all_bits_set(tmp, 0xC0000000)) | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | |||
| 493 | pr_err("DDR2 initialisation timed out, reg 0x0000=0x%08x", tmp); | ||
| 494 | return -ETIMEDOUT; | ||
| 495 | } | ||
| 496 | |||
| 497 | struct pll_values { | ||
| 498 | u32 div_r0; | ||
| 499 | u32 div_f0; | ||
| 500 | u32 div_q0; | ||
| 501 | u32 range0; | ||
| 502 | u32 div_r1; | ||
| 503 | u32 div_f1; | ||
| 504 | u32 div_q1; | ||
| 505 | u32 range1; | ||
| 506 | }; | ||
| 507 | |||
| 508 | static u32 ufx_calc_range(u32 ref_freq) | ||
| 509 | { | ||
| 510 | if (ref_freq >= 88000000) | ||
| 511 | return 7; | ||
| 512 | |||
| 513 | if (ref_freq >= 54000000) | ||
| 514 | return 6; | ||
| 515 | |||
| 516 | if (ref_freq >= 34000000) | ||
| 517 | return 5; | ||
| 518 | |||
| 519 | if (ref_freq >= 21000000) | ||
| 520 | return 4; | ||
| 521 | |||
| 522 | if (ref_freq >= 13000000) | ||
| 523 | return 3; | ||
| 524 | |||
| 525 | if (ref_freq >= 8000000) | ||
| 526 | return 2; | ||
| 527 | |||
| 528 | return 1; | ||
| 529 | } | ||
| 530 | |||
| 531 | /* calculates PLL divider settings for a desired target frequency */ | ||
| 532 | static void ufx_calc_pll_values(const u32 clk_pixel_pll, struct pll_values *asic_pll) | ||
| 533 | { | ||
| 534 | const u32 ref_clk = 25000000; | ||
| 535 | u32 div_r0, div_f0, div_q0, div_r1, div_f1, div_q1; | ||
| 536 | u32 min_error = clk_pixel_pll; | ||
| 537 | |||
| 538 | for (div_r0 = 1; div_r0 <= 32; div_r0++) { | ||
| 539 | u32 ref_freq0 = ref_clk / div_r0; | ||
| 540 | if (ref_freq0 < 5000000) | ||
| 541 | break; | ||
| 542 | |||
| 543 | if (ref_freq0 > 200000000) | ||
| 544 | continue; | ||
| 545 | |||
| 546 | for (div_f0 = 1; div_f0 <= 256; div_f0++) { | ||
| 547 | u32 vco_freq0 = ref_freq0 * div_f0; | ||
| 548 | |||
| 549 | if (vco_freq0 < 350000000) | ||
| 550 | continue; | ||
| 551 | |||
| 552 | if (vco_freq0 > 700000000) | ||
| 553 | break; | ||
| 554 | |||
| 555 | for (div_q0 = 0; div_q0 < 7; div_q0++) { | ||
| 556 | u32 pllout_freq0 = vco_freq0 / (1 << div_q0); | ||
| 557 | |||
| 558 | if (pllout_freq0 < 5000000) | ||
| 559 | break; | ||
| 560 | |||
| 561 | if (pllout_freq0 > 200000000) | ||
| 562 | continue; | ||
| 563 | |||
| 564 | for (div_r1 = 1; div_r1 <= 32; div_r1++) { | ||
| 565 | u32 ref_freq1 = pllout_freq0 / div_r1; | ||
| 566 | |||
| 567 | if (ref_freq1 < 5000000) | ||
| 568 | break; | ||
| 569 | |||
| 570 | for (div_f1 = 1; div_f1 <= 256; div_f1++) { | ||
| 571 | u32 vco_freq1 = ref_freq1 * div_f1; | ||
| 572 | |||
| 573 | if (vco_freq1 < 350000000) | ||
| 574 | continue; | ||
| 575 | |||
| 576 | if (vco_freq1 > 700000000) | ||
| 577 | break; | ||
| 578 | |||
| 579 | for (div_q1 = 0; div_q1 < 7; div_q1++) { | ||
| 580 | u32 pllout_freq1 = vco_freq1 / (1 << div_q1); | ||
| 581 | int error = abs(pllout_freq1 - clk_pixel_pll); | ||
| 582 | |||
| 583 | if (pllout_freq1 < 5000000) | ||
| 584 | break; | ||
| 585 | |||
| 586 | if (pllout_freq1 > 700000000) | ||
| 587 | continue; | ||
| 588 | |||
| 589 | if (error < min_error) { | ||
| 590 | min_error = error; | ||
| 591 | |||
| 592 | /* final returned value is equal to calculated value - 1 | ||
| 593 | * because a value of 0 = divide by 1 */ | ||
| 594 | asic_pll->div_r0 = div_r0 - 1; | ||
| 595 | asic_pll->div_f0 = div_f0 - 1; | ||
| 596 | asic_pll->div_q0 = div_q0; | ||
| 597 | asic_pll->div_r1 = div_r1 - 1; | ||
| 598 | asic_pll->div_f1 = div_f1 - 1; | ||
| 599 | asic_pll->div_q1 = div_q1; | ||
| 600 | |||
| 601 | asic_pll->range0 = ufx_calc_range(ref_freq0); | ||
| 602 | asic_pll->range1 = ufx_calc_range(ref_freq1); | ||
| 603 | |||
| 604 | if (min_error == 0) | ||
| 605 | return; | ||
| 606 | } | ||
| 607 | } | ||
| 608 | } | ||
| 609 | } | ||
| 610 | } | ||
| 611 | } | ||
| 612 | } | ||
| 613 | } | ||
| 614 | |||
| 615 | /* sets analog bit PLL configuration values */ | ||
| 616 | static int ufx_config_pix_clk(struct ufx_data *dev, u32 pixclock) | ||
| 617 | { | ||
| 618 | struct pll_values asic_pll = {0}; | ||
| 619 | u32 value, clk_pixel, clk_pixel_pll; | ||
| 620 | int status; | ||
| 621 | |||
| 622 | /* convert pixclock (in ps) to frequency (in Hz) */ | ||
| 623 | clk_pixel = PICOS2KHZ(pixclock) * 1000; | ||
| 624 | pr_debug("pixclock %d ps = clk_pixel %d Hz", pixclock, clk_pixel); | ||
| 625 | |||
| 626 | /* clk_pixel = 1/2 clk_pixel_pll */ | ||
| 627 | clk_pixel_pll = clk_pixel * 2; | ||
| 628 | |||
| 629 | ufx_calc_pll_values(clk_pixel_pll, &asic_pll); | ||
| 630 | |||
| 631 | /* Keep BYPASS and RESET signals asserted until configured */ | ||
| 632 | status = ufx_reg_write(dev, 0x7000, 0x8000000F); | ||
| 633 | check_warn_return(status, "error writing 0x7000"); | ||
| 634 | |||
| 635 | value = (asic_pll.div_f1 | (asic_pll.div_r1 << 8) | | ||
| 636 | (asic_pll.div_q1 << 16) | (asic_pll.range1 << 20)); | ||
| 637 | status = ufx_reg_write(dev, 0x7008, value); | ||
| 638 | check_warn_return(status, "error writing 0x7008"); | ||
| 639 | |||
| 640 | value = (asic_pll.div_f0 | (asic_pll.div_r0 << 8) | | ||
| 641 | (asic_pll.div_q0 << 16) | (asic_pll.range0 << 20)); | ||
| 642 | status = ufx_reg_write(dev, 0x7004, value); | ||
| 643 | check_warn_return(status, "error writing 0x7004"); | ||
| 644 | |||
| 645 | status = ufx_reg_clear_bits(dev, 0x7000, 0x00000005); | ||
| 646 | check_warn_return(status, | ||
| 647 | "error clearing PLL0 bypass bits in 0x7000"); | ||
| 648 | msleep(1); | ||
| 649 | |||
| 650 | status = ufx_reg_clear_bits(dev, 0x7000, 0x0000000A); | ||
| 651 | check_warn_return(status, | ||
| 652 | "error clearing PLL1 bypass bits in 0x7000"); | ||
| 653 | msleep(1); | ||
| 654 | |||
| 655 | status = ufx_reg_clear_bits(dev, 0x7000, 0x80000000); | ||
| 656 | check_warn_return(status, "error clearing gate bits in 0x7000"); | ||
| 657 | |||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | |||
| 661 | static int ufx_set_vid_mode(struct ufx_data *dev, struct fb_var_screeninfo *var) | ||
| 662 | { | ||
| 663 | u32 temp; | ||
| 664 | u16 h_total, h_active, h_blank_start, h_blank_end, h_sync_start, h_sync_end; | ||
| 665 | u16 v_total, v_active, v_blank_start, v_blank_end, v_sync_start, v_sync_end; | ||
| 666 | |||
| 667 | int status = ufx_reg_write(dev, 0x8028, 0); | ||
| 668 | check_warn_return(status, "ufx_set_vid_mode error disabling RGB pad"); | ||
| 669 | |||
| 670 | status = ufx_reg_write(dev, 0x8024, 0); | ||
| 671 | check_warn_return(status, "ufx_set_vid_mode error disabling VDAC"); | ||
| 672 | |||
| 673 | /* shut everything down before changing timing */ | ||
| 674 | status = ufx_blank(dev, true); | ||
| 675 | check_warn_return(status, "ufx_set_vid_mode error blanking display"); | ||
| 676 | |||
| 677 | status = ufx_disable(dev, true); | ||
| 678 | check_warn_return(status, "ufx_set_vid_mode error disabling display"); | ||
| 679 | |||
| 680 | status = ufx_config_pix_clk(dev, var->pixclock); | ||
| 681 | check_warn_return(status, "ufx_set_vid_mode error configuring pixclock"); | ||
| 682 | |||
| 683 | status = ufx_reg_write(dev, 0x2000, 0x00000104); | ||
| 684 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2000"); | ||
| 685 | |||
| 686 | /* set horizontal timings */ | ||
| 687 | h_total = var->xres + var->right_margin + var->hsync_len + var->left_margin; | ||
| 688 | h_active = var->xres; | ||
| 689 | h_blank_start = var->xres + var->right_margin; | ||
| 690 | h_blank_end = var->xres + var->right_margin + var->hsync_len; | ||
| 691 | h_sync_start = var->xres + var->right_margin; | ||
| 692 | h_sync_end = var->xres + var->right_margin + var->hsync_len; | ||
| 693 | |||
| 694 | temp = ((h_total - 1) << 16) | (h_active - 1); | ||
| 695 | status = ufx_reg_write(dev, 0x2008, temp); | ||
| 696 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2008"); | ||
| 697 | |||
| 698 | temp = ((h_blank_start - 1) << 16) | (h_blank_end - 1); | ||
| 699 | status = ufx_reg_write(dev, 0x200C, temp); | ||
| 700 | check_warn_return(status, "ufx_set_vid_mode error writing 0x200C"); | ||
| 701 | |||
| 702 | temp = ((h_sync_start - 1) << 16) | (h_sync_end - 1); | ||
| 703 | status = ufx_reg_write(dev, 0x2010, temp); | ||
| 704 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2010"); | ||
| 705 | |||
| 706 | /* set vertical timings */ | ||
| 707 | v_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; | ||
| 708 | v_active = var->yres; | ||
| 709 | v_blank_start = var->yres + var->lower_margin; | ||
| 710 | v_blank_end = var->yres + var->lower_margin + var->vsync_len; | ||
| 711 | v_sync_start = var->yres + var->lower_margin; | ||
| 712 | v_sync_end = var->yres + var->lower_margin + var->vsync_len; | ||
| 713 | |||
| 714 | temp = ((v_total - 1) << 16) | (v_active - 1); | ||
| 715 | status = ufx_reg_write(dev, 0x2014, temp); | ||
| 716 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2014"); | ||
| 717 | |||
| 718 | temp = ((v_blank_start - 1) << 16) | (v_blank_end - 1); | ||
| 719 | status = ufx_reg_write(dev, 0x2018, temp); | ||
| 720 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2018"); | ||
| 721 | |||
| 722 | temp = ((v_sync_start - 1) << 16) | (v_sync_end - 1); | ||
| 723 | status = ufx_reg_write(dev, 0x201C, temp); | ||
| 724 | check_warn_return(status, "ufx_set_vid_mode error writing 0x201C"); | ||
| 725 | |||
| 726 | status = ufx_reg_write(dev, 0x2020, 0x00000000); | ||
| 727 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2020"); | ||
| 728 | |||
| 729 | status = ufx_reg_write(dev, 0x2024, 0x00000000); | ||
| 730 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2024"); | ||
| 731 | |||
| 732 | /* Set the frame length register (#pix * 2 bytes/pixel) */ | ||
| 733 | temp = var->xres * var->yres * 2; | ||
| 734 | temp = (temp + 7) & (~0x7); | ||
| 735 | status = ufx_reg_write(dev, 0x2028, temp); | ||
| 736 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2028"); | ||
| 737 | |||
| 738 | /* enable desired output interface & disable others */ | ||
| 739 | status = ufx_reg_write(dev, 0x2040, 0); | ||
| 740 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2040"); | ||
| 741 | |||
| 742 | status = ufx_reg_write(dev, 0x2044, 0); | ||
| 743 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2044"); | ||
| 744 | |||
| 745 | status = ufx_reg_write(dev, 0x2048, 0); | ||
| 746 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2048"); | ||
| 747 | |||
| 748 | /* set the sync polarities & enable bit */ | ||
| 749 | temp = 0x00000001; | ||
| 750 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | ||
| 751 | temp |= 0x00000010; | ||
| 752 | |||
| 753 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | ||
| 754 | temp |= 0x00000008; | ||
| 755 | |||
| 756 | status = ufx_reg_write(dev, 0x2040, temp); | ||
| 757 | check_warn_return(status, "ufx_set_vid_mode error writing 0x2040"); | ||
| 758 | |||
| 759 | /* start everything back up */ | ||
| 760 | status = ufx_enable(dev, true); | ||
| 761 | check_warn_return(status, "ufx_set_vid_mode error enabling display"); | ||
| 762 | |||
| 763 | /* Unblank the display */ | ||
| 764 | status = ufx_unblank(dev, true); | ||
| 765 | check_warn_return(status, "ufx_set_vid_mode error unblanking display"); | ||
| 766 | |||
| 767 | /* enable RGB pad */ | ||
| 768 | status = ufx_reg_write(dev, 0x8028, 0x00000003); | ||
| 769 | check_warn_return(status, "ufx_set_vid_mode error enabling RGB pad"); | ||
| 770 | |||
| 771 | /* enable VDAC */ | ||
| 772 | status = ufx_reg_write(dev, 0x8024, 0x00000007); | ||
| 773 | check_warn_return(status, "ufx_set_vid_mode error enabling VDAC"); | ||
| 774 | |||
| 775 | return 0; | ||
| 776 | } | ||
| 777 | |||
| 778 | static int ufx_ops_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
| 779 | { | ||
| 780 | unsigned long start = vma->vm_start; | ||
| 781 | unsigned long size = vma->vm_end - vma->vm_start; | ||
| 782 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
| 783 | unsigned long page, pos; | ||
| 784 | |||
| 785 | if (offset + size > info->fix.smem_len) | ||
| 786 | return -EINVAL; | ||
| 787 | |||
| 788 | pos = (unsigned long)info->fix.smem_start + offset; | ||
| 789 | |||
| 790 | pr_debug("mmap() framebuffer addr:%lu size:%lu\n", | ||
| 791 | pos, size); | ||
| 792 | |||
| 793 | while (size > 0) { | ||
| 794 | page = vmalloc_to_pfn((void *)pos); | ||
| 795 | if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) | ||
| 796 | return -EAGAIN; | ||
| 797 | |||
| 798 | start += PAGE_SIZE; | ||
| 799 | pos += PAGE_SIZE; | ||
| 800 | if (size > PAGE_SIZE) | ||
| 801 | size -= PAGE_SIZE; | ||
| 802 | else | ||
| 803 | size = 0; | ||
| 804 | } | ||
| 805 | |||
| 806 | vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ | ||
| 807 | return 0; | ||
| 808 | } | ||
| 809 | |||
| 810 | static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y, | ||
| 811 | int width, int height) | ||
| 812 | { | ||
| 813 | size_t packed_line_len = ALIGN((width * 2), 4); | ||
| 814 | size_t packed_rect_len = packed_line_len * height; | ||
| 815 | int line; | ||
| 816 | |||
| 817 | BUG_ON(!dev); | ||
| 818 | BUG_ON(!dev->info); | ||
| 819 | |||
| 820 | /* command word */ | ||
| 821 | *((u32 *)&cmd[0]) = cpu_to_le32(0x01); | ||
| 822 | |||
| 823 | /* length word */ | ||
| 824 | *((u32 *)&cmd[2]) = cpu_to_le32(packed_rect_len + 16); | ||
| 825 | |||
| 826 | cmd[4] = cpu_to_le16(x); | ||
| 827 | cmd[5] = cpu_to_le16(y); | ||
| 828 | cmd[6] = cpu_to_le16(width); | ||
| 829 | cmd[7] = cpu_to_le16(height); | ||
| 830 | |||
| 831 | /* frame base address */ | ||
| 832 | *((u32 *)&cmd[8]) = cpu_to_le32(0); | ||
| 833 | |||
| 834 | /* color mode and horizontal resolution */ | ||
| 835 | cmd[10] = cpu_to_le16(0x4000 | dev->info->var.xres); | ||
| 836 | |||
| 837 | /* vertical resolution */ | ||
| 838 | cmd[11] = cpu_to_le16(dev->info->var.yres); | ||
| 839 | |||
| 840 | /* packed data */ | ||
| 841 | for (line = 0; line < height; line++) { | ||
| 842 | const int line_offset = dev->info->fix.line_length * (y + line); | ||
| 843 | const int byte_offset = line_offset + (x * BPP); | ||
| 844 | memcpy(&cmd[(24 + (packed_line_len * line)) / 2], | ||
| 845 | (char *)dev->info->fix.smem_start + byte_offset, width * BPP); | ||
| 846 | } | ||
| 847 | } | ||
| 848 | |||
| 849 | int ufx_handle_damage(struct ufx_data *dev, int x, int y, | ||
| 850 | int width, int height) | ||
| 851 | { | ||
| 852 | size_t packed_line_len = ALIGN((width * 2), 4); | ||
| 853 | int len, status, urb_lines, start_line = 0; | ||
| 854 | |||
| 855 | if ((width <= 0) || (height <= 0) || | ||
| 856 | (x + width > dev->info->var.xres) || | ||
| 857 | (y + height > dev->info->var.yres)) | ||
| 858 | return -EINVAL; | ||
| 859 | |||
| 860 | if (!atomic_read(&dev->usb_active)) | ||
| 861 | return 0; | ||
| 862 | |||
| 863 | while (start_line < height) { | ||
| 864 | struct urb *urb = ufx_get_urb(dev); | ||
| 865 | if (!urb) { | ||
| 866 | pr_warn("ufx_handle_damage unable to get urb"); | ||
| 867 | return 0; | ||
| 868 | } | ||
| 869 | |||
| 870 | /* assume we have enough space to transfer at least one line */ | ||
| 871 | BUG_ON(urb->transfer_buffer_length < (24 + (width * 2))); | ||
| 872 | |||
| 873 | /* calculate the maximum number of lines we could fit in */ | ||
| 874 | urb_lines = (urb->transfer_buffer_length - 24) / packed_line_len; | ||
| 875 | |||
| 876 | /* but we might not need this many */ | ||
| 877 | urb_lines = min(urb_lines, (height - start_line)); | ||
| 878 | |||
| 879 | memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); | ||
| 880 | |||
| 881 | ufx_raw_rect(dev, urb->transfer_buffer, x, (y + start_line), width, urb_lines); | ||
| 882 | len = 24 + (packed_line_len * urb_lines); | ||
| 883 | |||
| 884 | status = ufx_submit_urb(dev, urb, len); | ||
| 885 | check_warn_return(status, "Error submitting URB"); | ||
| 886 | |||
| 887 | start_line += urb_lines; | ||
| 888 | } | ||
| 889 | |||
| 890 | return 0; | ||
| 891 | } | ||
| 892 | |||
| 893 | /* Path triggered by usermode clients who write to filesystem | ||
| 894 | * e.g. cat filename > /dev/fb1 | ||
| 895 | * Not used by X Windows or text-mode console. But useful for testing. | ||
| 896 | * Slow because of extra copy and we must assume all pixels dirty. */ | ||
| 897 | static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf, | ||
| 898 | size_t count, loff_t *ppos) | ||
| 899 | { | ||
| 900 | ssize_t result; | ||
| 901 | struct ufx_data *dev = info->par; | ||
| 902 | u32 offset = (u32) *ppos; | ||
| 903 | |||
| 904 | result = fb_sys_write(info, buf, count, ppos); | ||
| 905 | |||
| 906 | if (result > 0) { | ||
| 907 | int start = max((int)(offset / info->fix.line_length) - 1, 0); | ||
| 908 | int lines = min((u32)((result / info->fix.line_length) + 1), | ||
| 909 | (u32)info->var.yres); | ||
| 910 | |||
| 911 | ufx_handle_damage(dev, 0, start, info->var.xres, lines); | ||
| 912 | } | ||
| 913 | |||
| 914 | return result; | ||
| 915 | } | ||
| 916 | |||
| 917 | static void ufx_ops_copyarea(struct fb_info *info, | ||
| 918 | const struct fb_copyarea *area) | ||
| 919 | { | ||
| 920 | |||
| 921 | struct ufx_data *dev = info->par; | ||
| 922 | |||
| 923 | sys_copyarea(info, area); | ||
| 924 | |||
| 925 | ufx_handle_damage(dev, area->dx, area->dy, | ||
| 926 | area->width, area->height); | ||
| 927 | } | ||
| 928 | |||
| 929 | static void ufx_ops_imageblit(struct fb_info *info, | ||
| 930 | const struct fb_image *image) | ||
| 931 | { | ||
| 932 | struct ufx_data *dev = info->par; | ||
| 933 | |||
| 934 | sys_imageblit(info, image); | ||
| 935 | |||
| 936 | ufx_handle_damage(dev, image->dx, image->dy, | ||
| 937 | image->width, image->height); | ||
| 938 | } | ||
| 939 | |||
| 940 | static void ufx_ops_fillrect(struct fb_info *info, | ||
| 941 | const struct fb_fillrect *rect) | ||
| 942 | { | ||
| 943 | struct ufx_data *dev = info->par; | ||
| 944 | |||
| 945 | sys_fillrect(info, rect); | ||
| 946 | |||
| 947 | ufx_handle_damage(dev, rect->dx, rect->dy, rect->width, | ||
| 948 | rect->height); | ||
| 949 | } | ||
| 950 | |||
| 951 | /* NOTE: fb_defio.c is holding info->fbdefio.mutex | ||
| 952 | * Touching ANY framebuffer memory that triggers a page fault | ||
| 953 | * in fb_defio will cause a deadlock, when it also tries to | ||
| 954 | * grab the same mutex. */ | ||
| 955 | static void ufx_dpy_deferred_io(struct fb_info *info, | ||
| 956 | struct list_head *pagelist) | ||
| 957 | { | ||
| 958 | struct page *cur; | ||
| 959 | struct fb_deferred_io *fbdefio = info->fbdefio; | ||
| 960 | struct ufx_data *dev = info->par; | ||
| 961 | |||
| 962 | if (!fb_defio) | ||
| 963 | return; | ||
| 964 | |||
| 965 | if (!atomic_read(&dev->usb_active)) | ||
| 966 | return; | ||
| 967 | |||
| 968 | /* walk the written page list and render each to device */ | ||
| 969 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { | ||
| 970 | /* create a rectangle of full screen width that encloses the | ||
| 971 | * entire dirty framebuffer page */ | ||
| 972 | const int x = 0; | ||
| 973 | const int width = dev->info->var.xres; | ||
| 974 | const int y = (cur->index << PAGE_SHIFT) / (width * 2); | ||
| 975 | int height = (PAGE_SIZE / (width * 2)) + 1; | ||
| 976 | height = min(height, (int)(dev->info->var.yres - y)); | ||
| 977 | |||
| 978 | BUG_ON(y >= dev->info->var.yres); | ||
| 979 | BUG_ON((y + height) > dev->info->var.yres); | ||
| 980 | |||
| 981 | ufx_handle_damage(dev, x, y, width, height); | ||
| 982 | } | ||
| 983 | } | ||
| 984 | |||
| 985 | static int ufx_ops_ioctl(struct fb_info *info, unsigned int cmd, | ||
| 986 | unsigned long arg) | ||
| 987 | { | ||
| 988 | struct ufx_data *dev = info->par; | ||
| 989 | struct dloarea *area = NULL; | ||
| 990 | |||
| 991 | if (!atomic_read(&dev->usb_active)) | ||
| 992 | return 0; | ||
| 993 | |||
| 994 | /* TODO: Update X server to get this from sysfs instead */ | ||
| 995 | if (cmd == UFX_IOCTL_RETURN_EDID) { | ||
| 996 | u8 __user *edid = (u8 __user *)arg; | ||
| 997 | if (copy_to_user(edid, dev->edid, dev->edid_size)) | ||
| 998 | return -EFAULT; | ||
| 999 | return 0; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ | ||
| 1003 | if (cmd == UFX_IOCTL_REPORT_DAMAGE) { | ||
| 1004 | /* If we have a damage-aware client, turn fb_defio "off" | ||
| 1005 | * To avoid perf imact of unecessary page fault handling. | ||
| 1006 | * Done by resetting the delay for this fb_info to a very | ||
| 1007 | * long period. Pages will become writable and stay that way. | ||
| 1008 | * Reset to normal value when all clients have closed this fb. | ||
| 1009 | */ | ||
| 1010 | if (info->fbdefio) | ||
| 1011 | info->fbdefio->delay = UFX_DEFIO_WRITE_DISABLE; | ||
| 1012 | |||
| 1013 | area = (struct dloarea *)arg; | ||
| 1014 | |||
| 1015 | if (area->x < 0) | ||
| 1016 | area->x = 0; | ||
| 1017 | |||
| 1018 | if (area->x > info->var.xres) | ||
| 1019 | area->x = info->var.xres; | ||
| 1020 | |||
| 1021 | if (area->y < 0) | ||
| 1022 | area->y = 0; | ||
| 1023 | |||
| 1024 | if (area->y > info->var.yres) | ||
| 1025 | area->y = info->var.yres; | ||
| 1026 | |||
| 1027 | ufx_handle_damage(dev, area->x, area->y, area->w, area->h); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | return 0; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | /* taken from vesafb */ | ||
| 1034 | static int | ||
| 1035 | ufx_ops_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
| 1036 | unsigned blue, unsigned transp, struct fb_info *info) | ||
| 1037 | { | ||
| 1038 | int err = 0; | ||
| 1039 | |||
| 1040 | if (regno >= info->cmap.len) | ||
| 1041 | return 1; | ||
| 1042 | |||
| 1043 | if (regno < 16) { | ||
| 1044 | if (info->var.red.offset == 10) { | ||
| 1045 | /* 1:5:5:5 */ | ||
| 1046 | ((u32 *) (info->pseudo_palette))[regno] = | ||
| 1047 | ((red & 0xf800) >> 1) | | ||
| 1048 | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); | ||
| 1049 | } else { | ||
| 1050 | /* 0:5:6:5 */ | ||
| 1051 | ((u32 *) (info->pseudo_palette))[regno] = | ||
| 1052 | ((red & 0xf800)) | | ||
| 1053 | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); | ||
| 1054 | } | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | return err; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | /* It's common for several clients to have framebuffer open simultaneously. | ||
| 1061 | * e.g. both fbcon and X. Makes things interesting. | ||
| 1062 | * Assumes caller is holding info->lock (for open and release at least) */ | ||
| 1063 | static int ufx_ops_open(struct fb_info *info, int user) | ||
| 1064 | { | ||
| 1065 | struct ufx_data *dev = info->par; | ||
| 1066 | |||
| 1067 | /* fbcon aggressively connects to first framebuffer it finds, | ||
| 1068 | * preventing other clients (X) from working properly. Usually | ||
| 1069 | * not what the user wants. Fail by default with option to enable. */ | ||
| 1070 | if (user == 0 && !console) | ||
| 1071 | return -EBUSY; | ||
| 1072 | |||
| 1073 | /* If the USB device is gone, we don't accept new opens */ | ||
| 1074 | if (dev->virtualized) | ||
| 1075 | return -ENODEV; | ||
| 1076 | |||
| 1077 | dev->fb_count++; | ||
| 1078 | |||
| 1079 | kref_get(&dev->kref); | ||
| 1080 | |||
| 1081 | if (fb_defio && (info->fbdefio == NULL)) { | ||
| 1082 | /* enable defio at last moment if not disabled by client */ | ||
| 1083 | |||
| 1084 | struct fb_deferred_io *fbdefio; | ||
| 1085 | |||
| 1086 | fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); | ||
| 1087 | |||
| 1088 | if (fbdefio) { | ||
| 1089 | fbdefio->delay = UFX_DEFIO_WRITE_DELAY; | ||
| 1090 | fbdefio->deferred_io = ufx_dpy_deferred_io; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | info->fbdefio = fbdefio; | ||
| 1094 | fb_deferred_io_init(info); | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | pr_debug("open /dev/fb%d user=%d fb_info=%p count=%d", | ||
| 1098 | info->node, user, info, dev->fb_count); | ||
| 1099 | |||
| 1100 | return 0; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | /* | ||
| 1104 | * Called when all client interfaces to start transactions have been disabled, | ||
| 1105 | * and all references to our device instance (ufx_data) are released. | ||
| 1106 | * Every transaction must have a reference, so we know are fully spun down | ||
| 1107 | */ | ||
| 1108 | static void ufx_free(struct kref *kref) | ||
| 1109 | { | ||
| 1110 | struct ufx_data *dev = container_of(kref, struct ufx_data, kref); | ||
| 1111 | |||
| 1112 | /* this function will wait for all in-flight urbs to complete */ | ||
| 1113 | if (dev->urbs.count > 0) | ||
| 1114 | ufx_free_urb_list(dev); | ||
| 1115 | |||
| 1116 | pr_debug("freeing ufx_data %p", dev); | ||
| 1117 | |||
| 1118 | kfree(dev); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | static void ufx_release_urb_work(struct work_struct *work) | ||
| 1122 | { | ||
| 1123 | struct urb_node *unode = container_of(work, struct urb_node, | ||
| 1124 | release_urb_work.work); | ||
| 1125 | |||
| 1126 | up(&unode->dev->urbs.limit_sem); | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | static void ufx_free_framebuffer_work(struct work_struct *work) | ||
| 1130 | { | ||
| 1131 | struct ufx_data *dev = container_of(work, struct ufx_data, | ||
| 1132 | free_framebuffer_work.work); | ||
| 1133 | struct fb_info *info = dev->info; | ||
| 1134 | int node = info->node; | ||
| 1135 | |||
| 1136 | unregister_framebuffer(info); | ||
| 1137 | |||
| 1138 | if (info->cmap.len != 0) | ||
| 1139 | fb_dealloc_cmap(&info->cmap); | ||
| 1140 | if (info->monspecs.modedb) | ||
| 1141 | fb_destroy_modedb(info->monspecs.modedb); | ||
| 1142 | if (info->screen_base) | ||
| 1143 | vfree(info->screen_base); | ||
| 1144 | |||
| 1145 | fb_destroy_modelist(&info->modelist); | ||
| 1146 | |||
| 1147 | dev->info = 0; | ||
| 1148 | |||
| 1149 | /* Assume info structure is freed after this point */ | ||
| 1150 | framebuffer_release(info); | ||
| 1151 | |||
| 1152 | pr_debug("fb_info for /dev/fb%d has been freed", node); | ||
| 1153 | |||
| 1154 | /* ref taken in probe() as part of registering framebfufer */ | ||
| 1155 | kref_put(&dev->kref, ufx_free); | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | /* | ||
| 1159 | * Assumes caller is holding info->lock mutex (for open and release at least) | ||
| 1160 | */ | ||
| 1161 | static int ufx_ops_release(struct fb_info *info, int user) | ||
| 1162 | { | ||
| 1163 | struct ufx_data *dev = info->par; | ||
| 1164 | |||
| 1165 | dev->fb_count--; | ||
| 1166 | |||
| 1167 | /* We can't free fb_info here - fbmem will touch it when we return */ | ||
| 1168 | if (dev->virtualized && (dev->fb_count == 0)) | ||
| 1169 | schedule_delayed_work(&dev->free_framebuffer_work, HZ); | ||
| 1170 | |||
| 1171 | if ((dev->fb_count == 0) && (info->fbdefio)) { | ||
| 1172 | fb_deferred_io_cleanup(info); | ||
| 1173 | kfree(info->fbdefio); | ||
| 1174 | info->fbdefio = NULL; | ||
| 1175 | info->fbops->fb_mmap = ufx_ops_mmap; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | pr_debug("released /dev/fb%d user=%d count=%d", | ||
| 1179 | info->node, user, dev->fb_count); | ||
| 1180 | |||
| 1181 | kref_put(&dev->kref, ufx_free); | ||
| 1182 | |||
| 1183 | return 0; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | /* Check whether a video mode is supported by the chip | ||
| 1187 | * We start from monitor's modes, so don't need to filter that here */ | ||
| 1188 | static int ufx_is_valid_mode(struct fb_videomode *mode, | ||
| 1189 | struct fb_info *info) | ||
| 1190 | { | ||
| 1191 | if ((mode->xres * mode->yres) > (2048 * 1152)) { | ||
| 1192 | pr_debug("%dx%d too many pixels", | ||
| 1193 | mode->xres, mode->yres); | ||
| 1194 | return 0; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | if (mode->pixclock < 5000) { | ||
| 1198 | pr_debug("%dx%d %dps pixel clock too fast", | ||
| 1199 | mode->xres, mode->yres, mode->pixclock); | ||
| 1200 | return 0; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | pr_debug("%dx%d (pixclk %dps %dMHz) valid mode", mode->xres, mode->yres, | ||
| 1204 | mode->pixclock, (1000000 / mode->pixclock)); | ||
| 1205 | return 1; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | static void ufx_var_color_format(struct fb_var_screeninfo *var) | ||
| 1209 | { | ||
| 1210 | const struct fb_bitfield red = { 11, 5, 0 }; | ||
| 1211 | const struct fb_bitfield green = { 5, 6, 0 }; | ||
| 1212 | const struct fb_bitfield blue = { 0, 5, 0 }; | ||
| 1213 | |||
| 1214 | var->bits_per_pixel = 16; | ||
| 1215 | var->red = red; | ||
| 1216 | var->green = green; | ||
| 1217 | var->blue = blue; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | static int ufx_ops_check_var(struct fb_var_screeninfo *var, | ||
| 1221 | struct fb_info *info) | ||
| 1222 | { | ||
| 1223 | struct fb_videomode mode; | ||
| 1224 | |||
| 1225 | /* TODO: support dynamically changing framebuffer size */ | ||
| 1226 | if ((var->xres * var->yres * 2) > info->fix.smem_len) | ||
| 1227 | return -EINVAL; | ||
| 1228 | |||
| 1229 | /* set device-specific elements of var unrelated to mode */ | ||
| 1230 | ufx_var_color_format(var); | ||
| 1231 | |||
| 1232 | fb_var_to_videomode(&mode, var); | ||
| 1233 | |||
| 1234 | if (!ufx_is_valid_mode(&mode, info)) | ||
| 1235 | return -EINVAL; | ||
| 1236 | |||
| 1237 | return 0; | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | static int ufx_ops_set_par(struct fb_info *info) | ||
| 1241 | { | ||
| 1242 | struct ufx_data *dev = info->par; | ||
| 1243 | int result; | ||
| 1244 | u16 *pix_framebuffer; | ||
| 1245 | int i; | ||
| 1246 | |||
| 1247 | pr_debug("set_par mode %dx%d", info->var.xres, info->var.yres); | ||
| 1248 | result = ufx_set_vid_mode(dev, &info->var); | ||
| 1249 | |||
| 1250 | if ((result == 0) && (dev->fb_count == 0)) { | ||
| 1251 | /* paint greenscreen */ | ||
| 1252 | pix_framebuffer = (u16 *) info->screen_base; | ||
| 1253 | for (i = 0; i < info->fix.smem_len / 2; i++) | ||
| 1254 | pix_framebuffer[i] = 0x37e6; | ||
| 1255 | |||
| 1256 | ufx_handle_damage(dev, 0, 0, info->var.xres, info->var.yres); | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | /* re-enable defio if previously disabled by damage tracking */ | ||
| 1260 | if (info->fbdefio) | ||
| 1261 | info->fbdefio->delay = UFX_DEFIO_WRITE_DELAY; | ||
| 1262 | |||
| 1263 | return result; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | /* In order to come back from full DPMS off, we need to set the mode again */ | ||
| 1267 | static int ufx_ops_blank(int blank_mode, struct fb_info *info) | ||
| 1268 | { | ||
| 1269 | struct ufx_data *dev = info->par; | ||
| 1270 | ufx_set_vid_mode(dev, &info->var); | ||
| 1271 | return 0; | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | static struct fb_ops ufx_ops = { | ||
| 1275 | .owner = THIS_MODULE, | ||
| 1276 | .fb_read = fb_sys_read, | ||
| 1277 | .fb_write = ufx_ops_write, | ||
| 1278 | .fb_setcolreg = ufx_ops_setcolreg, | ||
| 1279 | .fb_fillrect = ufx_ops_fillrect, | ||
| 1280 | .fb_copyarea = ufx_ops_copyarea, | ||
| 1281 | .fb_imageblit = ufx_ops_imageblit, | ||
| 1282 | .fb_mmap = ufx_ops_mmap, | ||
| 1283 | .fb_ioctl = ufx_ops_ioctl, | ||
| 1284 | .fb_open = ufx_ops_open, | ||
| 1285 | .fb_release = ufx_ops_release, | ||
| 1286 | .fb_blank = ufx_ops_blank, | ||
| 1287 | .fb_check_var = ufx_ops_check_var, | ||
| 1288 | .fb_set_par = ufx_ops_set_par, | ||
| 1289 | }; | ||
| 1290 | |||
| 1291 | /* Assumes &info->lock held by caller | ||
| 1292 | * Assumes no active clients have framebuffer open */ | ||
| 1293 | static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info) | ||
| 1294 | { | ||
| 1295 | int retval = -ENOMEM; | ||
| 1296 | int old_len = info->fix.smem_len; | ||
| 1297 | int new_len; | ||
| 1298 | unsigned char *old_fb = info->screen_base; | ||
| 1299 | unsigned char *new_fb; | ||
| 1300 | |||
| 1301 | pr_debug("Reallocating framebuffer. Addresses will change!"); | ||
| 1302 | |||
| 1303 | new_len = info->fix.line_length * info->var.yres; | ||
| 1304 | |||
| 1305 | if (PAGE_ALIGN(new_len) > old_len) { | ||
| 1306 | /* | ||
| 1307 | * Alloc system memory for virtual framebuffer | ||
| 1308 | */ | ||
| 1309 | new_fb = vmalloc(new_len); | ||
| 1310 | if (!new_fb) { | ||
| 1311 | pr_err("Virtual framebuffer alloc failed"); | ||
| 1312 | goto error; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | if (info->screen_base) { | ||
| 1316 | memcpy(new_fb, old_fb, old_len); | ||
| 1317 | vfree(info->screen_base); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | info->screen_base = new_fb; | ||
| 1321 | info->fix.smem_len = PAGE_ALIGN(new_len); | ||
| 1322 | info->fix.smem_start = (unsigned long) new_fb; | ||
| 1323 | info->flags = smscufx_info_flags; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | retval = 0; | ||
| 1327 | |||
| 1328 | error: | ||
| 1329 | return retval; | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | /* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master, | ||
| 1333 | * restart enabled, but no start byte, enable controller */ | ||
| 1334 | static int ufx_i2c_init(struct ufx_data *dev) | ||
| 1335 | { | ||
| 1336 | u32 tmp; | ||
| 1337 | |||
| 1338 | /* disable the controller before it can be reprogrammed */ | ||
| 1339 | int status = ufx_reg_write(dev, 0x106C, 0x00); | ||
| 1340 | check_warn_return(status, "failed to disable I2C"); | ||
| 1341 | |||
| 1342 | /* Setup the clock count registers | ||
| 1343 | * (12+1) = 13 clks @ 2.5 MHz = 5.2 uS */ | ||
| 1344 | status = ufx_reg_write(dev, 0x1018, 12); | ||
| 1345 | check_warn_return(status, "error writing 0x1018"); | ||
| 1346 | |||
| 1347 | /* (6+8) = 14 clks @ 2.5 MHz = 5.6 uS */ | ||
| 1348 | status = ufx_reg_write(dev, 0x1014, 6); | ||
| 1349 | check_warn_return(status, "error writing 0x1014"); | ||
| 1350 | |||
| 1351 | status = ufx_reg_read(dev, 0x1000, &tmp); | ||
| 1352 | check_warn_return(status, "error reading 0x1000"); | ||
| 1353 | |||
| 1354 | /* set speed to std mode */ | ||
| 1355 | tmp &= ~(0x06); | ||
| 1356 | tmp |= 0x02; | ||
| 1357 | |||
| 1358 | /* 7-bit (not 10-bit) addressing */ | ||
| 1359 | tmp &= ~(0x10); | ||
| 1360 | |||
| 1361 | /* enable restart conditions and master mode */ | ||
| 1362 | tmp |= 0x21; | ||
| 1363 | |||
| 1364 | status = ufx_reg_write(dev, 0x1000, tmp); | ||
| 1365 | check_warn_return(status, "error writing 0x1000"); | ||
| 1366 | |||
| 1367 | /* Set normal tx using target address 0 */ | ||
| 1368 | status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0xC00, 0x000); | ||
| 1369 | check_warn_return(status, "error setting TX mode bits in 0x1004"); | ||
| 1370 | |||
| 1371 | /* Enable the controller */ | ||
| 1372 | status = ufx_reg_write(dev, 0x106C, 0x01); | ||
| 1373 | check_warn_return(status, "failed to enable I2C"); | ||
| 1374 | |||
| 1375 | return 0; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /* sets the I2C port mux and target address */ | ||
| 1379 | static int ufx_i2c_configure(struct ufx_data *dev) | ||
| 1380 | { | ||
| 1381 | int status = ufx_reg_write(dev, 0x106C, 0x00); | ||
| 1382 | check_warn_return(status, "failed to disable I2C"); | ||
| 1383 | |||
| 1384 | status = ufx_reg_write(dev, 0x3010, 0x00000000); | ||
| 1385 | check_warn_return(status, "failed to write 0x3010"); | ||
| 1386 | |||
| 1387 | /* A0h is std for any EDID, right shifted by one */ | ||
| 1388 | status = ufx_reg_clear_and_set_bits(dev, 0x1004, 0x3FF, (0xA0 >> 1)); | ||
| 1389 | check_warn_return(status, "failed to set TAR bits in 0x1004"); | ||
| 1390 | |||
| 1391 | status = ufx_reg_write(dev, 0x106C, 0x01); | ||
| 1392 | check_warn_return(status, "failed to enable I2C"); | ||
| 1393 | |||
| 1394 | return 0; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | /* wait for BUSY to clear, with a timeout of 50ms with 10ms sleeps. if no | ||
| 1398 | * monitor is connected, there is no error except for timeout */ | ||
| 1399 | static int ufx_i2c_wait_busy(struct ufx_data *dev) | ||
| 1400 | { | ||
| 1401 | u32 tmp; | ||
| 1402 | int i, status; | ||
| 1403 | |||
| 1404 | for (i = 0; i < 15; i++) { | ||
| 1405 | status = ufx_reg_read(dev, 0x1100, &tmp); | ||
| 1406 | check_warn_return(status, "0x1100 read failed"); | ||
| 1407 | |||
| 1408 | /* if BUSY is clear, check for error */ | ||
| 1409 | if ((tmp & 0x80000000) == 0) { | ||
| 1410 | if (tmp & 0x20000000) { | ||
| 1411 | pr_warn("I2C read failed, 0x1100=0x%08x", tmp); | ||
| 1412 | return -EIO; | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | return 0; | ||
| 1416 | } | ||
| 1417 | |||
| 1418 | /* perform the first 10 retries without delay */ | ||
| 1419 | if (i >= 10) | ||
| 1420 | msleep(10); | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | pr_warn("I2C access timed out, resetting I2C hardware"); | ||
| 1424 | status = ufx_reg_write(dev, 0x1100, 0x40000000); | ||
| 1425 | check_warn_return(status, "0x1100 write failed"); | ||
| 1426 | |||
| 1427 | return -ETIMEDOUT; | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | /* reads a 128-byte EDID block from the currently selected port and TAR */ | ||
| 1431 | static int ufx_read_edid(struct ufx_data *dev, u8 *edid, int edid_len) | ||
| 1432 | { | ||
| 1433 | int i, j, status; | ||
| 1434 | u32 *edid_u32 = (u32 *)edid; | ||
| 1435 | |||
| 1436 | BUG_ON(edid_len != EDID_LENGTH); | ||
| 1437 | |||
| 1438 | status = ufx_i2c_configure(dev); | ||
| 1439 | if (status < 0) { | ||
| 1440 | pr_err("ufx_i2c_configure failed"); | ||
| 1441 | return status; | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | memset(edid, 0xff, EDID_LENGTH); | ||
| 1445 | |||
| 1446 | /* Read the 128-byte EDID as 2 bursts of 64 bytes */ | ||
| 1447 | for (i = 0; i < 2; i++) { | ||
| 1448 | u32 temp = 0x28070000 | (63 << 20) | (((u32)(i * 64)) << 8); | ||
| 1449 | status = ufx_reg_write(dev, 0x1100, temp); | ||
| 1450 | check_warn_return(status, "Failed to write 0x1100"); | ||
| 1451 | |||
| 1452 | temp |= 0x80000000; | ||
| 1453 | status = ufx_reg_write(dev, 0x1100, temp); | ||
| 1454 | check_warn_return(status, "Failed to write 0x1100"); | ||
| 1455 | |||
| 1456 | status = ufx_i2c_wait_busy(dev); | ||
| 1457 | check_warn_return(status, "Timeout waiting for I2C BUSY to clear"); | ||
| 1458 | |||
| 1459 | for (j = 0; j < 16; j++) { | ||
| 1460 | u32 data_reg_addr = 0x1110 + (j * 4); | ||
| 1461 | status = ufx_reg_read(dev, data_reg_addr, edid_u32++); | ||
| 1462 | check_warn_return(status, "Error reading i2c data"); | ||
| 1463 | } | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | /* all FF's in the first 16 bytes indicates nothing is connected */ | ||
| 1467 | for (i = 0; i < 16; i++) { | ||
| 1468 | if (edid[i] != 0xFF) { | ||
| 1469 | pr_debug("edid data read succesfully"); | ||
| 1470 | return EDID_LENGTH; | ||
| 1471 | } | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | pr_warn("edid data contains all 0xff"); | ||
| 1475 | return -ETIMEDOUT; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | /* 1) use sw default | ||
| 1479 | * 2) Parse into various fb_info structs | ||
| 1480 | * 3) Allocate virtual framebuffer memory to back highest res mode | ||
| 1481 | * | ||
| 1482 | * Parses EDID into three places used by various parts of fbdev: | ||
| 1483 | * fb_var_screeninfo contains the timing of the monitor's preferred mode | ||
| 1484 | * fb_info.monspecs is full parsed EDID info, including monspecs.modedb | ||
| 1485 | * fb_info.modelist is a linked list of all monitor & VESA modes which work | ||
| 1486 | * | ||
| 1487 | * If EDID is not readable/valid, then modelist is all VESA modes, | ||
| 1488 | * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode | ||
| 1489 | * Returns 0 if successful */ | ||
| 1490 | static int ufx_setup_modes(struct ufx_data *dev, struct fb_info *info, | ||
| 1491 | char *default_edid, size_t default_edid_size) | ||
| 1492 | { | ||
| 1493 | const struct fb_videomode *default_vmode = NULL; | ||
| 1494 | u8 *edid; | ||
| 1495 | int i, result = 0, tries = 3; | ||
| 1496 | |||
| 1497 | if (info->dev) /* only use mutex if info has been registered */ | ||
| 1498 | mutex_lock(&info->lock); | ||
| 1499 | |||
| 1500 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
| 1501 | if (!edid) { | ||
| 1502 | result = -ENOMEM; | ||
| 1503 | goto error; | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | fb_destroy_modelist(&info->modelist); | ||
| 1507 | memset(&info->monspecs, 0, sizeof(info->monspecs)); | ||
| 1508 | |||
| 1509 | /* Try to (re)read EDID from hardware first | ||
| 1510 | * EDID data may return, but not parse as valid | ||
| 1511 | * Try again a few times, in case of e.g. analog cable noise */ | ||
| 1512 | while (tries--) { | ||
| 1513 | i = ufx_read_edid(dev, edid, EDID_LENGTH); | ||
| 1514 | |||
| 1515 | if (i >= EDID_LENGTH) | ||
| 1516 | fb_edid_to_monspecs(edid, &info->monspecs); | ||
| 1517 | |||
| 1518 | if (info->monspecs.modedb_len > 0) { | ||
| 1519 | dev->edid = edid; | ||
| 1520 | dev->edid_size = i; | ||
| 1521 | break; | ||
| 1522 | } | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | /* If that fails, use a previously returned EDID if available */ | ||
| 1526 | if (info->monspecs.modedb_len == 0) { | ||
| 1527 | pr_err("Unable to get valid EDID from device/display\n"); | ||
| 1528 | |||
| 1529 | if (dev->edid) { | ||
| 1530 | fb_edid_to_monspecs(dev->edid, &info->monspecs); | ||
| 1531 | if (info->monspecs.modedb_len > 0) | ||
| 1532 | pr_err("Using previously queried EDID\n"); | ||
| 1533 | } | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | /* If that fails, use the default EDID we were handed */ | ||
| 1537 | if (info->monspecs.modedb_len == 0) { | ||
| 1538 | if (default_edid_size >= EDID_LENGTH) { | ||
| 1539 | fb_edid_to_monspecs(default_edid, &info->monspecs); | ||
| 1540 | if (info->monspecs.modedb_len > 0) { | ||
| 1541 | memcpy(edid, default_edid, default_edid_size); | ||
| 1542 | dev->edid = edid; | ||
| 1543 | dev->edid_size = default_edid_size; | ||
| 1544 | pr_err("Using default/backup EDID\n"); | ||
| 1545 | } | ||
| 1546 | } | ||
| 1547 | } | ||
| 1548 | |||
| 1549 | /* If we've got modes, let's pick a best default mode */ | ||
| 1550 | if (info->monspecs.modedb_len > 0) { | ||
| 1551 | |||
| 1552 | for (i = 0; i < info->monspecs.modedb_len; i++) { | ||
| 1553 | if (ufx_is_valid_mode(&info->monspecs.modedb[i], info)) | ||
| 1554 | fb_add_videomode(&info->monspecs.modedb[i], | ||
| 1555 | &info->modelist); | ||
| 1556 | else /* if we've removed top/best mode */ | ||
| 1557 | info->monspecs.misc &= ~FB_MISC_1ST_DETAIL; | ||
| 1558 | } | ||
| 1559 | |||
| 1560 | default_vmode = fb_find_best_display(&info->monspecs, | ||
| 1561 | &info->modelist); | ||
| 1562 | } | ||
| 1563 | |||
| 1564 | /* If everything else has failed, fall back to safe default mode */ | ||
| 1565 | if (default_vmode == NULL) { | ||
| 1566 | |||
| 1567 | struct fb_videomode fb_vmode = {0}; | ||
| 1568 | |||
| 1569 | /* Add the standard VESA modes to our modelist | ||
| 1570 | * Since we don't have EDID, there may be modes that | ||
| 1571 | * overspec monitor and/or are incorrect aspect ratio, etc. | ||
| 1572 | * But at least the user has a chance to choose | ||
| 1573 | */ | ||
| 1574 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { | ||
| 1575 | if (ufx_is_valid_mode((struct fb_videomode *) | ||
| 1576 | &vesa_modes[i], info)) | ||
| 1577 | fb_add_videomode(&vesa_modes[i], | ||
| 1578 | &info->modelist); | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | /* default to resolution safe for projectors | ||
| 1582 | * (since they are most common case without EDID) | ||
| 1583 | */ | ||
| 1584 | fb_vmode.xres = 800; | ||
| 1585 | fb_vmode.yres = 600; | ||
| 1586 | fb_vmode.refresh = 60; | ||
| 1587 | default_vmode = fb_find_nearest_mode(&fb_vmode, | ||
| 1588 | &info->modelist); | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | /* If we have good mode and no active clients */ | ||
| 1592 | if ((default_vmode != NULL) && (dev->fb_count == 0)) { | ||
| 1593 | |||
| 1594 | fb_videomode_to_var(&info->var, default_vmode); | ||
| 1595 | ufx_var_color_format(&info->var); | ||
| 1596 | |||
| 1597 | /* with mode size info, we can now alloc our framebuffer */ | ||
| 1598 | memcpy(&info->fix, &ufx_fix, sizeof(ufx_fix)); | ||
| 1599 | info->fix.line_length = info->var.xres * | ||
| 1600 | (info->var.bits_per_pixel / 8); | ||
| 1601 | |||
| 1602 | result = ufx_realloc_framebuffer(dev, info); | ||
| 1603 | |||
| 1604 | } else | ||
| 1605 | result = -EINVAL; | ||
| 1606 | |||
| 1607 | error: | ||
| 1608 | if (edid && (dev->edid != edid)) | ||
| 1609 | kfree(edid); | ||
| 1610 | |||
| 1611 | if (info->dev) | ||
| 1612 | mutex_unlock(&info->lock); | ||
| 1613 | |||
| 1614 | return result; | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | static int ufx_usb_probe(struct usb_interface *interface, | ||
| 1618 | const struct usb_device_id *id) | ||
| 1619 | { | ||
| 1620 | struct usb_device *usbdev; | ||
| 1621 | struct ufx_data *dev; | ||
| 1622 | struct fb_info *info = 0; | ||
| 1623 | int retval = -ENOMEM; | ||
| 1624 | u32 id_rev, fpga_rev; | ||
| 1625 | |||
| 1626 | /* usb initialization */ | ||
| 1627 | usbdev = interface_to_usbdev(interface); | ||
| 1628 | BUG_ON(!usbdev); | ||
| 1629 | |||
| 1630 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 1631 | if (dev == NULL) { | ||
| 1632 | dev_err(&usbdev->dev, "ufx_usb_probe: failed alloc of dev struct\n"); | ||
| 1633 | goto error; | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | /* we need to wait for both usb and fbdev to spin down on disconnect */ | ||
| 1637 | kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ | ||
| 1638 | kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */ | ||
| 1639 | |||
| 1640 | dev->udev = usbdev; | ||
| 1641 | dev->gdev = &usbdev->dev; /* our generic struct device * */ | ||
| 1642 | usb_set_intfdata(interface, dev); | ||
| 1643 | |||
| 1644 | dev_dbg(dev->gdev, "%s %s - serial #%s\n", | ||
| 1645 | usbdev->manufacturer, usbdev->product, usbdev->serial); | ||
| 1646 | dev_dbg(dev->gdev, "vid_%04x&pid_%04x&rev_%04x driver's ufx_data struct at %p\n", | ||
| 1647 | usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, | ||
| 1648 | usbdev->descriptor.bcdDevice, dev); | ||
| 1649 | dev_dbg(dev->gdev, "console enable=%d\n", console); | ||
| 1650 | dev_dbg(dev->gdev, "fb_defio enable=%d\n", fb_defio); | ||
| 1651 | |||
| 1652 | if (!ufx_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { | ||
| 1653 | retval = -ENOMEM; | ||
| 1654 | dev_err(dev->gdev, "ufx_alloc_urb_list failed\n"); | ||
| 1655 | goto error; | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | /* We don't register a new USB class. Our client interface is fbdev */ | ||
| 1659 | |||
| 1660 | /* allocates framebuffer driver structure, not framebuffer memory */ | ||
| 1661 | info = framebuffer_alloc(0, &usbdev->dev); | ||
| 1662 | if (!info) { | ||
| 1663 | retval = -ENOMEM; | ||
| 1664 | dev_err(dev->gdev, "framebuffer_alloc failed\n"); | ||
| 1665 | goto error; | ||
| 1666 | } | ||
| 1667 | |||
| 1668 | dev->info = info; | ||
| 1669 | info->par = dev; | ||
| 1670 | info->pseudo_palette = dev->pseudo_palette; | ||
| 1671 | info->fbops = &ufx_ops; | ||
| 1672 | |||
| 1673 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | ||
| 1674 | if (retval < 0) { | ||
| 1675 | dev_err(dev->gdev, "fb_alloc_cmap failed %x\n", retval); | ||
| 1676 | goto error; | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | INIT_DELAYED_WORK(&dev->free_framebuffer_work, | ||
| 1680 | ufx_free_framebuffer_work); | ||
| 1681 | |||
| 1682 | INIT_LIST_HEAD(&info->modelist); | ||
| 1683 | |||
| 1684 | retval = ufx_reg_read(dev, 0x3000, &id_rev); | ||
| 1685 | check_warn_goto_error(retval, "error %d reading 0x3000 register from device", retval); | ||
| 1686 | dev_dbg(dev->gdev, "ID_REV register value 0x%08x", id_rev); | ||
| 1687 | |||
| 1688 | retval = ufx_reg_read(dev, 0x3004, &fpga_rev); | ||
| 1689 | check_warn_goto_error(retval, "error %d reading 0x3004 register from device", retval); | ||
| 1690 | dev_dbg(dev->gdev, "FPGA_REV register value 0x%08x", fpga_rev); | ||
| 1691 | |||
| 1692 | dev_dbg(dev->gdev, "resetting device"); | ||
| 1693 | retval = ufx_lite_reset(dev); | ||
| 1694 | check_warn_goto_error(retval, "error %d resetting device", retval); | ||
| 1695 | |||
| 1696 | dev_dbg(dev->gdev, "configuring system clock"); | ||
| 1697 | retval = ufx_config_sys_clk(dev); | ||
| 1698 | check_warn_goto_error(retval, "error %d configuring system clock", retval); | ||
| 1699 | |||
| 1700 | dev_dbg(dev->gdev, "configuring DDR2 controller"); | ||
| 1701 | retval = ufx_config_ddr2(dev); | ||
| 1702 | check_warn_goto_error(retval, "error %d initialising DDR2 controller", retval); | ||
| 1703 | |||
| 1704 | dev_dbg(dev->gdev, "configuring I2C controller"); | ||
| 1705 | retval = ufx_i2c_init(dev); | ||
| 1706 | check_warn_goto_error(retval, "error %d initialising I2C controller", retval); | ||
| 1707 | |||
| 1708 | dev_dbg(dev->gdev, "selecting display mode"); | ||
| 1709 | retval = ufx_setup_modes(dev, info, NULL, 0); | ||
| 1710 | check_warn_goto_error(retval, "unable to find common mode for display and adapter"); | ||
| 1711 | |||
| 1712 | retval = ufx_reg_set_bits(dev, 0x4000, 0x00000001); | ||
| 1713 | check_warn_goto_error(retval, "error %d enabling graphics engine", retval); | ||
| 1714 | |||
| 1715 | /* ready to begin using device */ | ||
| 1716 | atomic_set(&dev->usb_active, 1); | ||
| 1717 | |||
| 1718 | dev_dbg(dev->gdev, "checking var"); | ||
| 1719 | retval = ufx_ops_check_var(&info->var, info); | ||
| 1720 | check_warn_goto_error(retval, "error %d ufx_ops_check_var", retval); | ||
| 1721 | |||
| 1722 | dev_dbg(dev->gdev, "setting par"); | ||
| 1723 | retval = ufx_ops_set_par(info); | ||
| 1724 | check_warn_goto_error(retval, "error %d ufx_ops_set_par", retval); | ||
| 1725 | |||
| 1726 | dev_dbg(dev->gdev, "registering framebuffer"); | ||
| 1727 | retval = register_framebuffer(info); | ||
| 1728 | check_warn_goto_error(retval, "error %d register_framebuffer", retval); | ||
| 1729 | |||
| 1730 | dev_info(dev->gdev, "SMSC UDX USB device /dev/fb%d attached. %dx%d resolution." | ||
| 1731 | " Using %dK framebuffer memory\n", info->node, | ||
| 1732 | info->var.xres, info->var.yres, info->fix.smem_len >> 10); | ||
| 1733 | |||
| 1734 | return 0; | ||
| 1735 | |||
| 1736 | error: | ||
| 1737 | if (dev) { | ||
| 1738 | if (info) { | ||
| 1739 | if (info->cmap.len != 0) | ||
| 1740 | fb_dealloc_cmap(&info->cmap); | ||
| 1741 | if (info->monspecs.modedb) | ||
| 1742 | fb_destroy_modedb(info->monspecs.modedb); | ||
| 1743 | if (info->screen_base) | ||
| 1744 | vfree(info->screen_base); | ||
| 1745 | |||
| 1746 | fb_destroy_modelist(&info->modelist); | ||
| 1747 | |||
| 1748 | framebuffer_release(info); | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | kref_put(&dev->kref, ufx_free); /* ref for framebuffer */ | ||
| 1752 | kref_put(&dev->kref, ufx_free); /* last ref from kref_init */ | ||
| 1753 | |||
| 1754 | /* dev has been deallocated. Do not dereference */ | ||
| 1755 | } | ||
| 1756 | |||
| 1757 | return retval; | ||
| 1758 | } | ||
| 1759 | |||
| 1760 | static void ufx_usb_disconnect(struct usb_interface *interface) | ||
| 1761 | { | ||
| 1762 | struct ufx_data *dev; | ||
| 1763 | struct fb_info *info; | ||
| 1764 | |||
| 1765 | dev = usb_get_intfdata(interface); | ||
| 1766 | info = dev->info; | ||
| 1767 | |||
| 1768 | pr_debug("USB disconnect starting\n"); | ||
| 1769 | |||
| 1770 | /* we virtualize until all fb clients release. Then we free */ | ||
| 1771 | dev->virtualized = true; | ||
| 1772 | |||
| 1773 | /* When non-active we'll update virtual framebuffer, but no new urbs */ | ||
| 1774 | atomic_set(&dev->usb_active, 0); | ||
| 1775 | |||
| 1776 | usb_set_intfdata(interface, NULL); | ||
| 1777 | |||
| 1778 | /* if clients still have us open, will be freed on last close */ | ||
| 1779 | if (dev->fb_count == 0) | ||
| 1780 | schedule_delayed_work(&dev->free_framebuffer_work, 0); | ||
| 1781 | |||
| 1782 | /* release reference taken by kref_init in probe() */ | ||
| 1783 | kref_put(&dev->kref, ufx_free); | ||
| 1784 | |||
| 1785 | /* consider ufx_data freed */ | ||
| 1786 | } | ||
| 1787 | |||
| 1788 | static struct usb_driver ufx_driver = { | ||
| 1789 | .name = "smscufx", | ||
| 1790 | .probe = ufx_usb_probe, | ||
| 1791 | .disconnect = ufx_usb_disconnect, | ||
| 1792 | .id_table = id_table, | ||
| 1793 | }; | ||
| 1794 | |||
| 1795 | static int __init ufx_module_init(void) | ||
| 1796 | { | ||
| 1797 | int res; | ||
| 1798 | |||
| 1799 | res = usb_register(&ufx_driver); | ||
| 1800 | if (res) | ||
| 1801 | err("usb_register failed. Error number %d", res); | ||
| 1802 | |||
| 1803 | return res; | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | static void __exit ufx_module_exit(void) | ||
| 1807 | { | ||
| 1808 | usb_deregister(&ufx_driver); | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | module_init(ufx_module_init); | ||
| 1812 | module_exit(ufx_module_exit); | ||
| 1813 | |||
| 1814 | static void ufx_urb_completion(struct urb *urb) | ||
| 1815 | { | ||
| 1816 | struct urb_node *unode = urb->context; | ||
| 1817 | struct ufx_data *dev = unode->dev; | ||
| 1818 | unsigned long flags; | ||
| 1819 | |||
| 1820 | /* sync/async unlink faults aren't errors */ | ||
| 1821 | if (urb->status) { | ||
| 1822 | if (!(urb->status == -ENOENT || | ||
| 1823 | urb->status == -ECONNRESET || | ||
| 1824 | urb->status == -ESHUTDOWN)) { | ||
| 1825 | pr_err("%s - nonzero write bulk status received: %d\n", | ||
| 1826 | __func__, urb->status); | ||
| 1827 | atomic_set(&dev->lost_pixels, 1); | ||
| 1828 | } | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */ | ||
| 1832 | |||
| 1833 | spin_lock_irqsave(&dev->urbs.lock, flags); | ||
| 1834 | list_add_tail(&unode->entry, &dev->urbs.list); | ||
| 1835 | dev->urbs.available++; | ||
| 1836 | spin_unlock_irqrestore(&dev->urbs.lock, flags); | ||
| 1837 | |||
| 1838 | /* When using fb_defio, we deadlock if up() is called | ||
| 1839 | * while another is waiting. So queue to another process */ | ||
| 1840 | if (fb_defio) | ||
| 1841 | schedule_delayed_work(&unode->release_urb_work, 0); | ||
| 1842 | else | ||
| 1843 | up(&dev->urbs.limit_sem); | ||
| 1844 | } | ||
| 1845 | |||
| 1846 | static void ufx_free_urb_list(struct ufx_data *dev) | ||
| 1847 | { | ||
| 1848 | int count = dev->urbs.count; | ||
| 1849 | struct list_head *node; | ||
| 1850 | struct urb_node *unode; | ||
| 1851 | struct urb *urb; | ||
| 1852 | int ret; | ||
| 1853 | unsigned long flags; | ||
| 1854 | |||
| 1855 | pr_debug("Waiting for completes and freeing all render urbs\n"); | ||
| 1856 | |||
| 1857 | /* keep waiting and freeing, until we've got 'em all */ | ||
| 1858 | while (count--) { | ||
| 1859 | /* Getting interrupted means a leak, but ok at shutdown*/ | ||
| 1860 | ret = down_interruptible(&dev->urbs.limit_sem); | ||
| 1861 | if (ret) | ||
| 1862 | break; | ||
| 1863 | |||
| 1864 | spin_lock_irqsave(&dev->urbs.lock, flags); | ||
| 1865 | |||
| 1866 | node = dev->urbs.list.next; /* have reserved one with sem */ | ||
| 1867 | list_del_init(node); | ||
| 1868 | |||
| 1869 | spin_unlock_irqrestore(&dev->urbs.lock, flags); | ||
| 1870 | |||
| 1871 | unode = list_entry(node, struct urb_node, entry); | ||
| 1872 | urb = unode->urb; | ||
| 1873 | |||
| 1874 | /* Free each separately allocated piece */ | ||
| 1875 | usb_free_coherent(urb->dev, dev->urbs.size, | ||
| 1876 | urb->transfer_buffer, urb->transfer_dma); | ||
| 1877 | usb_free_urb(urb); | ||
| 1878 | kfree(node); | ||
| 1879 | } | ||
| 1880 | } | ||
| 1881 | |||
| 1882 | static int ufx_alloc_urb_list(struct ufx_data *dev, int count, size_t size) | ||
| 1883 | { | ||
| 1884 | int i = 0; | ||
| 1885 | struct urb *urb; | ||
| 1886 | struct urb_node *unode; | ||
| 1887 | char *buf; | ||
| 1888 | |||
| 1889 | spin_lock_init(&dev->urbs.lock); | ||
| 1890 | |||
| 1891 | dev->urbs.size = size; | ||
| 1892 | INIT_LIST_HEAD(&dev->urbs.list); | ||
| 1893 | |||
| 1894 | while (i < count) { | ||
| 1895 | unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); | ||
| 1896 | if (!unode) | ||
| 1897 | break; | ||
| 1898 | unode->dev = dev; | ||
| 1899 | |||
| 1900 | INIT_DELAYED_WORK(&unode->release_urb_work, | ||
| 1901 | ufx_release_urb_work); | ||
| 1902 | |||
| 1903 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 1904 | if (!urb) { | ||
| 1905 | kfree(unode); | ||
| 1906 | break; | ||
| 1907 | } | ||
| 1908 | unode->urb = urb; | ||
| 1909 | |||
| 1910 | buf = usb_alloc_coherent(dev->udev, size, GFP_KERNEL, | ||
| 1911 | &urb->transfer_dma); | ||
| 1912 | if (!buf) { | ||
| 1913 | kfree(unode); | ||
| 1914 | usb_free_urb(urb); | ||
| 1915 | break; | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | /* urb->transfer_buffer_length set to actual before submit */ | ||
| 1919 | usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1), | ||
| 1920 | buf, size, ufx_urb_completion, unode); | ||
| 1921 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
| 1922 | |||
| 1923 | list_add_tail(&unode->entry, &dev->urbs.list); | ||
| 1924 | |||
| 1925 | i++; | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | sema_init(&dev->urbs.limit_sem, i); | ||
| 1929 | dev->urbs.count = i; | ||
| 1930 | dev->urbs.available = i; | ||
| 1931 | |||
| 1932 | pr_debug("allocated %d %d byte urbs\n", i, (int) size); | ||
| 1933 | |||
| 1934 | return i; | ||
| 1935 | } | ||
| 1936 | |||
| 1937 | static struct urb *ufx_get_urb(struct ufx_data *dev) | ||
| 1938 | { | ||
| 1939 | int ret = 0; | ||
| 1940 | struct list_head *entry; | ||
| 1941 | struct urb_node *unode; | ||
| 1942 | struct urb *urb = NULL; | ||
| 1943 | unsigned long flags; | ||
| 1944 | |||
| 1945 | /* Wait for an in-flight buffer to complete and get re-queued */ | ||
| 1946 | ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT); | ||
| 1947 | if (ret) { | ||
| 1948 | atomic_set(&dev->lost_pixels, 1); | ||
| 1949 | pr_warn("wait for urb interrupted: %x available: %d\n", | ||
| 1950 | ret, dev->urbs.available); | ||
| 1951 | goto error; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | spin_lock_irqsave(&dev->urbs.lock, flags); | ||
| 1955 | |||
| 1956 | BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */ | ||
| 1957 | entry = dev->urbs.list.next; | ||
| 1958 | list_del_init(entry); | ||
| 1959 | dev->urbs.available--; | ||
| 1960 | |||
| 1961 | spin_unlock_irqrestore(&dev->urbs.lock, flags); | ||
| 1962 | |||
| 1963 | unode = list_entry(entry, struct urb_node, entry); | ||
| 1964 | urb = unode->urb; | ||
| 1965 | |||
| 1966 | error: | ||
| 1967 | return urb; | ||
| 1968 | } | ||
| 1969 | |||
| 1970 | static int ufx_submit_urb(struct ufx_data *dev, struct urb *urb, size_t len) | ||
| 1971 | { | ||
| 1972 | int ret; | ||
| 1973 | |||
| 1974 | BUG_ON(len > dev->urbs.size); | ||
| 1975 | |||
| 1976 | urb->transfer_buffer_length = len; /* set to actual payload len */ | ||
| 1977 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
| 1978 | if (ret) { | ||
| 1979 | ufx_urb_completion(urb); /* because no one else will */ | ||
| 1980 | atomic_set(&dev->lost_pixels, 1); | ||
| 1981 | pr_err("usb_submit_urb error %x\n", ret); | ||
| 1982 | } | ||
| 1983 | return ret; | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | ||
| 1987 | MODULE_PARM_DESC(console, "Allow fbcon to be used on this display"); | ||
| 1988 | |||
| 1989 | module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | ||
| 1990 | MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support"); | ||
| 1991 | |||
| 1992 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); | ||
| 1993 | MODULE_DESCRIPTION("SMSC UFX kernel framebuffer driver"); | ||
| 1994 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index cd1c4dcef8fd..8e4a446b5ed1 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c | |||
| @@ -744,7 +744,7 @@ static int __devinit tmiofb_probe(struct platform_device *dev) | |||
| 744 | goto err_ioremap_vram; | 744 | goto err_ioremap_vram; |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, | 747 | retval = request_irq(irq, &tmiofb_irq, 0, |
| 748 | dev_name(&dev->dev), info); | 748 | dev_name(&dev->dev), info); |
| 749 | 749 | ||
| 750 | if (retval) | 750 | if (retval) |
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index c6c77562839d..34cf019bba44 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
| @@ -987,8 +987,8 @@ static int tridentfb_pan_display(struct fb_var_screeninfo *var, | |||
| 987 | unsigned int offset; | 987 | unsigned int offset; |
| 988 | 988 | ||
| 989 | debug("enter\n"); | 989 | debug("enter\n"); |
| 990 | offset = (var->xoffset + (var->yoffset * var->xres_virtual)) | 990 | offset = (var->xoffset + (var->yoffset * info->var.xres_virtual)) |
| 991 | * var->bits_per_pixel / 32; | 991 | * info->var.bits_per_pixel / 32; |
| 992 | set_screen_start(par, offset); | 992 | set_screen_start(par, offset); |
| 993 | debug("exit\n"); | 993 | debug("exit\n"); |
| 994 | return 0; | 994 | return 0; |
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index 087fc9960bb9..3473e75ce785 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c | |||
| @@ -48,20 +48,30 @@ static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | |||
| 48 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; | 48 | FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR; |
| 49 | 49 | ||
| 50 | /* | 50 | /* |
| 51 | * There are many DisplayLink-based products, all with unique PIDs. We are able | 51 | * There are many DisplayLink-based graphics products, all with unique PIDs. |
| 52 | * to support all volume ones (circa 2009) with a single driver, so we match | 52 | * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) |
| 53 | * globally on VID. TODO: Probe() needs to detect when we might be running | 53 | * We also require a match on SubClass (0x00) and Protocol (0x00), |
| 54 | * "future" chips, and bail on those, so a compatible driver can match. | 54 | * which is compatible with all known USB 2.0 era graphics chips and firmware, |
| 55 | * but allows DisplayLink to increment those for any future incompatible chips | ||
| 55 | */ | 56 | */ |
| 56 | static struct usb_device_id id_table[] = { | 57 | static struct usb_device_id id_table[] = { |
| 57 | {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, | 58 | {.idVendor = 0x17e9, |
| 59 | .bInterfaceClass = 0xff, | ||
| 60 | .bInterfaceSubClass = 0x00, | ||
| 61 | .bInterfaceProtocol = 0x00, | ||
| 62 | .match_flags = USB_DEVICE_ID_MATCH_VENDOR | | ||
| 63 | USB_DEVICE_ID_MATCH_INT_CLASS | | ||
| 64 | USB_DEVICE_ID_MATCH_INT_SUBCLASS | | ||
| 65 | USB_DEVICE_ID_MATCH_INT_PROTOCOL, | ||
| 66 | }, | ||
| 58 | {}, | 67 | {}, |
| 59 | }; | 68 | }; |
| 60 | MODULE_DEVICE_TABLE(usb, id_table); | 69 | MODULE_DEVICE_TABLE(usb, id_table); |
| 61 | 70 | ||
| 62 | /* module options */ | 71 | /* module options */ |
| 63 | static int console; /* Optionally allow fbcon to consume first framebuffer */ | 72 | static int console = 1; /* Allow fbcon to open framebuffer */ |
| 64 | static int fb_defio; /* Optionally enable experimental fb_defio mmap support */ | 73 | static int fb_defio = 1; /* Detect mmap writes using page faults */ |
| 74 | static int shadow = 1; /* Optionally disable shadow framebuffer */ | ||
| 65 | 75 | ||
| 66 | /* dlfb keeps a list of urbs for efficient bulk transfers */ | 76 | /* dlfb keeps a list of urbs for efficient bulk transfers */ |
| 67 | static void dlfb_urb_completion(struct urb *urb); | 77 | static void dlfb_urb_completion(struct urb *urb); |
| @@ -94,17 +104,39 @@ static char *dlfb_vidreg_unlock(char *buf) | |||
| 94 | } | 104 | } |
| 95 | 105 | ||
| 96 | /* | 106 | /* |
| 97 | * On/Off for driving the DisplayLink framebuffer to the display | 107 | * Map FB_BLANK_* to DisplayLink register |
| 98 | * 0x00 H and V sync on | 108 | * DLReg FB_BLANK_* |
| 99 | * 0x01 H and V sync off (screen blank but powered) | 109 | * ----- ----------------------------- |
| 100 | * 0x07 DPMS powerdown (requires modeset to come back) | 110 | * 0x00 FB_BLANK_UNBLANK (0) |
| 111 | * 0x01 FB_BLANK (1) | ||
| 112 | * 0x03 FB_BLANK_VSYNC_SUSPEND (2) | ||
| 113 | * 0x05 FB_BLANK_HSYNC_SUSPEND (3) | ||
| 114 | * 0x07 FB_BLANK_POWERDOWN (4) Note: requires modeset to come back | ||
| 101 | */ | 115 | */ |
| 102 | static char *dlfb_enable_hvsync(char *buf, bool enable) | 116 | static char *dlfb_blanking(char *buf, int fb_blank) |
| 103 | { | 117 | { |
| 104 | if (enable) | 118 | u8 reg; |
| 105 | return dlfb_set_register(buf, 0x1F, 0x00); | 119 | |
| 106 | else | 120 | switch (fb_blank) { |
| 107 | return dlfb_set_register(buf, 0x1F, 0x07); | 121 | case FB_BLANK_POWERDOWN: |
| 122 | reg = 0x07; | ||
| 123 | break; | ||
| 124 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 125 | reg = 0x05; | ||
| 126 | break; | ||
| 127 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 128 | reg = 0x03; | ||
| 129 | break; | ||
| 130 | case FB_BLANK_NORMAL: | ||
| 131 | reg = 0x01; | ||
| 132 | break; | ||
| 133 | default: | ||
| 134 | reg = 0x00; | ||
| 135 | } | ||
| 136 | |||
| 137 | buf = dlfb_set_register(buf, 0x1F, reg); | ||
| 138 | |||
| 139 | return buf; | ||
| 108 | } | 140 | } |
| 109 | 141 | ||
| 110 | static char *dlfb_set_color_depth(char *buf, u8 selection) | 142 | static char *dlfb_set_color_depth(char *buf, u8 selection) |
| @@ -272,13 +304,15 @@ static int dlfb_set_video_mode(struct dlfb_data *dev, | |||
| 272 | wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len); | 304 | wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len); |
| 273 | 305 | ||
| 274 | wrptr = dlfb_set_vid_cmds(wrptr, var); | 306 | wrptr = dlfb_set_vid_cmds(wrptr, var); |
| 275 | wrptr = dlfb_enable_hvsync(wrptr, true); | 307 | wrptr = dlfb_blanking(wrptr, FB_BLANK_UNBLANK); |
| 276 | wrptr = dlfb_vidreg_unlock(wrptr); | 308 | wrptr = dlfb_vidreg_unlock(wrptr); |
| 277 | 309 | ||
| 278 | writesize = wrptr - buf; | 310 | writesize = wrptr - buf; |
| 279 | 311 | ||
| 280 | retval = dlfb_submit_urb(dev, urb, writesize); | 312 | retval = dlfb_submit_urb(dev, urb, writesize); |
| 281 | 313 | ||
| 314 | dev->blank_mode = FB_BLANK_UNBLANK; | ||
| 315 | |||
| 282 | return retval; | 316 | return retval; |
| 283 | } | 317 | } |
| 284 | 318 | ||
| @@ -752,14 +786,13 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 752 | { | 786 | { |
| 753 | 787 | ||
| 754 | struct dlfb_data *dev = info->par; | 788 | struct dlfb_data *dev = info->par; |
| 755 | struct dloarea *area = NULL; | ||
| 756 | 789 | ||
| 757 | if (!atomic_read(&dev->usb_active)) | 790 | if (!atomic_read(&dev->usb_active)) |
| 758 | return 0; | 791 | return 0; |
| 759 | 792 | ||
| 760 | /* TODO: Update X server to get this from sysfs instead */ | 793 | /* TODO: Update X server to get this from sysfs instead */ |
| 761 | if (cmd == DLFB_IOCTL_RETURN_EDID) { | 794 | if (cmd == DLFB_IOCTL_RETURN_EDID) { |
| 762 | char *edid = (char *)arg; | 795 | void __user *edid = (void __user *)arg; |
| 763 | if (copy_to_user(edid, dev->edid, dev->edid_size)) | 796 | if (copy_to_user(edid, dev->edid, dev->edid_size)) |
| 764 | return -EFAULT; | 797 | return -EFAULT; |
| 765 | return 0; | 798 | return 0; |
| @@ -767,6 +800,11 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 767 | 800 | ||
| 768 | /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ | 801 | /* TODO: Help propose a standard fb.h ioctl to report mmap damage */ |
| 769 | if (cmd == DLFB_IOCTL_REPORT_DAMAGE) { | 802 | if (cmd == DLFB_IOCTL_REPORT_DAMAGE) { |
| 803 | struct dloarea area; | ||
| 804 | |||
| 805 | if (copy_from_user(&area, (void __user *)arg, | ||
| 806 | sizeof(struct dloarea))) | ||
| 807 | return -EFAULT; | ||
| 770 | 808 | ||
| 771 | /* | 809 | /* |
| 772 | * If we have a damage-aware client, turn fb_defio "off" | 810 | * If we have a damage-aware client, turn fb_defio "off" |
| @@ -778,21 +816,19 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd, | |||
| 778 | if (info->fbdefio) | 816 | if (info->fbdefio) |
| 779 | info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE; | 817 | info->fbdefio->delay = DL_DEFIO_WRITE_DISABLE; |
| 780 | 818 | ||
| 781 | area = (struct dloarea *)arg; | 819 | if (area.x < 0) |
| 820 | area.x = 0; | ||
| 782 | 821 | ||
| 783 | if (area->x < 0) | 822 | if (area.x > info->var.xres) |
| 784 | area->x = 0; | 823 | area.x = info->var.xres; |
| 785 | 824 | ||
| 786 | if (area->x > info->var.xres) | 825 | if (area.y < 0) |
| 787 | area->x = info->var.xres; | 826 | area.y = 0; |
| 788 | 827 | ||
| 789 | if (area->y < 0) | 828 | if (area.y > info->var.yres) |
| 790 | area->y = 0; | 829 | area.y = info->var.yres; |
| 791 | 830 | ||
| 792 | if (area->y > info->var.yres) | 831 | dlfb_handle_damage(dev, area.x, area.y, area.w, area.h, |
| 793 | area->y = info->var.yres; | ||
| 794 | |||
| 795 | dlfb_handle_damage(dev, area->x, area->y, area->w, area->h, | ||
| 796 | info->screen_base); | 832 | info->screen_base); |
| 797 | } | 833 | } |
| 798 | 834 | ||
| @@ -840,7 +876,7 @@ static int dlfb_ops_open(struct fb_info *info, int user) | |||
| 840 | * preventing other clients (X) from working properly. Usually | 876 | * preventing other clients (X) from working properly. Usually |
| 841 | * not what the user wants. Fail by default with option to enable. | 877 | * not what the user wants. Fail by default with option to enable. |
| 842 | */ | 878 | */ |
| 843 | if ((user == 0) & (!console)) | 879 | if ((user == 0) && (!console)) |
| 844 | return -EBUSY; | 880 | return -EBUSY; |
| 845 | 881 | ||
| 846 | /* If the USB device is gone, we don't accept new opens */ | 882 | /* If the USB device is gone, we don't accept new opens */ |
| @@ -1039,32 +1075,57 @@ static int dlfb_ops_set_par(struct fb_info *info) | |||
| 1039 | return result; | 1075 | return result; |
| 1040 | } | 1076 | } |
| 1041 | 1077 | ||
| 1078 | /* To fonzi the jukebox (e.g. make blanking changes take effect) */ | ||
| 1079 | static char *dlfb_dummy_render(char *buf) | ||
| 1080 | { | ||
| 1081 | *buf++ = 0xAF; | ||
| 1082 | *buf++ = 0x6A; /* copy */ | ||
| 1083 | *buf++ = 0x00; /* from address*/ | ||
| 1084 | *buf++ = 0x00; | ||
| 1085 | *buf++ = 0x00; | ||
| 1086 | *buf++ = 0x01; /* one pixel */ | ||
| 1087 | *buf++ = 0x00; /* to address */ | ||
| 1088 | *buf++ = 0x00; | ||
| 1089 | *buf++ = 0x00; | ||
| 1090 | return buf; | ||
| 1091 | } | ||
| 1092 | |||
| 1042 | /* | 1093 | /* |
| 1043 | * In order to come back from full DPMS off, we need to set the mode again | 1094 | * In order to come back from full DPMS off, we need to set the mode again |
| 1044 | */ | 1095 | */ |
| 1045 | static int dlfb_ops_blank(int blank_mode, struct fb_info *info) | 1096 | static int dlfb_ops_blank(int blank_mode, struct fb_info *info) |
| 1046 | { | 1097 | { |
| 1047 | struct dlfb_data *dev = info->par; | 1098 | struct dlfb_data *dev = info->par; |
| 1099 | char *bufptr; | ||
| 1100 | struct urb *urb; | ||
| 1048 | 1101 | ||
| 1049 | if (blank_mode != FB_BLANK_UNBLANK) { | 1102 | pr_info("/dev/fb%d FB_BLANK mode %d --> %d\n", |
| 1050 | char *bufptr; | 1103 | info->node, dev->blank_mode, blank_mode); |
| 1051 | struct urb *urb; | ||
| 1052 | |||
| 1053 | urb = dlfb_get_urb(dev); | ||
| 1054 | if (!urb) | ||
| 1055 | return 0; | ||
| 1056 | 1104 | ||
| 1057 | bufptr = (char *) urb->transfer_buffer; | 1105 | if ((dev->blank_mode == FB_BLANK_POWERDOWN) && |
| 1058 | bufptr = dlfb_vidreg_lock(bufptr); | 1106 | (blank_mode != FB_BLANK_POWERDOWN)) { |
| 1059 | bufptr = dlfb_enable_hvsync(bufptr, false); | ||
| 1060 | bufptr = dlfb_vidreg_unlock(bufptr); | ||
| 1061 | 1107 | ||
| 1062 | dlfb_submit_urb(dev, urb, bufptr - | 1108 | /* returning from powerdown requires a fresh modeset */ |
| 1063 | (char *) urb->transfer_buffer); | ||
| 1064 | } else { | ||
| 1065 | dlfb_set_video_mode(dev, &info->var); | 1109 | dlfb_set_video_mode(dev, &info->var); |
| 1066 | } | 1110 | } |
| 1067 | 1111 | ||
| 1112 | urb = dlfb_get_urb(dev); | ||
| 1113 | if (!urb) | ||
| 1114 | return 0; | ||
| 1115 | |||
| 1116 | bufptr = (char *) urb->transfer_buffer; | ||
| 1117 | bufptr = dlfb_vidreg_lock(bufptr); | ||
| 1118 | bufptr = dlfb_blanking(bufptr, blank_mode); | ||
| 1119 | bufptr = dlfb_vidreg_unlock(bufptr); | ||
| 1120 | |||
| 1121 | /* seems like a render op is needed to have blank change take effect */ | ||
| 1122 | bufptr = dlfb_dummy_render(bufptr); | ||
| 1123 | |||
| 1124 | dlfb_submit_urb(dev, urb, bufptr - | ||
| 1125 | (char *) urb->transfer_buffer); | ||
| 1126 | |||
| 1127 | dev->blank_mode = blank_mode; | ||
| 1128 | |||
| 1068 | return 0; | 1129 | return 0; |
| 1069 | } | 1130 | } |
| 1070 | 1131 | ||
| @@ -1097,7 +1158,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info) | |||
| 1097 | int new_len; | 1158 | int new_len; |
| 1098 | unsigned char *old_fb = info->screen_base; | 1159 | unsigned char *old_fb = info->screen_base; |
| 1099 | unsigned char *new_fb; | 1160 | unsigned char *new_fb; |
| 1100 | unsigned char *new_back; | 1161 | unsigned char *new_back = 0; |
| 1101 | 1162 | ||
| 1102 | pr_warn("Reallocating framebuffer. Addresses will change!\n"); | 1163 | pr_warn("Reallocating framebuffer. Addresses will change!\n"); |
| 1103 | 1164 | ||
| @@ -1129,7 +1190,8 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dev, struct fb_info *info) | |||
| 1129 | * But with imperfect damage info we may send pixels over USB | 1190 | * But with imperfect damage info we may send pixels over USB |
| 1130 | * that were, in fact, unchanged - wasting limited USB bandwidth | 1191 | * that were, in fact, unchanged - wasting limited USB bandwidth |
| 1131 | */ | 1192 | */ |
| 1132 | new_back = vzalloc(new_len); | 1193 | if (shadow) |
| 1194 | new_back = vzalloc(new_len); | ||
| 1133 | if (!new_back) | 1195 | if (!new_back) |
| 1134 | pr_info("No shadow/backing buffer allocated\n"); | 1196 | pr_info("No shadow/backing buffer allocated\n"); |
| 1135 | else { | 1197 | else { |
| @@ -1430,21 +1492,30 @@ static int dlfb_select_std_channel(struct dlfb_data *dev) | |||
| 1430 | } | 1492 | } |
| 1431 | 1493 | ||
| 1432 | static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, | 1494 | static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, |
| 1433 | struct usb_device *usbdev) | 1495 | struct usb_interface *interface) |
| 1434 | { | 1496 | { |
| 1435 | char *desc; | 1497 | char *desc; |
| 1436 | char *buf; | 1498 | char *buf; |
| 1437 | char *desc_end; | 1499 | char *desc_end; |
| 1438 | 1500 | ||
| 1439 | u8 total_len = 0; | 1501 | int total_len = 0; |
| 1440 | 1502 | ||
| 1441 | buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); | 1503 | buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); |
| 1442 | if (!buf) | 1504 | if (!buf) |
| 1443 | return false; | 1505 | return false; |
| 1444 | desc = buf; | 1506 | desc = buf; |
| 1445 | 1507 | ||
| 1446 | total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ | 1508 | total_len = usb_get_descriptor(interface_to_usbdev(interface), |
| 1447 | 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); | 1509 | 0x5f, /* vendor specific */ |
| 1510 | 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); | ||
| 1511 | |||
| 1512 | /* if not found, look in configuration descriptor */ | ||
| 1513 | if (total_len < 0) { | ||
| 1514 | if (0 == usb_get_extra_descriptor(interface->cur_altsetting, | ||
| 1515 | 0x5f, &desc)) | ||
| 1516 | total_len = (int) desc[0]; | ||
| 1517 | } | ||
| 1518 | |||
| 1448 | if (total_len > 5) { | 1519 | if (total_len > 5) { |
| 1449 | pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ | 1520 | pr_info("vendor descriptor length:%x data:%02x %02x %02x %02x" \ |
| 1450 | "%02x %02x %02x %02x %02x %02x %02x\n", | 1521 | "%02x %02x %02x %02x %02x %02x %02x\n", |
| @@ -1485,6 +1556,8 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev, | |||
| 1485 | } | 1556 | } |
| 1486 | desc += length; | 1557 | desc += length; |
| 1487 | } | 1558 | } |
| 1559 | } else { | ||
| 1560 | pr_info("vendor descriptor not available (%d)\n", total_len); | ||
| 1488 | } | 1561 | } |
| 1489 | 1562 | ||
| 1490 | goto success; | 1563 | goto success; |
| @@ -1531,10 +1604,11 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
| 1531 | usbdev->descriptor.bcdDevice, dev); | 1604 | usbdev->descriptor.bcdDevice, dev); |
| 1532 | pr_info("console enable=%d\n", console); | 1605 | pr_info("console enable=%d\n", console); |
| 1533 | pr_info("fb_defio enable=%d\n", fb_defio); | 1606 | pr_info("fb_defio enable=%d\n", fb_defio); |
| 1607 | pr_info("shadow enable=%d\n", shadow); | ||
| 1534 | 1608 | ||
| 1535 | dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ | 1609 | dev->sku_pixel_limit = 2048 * 1152; /* default to maximum */ |
| 1536 | 1610 | ||
| 1537 | if (!dlfb_parse_vendor_descriptor(dev, usbdev)) { | 1611 | if (!dlfb_parse_vendor_descriptor(dev, interface)) { |
| 1538 | pr_err("firmware not recognized. Assume incompatible device\n"); | 1612 | pr_err("firmware not recognized. Assume incompatible device\n"); |
| 1539 | goto error; | 1613 | goto error; |
| 1540 | } | 1614 | } |
| @@ -1548,7 +1622,7 @@ static int dlfb_usb_probe(struct usb_interface *interface, | |||
| 1548 | /* We don't register a new USB class. Our client interface is fbdev */ | 1622 | /* We don't register a new USB class. Our client interface is fbdev */ |
| 1549 | 1623 | ||
| 1550 | /* allocates framebuffer driver structure, not framebuffer memory */ | 1624 | /* allocates framebuffer driver structure, not framebuffer memory */ |
| 1551 | info = framebuffer_alloc(0, &usbdev->dev); | 1625 | info = framebuffer_alloc(0, &interface->dev); |
| 1552 | if (!info) { | 1626 | if (!info) { |
| 1553 | retval = -ENOMEM; | 1627 | retval = -ENOMEM; |
| 1554 | pr_err("framebuffer_alloc failed\n"); | 1628 | pr_err("framebuffer_alloc failed\n"); |
| @@ -1883,10 +1957,13 @@ static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len) | |||
| 1883 | } | 1957 | } |
| 1884 | 1958 | ||
| 1885 | module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | 1959 | module_param(console, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); |
| 1886 | MODULE_PARM_DESC(console, "Allow fbcon to consume first framebuffer found"); | 1960 | MODULE_PARM_DESC(console, "Allow fbcon to open framebuffer"); |
| 1887 | 1961 | ||
| 1888 | module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | 1962 | module_param(fb_defio, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); |
| 1889 | MODULE_PARM_DESC(fb_defio, "Enable fb_defio mmap support. *Experimental*"); | 1963 | MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes"); |
| 1964 | |||
| 1965 | module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); | ||
| 1966 | MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); | ||
| 1890 | 1967 | ||
| 1891 | MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " | 1968 | MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " |
| 1892 | "Jaya Kumar <jayakumar.lkml@gmail.com>, " | 1969 | "Jaya Kumar <jayakumar.lkml@gmail.com>, " |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 6b52bf65f0b5..3f5a041601da 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
| @@ -555,7 +555,7 @@ static int __init valkyrie_init_info(struct fb_info *info, | |||
| 555 | 555 | ||
| 556 | 556 | ||
| 557 | /* | 557 | /* |
| 558 | * Parse user speficied options (`video=valkyriefb:') | 558 | * Parse user specified options (`video=valkyriefb:') |
| 559 | */ | 559 | */ |
| 560 | int __init valkyriefb_setup(char *options) | 560 | int __init valkyriefb_setup(char *options) |
| 561 | { | 561 | { |
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index bc67251f1a2f..bf2f78065cf9 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
| @@ -395,8 +395,8 @@ static int vfb_pan_display(struct fb_var_screeninfo *var, | |||
| 395 | || var->xoffset) | 395 | || var->xoffset) |
| 396 | return -EINVAL; | 396 | return -EINVAL; |
| 397 | } else { | 397 | } else { |
| 398 | if (var->xoffset + var->xres > info->var.xres_virtual || | 398 | if (var->xoffset + info->var.xres > info->var.xres_virtual || |
| 399 | var->yoffset + var->yres > info->var.yres_virtual) | 399 | var->yoffset + info->var.yres > info->var.yres_virtual) |
| 400 | return -EINVAL; | 400 | return -EINVAL; |
| 401 | } | 401 | } |
| 402 | info->var.xoffset = var->xoffset; | 402 | info->var.xoffset = var->xoffset; |
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index 305c975b1787..0267acd8dc83 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
| @@ -207,7 +207,7 @@ static void vga16fb_pan_var(struct fb_info *info, | |||
| 207 | * granularity if someone supports xoffset in bit resolution */ | 207 | * granularity if someone supports xoffset in bit resolution */ |
| 208 | vga_io_r(VGA_IS1_RC); /* reset flip-flop */ | 208 | vga_io_r(VGA_IS1_RC); /* reset flip-flop */ |
| 209 | vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); | 209 | vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); |
| 210 | if (var->bits_per_pixel == 8) | 210 | if (info->var.bits_per_pixel == 8) |
| 211 | vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); | 211 | vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); |
| 212 | else | 212 | else |
| 213 | vga_io_w(VGA_ATT_IW, xoffset & 7); | 213 | vga_io_w(VGA_ATT_IW, xoffset & 7); |
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c index b1f364745ca0..9138e517267c 100644 --- a/drivers/video/via/dvi.c +++ b/drivers/video/via/dvi.c | |||
| @@ -172,30 +172,20 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) | |||
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | /* DVI Set Mode */ | 174 | /* DVI Set Mode */ |
| 175 | void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp, | 175 | void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) |
| 176 | int set_iga) | ||
| 177 | { | 176 | { |
| 178 | struct VideoModeTable *rb_mode; | 177 | struct fb_var_screeninfo dvi_var = *var; |
| 179 | struct crt_mode_table *pDviTiming; | 178 | struct crt_mode_table *rb_mode; |
| 180 | unsigned long desirePixelClock, maxPixelClock; | 179 | int maxPixelClock; |
| 181 | pDviTiming = mode->crtc; | 180 | |
| 182 | desirePixelClock = pDviTiming->refresh_rate | 181 | maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; |
| 183 | * pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total | 182 | if (maxPixelClock && PICOS2KHZ(var->pixclock) / 1000 > maxPixelClock) { |
| 184 | / 1000000; | 183 | rb_mode = viafb_get_best_rb_mode(var->xres, var->yres, 60); |
| 185 | maxPixelClock = (unsigned long)viaparinfo-> | 184 | if (rb_mode) |
| 186 | tmds_setting_info->max_pixel_clock; | 185 | viafb_fill_var_timing_info(&dvi_var, rb_mode); |
| 187 | |||
| 188 | DEBUG_MSG(KERN_INFO "\nDVI_set_mode!!\n"); | ||
| 189 | |||
| 190 | if ((maxPixelClock != 0) && (desirePixelClock > maxPixelClock)) { | ||
| 191 | rb_mode = viafb_get_rb_mode(mode->crtc[0].crtc.hor_addr, | ||
| 192 | mode->crtc[0].crtc.ver_addr); | ||
| 193 | if (rb_mode) { | ||
| 194 | mode = rb_mode; | ||
| 195 | pDviTiming = rb_mode->crtc; | ||
| 196 | } | ||
| 197 | } | 186 | } |
| 198 | viafb_fill_crtc_timing(pDviTiming, mode, mode_bpp / 8, set_iga); | 187 | |
| 188 | viafb_fill_crtc_timing(&dvi_var, iga); | ||
| 199 | } | 189 | } |
| 200 | 190 | ||
| 201 | /* Sense DVI Connector */ | 191 | /* Sense DVI Connector */ |
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h index f473dd010977..e2116aaf797a 100644 --- a/drivers/video/via/dvi.h +++ b/drivers/video/via/dvi.h | |||
| @@ -59,7 +59,6 @@ void viafb_dvi_enable(void); | |||
| 59 | bool __devinit viafb_tmds_trasmitter_identify(void); | 59 | bool __devinit viafb_tmds_trasmitter_identify(void); |
| 60 | void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, | 60 | void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, |
| 61 | struct tmds_setting_information *tmds_setting); | 61 | struct tmds_setting_information *tmds_setting); |
| 62 | void viafb_dvi_set_mode(struct VideoModeTable *videoMode, int mode_bpp, | 62 | void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); |
| 63 | int set_iga); | ||
| 64 | 63 | ||
| 65 | #endif /* __DVI_H__ */ | 64 | #endif /* __DVI_H__ */ |
diff --git a/drivers/video/via/global.c b/drivers/video/via/global.c index e10d8249534c..3102171c1674 100644 --- a/drivers/video/via/global.c +++ b/drivers/video/via/global.c | |||
| @@ -35,6 +35,8 @@ int viafb_LCD_ON ; | |||
| 35 | int viafb_LCD2_ON; | 35 | int viafb_LCD2_ON; |
| 36 | int viafb_SAMM_ON; | 36 | int viafb_SAMM_ON; |
| 37 | int viafb_dual_fb; | 37 | int viafb_dual_fb; |
| 38 | unsigned int viafb_second_xres = 640; | ||
| 39 | unsigned int viafb_second_yres = 480; | ||
| 38 | int viafb_hotplug_Xres = 640; | 40 | int viafb_hotplug_Xres = 640; |
| 39 | int viafb_hotplug_Yres = 480; | 41 | int viafb_hotplug_Yres = 480; |
| 40 | int viafb_hotplug_bpp = 32; | 42 | int viafb_hotplug_bpp = 32; |
diff --git a/drivers/video/via/global.h b/drivers/video/via/global.h index ff969dc34593..275dbbbd6b81 100644 --- a/drivers/video/via/global.h +++ b/drivers/video/via/global.h | |||
| @@ -67,6 +67,8 @@ extern int viafb_lcd_dsp_method; | |||
| 67 | extern int viafb_lcd_mode; | 67 | extern int viafb_lcd_mode; |
| 68 | 68 | ||
| 69 | extern int viafb_CRT_ON; | 69 | extern int viafb_CRT_ON; |
| 70 | extern unsigned int viafb_second_xres; | ||
| 71 | extern unsigned int viafb_second_yres; | ||
| 70 | extern int viafb_hotplug_Xres; | 72 | extern int viafb_hotplug_Xres; |
| 71 | extern int viafb_hotplug_Yres; | 73 | extern int viafb_hotplug_Yres; |
| 72 | extern int viafb_hotplug_bpp; | 74 | extern int viafb_hotplug_bpp; |
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c index 47b13535ed2b..d5aaca9cfa7e 100644 --- a/drivers/video/via/hw.c +++ b/drivers/video/via/hw.c | |||
| @@ -191,67 +191,6 @@ static struct fetch_count fetch_count_reg = { | |||
| 191 | {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } | 191 | {IGA2_FETCH_COUNT_REG_NUM, {{CR65, 0, 7}, {CR67, 2, 3} } } |
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | static struct iga1_crtc_timing iga1_crtc_reg = { | ||
| 195 | /* IGA1 Horizontal Total */ | ||
| 196 | {IGA1_HOR_TOTAL_REG_NUM, {{CR00, 0, 7}, {CR36, 3, 3} } }, | ||
| 197 | /* IGA1 Horizontal Addressable Video */ | ||
| 198 | {IGA1_HOR_ADDR_REG_NUM, {{CR01, 0, 7} } }, | ||
| 199 | /* IGA1 Horizontal Blank Start */ | ||
| 200 | {IGA1_HOR_BLANK_START_REG_NUM, {{CR02, 0, 7} } }, | ||
| 201 | /* IGA1 Horizontal Blank End */ | ||
| 202 | {IGA1_HOR_BLANK_END_REG_NUM, | ||
| 203 | {{CR03, 0, 4}, {CR05, 7, 7}, {CR33, 5, 5} } }, | ||
| 204 | /* IGA1 Horizontal Sync Start */ | ||
| 205 | {IGA1_HOR_SYNC_START_REG_NUM, {{CR04, 0, 7}, {CR33, 4, 4} } }, | ||
| 206 | /* IGA1 Horizontal Sync End */ | ||
| 207 | {IGA1_HOR_SYNC_END_REG_NUM, {{CR05, 0, 4} } }, | ||
| 208 | /* IGA1 Vertical Total */ | ||
| 209 | {IGA1_VER_TOTAL_REG_NUM, | ||
| 210 | {{CR06, 0, 7}, {CR07, 0, 0}, {CR07, 5, 5}, {CR35, 0, 0} } }, | ||
| 211 | /* IGA1 Vertical Addressable Video */ | ||
| 212 | {IGA1_VER_ADDR_REG_NUM, | ||
| 213 | {{CR12, 0, 7}, {CR07, 1, 1}, {CR07, 6, 6}, {CR35, 2, 2} } }, | ||
| 214 | /* IGA1 Vertical Blank Start */ | ||
| 215 | {IGA1_VER_BLANK_START_REG_NUM, | ||
| 216 | {{CR15, 0, 7}, {CR07, 3, 3}, {CR09, 5, 5}, {CR35, 3, 3} } }, | ||
| 217 | /* IGA1 Vertical Blank End */ | ||
| 218 | {IGA1_VER_BLANK_END_REG_NUM, {{CR16, 0, 7} } }, | ||
| 219 | /* IGA1 Vertical Sync Start */ | ||
| 220 | {IGA1_VER_SYNC_START_REG_NUM, | ||
| 221 | {{CR10, 0, 7}, {CR07, 2, 2}, {CR07, 7, 7}, {CR35, 1, 1} } }, | ||
| 222 | /* IGA1 Vertical Sync End */ | ||
| 223 | {IGA1_VER_SYNC_END_REG_NUM, {{CR11, 0, 3} } } | ||
| 224 | }; | ||
| 225 | |||
| 226 | static struct iga2_crtc_timing iga2_crtc_reg = { | ||
| 227 | /* IGA2 Horizontal Total */ | ||
| 228 | {IGA2_HOR_TOTAL_REG_NUM, {{CR50, 0, 7}, {CR55, 0, 3} } }, | ||
| 229 | /* IGA2 Horizontal Addressable Video */ | ||
| 230 | {IGA2_HOR_ADDR_REG_NUM, {{CR51, 0, 7}, {CR55, 4, 6} } }, | ||
| 231 | /* IGA2 Horizontal Blank Start */ | ||
| 232 | {IGA2_HOR_BLANK_START_REG_NUM, {{CR52, 0, 7}, {CR54, 0, 2} } }, | ||
| 233 | /* IGA2 Horizontal Blank End */ | ||
| 234 | {IGA2_HOR_BLANK_END_REG_NUM, | ||
| 235 | {{CR53, 0, 7}, {CR54, 3, 5}, {CR5D, 6, 6} } }, | ||
| 236 | /* IGA2 Horizontal Sync Start */ | ||
| 237 | {IGA2_HOR_SYNC_START_REG_NUM, | ||
| 238 | {{CR56, 0, 7}, {CR54, 6, 7}, {CR5C, 7, 7}, {CR5D, 7, 7} } }, | ||
| 239 | /* IGA2 Horizontal Sync End */ | ||
| 240 | {IGA2_HOR_SYNC_END_REG_NUM, {{CR57, 0, 7}, {CR5C, 6, 6} } }, | ||
| 241 | /* IGA2 Vertical Total */ | ||
| 242 | {IGA2_VER_TOTAL_REG_NUM, {{CR58, 0, 7}, {CR5D, 0, 2} } }, | ||
| 243 | /* IGA2 Vertical Addressable Video */ | ||
| 244 | {IGA2_VER_ADDR_REG_NUM, {{CR59, 0, 7}, {CR5D, 3, 5} } }, | ||
| 245 | /* IGA2 Vertical Blank Start */ | ||
| 246 | {IGA2_VER_BLANK_START_REG_NUM, {{CR5A, 0, 7}, {CR5C, 0, 2} } }, | ||
| 247 | /* IGA2 Vertical Blank End */ | ||
| 248 | {IGA2_VER_BLANK_END_REG_NUM, {{CR5B, 0, 7}, {CR5C, 3, 5} } }, | ||
| 249 | /* IGA2 Vertical Sync Start */ | ||
| 250 | {IGA2_VER_SYNC_START_REG_NUM, {{CR5E, 0, 7}, {CR5F, 5, 7} } }, | ||
| 251 | /* IGA2 Vertical Sync End */ | ||
| 252 | {IGA2_VER_SYNC_END_REG_NUM, {{CR5F, 0, 4} } } | ||
| 253 | }; | ||
| 254 | |||
| 255 | static struct rgbLUT palLUT_table[] = { | 194 | static struct rgbLUT palLUT_table[] = { |
| 256 | /* {R,G,B} */ | 195 | /* {R,G,B} */ |
| 257 | /* Index 0x00~0x03 */ | 196 | /* Index 0x00~0x03 */ |
| @@ -1528,302 +1467,40 @@ void viafb_set_vclock(u32 clk, int set_iga) | |||
| 1528 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ | 1467 | via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ |
| 1529 | } | 1468 | } |
| 1530 | 1469 | ||
| 1531 | void viafb_load_crtc_timing(struct display_timing device_timing, | 1470 | static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) |
| 1532 | int set_iga) | ||
| 1533 | { | 1471 | { |
| 1534 | int i; | 1472 | struct display_timing timing; |
| 1535 | int viafb_load_reg_num = 0; | 1473 | |
| 1536 | int reg_value = 0; | 1474 | timing.hor_addr = var->xres; |
| 1537 | struct io_register *reg = NULL; | 1475 | timing.hor_sync_start = timing.hor_addr + var->right_margin; |
| 1538 | 1476 | timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; | |
| 1539 | viafb_unlock_crt(); | 1477 | timing.hor_total = timing.hor_sync_end + var->left_margin; |
| 1540 | 1478 | timing.hor_blank_start = timing.hor_addr; | |
| 1541 | for (i = 0; i < 12; i++) { | 1479 | timing.hor_blank_end = timing.hor_total; |
| 1542 | if (set_iga == IGA1) { | 1480 | timing.ver_addr = var->yres; |
| 1543 | switch (i) { | 1481 | timing.ver_sync_start = timing.ver_addr + var->lower_margin; |
| 1544 | case H_TOTAL_INDEX: | 1482 | timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; |
| 1545 | reg_value = | 1483 | timing.ver_total = timing.ver_sync_end + var->upper_margin; |
| 1546 | IGA1_HOR_TOTAL_FORMULA(device_timing. | 1484 | timing.ver_blank_start = timing.ver_addr; |
| 1547 | hor_total); | 1485 | timing.ver_blank_end = timing.ver_total; |
| 1548 | viafb_load_reg_num = | 1486 | return timing; |
| 1549 | iga1_crtc_reg.hor_total.reg_num; | ||
| 1550 | reg = iga1_crtc_reg.hor_total.reg; | ||
| 1551 | break; | ||
| 1552 | case H_ADDR_INDEX: | ||
| 1553 | reg_value = | ||
| 1554 | IGA1_HOR_ADDR_FORMULA(device_timing. | ||
| 1555 | hor_addr); | ||
| 1556 | viafb_load_reg_num = | ||
| 1557 | iga1_crtc_reg.hor_addr.reg_num; | ||
| 1558 | reg = iga1_crtc_reg.hor_addr.reg; | ||
| 1559 | break; | ||
| 1560 | case H_BLANK_START_INDEX: | ||
| 1561 | reg_value = | ||
| 1562 | IGA1_HOR_BLANK_START_FORMULA | ||
| 1563 | (device_timing.hor_blank_start); | ||
| 1564 | viafb_load_reg_num = | ||
| 1565 | iga1_crtc_reg.hor_blank_start.reg_num; | ||
| 1566 | reg = iga1_crtc_reg.hor_blank_start.reg; | ||
| 1567 | break; | ||
| 1568 | case H_BLANK_END_INDEX: | ||
| 1569 | reg_value = | ||
| 1570 | IGA1_HOR_BLANK_END_FORMULA | ||
| 1571 | (device_timing.hor_blank_start, | ||
| 1572 | device_timing.hor_blank_end); | ||
| 1573 | viafb_load_reg_num = | ||
| 1574 | iga1_crtc_reg.hor_blank_end.reg_num; | ||
| 1575 | reg = iga1_crtc_reg.hor_blank_end.reg; | ||
| 1576 | break; | ||
| 1577 | case H_SYNC_START_INDEX: | ||
| 1578 | reg_value = | ||
| 1579 | IGA1_HOR_SYNC_START_FORMULA | ||
| 1580 | (device_timing.hor_sync_start); | ||
| 1581 | viafb_load_reg_num = | ||
| 1582 | iga1_crtc_reg.hor_sync_start.reg_num; | ||
| 1583 | reg = iga1_crtc_reg.hor_sync_start.reg; | ||
| 1584 | break; | ||
| 1585 | case H_SYNC_END_INDEX: | ||
| 1586 | reg_value = | ||
| 1587 | IGA1_HOR_SYNC_END_FORMULA | ||
| 1588 | (device_timing.hor_sync_start, | ||
| 1589 | device_timing.hor_sync_end); | ||
| 1590 | viafb_load_reg_num = | ||
| 1591 | iga1_crtc_reg.hor_sync_end.reg_num; | ||
| 1592 | reg = iga1_crtc_reg.hor_sync_end.reg; | ||
| 1593 | break; | ||
| 1594 | case V_TOTAL_INDEX: | ||
| 1595 | reg_value = | ||
| 1596 | IGA1_VER_TOTAL_FORMULA(device_timing. | ||
| 1597 | ver_total); | ||
| 1598 | viafb_load_reg_num = | ||
| 1599 | iga1_crtc_reg.ver_total.reg_num; | ||
| 1600 | reg = iga1_crtc_reg.ver_total.reg; | ||
| 1601 | break; | ||
| 1602 | case V_ADDR_INDEX: | ||
| 1603 | reg_value = | ||
| 1604 | IGA1_VER_ADDR_FORMULA(device_timing. | ||
| 1605 | ver_addr); | ||
| 1606 | viafb_load_reg_num = | ||
| 1607 | iga1_crtc_reg.ver_addr.reg_num; | ||
| 1608 | reg = iga1_crtc_reg.ver_addr.reg; | ||
| 1609 | break; | ||
| 1610 | case V_BLANK_START_INDEX: | ||
| 1611 | reg_value = | ||
| 1612 | IGA1_VER_BLANK_START_FORMULA | ||
| 1613 | (device_timing.ver_blank_start); | ||
| 1614 | viafb_load_reg_num = | ||
| 1615 | iga1_crtc_reg.ver_blank_start.reg_num; | ||
| 1616 | reg = iga1_crtc_reg.ver_blank_start.reg; | ||
| 1617 | break; | ||
| 1618 | case V_BLANK_END_INDEX: | ||
| 1619 | reg_value = | ||
| 1620 | IGA1_VER_BLANK_END_FORMULA | ||
| 1621 | (device_timing.ver_blank_start, | ||
| 1622 | device_timing.ver_blank_end); | ||
| 1623 | viafb_load_reg_num = | ||
| 1624 | iga1_crtc_reg.ver_blank_end.reg_num; | ||
| 1625 | reg = iga1_crtc_reg.ver_blank_end.reg; | ||
| 1626 | break; | ||
| 1627 | case V_SYNC_START_INDEX: | ||
| 1628 | reg_value = | ||
| 1629 | IGA1_VER_SYNC_START_FORMULA | ||
| 1630 | (device_timing.ver_sync_start); | ||
| 1631 | viafb_load_reg_num = | ||
| 1632 | iga1_crtc_reg.ver_sync_start.reg_num; | ||
| 1633 | reg = iga1_crtc_reg.ver_sync_start.reg; | ||
| 1634 | break; | ||
| 1635 | case V_SYNC_END_INDEX: | ||
| 1636 | reg_value = | ||
| 1637 | IGA1_VER_SYNC_END_FORMULA | ||
| 1638 | (device_timing.ver_sync_start, | ||
| 1639 | device_timing.ver_sync_end); | ||
| 1640 | viafb_load_reg_num = | ||
| 1641 | iga1_crtc_reg.ver_sync_end.reg_num; | ||
| 1642 | reg = iga1_crtc_reg.ver_sync_end.reg; | ||
| 1643 | break; | ||
| 1644 | |||
| 1645 | } | ||
| 1646 | } | ||
| 1647 | |||
| 1648 | if (set_iga == IGA2) { | ||
| 1649 | switch (i) { | ||
| 1650 | case H_TOTAL_INDEX: | ||
| 1651 | reg_value = | ||
| 1652 | IGA2_HOR_TOTAL_FORMULA(device_timing. | ||
| 1653 | hor_total); | ||
| 1654 | viafb_load_reg_num = | ||
| 1655 | iga2_crtc_reg.hor_total.reg_num; | ||
| 1656 | reg = iga2_crtc_reg.hor_total.reg; | ||
| 1657 | break; | ||
| 1658 | case H_ADDR_INDEX: | ||
| 1659 | reg_value = | ||
| 1660 | IGA2_HOR_ADDR_FORMULA(device_timing. | ||
| 1661 | hor_addr); | ||
| 1662 | viafb_load_reg_num = | ||
| 1663 | iga2_crtc_reg.hor_addr.reg_num; | ||
| 1664 | reg = iga2_crtc_reg.hor_addr.reg; | ||
| 1665 | break; | ||
| 1666 | case H_BLANK_START_INDEX: | ||
| 1667 | reg_value = | ||
| 1668 | IGA2_HOR_BLANK_START_FORMULA | ||
| 1669 | (device_timing.hor_blank_start); | ||
| 1670 | viafb_load_reg_num = | ||
| 1671 | iga2_crtc_reg.hor_blank_start.reg_num; | ||
| 1672 | reg = iga2_crtc_reg.hor_blank_start.reg; | ||
| 1673 | break; | ||
| 1674 | case H_BLANK_END_INDEX: | ||
| 1675 | reg_value = | ||
| 1676 | IGA2_HOR_BLANK_END_FORMULA | ||
| 1677 | (device_timing.hor_blank_start, | ||
| 1678 | device_timing.hor_blank_end); | ||
| 1679 | viafb_load_reg_num = | ||
| 1680 | iga2_crtc_reg.hor_blank_end.reg_num; | ||
| 1681 | reg = iga2_crtc_reg.hor_blank_end.reg; | ||
| 1682 | break; | ||
| 1683 | case H_SYNC_START_INDEX: | ||
| 1684 | reg_value = | ||
| 1685 | IGA2_HOR_SYNC_START_FORMULA | ||
| 1686 | (device_timing.hor_sync_start); | ||
| 1687 | if (UNICHROME_CN700 <= | ||
| 1688 | viaparinfo->chip_info->gfx_chip_name) | ||
| 1689 | viafb_load_reg_num = | ||
| 1690 | iga2_crtc_reg.hor_sync_start. | ||
| 1691 | reg_num; | ||
| 1692 | else | ||
| 1693 | viafb_load_reg_num = 3; | ||
| 1694 | reg = iga2_crtc_reg.hor_sync_start.reg; | ||
| 1695 | break; | ||
| 1696 | case H_SYNC_END_INDEX: | ||
| 1697 | reg_value = | ||
| 1698 | IGA2_HOR_SYNC_END_FORMULA | ||
| 1699 | (device_timing.hor_sync_start, | ||
| 1700 | device_timing.hor_sync_end); | ||
| 1701 | viafb_load_reg_num = | ||
| 1702 | iga2_crtc_reg.hor_sync_end.reg_num; | ||
| 1703 | reg = iga2_crtc_reg.hor_sync_end.reg; | ||
| 1704 | break; | ||
| 1705 | case V_TOTAL_INDEX: | ||
| 1706 | reg_value = | ||
| 1707 | IGA2_VER_TOTAL_FORMULA(device_timing. | ||
| 1708 | ver_total); | ||
| 1709 | viafb_load_reg_num = | ||
| 1710 | iga2_crtc_reg.ver_total.reg_num; | ||
| 1711 | reg = iga2_crtc_reg.ver_total.reg; | ||
| 1712 | break; | ||
| 1713 | case V_ADDR_INDEX: | ||
| 1714 | reg_value = | ||
| 1715 | IGA2_VER_ADDR_FORMULA(device_timing. | ||
| 1716 | ver_addr); | ||
| 1717 | viafb_load_reg_num = | ||
| 1718 | iga2_crtc_reg.ver_addr.reg_num; | ||
| 1719 | reg = iga2_crtc_reg.ver_addr.reg; | ||
| 1720 | break; | ||
| 1721 | case V_BLANK_START_INDEX: | ||
| 1722 | reg_value = | ||
| 1723 | IGA2_VER_BLANK_START_FORMULA | ||
| 1724 | (device_timing.ver_blank_start); | ||
| 1725 | viafb_load_reg_num = | ||
| 1726 | iga2_crtc_reg.ver_blank_start.reg_num; | ||
| 1727 | reg = iga2_crtc_reg.ver_blank_start.reg; | ||
| 1728 | break; | ||
| 1729 | case V_BLANK_END_INDEX: | ||
| 1730 | reg_value = | ||
| 1731 | IGA2_VER_BLANK_END_FORMULA | ||
| 1732 | (device_timing.ver_blank_start, | ||
| 1733 | device_timing.ver_blank_end); | ||
| 1734 | viafb_load_reg_num = | ||
| 1735 | iga2_crtc_reg.ver_blank_end.reg_num; | ||
| 1736 | reg = iga2_crtc_reg.ver_blank_end.reg; | ||
| 1737 | break; | ||
| 1738 | case V_SYNC_START_INDEX: | ||
| 1739 | reg_value = | ||
| 1740 | IGA2_VER_SYNC_START_FORMULA | ||
| 1741 | (device_timing.ver_sync_start); | ||
| 1742 | viafb_load_reg_num = | ||
| 1743 | iga2_crtc_reg.ver_sync_start.reg_num; | ||
| 1744 | reg = iga2_crtc_reg.ver_sync_start.reg; | ||
| 1745 | break; | ||
| 1746 | case V_SYNC_END_INDEX: | ||
| 1747 | reg_value = | ||
| 1748 | IGA2_VER_SYNC_END_FORMULA | ||
| 1749 | (device_timing.ver_sync_start, | ||
| 1750 | device_timing.ver_sync_end); | ||
| 1751 | viafb_load_reg_num = | ||
| 1752 | iga2_crtc_reg.ver_sync_end.reg_num; | ||
| 1753 | reg = iga2_crtc_reg.ver_sync_end.reg; | ||
| 1754 | break; | ||
| 1755 | |||
| 1756 | } | ||
| 1757 | } | ||
| 1758 | viafb_load_reg(reg_value, viafb_load_reg_num, reg, VIACR); | ||
| 1759 | } | ||
| 1760 | |||
| 1761 | viafb_lock_crt(); | ||
| 1762 | } | 1487 | } |
| 1763 | 1488 | ||
| 1764 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | 1489 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) |
| 1765 | struct VideoModeTable *video_mode, int bpp_byte, int set_iga) | ||
| 1766 | { | 1490 | { |
| 1767 | struct display_timing crt_reg; | 1491 | struct display_timing crt_reg = var_to_timing(var); |
| 1768 | int i; | ||
| 1769 | int index = 0; | ||
| 1770 | int h_addr, v_addr; | ||
| 1771 | u32 clock, refresh = viafb_refresh; | ||
| 1772 | |||
| 1773 | if (viafb_SAMM_ON && set_iga == IGA2) | ||
| 1774 | refresh = viafb_refresh1; | ||
| 1775 | |||
| 1776 | for (i = 0; i < video_mode->mode_array; i++) { | ||
| 1777 | index = i; | ||
| 1778 | |||
| 1779 | if (crt_table[i].refresh_rate == refresh) | ||
| 1780 | break; | ||
| 1781 | } | ||
| 1782 | 1492 | ||
| 1783 | crt_reg = crt_table[index].crtc; | 1493 | if (iga == IGA1) |
| 1494 | via_set_primary_timing(&crt_reg); | ||
| 1495 | else if (iga == IGA2) | ||
| 1496 | via_set_secondary_timing(&crt_reg); | ||
| 1784 | 1497 | ||
| 1785 | /* Mode 640x480 has border, but LCD/DFP didn't have border. */ | 1498 | viafb_load_fetch_count_reg(var->xres, var->bits_per_pixel / 8, iga); |
| 1786 | /* So we would delete border. */ | 1499 | if (viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266 |
| 1787 | if ((viafb_LCD_ON | viafb_DVI_ON) | 1500 | && viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400) |
| 1788 | && video_mode->crtc[0].crtc.hor_addr == 640 | 1501 | viafb_load_FIFO_reg(iga, var->xres, var->yres); |
| 1789 | && video_mode->crtc[0].crtc.ver_addr == 480 | ||
| 1790 | && refresh == 60) { | ||
| 1791 | /* The border is 8 pixels. */ | ||
| 1792 | crt_reg.hor_blank_start = crt_reg.hor_blank_start - 8; | ||
| 1793 | |||
| 1794 | /* Blanking time should add left and right borders. */ | ||
| 1795 | crt_reg.hor_blank_end = crt_reg.hor_blank_end + 16; | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | h_addr = crt_reg.hor_addr; | ||
| 1799 | v_addr = crt_reg.ver_addr; | ||
| 1800 | if (set_iga == IGA1) { | ||
| 1801 | viafb_unlock_crt(); | ||
| 1802 | viafb_write_reg_mask(CR17, VIACR, 0x00, BIT7); | ||
| 1803 | } | ||
| 1804 | |||
| 1805 | switch (set_iga) { | ||
| 1806 | case IGA1: | ||
| 1807 | viafb_load_crtc_timing(crt_reg, IGA1); | ||
| 1808 | break; | ||
| 1809 | case IGA2: | ||
| 1810 | viafb_load_crtc_timing(crt_reg, IGA2); | ||
| 1811 | break; | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | viafb_lock_crt(); | ||
| 1815 | viafb_write_reg_mask(CR17, VIACR, 0x80, BIT7); | ||
| 1816 | viafb_load_fetch_count_reg(h_addr, bpp_byte, set_iga); | ||
| 1817 | |||
| 1818 | /* load FIFO */ | ||
| 1819 | if ((viaparinfo->chip_info->gfx_chip_name != UNICHROME_CLE266) | ||
| 1820 | && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400)) | ||
| 1821 | viafb_load_FIFO_reg(set_iga, h_addr, v_addr); | ||
| 1822 | |||
| 1823 | clock = crt_reg.hor_total * crt_reg.ver_total | ||
| 1824 | * crt_table[index].refresh_rate; | ||
| 1825 | viafb_set_vclock(clock, set_iga); | ||
| 1826 | 1502 | ||
| 1503 | viafb_set_vclock(PICOS2KHZ(var->pixclock) * 1000, iga); | ||
| 1827 | } | 1504 | } |
| 1828 | 1505 | ||
| 1829 | void __devinit viafb_init_chip_info(int chip_type) | 1506 | void __devinit viafb_init_chip_info(int chip_type) |
| @@ -2092,23 +1769,9 @@ static u8 get_sync(struct fb_info *info) | |||
| 2092 | return polarity; | 1769 | return polarity; |
| 2093 | } | 1770 | } |
| 2094 | 1771 | ||
| 2095 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | 1772 | static void hw_init(void) |
| 2096 | struct VideoModeTable *vmode_tbl1, int video_bpp1) | ||
| 2097 | { | 1773 | { |
| 2098 | int i, j; | 1774 | int i; |
| 2099 | int port; | ||
| 2100 | u32 devices = viaparinfo->shared->iga1_devices | ||
| 2101 | | viaparinfo->shared->iga2_devices; | ||
| 2102 | u8 value, index, mask; | ||
| 2103 | struct crt_mode_table *crt_timing; | ||
| 2104 | struct crt_mode_table *crt_timing1 = NULL; | ||
| 2105 | |||
| 2106 | device_screen_off(); | ||
| 2107 | crt_timing = vmode_tbl->crtc; | ||
| 2108 | |||
| 2109 | if (viafb_SAMM_ON == 1) { | ||
| 2110 | crt_timing1 = vmode_tbl1->crtc; | ||
| 2111 | } | ||
| 2112 | 1775 | ||
| 2113 | inb(VIAStatus); | 1776 | inb(VIAStatus); |
| 2114 | outb(0x00, VIAAR); | 1777 | outb(0x00, VIAAR); |
| @@ -2147,9 +1810,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2147 | break; | 1810 | break; |
| 2148 | } | 1811 | } |
| 2149 | 1812 | ||
| 1813 | /* probably this should go to the scaling code one day */ | ||
| 2150 | viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); | 1814 | viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters)); |
| 2151 | device_off(); | ||
| 2152 | via_set_state(devices, VIA_STATE_OFF); | ||
| 2153 | 1815 | ||
| 2154 | /* Fill VPIT Parameters */ | 1816 | /* Fill VPIT Parameters */ |
| 2155 | /* Write Misc Register */ | 1817 | /* Write Misc Register */ |
| @@ -2175,12 +1837,29 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2175 | inb(VIAStatus); | 1837 | inb(VIAStatus); |
| 2176 | outb(0x20, VIAAR); | 1838 | outb(0x20, VIAAR); |
| 2177 | 1839 | ||
| 1840 | load_fix_bit_crtc_reg(); | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | int viafb_setmode(int video_bpp, int video_bpp1) | ||
| 1844 | { | ||
| 1845 | int j; | ||
| 1846 | int port; | ||
| 1847 | u32 devices = viaparinfo->shared->iga1_devices | ||
| 1848 | | viaparinfo->shared->iga2_devices; | ||
| 1849 | u8 value, index, mask; | ||
| 1850 | struct fb_var_screeninfo var2; | ||
| 1851 | |||
| 1852 | device_screen_off(); | ||
| 1853 | device_off(); | ||
| 1854 | via_set_state(devices, VIA_STATE_OFF); | ||
| 1855 | |||
| 1856 | hw_init(); | ||
| 1857 | |||
| 2178 | /* Update Patch Register */ | 1858 | /* Update Patch Register */ |
| 2179 | 1859 | ||
| 2180 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 | 1860 | if ((viaparinfo->chip_info->gfx_chip_name == UNICHROME_CLE266 |
| 2181 | || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) | 1861 | || viaparinfo->chip_info->gfx_chip_name == UNICHROME_K400) |
| 2182 | && vmode_tbl->crtc[0].crtc.hor_addr == 1024 | 1862 | && viafbinfo->var.xres == 1024 && viafbinfo->var.yres == 768) { |
| 2183 | && vmode_tbl->crtc[0].crtc.ver_addr == 768) { | ||
| 2184 | for (j = 0; j < res_patch_table[0].table_length; j++) { | 1863 | for (j = 0; j < res_patch_table[0].table_length; j++) { |
| 2185 | index = res_patch_table[0].io_reg_table[j].index; | 1864 | index = res_patch_table[0].io_reg_table[j].index; |
| 2186 | port = res_patch_table[0].io_reg_table[j].port; | 1865 | port = res_patch_table[0].io_reg_table[j].port; |
| @@ -2190,7 +1869,6 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2190 | } | 1869 | } |
| 2191 | } | 1870 | } |
| 2192 | 1871 | ||
| 2193 | load_fix_bit_crtc_reg(); | ||
| 2194 | via_set_primary_pitch(viafbinfo->fix.line_length); | 1872 | via_set_primary_pitch(viafbinfo->fix.line_length); |
| 2195 | via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length | 1873 | via_set_secondary_pitch(viafb_dual_fb ? viafbinfo1->fix.line_length |
| 2196 | : viafbinfo->fix.line_length); | 1874 | : viafbinfo->fix.line_length); |
| @@ -2208,23 +1886,28 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2208 | 1886 | ||
| 2209 | /* Clear On Screen */ | 1887 | /* Clear On Screen */ |
| 2210 | 1888 | ||
| 1889 | if (viafb_dual_fb) { | ||
| 1890 | var2 = viafbinfo1->var; | ||
| 1891 | } else if (viafb_SAMM_ON) { | ||
| 1892 | viafb_fill_var_timing_info(&var2, viafb_get_best_mode( | ||
| 1893 | viafb_second_xres, viafb_second_yres, viafb_refresh1)); | ||
| 1894 | var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; | ||
| 1895 | } | ||
| 1896 | |||
| 2211 | /* CRT set mode */ | 1897 | /* CRT set mode */ |
| 2212 | if (viafb_CRT_ON) { | 1898 | if (viafb_CRT_ON) { |
| 2213 | if (viafb_SAMM_ON && | 1899 | if (viaparinfo->shared->iga2_devices & VIA_CRT |
| 2214 | viaparinfo->shared->iga2_devices & VIA_CRT) { | 1900 | && viafb_SAMM_ON) |
| 2215 | viafb_fill_crtc_timing(crt_timing1, vmode_tbl1, | 1901 | viafb_fill_crtc_timing(&var2, IGA2); |
| 2216 | video_bpp1 / 8, IGA2); | 1902 | else |
| 2217 | } else { | 1903 | viafb_fill_crtc_timing(&viafbinfo->var, |
| 2218 | viafb_fill_crtc_timing(crt_timing, vmode_tbl, | ||
| 2219 | video_bpp / 8, | ||
| 2220 | (viaparinfo->shared->iga1_devices & VIA_CRT) | 1904 | (viaparinfo->shared->iga1_devices & VIA_CRT) |
| 2221 | ? IGA1 : IGA2); | 1905 | ? IGA1 : IGA2); |
| 2222 | } | ||
| 2223 | 1906 | ||
| 2224 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode | 1907 | /* Patch if set_hres is not 8 alignment (1366) to viafb_setmode |
| 2225 | to 8 alignment (1368),there is several pixels (2 pixels) | 1908 | to 8 alignment (1368),there is several pixels (2 pixels) |
| 2226 | on right side of screen. */ | 1909 | on right side of screen. */ |
| 2227 | if (vmode_tbl->crtc[0].crtc.hor_addr % 8) { | 1910 | if (viafbinfo->var.xres % 8) { |
| 2228 | viafb_unlock_crt(); | 1911 | viafb_unlock_crt(); |
| 2229 | viafb_write_reg(CR02, VIACR, | 1912 | viafb_write_reg(CR02, VIACR, |
| 2230 | viafb_read_reg(VIACR, CR02) - 1); | 1913 | viafb_read_reg(VIACR, CR02) - 1); |
| @@ -2233,31 +1916,20 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2233 | } | 1916 | } |
| 2234 | 1917 | ||
| 2235 | if (viafb_DVI_ON) { | 1918 | if (viafb_DVI_ON) { |
| 2236 | if (viafb_SAMM_ON && | 1919 | if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 |
| 2237 | (viaparinfo->tmds_setting_info->iga_path == IGA2)) { | 1920 | && viafb_SAMM_ON) |
| 2238 | viafb_dvi_set_mode(viafb_get_mode | 1921 | viafb_dvi_set_mode(&var2, IGA2); |
| 2239 | (viaparinfo->tmds_setting_info->h_active, | 1922 | else |
| 2240 | viaparinfo->tmds_setting_info-> | 1923 | viafb_dvi_set_mode(&viafbinfo->var, |
| 2241 | v_active), | 1924 | viaparinfo->tmds_setting_info->iga_path); |
| 2242 | video_bpp1, viaparinfo-> | ||
| 2243 | tmds_setting_info->iga_path); | ||
| 2244 | } else { | ||
| 2245 | viafb_dvi_set_mode(viafb_get_mode | ||
| 2246 | (viaparinfo->tmds_setting_info->h_active, | ||
| 2247 | viaparinfo-> | ||
| 2248 | tmds_setting_info->v_active), | ||
| 2249 | video_bpp, viaparinfo-> | ||
| 2250 | tmds_setting_info->iga_path); | ||
| 2251 | } | ||
| 2252 | } | 1925 | } |
| 2253 | 1926 | ||
| 2254 | if (viafb_LCD_ON) { | 1927 | if (viafb_LCD_ON) { |
| 2255 | if (viafb_SAMM_ON && | 1928 | if (viafb_SAMM_ON && |
| 2256 | (viaparinfo->lvds_setting_info->iga_path == IGA2)) { | 1929 | (viaparinfo->lvds_setting_info->iga_path == IGA2)) { |
| 2257 | viaparinfo->lvds_setting_info->bpp = video_bpp1; | 1930 | viaparinfo->lvds_setting_info->bpp = video_bpp1; |
| 2258 | viafb_lcd_set_mode(crt_timing1, viaparinfo-> | 1931 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info, |
| 2259 | lvds_setting_info, | 1932 | &viaparinfo->chip_info->lvds_chip_info); |
| 2260 | &viaparinfo->chip_info->lvds_chip_info); | ||
| 2261 | } else { | 1933 | } else { |
| 2262 | /* IGA1 doesn't have LCD scaling, so set it center. */ | 1934 | /* IGA1 doesn't have LCD scaling, so set it center. */ |
| 2263 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { | 1935 | if (viaparinfo->lvds_setting_info->iga_path == IGA1) { |
| @@ -2265,18 +1937,16 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2265 | LCD_CENTERING; | 1937 | LCD_CENTERING; |
| 2266 | } | 1938 | } |
| 2267 | viaparinfo->lvds_setting_info->bpp = video_bpp; | 1939 | viaparinfo->lvds_setting_info->bpp = video_bpp; |
| 2268 | viafb_lcd_set_mode(crt_timing, viaparinfo-> | 1940 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info, |
| 2269 | lvds_setting_info, | 1941 | &viaparinfo->chip_info->lvds_chip_info); |
| 2270 | &viaparinfo->chip_info->lvds_chip_info); | ||
| 2271 | } | 1942 | } |
| 2272 | } | 1943 | } |
| 2273 | if (viafb_LCD2_ON) { | 1944 | if (viafb_LCD2_ON) { |
| 2274 | if (viafb_SAMM_ON && | 1945 | if (viafb_SAMM_ON && |
| 2275 | (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { | 1946 | (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { |
| 2276 | viaparinfo->lvds_setting_info2->bpp = video_bpp1; | 1947 | viaparinfo->lvds_setting_info2->bpp = video_bpp1; |
| 2277 | viafb_lcd_set_mode(crt_timing1, viaparinfo-> | 1948 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, |
| 2278 | lvds_setting_info2, | 1949 | &viaparinfo->chip_info->lvds_chip_info2); |
| 2279 | &viaparinfo->chip_info->lvds_chip_info2); | ||
| 2280 | } else { | 1950 | } else { |
| 2281 | /* IGA1 doesn't have LCD scaling, so set it center. */ | 1951 | /* IGA1 doesn't have LCD scaling, so set it center. */ |
| 2282 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { | 1952 | if (viaparinfo->lvds_setting_info2->iga_path == IGA1) { |
| @@ -2284,9 +1954,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2284 | LCD_CENTERING; | 1954 | LCD_CENTERING; |
| 2285 | } | 1955 | } |
| 2286 | viaparinfo->lvds_setting_info2->bpp = video_bpp; | 1956 | viaparinfo->lvds_setting_info2->bpp = video_bpp; |
| 2287 | viafb_lcd_set_mode(crt_timing, viaparinfo-> | 1957 | viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, |
| 2288 | lvds_setting_info2, | 1958 | &viaparinfo->chip_info->lvds_chip_info2); |
| 2289 | &viaparinfo->chip_info->lvds_chip_info2); | ||
| 2290 | } | 1959 | } |
| 2291 | } | 1960 | } |
| 2292 | 1961 | ||
| @@ -2296,8 +1965,8 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2296 | 1965 | ||
| 2297 | /* If set mode normally, save resolution information for hot-plug . */ | 1966 | /* If set mode normally, save resolution information for hot-plug . */ |
| 2298 | if (!viafb_hotplug) { | 1967 | if (!viafb_hotplug) { |
| 2299 | viafb_hotplug_Xres = vmode_tbl->crtc[0].crtc.hor_addr; | 1968 | viafb_hotplug_Xres = viafbinfo->var.xres; |
| 2300 | viafb_hotplug_Yres = vmode_tbl->crtc[0].crtc.ver_addr; | 1969 | viafb_hotplug_Yres = viafbinfo->var.yres; |
| 2301 | viafb_hotplug_bpp = video_bpp; | 1970 | viafb_hotplug_bpp = video_bpp; |
| 2302 | viafb_hotplug_refresh = viafb_refresh; | 1971 | viafb_hotplug_refresh = viafb_refresh; |
| 2303 | 1972 | ||
| @@ -2348,42 +2017,14 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | |||
| 2348 | return 1; | 2017 | return 1; |
| 2349 | } | 2018 | } |
| 2350 | 2019 | ||
| 2351 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh) | ||
| 2352 | { | ||
| 2353 | int i; | ||
| 2354 | struct crt_mode_table *best; | ||
| 2355 | struct VideoModeTable *vmode = viafb_get_mode(hres, vres); | ||
| 2356 | |||
| 2357 | if (!vmode) | ||
| 2358 | return RES_640X480_60HZ_PIXCLOCK; | ||
| 2359 | |||
| 2360 | best = &vmode->crtc[0]; | ||
| 2361 | for (i = 1; i < vmode->mode_array; i++) { | ||
| 2362 | if (abs(vmode->crtc[i].refresh_rate - vmode_refresh) | ||
| 2363 | < abs(best->refresh_rate - vmode_refresh)) | ||
| 2364 | best = &vmode->crtc[i]; | ||
| 2365 | } | ||
| 2366 | |||
| 2367 | return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total) | ||
| 2368 | * 1000 / best->refresh_rate; | ||
| 2369 | } | ||
| 2370 | |||
| 2371 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) | 2020 | int viafb_get_refresh(int hres, int vres, u32 long_refresh) |
| 2372 | { | 2021 | { |
| 2373 | int i; | ||
| 2374 | struct crt_mode_table *best; | 2022 | struct crt_mode_table *best; |
| 2375 | struct VideoModeTable *vmode = viafb_get_mode(hres, vres); | ||
| 2376 | 2023 | ||
| 2377 | if (!vmode) | 2024 | best = viafb_get_best_mode(hres, vres, long_refresh); |
| 2025 | if (!best) | ||
| 2378 | return 60; | 2026 | return 60; |
| 2379 | 2027 | ||
| 2380 | best = &vmode->crtc[0]; | ||
| 2381 | for (i = 1; i < vmode->mode_array; i++) { | ||
| 2382 | if (abs(vmode->crtc[i].refresh_rate - long_refresh) | ||
| 2383 | < abs(best->refresh_rate - long_refresh)) | ||
| 2384 | best = &vmode->crtc[i]; | ||
| 2385 | } | ||
| 2386 | |||
| 2387 | if (abs(best->refresh_rate - long_refresh) > 3) { | 2028 | if (abs(best->refresh_rate - long_refresh) > 3) { |
| 2388 | if (hres == 1200 && vres == 900) | 2029 | if (hres == 1200 && vres == 900) |
| 2389 | return 49; /* OLPC DCON only supports 50 Hz */ | 2030 | return 49; /* OLPC DCON only supports 50 Hz */ |
| @@ -2485,21 +2126,14 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | |||
| 2485 | } | 2126 | } |
| 2486 | 2127 | ||
| 2487 | /*According var's xres, yres fill var's other timing information*/ | 2128 | /*According var's xres, yres fill var's other timing information*/ |
| 2488 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 2129 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, |
| 2489 | struct VideoModeTable *vmode_tbl) | 2130 | struct crt_mode_table *mode) |
| 2490 | { | 2131 | { |
| 2491 | struct crt_mode_table *crt_timing = NULL; | ||
| 2492 | struct display_timing crt_reg; | 2132 | struct display_timing crt_reg; |
| 2493 | int i = 0, index = 0; | ||
| 2494 | crt_timing = vmode_tbl->crtc; | ||
| 2495 | for (i = 0; i < vmode_tbl->mode_array; i++) { | ||
| 2496 | index = i; | ||
| 2497 | if (crt_timing[i].refresh_rate == refresh) | ||
| 2498 | break; | ||
| 2499 | } | ||
| 2500 | 2133 | ||
| 2501 | crt_reg = crt_timing[index].crtc; | 2134 | crt_reg = mode->crtc; |
| 2502 | var->pixclock = viafb_get_pixclock(var->xres, var->yres, refresh); | 2135 | var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total) |
| 2136 | * 1000 / mode->refresh_rate; | ||
| 2503 | var->left_margin = | 2137 | var->left_margin = |
| 2504 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); | 2138 | crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); |
| 2505 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; | 2139 | var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; |
| @@ -2509,8 +2143,8 @@ void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | |||
| 2509 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; | 2143 | var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr; |
| 2510 | var->vsync_len = crt_reg.ver_sync_end; | 2144 | var->vsync_len = crt_reg.ver_sync_end; |
| 2511 | var->sync = 0; | 2145 | var->sync = 0; |
| 2512 | if (crt_timing[index].h_sync_polarity == POSITIVE) | 2146 | if (mode->h_sync_polarity == POSITIVE) |
| 2513 | var->sync |= FB_SYNC_HOR_HIGH_ACT; | 2147 | var->sync |= FB_SYNC_HOR_HIGH_ACT; |
| 2514 | if (crt_timing[index].v_sync_polarity == POSITIVE) | 2148 | if (mode->v_sync_polarity == POSITIVE) |
| 2515 | var->sync |= FB_SYNC_VERT_HIGH_ACT; | 2149 | var->sync |= FB_SYNC_VERT_HIGH_ACT; |
| 2516 | } | 2150 | } |
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h index c7239eb83bae..4db5b6e8d8d0 100644 --- a/drivers/video/via/hw.h +++ b/drivers/video/via/hw.h | |||
| @@ -51,40 +51,6 @@ | |||
| 51 | #define VIA_HSYNC_NEGATIVE 0x01 | 51 | #define VIA_HSYNC_NEGATIVE 0x01 |
| 52 | #define VIA_VSYNC_NEGATIVE 0x02 | 52 | #define VIA_VSYNC_NEGATIVE 0x02 |
| 53 | 53 | ||
| 54 | /*************************************************** | ||
| 55 | * Definition IGA1 Design Method of CRTC Registers * | ||
| 56 | ****************************************************/ | ||
| 57 | #define IGA1_HOR_TOTAL_FORMULA(x) (((x)/8)-5) | ||
| 58 | #define IGA1_HOR_ADDR_FORMULA(x) (((x)/8)-1) | ||
| 59 | #define IGA1_HOR_BLANK_START_FORMULA(x) (((x)/8)-1) | ||
| 60 | #define IGA1_HOR_BLANK_END_FORMULA(x, y) (((x+y)/8)-1) | ||
| 61 | #define IGA1_HOR_SYNC_START_FORMULA(x) ((x)/8) | ||
| 62 | #define IGA1_HOR_SYNC_END_FORMULA(x, y) ((x+y)/8) | ||
| 63 | |||
| 64 | #define IGA1_VER_TOTAL_FORMULA(x) ((x)-2) | ||
| 65 | #define IGA1_VER_ADDR_FORMULA(x) ((x)-1) | ||
| 66 | #define IGA1_VER_BLANK_START_FORMULA(x) ((x)-1) | ||
| 67 | #define IGA1_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
| 68 | #define IGA1_VER_SYNC_START_FORMULA(x) ((x)-1) | ||
| 69 | #define IGA1_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
| 70 | |||
| 71 | /*************************************************** | ||
| 72 | ** Definition IGA2 Design Method of CRTC Registers * | ||
| 73 | ****************************************************/ | ||
| 74 | #define IGA2_HOR_TOTAL_FORMULA(x) ((x)-1) | ||
| 75 | #define IGA2_HOR_ADDR_FORMULA(x) ((x)-1) | ||
| 76 | #define IGA2_HOR_BLANK_START_FORMULA(x) ((x)-1) | ||
| 77 | #define IGA2_HOR_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
| 78 | #define IGA2_HOR_SYNC_START_FORMULA(x) ((x)-1) | ||
| 79 | #define IGA2_HOR_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
| 80 | |||
| 81 | #define IGA2_VER_TOTAL_FORMULA(x) ((x)-1) | ||
| 82 | #define IGA2_VER_ADDR_FORMULA(x) ((x)-1) | ||
| 83 | #define IGA2_VER_BLANK_START_FORMULA(x) ((x)-1) | ||
| 84 | #define IGA2_VER_BLANK_END_FORMULA(x, y) ((x+y)-1) | ||
| 85 | #define IGA2_VER_SYNC_START_FORMULA(x) ((x)-1) | ||
| 86 | #define IGA2_VER_SYNC_END_FORMULA(x, y) ((x+y)-1) | ||
| 87 | |||
| 88 | /**********************************************************/ | 54 | /**********************************************************/ |
| 89 | /* Definition IGA2 Design Method of CRTC Shadow Registers */ | 55 | /* Definition IGA2 Design Method of CRTC Shadow Registers */ |
| 90 | /**********************************************************/ | 56 | /**********************************************************/ |
| @@ -97,33 +63,6 @@ | |||
| 97 | #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) | 63 | #define IGA2_VER_SYNC_START_SHADOW_FORMULA(x) (x) |
| 98 | #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) | 64 | #define IGA2_VER_SYNC_END_SHADOW_FORMULA(x, y) (x+y) |
| 99 | 65 | ||
| 100 | /* Define Register Number for IGA1 CRTC Timing */ | ||
| 101 | |||
| 102 | /* location: {CR00,0,7},{CR36,3,3} */ | ||
| 103 | #define IGA1_HOR_TOTAL_REG_NUM 2 | ||
| 104 | /* location: {CR01,0,7} */ | ||
| 105 | #define IGA1_HOR_ADDR_REG_NUM 1 | ||
| 106 | /* location: {CR02,0,7} */ | ||
| 107 | #define IGA1_HOR_BLANK_START_REG_NUM 1 | ||
| 108 | /* location: {CR03,0,4},{CR05,7,7},{CR33,5,5} */ | ||
| 109 | #define IGA1_HOR_BLANK_END_REG_NUM 3 | ||
| 110 | /* location: {CR04,0,7},{CR33,4,4} */ | ||
| 111 | #define IGA1_HOR_SYNC_START_REG_NUM 2 | ||
| 112 | /* location: {CR05,0,4} */ | ||
| 113 | #define IGA1_HOR_SYNC_END_REG_NUM 1 | ||
| 114 | /* location: {CR06,0,7},{CR07,0,0},{CR07,5,5},{CR35,0,0} */ | ||
| 115 | #define IGA1_VER_TOTAL_REG_NUM 4 | ||
| 116 | /* location: {CR12,0,7},{CR07,1,1},{CR07,6,6},{CR35,2,2} */ | ||
| 117 | #define IGA1_VER_ADDR_REG_NUM 4 | ||
| 118 | /* location: {CR15,0,7},{CR07,3,3},{CR09,5,5},{CR35,3,3} */ | ||
| 119 | #define IGA1_VER_BLANK_START_REG_NUM 4 | ||
| 120 | /* location: {CR16,0,7} */ | ||
| 121 | #define IGA1_VER_BLANK_END_REG_NUM 1 | ||
| 122 | /* location: {CR10,0,7},{CR07,2,2},{CR07,7,7},{CR35,1,1} */ | ||
| 123 | #define IGA1_VER_SYNC_START_REG_NUM 4 | ||
| 124 | /* location: {CR11,0,3} */ | ||
| 125 | #define IGA1_VER_SYNC_END_REG_NUM 1 | ||
| 126 | |||
| 127 | /* Define Register Number for IGA2 Shadow CRTC Timing */ | 66 | /* Define Register Number for IGA2 Shadow CRTC Timing */ |
| 128 | 67 | ||
| 129 | /* location: {CR6D,0,7},{CR71,3,3} */ | 68 | /* location: {CR6D,0,7},{CR71,3,3} */ |
| @@ -143,37 +82,6 @@ | |||
| 143 | /* location: {CR76,0,3} */ | 82 | /* location: {CR76,0,3} */ |
| 144 | #define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 | 83 | #define IGA2_SHADOW_VER_SYNC_END_REG_NUM 1 |
| 145 | 84 | ||
| 146 | /* Define Register Number for IGA2 CRTC Timing */ | ||
| 147 | |||
| 148 | /* location: {CR50,0,7},{CR55,0,3} */ | ||
| 149 | #define IGA2_HOR_TOTAL_REG_NUM 2 | ||
| 150 | /* location: {CR51,0,7},{CR55,4,6} */ | ||
| 151 | #define IGA2_HOR_ADDR_REG_NUM 2 | ||
| 152 | /* location: {CR52,0,7},{CR54,0,2} */ | ||
| 153 | #define IGA2_HOR_BLANK_START_REG_NUM 2 | ||
| 154 | /* location: CLE266: {CR53,0,7},{CR54,3,5} => CLE266's CR5D[6] | ||
| 155 | is reserved, so it may have problem to set 1600x1200 on IGA2. */ | ||
| 156 | /* Others: {CR53,0,7},{CR54,3,5},{CR5D,6,6} */ | ||
| 157 | #define IGA2_HOR_BLANK_END_REG_NUM 3 | ||
| 158 | /* location: {CR56,0,7},{CR54,6,7},{CR5C,7,7} */ | ||
| 159 | /* VT3314 and Later: {CR56,0,7},{CR54,6,7},{CR5C,7,7}, {CR5D,7,7} */ | ||
| 160 | #define IGA2_HOR_SYNC_START_REG_NUM 4 | ||
| 161 | |||
| 162 | /* location: {CR57,0,7},{CR5C,6,6} */ | ||
| 163 | #define IGA2_HOR_SYNC_END_REG_NUM 2 | ||
| 164 | /* location: {CR58,0,7},{CR5D,0,2} */ | ||
| 165 | #define IGA2_VER_TOTAL_REG_NUM 2 | ||
| 166 | /* location: {CR59,0,7},{CR5D,3,5} */ | ||
| 167 | #define IGA2_VER_ADDR_REG_NUM 2 | ||
| 168 | /* location: {CR5A,0,7},{CR5C,0,2} */ | ||
| 169 | #define IGA2_VER_BLANK_START_REG_NUM 2 | ||
| 170 | /* location: {CR5E,0,7},{CR5C,3,5} */ | ||
| 171 | #define IGA2_VER_BLANK_END_REG_NUM 2 | ||
| 172 | /* location: {CR5E,0,7},{CR5F,5,7} */ | ||
| 173 | #define IGA2_VER_SYNC_START_REG_NUM 2 | ||
| 174 | /* location: {CR5F,0,4} */ | ||
| 175 | #define IGA2_VER_SYNC_END_REG_NUM 1 | ||
| 176 | |||
| 177 | /* Define Fetch Count Register*/ | 85 | /* Define Fetch Count Register*/ |
| 178 | 86 | ||
| 179 | /* location: {SR1C,0,7},{SR1D,0,1} */ | 87 | /* location: {SR1C,0,7},{SR1D,0,1} */ |
| @@ -446,87 +354,12 @@ is reserved, so it may have problem to set 1600x1200 on IGA2. */ | |||
| 446 | /* location: {CR78,0,7},{CR79,6,7} */ | 354 | /* location: {CR78,0,7},{CR79,6,7} */ |
| 447 | #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 | 355 | #define LCD_VER_SCALING_FACTOR_REG_NUM_CLE 2 |
| 448 | 356 | ||
| 449 | /************************************************ | ||
| 450 | ***** Define IGA1 Display Timing ***** | ||
| 451 | ************************************************/ | ||
| 452 | struct io_register { | 357 | struct io_register { |
| 453 | u8 io_addr; | 358 | u8 io_addr; |
| 454 | u8 start_bit; | 359 | u8 start_bit; |
| 455 | u8 end_bit; | 360 | u8 end_bit; |
| 456 | }; | 361 | }; |
| 457 | 362 | ||
| 458 | /* IGA1 Horizontal Total */ | ||
| 459 | struct iga1_hor_total { | ||
| 460 | int reg_num; | ||
| 461 | struct io_register reg[IGA1_HOR_TOTAL_REG_NUM]; | ||
| 462 | }; | ||
| 463 | |||
| 464 | /* IGA1 Horizontal Addressable Video */ | ||
| 465 | struct iga1_hor_addr { | ||
| 466 | int reg_num; | ||
| 467 | struct io_register reg[IGA1_HOR_ADDR_REG_NUM]; | ||
| 468 | }; | ||
| 469 | |||
| 470 | /* IGA1 Horizontal Blank Start */ | ||
| 471 | struct iga1_hor_blank_start { | ||
| 472 | int reg_num; | ||
| 473 | struct io_register reg[IGA1_HOR_BLANK_START_REG_NUM]; | ||
| 474 | }; | ||
| 475 | |||
| 476 | /* IGA1 Horizontal Blank End */ | ||
| 477 | struct iga1_hor_blank_end { | ||
| 478 | int reg_num; | ||
| 479 | struct io_register reg[IGA1_HOR_BLANK_END_REG_NUM]; | ||
| 480 | }; | ||
| 481 | |||
| 482 | /* IGA1 Horizontal Sync Start */ | ||
| 483 | struct iga1_hor_sync_start { | ||
| 484 | int reg_num; | ||
| 485 | struct io_register reg[IGA1_HOR_SYNC_START_REG_NUM]; | ||
| 486 | }; | ||
| 487 | |||
| 488 | /* IGA1 Horizontal Sync End */ | ||
| 489 | struct iga1_hor_sync_end { | ||
| 490 | int reg_num; | ||
| 491 | struct io_register reg[IGA1_HOR_SYNC_END_REG_NUM]; | ||
| 492 | }; | ||
| 493 | |||
| 494 | /* IGA1 Vertical Total */ | ||
| 495 | struct iga1_ver_total { | ||
| 496 | int reg_num; | ||
| 497 | struct io_register reg[IGA1_VER_TOTAL_REG_NUM]; | ||
| 498 | }; | ||
| 499 | |||
| 500 | /* IGA1 Vertical Addressable Video */ | ||
| 501 | struct iga1_ver_addr { | ||
| 502 | int reg_num; | ||
| 503 | struct io_register reg[IGA1_VER_ADDR_REG_NUM]; | ||
| 504 | }; | ||
| 505 | |||
| 506 | /* IGA1 Vertical Blank Start */ | ||
| 507 | struct iga1_ver_blank_start { | ||
| 508 | int reg_num; | ||
| 509 | struct io_register reg[IGA1_VER_BLANK_START_REG_NUM]; | ||
| 510 | }; | ||
| 511 | |||
| 512 | /* IGA1 Vertical Blank End */ | ||
| 513 | struct iga1_ver_blank_end { | ||
| 514 | int reg_num; | ||
| 515 | struct io_register reg[IGA1_VER_BLANK_END_REG_NUM]; | ||
| 516 | }; | ||
| 517 | |||
| 518 | /* IGA1 Vertical Sync Start */ | ||
| 519 | struct iga1_ver_sync_start { | ||
| 520 | int reg_num; | ||
| 521 | struct io_register reg[IGA1_VER_SYNC_START_REG_NUM]; | ||
| 522 | }; | ||
| 523 | |||
| 524 | /* IGA1 Vertical Sync End */ | ||
| 525 | struct iga1_ver_sync_end { | ||
| 526 | int reg_num; | ||
| 527 | struct io_register reg[IGA1_VER_SYNC_END_REG_NUM]; | ||
| 528 | }; | ||
| 529 | |||
| 530 | /***************************************************** | 363 | /***************************************************** |
| 531 | ** Define IGA2 Shadow Display Timing **** | 364 | ** Define IGA2 Shadow Display Timing **** |
| 532 | *****************************************************/ | 365 | *****************************************************/ |
| @@ -579,82 +412,6 @@ struct iga2_shadow_ver_sync_end { | |||
| 579 | struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; | 412 | struct io_register reg[IGA2_SHADOW_VER_SYNC_END_REG_NUM]; |
| 580 | }; | 413 | }; |
| 581 | 414 | ||
| 582 | /***************************************************** | ||
| 583 | ** Define IGA2 Display Timing **** | ||
| 584 | ******************************************************/ | ||
| 585 | |||
| 586 | /* IGA2 Horizontal Total */ | ||
| 587 | struct iga2_hor_total { | ||
| 588 | int reg_num; | ||
| 589 | struct io_register reg[IGA2_HOR_TOTAL_REG_NUM]; | ||
| 590 | }; | ||
| 591 | |||
| 592 | /* IGA2 Horizontal Addressable Video */ | ||
| 593 | struct iga2_hor_addr { | ||
| 594 | int reg_num; | ||
| 595 | struct io_register reg[IGA2_HOR_ADDR_REG_NUM]; | ||
| 596 | }; | ||
| 597 | |||
| 598 | /* IGA2 Horizontal Blank Start */ | ||
| 599 | struct iga2_hor_blank_start { | ||
| 600 | int reg_num; | ||
| 601 | struct io_register reg[IGA2_HOR_BLANK_START_REG_NUM]; | ||
| 602 | }; | ||
| 603 | |||
| 604 | /* IGA2 Horizontal Blank End */ | ||
| 605 | struct iga2_hor_blank_end { | ||
| 606 | int reg_num; | ||
| 607 | struct io_register reg[IGA2_HOR_BLANK_END_REG_NUM]; | ||
| 608 | }; | ||
| 609 | |||
| 610 | /* IGA2 Horizontal Sync Start */ | ||
| 611 | struct iga2_hor_sync_start { | ||
| 612 | int reg_num; | ||
| 613 | struct io_register reg[IGA2_HOR_SYNC_START_REG_NUM]; | ||
| 614 | }; | ||
| 615 | |||
| 616 | /* IGA2 Horizontal Sync End */ | ||
| 617 | struct iga2_hor_sync_end { | ||
| 618 | int reg_num; | ||
| 619 | struct io_register reg[IGA2_HOR_SYNC_END_REG_NUM]; | ||
| 620 | }; | ||
| 621 | |||
| 622 | /* IGA2 Vertical Total */ | ||
| 623 | struct iga2_ver_total { | ||
| 624 | int reg_num; | ||
| 625 | struct io_register reg[IGA2_VER_TOTAL_REG_NUM]; | ||
| 626 | }; | ||
| 627 | |||
| 628 | /* IGA2 Vertical Addressable Video */ | ||
| 629 | struct iga2_ver_addr { | ||
| 630 | int reg_num; | ||
| 631 | struct io_register reg[IGA2_VER_ADDR_REG_NUM]; | ||
| 632 | }; | ||
| 633 | |||
| 634 | /* IGA2 Vertical Blank Start */ | ||
| 635 | struct iga2_ver_blank_start { | ||
| 636 | int reg_num; | ||
| 637 | struct io_register reg[IGA2_VER_BLANK_START_REG_NUM]; | ||
| 638 | }; | ||
| 639 | |||
| 640 | /* IGA2 Vertical Blank End */ | ||
| 641 | struct iga2_ver_blank_end { | ||
| 642 | int reg_num; | ||
| 643 | struct io_register reg[IGA2_VER_BLANK_END_REG_NUM]; | ||
| 644 | }; | ||
| 645 | |||
| 646 | /* IGA2 Vertical Sync Start */ | ||
| 647 | struct iga2_ver_sync_start { | ||
| 648 | int reg_num; | ||
| 649 | struct io_register reg[IGA2_VER_SYNC_START_REG_NUM]; | ||
| 650 | }; | ||
| 651 | |||
| 652 | /* IGA2 Vertical Sync End */ | ||
| 653 | struct iga2_ver_sync_end { | ||
| 654 | int reg_num; | ||
| 655 | struct io_register reg[IGA2_VER_SYNC_END_REG_NUM]; | ||
| 656 | }; | ||
| 657 | |||
| 658 | /* IGA1 Fetch Count Register */ | 415 | /* IGA1 Fetch Count Register */ |
| 659 | struct iga1_fetch_count { | 416 | struct iga1_fetch_count { |
| 660 | int reg_num; | 417 | int reg_num; |
| @@ -817,21 +574,6 @@ struct display_queue_expire_num { | |||
| 817 | iga2_display_queue_expire_num_reg; | 574 | iga2_display_queue_expire_num_reg; |
| 818 | }; | 575 | }; |
| 819 | 576 | ||
| 820 | struct iga1_crtc_timing { | ||
| 821 | struct iga1_hor_total hor_total; | ||
| 822 | struct iga1_hor_addr hor_addr; | ||
| 823 | struct iga1_hor_blank_start hor_blank_start; | ||
| 824 | struct iga1_hor_blank_end hor_blank_end; | ||
| 825 | struct iga1_hor_sync_start hor_sync_start; | ||
| 826 | struct iga1_hor_sync_end hor_sync_end; | ||
| 827 | struct iga1_ver_total ver_total; | ||
| 828 | struct iga1_ver_addr ver_addr; | ||
| 829 | struct iga1_ver_blank_start ver_blank_start; | ||
| 830 | struct iga1_ver_blank_end ver_blank_end; | ||
| 831 | struct iga1_ver_sync_start ver_sync_start; | ||
| 832 | struct iga1_ver_sync_end ver_sync_end; | ||
| 833 | }; | ||
| 834 | |||
| 835 | struct iga2_shadow_crtc_timing { | 577 | struct iga2_shadow_crtc_timing { |
| 836 | struct iga2_shadow_hor_total hor_total_shadow; | 578 | struct iga2_shadow_hor_total hor_total_shadow; |
| 837 | struct iga2_shadow_hor_blank_end hor_blank_end_shadow; | 579 | struct iga2_shadow_hor_blank_end hor_blank_end_shadow; |
| @@ -843,21 +585,6 @@ struct iga2_shadow_crtc_timing { | |||
| 843 | struct iga2_shadow_ver_sync_end ver_sync_end_shadow; | 585 | struct iga2_shadow_ver_sync_end ver_sync_end_shadow; |
| 844 | }; | 586 | }; |
| 845 | 587 | ||
| 846 | struct iga2_crtc_timing { | ||
| 847 | struct iga2_hor_total hor_total; | ||
| 848 | struct iga2_hor_addr hor_addr; | ||
| 849 | struct iga2_hor_blank_start hor_blank_start; | ||
| 850 | struct iga2_hor_blank_end hor_blank_end; | ||
| 851 | struct iga2_hor_sync_start hor_sync_start; | ||
| 852 | struct iga2_hor_sync_end hor_sync_end; | ||
| 853 | struct iga2_ver_total ver_total; | ||
| 854 | struct iga2_ver_addr ver_addr; | ||
| 855 | struct iga2_ver_blank_start ver_blank_start; | ||
| 856 | struct iga2_ver_blank_end ver_blank_end; | ||
| 857 | struct iga2_ver_sync_start ver_sync_start; | ||
| 858 | struct iga2_ver_sync_end ver_sync_end; | ||
| 859 | }; | ||
| 860 | |||
| 861 | /* device ID */ | 588 | /* device ID */ |
| 862 | #define CLE266_FUNCTION3 0x3123 | 589 | #define CLE266_FUNCTION3 0x3123 |
| 863 | #define KM400_FUNCTION3 0x3205 | 590 | #define KM400_FUNCTION3 0x3205 |
| @@ -910,9 +637,7 @@ extern int viafb_LCD_ON; | |||
| 910 | extern int viafb_DVI_ON; | 637 | extern int viafb_DVI_ON; |
| 911 | extern int viafb_hotplug; | 638 | extern int viafb_hotplug; |
| 912 | 639 | ||
| 913 | void viafb_fill_crtc_timing(struct crt_mode_table *crt_table, | 640 | void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); |
| 914 | struct VideoModeTable *video_mode, int bpp_byte, int set_iga); | ||
| 915 | |||
| 916 | void viafb_set_vclock(u32 CLK, int set_iga); | 641 | void viafb_set_vclock(u32 CLK, int set_iga); |
| 917 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, | 642 | void viafb_load_reg(int timing_value, int viafb_load_reg_num, |
| 918 | struct io_register *reg, | 643 | struct io_register *reg, |
| @@ -932,13 +657,11 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active); | |||
| 932 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ | 657 | void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ |
| 933 | *p_gfx_dpa_setting); | 658 | *p_gfx_dpa_setting); |
| 934 | 659 | ||
| 935 | int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp, | 660 | int viafb_setmode(int video_bpp, int video_bpp1); |
| 936 | struct VideoModeTable *vmode_tbl1, int video_bpp1); | 661 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, |
| 937 | void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, int refresh, | 662 | struct crt_mode_table *mode); |
| 938 | struct VideoModeTable *vmode_tbl); | ||
| 939 | void __devinit viafb_init_chip_info(int chip_type); | 663 | void __devinit viafb_init_chip_info(int chip_type); |
| 940 | void __devinit viafb_init_dac(int set_iga); | 664 | void __devinit viafb_init_dac(int set_iga); |
| 941 | int viafb_get_pixclock(int hres, int vres, int vmode_refresh); | ||
| 942 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); | 665 | int viafb_get_refresh(int hres, int vres, u32 float_refresh); |
| 943 | void viafb_update_device_setting(int hres, int vres, int bpp, int flag); | 666 | void viafb_update_device_setting(int hres, int vres, int bpp, int flag); |
| 944 | 667 | ||
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c index 6e06981d638b..5f3b4e394e82 100644 --- a/drivers/video/via/lcd.c +++ b/drivers/video/via/lcd.c | |||
| @@ -548,9 +548,8 @@ static void lcd_patch_skew(struct lvds_setting_information | |||
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | /* LCD Set Mode */ | 550 | /* LCD Set Mode */ |
| 551 | void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | 551 | void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, |
| 552 | struct lvds_setting_information *plvds_setting_info, | 552 | struct lvds_chip_information *plvds_chip_info) |
| 553 | struct lvds_chip_information *plvds_chip_info) | ||
| 554 | { | 553 | { |
| 555 | int set_iga = plvds_setting_info->iga_path; | 554 | int set_iga = plvds_setting_info->iga_path; |
| 556 | int mode_bpp = plvds_setting_info->bpp; | 555 | int mode_bpp = plvds_setting_info->bpp; |
| @@ -559,16 +558,15 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
| 559 | int panel_hres = plvds_setting_info->lcd_panel_hres; | 558 | int panel_hres = plvds_setting_info->lcd_panel_hres; |
| 560 | int panel_vres = plvds_setting_info->lcd_panel_vres; | 559 | int panel_vres = plvds_setting_info->lcd_panel_vres; |
| 561 | u32 clock; | 560 | u32 clock; |
| 562 | struct display_timing mode_crt_reg, panel_crt_reg; | 561 | struct display_timing mode_crt_reg, panel_crt_reg, timing; |
| 563 | struct crt_mode_table *panel_crt_table = NULL; | 562 | struct crt_mode_table *mode_crt_table, *panel_crt_table; |
| 564 | struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres, | ||
| 565 | panel_vres); | ||
| 566 | 563 | ||
| 567 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); | 564 | DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); |
| 568 | /* Get mode table */ | 565 | /* Get mode table */ |
| 566 | mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60); | ||
| 569 | mode_crt_reg = mode_crt_table->crtc; | 567 | mode_crt_reg = mode_crt_table->crtc; |
| 570 | /* Get panel table Pointer */ | 568 | /* Get panel table Pointer */ |
| 571 | panel_crt_table = vmode_tbl->crtc; | 569 | panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60); |
| 572 | panel_crt_reg = panel_crt_table->crtc; | 570 | panel_crt_reg = panel_crt_table->crtc; |
| 573 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); | 571 | DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); |
| 574 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) | 572 | if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) |
| @@ -576,31 +574,28 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | |||
| 576 | clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total | 574 | clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total |
| 577 | * panel_crt_table->refresh_rate; | 575 | * panel_crt_table->refresh_rate; |
| 578 | plvds_setting_info->vclk = clock; | 576 | plvds_setting_info->vclk = clock; |
| 579 | if (set_iga == IGA1) { | 577 | |
| 580 | /* IGA1 doesn't have LCD scaling, so set it as centering. */ | 578 | if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres) |
| 581 | viafb_load_crtc_timing(lcd_centering_timging | 579 | && plvds_setting_info->display_method == LCD_EXPANDSION) { |
| 582 | (mode_crt_reg, panel_crt_reg), IGA1); | 580 | timing = panel_crt_reg; |
| 581 | load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres); | ||
| 583 | } else { | 582 | } else { |
| 584 | /* Expansion */ | 583 | timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg); |
| 585 | if (plvds_setting_info->display_method == LCD_EXPANDSION | 584 | if (set_iga == IGA2) |
| 586 | && (set_hres < panel_hres || set_vres < panel_vres)) { | 585 | /* disable scaling */ |
| 587 | /* expansion timing IGA2 loaded panel set timing*/ | 586 | via_write_reg_mask(VIACR, 0x79, 0x00, |
| 588 | viafb_load_crtc_timing(panel_crt_reg, IGA2); | ||
| 589 | DEBUG_MSG(KERN_INFO "viafb_load_crtc_timing!!\n"); | ||
| 590 | load_lcd_scaling(set_hres, set_vres, panel_hres, | ||
| 591 | panel_vres); | ||
| 592 | DEBUG_MSG(KERN_INFO "load_lcd_scaling!!\n"); | ||
| 593 | } else { /* Centering */ | ||
| 594 | /* centering timing IGA2 always loaded panel | ||
| 595 | and mode releative timing */ | ||
| 596 | viafb_load_crtc_timing(lcd_centering_timging | ||
| 597 | (mode_crt_reg, panel_crt_reg), IGA2); | ||
| 598 | viafb_write_reg_mask(CR79, VIACR, 0x00, | ||
| 599 | BIT0 + BIT1 + BIT2); | 587 | BIT0 + BIT1 + BIT2); |
| 600 | /* LCD scaling disabled */ | ||
| 601 | } | ||
| 602 | } | 588 | } |
| 603 | 589 | ||
| 590 | timing.hor_blank_end += timing.hor_blank_start; | ||
| 591 | timing.hor_sync_end += timing.hor_sync_start; | ||
| 592 | timing.ver_blank_end += timing.ver_blank_start; | ||
| 593 | timing.ver_sync_end += timing.ver_sync_start; | ||
| 594 | if (set_iga == IGA1) | ||
| 595 | via_set_primary_timing(&timing); | ||
| 596 | else if (set_iga == IGA2) | ||
| 597 | via_set_secondary_timing(&timing); | ||
| 598 | |||
| 604 | /* Fetch count for IGA2 only */ | 599 | /* Fetch count for IGA2 only */ |
| 605 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); | 600 | viafb_load_fetch_count_reg(set_hres, mode_bpp / 8, set_iga); |
| 606 | 601 | ||
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h index 75f60a655b0e..77ca7b862e68 100644 --- a/drivers/video/via/lcd.h +++ b/drivers/video/via/lcd.h | |||
| @@ -76,16 +76,13 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information | |||
| 76 | *plvds_chip_info, | 76 | *plvds_chip_info, |
| 77 | struct lvds_setting_information | 77 | struct lvds_setting_information |
| 78 | *plvds_setting_info); | 78 | *plvds_setting_info); |
| 79 | void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table, | 79 | void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, |
| 80 | struct lvds_setting_information *plvds_setting_info, | 80 | struct lvds_chip_information *plvds_chip_info); |
| 81 | struct lvds_chip_information *plvds_chip_info); | ||
| 82 | bool __devinit viafb_lvds_trasmitter_identify(void); | 81 | bool __devinit viafb_lvds_trasmitter_identify(void); |
| 83 | void viafb_init_lvds_output_interface(struct lvds_chip_information | 82 | void viafb_init_lvds_output_interface(struct lvds_chip_information |
| 84 | *plvds_chip_info, | 83 | *plvds_chip_info, |
| 85 | struct lvds_setting_information | 84 | struct lvds_setting_information |
| 86 | *plvds_setting_info); | 85 | *plvds_setting_info); |
| 87 | bool viafb_lcd_get_mobile_state(bool *mobile); | 86 | bool viafb_lcd_get_mobile_state(bool *mobile); |
| 88 | void viafb_load_crtc_timing(struct display_timing device_timing, | ||
| 89 | int set_iga); | ||
| 90 | 87 | ||
| 91 | #endif /* __LCD_H__ */ | 88 | #endif /* __LCD_H__ */ |
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h index 61b0bd596b85..69d882cbe709 100644 --- a/drivers/video/via/share.h +++ b/drivers/video/via/share.h | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #ifndef __SHARE_H__ | 22 | #ifndef __SHARE_H__ |
| 23 | #define __SHARE_H__ | 23 | #define __SHARE_H__ |
| 24 | 24 | ||
| 25 | #include "via_modesetting.h" | ||
| 26 | |||
| 25 | /* Define Bit Field */ | 27 | /* Define Bit Field */ |
| 26 | #define BIT0 0x01 | 28 | #define BIT0 0x01 |
| 27 | #define BIT1 0x02 | 29 | #define BIT1 0x02 |
| @@ -634,10 +636,6 @@ | |||
| 634 | #define V_SYNC_SATRT_SHADOW_INDEX 18 | 636 | #define V_SYNC_SATRT_SHADOW_INDEX 18 |
| 635 | #define V_SYNC_END_SHADOW_INDEX 19 | 637 | #define V_SYNC_END_SHADOW_INDEX 19 |
| 636 | 638 | ||
| 637 | /* Definition Video Mode Pixel Clock (picoseconds) | ||
| 638 | */ | ||
| 639 | #define RES_640X480_60HZ_PIXCLOCK 39722 | ||
| 640 | |||
| 641 | /* LCD display method | 639 | /* LCD display method |
| 642 | */ | 640 | */ |
| 643 | #define LCD_EXPANDSION 0x00 | 641 | #define LCD_EXPANDSION 0x00 |
| @@ -648,23 +646,6 @@ | |||
| 648 | #define LCD_OPENLDI 0x00 | 646 | #define LCD_OPENLDI 0x00 |
| 649 | #define LCD_SPWG 0x01 | 647 | #define LCD_SPWG 0x01 |
| 650 | 648 | ||
| 651 | /* Define display timing | ||
| 652 | */ | ||
| 653 | struct display_timing { | ||
| 654 | u16 hor_total; | ||
| 655 | u16 hor_addr; | ||
| 656 | u16 hor_blank_start; | ||
| 657 | u16 hor_blank_end; | ||
| 658 | u16 hor_sync_start; | ||
| 659 | u16 hor_sync_end; | ||
| 660 | u16 ver_total; | ||
| 661 | u16 ver_addr; | ||
| 662 | u16 ver_blank_start; | ||
| 663 | u16 ver_blank_end; | ||
| 664 | u16 ver_sync_start; | ||
| 665 | u16 ver_sync_end; | ||
| 666 | }; | ||
| 667 | |||
| 668 | struct crt_mode_table { | 649 | struct crt_mode_table { |
| 669 | int refresh_rate; | 650 | int refresh_rate; |
| 670 | int h_sync_polarity; | 651 | int h_sync_polarity; |
diff --git a/drivers/video/via/via-core.c b/drivers/video/via/via-core.c index eb112b621735..dd58b530c0df 100644 --- a/drivers/video/via/via-core.c +++ b/drivers/video/via/via-core.c | |||
| @@ -35,7 +35,7 @@ static struct via_port_cfg adap_configs[] = { | |||
| 35 | * The OLPC XO-1.5 puts the camera power and reset lines onto | 35 | * The OLPC XO-1.5 puts the camera power and reset lines onto |
| 36 | * GPIO 2C. | 36 | * GPIO 2C. |
| 37 | */ | 37 | */ |
| 38 | static const struct via_port_cfg olpc_adap_configs[] = { | 38 | static struct via_port_cfg olpc_adap_configs[] = { |
| 39 | [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, | 39 | [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 }, |
| 40 | [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, | 40 | [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 }, |
| 41 | [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, | 41 | [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 }, |
diff --git a/drivers/video/via/via-gpio.c b/drivers/video/via/via-gpio.c index ab5341814c74..d69cfef7c338 100644 --- a/drivers/video/via/via-gpio.c +++ b/drivers/video/via/via-gpio.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
| 11 | #include <linux/via-core.h> | 11 | #include <linux/via-core.h> |
| 12 | #include <linux/via-gpio.h> | 12 | #include <linux/via-gpio.h> |
| 13 | #include <linux/export.h> | ||
| 13 | 14 | ||
| 14 | /* | 15 | /* |
| 15 | * The ports we know about. Note that the port-25 gpios are not | 16 | * The ports we know about. Note that the port-25 gpios are not |
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c index 3cddcff88ab9..0e431aee17bb 100644 --- a/drivers/video/via/via_modesetting.c +++ b/drivers/video/via/via_modesetting.c | |||
| @@ -29,6 +29,110 @@ | |||
| 29 | #include "share.h" | 29 | #include "share.h" |
| 30 | #include "debug.h" | 30 | #include "debug.h" |
| 31 | 31 | ||
| 32 | |||
| 33 | void via_set_primary_timing(const struct display_timing *timing) | ||
| 34 | { | ||
| 35 | struct display_timing raw; | ||
| 36 | |||
| 37 | raw.hor_total = timing->hor_total / 8 - 5; | ||
| 38 | raw.hor_addr = timing->hor_addr / 8 - 1; | ||
| 39 | raw.hor_blank_start = timing->hor_blank_start / 8 - 1; | ||
| 40 | raw.hor_blank_end = timing->hor_blank_end / 8 - 1; | ||
| 41 | raw.hor_sync_start = timing->hor_sync_start / 8; | ||
| 42 | raw.hor_sync_end = timing->hor_sync_end / 8; | ||
| 43 | raw.ver_total = timing->ver_total - 2; | ||
| 44 | raw.ver_addr = timing->ver_addr - 1; | ||
| 45 | raw.ver_blank_start = timing->ver_blank_start - 1; | ||
| 46 | raw.ver_blank_end = timing->ver_blank_end - 1; | ||
| 47 | raw.ver_sync_start = timing->ver_sync_start - 1; | ||
| 48 | raw.ver_sync_end = timing->ver_sync_end - 1; | ||
| 49 | |||
| 50 | /* unlock timing registers */ | ||
| 51 | via_write_reg_mask(VIACR, 0x11, 0x00, 0x80); | ||
| 52 | |||
| 53 | via_write_reg(VIACR, 0x00, raw.hor_total & 0xFF); | ||
| 54 | via_write_reg(VIACR, 0x01, raw.hor_addr & 0xFF); | ||
| 55 | via_write_reg(VIACR, 0x02, raw.hor_blank_start & 0xFF); | ||
| 56 | via_write_reg_mask(VIACR, 0x03, raw.hor_blank_end & 0x1F, 0x1F); | ||
| 57 | via_write_reg(VIACR, 0x04, raw.hor_sync_start & 0xFF); | ||
| 58 | via_write_reg_mask(VIACR, 0x05, (raw.hor_sync_end & 0x1F) | ||
| 59 | | (raw.hor_blank_end << (7 - 5) & 0x80), 0x9F); | ||
| 60 | via_write_reg(VIACR, 0x06, raw.ver_total & 0xFF); | ||
| 61 | via_write_reg_mask(VIACR, 0x07, (raw.ver_total >> 8 & 0x01) | ||
| 62 | | (raw.ver_addr >> (8 - 1) & 0x02) | ||
| 63 | | (raw.ver_sync_start >> (8 - 2) & 0x04) | ||
| 64 | | (raw.ver_blank_start >> (8 - 3) & 0x08) | ||
| 65 | | (raw.ver_total >> (9 - 5) & 0x20) | ||
| 66 | | (raw.ver_addr >> (9 - 6) & 0x40) | ||
| 67 | | (raw.ver_sync_start >> (9 - 7) & 0x80), 0xEF); | ||
| 68 | via_write_reg_mask(VIACR, 0x09, raw.ver_blank_start >> (9 - 5) & 0x20, | ||
| 69 | 0x20); | ||
| 70 | via_write_reg(VIACR, 0x10, raw.ver_sync_start & 0xFF); | ||
| 71 | via_write_reg_mask(VIACR, 0x11, raw.ver_sync_end & 0x0F, 0x0F); | ||
| 72 | via_write_reg(VIACR, 0x12, raw.ver_addr & 0xFF); | ||
| 73 | via_write_reg(VIACR, 0x15, raw.ver_blank_start & 0xFF); | ||
| 74 | via_write_reg(VIACR, 0x16, raw.ver_blank_end & 0xFF); | ||
| 75 | via_write_reg_mask(VIACR, 0x33, (raw.hor_sync_start >> (8 - 4) & 0x10) | ||
| 76 | | (raw.hor_blank_end >> (6 - 5) & 0x20), 0x30); | ||
| 77 | via_write_reg_mask(VIACR, 0x35, (raw.ver_total >> 10 & 0x01) | ||
| 78 | | (raw.ver_sync_start >> (10 - 1) & 0x02) | ||
| 79 | | (raw.ver_addr >> (10 - 2) & 0x04) | ||
| 80 | | (raw.ver_blank_start >> (10 - 3) & 0x08), 0x0F); | ||
| 81 | via_write_reg_mask(VIACR, 0x36, raw.hor_total >> (8 - 3) & 0x08, 0x08); | ||
| 82 | |||
| 83 | /* lock timing registers */ | ||
| 84 | via_write_reg_mask(VIACR, 0x11, 0x80, 0x80); | ||
| 85 | |||
| 86 | /* reset timing control */ | ||
| 87 | via_write_reg_mask(VIACR, 0x17, 0x00, 0x80); | ||
| 88 | via_write_reg_mask(VIACR, 0x17, 0x80, 0x80); | ||
| 89 | } | ||
| 90 | |||
| 91 | void via_set_secondary_timing(const struct display_timing *timing) | ||
| 92 | { | ||
| 93 | struct display_timing raw; | ||
| 94 | |||
| 95 | raw.hor_total = timing->hor_total - 1; | ||
| 96 | raw.hor_addr = timing->hor_addr - 1; | ||
| 97 | raw.hor_blank_start = timing->hor_blank_start - 1; | ||
| 98 | raw.hor_blank_end = timing->hor_blank_end - 1; | ||
| 99 | raw.hor_sync_start = timing->hor_sync_start - 1; | ||
| 100 | raw.hor_sync_end = timing->hor_sync_end - 1; | ||
| 101 | raw.ver_total = timing->ver_total - 1; | ||
| 102 | raw.ver_addr = timing->ver_addr - 1; | ||
| 103 | raw.ver_blank_start = timing->ver_blank_start - 1; | ||
| 104 | raw.ver_blank_end = timing->ver_blank_end - 1; | ||
| 105 | raw.ver_sync_start = timing->ver_sync_start - 1; | ||
| 106 | raw.ver_sync_end = timing->ver_sync_end - 1; | ||
| 107 | |||
| 108 | via_write_reg(VIACR, 0x50, raw.hor_total & 0xFF); | ||
| 109 | via_write_reg(VIACR, 0x51, raw.hor_addr & 0xFF); | ||
| 110 | via_write_reg(VIACR, 0x52, raw.hor_blank_start & 0xFF); | ||
| 111 | via_write_reg(VIACR, 0x53, raw.hor_blank_end & 0xFF); | ||
| 112 | via_write_reg(VIACR, 0x54, (raw.hor_blank_start >> 8 & 0x07) | ||
| 113 | | (raw.hor_blank_end >> (8 - 3) & 0x38) | ||
| 114 | | (raw.hor_sync_start >> (8 - 6) & 0xC0)); | ||
| 115 | via_write_reg_mask(VIACR, 0x55, (raw.hor_total >> 8 & 0x0F) | ||
| 116 | | (raw.hor_addr >> (8 - 4) & 0x70), 0x7F); | ||
| 117 | via_write_reg(VIACR, 0x56, raw.hor_sync_start & 0xFF); | ||
| 118 | via_write_reg(VIACR, 0x57, raw.hor_sync_end & 0xFF); | ||
| 119 | via_write_reg(VIACR, 0x58, raw.ver_total & 0xFF); | ||
| 120 | via_write_reg(VIACR, 0x59, raw.ver_addr & 0xFF); | ||
| 121 | via_write_reg(VIACR, 0x5A, raw.ver_blank_start & 0xFF); | ||
| 122 | via_write_reg(VIACR, 0x5B, raw.ver_blank_end & 0xFF); | ||
| 123 | via_write_reg(VIACR, 0x5C, (raw.ver_blank_start >> 8 & 0x07) | ||
| 124 | | (raw.ver_blank_end >> (8 - 3) & 0x38) | ||
| 125 | | (raw.hor_sync_end >> (8 - 6) & 0x40) | ||
| 126 | | (raw.hor_sync_start >> (10 - 7) & 0x80)); | ||
| 127 | via_write_reg(VIACR, 0x5D, (raw.ver_total >> 8 & 0x07) | ||
| 128 | | (raw.ver_addr >> (8 - 3) & 0x38) | ||
| 129 | | (raw.hor_blank_end >> (11 - 6) & 0x40) | ||
| 130 | | (raw.hor_sync_start >> (11 - 7) & 0x80)); | ||
| 131 | via_write_reg(VIACR, 0x5E, raw.ver_sync_start & 0xFF); | ||
| 132 | via_write_reg(VIACR, 0x5F, (raw.ver_sync_end & 0x1F) | ||
| 133 | | (raw.ver_sync_start >> (8 - 5) & 0xE0)); | ||
| 134 | } | ||
| 135 | |||
| 32 | void via_set_primary_address(u32 addr) | 136 | void via_set_primary_address(u32 addr) |
| 33 | { | 137 | { |
| 34 | DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); | 138 | DEBUG_MSG(KERN_DEBUG "via_set_primary_address(0x%08X)\n", addr); |
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h index ae35cfdeb37c..06e09fe351ae 100644 --- a/drivers/video/via/via_modesetting.h +++ b/drivers/video/via/via_modesetting.h | |||
| @@ -28,6 +28,29 @@ | |||
| 28 | 28 | ||
| 29 | #include <linux/types.h> | 29 | #include <linux/types.h> |
| 30 | 30 | ||
| 31 | |||
| 32 | #define VIA_PITCH_SIZE (1<<3) | ||
| 33 | #define VIA_PITCH_MAX 0x3FF8 | ||
| 34 | |||
| 35 | |||
| 36 | struct display_timing { | ||
| 37 | u16 hor_total; | ||
| 38 | u16 hor_addr; | ||
| 39 | u16 hor_blank_start; | ||
| 40 | u16 hor_blank_end; | ||
| 41 | u16 hor_sync_start; | ||
| 42 | u16 hor_sync_end; | ||
| 43 | u16 ver_total; | ||
| 44 | u16 ver_addr; | ||
| 45 | u16 ver_blank_start; | ||
| 46 | u16 ver_blank_end; | ||
| 47 | u16 ver_sync_start; | ||
| 48 | u16 ver_sync_end; | ||
| 49 | }; | ||
| 50 | |||
| 51 | |||
| 52 | void via_set_primary_timing(const struct display_timing *timing); | ||
| 53 | void via_set_secondary_timing(const struct display_timing *timing); | ||
| 31 | void via_set_primary_address(u32 addr); | 54 | void via_set_primary_address(u32 addr); |
| 32 | void via_set_secondary_address(u32 addr); | 55 | void via_set_secondary_address(u32 addr); |
| 33 | void via_set_primary_pitch(u32 pitch); | 56 | void via_set_primary_pitch(u32 pitch); |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 53aa4430d86e..a13c258bd32f 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
| @@ -38,8 +38,6 @@ static char *viafb_mode1; | |||
| 38 | static int viafb_bpp = 32; | 38 | static int viafb_bpp = 32; |
| 39 | static int viafb_bpp1 = 32; | 39 | static int viafb_bpp1 = 32; |
| 40 | 40 | ||
| 41 | static unsigned int viafb_second_xres = 640; | ||
| 42 | static unsigned int viafb_second_yres = 480; | ||
| 43 | static unsigned int viafb_second_offset; | 41 | static unsigned int viafb_second_offset; |
| 44 | static int viafb_second_size; | 42 | static int viafb_second_size; |
| 45 | 43 | ||
| @@ -151,7 +149,8 @@ static void viafb_update_fix(struct fb_info *info) | |||
| 151 | 149 | ||
| 152 | info->fix.visual = | 150 | info->fix.visual = |
| 153 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | 151 | bpp == 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; |
| 154 | info->fix.line_length = (info->var.xres_virtual * bpp / 8 + 7) & ~7; | 152 | info->fix.line_length = ALIGN(info->var.xres_virtual * bpp / 8, |
| 153 | VIA_PITCH_SIZE); | ||
| 155 | } | 154 | } |
| 156 | 155 | ||
| 157 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, | 156 | static void viafb_setup_fixinfo(struct fb_fix_screeninfo *fix, |
| @@ -200,7 +199,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
| 200 | struct fb_info *info) | 199 | struct fb_info *info) |
| 201 | { | 200 | { |
| 202 | int depth, refresh; | 201 | int depth, refresh; |
| 203 | struct VideoModeTable *vmode_entry; | ||
| 204 | struct viafb_par *ppar = info->par; | 202 | struct viafb_par *ppar = info->par; |
| 205 | u32 line; | 203 | u32 line; |
| 206 | 204 | ||
| @@ -210,8 +208,10 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
| 210 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) | 208 | if (var->vmode & FB_VMODE_INTERLACED || var->vmode & FB_VMODE_DOUBLE) |
| 211 | return -EINVAL; | 209 | return -EINVAL; |
| 212 | 210 | ||
| 213 | vmode_entry = viafb_get_mode(var->xres, var->yres); | 211 | /* the refresh rate is not important here, as we only want to know |
| 214 | if (!vmode_entry) { | 212 | * whether the resolution exists |
| 213 | */ | ||
| 214 | if (!viafb_get_best_mode(var->xres, var->yres, 60)) { | ||
| 215 | DEBUG_MSG(KERN_INFO | 215 | DEBUG_MSG(KERN_INFO |
| 216 | "viafb: Mode %dx%dx%d not supported!!\n", | 216 | "viafb: Mode %dx%dx%d not supported!!\n", |
| 217 | var->xres, var->yres, var->bits_per_pixel); | 217 | var->xres, var->yres, var->bits_per_pixel); |
| @@ -238,8 +238,12 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
| 238 | depth = 24; | 238 | depth = 24; |
| 239 | 239 | ||
| 240 | viafb_fill_var_color_info(var, depth); | 240 | viafb_fill_var_color_info(var, depth); |
| 241 | line = (var->xres_virtual * var->bits_per_pixel / 8 + 7) & ~7; | 241 | if (var->xres_virtual < var->xres) |
| 242 | if (line * var->yres_virtual > ppar->memsize) | 242 | var->xres_virtual = var->xres; |
| 243 | |||
| 244 | line = ALIGN(var->xres_virtual * var->bits_per_pixel / 8, | ||
| 245 | VIA_PITCH_SIZE); | ||
| 246 | if (line > VIA_PITCH_MAX || line * var->yres_virtual > ppar->memsize) | ||
| 243 | return -EINVAL; | 247 | return -EINVAL; |
| 244 | 248 | ||
| 245 | /* Based on var passed in to calculate the refresh, | 249 | /* Based on var passed in to calculate the refresh, |
| @@ -249,7 +253,8 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
| 249 | get_var_refresh(var)); | 253 | get_var_refresh(var)); |
| 250 | 254 | ||
| 251 | /* Adjust var according to our driver's own table */ | 255 | /* Adjust var according to our driver's own table */ |
| 252 | viafb_fill_var_timing_info(var, refresh, vmode_entry); | 256 | viafb_fill_var_timing_info(var, |
| 257 | viafb_get_best_mode(var->xres, var->yres, refresh)); | ||
| 253 | if (var->accel_flags & FB_ACCELF_TEXT && | 258 | if (var->accel_flags & FB_ACCELF_TEXT && |
| 254 | !ppar->shared->vdev->engine_mmio) | 259 | !ppar->shared->vdev->engine_mmio) |
| 255 | var->accel_flags = 0; | 260 | var->accel_flags = 0; |
| @@ -260,7 +265,6 @@ static int viafb_check_var(struct fb_var_screeninfo *var, | |||
| 260 | static int viafb_set_par(struct fb_info *info) | 265 | static int viafb_set_par(struct fb_info *info) |
| 261 | { | 266 | { |
| 262 | struct viafb_par *viapar = info->par; | 267 | struct viafb_par *viapar = info->par; |
| 263 | struct VideoModeTable *vmode_entry, *vmode_entry1 = NULL; | ||
| 264 | int refresh; | 268 | int refresh; |
| 265 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); | 269 | DEBUG_MSG(KERN_INFO "viafb_set_par!\n"); |
| 266 | 270 | ||
| @@ -269,10 +273,7 @@ static int viafb_set_par(struct fb_info *info) | |||
| 269 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, | 273 | viafb_update_device_setting(viafbinfo->var.xres, viafbinfo->var.yres, |
| 270 | viafbinfo->var.bits_per_pixel, 0); | 274 | viafbinfo->var.bits_per_pixel, 0); |
| 271 | 275 | ||
| 272 | vmode_entry = viafb_get_mode(viafbinfo->var.xres, viafbinfo->var.yres); | ||
| 273 | if (viafb_dual_fb) { | 276 | if (viafb_dual_fb) { |
| 274 | vmode_entry1 = viafb_get_mode(viafbinfo1->var.xres, | ||
| 275 | viafbinfo1->var.yres); | ||
| 276 | viafb_update_device_setting(viafbinfo1->var.xres, | 277 | viafb_update_device_setting(viafbinfo1->var.xres, |
| 277 | viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, | 278 | viafbinfo1->var.yres, viafbinfo1->var.bits_per_pixel, |
| 278 | 1); | 279 | 1); |
| @@ -280,8 +281,6 @@ static int viafb_set_par(struct fb_info *info) | |||
| 280 | DEBUG_MSG(KERN_INFO | 281 | DEBUG_MSG(KERN_INFO |
| 281 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", | 282 | "viafb_second_xres = %d, viafb_second_yres = %d, bpp = %d\n", |
| 282 | viafb_second_xres, viafb_second_yres, viafb_bpp1); | 283 | viafb_second_xres, viafb_second_yres, viafb_bpp1); |
| 283 | vmode_entry1 = viafb_get_mode(viafb_second_xres, | ||
| 284 | viafb_second_yres); | ||
| 285 | 284 | ||
| 286 | viafb_update_device_setting(viafb_second_xres, | 285 | viafb_update_device_setting(viafb_second_xres, |
| 287 | viafb_second_yres, viafb_bpp1, 1); | 286 | viafb_second_yres, viafb_bpp1, 1); |
| @@ -289,7 +288,8 @@ static int viafb_set_par(struct fb_info *info) | |||
| 289 | 288 | ||
| 290 | refresh = viafb_get_refresh(info->var.xres, info->var.yres, | 289 | refresh = viafb_get_refresh(info->var.xres, info->var.yres, |
| 291 | get_var_refresh(&info->var)); | 290 | get_var_refresh(&info->var)); |
| 292 | if (vmode_entry) { | 291 | if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres, |
| 292 | refresh)) { | ||
| 293 | if (viafb_dual_fb && viapar->iga_path == IGA2) { | 293 | if (viafb_dual_fb && viapar->iga_path == IGA2) { |
| 294 | viafb_bpp1 = info->var.bits_per_pixel; | 294 | viafb_bpp1 = info->var.bits_per_pixel; |
| 295 | viafb_refresh1 = refresh; | 295 | viafb_refresh1 = refresh; |
| @@ -302,8 +302,7 @@ static int viafb_set_par(struct fb_info *info) | |||
| 302 | info->flags &= ~FBINFO_HWACCEL_DISABLED; | 302 | info->flags &= ~FBINFO_HWACCEL_DISABLED; |
| 303 | else | 303 | else |
| 304 | info->flags |= FBINFO_HWACCEL_DISABLED; | 304 | info->flags |= FBINFO_HWACCEL_DISABLED; |
| 305 | viafb_setmode(vmode_entry, info->var.bits_per_pixel, | 305 | viafb_setmode(info->var.bits_per_pixel, viafb_bpp1); |
| 306 | vmode_entry1, viafb_bpp1); | ||
| 307 | viafb_pan_display(&info->var, info); | 306 | viafb_pan_display(&info->var, info); |
| 308 | } | 307 | } |
| 309 | 308 | ||
| @@ -348,8 +347,9 @@ static int viafb_pan_display(struct fb_var_screeninfo *var, | |||
| 348 | struct fb_info *info) | 347 | struct fb_info *info) |
| 349 | { | 348 | { |
| 350 | struct viafb_par *viapar = info->par; | 349 | struct viafb_par *viapar = info->par; |
| 351 | u32 vram_addr = (var->yoffset * var->xres_virtual + var->xoffset) | 350 | u32 vram_addr = viapar->vram_addr |
| 352 | * (var->bits_per_pixel / 8) + viapar->vram_addr; | 351 | + var->yoffset * info->fix.line_length |
| 352 | + var->xoffset * info->var.bits_per_pixel / 8; | ||
| 353 | 353 | ||
| 354 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); | 354 | DEBUG_MSG(KERN_DEBUG "viafb_pan_display, address = %d\n", vram_addr); |
| 355 | if (!viafb_dual_fb) { | 355 | if (!viafb_dual_fb) { |
| @@ -1158,7 +1158,8 @@ static ssize_t viafb_dvp0_proc_write(struct file *file, | |||
| 1158 | for (i = 0; i < 3; i++) { | 1158 | for (i = 0; i < 3; i++) { |
| 1159 | value = strsep(&pbuf, " "); | 1159 | value = strsep(&pbuf, " "); |
| 1160 | if (value != NULL) { | 1160 | if (value != NULL) { |
| 1161 | strict_strtoul(value, 0, (unsigned long *)®_val); | 1161 | if (kstrtou8(value, 0, ®_val) < 0) |
| 1162 | return -EINVAL; | ||
| 1162 | DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, | 1163 | DEBUG_MSG(KERN_INFO "DVP0:reg_val[%l]=:%x\n", i, |
| 1163 | reg_val); | 1164 | reg_val); |
| 1164 | switch (i) { | 1165 | switch (i) { |
| @@ -1228,7 +1229,8 @@ static ssize_t viafb_dvp1_proc_write(struct file *file, | |||
| 1228 | for (i = 0; i < 3; i++) { | 1229 | for (i = 0; i < 3; i++) { |
| 1229 | value = strsep(&pbuf, " "); | 1230 | value = strsep(&pbuf, " "); |
| 1230 | if (value != NULL) { | 1231 | if (value != NULL) { |
| 1231 | strict_strtoul(value, 0, (unsigned long *)®_val); | 1232 | if (kstrtou8(value, 0, ®_val) < 0) |
| 1233 | return -EINVAL; | ||
| 1232 | switch (i) { | 1234 | switch (i) { |
| 1233 | case 0: | 1235 | case 0: |
| 1234 | viafb_write_reg_mask(CR9B, VIACR, | 1236 | viafb_write_reg_mask(CR9B, VIACR, |
| @@ -1286,7 +1288,8 @@ static ssize_t viafb_dfph_proc_write(struct file *file, | |||
| 1286 | if (copy_from_user(&buf[0], buffer, length)) | 1288 | if (copy_from_user(&buf[0], buffer, length)) |
| 1287 | return -EFAULT; | 1289 | return -EFAULT; |
| 1288 | buf[length - 1] = '\0'; /*Ensure end string */ | 1290 | buf[length - 1] = '\0'; /*Ensure end string */ |
| 1289 | strict_strtoul(&buf[0], 0, (unsigned long *)®_val); | 1291 | if (kstrtou8(buf, 0, ®_val) < 0) |
| 1292 | return -EINVAL; | ||
| 1290 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); | 1293 | viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f); |
| 1291 | return count; | 1294 | return count; |
| 1292 | } | 1295 | } |
| @@ -1325,7 +1328,8 @@ static ssize_t viafb_dfpl_proc_write(struct file *file, | |||
| 1325 | if (copy_from_user(&buf[0], buffer, length)) | 1328 | if (copy_from_user(&buf[0], buffer, length)) |
| 1326 | return -EFAULT; | 1329 | return -EFAULT; |
| 1327 | buf[length - 1] = '\0'; /*Ensure end string */ | 1330 | buf[length - 1] = '\0'; /*Ensure end string */ |
| 1328 | strict_strtoul(&buf[0], 0, (unsigned long *)®_val); | 1331 | if (kstrtou8(buf, 0, ®_val) < 0) |
| 1332 | return -EINVAL; | ||
| 1329 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); | 1333 | viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f); |
| 1330 | return count; | 1334 | return count; |
| 1331 | } | 1335 | } |
| @@ -1394,8 +1398,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file, | |||
| 1394 | for (i = 0; i < 2; i++) { | 1398 | for (i = 0; i < 2; i++) { |
| 1395 | value = strsep(&pbuf, " "); | 1399 | value = strsep(&pbuf, " "); |
| 1396 | if (value != NULL) { | 1400 | if (value != NULL) { |
| 1397 | strict_strtoul(value, 0, | 1401 | if (kstrtou8(value, 0, ®_val.Data) < 0) |
| 1398 | (unsigned long *)®_val.Data); | 1402 | return -EINVAL; |
| 1399 | switch (i) { | 1403 | switch (i) { |
| 1400 | case 0: | 1404 | case 0: |
| 1401 | reg_val.Index = 0x08; | 1405 | reg_val.Index = 0x08; |
| @@ -1431,8 +1435,8 @@ static ssize_t viafb_vt1636_proc_write(struct file *file, | |||
| 1431 | for (i = 0; i < 2; i++) { | 1435 | for (i = 0; i < 2; i++) { |
| 1432 | value = strsep(&pbuf, " "); | 1436 | value = strsep(&pbuf, " "); |
| 1433 | if (value != NULL) { | 1437 | if (value != NULL) { |
| 1434 | strict_strtoul(value, 0, | 1438 | if (kstrtou8(value, 0, ®_val.Data) < 0) |
| 1435 | (unsigned long *)®_val.Data); | 1439 | return -EINVAL; |
| 1436 | switch (i) { | 1440 | switch (i) { |
| 1437 | case 0: | 1441 | case 0: |
| 1438 | reg_val.Index = 0x08; | 1442 | reg_val.Index = 0x08; |
| @@ -1729,7 +1733,6 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = { | |||
| 1729 | int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | 1733 | int __devinit via_fb_pci_probe(struct viafb_dev *vdev) |
| 1730 | { | 1734 | { |
| 1731 | u32 default_xres, default_yres; | 1735 | u32 default_xres, default_yres; |
| 1732 | struct VideoModeTable *vmode_entry; | ||
| 1733 | struct fb_var_screeninfo default_var; | 1736 | struct fb_var_screeninfo default_var; |
| 1734 | int rc; | 1737 | int rc; |
| 1735 | u32 viafb_par_length; | 1738 | u32 viafb_par_length; |
| @@ -1802,7 +1805,6 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
| 1802 | } | 1805 | } |
| 1803 | 1806 | ||
| 1804 | parse_mode(viafb_mode, &default_xres, &default_yres); | 1807 | parse_mode(viafb_mode, &default_xres, &default_yres); |
| 1805 | vmode_entry = viafb_get_mode(default_xres, default_yres); | ||
| 1806 | if (viafb_SAMM_ON == 1) | 1808 | if (viafb_SAMM_ON == 1) |
| 1807 | parse_mode(viafb_mode1, &viafb_second_xres, | 1809 | parse_mode(viafb_mode1, &viafb_second_xres, |
| 1808 | &viafb_second_yres); | 1810 | &viafb_second_yres); |
| @@ -1812,9 +1814,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
| 1812 | default_var.xres_virtual = default_xres; | 1814 | default_var.xres_virtual = default_xres; |
| 1813 | default_var.yres_virtual = default_yres; | 1815 | default_var.yres_virtual = default_yres; |
| 1814 | default_var.bits_per_pixel = viafb_bpp; | 1816 | default_var.bits_per_pixel = viafb_bpp; |
| 1815 | viafb_fill_var_timing_info(&default_var, viafb_get_refresh( | 1817 | viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( |
| 1816 | default_var.xres, default_var.yres, viafb_refresh), | 1818 | default_var.xres, default_var.yres, viafb_refresh)); |
| 1817 | viafb_get_mode(default_var.xres, default_var.yres)); | ||
| 1818 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); | 1819 | viafb_setup_fixinfo(&viafbinfo->fix, viaparinfo); |
| 1819 | viafbinfo->var = default_var; | 1820 | viafbinfo->var = default_var; |
| 1820 | 1821 | ||
| @@ -1853,9 +1854,8 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev) | |||
| 1853 | default_var.xres_virtual = viafb_second_xres; | 1854 | default_var.xres_virtual = viafb_second_xres; |
| 1854 | default_var.yres_virtual = viafb_second_yres; | 1855 | default_var.yres_virtual = viafb_second_yres; |
| 1855 | default_var.bits_per_pixel = viafb_bpp1; | 1856 | default_var.bits_per_pixel = viafb_bpp1; |
| 1856 | viafb_fill_var_timing_info(&default_var, viafb_get_refresh( | 1857 | viafb_fill_var_timing_info(&default_var, viafb_get_best_mode( |
| 1857 | default_var.xres, default_var.yres, viafb_refresh1), | 1858 | default_var.xres, default_var.yres, viafb_refresh1)); |
| 1858 | viafb_get_mode(default_var.xres, default_var.yres)); | ||
| 1859 | 1859 | ||
| 1860 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); | 1860 | viafb_setup_fixinfo(&viafbinfo1->fix, viaparinfo1); |
| 1861 | viafb_check_var(&default_var, viafbinfo1); | 1861 | viafb_check_var(&default_var, viafbinfo1); |
| @@ -1950,61 +1950,67 @@ static int __init viafb_setup(void) | |||
| 1950 | if (!*this_opt) | 1950 | if (!*this_opt) |
| 1951 | continue; | 1951 | continue; |
| 1952 | 1952 | ||
| 1953 | if (!strncmp(this_opt, "viafb_mode1=", 12)) | 1953 | if (!strncmp(this_opt, "viafb_mode1=", 12)) { |
| 1954 | viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); | 1954 | viafb_mode1 = kstrdup(this_opt + 12, GFP_KERNEL); |
| 1955 | else if (!strncmp(this_opt, "viafb_mode=", 11)) | 1955 | } else if (!strncmp(this_opt, "viafb_mode=", 11)) { |
| 1956 | viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); | 1956 | viafb_mode = kstrdup(this_opt + 11, GFP_KERNEL); |
| 1957 | else if (!strncmp(this_opt, "viafb_bpp1=", 11)) | 1957 | } else if (!strncmp(this_opt, "viafb_bpp1=", 11)) { |
| 1958 | strict_strtoul(this_opt + 11, 0, | 1958 | if (kstrtouint(this_opt + 11, 0, &viafb_bpp1) < 0) |
| 1959 | (unsigned long *)&viafb_bpp1); | 1959 | return -EINVAL; |
| 1960 | else if (!strncmp(this_opt, "viafb_bpp=", 10)) | 1960 | } else if (!strncmp(this_opt, "viafb_bpp=", 10)) { |
| 1961 | strict_strtoul(this_opt + 10, 0, | 1961 | if (kstrtouint(this_opt + 10, 0, &viafb_bpp) < 0) |
| 1962 | (unsigned long *)&viafb_bpp); | 1962 | return -EINVAL; |
| 1963 | else if (!strncmp(this_opt, "viafb_refresh1=", 15)) | 1963 | } else if (!strncmp(this_opt, "viafb_refresh1=", 15)) { |
| 1964 | strict_strtoul(this_opt + 15, 0, | 1964 | if (kstrtoint(this_opt + 15, 0, &viafb_refresh1) < 0) |
| 1965 | (unsigned long *)&viafb_refresh1); | 1965 | return -EINVAL; |
| 1966 | else if (!strncmp(this_opt, "viafb_refresh=", 14)) | 1966 | } else if (!strncmp(this_opt, "viafb_refresh=", 14)) { |
| 1967 | strict_strtoul(this_opt + 14, 0, | 1967 | if (kstrtoint(this_opt + 14, 0, &viafb_refresh) < 0) |
| 1968 | (unsigned long *)&viafb_refresh); | 1968 | return -EINVAL; |
| 1969 | else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) | 1969 | } else if (!strncmp(this_opt, "viafb_lcd_dsp_method=", 21)) { |
| 1970 | strict_strtoul(this_opt + 21, 0, | 1970 | if (kstrtoint(this_opt + 21, 0, |
| 1971 | (unsigned long *)&viafb_lcd_dsp_method); | 1971 | &viafb_lcd_dsp_method) < 0) |
| 1972 | else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) | 1972 | return -EINVAL; |
| 1973 | strict_strtoul(this_opt + 19, 0, | 1973 | } else if (!strncmp(this_opt, "viafb_lcd_panel_id=", 19)) { |
| 1974 | (unsigned long *)&viafb_lcd_panel_id); | 1974 | if (kstrtoint(this_opt + 19, 0, |
| 1975 | else if (!strncmp(this_opt, "viafb_accel=", 12)) | 1975 | &viafb_lcd_panel_id) < 0) |
| 1976 | strict_strtoul(this_opt + 12, 0, | 1976 | return -EINVAL; |
| 1977 | (unsigned long *)&viafb_accel); | 1977 | } else if (!strncmp(this_opt, "viafb_accel=", 12)) { |
| 1978 | else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) | 1978 | if (kstrtoint(this_opt + 12, 0, &viafb_accel) < 0) |
| 1979 | strict_strtoul(this_opt + 14, 0, | 1979 | return -EINVAL; |
| 1980 | (unsigned long *)&viafb_SAMM_ON); | 1980 | } else if (!strncmp(this_opt, "viafb_SAMM_ON=", 14)) { |
| 1981 | else if (!strncmp(this_opt, "viafb_active_dev=", 17)) | 1981 | if (kstrtoint(this_opt + 14, 0, &viafb_SAMM_ON) < 0) |
| 1982 | return -EINVAL; | ||
| 1983 | } else if (!strncmp(this_opt, "viafb_active_dev=", 17)) { | ||
| 1982 | viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); | 1984 | viafb_active_dev = kstrdup(this_opt + 17, GFP_KERNEL); |
| 1983 | else if (!strncmp(this_opt, | 1985 | } else if (!strncmp(this_opt, |
| 1984 | "viafb_display_hardware_layout=", 30)) | 1986 | "viafb_display_hardware_layout=", 30)) { |
| 1985 | strict_strtoul(this_opt + 30, 0, | 1987 | if (kstrtoint(this_opt + 30, 0, |
| 1986 | (unsigned long *)&viafb_display_hardware_layout); | 1988 | &viafb_display_hardware_layout) < 0) |
| 1987 | else if (!strncmp(this_opt, "viafb_second_size=", 18)) | 1989 | return -EINVAL; |
| 1988 | strict_strtoul(this_opt + 18, 0, | 1990 | } else if (!strncmp(this_opt, "viafb_second_size=", 18)) { |
| 1989 | (unsigned long *)&viafb_second_size); | 1991 | if (kstrtoint(this_opt + 18, 0, &viafb_second_size) < 0) |
| 1990 | else if (!strncmp(this_opt, | 1992 | return -EINVAL; |
| 1991 | "viafb_platform_epia_dvi=", 24)) | 1993 | } else if (!strncmp(this_opt, |
| 1992 | strict_strtoul(this_opt + 24, 0, | 1994 | "viafb_platform_epia_dvi=", 24)) { |
| 1993 | (unsigned long *)&viafb_platform_epia_dvi); | 1995 | if (kstrtoint(this_opt + 24, 0, |
| 1994 | else if (!strncmp(this_opt, | 1996 | &viafb_platform_epia_dvi) < 0) |
| 1995 | "viafb_device_lcd_dualedge=", 26)) | 1997 | return -EINVAL; |
| 1996 | strict_strtoul(this_opt + 26, 0, | 1998 | } else if (!strncmp(this_opt, |
| 1997 | (unsigned long *)&viafb_device_lcd_dualedge); | 1999 | "viafb_device_lcd_dualedge=", 26)) { |
| 1998 | else if (!strncmp(this_opt, "viafb_bus_width=", 16)) | 2000 | if (kstrtoint(this_opt + 26, 0, |
| 1999 | strict_strtoul(this_opt + 16, 0, | 2001 | &viafb_device_lcd_dualedge) < 0) |
| 2000 | (unsigned long *)&viafb_bus_width); | 2002 | return -EINVAL; |
| 2001 | else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) | 2003 | } else if (!strncmp(this_opt, "viafb_bus_width=", 16)) { |
| 2002 | strict_strtoul(this_opt + 15, 0, | 2004 | if (kstrtoint(this_opt + 16, 0, &viafb_bus_width) < 0) |
| 2003 | (unsigned long *)&viafb_lcd_mode); | 2005 | return -EINVAL; |
| 2004 | else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) | 2006 | } else if (!strncmp(this_opt, "viafb_lcd_mode=", 15)) { |
| 2007 | if (kstrtoint(this_opt + 15, 0, &viafb_lcd_mode) < 0) | ||
| 2008 | return -EINVAL; | ||
| 2009 | } else if (!strncmp(this_opt, "viafb_lcd_port=", 15)) { | ||
| 2005 | viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); | 2010 | viafb_lcd_port = kstrdup(this_opt + 15, GFP_KERNEL); |
| 2006 | else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) | 2011 | } else if (!strncmp(this_opt, "viafb_dvi_port=", 15)) { |
| 2007 | viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); | 2012 | viafb_dvi_port = kstrdup(this_opt + 15, GFP_KERNEL); |
| 2013 | } | ||
| 2008 | } | 2014 | } |
| 2009 | return 0; | 2015 | return 0; |
| 2010 | } | 2016 | } |
| @@ -2028,9 +2034,9 @@ int __init viafb_init(void) | |||
| 2028 | return r; | 2034 | return r; |
| 2029 | #endif | 2035 | #endif |
| 2030 | if (parse_mode(viafb_mode, &dummy_x, &dummy_y) | 2036 | if (parse_mode(viafb_mode, &dummy_x, &dummy_y) |
| 2031 | || !viafb_get_mode(dummy_x, dummy_y) | 2037 | || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) |
| 2032 | || parse_mode(viafb_mode1, &dummy_x, &dummy_y) | 2038 | || parse_mode(viafb_mode1, &dummy_x, &dummy_y) |
| 2033 | || !viafb_get_mode(dummy_x, dummy_y) | 2039 | || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) |
| 2034 | || viafb_bpp < 0 || viafb_bpp > 32 | 2040 | || viafb_bpp < 0 || viafb_bpp > 32 |
| 2035 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 | 2041 | || viafb_bpp1 < 0 || viafb_bpp1 > 32 |
| 2036 | || parse_active_dev()) | 2042 | || parse_active_dev()) |
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c index 58df74e1417e..0911cac1b2ff 100644 --- a/drivers/video/via/viamode.c +++ b/drivers/video/via/viamode.c | |||
| @@ -281,7 +281,7 @@ static struct crt_mode_table CRTM640x480[] = { | |||
| 281 | /*r_rate,hsp,vsp */ | 281 | /*r_rate,hsp,vsp */ |
| 282 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ | 282 | /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ |
| 283 | {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, | 283 | {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, |
| 284 | {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} }, | 284 | {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} }, |
| 285 | {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, | 285 | {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, |
| 286 | {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, | 286 | {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, |
| 287 | {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, | 287 | {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, |
| @@ -863,26 +863,56 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs); | |||
| 863 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); | 863 | int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); |
| 864 | 864 | ||
| 865 | 865 | ||
| 866 | struct VideoModeTable *viafb_get_mode(int hres, int vres) | 866 | static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n, |
| 867 | int hres, int vres) | ||
| 867 | { | 868 | { |
| 868 | u32 i; | 869 | int i; |
| 869 | for (i = 0; i < ARRAY_SIZE(viafb_modes); i++) | 870 | |
| 870 | if (viafb_modes[i].mode_array && | 871 | for (i = 0; i < n; i++) |
| 871 | viafb_modes[i].crtc[0].crtc.hor_addr == hres && | 872 | if (vmt[i].mode_array && |
| 872 | viafb_modes[i].crtc[0].crtc.ver_addr == vres) | 873 | vmt[i].crtc[0].crtc.hor_addr == hres && |
| 874 | vmt[i].crtc[0].crtc.ver_addr == vres) | ||
| 873 | return &viafb_modes[i]; | 875 | return &viafb_modes[i]; |
| 874 | 876 | ||
| 875 | return NULL; | 877 | return NULL; |
| 876 | } | 878 | } |
| 877 | 879 | ||
| 878 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) | 880 | static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt, |
| 881 | int refresh) | ||
| 879 | { | 882 | { |
| 880 | u32 i; | 883 | struct crt_mode_table *best; |
| 881 | for (i = 0; i < ARRAY_SIZE(viafb_rb_modes); i++) | 884 | int i; |
| 882 | if (viafb_rb_modes[i].mode_array && | ||
| 883 | viafb_rb_modes[i].crtc[0].crtc.hor_addr == hres && | ||
| 884 | viafb_rb_modes[i].crtc[0].crtc.ver_addr == vres) | ||
| 885 | return &viafb_rb_modes[i]; | ||
| 886 | 885 | ||
| 887 | return NULL; | 886 | if (!vmt) |
| 887 | return NULL; | ||
| 888 | |||
| 889 | best = &vmt->crtc[0]; | ||
| 890 | for (i = 1; i < vmt->mode_array; i++) { | ||
| 891 | if (abs(vmt->crtc[i].refresh_rate - refresh) | ||
| 892 | < abs(best->refresh_rate - refresh)) | ||
| 893 | best = &vmt->crtc[i]; | ||
| 894 | } | ||
| 895 | |||
| 896 | return best; | ||
| 897 | } | ||
| 898 | |||
| 899 | static struct VideoModeTable *viafb_get_mode(int hres, int vres) | ||
| 900 | { | ||
| 901 | return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres); | ||
| 902 | } | ||
| 903 | |||
| 904 | struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh) | ||
| 905 | { | ||
| 906 | return get_best_mode(viafb_get_mode(hres, vres), refresh); | ||
| 907 | } | ||
| 908 | |||
| 909 | static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) | ||
| 910 | { | ||
| 911 | return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres, | ||
| 912 | vres); | ||
| 913 | } | ||
| 914 | |||
| 915 | struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh) | ||
| 916 | { | ||
| 917 | return get_best_mode(viafb_get_rb_mode(hres, vres), refresh); | ||
| 888 | } | 918 | } |
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h index 3751289eb450..5917a2b00e1b 100644 --- a/drivers/video/via/viamode.h +++ b/drivers/video/via/viamode.h | |||
| @@ -60,7 +60,7 @@ extern struct io_reg PM1024x768[]; | |||
| 60 | extern struct patch_table res_patch_table[]; | 60 | extern struct patch_table res_patch_table[]; |
| 61 | extern struct VPITTable VPIT; | 61 | extern struct VPITTable VPIT; |
| 62 | 62 | ||
| 63 | struct VideoModeTable *viafb_get_mode(int hres, int vres); | 63 | struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh); |
| 64 | struct VideoModeTable *viafb_get_rb_mode(int hres, int vres); | 64 | struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh); |
| 65 | 65 | ||
| 66 | #endif /* __VIAMODE_H__ */ | 66 | #endif /* __VIAMODE_H__ */ |
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c index 0e120d67eb65..777c21dd7a6b 100644 --- a/drivers/video/vt8500lcdfb.c +++ b/drivers/video/vt8500lcdfb.c | |||
| @@ -210,8 +210,8 @@ static int vt8500lcd_pan_display(struct fb_var_screeninfo *var, | |||
| 210 | struct vt8500lcd_info *fbi = to_vt8500lcd_info(info); | 210 | struct vt8500lcd_info *fbi = to_vt8500lcd_info(info); |
| 211 | 211 | ||
| 212 | writel((1 << 31) | 212 | writel((1 << 31) |
| 213 | | (((var->xres_virtual - var->xres) * pixlen / 4) << 20) | 213 | | (((info->var.xres_virtual - info->var.xres) * pixlen / 4) << 20) |
| 214 | | (off >> 2), fbi->regbase + 0x20); | 214 | | (off >> 2), fbi->regbase + 0x20); |
| 215 | return 0; | 215 | return 0; |
| 216 | } | 216 | } |
| 217 | 217 | ||
| @@ -355,7 +355,7 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev) | |||
| 355 | goto failed_free_palette; | 355 | goto failed_free_palette; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi); | 358 | ret = request_irq(irq, vt8500lcd_handle_irq, 0, "LCD", fbi); |
| 359 | if (ret) { | 359 | if (ret) { |
| 360 | dev_err(&pdev->dev, "request_irq failed: %d\n", ret); | 360 | dev_err(&pdev->dev, "request_irq failed: %d\n", ret); |
| 361 | ret = -EBUSY; | 361 | ret = -EBUSY; |
diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index f9b3e3dc2421..4e74d262cf3e 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c | |||
| @@ -620,13 +620,14 @@ static int vt8623fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *i | |||
| 620 | unsigned int offset; | 620 | unsigned int offset; |
| 621 | 621 | ||
| 622 | /* Calculate the offset */ | 622 | /* Calculate the offset */ |
| 623 | if (var->bits_per_pixel == 0) { | 623 | if (info->var.bits_per_pixel == 0) { |
| 624 | offset = (var->yoffset / 16) * var->xres_virtual + var->xoffset; | 624 | offset = (var->yoffset / 16) * info->var.xres_virtual |
| 625 | + var->xoffset; | ||
| 625 | offset = offset >> 3; | 626 | offset = offset >> 3; |
| 626 | } else { | 627 | } else { |
| 627 | offset = (var->yoffset * info->fix.line_length) + | 628 | offset = (var->yoffset * info->fix.line_length) + |
| 628 | (var->xoffset * var->bits_per_pixel / 8); | 629 | (var->xoffset * info->var.bits_per_pixel / 8); |
| 629 | offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 1); | 630 | offset = offset >> ((info->var.bits_per_pixel == 4) ? 2 : 1); |
| 630 | } | 631 | } |
| 631 | 632 | ||
| 632 | /* Set the offset */ | 633 | /* Set the offset */ |
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index c8be8af0cc6d..2375e5bbf572 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/string.h> | 34 | #include <linux/string.h> |
| 35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
| 36 | #include <linux/module.h> | ||
| 36 | #include <asm/io.h> | 37 | #include <asm/io.h> |
| 37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
| 38 | #include <video/w100fb.h> | 39 | #include <video/w100fb.h> |
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 77dea015ff69..fcb6cd90f64d 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/version.h> | ||
| 27 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
| 28 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| 29 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
