aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-11 21:21:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-11 21:21:02 -0400
commit5f76945a9c978b8b8bf8eb7fe3b17b9981240a97 (patch)
treedf61aca168df657bc71ce8b578bcb0c81b0622ee /drivers/video
parent940e3a8dd6683a3787faf769b3df7a06f1c2fa31 (diff)
parentcd9d6f10d07f26dd8a70e519c22b6b4f8a9e3e7a (diff)
Merge tag 'fbdev-updates-for-3.7' of git://github.com/schandinat/linux-2.6
Pull fbdev updates from Florian Tobias Schandinat: "This includes: - large updates for OMAP - basic OMAP5 DSS support for DPI and DSI outputs - large cleanups and restructuring - some update to Exynos and da8xx-fb - removal of the pnx4008 driver (arch removed) - various other small patches" Fix up some trivial conflicts (mostly just include line changes, but also some due to the renaming of the deferred work functions by Tejun). * tag 'fbdev-updates-for-3.7' of git://github.com/schandinat/linux-2.6: (193 commits) gbefb: fix compile error video: mark nuc900fb_map_video_memory as __devinit video/mx3fb: set .owner to prevent module unloading while being used video: exynos_dp: use clk_prepare_enable and clk_disable_unprepare drivers/video/exynos/exynos_mipi_dsi.c: fix error return code drivers/video/savage/savagefb_driver.c: fix error return code video: s3c-fb: use clk_prepare_enable and clk_disable_unprepare da8xx-fb: save and restore LCDC context across suspend/resume cycle da8xx-fb: add pm_runtime support video/udlfb: fix line counting in fb_write OMAPDSS: add missing include for string.h OMAPDSS: DISPC: Configure color conversion coefficients for writeback OMAPDSS: DISPC: Add manager like functions for writeback OMAPDSS: DISPC: Configure writeback FIFOs OMAPDSS: DISPC: Configure writeback specific parameters in dispc_wb_setup() OMAPDSS: DISPC: Configure overlay-like parameters in dispc_wb_setup OMAPDSS: DISPC: Add function to set channel in for writeback OMAPDSS: DISPC: Don't set chroma resampling bit for writeback OMAPDSS: DISPC: Downscale chroma if plane is writeback OMAPDSS: DISPC: Configure input and output sizes for writeback ...
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/Kconfig15
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c2
-rw-r--r--drivers/video/arcfb.c1
-rw-r--r--drivers/video/atmel_lcdfb.c5
-rw-r--r--drivers/video/bf537-lq035.c12
-rw-r--r--drivers/video/bf54x-lq043fb.c9
-rw-r--r--drivers/video/bfin-lq035q1-fb.c13
-rw-r--r--drivers/video/bfin-t350mcqb-fb.c1
-rw-r--r--drivers/video/bw2.c4
-rw-r--r--drivers/video/cg3.c3
-rw-r--r--drivers/video/cobalt_lcdfb.c5
-rw-r--r--drivers/video/console/font_mini_4x6.c2
-rw-r--r--drivers/video/console/font_sun8x16.c2
-rw-r--r--drivers/video/cyber2000fb.c4
-rw-r--r--drivers/video/da8xx-fb.c283
-rw-r--r--drivers/video/ep93xx-fb.c17
-rw-r--r--drivers/video/exynos/exynos_dp_core.c322
-rw-r--r--drivers/video/exynos/exynos_dp_core.h6
-rw-r--r--drivers/video/exynos/exynos_dp_reg.c58
-rw-r--r--drivers/video/exynos/exynos_dp_reg.h3
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi.c9
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_common.c8
-rw-r--r--drivers/video/fsl-diu-fb.c10
-rw-r--r--drivers/video/gbefb.c17
-rw-r--r--drivers/video/hpfb.c28
-rw-r--r--drivers/video/imxfb.c1
-rw-r--r--drivers/video/jz4740_fb.c44
-rw-r--r--drivers/video/mb862xx/mb862xxfbdrv.c10
-rw-r--r--drivers/video/mbx/mbxfb.c25
-rw-r--r--drivers/video/msm/mddi.c3
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c6
-rw-r--r--drivers/video/msm/mdp.c1
-rw-r--r--drivers/video/msm/mdp_hw.h1
-rw-r--r--drivers/video/mx3fb.c3
-rw-r--r--drivers/video/nuc900fb.c2
-rw-r--r--drivers/video/omap/hwa742.c1
-rw-r--r--drivers/video/omap/lcd_palmte.c1
-rw-r--r--drivers/video/omap/omapfb_main.c9
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c14
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c76
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c3
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c31
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c3
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c4
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c3
-rw-r--r--drivers/video/omap2/displays/panel-taal.c239
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c20
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c7
-rw-r--r--drivers/video/omap2/dss/Kconfig2
-rw-r--r--drivers/video/omap2/dss/Makefile4
-rw-r--r--drivers/video/omap2/dss/apply.c330
-rw-r--r--drivers/video/omap2/dss/core.c91
-rw-r--r--drivers/video/omap2/dss/dispc.c1018
-rw-r--r--drivers/video/omap2/dss/dispc.h37
-rw-r--r--drivers/video/omap2/dss/display.c108
-rw-r--r--drivers/video/omap2/dss/dpi.c181
-rw-r--r--drivers/video/omap2/dss/dsi.c675
-rw-r--r--drivers/video/omap2/dss/dss.c257
-rw-r--r--drivers/video/omap2/dss/dss.h79
-rw-r--r--drivers/video/omap2/dss/dss_features.c278
-rw-r--r--drivers/video/omap2/dss/dss_features.h7
-rw-r--r--drivers/video/omap2/dss/hdmi.c247
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c31
-rw-r--r--drivers/video/omap2/dss/manager-sysfs.c512
-rw-r--r--drivers/video/omap2/dss/manager.c473
-rw-r--r--drivers/video/omap2/dss/output.c148
-rw-r--r--drivers/video/omap2/dss/overlay-sysfs.c456
-rw-r--r--drivers/video/omap2/dss/overlay.c492
-rw-r--r--drivers/video/omap2/dss/rfbi.c222
-rw-r--r--drivers/video/omap2/dss/sdi.c126
-rw-r--r--drivers/video/omap2/dss/venc.c337
-rw-r--r--drivers/video/omap2/dss/venc_panel.c251
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c7
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c32
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h5
-rw-r--r--drivers/video/omap2/vram.c56
-rw-r--r--drivers/video/pnx4008/Makefile7
-rw-r--r--drivers/video/pnx4008/dum.h211
-rw-r--r--drivers/video/pnx4008/fbcommon.h43
-rw-r--r--drivers/video/pnx4008/pnxrgbfb.c198
-rw-r--r--drivers/video/pnx4008/sdum.c861
-rw-r--r--drivers/video/pnx4008/sdum.h136
-rw-r--r--drivers/video/ps3fb.c7
-rw-r--r--drivers/video/s3c-fb.c54
-rw-r--r--drivers/video/s3c2410fb.c34
-rw-r--r--drivers/video/savage/savagefb_driver.c4
-rw-r--r--drivers/video/sis/initextlfb.c2
-rw-r--r--drivers/video/sunxvr1000.c4
-rw-r--r--drivers/video/sunxvr2500.c4
-rw-r--r--drivers/video/sunxvr500.c8
-rw-r--r--drivers/video/udlfb.c2
-rw-r--r--drivers/video/uvesafb.c2
-rw-r--r--drivers/video/vermilion/vermilion.c3
-rw-r--r--drivers/video/via/via_clock.c19
95 files changed, 5027 insertions, 4382 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 20c33c42600a..d08d7998a4aa 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2139,21 +2139,6 @@ config FB_UDL
2139 mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices. 2139 mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
2140 To compile as a module, choose M here: the module name is udlfb. 2140 To compile as a module, choose M here: the module name is udlfb.
2141 2141
2142config FB_PNX4008_DUM
2143 tristate "Display Update Module support on Philips PNX4008 board"
2144 depends on FB && ARCH_PNX4008
2145 ---help---
2146 Say Y here to enable support for PNX4008 Display Update Module (DUM)
2147
2148config FB_PNX4008_DUM_RGB
2149 tristate "RGB Framebuffer support on Philips PNX4008 board"
2150 depends on FB_PNX4008_DUM
2151 select FB_CFB_FILLRECT
2152 select FB_CFB_COPYAREA
2153 select FB_CFB_IMAGEBLIT
2154 ---help---
2155 Say Y here to enable support for PNX4008 RGB Framebuffer
2156
2157config FB_IBM_GXT4500 2142config FB_IBM_GXT4500
2158 tristate "Framebuffer support for IBM GXT4500P adaptor" 2143 tristate "Framebuffer support for IBM GXT4500P adaptor"
2159 depends on FB && PPC 2144 depends on FB && PPC
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 194035986af2..23e948ebfab8 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -127,8 +127,6 @@ obj-$(CONFIG_FB_S3C) += s3c-fb.o
127obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o 127obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
128obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o 128obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
129obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o 129obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
130obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/
131obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/
132obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o 130obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o
133obj-$(CONFIG_FB_PS3) += ps3fb.o 131obj-$(CONFIG_FB_PS3) += ps3fb.o
134obj-$(CONFIG_FB_SM501) += sm501fb.o 132obj-$(CONFIG_FB_SM501) += sm501fb.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 887df9d81422..7fa1bf823729 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -949,7 +949,6 @@ static int round_down_bpp = 1; /* for mode probing */
949 949
950 950
951static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ 951static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
952static int amifb_inverse = 0;
953 952
954static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */ 953static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
955static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */ 954static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
@@ -2355,7 +2354,6 @@ static int __init amifb_setup(char *options)
2355 if (!*this_opt) 2354 if (!*this_opt)
2356 continue; 2355 continue;
2357 if (!strcmp(this_opt, "inverse")) { 2356 if (!strcmp(this_opt, "inverse")) {
2358 amifb_inverse = 1;
2359 fb_invert_cmaps(); 2357 fb_invert_cmaps();
2360 } else if (!strcmp(this_opt, "ilbm")) 2358 } else if (!strcmp(this_opt, "ilbm"))
2361 amifb_ilbm = 1; 2359 amifb_ilbm = 1;
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index a1d58e9d3073..4659d5da6ff8 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -552,6 +552,7 @@ static int __devinit arcfb_probe(struct platform_device *dev)
552 "arcfb", info)) { 552 "arcfb", info)) {
553 printk(KERN_INFO 553 printk(KERN_INFO
554 "arcfb: Failed req IRQ %d\n", par->irq); 554 "arcfb: Failed req IRQ %d\n", par->irq);
555 retval = -EBUSY;
555 goto err1; 556 goto err1;
556 } 557 }
557 } 558 }
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 15055395cd95..94cac9f9919f 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -931,8 +931,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
931 } 931 }
932 932
933 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); 933 info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
934 if (!info->screen_base) 934 if (!info->screen_base) {
935 ret = -ENOMEM;
935 goto release_intmem; 936 goto release_intmem;
937 }
936 938
937 /* 939 /*
938 * Don't clear the framebuffer -- someone may have set 940 * Don't clear the framebuffer -- someone may have set
@@ -960,6 +962,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
960 sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len); 962 sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
961 if (!sinfo->mmio) { 963 if (!sinfo->mmio) {
962 dev_err(dev, "cannot map LCDC registers\n"); 964 dev_err(dev, "cannot map LCDC registers\n");
965 ret = -ENOMEM;
963 goto release_mem; 966 goto release_mem;
964 } 967 }
965 968
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
index befbc80d11fc..7347aa1e5e4a 100644
--- a/drivers/video/bf537-lq035.c
+++ b/drivers/video/bf537-lq035.c
@@ -760,18 +760,20 @@ static int __devinit bfin_lq035_probe(struct platform_device *pdev)
760 bfin_lq035_fb.flags = FBINFO_DEFAULT; 760 bfin_lq035_fb.flags = FBINFO_DEFAULT;
761 761
762 762
763 bfin_lq035_fb.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); 763 bfin_lq035_fb.pseudo_palette = devm_kzalloc(&pdev->dev,
764 sizeof(u32) * 16,
765 GFP_KERNEL);
764 if (bfin_lq035_fb.pseudo_palette == NULL) { 766 if (bfin_lq035_fb.pseudo_palette == NULL) {
765 pr_err("failed to allocate pseudo_palette\n"); 767 pr_err("failed to allocate pseudo_palette\n");
766 ret = -ENOMEM; 768 ret = -ENOMEM;
767 goto out_palette; 769 goto out_table;
768 } 770 }
769 771
770 if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) { 772 if (fb_alloc_cmap(&bfin_lq035_fb.cmap, NBR_PALETTE, 0) < 0) {
771 pr_err("failed to allocate colormap (%d entries)\n", 773 pr_err("failed to allocate colormap (%d entries)\n",
772 NBR_PALETTE); 774 NBR_PALETTE);
773 ret = -EFAULT; 775 ret = -EFAULT;
774 goto out_cmap; 776 goto out_table;
775 } 777 }
776 778
777 if (register_framebuffer(&bfin_lq035_fb) < 0) { 779 if (register_framebuffer(&bfin_lq035_fb) < 0) {
@@ -804,9 +806,6 @@ out_lcd:
804 unregister_framebuffer(&bfin_lq035_fb); 806 unregister_framebuffer(&bfin_lq035_fb);
805out_reg: 807out_reg:
806 fb_dealloc_cmap(&bfin_lq035_fb.cmap); 808 fb_dealloc_cmap(&bfin_lq035_fb.cmap);
807out_cmap:
808 kfree(bfin_lq035_fb.pseudo_palette);
809out_palette:
810out_table: 809out_table:
811 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0); 810 dma_free_coherent(NULL, TOTAL_VIDEO_MEM_SIZE, fb_buffer, 0);
812 fb_buffer = NULL; 811 fb_buffer = NULL;
@@ -834,7 +833,6 @@ static int __devexit bfin_lq035_remove(struct platform_device *pdev)
834 free_dma(CH_PPI); 833 free_dma(CH_PPI);
835 834
836 835
837 kfree(bfin_lq035_fb.pseudo_palette);
838 fb_dealloc_cmap(&bfin_lq035_fb.cmap); 836 fb_dealloc_cmap(&bfin_lq035_fb.cmap);
839 837
840 838
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index dc2f0047769b..ff5663f5c64f 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -525,6 +525,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
525 info = fbinfo->par; 525 info = fbinfo->par;
526 info->fb = fbinfo; 526 info->fb = fbinfo;
527 info->dev = &pdev->dev; 527 info->dev = &pdev->dev;
528 spin_lock_init(&info->lock);
528 529
529 platform_set_drvdata(pdev, fbinfo); 530 platform_set_drvdata(pdev, fbinfo);
530 531
@@ -601,7 +602,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
601 602
602 fbinfo->fbops = &bfin_bf54x_fb_ops; 603 fbinfo->fbops = &bfin_bf54x_fb_ops;
603 604
604 fbinfo->pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL); 605 fbinfo->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
606 GFP_KERNEL);
605 if (!fbinfo->pseudo_palette) { 607 if (!fbinfo->pseudo_palette) {
606 printk(KERN_ERR DRIVER_NAME 608 printk(KERN_ERR DRIVER_NAME
607 "Fail to allocate pseudo_palette\n"); 609 "Fail to allocate pseudo_palette\n");
@@ -616,7 +618,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
616 "Fail to allocate colormap (%d entries)\n", 618 "Fail to allocate colormap (%d entries)\n",
617 BFIN_LCD_NBR_PALETTE_ENTRIES); 619 BFIN_LCD_NBR_PALETTE_ENTRIES);
618 ret = -EFAULT; 620 ret = -EFAULT;
619 goto out5; 621 goto out4;
620 } 622 }
621 623
622 if (request_ports(info)) { 624 if (request_ports(info)) {
@@ -671,8 +673,6 @@ out7:
671 free_ports(info); 673 free_ports(info);
672out6: 674out6:
673 fb_dealloc_cmap(&fbinfo->cmap); 675 fb_dealloc_cmap(&fbinfo->cmap);
674out5:
675 kfree(fbinfo->pseudo_palette);
676out4: 676out4:
677 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 677 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
678 info->dma_handle); 678 info->dma_handle);
@@ -699,7 +699,6 @@ static int __devexit bfin_bf54x_remove(struct platform_device *pdev)
699 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, 699 dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer,
700 info->dma_handle); 700 info->dma_handle);
701 701
702 kfree(fbinfo->pseudo_palette);
703 fb_dealloc_cmap(&fbinfo->cmap); 702 fb_dealloc_cmap(&fbinfo->cmap);
704 703
705#ifndef NO_BL_SUPPORT 704#ifndef NO_BL_SUPPORT
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index 353c02fe8a95..6fbc75c2f0a1 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -577,6 +577,7 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
577 info = fbinfo->par; 577 info = fbinfo->par;
578 info->fb = fbinfo; 578 info->fb = fbinfo;
579 info->dev = &pdev->dev; 579 info->dev = &pdev->dev;
580 spin_lock_init(&info->lock);
580 581
581 info->disp_info = pdev->dev.platform_data; 582 info->disp_info = pdev->dev.platform_data;
582 583
@@ -853,17 +854,7 @@ static struct platform_driver bfin_lq035q1_driver = {
853 }, 854 },
854}; 855};
855 856
856static int __init bfin_lq035q1_driver_init(void) 857module_platform_driver(bfin_lq035q1_driver);
857{
858 return platform_driver_register(&bfin_lq035q1_driver);
859}
860module_init(bfin_lq035q1_driver_init);
861
862static void __exit bfin_lq035q1_driver_cleanup(void)
863{
864 platform_driver_unregister(&bfin_lq035q1_driver);
865}
866module_exit(bfin_lq035q1_driver_cleanup);
867 858
868MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); 859MODULE_DESCRIPTION("Blackfin TFT LCD Driver");
869MODULE_LICENSE("GPL"); 860MODULE_LICENSE("GPL");
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 7a0c05f3537e..ae0fb24b8b43 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -447,6 +447,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
447 info = fbinfo->par; 447 info = fbinfo->par;
448 info->fb = fbinfo; 448 info->fb = fbinfo;
449 info->dev = &pdev->dev; 449 info->dev = &pdev->dev;
450 spin_lock_init(&info->lock);
450 451
451 platform_set_drvdata(pdev, fbinfo); 452 platform_set_drvdata(pdev, fbinfo);
452 453
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 7ba74cd4be61..6bea9a936798 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -319,8 +319,10 @@ static int __devinit bw2_probe(struct platform_device *op)
319 319
320 info->screen_base = of_ioremap(&op->resource[0], 0, 320 info->screen_base = of_ioremap(&op->resource[0], 0,
321 info->fix.smem_len, "bw2 ram"); 321 info->fix.smem_len, "bw2 ram");
322 if (!info->screen_base) 322 if (!info->screen_base) {
323 err = -ENOMEM;
323 goto out_unmap_regs; 324 goto out_unmap_regs;
325 }
324 326
325 bw2_blank(FB_BLANK_UNBLANK, info); 327 bw2_blank(FB_BLANK_UNBLANK, info);
326 328
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index f927a7b1a8d4..c5e7612ff876 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -398,7 +398,8 @@ static int __devinit cg3_probe(struct platform_device *op)
398 goto out_unmap_screen; 398 goto out_unmap_screen;
399 } 399 }
400 400
401 if (fb_alloc_cmap(&info->cmap, 256, 0)) 401 err = fb_alloc_cmap(&info->cmap, 256, 0);
402 if (err)
402 goto out_unmap_screen; 403 goto out_unmap_screen;
403 404
404 fb_set_cmap(&info->cmap, info); 405 fb_set_cmap(&info->cmap, info);
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index eae46f6457e2..01a4ee7cc6b1 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -348,7 +348,8 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
348 } 348 }
349 349
350 info->screen_size = resource_size(res); 350 info->screen_size = resource_size(res);
351 info->screen_base = ioremap(res->start, info->screen_size); 351 info->screen_base = devm_ioremap(&dev->dev, res->start,
352 info->screen_size);
352 info->fbops = &cobalt_lcd_fbops; 353 info->fbops = &cobalt_lcd_fbops;
353 info->fix = cobalt_lcdfb_fix; 354 info->fix = cobalt_lcdfb_fix;
354 info->fix.smem_start = res->start; 355 info->fix.smem_start = res->start;
@@ -359,7 +360,6 @@ static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
359 360
360 retval = register_framebuffer(info); 361 retval = register_framebuffer(info);
361 if (retval < 0) { 362 if (retval < 0) {
362 iounmap(info->screen_base);
363 framebuffer_release(info); 363 framebuffer_release(info);
364 return retval; 364 return retval;
365 } 365 }
@@ -380,7 +380,6 @@ static int __devexit cobalt_lcdfb_remove(struct platform_device *dev)
380 380
381 info = platform_get_drvdata(dev); 381 info = platform_get_drvdata(dev);
382 if (info) { 382 if (info) {
383 iounmap(info->screen_base);
384 unregister_framebuffer(info); 383 unregister_framebuffer(info);
385 framebuffer_release(info); 384 framebuffer_release(info);
386 } 385 }
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index fa6e698e63c4..838caa1cfef7 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -1092,7 +1092,7 @@ static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
1092 /*{*/ /* Char 124: '|' */ 1092 /*{*/ /* Char 124: '|' */
1093 0x44, /*= [ * ] */ 1093 0x44, /*= [ * ] */
1094 0x44, /*= [ * ] */ 1094 0x44, /*= [ * ] */
1095 0x00, /*= [ ] */ 1095 0x44, /*= [ * ] */
1096 0x44, /*= [ * ] */ 1096 0x44, /*= [ * ] */
1097 0x44, /*= [ * ] */ 1097 0x44, /*= [ * ] */
1098 0x00, /*= [ ] */ 1098 0x00, /*= [ ] */
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 5abf290c6eb7..268151325b83 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -127,7 +127,7 @@ static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
127/*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, 127/*y*/ 0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00,
128/*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, 128/*z*/ 0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00,
129/*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, 129/*{*/ 0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00,
130/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, 130/*|*/ 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
131/*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, 131/*}*/ 0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,
132/*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 132/*~*/ 0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, 133/* */ 0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00,
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index c1527f5b47ee..e40125cb313e 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1804,8 +1804,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
1804 1804
1805 cfb->irq = dev->irq; 1805 cfb->irq = dev->irq;
1806 cfb->region = pci_ioremap_bar(dev, 0); 1806 cfb->region = pci_ioremap_bar(dev, 0);
1807 if (!cfb->region) 1807 if (!cfb->region) {
1808 err = -ENOMEM;
1808 goto failed_ioremap; 1809 goto failed_ioremap;
1810 }
1809 1811
1810 cfb->regs = cfb->region + MMIO_OFFSET; 1812 cfb->regs = cfb->region + MMIO_OFFSET;
1811 cfb->fb.device = &dev->dev; 1813 cfb->fb.device = &dev->dev;
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 113d43a16f54..80665f66ac1a 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -26,7 +26,9 @@
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/uaccess.h> 28#include <linux/uaccess.h>
29#include <linux/pm_runtime.h>
29#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/wait.h>
30#include <linux/clk.h> 32#include <linux/clk.h>
31#include <linux/cpufreq.h> 33#include <linux/cpufreq.h>
32#include <linux/console.h> 34#include <linux/console.h>
@@ -48,6 +50,7 @@
48#define LCD_PL_LOAD_DONE BIT(6) 50#define LCD_PL_LOAD_DONE BIT(6)
49#define LCD_FIFO_UNDERFLOW BIT(5) 51#define LCD_FIFO_UNDERFLOW BIT(5)
50#define LCD_SYNC_LOST BIT(2) 52#define LCD_SYNC_LOST BIT(2)
53#define LCD_FRAME_DONE BIT(0)
51 54
52/* LCD DMA Control Register */ 55/* LCD DMA Control Register */
53#define LCD_DMA_BURST_SIZE(x) ((x) << 4) 56#define LCD_DMA_BURST_SIZE(x) ((x) << 4)
@@ -86,6 +89,8 @@
86#define LCD_V2_LIDD_CLK_EN BIT(1) 89#define LCD_V2_LIDD_CLK_EN BIT(1)
87#define LCD_V2_CORE_CLK_EN BIT(0) 90#define LCD_V2_CORE_CLK_EN BIT(0)
88#define LCD_V2_LPP_B10 26 91#define LCD_V2_LPP_B10 26
92#define LCD_V2_TFT_24BPP_MODE BIT(25)
93#define LCD_V2_TFT_24BPP_UNPACK BIT(26)
89 94
90/* LCD Raster Timing 2 Register */ 95/* LCD Raster Timing 2 Register */
91#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) 96#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16)
@@ -135,6 +140,8 @@ static void __iomem *da8xx_fb_reg_base;
135static struct resource *lcdc_regs; 140static struct resource *lcdc_regs;
136static unsigned int lcd_revision; 141static unsigned int lcd_revision;
137static irq_handler_t lcdc_irq_handler; 142static irq_handler_t lcdc_irq_handler;
143static wait_queue_head_t frame_done_wq;
144static int frame_done_flag;
138 145
139static inline unsigned int lcdc_read(unsigned int addr) 146static inline unsigned int lcdc_read(unsigned int addr)
140{ 147{
@@ -156,7 +163,6 @@ struct da8xx_fb_par {
156 unsigned int dma_end; 163 unsigned int dma_end;
157 struct clk *lcdc_clk; 164 struct clk *lcdc_clk;
158 int irq; 165 int irq;
159 unsigned short pseudo_palette[16];
160 unsigned int palette_sz; 166 unsigned int palette_sz;
161 unsigned int pxl_clk; 167 unsigned int pxl_clk;
162 int blank; 168 int blank;
@@ -175,6 +181,7 @@ struct da8xx_fb_par {
175 unsigned int lcd_fck_rate; 181 unsigned int lcd_fck_rate;
176#endif 182#endif
177 void (*panel_power_ctrl)(int); 183 void (*panel_power_ctrl)(int);
184 u32 pseudo_palette[16];
178}; 185};
179 186
180/* Variable Screen Information */ 187/* Variable Screen Information */
@@ -288,13 +295,26 @@ static inline void lcd_enable_raster(void)
288} 295}
289 296
290/* Disable the Raster Engine of the LCD Controller */ 297/* Disable the Raster Engine of the LCD Controller */
291static inline void lcd_disable_raster(void) 298static inline void lcd_disable_raster(bool wait_for_frame_done)
292{ 299{
293 u32 reg; 300 u32 reg;
301 int ret;
294 302
295 reg = lcdc_read(LCD_RASTER_CTRL_REG); 303 reg = lcdc_read(LCD_RASTER_CTRL_REG);
296 if (reg & LCD_RASTER_ENABLE) 304 if (reg & LCD_RASTER_ENABLE)
297 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); 305 lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
306 else
307 /* return if already disabled */
308 return;
309
310 if ((wait_for_frame_done == true) && (lcd_revision == LCD_VERSION_2)) {
311 frame_done_flag = 0;
312 ret = wait_event_interruptible_timeout(frame_done_wq,
313 frame_done_flag != 0,
314 msecs_to_jiffies(50));
315 if (ret == 0)
316 pr_err("LCD Controller timed out\n");
317 }
298} 318}
299 319
300static void lcd_blit(int load_mode, struct da8xx_fb_par *par) 320static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
@@ -321,7 +341,8 @@ static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
321 } else { 341 } else {
322 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | 342 reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) |
323 LCD_V2_END_OF_FRAME0_INT_ENA | 343 LCD_V2_END_OF_FRAME0_INT_ENA |
324 LCD_V2_END_OF_FRAME1_INT_ENA; 344 LCD_V2_END_OF_FRAME1_INT_ENA |
345 LCD_FRAME_DONE;
325 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); 346 lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG);
326 } 347 }
327 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; 348 reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE;
@@ -499,6 +520,9 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
499{ 520{
500 u32 reg; 521 u32 reg;
501 522
523 if (bpp > 16 && lcd_revision == LCD_VERSION_1)
524 return -EINVAL;
525
502 /* Set the Panel Width */ 526 /* Set the Panel Width */
503 /* Pixels per line = (PPL + 1)*16 */ 527 /* Pixels per line = (PPL + 1)*16 */
504 if (lcd_revision == LCD_VERSION_1) { 528 if (lcd_revision == LCD_VERSION_1) {
@@ -542,14 +566,19 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
542 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); 566 reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8);
543 if (raster_order) 567 if (raster_order)
544 reg |= LCD_RASTER_ORDER; 568 reg |= LCD_RASTER_ORDER;
545 lcdc_write(reg, LCD_RASTER_CTRL_REG); 569
570 par->palette_sz = 16 * 2;
546 571
547 switch (bpp) { 572 switch (bpp) {
548 case 1: 573 case 1:
549 case 2: 574 case 2:
550 case 4: 575 case 4:
551 case 16: 576 case 16:
552 par->palette_sz = 16 * 2; 577 break;
578 case 24:
579 reg |= LCD_V2_TFT_24BPP_MODE;
580 case 32:
581 reg |= LCD_V2_TFT_24BPP_UNPACK;
553 break; 582 break;
554 583
555 case 8: 584 case 8:
@@ -560,9 +589,12 @@ static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height,
560 return -EINVAL; 589 return -EINVAL;
561 } 590 }
562 591
592 lcdc_write(reg, LCD_RASTER_CTRL_REG);
593
563 return 0; 594 return 0;
564} 595}
565 596
597#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
566static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, 598static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
567 unsigned blue, unsigned transp, 599 unsigned blue, unsigned transp,
568 struct fb_info *info) 600 struct fb_info *info)
@@ -578,13 +610,38 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
578 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 610 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
579 return 1; 611 return 1;
580 612
581 if (info->var.bits_per_pixel == 4) { 613 if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
582 if (regno > 15) 614 return -EINVAL;
583 return 1;
584 615
585 if (info->var.grayscale) { 616 switch (info->fix.visual) {
586 pal = regno; 617 case FB_VISUAL_TRUECOLOR:
587 } else { 618 red = CNVT_TOHW(red, info->var.red.length);
619 green = CNVT_TOHW(green, info->var.green.length);
620 blue = CNVT_TOHW(blue, info->var.blue.length);
621 break;
622 case FB_VISUAL_PSEUDOCOLOR:
623 switch (info->var.bits_per_pixel) {
624 case 4:
625 if (regno > 15)
626 return -EINVAL;
627
628 if (info->var.grayscale) {
629 pal = regno;
630 } else {
631 red >>= 4;
632 green >>= 8;
633 blue >>= 12;
634
635 pal = red & 0x0f00;
636 pal |= green & 0x00f0;
637 pal |= blue & 0x000f;
638 }
639 if (regno == 0)
640 pal |= 0x2000;
641 palette[regno] = pal;
642 break;
643
644 case 8:
588 red >>= 4; 645 red >>= 4;
589 green >>= 8; 646 green >>= 8;
590 blue >>= 12; 647 blue >>= 12;
@@ -592,36 +649,36 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
592 pal = (red & 0x0f00); 649 pal = (red & 0x0f00);
593 pal |= (green & 0x00f0); 650 pal |= (green & 0x00f0);
594 pal |= (blue & 0x000f); 651 pal |= (blue & 0x000f);
595 }
596 if (regno == 0)
597 pal |= 0x2000;
598 palette[regno] = pal;
599
600 } else if (info->var.bits_per_pixel == 8) {
601 red >>= 4;
602 green >>= 8;
603 blue >>= 12;
604
605 pal = (red & 0x0f00);
606 pal |= (green & 0x00f0);
607 pal |= (blue & 0x000f);
608 652
609 if (palette[regno] != pal) { 653 if (palette[regno] != pal) {
610 update_hw = 1; 654 update_hw = 1;
611 palette[regno] = pal; 655 palette[regno] = pal;
656 }
657 break;
612 } 658 }
613 } else if ((info->var.bits_per_pixel == 16) && regno < 16) { 659 break;
614 red >>= (16 - info->var.red.length); 660 }
615 red <<= info->var.red.offset;
616 661
617 green >>= (16 - info->var.green.length); 662 /* Truecolor has hardware independent palette */
618 green <<= info->var.green.offset; 663 if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
664 u32 v;
619 665
620 blue >>= (16 - info->var.blue.length); 666 if (regno > 15)
621 blue <<= info->var.blue.offset; 667 return -EINVAL;
622 668
623 par->pseudo_palette[regno] = red | green | blue; 669 v = (red << info->var.red.offset) |
670 (green << info->var.green.offset) |
671 (blue << info->var.blue.offset);
624 672
673 switch (info->var.bits_per_pixel) {
674 case 16:
675 ((u16 *) (info->pseudo_palette))[regno] = v;
676 break;
677 case 24:
678 case 32:
679 ((u32 *) (info->pseudo_palette))[regno] = v;
680 break;
681 }
625 if (palette[0] != 0x4000) { 682 if (palette[0] != 0x4000) {
626 update_hw = 1; 683 update_hw = 1;
627 palette[0] = 0x4000; 684 palette[0] = 0x4000;
@@ -634,11 +691,12 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
634 691
635 return 0; 692 return 0;
636} 693}
694#undef CNVT_TOHW
637 695
638static void lcd_reset(struct da8xx_fb_par *par) 696static void lcd_reset(struct da8xx_fb_par *par)
639{ 697{
640 /* Disable the Raster if previously Enabled */ 698 /* Disable the Raster if previously Enabled */
641 lcd_disable_raster(); 699 lcd_disable_raster(false);
642 700
643 /* DMA has to be disabled */ 701 /* DMA has to be disabled */
644 lcdc_write(0, LCD_DMA_CTRL_REG); 702 lcdc_write(0, LCD_DMA_CTRL_REG);
@@ -734,7 +792,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
734 u32 stat = lcdc_read(LCD_MASKED_STAT_REG); 792 u32 stat = lcdc_read(LCD_MASKED_STAT_REG);
735 793
736 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 794 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
737 lcd_disable_raster(); 795 lcd_disable_raster(false);
738 lcdc_write(stat, LCD_MASKED_STAT_REG); 796 lcdc_write(stat, LCD_MASKED_STAT_REG);
739 lcd_enable_raster(); 797 lcd_enable_raster();
740 } else if (stat & LCD_PL_LOAD_DONE) { 798 } else if (stat & LCD_PL_LOAD_DONE) {
@@ -744,7 +802,7 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
744 * interrupt via the following write to the status register. If 802 * interrupt via the following write to the status register. If
745 * this is done after then one gets multiple PL done interrupts. 803 * this is done after then one gets multiple PL done interrupts.
746 */ 804 */
747 lcd_disable_raster(); 805 lcd_disable_raster(false);
748 806
749 lcdc_write(stat, LCD_MASKED_STAT_REG); 807 lcdc_write(stat, LCD_MASKED_STAT_REG);
750 808
@@ -775,6 +833,14 @@ static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg)
775 par->vsync_flag = 1; 833 par->vsync_flag = 1;
776 wake_up_interruptible(&par->vsync_wait); 834 wake_up_interruptible(&par->vsync_wait);
777 } 835 }
836
837 /* Set only when controller is disabled and at the end of
838 * active frame
839 */
840 if (stat & BIT(0)) {
841 frame_done_flag = 1;
842 wake_up_interruptible(&frame_done_wq);
843 }
778 } 844 }
779 845
780 lcdc_write(0, LCD_END_OF_INT_IND_REG); 846 lcdc_write(0, LCD_END_OF_INT_IND_REG);
@@ -789,7 +855,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
789 u32 reg_ras; 855 u32 reg_ras;
790 856
791 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { 857 if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) {
792 lcd_disable_raster(); 858 lcd_disable_raster(false);
793 lcdc_write(stat, LCD_STAT_REG); 859 lcdc_write(stat, LCD_STAT_REG);
794 lcd_enable_raster(); 860 lcd_enable_raster();
795 } else if (stat & LCD_PL_LOAD_DONE) { 861 } else if (stat & LCD_PL_LOAD_DONE) {
@@ -799,7 +865,7 @@ static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg)
799 * interrupt via the following write to the status register. If 865 * interrupt via the following write to the status register. If
800 * this is done after then one gets multiple PL done interrupts. 866 * this is done after then one gets multiple PL done interrupts.
801 */ 867 */
802 lcd_disable_raster(); 868 lcd_disable_raster(false);
803 869
804 lcdc_write(stat, LCD_STAT_REG); 870 lcdc_write(stat, LCD_STAT_REG);
805 871
@@ -842,6 +908,9 @@ static int fb_check_var(struct fb_var_screeninfo *var,
842{ 908{
843 int err = 0; 909 int err = 0;
844 910
911 if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1)
912 return -EINVAL;
913
845 switch (var->bits_per_pixel) { 914 switch (var->bits_per_pixel) {
846 case 1: 915 case 1:
847 case 8: 916 case 8:
@@ -877,6 +946,26 @@ static int fb_check_var(struct fb_var_screeninfo *var,
877 var->transp.length = 0; 946 var->transp.length = 0;
878 var->nonstd = 0; 947 var->nonstd = 0;
879 break; 948 break;
949 case 24:
950 var->red.offset = 16;
951 var->red.length = 8;
952 var->green.offset = 8;
953 var->green.length = 8;
954 var->blue.offset = 0;
955 var->blue.length = 8;
956 var->nonstd = 0;
957 break;
958 case 32:
959 var->transp.offset = 24;
960 var->transp.length = 8;
961 var->red.offset = 16;
962 var->red.length = 8;
963 var->green.offset = 8;
964 var->green.length = 8;
965 var->blue.offset = 0;
966 var->blue.length = 8;
967 var->nonstd = 0;
968 break;
880 default: 969 default:
881 err = -EINVAL; 970 err = -EINVAL;
882 } 971 }
@@ -898,9 +987,10 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
898 if (val == CPUFREQ_POSTCHANGE) { 987 if (val == CPUFREQ_POSTCHANGE) {
899 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) { 988 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
900 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk); 989 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
901 lcd_disable_raster(); 990 lcd_disable_raster(true);
902 lcd_calc_clk_divider(par); 991 lcd_calc_clk_divider(par);
903 lcd_enable_raster(); 992 if (par->blank == FB_BLANK_UNBLANK)
993 lcd_enable_raster();
904 } 994 }
905 } 995 }
906 996
@@ -935,7 +1025,7 @@ static int __devexit fb_remove(struct platform_device *dev)
935 if (par->panel_power_ctrl) 1025 if (par->panel_power_ctrl)
936 par->panel_power_ctrl(0); 1026 par->panel_power_ctrl(0);
937 1027
938 lcd_disable_raster(); 1028 lcd_disable_raster(true);
939 lcdc_write(0, LCD_RASTER_CTRL_REG); 1029 lcdc_write(0, LCD_RASTER_CTRL_REG);
940 1030
941 /* disable DMA */ 1031 /* disable DMA */
@@ -948,8 +1038,8 @@ static int __devexit fb_remove(struct platform_device *dev)
948 dma_free_coherent(NULL, par->vram_size, par->vram_virt, 1038 dma_free_coherent(NULL, par->vram_size, par->vram_virt,
949 par->vram_phys); 1039 par->vram_phys);
950 free_irq(par->irq, par); 1040 free_irq(par->irq, par);
951 clk_disable(par->lcdc_clk); 1041 pm_runtime_put_sync(&dev->dev);
952 clk_put(par->lcdc_clk); 1042 pm_runtime_disable(&dev->dev);
953 framebuffer_release(info); 1043 framebuffer_release(info);
954 iounmap(da8xx_fb_reg_base); 1044 iounmap(da8xx_fb_reg_base);
955 release_mem_region(lcdc_regs->start, resource_size(lcdc_regs)); 1045 release_mem_region(lcdc_regs->start, resource_size(lcdc_regs));
@@ -1051,7 +1141,7 @@ static int cfb_blank(int blank, struct fb_info *info)
1051 if (par->panel_power_ctrl) 1141 if (par->panel_power_ctrl)
1052 par->panel_power_ctrl(0); 1142 par->panel_power_ctrl(0);
1053 1143
1054 lcd_disable_raster(); 1144 lcd_disable_raster(true);
1055 break; 1145 break;
1056 default: 1146 default:
1057 ret = -EINVAL; 1147 ret = -EINVAL;
@@ -1183,9 +1273,9 @@ static int __devinit fb_probe(struct platform_device *device)
1183 ret = -ENODEV; 1273 ret = -ENODEV;
1184 goto err_ioremap; 1274 goto err_ioremap;
1185 } 1275 }
1186 ret = clk_enable(fb_clk); 1276
1187 if (ret) 1277 pm_runtime_enable(&device->dev);
1188 goto err_clk_put; 1278 pm_runtime_get_sync(&device->dev);
1189 1279
1190 /* Determine LCD IP Version */ 1280 /* Determine LCD IP Version */
1191 switch (lcdc_read(LCD_PID_REG)) { 1281 switch (lcdc_read(LCD_PID_REG)) {
@@ -1213,7 +1303,7 @@ static int __devinit fb_probe(struct platform_device *device)
1213 if (i == ARRAY_SIZE(known_lcd_panels)) { 1303 if (i == ARRAY_SIZE(known_lcd_panels)) {
1214 dev_err(&device->dev, "GLCD: No valid panel found\n"); 1304 dev_err(&device->dev, "GLCD: No valid panel found\n");
1215 ret = -ENODEV; 1305 ret = -ENODEV;
1216 goto err_clk_disable; 1306 goto err_pm_runtime_disable;
1217 } else 1307 } else
1218 dev_info(&device->dev, "GLCD: Found %s panel\n", 1308 dev_info(&device->dev, "GLCD: Found %s panel\n",
1219 fb_pdata->type); 1309 fb_pdata->type);
@@ -1225,7 +1315,7 @@ static int __devinit fb_probe(struct platform_device *device)
1225 if (!da8xx_fb_info) { 1315 if (!da8xx_fb_info) {
1226 dev_dbg(&device->dev, "Memory allocation failed for fb_info\n"); 1316 dev_dbg(&device->dev, "Memory allocation failed for fb_info\n");
1227 ret = -ENOMEM; 1317 ret = -ENOMEM;
1228 goto err_clk_disable; 1318 goto err_pm_runtime_disable;
1229 } 1319 }
1230 1320
1231 par = da8xx_fb_info->par; 1321 par = da8xx_fb_info->par;
@@ -1356,8 +1446,10 @@ static int __devinit fb_probe(struct platform_device *device)
1356 1446
1357 if (lcd_revision == LCD_VERSION_1) 1447 if (lcd_revision == LCD_VERSION_1)
1358 lcdc_irq_handler = lcdc_irq_handler_rev01; 1448 lcdc_irq_handler = lcdc_irq_handler_rev01;
1359 else 1449 else {
1450 init_waitqueue_head(&frame_done_wq);
1360 lcdc_irq_handler = lcdc_irq_handler_rev02; 1451 lcdc_irq_handler = lcdc_irq_handler_rev02;
1452 }
1361 1453
1362 ret = request_irq(par->irq, lcdc_irq_handler, 0, 1454 ret = request_irq(par->irq, lcdc_irq_handler, 0,
1363 DRIVER_NAME, par); 1455 DRIVER_NAME, par);
@@ -1385,11 +1477,9 @@ err_release_fb_mem:
1385err_release_fb: 1477err_release_fb:
1386 framebuffer_release(da8xx_fb_info); 1478 framebuffer_release(da8xx_fb_info);
1387 1479
1388err_clk_disable: 1480err_pm_runtime_disable:
1389 clk_disable(fb_clk); 1481 pm_runtime_put_sync(&device->dev);
1390 1482 pm_runtime_disable(&device->dev);
1391err_clk_put:
1392 clk_put(fb_clk);
1393 1483
1394err_ioremap: 1484err_ioremap:
1395 iounmap(da8xx_fb_reg_base); 1485 iounmap(da8xx_fb_reg_base);
@@ -1401,6 +1491,69 @@ err_request_mem:
1401} 1491}
1402 1492
1403#ifdef CONFIG_PM 1493#ifdef CONFIG_PM
1494struct lcdc_context {
1495 u32 clk_enable;
1496 u32 ctrl;
1497 u32 dma_ctrl;
1498 u32 raster_timing_0;
1499 u32 raster_timing_1;
1500 u32 raster_timing_2;
1501 u32 int_enable_set;
1502 u32 dma_frm_buf_base_addr_0;
1503 u32 dma_frm_buf_ceiling_addr_0;
1504 u32 dma_frm_buf_base_addr_1;
1505 u32 dma_frm_buf_ceiling_addr_1;
1506 u32 raster_ctrl;
1507} reg_context;
1508
1509static void lcd_context_save(void)
1510{
1511 if (lcd_revision == LCD_VERSION_2) {
1512 reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG);
1513 reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG);
1514 }
1515
1516 reg_context.ctrl = lcdc_read(LCD_CTRL_REG);
1517 reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG);
1518 reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG);
1519 reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG);
1520 reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG);
1521 reg_context.dma_frm_buf_base_addr_0 =
1522 lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
1523 reg_context.dma_frm_buf_ceiling_addr_0 =
1524 lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
1525 reg_context.dma_frm_buf_base_addr_1 =
1526 lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
1527 reg_context.dma_frm_buf_ceiling_addr_1 =
1528 lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
1529 reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG);
1530 return;
1531}
1532
1533static void lcd_context_restore(void)
1534{
1535 if (lcd_revision == LCD_VERSION_2) {
1536 lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG);
1537 lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG);
1538 }
1539
1540 lcdc_write(reg_context.ctrl, LCD_CTRL_REG);
1541 lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG);
1542 lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG);
1543 lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG);
1544 lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG);
1545 lcdc_write(reg_context.dma_frm_buf_base_addr_0,
1546 LCD_DMA_FRM_BUF_BASE_ADDR_0_REG);
1547 lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0,
1548 LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG);
1549 lcdc_write(reg_context.dma_frm_buf_base_addr_1,
1550 LCD_DMA_FRM_BUF_BASE_ADDR_1_REG);
1551 lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1,
1552 LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG);
1553 lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG);
1554 return;
1555}
1556
1404static int fb_suspend(struct platform_device *dev, pm_message_t state) 1557static int fb_suspend(struct platform_device *dev, pm_message_t state)
1405{ 1558{
1406 struct fb_info *info = platform_get_drvdata(dev); 1559 struct fb_info *info = platform_get_drvdata(dev);
@@ -1411,8 +1564,9 @@ static int fb_suspend(struct platform_device *dev, pm_message_t state)
1411 par->panel_power_ctrl(0); 1564 par->panel_power_ctrl(0);
1412 1565
1413 fb_set_suspend(info, 1); 1566 fb_set_suspend(info, 1);
1414 lcd_disable_raster(); 1567 lcd_disable_raster(true);
1415 clk_disable(par->lcdc_clk); 1568 lcd_context_save();
1569 pm_runtime_put_sync(&dev->dev);
1416 console_unlock(); 1570 console_unlock();
1417 1571
1418 return 0; 1572 return 0;
@@ -1423,11 +1577,14 @@ static int fb_resume(struct platform_device *dev)
1423 struct da8xx_fb_par *par = info->par; 1577 struct da8xx_fb_par *par = info->par;
1424 1578
1425 console_lock(); 1579 console_lock();
1426 clk_enable(par->lcdc_clk); 1580 pm_runtime_get_sync(&dev->dev);
1427 lcd_enable_raster(); 1581 lcd_context_restore();
1582 if (par->blank == FB_BLANK_UNBLANK) {
1583 lcd_enable_raster();
1428 1584
1429 if (par->panel_power_ctrl) 1585 if (par->panel_power_ctrl)
1430 par->panel_power_ctrl(1); 1586 par->panel_power_ctrl(1);
1587 }
1431 1588
1432 fb_set_suspend(info, 0); 1589 fb_set_suspend(info, 0);
1433 console_unlock(); 1590 console_unlock();
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c
index f2c092da84b0..755ef3e65caf 100644
--- a/drivers/video/ep93xx-fb.c
+++ b/drivers/video/ep93xx-fb.c
@@ -529,7 +529,8 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
529 * any of the framebuffer registers. 529 * any of the framebuffer registers.
530 */ 530 */
531 fbi->res = res; 531 fbi->res = res;
532 fbi->mmio_base = ioremap(res->start, resource_size(res)); 532 fbi->mmio_base = devm_ioremap(&pdev->dev, res->start,
533 resource_size(res));
533 if (!fbi->mmio_base) { 534 if (!fbi->mmio_base) {
534 err = -ENXIO; 535 err = -ENXIO;
535 goto failed_resource; 536 goto failed_resource;
@@ -553,20 +554,20 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
553 if (err == 0) { 554 if (err == 0) {
554 dev_err(info->dev, "No suitable video mode found\n"); 555 dev_err(info->dev, "No suitable video mode found\n");
555 err = -EINVAL; 556 err = -EINVAL;
556 goto failed_mode; 557 goto failed_resource;
557 } 558 }
558 559
559 if (mach_info->setup) { 560 if (mach_info->setup) {
560 err = mach_info->setup(pdev); 561 err = mach_info->setup(pdev);
561 if (err) 562 if (err)
562 goto failed_mode; 563 goto failed_resource;
563 } 564 }
564 565
565 err = ep93xxfb_check_var(&info->var, info); 566 err = ep93xxfb_check_var(&info->var, info);
566 if (err) 567 if (err)
567 goto failed_check; 568 goto failed_check;
568 569
569 fbi->clk = clk_get(info->dev, NULL); 570 fbi->clk = devm_clk_get(&pdev->dev, NULL);
570 if (IS_ERR(fbi->clk)) { 571 if (IS_ERR(fbi->clk)) {
571 err = PTR_ERR(fbi->clk); 572 err = PTR_ERR(fbi->clk);
572 fbi->clk = NULL; 573 fbi->clk = NULL;
@@ -578,19 +579,15 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
578 579
579 err = register_framebuffer(info); 580 err = register_framebuffer(info);
580 if (err) 581 if (err)
581 goto failed; 582 goto failed_check;
582 583
583 dev_info(info->dev, "registered. Mode = %dx%d-%d\n", 584 dev_info(info->dev, "registered. Mode = %dx%d-%d\n",
584 info->var.xres, info->var.yres, info->var.bits_per_pixel); 585 info->var.xres, info->var.yres, info->var.bits_per_pixel);
585 return 0; 586 return 0;
586 587
587failed:
588 clk_put(fbi->clk);
589failed_check: 588failed_check:
590 if (fbi->mach_info->teardown) 589 if (fbi->mach_info->teardown)
591 fbi->mach_info->teardown(pdev); 590 fbi->mach_info->teardown(pdev);
592failed_mode:
593 iounmap(fbi->mmio_base);
594failed_resource: 591failed_resource:
595 ep93xxfb_dealloc_videomem(info); 592 ep93xxfb_dealloc_videomem(info);
596failed_videomem: 593failed_videomem:
@@ -609,8 +606,6 @@ static int __devexit ep93xxfb_remove(struct platform_device *pdev)
609 606
610 unregister_framebuffer(info); 607 unregister_framebuffer(info);
611 clk_disable(fbi->clk); 608 clk_disable(fbi->clk);
612 clk_put(fbi->clk);
613 iounmap(fbi->mmio_base);
614 ep93xxfb_dealloc_videomem(info); 609 ep93xxfb_dealloc_videomem(info);
615 fb_dealloc_cmap(&info->cmap); 610 fb_dealloc_cmap(&info->cmap);
616 611
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index c6c016a506ce..d55470e75412 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -29,6 +29,9 @@ static int exynos_dp_init_dp(struct exynos_dp_device *dp)
29 29
30 exynos_dp_swreset(dp); 30 exynos_dp_swreset(dp);
31 31
32 exynos_dp_init_analog_param(dp);
33 exynos_dp_init_interrupt(dp);
34
32 /* SW defined function Normal operation */ 35 /* SW defined function Normal operation */
33 exynos_dp_enable_sw_function(dp); 36 exynos_dp_enable_sw_function(dp);
34 37
@@ -260,7 +263,7 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
260 263
261static void exynos_dp_link_start(struct exynos_dp_device *dp) 264static void exynos_dp_link_start(struct exynos_dp_device *dp)
262{ 265{
263 u8 buf[5]; 266 u8 buf[4];
264 int lane; 267 int lane;
265 int lane_count; 268 int lane_count;
266 269
@@ -295,10 +298,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
295 exynos_dp_set_training_pattern(dp, TRAINING_PTN1); 298 exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
296 299
297 /* Set RX training pattern */ 300 /* Set RX training pattern */
298 buf[0] = DPCD_SCRAMBLING_DISABLED |
299 DPCD_TRAINING_PATTERN_1;
300 exynos_dp_write_byte_to_dpcd(dp, 301 exynos_dp_write_byte_to_dpcd(dp,
301 DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]); 302 DPCD_ADDR_TRAINING_PATTERN_SET,
303 DPCD_SCRAMBLING_DISABLED |
304 DPCD_TRAINING_PATTERN_1);
302 305
303 for (lane = 0; lane < lane_count; lane++) 306 for (lane = 0; lane < lane_count; lane++)
304 buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | 307 buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
@@ -308,7 +311,7 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp)
308 lane_count, buf); 311 lane_count, buf);
309} 312}
310 313
311static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane) 314static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
312{ 315{
313 int shift = (lane & 1) * 4; 316 int shift = (lane & 1) * 4;
314 u8 link_value = link_status[lane>>1]; 317 u8 link_value = link_status[lane>>1];
@@ -316,7 +319,7 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
316 return (link_value >> shift) & 0xf; 319 return (link_value >> shift) & 0xf;
317} 320}
318 321
319static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count) 322static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count)
320{ 323{
321 int lane; 324 int lane;
322 u8 lane_status; 325 u8 lane_status;
@@ -329,22 +332,23 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
329 return 0; 332 return 0;
330} 333}
331 334
332static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count) 335static int exynos_dp_channel_eq_ok(u8 link_align[3], int lane_count)
333{ 336{
334 int lane; 337 int lane;
335 u8 lane_align; 338 u8 lane_align;
336 u8 lane_status; 339 u8 lane_status;
337 340
338 lane_align = link_status[2]; 341 lane_align = link_align[2];
339 if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0) 342 if ((lane_align & DPCD_INTERLANE_ALIGN_DONE) == 0)
340 return -EINVAL; 343 return -EINVAL;
341 344
342 for (lane = 0; lane < lane_count; lane++) { 345 for (lane = 0; lane < lane_count; lane++) {
343 lane_status = exynos_dp_get_lane_status(link_status, lane); 346 lane_status = exynos_dp_get_lane_status(link_align, lane);
344 lane_status &= DPCD_CHANNEL_EQ_BITS; 347 lane_status &= DPCD_CHANNEL_EQ_BITS;
345 if (lane_status != DPCD_CHANNEL_EQ_BITS) 348 if (lane_status != DPCD_CHANNEL_EQ_BITS)
346 return -EINVAL; 349 return -EINVAL;
347 } 350 }
351
348 return 0; 352 return 0;
349} 353}
350 354
@@ -417,69 +421,17 @@ static unsigned int exynos_dp_get_lane_link_training(
417 421
418static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) 422static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
419{ 423{
420 if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) { 424 exynos_dp_training_pattern_dis(dp);
421 /* set to reduced bit rate */ 425 exynos_dp_set_enhanced_mode(dp);
422 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
423 dev_err(dp->dev, "set to bandwidth %.2x\n",
424 dp->link_train.link_rate);
425 dp->link_train.lt_state = START;
426 } else {
427 exynos_dp_training_pattern_dis(dp);
428 /* set enhanced mode if available */
429 exynos_dp_set_enhanced_mode(dp);
430 dp->link_train.lt_state = FAILED;
431 }
432}
433 426
434static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp, 427 dp->link_train.lt_state = FAILED;
435 u8 adjust_request[2])
436{
437 int lane;
438 int lane_count;
439 u8 voltage_swing;
440 u8 pre_emphasis;
441 u8 training_lane;
442
443 lane_count = dp->link_train.lane_count;
444 for (lane = 0; lane < lane_count; lane++) {
445 voltage_swing = exynos_dp_get_adjust_request_voltage(
446 adjust_request, lane);
447 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
448 adjust_request, lane);
449 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
450 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
451
452 if (voltage_swing == VOLTAGE_LEVEL_3 ||
453 pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
454 training_lane |= DPCD_MAX_SWING_REACHED;
455 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
456 }
457 dp->link_train.training_lane[lane] = training_lane;
458 }
459}
460
461static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
462 u8 voltage_swing)
463{
464 int lane;
465 int lane_count;
466
467 lane_count = dp->link_train.lane_count;
468 for (lane = 0; lane < lane_count; lane++) {
469 if (voltage_swing == VOLTAGE_LEVEL_3 ||
470 dp->link_train.cr_loop[lane] == MAX_CR_LOOP)
471 return -EINVAL;
472 }
473 return 0;
474} 428}
475 429
476static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) 430static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
477{ 431{
478 u8 data; 432 u8 link_status[2];
479 u8 link_status[6];
480 int lane; 433 int lane;
481 int lane_count; 434 int lane_count;
482 u8 buf[5];
483 435
484 u8 adjust_request[2]; 436 u8 adjust_request[2];
485 u8 voltage_swing; 437 u8 voltage_swing;
@@ -488,100 +440,154 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
488 440
489 usleep_range(100, 101); 441 usleep_range(100, 101);
490 442
491 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
492 6, link_status);
493 lane_count = dp->link_train.lane_count; 443 lane_count = dp->link_train.lane_count;
494 444
445 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
446 2, link_status);
447
495 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { 448 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
496 /* set training pattern 2 for EQ */ 449 /* set training pattern 2 for EQ */
497 exynos_dp_set_training_pattern(dp, TRAINING_PTN2); 450 exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
498 451
499 adjust_request[0] = link_status[4]; 452 for (lane = 0; lane < lane_count; lane++) {
500 adjust_request[1] = link_status[5]; 453 exynos_dp_read_bytes_from_dpcd(dp,
454 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
455 2, adjust_request);
456 voltage_swing = exynos_dp_get_adjust_request_voltage(
457 adjust_request, lane);
458 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
459 adjust_request, lane);
460 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
461 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
501 462
502 exynos_dp_get_adjust_train(dp, adjust_request); 463 if (voltage_swing == VOLTAGE_LEVEL_3)
464 training_lane |= DPCD_MAX_SWING_REACHED;
465 if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
466 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
503 467
504 buf[0] = DPCD_SCRAMBLING_DISABLED | 468 dp->link_train.training_lane[lane] = training_lane;
505 DPCD_TRAINING_PATTERN_2;
506 exynos_dp_write_byte_to_dpcd(dp,
507 DPCD_ADDR_TRAINING_PATTERN_SET,
508 buf[0]);
509 469
510 for (lane = 0; lane < lane_count; lane++) {
511 exynos_dp_set_lane_link_training(dp, 470 exynos_dp_set_lane_link_training(dp,
512 dp->link_train.training_lane[lane], 471 dp->link_train.training_lane[lane],
513 lane); 472 lane);
514 buf[lane] = dp->link_train.training_lane[lane];
515 exynos_dp_write_byte_to_dpcd(dp,
516 DPCD_ADDR_TRAINING_LANE0_SET + lane,
517 buf[lane]);
518 } 473 }
519 dp->link_train.lt_state = EQUALIZER_TRAINING;
520 } else {
521 exynos_dp_read_byte_from_dpcd(dp,
522 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
523 &data);
524 adjust_request[0] = data;
525 474
526 exynos_dp_read_byte_from_dpcd(dp, 475 exynos_dp_write_byte_to_dpcd(dp,
527 DPCD_ADDR_ADJUST_REQUEST_LANE2_3, 476 DPCD_ADDR_TRAINING_PATTERN_SET,
528 &data); 477 DPCD_SCRAMBLING_DISABLED |
529 adjust_request[1] = data; 478 DPCD_TRAINING_PATTERN_2);
479
480 exynos_dp_write_bytes_to_dpcd(dp,
481 DPCD_ADDR_TRAINING_LANE0_SET,
482 lane_count,
483 dp->link_train.training_lane);
530 484
485 dev_info(dp->dev, "Link Training Clock Recovery success\n");
486 dp->link_train.lt_state = EQUALIZER_TRAINING;
487 } else {
531 for (lane = 0; lane < lane_count; lane++) { 488 for (lane = 0; lane < lane_count; lane++) {
532 training_lane = exynos_dp_get_lane_link_training( 489 training_lane = exynos_dp_get_lane_link_training(
533 dp, lane); 490 dp, lane);
491 exynos_dp_read_bytes_from_dpcd(dp,
492 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
493 2, adjust_request);
534 voltage_swing = exynos_dp_get_adjust_request_voltage( 494 voltage_swing = exynos_dp_get_adjust_request_voltage(
535 adjust_request, lane); 495 adjust_request, lane);
536 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( 496 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
537 adjust_request, lane); 497 adjust_request, lane);
538 if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
539 (DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
540 dp->link_train.cr_loop[lane]++;
541 dp->link_train.training_lane[lane] = training_lane;
542 }
543 498
544 if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) { 499 if (voltage_swing == VOLTAGE_LEVEL_3 ||
545 exynos_dp_reduce_link_rate(dp); 500 pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
546 } else { 501 dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
547 exynos_dp_get_adjust_train(dp, adjust_request); 502 goto reduce_link_rate;
503 }
548 504
549 for (lane = 0; lane < lane_count; lane++) { 505 if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
550 exynos_dp_set_lane_link_training(dp, 506 voltage_swing) &&
551 dp->link_train.training_lane[lane], 507 (DPCD_PRE_EMPHASIS_GET(training_lane) ==
552 lane); 508 pre_emphasis)) {
553 buf[lane] = dp->link_train.training_lane[lane]; 509 dp->link_train.cr_loop[lane]++;
554 exynos_dp_write_byte_to_dpcd(dp, 510 if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
555 DPCD_ADDR_TRAINING_LANE0_SET + lane, 511 dev_err(dp->dev, "CR Max loop\n");
556 buf[lane]); 512 goto reduce_link_rate;
513 }
557 } 514 }
515
516 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
517 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
518
519 if (voltage_swing == VOLTAGE_LEVEL_3)
520 training_lane |= DPCD_MAX_SWING_REACHED;
521 if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
522 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
523
524 dp->link_train.training_lane[lane] = training_lane;
525
526 exynos_dp_set_lane_link_training(dp,
527 dp->link_train.training_lane[lane], lane);
558 } 528 }
529
530 exynos_dp_write_bytes_to_dpcd(dp,
531 DPCD_ADDR_TRAINING_LANE0_SET,
532 lane_count,
533 dp->link_train.training_lane);
559 } 534 }
560 535
561 return 0; 536 return 0;
537
538reduce_link_rate:
539 exynos_dp_reduce_link_rate(dp);
540 return -EIO;
562} 541}
563 542
564static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) 543static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
565{ 544{
566 u8 link_status[6]; 545 u8 link_status[2];
546 u8 link_align[3];
567 int lane; 547 int lane;
568 int lane_count; 548 int lane_count;
569 u8 buf[5];
570 u32 reg; 549 u32 reg;
571 550
572 u8 adjust_request[2]; 551 u8 adjust_request[2];
552 u8 voltage_swing;
553 u8 pre_emphasis;
554 u8 training_lane;
573 555
574 usleep_range(400, 401); 556 usleep_range(400, 401);
575 557
576 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
577 6, link_status);
578 lane_count = dp->link_train.lane_count; 558 lane_count = dp->link_train.lane_count;
579 559
560 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
561 2, link_status);
562
580 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { 563 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
581 adjust_request[0] = link_status[4]; 564 link_align[0] = link_status[0];
582 adjust_request[1] = link_status[5]; 565 link_align[1] = link_status[1];
583 566
584 if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) { 567 exynos_dp_read_byte_from_dpcd(dp,
568 DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
569 &link_align[2]);
570
571 for (lane = 0; lane < lane_count; lane++) {
572 exynos_dp_read_bytes_from_dpcd(dp,
573 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
574 2, adjust_request);
575 voltage_swing = exynos_dp_get_adjust_request_voltage(
576 adjust_request, lane);
577 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
578 adjust_request, lane);
579 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
580 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
581
582 if (voltage_swing == VOLTAGE_LEVEL_3)
583 training_lane |= DPCD_MAX_SWING_REACHED;
584 if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
585 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
586
587 dp->link_train.training_lane[lane] = training_lane;
588 }
589
590 if (exynos_dp_channel_eq_ok(link_align, lane_count) == 0) {
585 /* traing pattern Set to Normal */ 591 /* traing pattern Set to Normal */
586 exynos_dp_training_pattern_dis(dp); 592 exynos_dp_training_pattern_dis(dp);
587 593
@@ -596,39 +602,42 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
596 dp->link_train.lane_count = reg; 602 dp->link_train.lane_count = reg;
597 dev_dbg(dp->dev, "final lane count = %.2x\n", 603 dev_dbg(dp->dev, "final lane count = %.2x\n",
598 dp->link_train.lane_count); 604 dp->link_train.lane_count);
605
599 /* set enhanced mode if available */ 606 /* set enhanced mode if available */
600 exynos_dp_set_enhanced_mode(dp); 607 exynos_dp_set_enhanced_mode(dp);
601
602 dp->link_train.lt_state = FINISHED; 608 dp->link_train.lt_state = FINISHED;
603 } else { 609 } else {
604 /* not all locked */ 610 /* not all locked */
605 dp->link_train.eq_loop++; 611 dp->link_train.eq_loop++;
606 612
607 if (dp->link_train.eq_loop > MAX_EQ_LOOP) { 613 if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
608 exynos_dp_reduce_link_rate(dp); 614 dev_err(dp->dev, "EQ Max loop\n");
609 } else { 615 goto reduce_link_rate;
610 exynos_dp_get_adjust_train(dp, adjust_request);
611
612 for (lane = 0; lane < lane_count; lane++) {
613 exynos_dp_set_lane_link_training(dp,
614 dp->link_train.training_lane[lane],
615 lane);
616 buf[lane] = dp->link_train.training_lane[lane];
617 exynos_dp_write_byte_to_dpcd(dp,
618 DPCD_ADDR_TRAINING_LANE0_SET + lane,
619 buf[lane]);
620 }
621 } 616 }
617
618 for (lane = 0; lane < lane_count; lane++)
619 exynos_dp_set_lane_link_training(dp,
620 dp->link_train.training_lane[lane],
621 lane);
622
623 exynos_dp_write_bytes_to_dpcd(dp,
624 DPCD_ADDR_TRAINING_LANE0_SET,
625 lane_count,
626 dp->link_train.training_lane);
622 } 627 }
623 } else { 628 } else {
624 exynos_dp_reduce_link_rate(dp); 629 goto reduce_link_rate;
625 } 630 }
626 631
627 return 0; 632 return 0;
633
634reduce_link_rate:
635 exynos_dp_reduce_link_rate(dp);
636 return -EIO;
628} 637}
629 638
630static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, 639static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
631 u8 *bandwidth) 640 u8 *bandwidth)
632{ 641{
633 u8 data; 642 u8 data;
634 643
@@ -641,7 +650,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
641} 650}
642 651
643static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, 652static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
644 u8 *lane_count) 653 u8 *lane_count)
645{ 654{
646 u8 data; 655 u8 data;
647 656
@@ -693,13 +702,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp,
693static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) 702static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
694{ 703{
695 int retval = 0; 704 int retval = 0;
696 int training_finished; 705 int training_finished = 0;
697
698 /* Turn off unnecessary lane */
699 if (dp->link_train.lane_count == 1)
700 exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
701
702 training_finished = 0;
703 706
704 dp->link_train.lt_state = START; 707 dp->link_train.lt_state = START;
705 708
@@ -710,10 +713,14 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
710 exynos_dp_link_start(dp); 713 exynos_dp_link_start(dp);
711 break; 714 break;
712 case CLOCK_RECOVERY: 715 case CLOCK_RECOVERY:
713 exynos_dp_process_clock_recovery(dp); 716 retval = exynos_dp_process_clock_recovery(dp);
717 if (retval)
718 dev_err(dp->dev, "LT CR failed!\n");
714 break; 719 break;
715 case EQUALIZER_TRAINING: 720 case EQUALIZER_TRAINING:
716 exynos_dp_process_equalizer_training(dp); 721 retval = exynos_dp_process_equalizer_training(dp);
722 if (retval)
723 dev_err(dp->dev, "LT EQ failed!\n");
717 break; 724 break;
718 case FINISHED: 725 case FINISHED:
719 training_finished = 1; 726 training_finished = 1;
@@ -872,40 +879,33 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
872 879
873 dp->dev = &pdev->dev; 880 dp->dev = &pdev->dev;
874 881
875 dp->clock = clk_get(&pdev->dev, "dp"); 882 dp->clock = devm_clk_get(&pdev->dev, "dp");
876 if (IS_ERR(dp->clock)) { 883 if (IS_ERR(dp->clock)) {
877 dev_err(&pdev->dev, "failed to get clock\n"); 884 dev_err(&pdev->dev, "failed to get clock\n");
878 return PTR_ERR(dp->clock); 885 return PTR_ERR(dp->clock);
879 } 886 }
880 887
881 clk_enable(dp->clock); 888 clk_prepare_enable(dp->clock);
882 889
883 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 890 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
884 if (!res) {
885 dev_err(&pdev->dev, "failed to get registers\n");
886 ret = -EINVAL;
887 goto err_clock;
888 }
889 891
890 dp->reg_base = devm_request_and_ioremap(&pdev->dev, res); 892 dp->reg_base = devm_request_and_ioremap(&pdev->dev, res);
891 if (!dp->reg_base) { 893 if (!dp->reg_base) {
892 dev_err(&pdev->dev, "failed to ioremap\n"); 894 dev_err(&pdev->dev, "failed to ioremap\n");
893 ret = -ENOMEM; 895 return -ENOMEM;
894 goto err_clock;
895 } 896 }
896 897
897 dp->irq = platform_get_irq(pdev, 0); 898 dp->irq = platform_get_irq(pdev, 0);
898 if (!dp->irq) { 899 if (!dp->irq) {
899 dev_err(&pdev->dev, "failed to get irq\n"); 900 dev_err(&pdev->dev, "failed to get irq\n");
900 ret = -ENODEV; 901 return -ENODEV;
901 goto err_clock;
902 } 902 }
903 903
904 ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0, 904 ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
905 "exynos-dp", dp); 905 "exynos-dp", dp);
906 if (ret) { 906 if (ret) {
907 dev_err(&pdev->dev, "failed to request irq\n"); 907 dev_err(&pdev->dev, "failed to request irq\n");
908 goto err_clock; 908 return ret;
909 } 909 }
910 910
911 dp->video_info = pdata->video_info; 911 dp->video_info = pdata->video_info;
@@ -917,7 +917,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
917 ret = exynos_dp_detect_hpd(dp); 917 ret = exynos_dp_detect_hpd(dp);
918 if (ret) { 918 if (ret) {
919 dev_err(&pdev->dev, "unable to detect hpd\n"); 919 dev_err(&pdev->dev, "unable to detect hpd\n");
920 goto err_clock; 920 return ret;
921 } 921 }
922 922
923 exynos_dp_handle_edid(dp); 923 exynos_dp_handle_edid(dp);
@@ -926,7 +926,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
926 dp->video_info->link_rate); 926 dp->video_info->link_rate);
927 if (ret) { 927 if (ret) {
928 dev_err(&pdev->dev, "unable to do link train\n"); 928 dev_err(&pdev->dev, "unable to do link train\n");
929 goto err_clock; 929 return ret;
930 } 930 }
931 931
932 exynos_dp_enable_scramble(dp, 1); 932 exynos_dp_enable_scramble(dp, 1);
@@ -940,17 +940,12 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
940 ret = exynos_dp_config_video(dp, dp->video_info); 940 ret = exynos_dp_config_video(dp, dp->video_info);
941 if (ret) { 941 if (ret) {
942 dev_err(&pdev->dev, "unable to config video\n"); 942 dev_err(&pdev->dev, "unable to config video\n");
943 goto err_clock; 943 return ret;
944 } 944 }
945 945
946 platform_set_drvdata(pdev, dp); 946 platform_set_drvdata(pdev, dp);
947 947
948 return 0; 948 return 0;
949
950err_clock:
951 clk_put(dp->clock);
952
953 return ret;
954} 949}
955 950
956static int __devexit exynos_dp_remove(struct platform_device *pdev) 951static int __devexit exynos_dp_remove(struct platform_device *pdev)
@@ -961,8 +956,7 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
961 if (pdata && pdata->phy_exit) 956 if (pdata && pdata->phy_exit)
962 pdata->phy_exit(); 957 pdata->phy_exit();
963 958
964 clk_disable(dp->clock); 959 clk_disable_unprepare(dp->clock);
965 clk_put(dp->clock);
966 960
967 return 0; 961 return 0;
968} 962}
@@ -977,7 +971,7 @@ static int exynos_dp_suspend(struct device *dev)
977 if (pdata && pdata->phy_exit) 971 if (pdata && pdata->phy_exit)
978 pdata->phy_exit(); 972 pdata->phy_exit();
979 973
980 clk_disable(dp->clock); 974 clk_disable_unprepare(dp->clock);
981 975
982 return 0; 976 return 0;
983} 977}
@@ -991,7 +985,7 @@ static int exynos_dp_resume(struct device *dev)
991 if (pdata && pdata->phy_init) 985 if (pdata && pdata->phy_init)
992 pdata->phy_init(); 986 pdata->phy_init();
993 987
994 clk_enable(dp->clock); 988 clk_prepare_enable(dp->clock);
995 989
996 exynos_dp_init_dp(dp); 990 exynos_dp_init_dp(dp);
997 991
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 8526e548c385..57b8a6531c0e 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -43,7 +43,7 @@ void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
43void exynos_dp_reset(struct exynos_dp_device *dp); 43void exynos_dp_reset(struct exynos_dp_device *dp);
44void exynos_dp_swreset(struct exynos_dp_device *dp); 44void exynos_dp_swreset(struct exynos_dp_device *dp);
45void exynos_dp_config_interrupt(struct exynos_dp_device *dp); 45void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
46u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); 46enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
47void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); 47void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
48void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, 48void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
49 enum analog_power_block block, 49 enum analog_power_block block,
@@ -105,7 +105,7 @@ u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
105u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); 105u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
106u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); 106u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
107void exynos_dp_reset_macro(struct exynos_dp_device *dp); 107void exynos_dp_reset_macro(struct exynos_dp_device *dp);
108int exynos_dp_init_video(struct exynos_dp_device *dp); 108void exynos_dp_init_video(struct exynos_dp_device *dp);
109 109
110void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, 110void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
111 u32 color_depth, 111 u32 color_depth,
@@ -144,7 +144,7 @@ void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
144#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102 144#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
145#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103 145#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
146#define DPCD_ADDR_LANE0_1_STATUS 0x0202 146#define DPCD_ADDR_LANE0_1_STATUS 0x0202
147#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204 147#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED 0x0204
148#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206 148#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
149#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207 149#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
150#define DPCD_ADDR_TEST_REQUEST 0x0218 150#define DPCD_ADDR_TEST_REQUEST 0x0218
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
index 2db5b9aa250a..3f5ca8a0d5ea 100644
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -77,7 +77,7 @@ void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
77 writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3); 77 writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
78 78
79 reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | 79 reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
80 TX_CUR1_2X | TX_CUR_8_MA; 80 TX_CUR1_2X | TX_CUR_16_MA;
81 writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1); 81 writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
82 82
83 reg = CH3_AMP_400_MV | CH2_AMP_400_MV | 83 reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
@@ -148,9 +148,6 @@ void exynos_dp_reset(struct exynos_dp_device *dp)
148 writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH); 148 writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
149 149
150 writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); 150 writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
151
152 exynos_dp_init_analog_param(dp);
153 exynos_dp_init_interrupt(dp);
154} 151}
155 152
156void exynos_dp_swreset(struct exynos_dp_device *dp) 153void exynos_dp_swreset(struct exynos_dp_device *dp)
@@ -179,7 +176,7 @@ void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
179 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK); 176 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
180} 177}
181 178
182u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp) 179enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
183{ 180{
184 u32 reg; 181 u32 reg;
185 182
@@ -401,6 +398,7 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
401{ 398{
402 int reg; 399 int reg;
403 int retval = 0; 400 int retval = 0;
401 int timeout_loop = 0;
404 402
405 /* Enable AUX CH operation */ 403 /* Enable AUX CH operation */
406 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); 404 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
@@ -409,8 +407,15 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
409 407
410 /* Is AUX CH command reply received? */ 408 /* Is AUX CH command reply received? */
411 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); 409 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
412 while (!(reg & RPLY_RECEIV)) 410 while (!(reg & RPLY_RECEIV)) {
411 timeout_loop++;
412 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
413 dev_err(dp->dev, "AUX CH command reply failed!\n");
414 return -ETIMEDOUT;
415 }
413 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); 416 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
417 usleep_range(10, 11);
418 }
414 419
415 /* Clear interrupt source for AUX CH command reply */ 420 /* Clear interrupt source for AUX CH command reply */
416 writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA); 421 writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
@@ -471,7 +476,8 @@ int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
471 if (retval == 0) 476 if (retval == 0)
472 break; 477 break;
473 else 478 else
474 dev_err(dp->dev, "Aux Transaction fail!\n"); 479 dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
480 __func__);
475 } 481 }
476 482
477 return retval; 483 return retval;
@@ -511,7 +517,8 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
511 if (retval == 0) 517 if (retval == 0)
512 break; 518 break;
513 else 519 else
514 dev_err(dp->dev, "Aux Transaction fail!\n"); 520 dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
521 __func__);
515 } 522 }
516 523
517 /* Read data buffer */ 524 /* Read data buffer */
@@ -575,7 +582,8 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
575 if (retval == 0) 582 if (retval == 0)
576 break; 583 break;
577 else 584 else
578 dev_err(dp->dev, "Aux Transaction fail!\n"); 585 dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
586 __func__);
579 } 587 }
580 588
581 start_offset += cur_data_count; 589 start_offset += cur_data_count;
@@ -632,7 +640,8 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
632 if (retval == 0) 640 if (retval == 0)
633 break; 641 break;
634 else 642 else
635 dev_err(dp->dev, "Aux Transaction fail!\n"); 643 dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
644 __func__);
636 } 645 }
637 646
638 for (cur_data_idx = 0; cur_data_idx < cur_data_count; 647 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
@@ -677,7 +686,7 @@ int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
677 /* Start AUX transaction */ 686 /* Start AUX transaction */
678 retval = exynos_dp_start_aux_transaction(dp); 687 retval = exynos_dp_start_aux_transaction(dp);
679 if (retval != 0) 688 if (retval != 0)
680 dev_err(dp->dev, "Aux Transaction fail!\n"); 689 dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
681 690
682 return retval; 691 return retval;
683} 692}
@@ -717,7 +726,8 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
717 if (retval == 0) 726 if (retval == 0)
718 break; 727 break;
719 else 728 else
720 dev_err(dp->dev, "Aux Transaction fail!\n"); 729 dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
730 __func__);
721 } 731 }
722 732
723 /* Read data */ 733 /* Read data */
@@ -777,7 +787,9 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
777 if (retval == 0) 787 if (retval == 0)
778 break; 788 break;
779 else 789 else
780 dev_err(dp->dev, "Aux Transaction fail!\n"); 790 dev_dbg(dp->dev,
791 "%s: Aux Transaction fail!\n",
792 __func__);
781 } 793 }
782 /* Check if Rx sends defer */ 794 /* Check if Rx sends defer */
783 reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM); 795 reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
@@ -883,7 +895,9 @@ void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
883{ 895{
884 u32 reg; 896 u32 reg;
885 897
886 reg = level << PRE_EMPHASIS_SET_SHIFT; 898 reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
899 reg &= ~PRE_EMPHASIS_SET_MASK;
900 reg |= level << PRE_EMPHASIS_SET_SHIFT;
887 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); 901 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
888} 902}
889 903
@@ -891,7 +905,9 @@ void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
891{ 905{
892 u32 reg; 906 u32 reg;
893 907
894 reg = level << PRE_EMPHASIS_SET_SHIFT; 908 reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
909 reg &= ~PRE_EMPHASIS_SET_MASK;
910 reg |= level << PRE_EMPHASIS_SET_SHIFT;
895 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); 911 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
896} 912}
897 913
@@ -899,7 +915,9 @@ void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
899{ 915{
900 u32 reg; 916 u32 reg;
901 917
902 reg = level << PRE_EMPHASIS_SET_SHIFT; 918 reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
919 reg &= ~PRE_EMPHASIS_SET_MASK;
920 reg |= level << PRE_EMPHASIS_SET_SHIFT;
903 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); 921 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
904} 922}
905 923
@@ -907,7 +925,9 @@ void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
907{ 925{
908 u32 reg; 926 u32 reg;
909 927
910 reg = level << PRE_EMPHASIS_SET_SHIFT; 928 reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
929 reg &= ~PRE_EMPHASIS_SET_MASK;
930 reg |= level << PRE_EMPHASIS_SET_SHIFT;
911 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); 931 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
912} 932}
913 933
@@ -994,7 +1014,7 @@ void exynos_dp_reset_macro(struct exynos_dp_device *dp)
994 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST); 1014 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
995} 1015}
996 1016
997int exynos_dp_init_video(struct exynos_dp_device *dp) 1017void exynos_dp_init_video(struct exynos_dp_device *dp)
998{ 1018{
999 u32 reg; 1019 u32 reg;
1000 1020
@@ -1012,8 +1032,6 @@ int exynos_dp_init_video(struct exynos_dp_device *dp)
1012 1032
1013 reg = VID_HRES_TH(2) | VID_VRES_TH(0); 1033 reg = VID_HRES_TH(2) | VID_VRES_TH(0);
1014 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8); 1034 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
1015
1016 return 0;
1017} 1035}
1018 1036
1019void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, 1037void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
index 125b27cd57ae..1f2f014cfe88 100644
--- a/drivers/video/exynos/exynos_dp_reg.h
+++ b/drivers/video/exynos/exynos_dp_reg.h
@@ -187,7 +187,7 @@
187#define PD_RING_OSC (0x1 << 6) 187#define PD_RING_OSC (0x1 << 6)
188#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) 188#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4)
189#define TX_CUR1_2X (0x1 << 2) 189#define TX_CUR1_2X (0x1 << 2)
190#define TX_CUR_8_MA (0x2 << 0) 190#define TX_CUR_16_MA (0x3 << 0)
191 191
192/* EXYNOS_DP_TX_AMP_TUNING_CTL */ 192/* EXYNOS_DP_TX_AMP_TUNING_CTL */
193#define CH3_AMP_400_MV (0x0 << 24) 193#define CH3_AMP_400_MV (0x0 << 24)
@@ -285,6 +285,7 @@
285#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0) 285#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
286 286
287/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ 287/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
288#define PRE_EMPHASIS_SET_MASK (0x3 << 3)
288#define PRE_EMPHASIS_SET_SHIFT (3) 289#define PRE_EMPHASIS_SET_SHIFT (3)
289 290
290/* EXYNOS_DP_DEBUG_CTL */ 291/* EXYNOS_DP_DEBUG_CTL */
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
index 663c308d0e73..07d70a3a628b 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -205,7 +205,8 @@ int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
205 return 0; 205 return 0;
206} 206}
207 207
208struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv) 208static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
209 struct mipi_dsim_lcd_driver *lcd_drv)
209{ 210{
210 struct mipi_dsim_ddi *dsim_ddi, *next; 211 struct mipi_dsim_ddi *dsim_ddi, *next;
211 struct mipi_dsim_lcd_device *lcd_dev; 212 struct mipi_dsim_lcd_device *lcd_dev;
@@ -265,7 +266,8 @@ int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
265 266
266} 267}
267 268
268struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim, 269static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
270 struct mipi_dsim_device *dsim,
269 const char *name) 271 const char *name)
270{ 272{
271 struct mipi_dsim_ddi *dsim_ddi, *next; 273 struct mipi_dsim_ddi *dsim_ddi, *next;
@@ -373,6 +375,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
373 dsim->clock = clk_get(&pdev->dev, "dsim0"); 375 dsim->clock = clk_get(&pdev->dev, "dsim0");
374 if (IS_ERR(dsim->clock)) { 376 if (IS_ERR(dsim->clock)) {
375 dev_err(&pdev->dev, "failed to get dsim clock source\n"); 377 dev_err(&pdev->dev, "failed to get dsim clock source\n");
378 ret = -ENODEV;
376 goto err_clock_get; 379 goto err_clock_get;
377 } 380 }
378 381
@@ -381,6 +384,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
381 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 384 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
382 if (!res) { 385 if (!res) {
383 dev_err(&pdev->dev, "failed to get io memory region\n"); 386 dev_err(&pdev->dev, "failed to get io memory region\n");
387 ret = -ENODEV;
384 goto err_platform_get; 388 goto err_platform_get;
385 } 389 }
386 390
@@ -405,6 +409,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
405 dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name); 409 dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
406 if (!dsim_ddi) { 410 if (!dsim_ddi) {
407 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n"); 411 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
412 ret = -EINVAL;
408 goto err_bind; 413 goto err_bind;
409 } 414 }
410 415
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
index 47b533a183be..3cd29a4fc10a 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -79,11 +79,6 @@ irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
79 struct mipi_dsim_device *dsim = dev_id; 79 struct mipi_dsim_device *dsim = dev_id;
80 unsigned int intsrc, intmsk; 80 unsigned int intsrc, intmsk;
81 81
82 if (dsim == NULL) {
83 dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
84 return IRQ_NONE;
85 }
86
87 intsrc = exynos_mipi_dsi_read_interrupt(dsim); 82 intsrc = exynos_mipi_dsi_read_interrupt(dsim);
88 intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim); 83 intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
89 intmsk = ~intmsk & intsrc; 84 intmsk = ~intmsk & intsrc;
@@ -288,9 +283,6 @@ int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
288 mutex_unlock(&dsim->lock); 283 mutex_unlock(&dsim->lock);
289 return -EINVAL; 284 return -EINVAL;
290 } 285 }
291
292 mutex_unlock(&dsim->lock);
293 return 0;
294} 286}
295 287
296static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim, 288static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 458c00664ade..ede9e55413f8 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1501,8 +1501,8 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1501 unsigned int i; 1501 unsigned int i;
1502 int ret; 1502 int ret;
1503 1503
1504 data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data), 1504 data = dmam_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
1505 &dma_addr, GFP_DMA | __GFP_ZERO); 1505 &dma_addr, GFP_DMA | __GFP_ZERO);
1506 if (!data) 1506 if (!data)
1507 return -ENOMEM; 1507 return -ENOMEM;
1508 data->dma_addr = dma_addr; 1508 data->dma_addr = dma_addr;
@@ -1628,9 +1628,6 @@ error:
1628 1628
1629 iounmap(data->diu_reg); 1629 iounmap(data->diu_reg);
1630 1630
1631 dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
1632 data->dma_addr);
1633
1634 return ret; 1631 return ret;
1635} 1632}
1636 1633
@@ -1648,9 +1645,6 @@ static int fsl_diu_remove(struct platform_device *pdev)
1648 1645
1649 iounmap(data->diu_reg); 1646 iounmap(data->diu_reg);
1650 1647
1651 dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
1652 data->dma_addr);
1653
1654 return 0; 1648 return 0;
1655} 1649}
1656 1650
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 05e2a8a99d8f..3dad31975db8 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -20,6 +20,7 @@
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/io.h>
23 24
24#ifdef CONFIG_X86 25#ifdef CONFIG_X86
25#include <asm/mtrr.h> 26#include <asm/mtrr.h>
@@ -28,7 +29,6 @@
28#include <asm/addrspace.h> 29#include <asm/addrspace.h>
29#endif 30#endif
30#include <asm/byteorder.h> 31#include <asm/byteorder.h>
31#include <asm/io.h>
32#include <asm/tlbflush.h> 32#include <asm/tlbflush.h>
33 33
34#include <video/gbe.h> 34#include <video/gbe.h>
@@ -1156,7 +1156,8 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
1156 goto out_release_framebuffer; 1156 goto out_release_framebuffer;
1157 } 1157 }
1158 1158
1159 gbe = (struct sgi_gbe *) ioremap(GBE_BASE, sizeof(struct sgi_gbe)); 1159 gbe = (struct sgi_gbe *) devm_ioremap(&p_dev->dev, GBE_BASE,
1160 sizeof(struct sgi_gbe));
1160 if (!gbe) { 1161 if (!gbe) {
1161 printk(KERN_ERR "gbefb: couldn't map mmio region\n"); 1162 printk(KERN_ERR "gbefb: couldn't map mmio region\n");
1162 ret = -ENXIO; 1163 ret = -ENXIO;
@@ -1170,12 +1171,13 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
1170 if (!gbe_tiles.cpu) { 1171 if (!gbe_tiles.cpu) {
1171 printk(KERN_ERR "gbefb: couldn't allocate tiles table\n"); 1172 printk(KERN_ERR "gbefb: couldn't allocate tiles table\n");
1172 ret = -ENOMEM; 1173 ret = -ENOMEM;
1173 goto out_unmap; 1174 goto out_release_mem_region;
1174 } 1175 }
1175 1176
1176 if (gbe_mem_phys) { 1177 if (gbe_mem_phys) {
1177 /* memory was allocated at boot time */ 1178 /* memory was allocated at boot time */
1178 gbe_mem = ioremap_nocache(gbe_mem_phys, gbe_mem_size); 1179 gbe_mem = devm_ioremap_nocache(&p_dev->dev, gbe_mem_phys,
1180 gbe_mem_size);
1179 if (!gbe_mem) { 1181 if (!gbe_mem) {
1180 printk(KERN_ERR "gbefb: couldn't map framebuffer\n"); 1182 printk(KERN_ERR "gbefb: couldn't map framebuffer\n");
1181 ret = -ENOMEM; 1183 ret = -ENOMEM;
@@ -1241,13 +1243,9 @@ static int __devinit gbefb_probe(struct platform_device *p_dev)
1241out_gbe_unmap: 1243out_gbe_unmap:
1242 if (gbe_dma_addr) 1244 if (gbe_dma_addr)
1243 dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); 1245 dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
1244 else
1245 iounmap(gbe_mem);
1246out_tiles_free: 1246out_tiles_free:
1247 dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), 1247 dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1248 (void *)gbe_tiles.cpu, gbe_tiles.dma); 1248 (void *)gbe_tiles.cpu, gbe_tiles.dma);
1249out_unmap:
1250 iounmap(gbe);
1251out_release_mem_region: 1249out_release_mem_region:
1252 release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); 1250 release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1253out_release_framebuffer: 1251out_release_framebuffer:
@@ -1264,12 +1262,9 @@ static int __devexit gbefb_remove(struct platform_device* p_dev)
1264 gbe_turn_off(); 1262 gbe_turn_off();
1265 if (gbe_dma_addr) 1263 if (gbe_dma_addr)
1266 dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys); 1264 dma_free_coherent(NULL, gbe_mem_size, gbe_mem, gbe_mem_phys);
1267 else
1268 iounmap(gbe_mem);
1269 dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t), 1265 dma_free_coherent(NULL, GBE_TLB_SIZE * sizeof(uint16_t),
1270 (void *)gbe_tiles.cpu, gbe_tiles.dma); 1266 (void *)gbe_tiles.cpu, gbe_tiles.dma);
1271 release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); 1267 release_mem_region(GBE_BASE, sizeof(struct sgi_gbe));
1272 iounmap(gbe);
1273 gbefb_remove_sysfs(&p_dev->dev); 1268 gbefb_remove_sysfs(&p_dev->dev);
1274 framebuffer_release(info); 1269 framebuffer_release(info);
1275 1270
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c
index ebf8495ff198..7324865f965f 100644
--- a/drivers/video/hpfb.c
+++ b/drivers/video/hpfb.c
@@ -210,6 +210,7 @@ static int __devinit hpfb_init_one(unsigned long phys_base,
210 unsigned long virt_base) 210 unsigned long virt_base)
211{ 211{
212 unsigned long fboff, fb_width, fb_height, fb_start; 212 unsigned long fboff, fb_width, fb_height, fb_start;
213 int ret;
213 214
214 fb_regs = virt_base; 215 fb_regs = virt_base;
215 fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB); 216 fboff = (in_8(fb_regs + HPFB_FBOMSB) << 8) | in_8(fb_regs + HPFB_FBOLSB);
@@ -290,19 +291,29 @@ static int __devinit hpfb_init_one(unsigned long phys_base,
290 fb_info.var = hpfb_defined; 291 fb_info.var = hpfb_defined;
291 fb_info.screen_base = (char *)fb_start; 292 fb_info.screen_base = (char *)fb_start;
292 293
293 fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0); 294 ret = fb_alloc_cmap(&fb_info.cmap, 1 << hpfb_defined.bits_per_pixel, 0);
295 if (ret < 0)
296 goto unmap_screen_base;
294 297
295 if (register_framebuffer(&fb_info) < 0) { 298 ret = register_framebuffer(&fb_info);
296 fb_dealloc_cmap(&fb_info.cmap); 299 if (ret < 0)
297 iounmap(fb_info.screen_base); 300 goto dealloc_cmap;
298 fb_info.screen_base = NULL;
299 return 1;
300 }
301 301
302 printk(KERN_INFO "fb%d: %s frame buffer device\n", 302 printk(KERN_INFO "fb%d: %s frame buffer device\n",
303 fb_info.node, fb_info.fix.id); 303 fb_info.node, fb_info.fix.id);
304 304
305 return 0; 305 return 0;
306
307dealloc_cmap:
308 fb_dealloc_cmap(&fb_info.cmap);
309
310unmap_screen_base:
311 if (fb_info.screen_base) {
312 iounmap(fb_info.screen_base);
313 fb_info.screen_base = NULL;
314 }
315
316 return ret;
306} 317}
307 318
308/* 319/*
@@ -345,6 +356,9 @@ static void __devexit hpfb_remove_one(struct dio_dev *d)
345 if (d->scode >= DIOII_SCBASE) 356 if (d->scode >= DIOII_SCBASE)
346 iounmap((void *)fb_regs); 357 iounmap((void *)fb_regs);
347 release_mem_region(d->resource.start, resource_size(&d->resource)); 358 release_mem_region(d->resource.start, resource_size(&d->resource));
359 fb_dealloc_cmap(&fb_info.cmap);
360 if (fb_info.screen_base)
361 iounmap(fb_info.screen_base);
348} 362}
349 363
350static struct dio_device_id hpfb_dio_tbl[] = { 364static struct dio_device_id hpfb_dio_tbl[] = {
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 53ffdfc82a75..cf2688de0832 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -803,6 +803,7 @@ static int __init imxfb_probe(struct platform_device *pdev)
803 fbi->regs = ioremap(res->start, resource_size(res)); 803 fbi->regs = ioremap(res->start, resource_size(res));
804 if (fbi->regs == NULL) { 804 if (fbi->regs == NULL) {
805 dev_err(&pdev->dev, "Cannot map frame buffer registers\n"); 805 dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
806 ret = -ENOMEM;
806 goto failed_ioremap; 807 goto failed_ioremap;
807 } 808 }
808 809
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c
index 3c63fc24bb1f..4d25711b9982 100644
--- a/drivers/video/jz4740_fb.c
+++ b/drivers/video/jz4740_fb.c
@@ -632,23 +632,10 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
632 return -ENXIO; 632 return -ENXIO;
633 } 633 }
634 634
635 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
636 if (!mem) {
637 dev_err(&pdev->dev, "Failed to get register memory resource\n");
638 return -ENXIO;
639 }
640
641 mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
642 if (!mem) {
643 dev_err(&pdev->dev, "Failed to request register memory region\n");
644 return -EBUSY;
645 }
646
647 fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev); 635 fb = framebuffer_alloc(sizeof(struct jzfb), &pdev->dev);
648 if (!fb) { 636 if (!fb) {
649 dev_err(&pdev->dev, "Failed to allocate framebuffer device\n"); 637 dev_err(&pdev->dev, "Failed to allocate framebuffer device\n");
650 ret = -ENOMEM; 638 return -ENOMEM;
651 goto err_release_mem_region;
652 } 639 }
653 640
654 fb->fbops = &jzfb_ops; 641 fb->fbops = &jzfb_ops;
@@ -657,27 +644,26 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
657 jzfb = fb->par; 644 jzfb = fb->par;
658 jzfb->pdev = pdev; 645 jzfb->pdev = pdev;
659 jzfb->pdata = pdata; 646 jzfb->pdata = pdata;
660 jzfb->mem = mem;
661 647
662 jzfb->ldclk = clk_get(&pdev->dev, "lcd"); 648 jzfb->ldclk = devm_clk_get(&pdev->dev, "lcd");
663 if (IS_ERR(jzfb->ldclk)) { 649 if (IS_ERR(jzfb->ldclk)) {
664 ret = PTR_ERR(jzfb->ldclk); 650 ret = PTR_ERR(jzfb->ldclk);
665 dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret); 651 dev_err(&pdev->dev, "Failed to get lcd clock: %d\n", ret);
666 goto err_framebuffer_release; 652 goto err_framebuffer_release;
667 } 653 }
668 654
669 jzfb->lpclk = clk_get(&pdev->dev, "lcd_pclk"); 655 jzfb->lpclk = devm_clk_get(&pdev->dev, "lcd_pclk");
670 if (IS_ERR(jzfb->lpclk)) { 656 if (IS_ERR(jzfb->lpclk)) {
671 ret = PTR_ERR(jzfb->lpclk); 657 ret = PTR_ERR(jzfb->lpclk);
672 dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret); 658 dev_err(&pdev->dev, "Failed to get lcd pixel clock: %d\n", ret);
673 goto err_put_ldclk; 659 goto err_framebuffer_release;
674 } 660 }
675 661
676 jzfb->base = ioremap(mem->start, resource_size(mem)); 662 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
663 jzfb->base = devm_request_and_ioremap(&pdev->dev, mem);
677 if (!jzfb->base) { 664 if (!jzfb->base) {
678 dev_err(&pdev->dev, "Failed to ioremap register memory region\n");
679 ret = -EBUSY; 665 ret = -EBUSY;
680 goto err_put_lpclk; 666 goto err_framebuffer_release;
681 } 667 }
682 668
683 platform_set_drvdata(pdev, jzfb); 669 platform_set_drvdata(pdev, jzfb);
@@ -693,7 +679,7 @@ static int __devinit jzfb_probe(struct platform_device *pdev)
693 ret = jzfb_alloc_devmem(jzfb); 679 ret = jzfb_alloc_devmem(jzfb);
694 if (ret) { 680 if (ret) {
695 dev_err(&pdev->dev, "Failed to allocate video memory\n"); 681 dev_err(&pdev->dev, "Failed to allocate video memory\n");
696 goto err_iounmap; 682 goto err_framebuffer_release;
697 } 683 }
698 684
699 fb->fix = jzfb_fix; 685 fb->fix = jzfb_fix;
@@ -734,16 +720,8 @@ err_free_devmem:
734 720
735 fb_dealloc_cmap(&fb->cmap); 721 fb_dealloc_cmap(&fb->cmap);
736 jzfb_free_devmem(jzfb); 722 jzfb_free_devmem(jzfb);
737err_iounmap:
738 iounmap(jzfb->base);
739err_put_lpclk:
740 clk_put(jzfb->lpclk);
741err_put_ldclk:
742 clk_put(jzfb->ldclk);
743err_framebuffer_release: 723err_framebuffer_release:
744 framebuffer_release(fb); 724 framebuffer_release(fb);
745err_release_mem_region:
746 release_mem_region(mem->start, resource_size(mem));
747 return ret; 725 return ret;
748} 726}
749 727
@@ -756,17 +734,11 @@ static int __devexit jzfb_remove(struct platform_device *pdev)
756 jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb)); 734 jz_gpio_bulk_free(jz_lcd_ctrl_pins, jzfb_num_ctrl_pins(jzfb));
757 jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb)); 735 jz_gpio_bulk_free(jz_lcd_data_pins, jzfb_num_data_pins(jzfb));
758 736
759 iounmap(jzfb->base);
760 release_mem_region(jzfb->mem->start, resource_size(jzfb->mem));
761
762 fb_dealloc_cmap(&jzfb->fb->cmap); 737 fb_dealloc_cmap(&jzfb->fb->cmap);
763 jzfb_free_devmem(jzfb); 738 jzfb_free_devmem(jzfb);
764 739
765 platform_set_drvdata(pdev, NULL); 740 platform_set_drvdata(pdev, NULL);
766 741
767 clk_put(jzfb->lpclk);
768 clk_put(jzfb->ldclk);
769
770 framebuffer_release(jzfb->fb); 742 framebuffer_release(jzfb->fb);
771 743
772 return 0; 744 return 0;
diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/mb862xx/mb862xxfbdrv.c
index 57d940be5f3d..d68e332aa21c 100644
--- a/drivers/video/mb862xx/mb862xxfbdrv.c
+++ b/drivers/video/mb862xx/mb862xxfbdrv.c
@@ -1052,12 +1052,14 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
1052 break; 1052 break;
1053 default: 1053 default:
1054 /* should never occur */ 1054 /* should never occur */
1055 ret = -EIO;
1055 goto rel_reg; 1056 goto rel_reg;
1056 } 1057 }
1057 1058
1058 par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); 1059 par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram);
1059 if (par->fb_base == NULL) { 1060 if (par->fb_base == NULL) {
1060 dev_err(dev, "Cannot map framebuffer\n"); 1061 dev_err(dev, "Cannot map framebuffer\n");
1062 ret = -EIO;
1061 goto rel_reg; 1063 goto rel_reg;
1062 } 1064 }
1063 1065
@@ -1073,11 +1075,13 @@ static int __devinit mb862xx_pci_probe(struct pci_dev *pdev,
1073 dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n", 1075 dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n",
1074 (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len); 1076 (unsigned long long)par->mmio_base_phys, (ulong)par->mmio_len);
1075 1077
1076 if (mb862xx_pci_gdc_init(par)) 1078 ret = mb862xx_pci_gdc_init(par);
1079 if (ret)
1077 goto io_unmap; 1080 goto io_unmap;
1078 1081
1079 if (request_irq(par->irq, mb862xx_intr, IRQF_SHARED, 1082 ret = request_irq(par->irq, mb862xx_intr, IRQF_SHARED,
1080 DRV_NAME, (void *)par)) { 1083 DRV_NAME, (void *)par);
1084 if (ret) {
1081 dev_err(dev, "Cannot request irq\n"); 1085 dev_err(dev, "Cannot request irq\n");
1082 goto io_unmap; 1086 goto io_unmap;
1083 } 1087 }
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 85e4f44bfa61..6563e50413c1 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -26,8 +26,7 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/uaccess.h> 28#include <linux/uaccess.h>
29 29#include <linux/io.h>
30#include <asm/io.h>
31 30
32#include <video/mbxfb.h> 31#include <video/mbxfb.h>
33 32
@@ -939,8 +938,9 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
939 } 938 }
940 mfbi->reg_phys_addr = mfbi->reg_res->start; 939 mfbi->reg_phys_addr = mfbi->reg_res->start;
941 940
942 mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr, 941 mfbi->reg_virt_addr = devm_ioremap_nocache(&dev->dev,
943 res_size(mfbi->reg_req)); 942 mfbi->reg_phys_addr,
943 res_size(mfbi->reg_req));
944 if (!mfbi->reg_virt_addr) { 944 if (!mfbi->reg_virt_addr) {
945 dev_err(&dev->dev, "failed to ioremap Marathon registers\n"); 945 dev_err(&dev->dev, "failed to ioremap Marathon registers\n");
946 ret = -EINVAL; 946 ret = -EINVAL;
@@ -948,12 +948,12 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
948 } 948 }
949 virt_base_2700 = 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 = devm_ioremap_nocache(&dev->dev, mfbi->fb_phys_addr,
952 res_size(mfbi->fb_req)); 952 res_size(mfbi->fb_req));
953 if (!mfbi->fb_virt_addr) { 953 if (!mfbi->fb_virt_addr) {
954 dev_err(&dev->dev, "failed to ioremap frame buffer\n"); 954 dev_err(&dev->dev, "failed to ioremap frame buffer\n");
955 ret = -EINVAL; 955 ret = -EINVAL;
956 goto err4; 956 goto err3;
957 } 957 }
958 958
959 fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); 959 fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000);
@@ -971,7 +971,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
971 if (ret < 0) { 971 if (ret < 0) {
972 dev_err(&dev->dev, "fb_alloc_cmap failed\n"); 972 dev_err(&dev->dev, "fb_alloc_cmap failed\n");
973 ret = -EINVAL; 973 ret = -EINVAL;
974 goto err5; 974 goto err3;
975 } 975 }
976 976
977 platform_set_drvdata(dev, fbi); 977 platform_set_drvdata(dev, fbi);
@@ -996,10 +996,6 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
996 996
997err6: 997err6:
998 fb_dealloc_cmap(&fbi->cmap); 998 fb_dealloc_cmap(&fbi->cmap);
999err5:
1000 iounmap(mfbi->fb_virt_addr);
1001err4:
1002 iounmap(mfbi->reg_virt_addr);
1003err3: 999err3:
1004 release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res)); 1000 release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res));
1005err2: 1001err2:
@@ -1026,10 +1022,7 @@ static int __devexit mbxfb_remove(struct platform_device *dev)
1026 if (mfbi->platform_remove) 1022 if (mfbi->platform_remove)
1027 mfbi->platform_remove(fbi); 1023 mfbi->platform_remove(fbi);
1028 1024
1029 if (mfbi->fb_virt_addr) 1025
1030 iounmap(mfbi->fb_virt_addr);
1031 if (mfbi->reg_virt_addr)
1032 iounmap(mfbi->reg_virt_addr);
1033 if (mfbi->reg_req) 1026 if (mfbi->reg_req)
1034 release_mem_region(mfbi->reg_req->start, 1027 release_mem_region(mfbi->reg_req->start,
1035 res_size(mfbi->reg_req)); 1028 res_size(mfbi->reg_req));
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index bf73f0480061..35ac9e8bee63 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -26,9 +26,6 @@
26#include <linux/clk.h> 26#include <linux/clk.h>
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/sched.h> 28#include <linux/sched.h>
29#include <mach/msm_iomap.h>
30#include <mach/irqs.h>
31#include <mach/board.h>
32#include <linux/platform_data/video-msm_fb.h> 29#include <linux/platform_data/video-msm_fb.h>
33#include "mddi_hw.h" 30#include "mddi_hw.h"
34 31
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
index d7a5bf84fb2a..f96df32e5509 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -189,8 +189,9 @@ static int mddi_nt35399_probe(struct platform_device *pdev)
189 189
190 int ret; 190 int ret;
191 191
192 struct panel_info *panel = kzalloc(sizeof(struct panel_info), 192 struct panel_info *panel = devm_kzalloc(&pdev->dev,
193 GFP_KERNEL); 193 sizeof(struct panel_info),
194 GFP_KERNEL);
194 195
195 printk(KERN_DEBUG "%s: enter.\n", __func__); 196 printk(KERN_DEBUG "%s: enter.\n", __func__);
196 197
@@ -233,7 +234,6 @@ static int mddi_nt35399_remove(struct platform_device *pdev)
233 struct panel_info *panel = platform_get_drvdata(pdev); 234 struct panel_info *panel = platform_get_drvdata(pdev);
234 235
235 setup_vsync(panel, 0); 236 setup_vsync(panel, 0);
236 kfree(panel);
237 return 0; 237 return 0;
238} 238}
239 239
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 2e0f3bab6114..f2566c19e71c 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -25,7 +25,6 @@
25#include <linux/major.h> 25#include <linux/major.h>
26#include <linux/slab.h> 26#include <linux/slab.h>
27 27
28#include <mach/msm_iomap.h>
29#include <linux/platform_data/video-msm_fb.h> 28#include <linux/platform_data/video-msm_fb.h>
30#include <linux/platform_device.h> 29#include <linux/platform_device.h>
31#include <linux/export.h> 30#include <linux/export.h>
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index a0bacf581b32..35848d741001 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -15,7 +15,6 @@
15#ifndef _MDP_HW_H_ 15#ifndef _MDP_HW_H_
16#define _MDP_HW_H_ 16#define _MDP_HW_H_
17 17
18#include <mach/msm_iomap.h>
19#include <linux/platform_data/video-msm_fb.h> 18#include <linux/platform_data/video-msm_fb.h>
20 19
21struct mdp_info { 20struct mdp_info {
diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c
index d7381088a180..ce1d452464ed 100644
--- a/drivers/video/mx3fb.c
+++ b/drivers/video/mx3fb.c
@@ -1568,7 +1568,8 @@ static int mx3fb_remove(struct platform_device *dev)
1568 1568
1569static struct platform_driver mx3fb_driver = { 1569static struct platform_driver mx3fb_driver = {
1570 .driver = { 1570 .driver = {
1571 .name = MX3FB_NAME, 1571 .name = MX3FB_NAME,
1572 .owner = THIS_MODULE,
1572 }, 1573 },
1573 .probe = mx3fb_probe, 1574 .probe = mx3fb_probe,
1574 .remove = mx3fb_remove, 1575 .remove = mx3fb_remove,
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index 93387555337e..475dfee82c4a 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -387,7 +387,7 @@ static int nuc900fb_init_registers(struct fb_info *info)
387 * The buffer should be a non-cached, non-buffered, memory region 387 * The buffer should be a non-cached, non-buffered, memory region
388 * to allow palette and pixel writes without flushing the cache. 388 * to allow palette and pixel writes without flushing the cache.
389 */ 389 */
390static int __init nuc900fb_map_video_memory(struct fb_info *info) 390static int __devinit nuc900fb_map_video_memory(struct fb_info *info)
391{ 391{
392 struct nuc900fb_info *fbi = info->par; 392 struct nuc900fb_info *fbi = info->par;
393 dma_addr_t map_dma; 393 dma_addr_t map_dma;
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c
index 9f1d23c319cb..f349ee6f0cea 100644
--- a/drivers/video/omap/hwa742.c
+++ b/drivers/video/omap/hwa742.c
@@ -27,7 +27,6 @@
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29 29
30#include <plat/dma.h>
31#include "omapfb.h" 30#include "omapfb.h"
32 31
33#define HWA742_REV_CODE_REG 0x0 32#define HWA742_REV_CODE_REG 0x0
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 88c31eb0cd6c..ff4fb624b904 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -23,7 +23,6 @@
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24#include <linux/io.h> 24#include <linux/io.h>
25 25
26#include <plat/fpga.h>
27#include "omapfb.h" 26#include "omapfb.h"
28 27
29static int palmte_panel_init(struct lcd_panel *panel, 28static int palmte_panel_init(struct lcd_panel *panel,
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index f54b463709e9..4351c438b76f 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -131,15 +131,6 @@ static void omapfb_rqueue_unlock(struct omapfb_device *fbdev)
131 * LCD controller and LCD DMA 131 * LCD controller and LCD DMA
132 * --------------------------------------------------------------------------- 132 * ---------------------------------------------------------------------------
133 */ 133 */
134/* Lookup table to map elem size to elem type. */
135static const int dma_elem_type[] = {
136 0,
137 OMAP_DMA_DATA_TYPE_S8,
138 OMAP_DMA_DATA_TYPE_S16,
139 0,
140 OMAP_DMA_DATA_TYPE_S32,
141};
142
143/* 134/*
144 * Allocate resources needed for LCD controller and LCD DMA operations. Video 135 * Allocate resources needed for LCD controller and LCD DMA operations. Video
145 * memory is allocated from system memory according to the virtual display 136 * memory is allocated from system memory according to the virtual display
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index eaeed4340e04..c835aa70f96f 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -600,6 +600,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
600 600
601 mutex_lock(&md->mutex); 601 mutex_lock(&md->mutex);
602 602
603 omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
604 omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
605
603 r = omapdss_sdi_display_enable(dssdev); 606 r = omapdss_sdi_display_enable(dssdev);
604 if (r) { 607 if (r) {
605 pr_err("%s sdi enable failed\n", __func__); 608 pr_err("%s sdi enable failed\n", __func__);
@@ -731,18 +734,9 @@ static int acx_panel_resume(struct omap_dss_device *dssdev)
731static void acx_panel_set_timings(struct omap_dss_device *dssdev, 734static void acx_panel_set_timings(struct omap_dss_device *dssdev,
732 struct omap_video_timings *timings) 735 struct omap_video_timings *timings)
733{ 736{
734 int r; 737 omapdss_sdi_set_timings(dssdev, timings);
735
736 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
737 omapdss_sdi_display_disable(dssdev);
738 738
739 dssdev->panel.timings = *timings; 739 dssdev->panel.timings = *timings;
740
741 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
742 r = omapdss_sdi_display_enable(dssdev);
743 if (r)
744 dev_err(&dssdev->dev, "%s enable failed\n", __func__);
745 }
746} 740}
747 741
748static int acx_panel_check_timings(struct omap_dss_device *dssdev, 742static int acx_panel_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index bc5af2500eb9..88295c526815 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -545,6 +545,8 @@ struct panel_drv_data {
545 struct omap_dss_device *dssdev; 545 struct omap_dss_device *dssdev;
546 546
547 struct panel_config *panel_config; 547 struct panel_config *panel_config;
548
549 struct mutex lock;
548}; 550};
549 551
550static inline struct panel_generic_dpi_data 552static inline struct panel_generic_dpi_data
@@ -563,6 +565,9 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
563 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 565 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
564 return 0; 566 return 0;
565 567
568 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
569 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
570
566 r = omapdss_dpi_display_enable(dssdev); 571 r = omapdss_dpi_display_enable(dssdev);
567 if (r) 572 if (r)
568 goto err0; 573 goto err0;
@@ -634,6 +639,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
634 drv_data->dssdev = dssdev; 639 drv_data->dssdev = dssdev;
635 drv_data->panel_config = panel_config; 640 drv_data->panel_config = panel_config;
636 641
642 mutex_init(&drv_data->lock);
643
637 dev_set_drvdata(&dssdev->dev, drv_data); 644 dev_set_drvdata(&dssdev->dev, drv_data);
638 645
639 return 0; 646 return 0;
@@ -652,56 +659,108 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
652 659
653static int generic_dpi_panel_enable(struct omap_dss_device *dssdev) 660static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
654{ 661{
655 int r = 0; 662 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
663 int r;
664
665 mutex_lock(&drv_data->lock);
656 666
657 r = generic_dpi_panel_power_on(dssdev); 667 r = generic_dpi_panel_power_on(dssdev);
658 if (r) 668 if (r)
659 return r; 669 goto err;
660 670
661 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 671 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
672err:
673 mutex_unlock(&drv_data->lock);
662 674
663 return 0; 675 return r;
664} 676}
665 677
666static void generic_dpi_panel_disable(struct omap_dss_device *dssdev) 678static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
667{ 679{
680 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
681
682 mutex_lock(&drv_data->lock);
683
668 generic_dpi_panel_power_off(dssdev); 684 generic_dpi_panel_power_off(dssdev);
669 685
670 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 686 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
687
688 mutex_unlock(&drv_data->lock);
671} 689}
672 690
673static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev) 691static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
674{ 692{
693 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
694
695 mutex_lock(&drv_data->lock);
696
675 generic_dpi_panel_power_off(dssdev); 697 generic_dpi_panel_power_off(dssdev);
676 698
677 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 699 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
678 700
701 mutex_unlock(&drv_data->lock);
702
679 return 0; 703 return 0;
680} 704}
681 705
682static int generic_dpi_panel_resume(struct omap_dss_device *dssdev) 706static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
683{ 707{
684 int r = 0; 708 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
709 int r;
710
711 mutex_lock(&drv_data->lock);
685 712
686 r = generic_dpi_panel_power_on(dssdev); 713 r = generic_dpi_panel_power_on(dssdev);
687 if (r) 714 if (r)
688 return r; 715 goto err;
689 716
690 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 717 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
691 718
692 return 0; 719err:
720 mutex_unlock(&drv_data->lock);
721
722 return r;
693} 723}
694 724
695static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, 725static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
696 struct omap_video_timings *timings) 726 struct omap_video_timings *timings)
697{ 727{
698 dpi_set_timings(dssdev, timings); 728 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
729
730 mutex_lock(&drv_data->lock);
731
732 omapdss_dpi_set_timings(dssdev, timings);
733
734 dssdev->panel.timings = *timings;
735
736 mutex_unlock(&drv_data->lock);
737}
738
739static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
740 struct omap_video_timings *timings)
741{
742 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
743
744 mutex_lock(&drv_data->lock);
745
746 *timings = dssdev->panel.timings;
747
748 mutex_unlock(&drv_data->lock);
699} 749}
700 750
701static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, 751static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
702 struct omap_video_timings *timings) 752 struct omap_video_timings *timings)
703{ 753{
704 return dpi_check_timings(dssdev, timings); 754 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
755 int r;
756
757 mutex_lock(&drv_data->lock);
758
759 r = dpi_check_timings(dssdev, timings);
760
761 mutex_unlock(&drv_data->lock);
762
763 return r;
705} 764}
706 765
707static struct omap_dss_driver dpi_driver = { 766static struct omap_dss_driver dpi_driver = {
@@ -714,6 +773,7 @@ static struct omap_dss_driver dpi_driver = {
714 .resume = generic_dpi_panel_resume, 773 .resume = generic_dpi_panel_resume,
715 774
716 .set_timings = generic_dpi_panel_set_timings, 775 .set_timings = generic_dpi_panel_set_timings,
776 .get_timings = generic_dpi_panel_get_timings,
717 .check_timings = generic_dpi_panel_check_timings, 777 .check_timings = generic_dpi_panel_check_timings,
718 778
719 .driver = { 779 .driver = {
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 802807798846..90c1cabf244e 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -55,6 +55,9 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
55 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 55 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
56 return 0; 56 return 0;
57 57
58 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
59 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
60
58 r = omapdss_dpi_display_enable(dssdev); 61 r = omapdss_dpi_display_enable(dssdev);
59 if (r) 62 if (r)
60 goto err0; 63 goto err0;
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index e6c115373c00..3fc5ad081a21 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -150,11 +150,17 @@ static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
150 BLIZZARD_SRC_WRITE_LCD : 150 BLIZZARD_SRC_WRITE_LCD :
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE; 151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
152 152
153 omap_rfbi_configure(dssdev, 16, 8); 153 omapdss_rfbi_set_pixel_size(dssdev, 16);
154 omapdss_rfbi_set_data_lines(dssdev, 8);
155
156 omap_rfbi_configure(dssdev);
154 157
155 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18); 158 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
156 159
157 omap_rfbi_configure(dssdev, 16, 16); 160 omapdss_rfbi_set_pixel_size(dssdev, 16);
161 omapdss_rfbi_set_data_lines(dssdev, 16);
162
163 omap_rfbi_configure(dssdev);
158} 164}
159 165
160static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, 166static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
@@ -297,6 +303,12 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
297 goto err_plat_en; 303 goto err_plat_en;
298 } 304 }
299 305
306 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
307 dssdev->panel.timings.y_res);
308 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
309 omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
310 omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
311
300 r = omapdss_rfbi_display_enable(dssdev); 312 r = omapdss_rfbi_display_enable(dssdev);
301 if (r) 313 if (r)
302 goto err_rfbi_en; 314 goto err_rfbi_en;
@@ -477,6 +489,7 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev)
477 dssdev->panel.timings.y_res = 480; 489 dssdev->panel.timings.y_res = 480;
478 dssdev->ctrl.pixel_size = 16; 490 dssdev->ctrl.pixel_size = 16;
479 dssdev->ctrl.rfbi_timings = n8x0_panel_timings; 491 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
492 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
480 493
481 memset(&props, 0, sizeof(props)); 494 memset(&props, 0, sizeof(props));
482 props.max_brightness = 127; 495 props.max_brightness = 127;
@@ -625,17 +638,25 @@ static int n8x0_panel_update(struct omap_dss_device *dssdev,
625 u16 x, u16 y, u16 w, u16 h) 638 u16 x, u16 y, u16 w, u16 h)
626{ 639{
627 struct panel_drv_data *ddata = get_drv_data(dssdev); 640 struct panel_drv_data *ddata = get_drv_data(dssdev);
641 u16 dw, dh;
628 642
629 dev_dbg(&dssdev->dev, "update\n"); 643 dev_dbg(&dssdev->dev, "update\n");
630 644
645 dw = dssdev->panel.timings.x_res;
646 dh = dssdev->panel.timings.y_res;
647
648 if (x != 0 || y != 0 || w != dw || h != dh) {
649 dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
650 x, y, w, h);
651 return -EINVAL;
652 }
653
631 mutex_lock(&ddata->lock); 654 mutex_lock(&ddata->lock);
632 rfbi_bus_lock(); 655 rfbi_bus_lock();
633 656
634 omap_rfbi_prepare_update(dssdev, &x, &y, &w, &h);
635
636 blizzard_ctrl_setup_update(dssdev, x, y, w, h); 657 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
637 658
638 omap_rfbi_update(dssdev, x, y, w, h, update_done, NULL); 659 omap_rfbi_update(dssdev, update_done, NULL);
639 660
640 mutex_unlock(&ddata->lock); 661 mutex_unlock(&ddata->lock);
641 662
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index b122b0f31c43..908fd268f3dc 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -175,6 +175,9 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
175 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 175 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
176 return 0; 176 return 0;
177 177
178 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
179 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
180
178 r = omapdss_dpi_display_enable(dssdev); 181 r = omapdss_dpi_display_enable(dssdev);
179 if (r) 182 if (r)
180 goto err0; 183 goto err0;
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
index 2d35bd388860..9df87640ddd2 100644
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ b/drivers/video/omap2/displays/panel-picodlp.c
@@ -377,6 +377,10 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
377 * then only i2c commands can be successfully sent to dpp2600 377 * then only i2c commands can be successfully sent to dpp2600
378 */ 378 */
379 msleep(1000); 379 msleep(1000);
380
381 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
382 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
383
380 r = omapdss_dpi_display_enable(dssdev); 384 r = omapdss_dpi_display_enable(dssdev);
381 if (r) { 385 if (r) {
382 dev_err(&dssdev->dev, "failed to enable DPI\n"); 386 dev_err(&dssdev->dev, "failed to enable DPI\n");
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index bd86ba9ccf76..1ec3b277ff15 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -142,6 +142,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
142 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 142 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
143 return 0; 143 return 0;
144 144
145 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
146 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
147
145 r = omapdss_dpi_display_enable(dssdev); 148 r = omapdss_dpi_display_enable(dssdev);
146 if (r) 149 if (r)
147 goto err0; 150 goto err0;
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 6b5e6e0e202f..f2f644680ca8 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -121,6 +121,18 @@ struct taal_data {
121 121
122 struct omap_dss_device *dssdev; 122 struct omap_dss_device *dssdev;
123 123
124 /* panel specific HW info */
125 struct panel_config *panel_config;
126
127 /* panel HW configuration from DT or platform data */
128 int reset_gpio;
129 int ext_te_gpio;
130
131 bool use_dsi_backlight;
132
133 struct omap_dsi_pin_config pin_config;
134
135 /* runtime variables */
124 bool enabled; 136 bool enabled;
125 u8 rotate; 137 u8 rotate;
126 bool mirror; 138 bool mirror;
@@ -145,16 +157,8 @@ struct taal_data {
145 bool ulps_enabled; 157 bool ulps_enabled;
146 unsigned ulps_timeout; 158 unsigned ulps_timeout;
147 struct delayed_work ulps_work; 159 struct delayed_work ulps_work;
148
149 struct panel_config *panel_config;
150}; 160};
151 161
152static inline struct nokia_dsi_panel_data
153*get_panel_data(const struct omap_dss_device *dssdev)
154{
155 return (struct nokia_dsi_panel_data *) dssdev->data;
156}
157
158static void taal_esd_work(struct work_struct *work); 162static void taal_esd_work(struct work_struct *work);
159static void taal_ulps_work(struct work_struct *work); 163static void taal_ulps_work(struct work_struct *work);
160 164
@@ -371,7 +375,6 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
371static int taal_enter_ulps(struct omap_dss_device *dssdev) 375static int taal_enter_ulps(struct omap_dss_device *dssdev)
372{ 376{
373 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 377 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
374 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
375 int r; 378 int r;
376 379
377 if (td->ulps_enabled) 380 if (td->ulps_enabled)
@@ -383,7 +386,8 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)
383 if (r) 386 if (r)
384 goto err; 387 goto err;
385 388
386 disable_irq(gpio_to_irq(panel_data->ext_te_gpio)); 389 if (gpio_is_valid(td->ext_te_gpio))
390 disable_irq(gpio_to_irq(td->ext_te_gpio));
387 391
388 omapdss_dsi_display_disable(dssdev, false, true); 392 omapdss_dsi_display_disable(dssdev, false, true);
389 393
@@ -405,7 +409,6 @@ err:
405static int taal_exit_ulps(struct omap_dss_device *dssdev) 409static int taal_exit_ulps(struct omap_dss_device *dssdev)
406{ 410{
407 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 411 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
408 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
409 int r; 412 int r;
410 413
411 if (!td->ulps_enabled) 414 if (!td->ulps_enabled)
@@ -425,7 +428,8 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
425 goto err2; 428 goto err2;
426 } 429 }
427 430
428 enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); 431 if (gpio_is_valid(td->ext_te_gpio))
432 enable_irq(gpio_to_irq(td->ext_te_gpio));
429 433
430 taal_queue_ulps_work(dssdev); 434 taal_queue_ulps_work(dssdev);
431 435
@@ -438,7 +442,8 @@ err2:
438 442
439 r = taal_panel_reset(dssdev); 443 r = taal_panel_reset(dssdev);
440 if (!r) { 444 if (!r) {
441 enable_irq(gpio_to_irq(panel_data->ext_te_gpio)); 445 if (gpio_is_valid(td->ext_te_gpio))
446 enable_irq(gpio_to_irq(td->ext_te_gpio));
442 td->ulps_enabled = false; 447 td->ulps_enabled = false;
443 } 448 }
444err1: 449err1:
@@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = {
835static void taal_hw_reset(struct omap_dss_device *dssdev) 840static void taal_hw_reset(struct omap_dss_device *dssdev)
836{ 841{
837 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 842 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
838 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
839 843
840 if (panel_data->reset_gpio == -1) 844 if (!gpio_is_valid(td->reset_gpio))
841 return; 845 return;
842 846
843 gpio_set_value(panel_data->reset_gpio, 1); 847 gpio_set_value(td->reset_gpio, 1);
844 if (td->panel_config->reset_sequence.high) 848 if (td->panel_config->reset_sequence.high)
845 udelay(td->panel_config->reset_sequence.high); 849 udelay(td->panel_config->reset_sequence.high);
846 /* reset the panel */ 850 /* reset the panel */
847 gpio_set_value(panel_data->reset_gpio, 0); 851 gpio_set_value(td->reset_gpio, 0);
848 /* assert reset */ 852 /* assert reset */
849 if (td->panel_config->reset_sequence.low) 853 if (td->panel_config->reset_sequence.low)
850 udelay(td->panel_config->reset_sequence.low); 854 udelay(td->panel_config->reset_sequence.low);
851 gpio_set_value(panel_data->reset_gpio, 1); 855 gpio_set_value(td->reset_gpio, 1);
852 /* wait after releasing reset */ 856 /* wait after releasing reset */
853 if (td->panel_config->sleep.hw_reset) 857 if (td->panel_config->sleep.hw_reset)
854 msleep(td->panel_config->sleep.hw_reset); 858 msleep(td->panel_config->sleep.hw_reset);
855} 859}
856 860
861static void taal_probe_pdata(struct taal_data *td,
862 const struct nokia_dsi_panel_data *pdata)
863{
864 td->reset_gpio = pdata->reset_gpio;
865
866 if (pdata->use_ext_te)
867 td->ext_te_gpio = pdata->ext_te_gpio;
868 else
869 td->ext_te_gpio = -1;
870
871 td->esd_interval = pdata->esd_interval;
872 td->ulps_timeout = pdata->ulps_timeout;
873
874 td->use_dsi_backlight = pdata->use_dsi_backlight;
875
876 td->pin_config = pdata->pin_config;
877}
878
857static int taal_probe(struct omap_dss_device *dssdev) 879static int taal_probe(struct omap_dss_device *dssdev)
858{ 880{
859 struct backlight_properties props; 881 struct backlight_properties props;
860 struct taal_data *td; 882 struct taal_data *td;
861 struct backlight_device *bldev = NULL; 883 struct backlight_device *bldev = NULL;
862 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
863 struct panel_config *panel_config = NULL;
864 int r, i; 884 int r, i;
885 const char *panel_name;
865 886
866 dev_dbg(&dssdev->dev, "probe\n"); 887 dev_dbg(&dssdev->dev, "probe\n");
867 888
868 if (!panel_data || !panel_data->name) { 889 td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL);
869 r = -EINVAL; 890 if (!td)
870 goto err; 891 return -ENOMEM;
892
893 dev_set_drvdata(&dssdev->dev, td);
894 td->dssdev = dssdev;
895
896 if (dssdev->data) {
897 const struct nokia_dsi_panel_data *pdata = dssdev->data;
898
899 taal_probe_pdata(td, pdata);
900
901 panel_name = pdata->name;
902 } else {
903 return -ENODEV;
871 } 904 }
872 905
906 if (panel_name == NULL)
907 return -EINVAL;
908
873 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { 909 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
874 if (strcmp(panel_data->name, panel_configs[i].name) == 0) { 910 if (strcmp(panel_name, panel_configs[i].name) == 0) {
875 panel_config = &panel_configs[i]; 911 td->panel_config = &panel_configs[i];
876 break; 912 break;
877 } 913 }
878 } 914 }
879 915
880 if (!panel_config) { 916 if (!td->panel_config)
881 r = -EINVAL; 917 return -EINVAL;
882 goto err;
883 }
884 918
885 dssdev->panel.timings = panel_config->timings; 919 dssdev->panel.timings = td->panel_config->timings;
886 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; 920 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
887 921 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
888 td = kzalloc(sizeof(*td), GFP_KERNEL); 922 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
889 if (!td) {
890 r = -ENOMEM;
891 goto err;
892 }
893 td->dssdev = dssdev;
894 td->panel_config = panel_config;
895 td->esd_interval = panel_data->esd_interval;
896 td->ulps_enabled = false;
897 td->ulps_timeout = panel_data->ulps_timeout;
898 923
899 mutex_init(&td->lock); 924 mutex_init(&td->lock);
900 925
901 atomic_set(&td->do_update, 0); 926 atomic_set(&td->do_update, 0);
902 927
903 td->workqueue = create_singlethread_workqueue("taal_esd"); 928 if (gpio_is_valid(td->reset_gpio)) {
904 if (td->workqueue == NULL) { 929 r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio,
905 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 930 GPIOF_OUT_INIT_LOW, "taal rst");
906 r = -ENOMEM; 931 if (r) {
907 goto err_wq; 932 dev_err(&dssdev->dev, "failed to request reset gpio\n");
933 return r;
934 }
908 } 935 }
909 INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work);
910 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
911 936
912 dev_set_drvdata(&dssdev->dev, td); 937 if (gpio_is_valid(td->ext_te_gpio)) {
938 r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio,
939 GPIOF_IN, "taal irq");
940 if (r) {
941 dev_err(&dssdev->dev, "GPIO request failed\n");
942 return r;
943 }
944
945 r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio),
946 taal_te_isr,
947 IRQF_TRIGGER_RISING,
948 "taal vsync", dssdev);
913 949
914 if (gpio_is_valid(panel_data->reset_gpio)) {
915 r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
916 "taal rst");
917 if (r) { 950 if (r) {
918 dev_err(&dssdev->dev, "failed to request reset gpio\n"); 951 dev_err(&dssdev->dev, "IRQ request failed\n");
919 goto err_rst_gpio; 952 return r;
920 } 953 }
954
955 INIT_DEFERRABLE_WORK(&td->te_timeout_work,
956 taal_te_timeout_work_callback);
957
958 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
921 } 959 }
922 960
961 td->workqueue = create_singlethread_workqueue("taal_esd");
962 if (td->workqueue == NULL) {
963 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
964 return -ENOMEM;
965 }
966 INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work);
967 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
968
923 taal_hw_reset(dssdev); 969 taal_hw_reset(dssdev);
924 970
925 if (panel_data->use_dsi_backlight) { 971 if (td->use_dsi_backlight) {
926 memset(&props, 0, sizeof(struct backlight_properties)); 972 memset(&props, 0, sizeof(struct backlight_properties));
927 props.max_brightness = 255; 973 props.max_brightness = 255;
928 974
@@ -943,31 +989,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
943 taal_bl_update_status(bldev); 989 taal_bl_update_status(bldev);
944 } 990 }
945 991
946 if (panel_data->use_ext_te) {
947 int gpio = panel_data->ext_te_gpio;
948
949 r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
950 if (r) {
951 dev_err(&dssdev->dev, "GPIO request failed\n");
952 goto err_gpio;
953 }
954
955 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
956 IRQF_TRIGGER_RISING,
957 "taal vsync", dssdev);
958
959 if (r) {
960 dev_err(&dssdev->dev, "IRQ request failed\n");
961 gpio_free(gpio);
962 goto err_irq;
963 }
964
965 INIT_DEFERRABLE_WORK(&td->te_timeout_work,
966 taal_te_timeout_work_callback);
967
968 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
969 }
970
971 r = omap_dsi_request_vc(dssdev, &td->channel); 992 r = omap_dsi_request_vc(dssdev, &td->channel);
972 if (r) { 993 if (r) {
973 dev_err(&dssdev->dev, "failed to get virtual channel\n"); 994 dev_err(&dssdev->dev, "failed to get virtual channel\n");
@@ -991,29 +1012,16 @@ static int taal_probe(struct omap_dss_device *dssdev)
991err_vc_id: 1012err_vc_id:
992 omap_dsi_release_vc(dssdev, td->channel); 1013 omap_dsi_release_vc(dssdev, td->channel);
993err_req_vc: 1014err_req_vc:
994 if (panel_data->use_ext_te)
995 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
996err_irq:
997 if (panel_data->use_ext_te)
998 gpio_free(panel_data->ext_te_gpio);
999err_gpio:
1000 if (bldev != NULL) 1015 if (bldev != NULL)
1001 backlight_device_unregister(bldev); 1016 backlight_device_unregister(bldev);
1002err_bl: 1017err_bl:
1003 if (gpio_is_valid(panel_data->reset_gpio))
1004 gpio_free(panel_data->reset_gpio);
1005err_rst_gpio:
1006 destroy_workqueue(td->workqueue); 1018 destroy_workqueue(td->workqueue);
1007err_wq:
1008 kfree(td);
1009err:
1010 return r; 1019 return r;
1011} 1020}
1012 1021
1013static void __exit taal_remove(struct omap_dss_device *dssdev) 1022static void __exit taal_remove(struct omap_dss_device *dssdev)
1014{ 1023{
1015 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1024 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1016 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1017 struct backlight_device *bldev; 1025 struct backlight_device *bldev;
1018 1026
1019 dev_dbg(&dssdev->dev, "remove\n"); 1027 dev_dbg(&dssdev->dev, "remove\n");
@@ -1021,12 +1029,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1021 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); 1029 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
1022 omap_dsi_release_vc(dssdev, td->channel); 1030 omap_dsi_release_vc(dssdev, td->channel);
1023 1031
1024 if (panel_data->use_ext_te) {
1025 int gpio = panel_data->ext_te_gpio;
1026 free_irq(gpio_to_irq(gpio), dssdev);
1027 gpio_free(gpio);
1028 }
1029
1030 bldev = td->bldev; 1032 bldev = td->bldev;
1031 if (bldev != NULL) { 1033 if (bldev != NULL) {
1032 bldev->props.power = FB_BLANK_POWERDOWN; 1034 bldev->props.power = FB_BLANK_POWERDOWN;
@@ -1040,26 +1042,31 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1040 1042
1041 /* reset, to be sure that the panel is in a valid state */ 1043 /* reset, to be sure that the panel is in a valid state */
1042 taal_hw_reset(dssdev); 1044 taal_hw_reset(dssdev);
1043
1044 if (gpio_is_valid(panel_data->reset_gpio))
1045 gpio_free(panel_data->reset_gpio);
1046
1047 kfree(td);
1048} 1045}
1049 1046
1050static int taal_power_on(struct omap_dss_device *dssdev) 1047static int taal_power_on(struct omap_dss_device *dssdev)
1051{ 1048{
1052 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1049 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1053 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1054 u8 id1, id2, id3; 1050 u8 id1, id2, id3;
1055 int r; 1051 int r;
1056 1052
1057 r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config); 1053 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
1058 if (r) { 1054 if (r) {
1059 dev_err(&dssdev->dev, "failed to configure DSI pins\n"); 1055 dev_err(&dssdev->dev, "failed to configure DSI pins\n");
1060 goto err0; 1056 goto err0;
1061 }; 1057 };
1062 1058
1059 omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
1060 dssdev->panel.timings.y_res);
1061 omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
1062 omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
1063
1064 r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
1065 if (r) {
1066 dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
1067 goto err0;
1068 }
1069
1063 r = omapdss_dsi_display_enable(dssdev); 1070 r = omapdss_dsi_display_enable(dssdev);
1064 if (r) { 1071 if (r) {
1065 dev_err(&dssdev->dev, "failed to enable DSI\n"); 1072 dev_err(&dssdev->dev, "failed to enable DSI\n");
@@ -1356,7 +1363,6 @@ static int taal_update(struct omap_dss_device *dssdev,
1356 u16 x, u16 y, u16 w, u16 h) 1363 u16 x, u16 y, u16 w, u16 h)
1357{ 1364{
1358 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1365 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1359 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1360 int r; 1366 int r;
1361 1367
1362 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 1368 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -1380,7 +1386,7 @@ static int taal_update(struct omap_dss_device *dssdev,
1380 if (r) 1386 if (r)
1381 goto err; 1387 goto err;
1382 1388
1383 if (td->te_enabled && panel_data->use_ext_te) { 1389 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
1384 schedule_delayed_work(&td->te_timeout_work, 1390 schedule_delayed_work(&td->te_timeout_work,
1385 msecs_to_jiffies(250)); 1391 msecs_to_jiffies(250));
1386 atomic_set(&td->do_update, 1); 1392 atomic_set(&td->do_update, 1);
@@ -1419,7 +1425,6 @@ static int taal_sync(struct omap_dss_device *dssdev)
1419static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) 1425static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1420{ 1426{
1421 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1427 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1422 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1423 int r; 1428 int r;
1424 1429
1425 if (enable) 1430 if (enable)
@@ -1427,7 +1432,7 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1427 else 1432 else
1428 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); 1433 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF);
1429 1434
1430 if (!panel_data->use_ext_te) 1435 if (!gpio_is_valid(td->ext_te_gpio))
1431 omapdss_dsi_enable_te(dssdev, enable); 1436 omapdss_dsi_enable_te(dssdev, enable);
1432 1437
1433 if (td->panel_config->sleep.enable_te) 1438 if (td->panel_config->sleep.enable_te)
@@ -1487,6 +1492,7 @@ static int taal_get_te(struct omap_dss_device *dssdev)
1487static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) 1492static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1488{ 1493{
1489 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1494 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1495 u16 dw, dh;
1490 int r; 1496 int r;
1491 1497
1492 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 1498 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
@@ -1508,6 +1514,16 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1508 goto err; 1514 goto err;
1509 } 1515 }
1510 1516
1517 if (rotate == 0 || rotate == 2) {
1518 dw = dssdev->panel.timings.x_res;
1519 dh = dssdev->panel.timings.y_res;
1520 } else {
1521 dw = dssdev->panel.timings.y_res;
1522 dh = dssdev->panel.timings.x_res;
1523 }
1524
1525 omapdss_dsi_set_size(dssdev, dw, dh);
1526
1511 td->rotate = rotate; 1527 td->rotate = rotate;
1512 1528
1513 dsi_bus_unlock(dssdev); 1529 dsi_bus_unlock(dssdev);
@@ -1726,7 +1742,6 @@ static void taal_esd_work(struct work_struct *work)
1726 struct taal_data *td = container_of(work, struct taal_data, 1742 struct taal_data *td = container_of(work, struct taal_data,
1727 esd_work.work); 1743 esd_work.work);
1728 struct omap_dss_device *dssdev = td->dssdev; 1744 struct omap_dss_device *dssdev = td->dssdev;
1729 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1730 u8 state1, state2; 1745 u8 state1, state2;
1731 int r; 1746 int r;
1732 1747
@@ -1773,7 +1788,7 @@ static void taal_esd_work(struct work_struct *work)
1773 } 1788 }
1774 /* Self-diagnostics result is also shown on TE GPIO line. We need 1789 /* Self-diagnostics result is also shown on TE GPIO line. We need
1775 * to re-enable TE after self diagnostics */ 1790 * to re-enable TE after self diagnostics */
1776 if (td->te_enabled && panel_data->use_ext_te) { 1791 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) {
1777 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); 1792 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0);
1778 if (r) 1793 if (r)
1779 goto err; 1794 goto err;
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index 40cc0cfa5d17..383811cf8648 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -65,6 +65,9 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
65 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 65 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
66 return 0; 66 return 0;
67 67
68 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
69 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
70
68 r = omapdss_dpi_display_enable(dssdev); 71 r = omapdss_dpi_display_enable(dssdev);
69 if (r) 72 if (r)
70 goto err0; 73 goto err0;
@@ -116,8 +119,8 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
116 } 119 }
117 120
118 if (gpio_is_valid(ddata->pd_gpio)) { 121 if (gpio_is_valid(ddata->pd_gpio)) {
119 r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW, 122 r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio,
120 "tfp410 pd"); 123 GPIOF_OUT_INIT_LOW, "tfp410 pd");
121 if (r) { 124 if (r) {
122 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n", 125 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
123 ddata->pd_gpio); 126 ddata->pd_gpio);
@@ -132,8 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
132 if (!adapter) { 135 if (!adapter) {
133 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", 136 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
134 i2c_bus_num); 137 i2c_bus_num);
135 r = -EINVAL; 138 return -EINVAL;
136 goto err_i2c;
137 } 139 }
138 140
139 ddata->i2c_adapter = adapter; 141 ddata->i2c_adapter = adapter;
@@ -142,10 +144,6 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
142 dev_set_drvdata(&dssdev->dev, ddata); 144 dev_set_drvdata(&dssdev->dev, ddata);
143 145
144 return 0; 146 return 0;
145err_i2c:
146 if (gpio_is_valid(ddata->pd_gpio))
147 gpio_free(ddata->pd_gpio);
148 return r;
149} 147}
150 148
151static void __exit tfp410_remove(struct omap_dss_device *dssdev) 149static void __exit tfp410_remove(struct omap_dss_device *dssdev)
@@ -157,9 +155,6 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)
157 if (ddata->i2c_adapter) 155 if (ddata->i2c_adapter)
158 i2c_put_adapter(ddata->i2c_adapter); 156 i2c_put_adapter(ddata->i2c_adapter);
159 157
160 if (gpio_is_valid(ddata->pd_gpio))
161 gpio_free(ddata->pd_gpio);
162
163 dev_set_drvdata(&dssdev->dev, NULL); 158 dev_set_drvdata(&dssdev->dev, NULL);
164 159
165 mutex_unlock(&ddata->lock); 160 mutex_unlock(&ddata->lock);
@@ -231,7 +226,8 @@ static void tfp410_set_timings(struct omap_dss_device *dssdev,
231 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 226 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
232 227
233 mutex_lock(&ddata->lock); 228 mutex_lock(&ddata->lock);
234 dpi_set_timings(dssdev, timings); 229 omapdss_dpi_set_timings(dssdev, timings);
230 dssdev->panel.timings = *timings;
235 mutex_unlock(&ddata->lock); 231 mutex_unlock(&ddata->lock);
236} 232}
237 233
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index fa7baa650ae0..b5e6dbc59f0a 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -337,6 +337,9 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev)
337 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 337 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
338 return 0; 338 return 0;
339 339
340 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
341 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
342
340 r = omapdss_dpi_display_enable(dssdev); 343 r = omapdss_dpi_display_enable(dssdev);
341 if (r) 344 if (r)
342 goto err0; 345 goto err0;
@@ -480,7 +483,9 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
480static void tpo_td043_set_timings(struct omap_dss_device *dssdev, 483static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
481 struct omap_video_timings *timings) 484 struct omap_video_timings *timings)
482{ 485{
483 dpi_set_timings(dssdev, timings); 486 omapdss_dpi_set_timings(dssdev, timings);
487
488 dssdev->panel.timings = *timings;
484} 489}
485 490
486static int tpo_td043_check_timings(struct omap_dss_device *dssdev, 491static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index b337a8469fd8..80f5390aa136 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -84,7 +84,7 @@ config OMAP2_DSS_SDI
84 84
85config OMAP2_DSS_DSI 85config OMAP2_DSS_DSI
86 bool "DSI support" 86 bool "DSI support"
87 depends on ARCH_OMAP3 || ARCH_OMAP4 87 depends on ARCH_OMAP3 || ARCH_OMAP4 || ARCH_OMAP5
88 default n 88 default n
89 help 89 help
90 MIPI DSI (Display Serial Interface) support. 90 MIPI DSI (Display Serial Interface) support.
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 5c450b0f94d0..4549869bfe1a 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,9 +1,9 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
3 manager.o overlay.o apply.o 3 manager.o manager-sysfs.o overlay.o overlay-sysfs.o output.o apply.o
4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o
7omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 7omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 8omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ 9omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 0fefc68372b9..19d66f471b4b 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -111,9 +111,6 @@ static struct {
111 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS]; 111 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
112 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS]; 112 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
113 113
114 bool fifo_merge_dirty;
115 bool fifo_merge;
116
117 bool irq_enabled; 114 bool irq_enabled;
118} dss_data; 115} dss_data;
119 116
@@ -424,17 +421,25 @@ static void wait_pending_extra_info_updates(void)
424int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 421int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
425{ 422{
426 unsigned long timeout = msecs_to_jiffies(500); 423 unsigned long timeout = msecs_to_jiffies(500);
427 struct mgr_priv_data *mp; 424 struct mgr_priv_data *mp = get_mgr_priv(mgr);
428 u32 irq; 425 u32 irq;
426 unsigned long flags;
429 int r; 427 int r;
430 int i; 428 int i;
431 struct omap_dss_device *dssdev = mgr->device;
432 429
433 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 430 spin_lock_irqsave(&data_lock, flags);
431
432 if (mgr_manual_update(mgr)) {
433 spin_unlock_irqrestore(&data_lock, flags);
434 return 0; 434 return 0;
435 }
435 436
436 if (mgr_manual_update(mgr)) 437 if (!mp->enabled) {
438 spin_unlock_irqrestore(&data_lock, flags);
437 return 0; 439 return 0;
440 }
441
442 spin_unlock_irqrestore(&data_lock, flags);
438 443
439 r = dispc_runtime_get(); 444 r = dispc_runtime_get();
440 if (r) 445 if (r)
@@ -442,10 +447,8 @@ int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
442 447
443 irq = dispc_mgr_get_vsync_irq(mgr->id); 448 irq = dispc_mgr_get_vsync_irq(mgr->id);
444 449
445 mp = get_mgr_priv(mgr);
446 i = 0; 450 i = 0;
447 while (1) { 451 while (1) {
448 unsigned long flags;
449 bool shadow_dirty, dirty; 452 bool shadow_dirty, dirty;
450 453
451 spin_lock_irqsave(&data_lock, flags); 454 spin_lock_irqsave(&data_lock, flags);
@@ -489,21 +492,30 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
489{ 492{
490 unsigned long timeout = msecs_to_jiffies(500); 493 unsigned long timeout = msecs_to_jiffies(500);
491 struct ovl_priv_data *op; 494 struct ovl_priv_data *op;
492 struct omap_dss_device *dssdev; 495 struct mgr_priv_data *mp;
493 u32 irq; 496 u32 irq;
497 unsigned long flags;
494 int r; 498 int r;
495 int i; 499 int i;
496 500
497 if (!ovl->manager) 501 if (!ovl->manager)
498 return 0; 502 return 0;
499 503
500 dssdev = ovl->manager->device; 504 mp = get_mgr_priv(ovl->manager);
505
506 spin_lock_irqsave(&data_lock, flags);
501 507
502 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 508 if (ovl_manual_update(ovl)) {
509 spin_unlock_irqrestore(&data_lock, flags);
503 return 0; 510 return 0;
511 }
504 512
505 if (ovl_manual_update(ovl)) 513 if (!mp->enabled) {
514 spin_unlock_irqrestore(&data_lock, flags);
506 return 0; 515 return 0;
516 }
517
518 spin_unlock_irqrestore(&data_lock, flags);
507 519
508 r = dispc_runtime_get(); 520 r = dispc_runtime_get();
509 if (r) 521 if (r)
@@ -514,7 +526,6 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
514 op = get_ovl_priv(ovl); 526 op = get_ovl_priv(ovl);
515 i = 0; 527 i = 0;
516 while (1) { 528 while (1) {
517 unsigned long flags;
518 bool shadow_dirty, dirty; 529 bool shadow_dirty, dirty;
519 530
520 spin_lock_irqsave(&data_lock, flags); 531 spin_lock_irqsave(&data_lock, flags);
@@ -573,7 +584,7 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
573 584
574 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode); 585 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
575 586
576 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings); 587 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
577 if (r) { 588 if (r) {
578 /* 589 /*
579 * We can't do much here, as this function can be called from 590 * We can't do much here, as this function can be called from
@@ -677,40 +688,11 @@ static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
677 mp->shadow_extra_info_dirty = true; 688 mp->shadow_extra_info_dirty = true;
678} 689}
679 690
680static void dss_write_regs_common(void)
681{
682 const int num_mgrs = omap_dss_get_num_overlay_managers();
683 int i;
684
685 if (!dss_data.fifo_merge_dirty)
686 return;
687
688 for (i = 0; i < num_mgrs; ++i) {
689 struct omap_overlay_manager *mgr;
690 struct mgr_priv_data *mp;
691
692 mgr = omap_dss_get_overlay_manager(i);
693 mp = get_mgr_priv(mgr);
694
695 if (mp->enabled) {
696 if (dss_data.fifo_merge_dirty) {
697 dispc_enable_fifomerge(dss_data.fifo_merge);
698 dss_data.fifo_merge_dirty = false;
699 }
700
701 if (mp->updating)
702 mp->shadow_info_dirty = true;
703 }
704 }
705}
706
707static void dss_write_regs(void) 691static void dss_write_regs(void)
708{ 692{
709 const int num_mgrs = omap_dss_get_num_overlay_managers(); 693 const int num_mgrs = omap_dss_get_num_overlay_managers();
710 int i; 694 int i;
711 695
712 dss_write_regs_common();
713
714 for (i = 0; i < num_mgrs; ++i) { 696 for (i = 0; i < num_mgrs; ++i) {
715 struct omap_overlay_manager *mgr; 697 struct omap_overlay_manager *mgr;
716 struct mgr_priv_data *mp; 698 struct mgr_priv_data *mp;
@@ -799,8 +781,6 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
799 dss_mgr_write_regs(mgr); 781 dss_mgr_write_regs(mgr);
800 dss_mgr_write_regs_extra(mgr); 782 dss_mgr_write_regs_extra(mgr);
801 783
802 dss_write_regs_common();
803
804 mp->updating = true; 784 mp->updating = true;
805 785
806 if (!dss_data.irq_enabled && need_isr()) 786 if (!dss_data.irq_enabled && need_isr())
@@ -984,20 +964,11 @@ static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
984 op->extra_info_dirty = true; 964 op->extra_info_dirty = true;
985} 965}
986 966
987static void dss_apply_fifo_merge(bool use_fifo_merge) 967static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
988{
989 if (dss_data.fifo_merge == use_fifo_merge)
990 return;
991
992 dss_data.fifo_merge = use_fifo_merge;
993 dss_data.fifo_merge_dirty = true;
994}
995
996static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
997 bool use_fifo_merge)
998{ 968{
999 struct ovl_priv_data *op = get_ovl_priv(ovl); 969 struct ovl_priv_data *op = get_ovl_priv(ovl);
1000 u32 fifo_low, fifo_high; 970 u32 fifo_low, fifo_high;
971 bool use_fifo_merge = false;
1001 972
1002 if (!op->enabled && !op->enabling) 973 if (!op->enabled && !op->enabling)
1003 return; 974 return;
@@ -1008,8 +979,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
1008 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 979 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
1009} 980}
1010 981
1011static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, 982static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
1012 bool use_fifo_merge)
1013{ 983{
1014 struct omap_overlay *ovl; 984 struct omap_overlay *ovl;
1015 struct mgr_priv_data *mp; 985 struct mgr_priv_data *mp;
@@ -1020,94 +990,19 @@ static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr,
1020 return; 990 return;
1021 991
1022 list_for_each_entry(ovl, &mgr->overlays, list) 992 list_for_each_entry(ovl, &mgr->overlays, list)
1023 dss_ovl_setup_fifo(ovl, use_fifo_merge); 993 dss_ovl_setup_fifo(ovl);
1024}
1025
1026static void dss_setup_fifos(bool use_fifo_merge)
1027{
1028 const int num_mgrs = omap_dss_get_num_overlay_managers();
1029 struct omap_overlay_manager *mgr;
1030 int i;
1031
1032 for (i = 0; i < num_mgrs; ++i) {
1033 mgr = omap_dss_get_overlay_manager(i);
1034 dss_mgr_setup_fifos(mgr, use_fifo_merge);
1035 }
1036} 994}
1037 995
1038static int get_num_used_managers(void) 996static void dss_setup_fifos(void)
1039{ 997{
1040 const int num_mgrs = omap_dss_get_num_overlay_managers(); 998 const int num_mgrs = omap_dss_get_num_overlay_managers();
1041 struct omap_overlay_manager *mgr; 999 struct omap_overlay_manager *mgr;
1042 struct mgr_priv_data *mp;
1043 int i; 1000 int i;
1044 int enabled_mgrs;
1045
1046 enabled_mgrs = 0;
1047 1001
1048 for (i = 0; i < num_mgrs; ++i) { 1002 for (i = 0; i < num_mgrs; ++i) {
1049 mgr = omap_dss_get_overlay_manager(i); 1003 mgr = omap_dss_get_overlay_manager(i);
1050 mp = get_mgr_priv(mgr); 1004 dss_mgr_setup_fifos(mgr);
1051
1052 if (!mp->enabled)
1053 continue;
1054
1055 enabled_mgrs++;
1056 } 1005 }
1057
1058 return enabled_mgrs;
1059}
1060
1061static int get_num_used_overlays(void)
1062{
1063 const int num_ovls = omap_dss_get_num_overlays();
1064 struct omap_overlay *ovl;
1065 struct ovl_priv_data *op;
1066 struct mgr_priv_data *mp;
1067 int i;
1068 int enabled_ovls;
1069
1070 enabled_ovls = 0;
1071
1072 for (i = 0; i < num_ovls; ++i) {
1073 ovl = omap_dss_get_overlay(i);
1074 op = get_ovl_priv(ovl);
1075
1076 if (!op->enabled && !op->enabling)
1077 continue;
1078
1079 mp = get_mgr_priv(ovl->manager);
1080
1081 if (!mp->enabled)
1082 continue;
1083
1084 enabled_ovls++;
1085 }
1086
1087 return enabled_ovls;
1088}
1089
1090static bool get_use_fifo_merge(void)
1091{
1092 int enabled_mgrs = get_num_used_managers();
1093 int enabled_ovls = get_num_used_overlays();
1094
1095 if (!dss_has_feature(FEAT_FIFO_MERGE))
1096 return false;
1097
1098 /*
1099 * In theory the only requirement for fifomerge is enabled_ovls <= 1.
1100 * However, if we have two managers enabled and set/unset the fifomerge,
1101 * we need to set the GO bits in particular sequence for the managers,
1102 * and wait in between.
1103 *
1104 * This is rather difficult as new apply calls can happen at any time,
1105 * so we simplify the problem by requiring also that enabled_mgrs <= 1.
1106 * In practice this shouldn't matter, because when only one overlay is
1107 * enabled, most likely only one output is enabled.
1108 */
1109
1110 return enabled_mgrs <= 1 && enabled_ovls <= 1;
1111} 1006}
1112 1007
1113int dss_mgr_enable(struct omap_overlay_manager *mgr) 1008int dss_mgr_enable(struct omap_overlay_manager *mgr)
@@ -1115,7 +1010,6 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1115 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1010 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1116 unsigned long flags; 1011 unsigned long flags;
1117 int r; 1012 int r;
1118 bool fifo_merge;
1119 1013
1120 mutex_lock(&apply_lock); 1014 mutex_lock(&apply_lock);
1121 1015
@@ -1133,23 +1027,11 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1133 goto err; 1027 goto err;
1134 } 1028 }
1135 1029
1136 /* step 1: setup fifos/fifomerge before enabling the manager */ 1030 dss_setup_fifos();
1137
1138 fifo_merge = get_use_fifo_merge();
1139 dss_setup_fifos(fifo_merge);
1140 dss_apply_fifo_merge(fifo_merge);
1141 1031
1142 dss_write_regs(); 1032 dss_write_regs();
1143 dss_set_go_bits(); 1033 dss_set_go_bits();
1144 1034
1145 spin_unlock_irqrestore(&data_lock, flags);
1146
1147 /* wait until fifo config is in */
1148 wait_pending_extra_info_updates();
1149
1150 /* step 2: enable the manager */
1151 spin_lock_irqsave(&data_lock, flags);
1152
1153 if (!mgr_manual_update(mgr)) 1035 if (!mgr_manual_update(mgr))
1154 mp->updating = true; 1036 mp->updating = true;
1155 1037
@@ -1174,7 +1056,6 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1174{ 1056{
1175 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1057 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1176 unsigned long flags; 1058 unsigned long flags;
1177 bool fifo_merge;
1178 1059
1179 mutex_lock(&apply_lock); 1060 mutex_lock(&apply_lock);
1180 1061
@@ -1189,16 +1070,8 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1189 mp->updating = false; 1070 mp->updating = false;
1190 mp->enabled = false; 1071 mp->enabled = false;
1191 1072
1192 fifo_merge = get_use_fifo_merge();
1193 dss_setup_fifos(fifo_merge);
1194 dss_apply_fifo_merge(fifo_merge);
1195
1196 dss_write_regs();
1197 dss_set_go_bits();
1198
1199 spin_unlock_irqrestore(&data_lock, flags); 1073 spin_unlock_irqrestore(&data_lock, flags);
1200 1074
1201 wait_pending_extra_info_updates();
1202out: 1075out:
1203 mutex_unlock(&apply_lock); 1076 mutex_unlock(&apply_lock);
1204} 1077}
@@ -1237,29 +1110,29 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1237 spin_unlock_irqrestore(&data_lock, flags); 1110 spin_unlock_irqrestore(&data_lock, flags);
1238} 1111}
1239 1112
1240int dss_mgr_set_device(struct omap_overlay_manager *mgr, 1113int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1241 struct omap_dss_device *dssdev) 1114 struct omap_dss_output *output)
1242{ 1115{
1243 int r; 1116 int r;
1244 1117
1245 mutex_lock(&apply_lock); 1118 mutex_lock(&apply_lock);
1246 1119
1247 if (dssdev->manager) { 1120 if (mgr->output) {
1248 DSSERR("display '%s' already has a manager '%s'\n", 1121 DSSERR("manager %s is already connected to an output\n",
1249 dssdev->name, dssdev->manager->name); 1122 mgr->name);
1250 r = -EINVAL; 1123 r = -EINVAL;
1251 goto err; 1124 goto err;
1252 } 1125 }
1253 1126
1254 if ((mgr->supported_displays & dssdev->type) == 0) { 1127 if ((mgr->supported_outputs & output->id) == 0) {
1255 DSSERR("display '%s' does not support manager '%s'\n", 1128 DSSERR("output does not support manager %s\n",
1256 dssdev->name, mgr->name); 1129 mgr->name);
1257 r = -EINVAL; 1130 r = -EINVAL;
1258 goto err; 1131 goto err;
1259 } 1132 }
1260 1133
1261 dssdev->manager = mgr; 1134 output->manager = mgr;
1262 mgr->device = dssdev; 1135 mgr->output = output;
1263 1136
1264 mutex_unlock(&apply_lock); 1137 mutex_unlock(&apply_lock);
1265 1138
@@ -1269,40 +1142,46 @@ err:
1269 return r; 1142 return r;
1270} 1143}
1271 1144
1272int dss_mgr_unset_device(struct omap_overlay_manager *mgr) 1145int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1273{ 1146{
1274 int r; 1147 int r;
1148 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1149 unsigned long flags;
1275 1150
1276 mutex_lock(&apply_lock); 1151 mutex_lock(&apply_lock);
1277 1152
1278 if (!mgr->device) { 1153 if (!mgr->output) {
1279 DSSERR("failed to unset display, display not set.\n"); 1154 DSSERR("failed to unset output, output not set\n");
1280 r = -EINVAL; 1155 r = -EINVAL;
1281 goto err; 1156 goto err;
1282 } 1157 }
1283 1158
1284 /* 1159 spin_lock_irqsave(&data_lock, flags);
1285 * Don't allow currently enabled displays to have the overlay manager 1160
1286 * pulled out from underneath them 1161 if (mp->enabled) {
1287 */ 1162 DSSERR("output can't be unset when manager is enabled\n");
1288 if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
1289 r = -EINVAL; 1163 r = -EINVAL;
1290 goto err; 1164 goto err1;
1291 } 1165 }
1292 1166
1293 mgr->device->manager = NULL; 1167 spin_unlock_irqrestore(&data_lock, flags);
1294 mgr->device = NULL; 1168
1169 mgr->output->manager = NULL;
1170 mgr->output = NULL;
1295 1171
1296 mutex_unlock(&apply_lock); 1172 mutex_unlock(&apply_lock);
1297 1173
1298 return 0; 1174 return 0;
1175err1:
1176 spin_unlock_irqrestore(&data_lock, flags);
1299err: 1177err:
1300 mutex_unlock(&apply_lock); 1178 mutex_unlock(&apply_lock);
1179
1301 return r; 1180 return r;
1302} 1181}
1303 1182
1304static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, 1183static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1305 struct omap_video_timings *timings) 1184 const struct omap_video_timings *timings)
1306{ 1185{
1307 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1186 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1308 1187
@@ -1311,24 +1190,22 @@ static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1311} 1190}
1312 1191
1313void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 1192void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1314 struct omap_video_timings *timings) 1193 const struct omap_video_timings *timings)
1315{ 1194{
1316 unsigned long flags; 1195 unsigned long flags;
1317 1196 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1318 mutex_lock(&apply_lock);
1319 1197
1320 spin_lock_irqsave(&data_lock, flags); 1198 spin_lock_irqsave(&data_lock, flags);
1321 1199
1322 dss_apply_mgr_timings(mgr, timings); 1200 if (mp->updating) {
1323 1201 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1324 dss_write_regs(); 1202 mgr->name);
1325 dss_set_go_bits(); 1203 goto out;
1204 }
1326 1205
1206 dss_apply_mgr_timings(mgr, timings);
1207out:
1327 spin_unlock_irqrestore(&data_lock, flags); 1208 spin_unlock_irqrestore(&data_lock, flags);
1328
1329 wait_pending_extra_info_updates();
1330
1331 mutex_unlock(&apply_lock);
1332} 1209}
1333 1210
1334static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, 1211static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
@@ -1346,7 +1223,7 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1346 unsigned long flags; 1223 unsigned long flags;
1347 struct mgr_priv_data *mp = get_mgr_priv(mgr); 1224 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1348 1225
1349 mutex_lock(&apply_lock); 1226 spin_lock_irqsave(&data_lock, flags);
1350 1227
1351 if (mp->enabled) { 1228 if (mp->enabled) {
1352 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n", 1229 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
@@ -1354,19 +1231,9 @@ void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
1354 goto out; 1231 goto out;
1355 } 1232 }
1356 1233
1357 spin_lock_irqsave(&data_lock, flags);
1358
1359 dss_apply_mgr_lcd_config(mgr, config); 1234 dss_apply_mgr_lcd_config(mgr, config);
1360
1361 dss_write_regs();
1362 dss_set_go_bits();
1363
1364 spin_unlock_irqrestore(&data_lock, flags);
1365
1366 wait_pending_extra_info_updates();
1367
1368out: 1235out:
1369 mutex_unlock(&apply_lock); 1236 spin_unlock_irqrestore(&data_lock, flags);
1370} 1237}
1371 1238
1372int dss_ovl_set_info(struct omap_overlay *ovl, 1239int dss_ovl_set_info(struct omap_overlay *ovl,
@@ -1483,6 +1350,13 @@ int dss_ovl_unset_manager(struct omap_overlay *ovl)
1483 goto err; 1350 goto err;
1484 } 1351 }
1485 1352
1353 spin_unlock_irqrestore(&data_lock, flags);
1354
1355 /* wait for pending extra_info updates to ensure the ovl is disabled */
1356 wait_pending_extra_info_updates();
1357
1358 spin_lock_irqsave(&data_lock, flags);
1359
1486 op->channel = -1; 1360 op->channel = -1;
1487 1361
1488 ovl->manager = NULL; 1362 ovl->manager = NULL;
@@ -1517,7 +1391,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1517{ 1391{
1518 struct ovl_priv_data *op = get_ovl_priv(ovl); 1392 struct ovl_priv_data *op = get_ovl_priv(ovl);
1519 unsigned long flags; 1393 unsigned long flags;
1520 bool fifo_merge;
1521 int r; 1394 int r;
1522 1395
1523 mutex_lock(&apply_lock); 1396 mutex_lock(&apply_lock);
@@ -1527,7 +1400,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1527 goto err1; 1400 goto err1;
1528 } 1401 }
1529 1402
1530 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1403 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1531 r = -EINVAL; 1404 r = -EINVAL;
1532 goto err1; 1405 goto err1;
1533 } 1406 }
@@ -1543,22 +1416,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1543 goto err2; 1416 goto err2;
1544 } 1417 }
1545 1418
1546 /* step 1: configure fifos/fifomerge for currently enabled ovls */ 1419 dss_setup_fifos();
1547
1548 fifo_merge = get_use_fifo_merge();
1549 dss_setup_fifos(fifo_merge);
1550 dss_apply_fifo_merge(fifo_merge);
1551
1552 dss_write_regs();
1553 dss_set_go_bits();
1554
1555 spin_unlock_irqrestore(&data_lock, flags);
1556
1557 /* wait for fifo configs to go in */
1558 wait_pending_extra_info_updates();
1559
1560 /* step 2: enable the overlay */
1561 spin_lock_irqsave(&data_lock, flags);
1562 1420
1563 op->enabling = false; 1421 op->enabling = false;
1564 dss_apply_ovl_enable(ovl, true); 1422 dss_apply_ovl_enable(ovl, true);
@@ -1568,9 +1426,6 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1568 1426
1569 spin_unlock_irqrestore(&data_lock, flags); 1427 spin_unlock_irqrestore(&data_lock, flags);
1570 1428
1571 /* wait for overlay to be enabled */
1572 wait_pending_extra_info_updates();
1573
1574 mutex_unlock(&apply_lock); 1429 mutex_unlock(&apply_lock);
1575 1430
1576 return 0; 1431 return 0;
@@ -1586,7 +1441,6 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1586{ 1441{
1587 struct ovl_priv_data *op = get_ovl_priv(ovl); 1442 struct ovl_priv_data *op = get_ovl_priv(ovl);
1588 unsigned long flags; 1443 unsigned long flags;
1589 bool fifo_merge;
1590 int r; 1444 int r;
1591 1445
1592 mutex_lock(&apply_lock); 1446 mutex_lock(&apply_lock);
@@ -1596,39 +1450,19 @@ int dss_ovl_disable(struct omap_overlay *ovl)
1596 goto err; 1450 goto err;
1597 } 1451 }
1598 1452
1599 if (ovl->manager == NULL || ovl->manager->device == NULL) { 1453 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1600 r = -EINVAL; 1454 r = -EINVAL;
1601 goto err; 1455 goto err;
1602 } 1456 }
1603 1457
1604 /* step 1: disable the overlay */
1605 spin_lock_irqsave(&data_lock, flags); 1458 spin_lock_irqsave(&data_lock, flags);
1606 1459
1607 dss_apply_ovl_enable(ovl, false); 1460 dss_apply_ovl_enable(ovl, false);
1608
1609 dss_write_regs(); 1461 dss_write_regs();
1610 dss_set_go_bits(); 1462 dss_set_go_bits();
1611 1463
1612 spin_unlock_irqrestore(&data_lock, flags); 1464 spin_unlock_irqrestore(&data_lock, flags);
1613 1465
1614 /* wait for the overlay to be disabled */
1615 wait_pending_extra_info_updates();
1616
1617 /* step 2: configure fifos/fifomerge */
1618 spin_lock_irqsave(&data_lock, flags);
1619
1620 fifo_merge = get_use_fifo_merge();
1621 dss_setup_fifos(fifo_merge);
1622 dss_apply_fifo_merge(fifo_merge);
1623
1624 dss_write_regs();
1625 dss_set_go_bits();
1626
1627 spin_unlock_irqrestore(&data_lock, flags);
1628
1629 /* wait for fifo config to go in */
1630 wait_pending_extra_info_updates();
1631
1632 mutex_unlock(&apply_lock); 1466 mutex_unlock(&apply_lock);
1633 1467
1634 return 0; 1468 return 0;
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 58bd9c27369d..b2af72dc20bd 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -33,6 +33,7 @@
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/suspend.h> 35#include <linux/suspend.h>
36#include <linux/slab.h>
36 37
37#include <video/omapdss.h> 38#include <video/omapdss.h>
38 39
@@ -57,6 +58,11 @@ bool dss_debug;
57module_param_named(debug, dss_debug, bool, 0644); 58module_param_named(debug, dss_debug, bool, 0644);
58#endif 59#endif
59 60
61const char *dss_get_default_display_name(void)
62{
63 return core.default_display_name;
64}
65
60/* REGULATORS */ 66/* REGULATORS */
61 67
62struct regulator *dss_get_vdds_dsi(void) 68struct regulator *dss_get_vdds_dsi(void)
@@ -347,17 +353,14 @@ static int dss_driver_probe(struct device *dev)
347 int r; 353 int r;
348 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 354 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
349 struct omap_dss_device *dssdev = to_dss_device(dev); 355 struct omap_dss_device *dssdev = to_dss_device(dev);
350 bool force;
351 356
352 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 357 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
353 dev_name(dev), dssdev->driver_name, 358 dev_name(dev), dssdev->driver_name,
354 dssdrv->driver.name); 359 dssdrv->driver.name);
355 360
356 dss_init_device(core.pdev, dssdev); 361 r = dss_init_device(core.pdev, dssdev);
357 362 if (r)
358 force = core.default_display_name && 363 return r;
359 strcmp(core.default_display_name, dssdev->name) == 0;
360 dss_recheck_connections(dssdev, force);
361 364
362 r = dssdrv->probe(dssdev); 365 r = dssdrv->probe(dssdev);
363 366
@@ -416,54 +419,44 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
416EXPORT_SYMBOL(omap_dss_unregister_driver); 419EXPORT_SYMBOL(omap_dss_unregister_driver);
417 420
418/* DEVICE */ 421/* DEVICE */
419static void reset_device(struct device *dev, int check)
420{
421 u8 *dev_p = (u8 *)dev;
422 u8 *dev_end = dev_p + sizeof(*dev);
423 void *saved_pdata;
424
425 saved_pdata = dev->platform_data;
426 if (check) {
427 /*
428 * Check if there is any other setting than platform_data
429 * in struct device; warn that these will be reset by our
430 * init.
431 */
432 dev->platform_data = NULL;
433 while (dev_p < dev_end) {
434 if (*dev_p) {
435 WARN("%s: struct device fields will be "
436 "discarded\n",
437 __func__);
438 break;
439 }
440 dev_p++;
441 }
442 }
443 memset(dev, 0, sizeof(*dev));
444 dev->platform_data = saved_pdata;
445}
446
447 422
448static void omap_dss_dev_release(struct device *dev) 423static void omap_dss_dev_release(struct device *dev)
449{ 424{
450 reset_device(dev, 0); 425 struct omap_dss_device *dssdev = to_dss_device(dev);
426 kfree(dssdev);
451} 427}
452 428
453int omap_dss_register_device(struct omap_dss_device *dssdev, 429static int disp_num_counter;
454 struct device *parent, int disp_num) 430
431struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
455{ 432{
456 WARN_ON(!dssdev->driver_name); 433 struct omap_dss_device *dssdev;
434
435 dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL);
436 if (!dssdev)
437 return NULL;
457 438
458 reset_device(&dssdev->dev, 1);
459 dssdev->dev.bus = &dss_bus_type; 439 dssdev->dev.bus = &dss_bus_type;
460 dssdev->dev.parent = parent; 440 dssdev->dev.parent = parent;
461 dssdev->dev.release = omap_dss_dev_release; 441 dssdev->dev.release = omap_dss_dev_release;
462 dev_set_name(&dssdev->dev, "display%d", disp_num); 442 dev_set_name(&dssdev->dev, "display%d", disp_num_counter++);
463 return device_register(&dssdev->dev); 443
444 device_initialize(&dssdev->dev);
445
446 return dssdev;
447}
448
449int dss_add_device(struct omap_dss_device *dssdev)
450{
451 return device_add(&dssdev->dev);
452}
453
454void dss_put_device(struct omap_dss_device *dssdev)
455{
456 put_device(&dssdev->dev);
464} 457}
465 458
466void omap_dss_unregister_device(struct omap_dss_device *dssdev) 459void dss_unregister_device(struct omap_dss_device *dssdev)
467{ 460{
468 device_unregister(&dssdev->dev); 461 device_unregister(&dssdev->dev);
469} 462}
@@ -471,15 +464,25 @@ void omap_dss_unregister_device(struct omap_dss_device *dssdev)
471static int dss_unregister_dss_dev(struct device *dev, void *data) 464static int dss_unregister_dss_dev(struct device *dev, void *data)
472{ 465{
473 struct omap_dss_device *dssdev = to_dss_device(dev); 466 struct omap_dss_device *dssdev = to_dss_device(dev);
474 omap_dss_unregister_device(dssdev); 467 dss_unregister_device(dssdev);
475 return 0; 468 return 0;
476} 469}
477 470
478void omap_dss_unregister_child_devices(struct device *parent) 471void dss_unregister_child_devices(struct device *parent)
479{ 472{
480 device_for_each_child(parent, NULL, dss_unregister_dss_dev); 473 device_for_each_child(parent, NULL, dss_unregister_dss_dev);
481} 474}
482 475
476void dss_copy_device_pdata(struct omap_dss_device *dst,
477 const struct omap_dss_device *src)
478{
479 u8 *d = (u8 *)dst;
480 u8 *s = (u8 *)src;
481 size_t dsize = sizeof(struct device);
482
483 memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
484}
485
483/* BUS */ 486/* BUS */
484static int __init omap_dss_bus_register(void) 487static int __init omap_dss_bus_register(void)
485{ 488{
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ee9e29639dcc..b43477a5fae8 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -38,7 +38,6 @@
38#include <linux/pm_runtime.h> 38#include <linux/pm_runtime.h>
39 39
40#include <plat/cpu.h> 40#include <plat/cpu.h>
41#include <plat/clock.h>
42 41
43#include <video/omapdss.h> 42#include <video/omapdss.h>
44 43
@@ -82,6 +81,30 @@ struct dispc_irq_stats {
82 unsigned irqs[32]; 81 unsigned irqs[32];
83}; 82};
84 83
84struct dispc_features {
85 u8 sw_start;
86 u8 fp_start;
87 u8 bp_start;
88 u16 sw_max;
89 u16 vp_max;
90 u16 hp_max;
91 int (*calc_scaling) (enum omap_plane plane,
92 const struct omap_video_timings *mgr_timings,
93 u16 width, u16 height, u16 out_width, u16 out_height,
94 enum omap_color_mode color_mode, bool *five_taps,
95 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
96 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
97 unsigned long (*calc_core_clk) (enum omap_plane plane,
98 u16 width, u16 height, u16 out_width, u16 out_height,
99 bool mem_to_mem);
100 u8 num_fifos;
101
102 /* swap GFX & WB fifos */
103 bool gfx_fifo_workaround:1;
104};
105
106#define DISPC_MAX_NR_FIFOS 5
107
85static struct { 108static struct {
86 struct platform_device *pdev; 109 struct platform_device *pdev;
87 void __iomem *base; 110 void __iomem *base;
@@ -91,7 +114,9 @@ static struct {
91 int irq; 114 int irq;
92 struct clk *dss_clk; 115 struct clk *dss_clk;
93 116
94 u32 fifo_size[MAX_DSS_OVERLAYS]; 117 u32 fifo_size[DISPC_MAX_NR_FIFOS];
118 /* maps which plane is using a fifo. fifo-id -> plane-id */
119 int fifo_assignment[DISPC_MAX_NR_FIFOS];
95 120
96 spinlock_t irq_lock; 121 spinlock_t irq_lock;
97 u32 irq_error_mask; 122 u32 irq_error_mask;
@@ -102,6 +127,8 @@ static struct {
102 bool ctx_valid; 127 bool ctx_valid;
103 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 128 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
104 129
130 const struct dispc_features *feat;
131
105#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 132#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
106 spinlock_t irq_stats_lock; 133 spinlock_t irq_stats_lock;
107 struct dispc_irq_stats irq_stats; 134 struct dispc_irq_stats irq_stats;
@@ -211,7 +238,14 @@ static const struct {
211 }, 238 },
212}; 239};
213 240
241struct color_conv_coef {
242 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
243 int full_range;
244};
245
214static void _omap_dispc_set_irqs(void); 246static void _omap_dispc_set_irqs(void);
247static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
248static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
215 249
216static inline void dispc_write_reg(const u16 idx, u32 val) 250static inline void dispc_write_reg(const u16 idx, u32 val)
217{ 251{
@@ -509,6 +543,11 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
509 return mgr_desc[channel].framedone_irq; 543 return mgr_desc[channel].framedone_irq;
510} 544}
511 545
546u32 dispc_wb_get_framedone_irq(void)
547{
548 return DISPC_IRQ_FRAMEDONEWB;
549}
550
512bool dispc_mgr_go_busy(enum omap_channel channel) 551bool dispc_mgr_go_busy(enum omap_channel channel)
513{ 552{
514 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 553 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1;
@@ -536,6 +575,30 @@ void dispc_mgr_go(enum omap_channel channel)
536 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 575 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1);
537} 576}
538 577
578bool dispc_wb_go_busy(void)
579{
580 return REG_GET(DISPC_CONTROL2, 6, 6) == 1;
581}
582
583void dispc_wb_go(void)
584{
585 enum omap_plane plane = OMAP_DSS_WB;
586 bool enable, go;
587
588 enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1;
589
590 if (!enable)
591 return;
592
593 go = REG_GET(DISPC_CONTROL2, 6, 6) == 1;
594 if (go) {
595 DSSERR("GO bit not down for WB\n");
596 return;
597 }
598
599 REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6);
600}
601
539static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) 602static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value)
540{ 603{
541 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); 604 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
@@ -618,41 +681,41 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
618 } 681 }
619} 682}
620 683
621static void _dispc_setup_color_conv_coef(void)
622{
623 int i;
624 const struct color_conv_coef {
625 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
626 int full_range;
627 } ctbl_bt601_5 = {
628 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
629 };
630
631 const struct color_conv_coef *ct;
632 684
685static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
686 const struct color_conv_coef *ct)
687{
633#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) 688#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
634 689
635 ct = &ctbl_bt601_5; 690 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry));
691 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb));
692 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr));
693 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by));
694 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
636 695
637 for (i = 1; i < dss_feat_get_num_ovls(); i++) { 696 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
638 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 0),
639 CVAL(ct->rcr, ct->ry));
640 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 1),
641 CVAL(ct->gy, ct->rcb));
642 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 2),
643 CVAL(ct->gcb, ct->gcr));
644 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 3),
645 CVAL(ct->bcr, ct->by));
646 dispc_write_reg(DISPC_OVL_CONV_COEF(i, 4),
647 CVAL(0, ct->bcb));
648
649 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), ct->full_range,
650 11, 11);
651 }
652 697
653#undef CVAL 698#undef CVAL
654} 699}
655 700
701static void dispc_setup_color_conv_coef(void)
702{
703 int i;
704 int num_ovl = dss_feat_get_num_ovls();
705 int num_wb = dss_feat_get_num_wbs();
706 const struct color_conv_coef ctbl_bt601_5_ovl = {
707 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
708 };
709 const struct color_conv_coef ctbl_bt601_5_wb = {
710 66, 112, -38, 129, -94, -74, 25, -18, 112, 0,
711 };
712
713 for (i = 1; i < num_ovl; i++)
714 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
715
716 for (; i < num_wb; i++)
717 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb);
718}
656 719
657static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) 720static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr)
658{ 721{
@@ -674,24 +737,32 @@ static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr)
674 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); 737 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
675} 738}
676 739
677static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) 740static void dispc_ovl_set_pos(enum omap_plane plane,
741 enum omap_overlay_caps caps, int x, int y)
678{ 742{
679 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 743 u32 val;
744
745 if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
746 return;
747
748 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
680 749
681 dispc_write_reg(DISPC_OVL_POSITION(plane), val); 750 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
682} 751}
683 752
684static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) 753static void dispc_ovl_set_input_size(enum omap_plane plane, int width,
754 int height)
685{ 755{
686 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 756 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
687 757
688 if (plane == OMAP_DSS_GFX) 758 if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB)
689 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 759 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
690 else 760 else
691 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); 761 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
692} 762}
693 763
694static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) 764static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
765 int height)
695{ 766{
696 u32 val; 767 u32 val;
697 768
@@ -699,14 +770,16 @@ static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height)
699 770
700 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 771 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
701 772
702 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 773 if (plane == OMAP_DSS_WB)
774 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
775 else
776 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
703} 777}
704 778
705static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) 779static void dispc_ovl_set_zorder(enum omap_plane plane,
780 enum omap_overlay_caps caps, u8 zorder)
706{ 781{
707 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 782 if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
708
709 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
710 return; 783 return;
711 784
712 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26); 785 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
@@ -723,23 +796,22 @@ static void dispc_ovl_enable_zorder_planes(void)
723 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); 796 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25);
724} 797}
725 798
726static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) 799static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
800 enum omap_overlay_caps caps, bool enable)
727{ 801{
728 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 802 if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
729
730 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
731 return; 803 return;
732 804
733 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); 805 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
734} 806}
735 807
736static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 808static void dispc_ovl_setup_global_alpha(enum omap_plane plane,
809 enum omap_overlay_caps caps, u8 global_alpha)
737{ 810{
738 static const unsigned shifts[] = { 0, 8, 16, 24, }; 811 static const unsigned shifts[] = { 0, 8, 16, 24, };
739 int shift; 812 int shift;
740 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
741 813
742 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) 814 if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
743 return; 815 return;
744 816
745 shift = shifts[plane]; 817 shift = shifts[plane];
@@ -947,10 +1019,17 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
947 return channel; 1019 return channel;
948} 1020}
949 1021
1022void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
1023{
1024 enum omap_plane plane = OMAP_DSS_WB;
1025
1026 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
1027}
1028
950static void dispc_ovl_set_burst_size(enum omap_plane plane, 1029static void dispc_ovl_set_burst_size(enum omap_plane plane,
951 enum omap_burst_size burst_size) 1030 enum omap_burst_size burst_size)
952{ 1031{
953 static const unsigned shifts[] = { 6, 14, 14, 14, }; 1032 static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
954 int shift; 1033 int shift;
955 1034
956 shift = shifts[plane]; 1035 shift = shifts[plane];
@@ -1027,11 +1106,15 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1027 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1106 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1028} 1107}
1029 1108
1030static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) 1109static void dispc_ovl_enable_replication(enum omap_plane plane,
1110 enum omap_overlay_caps caps, bool enable)
1031{ 1111{
1032 static const unsigned shifts[] = { 5, 10, 10, 10 }; 1112 static const unsigned shifts[] = { 5, 10, 10, 10 };
1033 int shift; 1113 int shift;
1034 1114
1115 if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0)
1116 return;
1117
1035 shift = shifts[plane]; 1118 shift = shifts[plane];
1036 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); 1119 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1037} 1120}
@@ -1045,10 +1128,10 @@ static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
1045 dispc_write_reg(DISPC_SIZE_MGR(channel), val); 1128 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1046} 1129}
1047 1130
1048static void dispc_read_plane_fifo_sizes(void) 1131static void dispc_init_fifos(void)
1049{ 1132{
1050 u32 size; 1133 u32 size;
1051 int plane; 1134 int fifo;
1052 u8 start, end; 1135 u8 start, end;
1053 u32 unit; 1136 u32 unit;
1054 1137
@@ -1056,16 +1139,53 @@ static void dispc_read_plane_fifo_sizes(void)
1056 1139
1057 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); 1140 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1058 1141
1059 for (plane = 0; plane < dss_feat_get_num_ovls(); ++plane) { 1142 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1060 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end); 1143 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end);
1061 size *= unit; 1144 size *= unit;
1062 dispc.fifo_size[plane] = size; 1145 dispc.fifo_size[fifo] = size;
1146
1147 /*
1148 * By default fifos are mapped directly to overlays, fifo 0 to
1149 * ovl 0, fifo 1 to ovl 1, etc.
1150 */
1151 dispc.fifo_assignment[fifo] = fifo;
1152 }
1153
1154 /*
1155 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
1156 * causes problems with certain use cases, like using the tiler in 2D
1157 * mode. The below hack swaps the fifos of GFX and WB planes, thus
1158 * giving GFX plane a larger fifo. WB but should work fine with a
1159 * smaller fifo.
1160 */
1161 if (dispc.feat->gfx_fifo_workaround) {
1162 u32 v;
1163
1164 v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
1165
1166 v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
1167 v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
1168 v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
1169 v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
1170
1171 dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
1172
1173 dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1174 dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1063 } 1175 }
1064} 1176}
1065 1177
1066static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) 1178static u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1067{ 1179{
1068 return dispc.fifo_size[plane]; 1180 int fifo;
1181 u32 size = 0;
1182
1183 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1184 if (dispc.fifo_assignment[fifo] == plane)
1185 size += dispc.fifo_size[fifo];
1186 }
1187
1188 return size;
1069} 1189}
1070 1190
1071void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) 1191void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
@@ -1141,6 +1261,14 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1141 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { 1261 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1142 *fifo_low = ovl_fifo_size - burst_size * 2; 1262 *fifo_low = ovl_fifo_size - burst_size * 2;
1143 *fifo_high = total_fifo_size - burst_size; 1263 *fifo_high = total_fifo_size - burst_size;
1264 } else if (plane == OMAP_DSS_WB) {
1265 /*
1266 * Most optimal configuration for writeback is to push out data
1267 * to the interconnect the moment writeback pushes enough pixels
1268 * in the FIFO to form a burst
1269 */
1270 *fifo_low = 0;
1271 *fifo_high = burst_size;
1144 } else { 1272 } else {
1145 *fifo_low = ovl_fifo_size - burst_size; 1273 *fifo_low = ovl_fifo_size - burst_size;
1146 *fifo_high = total_fifo_size - buf_unit; 1274 *fifo_high = total_fifo_size - buf_unit;
@@ -1383,6 +1511,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1383{ 1511{
1384 int scale_x = out_width != orig_width; 1512 int scale_x = out_width != orig_width;
1385 int scale_y = out_height != orig_height; 1513 int scale_y = out_height != orig_height;
1514 bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
1386 1515
1387 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) 1516 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1388 return; 1517 return;
@@ -1390,7 +1519,8 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1390 color_mode != OMAP_DSS_COLOR_UYVY && 1519 color_mode != OMAP_DSS_COLOR_UYVY &&
1391 color_mode != OMAP_DSS_COLOR_NV12)) { 1520 color_mode != OMAP_DSS_COLOR_NV12)) {
1392 /* reset chroma resampling for RGB formats */ 1521 /* reset chroma resampling for RGB formats */
1393 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); 1522 if (plane != OMAP_DSS_WB)
1523 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1394 return; 1524 return;
1395 } 1525 }
1396 1526
@@ -1399,23 +1529,34 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1399 1529
1400 switch (color_mode) { 1530 switch (color_mode) {
1401 case OMAP_DSS_COLOR_NV12: 1531 case OMAP_DSS_COLOR_NV12:
1402 /* UV is subsampled by 2 vertically*/ 1532 if (chroma_upscale) {
1403 orig_height >>= 1; 1533 /* UV is subsampled by 2 horizontally and vertically */
1404 /* UV is subsampled by 2 horz.*/ 1534 orig_height >>= 1;
1405 orig_width >>= 1; 1535 orig_width >>= 1;
1536 } else {
1537 /* UV is downsampled by 2 horizontally and vertically */
1538 orig_height <<= 1;
1539 orig_width <<= 1;
1540 }
1541
1406 break; 1542 break;
1407 case OMAP_DSS_COLOR_YUV2: 1543 case OMAP_DSS_COLOR_YUV2:
1408 case OMAP_DSS_COLOR_UYVY: 1544 case OMAP_DSS_COLOR_UYVY:
1409 /*For YUV422 with 90/270 rotation, 1545 /* For YUV422 with 90/270 rotation, we don't upsample chroma */
1410 *we don't upsample chroma
1411 */
1412 if (rotation == OMAP_DSS_ROT_0 || 1546 if (rotation == OMAP_DSS_ROT_0 ||
1413 rotation == OMAP_DSS_ROT_180) 1547 rotation == OMAP_DSS_ROT_180) {
1414 /* UV is subsampled by 2 hrz*/ 1548 if (chroma_upscale)
1415 orig_width >>= 1; 1549 /* UV is subsampled by 2 horizontally */
1550 orig_width >>= 1;
1551 else
1552 /* UV is downsampled by 2 horizontally */
1553 orig_width <<= 1;
1554 }
1555
1416 /* must use FIR for YUV422 if rotated */ 1556 /* must use FIR for YUV422 if rotated */
1417 if (rotation != OMAP_DSS_ROT_0) 1557 if (rotation != OMAP_DSS_ROT_0)
1418 scale_x = scale_y = true; 1558 scale_x = scale_y = true;
1559
1419 break; 1560 break;
1420 default: 1561 default:
1421 BUG(); 1562 BUG();
@@ -1431,8 +1572,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1431 out_width, out_height, five_taps, 1572 out_width, out_height, five_taps,
1432 rotation, DISPC_COLOR_COMPONENT_UV); 1573 rotation, DISPC_COLOR_COMPONENT_UV);
1433 1574
1434 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 1575 if (plane != OMAP_DSS_WB)
1435 (scale_x || scale_y) ? 1 : 0, 8, 8); 1576 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1577 (scale_x || scale_y) ? 1 : 0, 8, 8);
1578
1436 /* set H scaling */ 1579 /* set H scaling */
1437 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); 1580 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1438 /* set V scaling */ 1581 /* set V scaling */
@@ -1848,22 +1991,19 @@ static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1848 * This function is used to avoid synclosts in OMAP3, because of some 1991 * This function is used to avoid synclosts in OMAP3, because of some
1849 * undocumented horizontal position and timing related limitations. 1992 * undocumented horizontal position and timing related limitations.
1850 */ 1993 */
1851static int check_horiz_timing_omap3(enum omap_channel channel, 1994static int check_horiz_timing_omap3(enum omap_plane plane,
1852 const struct omap_video_timings *t, u16 pos_x, 1995 const struct omap_video_timings *t, u16 pos_x,
1853 u16 width, u16 height, u16 out_width, u16 out_height) 1996 u16 width, u16 height, u16 out_width, u16 out_height)
1854{ 1997{
1855 int DS = DIV_ROUND_UP(height, out_height); 1998 int DS = DIV_ROUND_UP(height, out_height);
1856 unsigned long nonactive, lclk, pclk; 1999 unsigned long nonactive;
1857 static const u8 limits[3] = { 8, 10, 20 }; 2000 static const u8 limits[3] = { 8, 10, 20 };
1858 u64 val, blank; 2001 u64 val, blank;
2002 unsigned long pclk = dispc_plane_pclk_rate(plane);
2003 unsigned long lclk = dispc_plane_lclk_rate(plane);
1859 int i; 2004 int i;
1860 2005
1861 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width; 2006 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1862 pclk = dispc_mgr_pclk_rate(channel);
1863 if (dss_mgr_is_lcd(channel))
1864 lclk = dispc_mgr_lclk_rate(channel);
1865 else
1866 lclk = dispc_fclk_rate();
1867 2007
1868 i = 0; 2008 i = 0;
1869 if (out_height < height) 2009 if (out_height < height)
@@ -1900,13 +2040,14 @@ static int check_horiz_timing_omap3(enum omap_channel channel,
1900 return 0; 2040 return 0;
1901} 2041}
1902 2042
1903static unsigned long calc_core_clk_five_taps(enum omap_channel channel, 2043static unsigned long calc_core_clk_five_taps(enum omap_plane plane,
1904 const struct omap_video_timings *mgr_timings, u16 width, 2044 const struct omap_video_timings *mgr_timings, u16 width,
1905 u16 height, u16 out_width, u16 out_height, 2045 u16 height, u16 out_width, u16 out_height,
1906 enum omap_color_mode color_mode) 2046 enum omap_color_mode color_mode)
1907{ 2047{
1908 u32 core_clk = 0; 2048 u32 core_clk = 0;
1909 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 2049 u64 tmp;
2050 unsigned long pclk = dispc_plane_pclk_rate(plane);
1910 2051
1911 if (height <= out_height && width <= out_width) 2052 if (height <= out_height && width <= out_width)
1912 return (unsigned long) pclk; 2053 return (unsigned long) pclk;
@@ -1940,11 +2081,22 @@ static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
1940 return core_clk; 2081 return core_clk;
1941} 2082}
1942 2083
1943static unsigned long calc_core_clk(enum omap_channel channel, u16 width, 2084static unsigned long calc_core_clk_24xx(enum omap_plane plane, u16 width,
1944 u16 height, u16 out_width, u16 out_height) 2085 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2086{
2087 unsigned long pclk = dispc_plane_pclk_rate(plane);
2088
2089 if (height > out_height && width > out_width)
2090 return pclk * 4;
2091 else
2092 return pclk * 2;
2093}
2094
2095static unsigned long calc_core_clk_34xx(enum omap_plane plane, u16 width,
2096 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
1945{ 2097{
1946 unsigned int hf, vf; 2098 unsigned int hf, vf;
1947 unsigned long pclk = dispc_mgr_pclk_rate(channel); 2099 unsigned long pclk = dispc_plane_pclk_rate(plane);
1948 2100
1949 /* 2101 /*
1950 * FIXME how to determine the 'A' factor 2102 * FIXME how to determine the 'A' factor
@@ -1959,51 +2111,207 @@ static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
1959 hf = 2; 2111 hf = 2;
1960 else 2112 else
1961 hf = 1; 2113 hf = 1;
1962
1963 if (height > out_height) 2114 if (height > out_height)
1964 vf = 2; 2115 vf = 2;
1965 else 2116 else
1966 vf = 1; 2117 vf = 1;
1967 2118
1968 if (cpu_is_omap24xx()) { 2119 return pclk * vf * hf;
1969 if (vf > 1 && hf > 1) 2120}
1970 return pclk * 4; 2121
1971 else 2122static unsigned long calc_core_clk_44xx(enum omap_plane plane, u16 width,
1972 return pclk * 2; 2123 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
1973 } else if (cpu_is_omap34xx()) { 2124{
1974 return pclk * vf * hf; 2125 unsigned long pclk;
1975 } else { 2126
1976 if (hf > 1) 2127 /*
1977 return DIV_ROUND_UP(pclk, out_width) * width; 2128 * If the overlay/writeback is in mem to mem mode, there are no
1978 else 2129 * downscaling limitations with respect to pixel clock, return 1 as
1979 return pclk; 2130 * required core clock to represent that we have sufficient enough
2131 * core clock to do maximum downscaling
2132 */
2133 if (mem_to_mem)
2134 return 1;
2135
2136 pclk = dispc_plane_pclk_rate(plane);
2137
2138 if (width > out_width)
2139 return DIV_ROUND_UP(pclk, out_width) * width;
2140 else
2141 return pclk;
2142}
2143
2144static int dispc_ovl_calc_scaling_24xx(enum omap_plane plane,
2145 const struct omap_video_timings *mgr_timings,
2146 u16 width, u16 height, u16 out_width, u16 out_height,
2147 enum omap_color_mode color_mode, bool *five_taps,
2148 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2149 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2150{
2151 int error;
2152 u16 in_width, in_height;
2153 int min_factor = min(*decim_x, *decim_y);
2154 const int maxsinglelinewidth =
2155 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2156
2157 *five_taps = false;
2158
2159 do {
2160 in_height = DIV_ROUND_UP(height, *decim_y);
2161 in_width = DIV_ROUND_UP(width, *decim_x);
2162 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2163 in_height, out_width, out_height, mem_to_mem);
2164 error = (in_width > maxsinglelinewidth || !*core_clk ||
2165 *core_clk > dispc_core_clk_rate());
2166 if (error) {
2167 if (*decim_x == *decim_y) {
2168 *decim_x = min_factor;
2169 ++*decim_y;
2170 } else {
2171 swap(*decim_x, *decim_y);
2172 if (*decim_x < *decim_y)
2173 ++*decim_x;
2174 }
2175 }
2176 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2177
2178 if (in_width > maxsinglelinewidth) {
2179 DSSERR("Cannot scale max input width exceeded");
2180 return -EINVAL;
1980 } 2181 }
2182 return 0;
1981} 2183}
1982 2184
1983static int dispc_ovl_calc_scaling(enum omap_plane plane, 2185static int dispc_ovl_calc_scaling_34xx(enum omap_plane plane,
1984 enum omap_channel channel,
1985 const struct omap_video_timings *mgr_timings, 2186 const struct omap_video_timings *mgr_timings,
1986 u16 width, u16 height, u16 out_width, u16 out_height, 2187 u16 width, u16 height, u16 out_width, u16 out_height,
1987 enum omap_color_mode color_mode, bool *five_taps, 2188 enum omap_color_mode color_mode, bool *five_taps,
1988 int *x_predecim, int *y_predecim, u16 pos_x) 2189 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2190 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
1989{ 2191{
1990 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 2192 int error;
1991 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 2193 u16 in_width, in_height;
2194 int min_factor = min(*decim_x, *decim_y);
2195 const int maxsinglelinewidth =
2196 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2197
2198 do {
2199 in_height = DIV_ROUND_UP(height, *decim_y);
2200 in_width = DIV_ROUND_UP(width, *decim_x);
2201 *core_clk = calc_core_clk_five_taps(plane, mgr_timings,
2202 in_width, in_height, out_width, out_height, color_mode);
2203
2204 error = check_horiz_timing_omap3(plane, mgr_timings,
2205 pos_x, in_width, in_height, out_width,
2206 out_height);
2207
2208 if (in_width > maxsinglelinewidth)
2209 if (in_height > out_height &&
2210 in_height < out_height * 2)
2211 *five_taps = false;
2212 if (!*five_taps)
2213 *core_clk = dispc.feat->calc_core_clk(plane, in_width,
2214 in_height, out_width, out_height,
2215 mem_to_mem);
2216
2217 error = (error || in_width > maxsinglelinewidth * 2 ||
2218 (in_width > maxsinglelinewidth && *five_taps) ||
2219 !*core_clk || *core_clk > dispc_core_clk_rate());
2220 if (error) {
2221 if (*decim_x == *decim_y) {
2222 *decim_x = min_factor;
2223 ++*decim_y;
2224 } else {
2225 swap(*decim_x, *decim_y);
2226 if (*decim_x < *decim_y)
2227 ++*decim_x;
2228 }
2229 }
2230 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2231
2232 if (check_horiz_timing_omap3(plane, mgr_timings, pos_x, width, height,
2233 out_width, out_height)){
2234 DSSERR("horizontal timing too tight\n");
2235 return -EINVAL;
2236 }
2237
2238 if (in_width > (maxsinglelinewidth * 2)) {
2239 DSSERR("Cannot setup scaling");
2240 DSSERR("width exceeds maximum width possible");
2241 return -EINVAL;
2242 }
2243
2244 if (in_width > maxsinglelinewidth && *five_taps) {
2245 DSSERR("cannot setup scaling with five taps");
2246 return -EINVAL;
2247 }
2248 return 0;
2249}
2250
2251static int dispc_ovl_calc_scaling_44xx(enum omap_plane plane,
2252 const struct omap_video_timings *mgr_timings,
2253 u16 width, u16 height, u16 out_width, u16 out_height,
2254 enum omap_color_mode color_mode, bool *five_taps,
2255 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2256 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2257{
2258 u16 in_width, in_width_max;
2259 int decim_x_min = *decim_x;
2260 u16 in_height = DIV_ROUND_UP(height, *decim_y);
1992 const int maxsinglelinewidth = 2261 const int maxsinglelinewidth =
1993 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 2262 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2263 unsigned long pclk = dispc_plane_pclk_rate(plane);
2264 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2265
2266 if (mem_to_mem)
2267 in_width_max = DIV_ROUND_UP(out_width, maxdownscale);
2268 else
2269 in_width_max = dispc_core_clk_rate() /
2270 DIV_ROUND_UP(pclk, out_width);
2271
2272 *decim_x = DIV_ROUND_UP(width, in_width_max);
2273
2274 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
2275 if (*decim_x > *x_predecim)
2276 return -EINVAL;
2277
2278 do {
2279 in_width = DIV_ROUND_UP(width, *decim_x);
2280 } while (*decim_x <= *x_predecim &&
2281 in_width > maxsinglelinewidth && ++*decim_x);
2282
2283 if (in_width > maxsinglelinewidth) {
2284 DSSERR("Cannot scale width exceeds max line width");
2285 return -EINVAL;
2286 }
2287
2288 *core_clk = dispc.feat->calc_core_clk(plane, in_width, in_height,
2289 out_width, out_height, mem_to_mem);
2290 return 0;
2291}
2292
2293static int dispc_ovl_calc_scaling(enum omap_plane plane,
2294 enum omap_overlay_caps caps,
2295 const struct omap_video_timings *mgr_timings,
2296 u16 width, u16 height, u16 out_width, u16 out_height,
2297 enum omap_color_mode color_mode, bool *five_taps,
2298 int *x_predecim, int *y_predecim, u16 pos_x,
2299 enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
2300{
2301 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1994 const int max_decim_limit = 16; 2302 const int max_decim_limit = 16;
1995 unsigned long core_clk = 0; 2303 unsigned long core_clk = 0;
1996 int decim_x, decim_y, error, min_factor; 2304 int decim_x, decim_y, ret;
1997 u16 in_width, in_height, in_width_max = 0;
1998 2305
1999 if (width == out_width && height == out_height) 2306 if (width == out_width && height == out_height)
2000 return 0; 2307 return 0;
2001 2308
2002 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 2309 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2003 return -EINVAL; 2310 return -EINVAL;
2004 2311
2005 *x_predecim = max_decim_limit; 2312 *x_predecim = max_decim_limit;
2006 *y_predecim = max_decim_limit; 2313 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
2314 dss_has_feature(FEAT_BURST_2D)) ? 2 : max_decim_limit;
2007 2315
2008 if (color_mode == OMAP_DSS_COLOR_CLUT1 || 2316 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
2009 color_mode == OMAP_DSS_COLOR_CLUT2 || 2317 color_mode == OMAP_DSS_COLOR_CLUT2 ||
@@ -2018,118 +2326,18 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2018 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); 2326 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
2019 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); 2327 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
2020 2328
2021 min_factor = min(decim_x, decim_y);
2022
2023 if (decim_x > *x_predecim || out_width > width * 8) 2329 if (decim_x > *x_predecim || out_width > width * 8)
2024 return -EINVAL; 2330 return -EINVAL;
2025 2331
2026 if (decim_y > *y_predecim || out_height > height * 8) 2332 if (decim_y > *y_predecim || out_height > height * 8)
2027 return -EINVAL; 2333 return -EINVAL;
2028 2334
2029 if (cpu_is_omap24xx()) { 2335 ret = dispc.feat->calc_scaling(plane, mgr_timings, width, height,
2030 *five_taps = false; 2336 out_width, out_height, color_mode, five_taps,
2031 2337 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2032 do { 2338 mem_to_mem);
2033 in_height = DIV_ROUND_UP(height, decim_y); 2339 if (ret)
2034 in_width = DIV_ROUND_UP(width, decim_x); 2340 return ret;
2035 core_clk = calc_core_clk(channel, in_width, in_height,
2036 out_width, out_height);
2037 error = (in_width > maxsinglelinewidth || !core_clk ||
2038 core_clk > dispc_core_clk_rate());
2039 if (error) {
2040 if (decim_x == decim_y) {
2041 decim_x = min_factor;
2042 decim_y++;
2043 } else {
2044 swap(decim_x, decim_y);
2045 if (decim_x < decim_y)
2046 decim_x++;
2047 }
2048 }
2049 } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
2050 error);
2051
2052 if (in_width > maxsinglelinewidth) {
2053 DSSERR("Cannot scale max input width exceeded");
2054 return -EINVAL;
2055 }
2056 } else if (cpu_is_omap34xx()) {
2057
2058 do {
2059 in_height = DIV_ROUND_UP(height, decim_y);
2060 in_width = DIV_ROUND_UP(width, decim_x);
2061 core_clk = calc_core_clk_five_taps(channel, mgr_timings,
2062 in_width, in_height, out_width, out_height,
2063 color_mode);
2064
2065 error = check_horiz_timing_omap3(channel, mgr_timings,
2066 pos_x, in_width, in_height, out_width,
2067 out_height);
2068
2069 if (in_width > maxsinglelinewidth)
2070 if (in_height > out_height &&
2071 in_height < out_height * 2)
2072 *five_taps = false;
2073 if (!*five_taps)
2074 core_clk = calc_core_clk(channel, in_width,
2075 in_height, out_width, out_height);
2076 error = (error || in_width > maxsinglelinewidth * 2 ||
2077 (in_width > maxsinglelinewidth && *five_taps) ||
2078 !core_clk || core_clk > dispc_core_clk_rate());
2079 if (error) {
2080 if (decim_x == decim_y) {
2081 decim_x = min_factor;
2082 decim_y++;
2083 } else {
2084 swap(decim_x, decim_y);
2085 if (decim_x < decim_y)
2086 decim_x++;
2087 }
2088 }
2089 } while (decim_x <= *x_predecim && decim_y <= *y_predecim
2090 && error);
2091
2092 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
2093 height, out_width, out_height)){
2094 DSSERR("horizontal timing too tight\n");
2095 return -EINVAL;
2096 }
2097
2098 if (in_width > (maxsinglelinewidth * 2)) {
2099 DSSERR("Cannot setup scaling");
2100 DSSERR("width exceeds maximum width possible");
2101 return -EINVAL;
2102 }
2103
2104 if (in_width > maxsinglelinewidth && *five_taps) {
2105 DSSERR("cannot setup scaling with five taps");
2106 return -EINVAL;
2107 }
2108 } else {
2109 int decim_x_min = decim_x;
2110 in_height = DIV_ROUND_UP(height, decim_y);
2111 in_width_max = dispc_core_clk_rate() /
2112 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
2113 out_width);
2114 decim_x = DIV_ROUND_UP(width, in_width_max);
2115
2116 decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
2117 if (decim_x > *x_predecim)
2118 return -EINVAL;
2119
2120 do {
2121 in_width = DIV_ROUND_UP(width, decim_x);
2122 } while (decim_x <= *x_predecim &&
2123 in_width > maxsinglelinewidth && decim_x++);
2124
2125 if (in_width > maxsinglelinewidth) {
2126 DSSERR("Cannot scale width exceeds max line width");
2127 return -EINVAL;
2128 }
2129
2130 core_clk = calc_core_clk(channel, in_width, in_height,
2131 out_width, out_height);
2132 }
2133 2341
2134 DSSDBG("required core clk rate = %lu Hz\n", core_clk); 2342 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2135 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate()); 2343 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
@@ -2147,69 +2355,64 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
2147 return 0; 2355 return 0;
2148} 2356}
2149 2357
2150int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 2358static int dispc_ovl_setup_common(enum omap_plane plane,
2151 bool replication, const struct omap_video_timings *mgr_timings) 2359 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2360 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2361 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2362 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2363 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2364 bool replication, const struct omap_video_timings *mgr_timings,
2365 bool mem_to_mem)
2152{ 2366{
2153 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2154 bool five_taps = true; 2367 bool five_taps = true;
2155 bool fieldmode = 0; 2368 bool fieldmode = 0;
2156 int r, cconv = 0; 2369 int r, cconv = 0;
2157 unsigned offset0, offset1; 2370 unsigned offset0, offset1;
2158 s32 row_inc; 2371 s32 row_inc;
2159 s32 pix_inc; 2372 s32 pix_inc;
2160 u16 frame_height = oi->height; 2373 u16 frame_height = height;
2161 unsigned int field_offset = 0; 2374 unsigned int field_offset = 0;
2162 u16 in_height = oi->height; 2375 u16 in_height = height;
2163 u16 in_width = oi->width; 2376 u16 in_width = width;
2164 u16 out_width, out_height;
2165 enum omap_channel channel;
2166 int x_predecim = 1, y_predecim = 1; 2377 int x_predecim = 1, y_predecim = 1;
2167 bool ilace = mgr_timings->interlace; 2378 bool ilace = mgr_timings->interlace;
2168 2379
2169 channel = dispc_ovl_get_channel_out(plane); 2380 if (paddr == 0)
2170
2171 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2172 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
2173 plane, oi->paddr, oi->p_uv_addr,
2174 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2175 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2176 oi->mirror, ilace, channel, replication);
2177
2178 if (oi->paddr == 0)
2179 return -EINVAL; 2381 return -EINVAL;
2180 2382
2181 out_width = oi->out_width == 0 ? oi->width : oi->out_width; 2383 out_width = out_width == 0 ? width : out_width;
2182 out_height = oi->out_height == 0 ? oi->height : oi->out_height; 2384 out_height = out_height == 0 ? height : out_height;
2183 2385
2184 if (ilace && oi->height == out_height) 2386 if (ilace && height == out_height)
2185 fieldmode = 1; 2387 fieldmode = 1;
2186 2388
2187 if (ilace) { 2389 if (ilace) {
2188 if (fieldmode) 2390 if (fieldmode)
2189 in_height /= 2; 2391 in_height /= 2;
2190 oi->pos_y /= 2; 2392 pos_y /= 2;
2191 out_height /= 2; 2393 out_height /= 2;
2192 2394
2193 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 2395 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
2194 "out_height %d\n", 2396 "out_height %d\n", in_height, pos_y,
2195 in_height, oi->pos_y, out_height); 2397 out_height);
2196 } 2398 }
2197 2399
2198 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 2400 if (!dss_feat_color_mode_supported(plane, color_mode))
2199 return -EINVAL; 2401 return -EINVAL;
2200 2402
2201 r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width, 2403 r = dispc_ovl_calc_scaling(plane, caps, mgr_timings, in_width,
2202 in_height, out_width, out_height, oi->color_mode, 2404 in_height, out_width, out_height, color_mode,
2203 &five_taps, &x_predecim, &y_predecim, oi->pos_x); 2405 &five_taps, &x_predecim, &y_predecim, pos_x,
2406 rotation_type, mem_to_mem);
2204 if (r) 2407 if (r)
2205 return r; 2408 return r;
2206 2409
2207 in_width = DIV_ROUND_UP(in_width, x_predecim); 2410 in_width = DIV_ROUND_UP(in_width, x_predecim);
2208 in_height = DIV_ROUND_UP(in_height, y_predecim); 2411 in_height = DIV_ROUND_UP(in_height, y_predecim);
2209 2412
2210 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 2413 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2211 oi->color_mode == OMAP_DSS_COLOR_UYVY || 2414 color_mode == OMAP_DSS_COLOR_UYVY ||
2212 oi->color_mode == OMAP_DSS_COLOR_NV12) 2415 color_mode == OMAP_DSS_COLOR_NV12)
2213 cconv = 1; 2416 cconv = 1;
2214 2417
2215 if (ilace && !fieldmode) { 2418 if (ilace && !fieldmode) {
@@ -2235,70 +2438,144 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
2235 row_inc = 0; 2438 row_inc = 0;
2236 pix_inc = 0; 2439 pix_inc = 0;
2237 2440
2238 if (oi->rotation_type == OMAP_DSS_ROT_TILER) 2441 if (rotation_type == OMAP_DSS_ROT_TILER)
2239 calc_tiler_rotation_offset(oi->screen_width, in_width, 2442 calc_tiler_rotation_offset(screen_width, in_width,
2240 oi->color_mode, fieldmode, field_offset, 2443 color_mode, fieldmode, field_offset,
2241 &offset0, &offset1, &row_inc, &pix_inc, 2444 &offset0, &offset1, &row_inc, &pix_inc,
2242 x_predecim, y_predecim); 2445 x_predecim, y_predecim);
2243 else if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2446 else if (rotation_type == OMAP_DSS_ROT_DMA)
2244 calc_dma_rotation_offset(oi->rotation, oi->mirror, 2447 calc_dma_rotation_offset(rotation, mirror,
2245 oi->screen_width, in_width, frame_height, 2448 screen_width, in_width, frame_height,
2246 oi->color_mode, fieldmode, field_offset, 2449 color_mode, fieldmode, field_offset,
2247 &offset0, &offset1, &row_inc, &pix_inc, 2450 &offset0, &offset1, &row_inc, &pix_inc,
2248 x_predecim, y_predecim); 2451 x_predecim, y_predecim);
2249 else 2452 else
2250 calc_vrfb_rotation_offset(oi->rotation, oi->mirror, 2453 calc_vrfb_rotation_offset(rotation, mirror,
2251 oi->screen_width, in_width, frame_height, 2454 screen_width, in_width, frame_height,
2252 oi->color_mode, fieldmode, field_offset, 2455 color_mode, fieldmode, field_offset,
2253 &offset0, &offset1, &row_inc, &pix_inc, 2456 &offset0, &offset1, &row_inc, &pix_inc,
2254 x_predecim, y_predecim); 2457 x_predecim, y_predecim);
2255 2458
2256 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 2459 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
2257 offset0, offset1, row_inc, pix_inc); 2460 offset0, offset1, row_inc, pix_inc);
2258 2461
2259 dispc_ovl_set_color_mode(plane, oi->color_mode); 2462 dispc_ovl_set_color_mode(plane, color_mode);
2260 2463
2261 dispc_ovl_configure_burst_type(plane, oi->rotation_type); 2464 dispc_ovl_configure_burst_type(plane, rotation_type);
2262 2465
2263 dispc_ovl_set_ba0(plane, oi->paddr + offset0); 2466 dispc_ovl_set_ba0(plane, paddr + offset0);
2264 dispc_ovl_set_ba1(plane, oi->paddr + offset1); 2467 dispc_ovl_set_ba1(plane, paddr + offset1);
2265 2468
2266 if (OMAP_DSS_COLOR_NV12 == oi->color_mode) { 2469 if (OMAP_DSS_COLOR_NV12 == color_mode) {
2267 dispc_ovl_set_ba0_uv(plane, oi->p_uv_addr + offset0); 2470 dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0);
2268 dispc_ovl_set_ba1_uv(plane, oi->p_uv_addr + offset1); 2471 dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1);
2269 } 2472 }
2270 2473
2271
2272 dispc_ovl_set_row_inc(plane, row_inc); 2474 dispc_ovl_set_row_inc(plane, row_inc);
2273 dispc_ovl_set_pix_inc(plane, pix_inc); 2475 dispc_ovl_set_pix_inc(plane, pix_inc);
2274 2476
2275 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width, 2477 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width,
2276 in_height, out_width, out_height); 2478 in_height, out_width, out_height);
2277 2479
2278 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 2480 dispc_ovl_set_pos(plane, caps, pos_x, pos_y);
2279 2481
2280 dispc_ovl_set_pic_size(plane, in_width, in_height); 2482 dispc_ovl_set_input_size(plane, in_width, in_height);
2281 2483
2282 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 2484 if (caps & OMAP_DSS_OVL_CAP_SCALE) {
2283 dispc_ovl_set_scaling(plane, in_width, in_height, out_width, 2485 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
2284 out_height, ilace, five_taps, fieldmode, 2486 out_height, ilace, five_taps, fieldmode,
2285 oi->color_mode, oi->rotation); 2487 color_mode, rotation);
2286 dispc_ovl_set_vid_size(plane, out_width, out_height); 2488 dispc_ovl_set_output_size(plane, out_width, out_height);
2287 dispc_ovl_set_vid_color_conv(plane, cconv); 2489 dispc_ovl_set_vid_color_conv(plane, cconv);
2288 } 2490 }
2289 2491
2290 dispc_ovl_set_rotation_attrs(plane, oi->rotation, oi->mirror, 2492 dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode);
2291 oi->color_mode);
2292 2493
2293 dispc_ovl_set_zorder(plane, oi->zorder); 2494 dispc_ovl_set_zorder(plane, caps, zorder);
2294 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); 2495 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
2295 dispc_ovl_setup_global_alpha(plane, oi->global_alpha); 2496 dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
2296 2497
2297 dispc_ovl_enable_replication(plane, replication); 2498 dispc_ovl_enable_replication(plane, caps, replication);
2298 2499
2299 return 0; 2500 return 0;
2300} 2501}
2301 2502
2503int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2504 bool replication, const struct omap_video_timings *mgr_timings,
2505 bool mem_to_mem)
2506{
2507 int r;
2508 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
2509 enum omap_channel channel;
2510
2511 channel = dispc_ovl_get_channel_out(plane);
2512
2513 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
2514 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
2515 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
2516 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2517 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2518
2519 r = dispc_ovl_setup_common(plane, ovl->caps, oi->paddr, oi->p_uv_addr,
2520 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
2521 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
2522 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
2523 oi->rotation_type, replication, mgr_timings, mem_to_mem);
2524
2525 return r;
2526}
2527
2528int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
2529 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
2530{
2531 int r;
2532 u32 l;
2533 enum omap_plane plane = OMAP_DSS_WB;
2534 const int pos_x = 0, pos_y = 0;
2535 const u8 zorder = 0, global_alpha = 0;
2536 const bool replication = false;
2537 bool truncation;
2538 int in_width = mgr_timings->x_res;
2539 int in_height = mgr_timings->y_res;
2540 enum omap_overlay_caps caps =
2541 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
2542
2543 DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
2544 "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
2545 in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
2546 wi->mirror);
2547
2548 r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
2549 wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
2550 wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
2551 wi->pre_mult_alpha, global_alpha, wi->rotation_type,
2552 replication, mgr_timings, mem_to_mem);
2553
2554 switch (wi->color_mode) {
2555 case OMAP_DSS_COLOR_RGB16:
2556 case OMAP_DSS_COLOR_RGB24P:
2557 case OMAP_DSS_COLOR_ARGB16:
2558 case OMAP_DSS_COLOR_RGBA16:
2559 case OMAP_DSS_COLOR_RGB12U:
2560 case OMAP_DSS_COLOR_ARGB16_1555:
2561 case OMAP_DSS_COLOR_XRGB16_1555:
2562 case OMAP_DSS_COLOR_RGBX16:
2563 truncation = true;
2564 break;
2565 default:
2566 truncation = false;
2567 break;
2568 }
2569
2570 /* setup extra DISPC_WB_ATTRIBUTES */
2571 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
2572 l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */
2573 l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */
2574 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l);
2575
2576 return r;
2577}
2578
2302int dispc_ovl_enable(enum omap_plane plane, bool enable) 2579int dispc_ovl_enable(enum omap_plane plane, bool enable)
2303{ 2580{
2304 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 2581 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
@@ -2451,6 +2728,47 @@ void dispc_mgr_enable(enum omap_channel channel, bool enable)
2451 BUG(); 2728 BUG();
2452} 2729}
2453 2730
2731void dispc_wb_enable(bool enable)
2732{
2733 enum omap_plane plane = OMAP_DSS_WB;
2734 struct completion frame_done_completion;
2735 bool is_on;
2736 int r;
2737 u32 irq;
2738
2739 is_on = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2740 irq = DISPC_IRQ_FRAMEDONEWB;
2741
2742 if (!enable && is_on) {
2743 init_completion(&frame_done_completion);
2744
2745 r = omap_dispc_register_isr(dispc_disable_isr,
2746 &frame_done_completion, irq);
2747 if (r)
2748 DSSERR("failed to register FRAMEDONEWB isr\n");
2749 }
2750
2751 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2752
2753 if (!enable && is_on) {
2754 if (!wait_for_completion_timeout(&frame_done_completion,
2755 msecs_to_jiffies(100)))
2756 DSSERR("timeout waiting for FRAMEDONEWB\n");
2757
2758 r = omap_dispc_unregister_isr(dispc_disable_isr,
2759 &frame_done_completion, irq);
2760 if (r)
2761 DSSERR("failed to unregister FRAMEDONEWB isr\n");
2762 }
2763}
2764
2765bool dispc_wb_is_enabled(void)
2766{
2767 enum omap_plane plane = OMAP_DSS_WB;
2768
2769 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0);
2770}
2771
2454void dispc_lcd_enable_signal_polarity(bool act_high) 2772void dispc_lcd_enable_signal_polarity(bool act_high)
2455{ 2773{
2456 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2774 if (!dss_has_feature(FEAT_LCDENABLEPOL))
@@ -2605,24 +2923,13 @@ static bool _dispc_mgr_size_ok(u16 width, u16 height)
2605static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2923static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2606 int vsw, int vfp, int vbp) 2924 int vsw, int vfp, int vbp)
2607{ 2925{
2608 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2926 if (hsw < 1 || hsw > dispc.feat->sw_max ||
2609 if (hsw < 1 || hsw > 64 || 2927 hfp < 1 || hfp > dispc.feat->hp_max ||
2610 hfp < 1 || hfp > 256 || 2928 hbp < 1 || hbp > dispc.feat->hp_max ||
2611 hbp < 1 || hbp > 256 || 2929 vsw < 1 || vsw > dispc.feat->sw_max ||
2612 vsw < 1 || vsw > 64 || 2930 vfp < 0 || vfp > dispc.feat->vp_max ||
2613 vfp < 0 || vfp > 255 || 2931 vbp < 0 || vbp > dispc.feat->vp_max)
2614 vbp < 0 || vbp > 255) 2932 return false;
2615 return false;
2616 } else {
2617 if (hsw < 1 || hsw > 256 ||
2618 hfp < 1 || hfp > 4096 ||
2619 hbp < 1 || hbp > 4096 ||
2620 vsw < 1 || vsw > 256 ||
2621 vfp < 0 || vfp > 4095 ||
2622 vbp < 0 || vbp > 4095)
2623 return false;
2624 }
2625
2626 return true; 2933 return true;
2627} 2934}
2628 2935
@@ -2654,19 +2961,12 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2654 u32 timing_h, timing_v, l; 2961 u32 timing_h, timing_v, l;
2655 bool onoff, rf, ipc; 2962 bool onoff, rf, ipc;
2656 2963
2657 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2964 timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
2658 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | 2965 FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
2659 FLD_VAL(hbp-1, 27, 20); 2966 FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
2660 2967 timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
2661 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | 2968 FLD_VAL(vfp, dispc.feat->fp_start, 8) |
2662 FLD_VAL(vbp, 27, 20); 2969 FLD_VAL(vbp, dispc.feat->bp_start, 20);
2663 } else {
2664 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2665 FLD_VAL(hbp-1, 31, 20);
2666
2667 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2668 FLD_VAL(vbp, 31, 20);
2669 }
2670 2970
2671 dispc_write_reg(DISPC_TIMING_H(channel), timing_h); 2971 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2672 dispc_write_reg(DISPC_TIMING_V(channel), timing_v); 2972 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
@@ -2872,6 +3172,23 @@ unsigned long dispc_core_clk_rate(void)
2872 return fclk / lcd; 3172 return fclk / lcd;
2873} 3173}
2874 3174
3175static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3176{
3177 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3178
3179 return dispc_mgr_pclk_rate(channel);
3180}
3181
3182static unsigned long dispc_plane_lclk_rate(enum omap_plane plane)
3183{
3184 enum omap_channel channel = dispc_ovl_get_channel_out(plane);
3185
3186 if (dss_mgr_is_lcd(channel))
3187 return dispc_mgr_lclk_rate(channel);
3188 else
3189 return dispc_fclk_rate();
3190
3191}
2875static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) 3192static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
2876{ 3193{
2877 int lcd, pcd; 3194 int lcd, pcd;
@@ -3492,7 +3809,7 @@ static void dispc_error_worker(struct work_struct *work)
3492 ovl->name); 3809 ovl->name);
3493 dispc_ovl_enable(ovl->id, false); 3810 dispc_ovl_enable(ovl->id, false);
3494 dispc_mgr_go(ovl->manager->id); 3811 dispc_mgr_go(ovl->manager->id);
3495 mdelay(50); 3812 msleep(50);
3496 } 3813 }
3497 } 3814 }
3498 3815
@@ -3504,7 +3821,7 @@ static void dispc_error_worker(struct work_struct *work)
3504 bit = mgr_desc[i].sync_lost_irq; 3821 bit = mgr_desc[i].sync_lost_irq;
3505 3822
3506 if (bit & errors) { 3823 if (bit & errors) {
3507 struct omap_dss_device *dssdev = mgr->device; 3824 struct omap_dss_device *dssdev = mgr->get_device(mgr);
3508 bool enable; 3825 bool enable;
3509 3826
3510 DSSERR("SYNC_LOST on channel %s, restarting the output " 3827 DSSERR("SYNC_LOST on channel %s, restarting the output "
@@ -3524,7 +3841,7 @@ static void dispc_error_worker(struct work_struct *work)
3524 } 3841 }
3525 3842
3526 dispc_mgr_go(mgr->id); 3843 dispc_mgr_go(mgr->id);
3527 mdelay(50); 3844 msleep(50);
3528 3845
3529 if (enable) 3846 if (enable)
3530 dssdev->driver->enable(dssdev); 3847 dssdev->driver->enable(dssdev);
@@ -3535,9 +3852,13 @@ static void dispc_error_worker(struct work_struct *work)
3535 DSSERR("OCP_ERR\n"); 3852 DSSERR("OCP_ERR\n");
3536 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3853 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3537 struct omap_overlay_manager *mgr; 3854 struct omap_overlay_manager *mgr;
3855 struct omap_dss_device *dssdev;
3856
3538 mgr = omap_dss_get_overlay_manager(i); 3857 mgr = omap_dss_get_overlay_manager(i);
3539 if (mgr->device && mgr->device->driver) 3858 dssdev = mgr->get_device(mgr);
3540 mgr->device->driver->disable(mgr->device); 3859
3860 if (dssdev && dssdev->driver)
3861 dssdev->driver->disable(dssdev);
3541 } 3862 }
3542 } 3863 }
3543 3864
@@ -3661,17 +3982,98 @@ static void _omap_dispc_initial_config(void)
3661 if (dss_has_feature(FEAT_FUNCGATED)) 3982 if (dss_has_feature(FEAT_FUNCGATED))
3662 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3983 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3663 3984
3664 _dispc_setup_color_conv_coef(); 3985 dispc_setup_color_conv_coef();
3665 3986
3666 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); 3987 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3667 3988
3668 dispc_read_plane_fifo_sizes(); 3989 dispc_init_fifos();
3669 3990
3670 dispc_configure_burst_sizes(); 3991 dispc_configure_burst_sizes();
3671 3992
3672 dispc_ovl_enable_zorder_planes(); 3993 dispc_ovl_enable_zorder_planes();
3673} 3994}
3674 3995
3996static const struct dispc_features omap24xx_dispc_feats __initconst = {
3997 .sw_start = 5,
3998 .fp_start = 15,
3999 .bp_start = 27,
4000 .sw_max = 64,
4001 .vp_max = 255,
4002 .hp_max = 256,
4003 .calc_scaling = dispc_ovl_calc_scaling_24xx,
4004 .calc_core_clk = calc_core_clk_24xx,
4005 .num_fifos = 3,
4006};
4007
4008static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = {
4009 .sw_start = 5,
4010 .fp_start = 15,
4011 .bp_start = 27,
4012 .sw_max = 64,
4013 .vp_max = 255,
4014 .hp_max = 256,
4015 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4016 .calc_core_clk = calc_core_clk_34xx,
4017 .num_fifos = 3,
4018};
4019
4020static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = {
4021 .sw_start = 7,
4022 .fp_start = 19,
4023 .bp_start = 31,
4024 .sw_max = 256,
4025 .vp_max = 4095,
4026 .hp_max = 4096,
4027 .calc_scaling = dispc_ovl_calc_scaling_34xx,
4028 .calc_core_clk = calc_core_clk_34xx,
4029 .num_fifos = 3,
4030};
4031
4032static const struct dispc_features omap44xx_dispc_feats __initconst = {
4033 .sw_start = 7,
4034 .fp_start = 19,
4035 .bp_start = 31,
4036 .sw_max = 256,
4037 .vp_max = 4095,
4038 .hp_max = 4096,
4039 .calc_scaling = dispc_ovl_calc_scaling_44xx,
4040 .calc_core_clk = calc_core_clk_44xx,
4041 .num_fifos = 5,
4042 .gfx_fifo_workaround = true,
4043};
4044
4045static int __init dispc_init_features(struct device *dev)
4046{
4047 const struct dispc_features *src;
4048 struct dispc_features *dst;
4049
4050 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
4051 if (!dst) {
4052 dev_err(dev, "Failed to allocate DISPC Features\n");
4053 return -ENOMEM;
4054 }
4055
4056 if (cpu_is_omap24xx()) {
4057 src = &omap24xx_dispc_feats;
4058 } else if (cpu_is_omap34xx()) {
4059 if (omap_rev() < OMAP3430_REV_ES3_0)
4060 src = &omap34xx_rev1_0_dispc_feats;
4061 else
4062 src = &omap34xx_rev3_0_dispc_feats;
4063 } else if (cpu_is_omap44xx()) {
4064 src = &omap44xx_dispc_feats;
4065 } else if (soc_is_omap54xx()) {
4066 src = &omap44xx_dispc_feats;
4067 } else {
4068 return -ENODEV;
4069 }
4070
4071 memcpy(dst, src, sizeof(*dst));
4072 dispc.feat = dst;
4073
4074 return 0;
4075}
4076
3675/* DISPC HW IP initialisation */ 4077/* DISPC HW IP initialisation */
3676static int __init omap_dispchw_probe(struct platform_device *pdev) 4078static int __init omap_dispchw_probe(struct platform_device *pdev)
3677{ 4079{
@@ -3682,6 +4084,10 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3682 4084
3683 dispc.pdev = pdev; 4085 dispc.pdev = pdev;
3684 4086
4087 r = dispc_init_features(&dispc.pdev->dev);
4088 if (r)
4089 return r;
4090
3685 spin_lock_init(&dispc.irq_lock); 4091 spin_lock_init(&dispc.irq_lock);
3686 4092
3687#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 4093#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 92d8a9be86fc..222363c6e623 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -36,6 +36,7 @@
36#define DISPC_CONTROL2 0x0238 36#define DISPC_CONTROL2 0x0238
37#define DISPC_CONFIG2 0x0620 37#define DISPC_CONFIG2 0x0620
38#define DISPC_DIVISOR 0x0804 38#define DISPC_DIVISOR 0x0804
39#define DISPC_GLOBAL_BUFFER 0x0800
39#define DISPC_CONTROL3 0x0848 40#define DISPC_CONTROL3 0x0848
40#define DISPC_CONFIG3 0x084C 41#define DISPC_CONFIG3 0x084C
41 42
@@ -355,6 +356,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
355 return 0x014C; 356 return 0x014C;
356 case OMAP_DSS_VIDEO3: 357 case OMAP_DSS_VIDEO3:
357 return 0x0300; 358 return 0x0300;
359 case OMAP_DSS_WB:
360 return 0x0500;
358 default: 361 default:
359 BUG(); 362 BUG();
360 return 0; 363 return 0;
@@ -370,6 +373,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
370 case OMAP_DSS_VIDEO2: 373 case OMAP_DSS_VIDEO2:
371 return 0x0000; 374 return 0x0000;
372 case OMAP_DSS_VIDEO3: 375 case OMAP_DSS_VIDEO3:
376 case OMAP_DSS_WB:
373 return 0x0008; 377 return 0x0008;
374 default: 378 default:
375 BUG(); 379 BUG();
@@ -385,6 +389,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
385 case OMAP_DSS_VIDEO2: 389 case OMAP_DSS_VIDEO2:
386 return 0x0004; 390 return 0x0004;
387 case OMAP_DSS_VIDEO3: 391 case OMAP_DSS_VIDEO3:
392 case OMAP_DSS_WB:
388 return 0x000C; 393 return 0x000C;
389 default: 394 default:
390 BUG(); 395 BUG();
@@ -404,6 +409,8 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
404 return 0x04BC; 409 return 0x04BC;
405 case OMAP_DSS_VIDEO3: 410 case OMAP_DSS_VIDEO3:
406 return 0x0310; 411 return 0x0310;
412 case OMAP_DSS_WB:
413 return 0x0118;
407 default: 414 default:
408 BUG(); 415 BUG();
409 return 0; 416 return 0;
@@ -422,6 +429,8 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
422 return 0x04C0; 429 return 0x04C0;
423 case OMAP_DSS_VIDEO3: 430 case OMAP_DSS_VIDEO3:
424 return 0x0314; 431 return 0x0314;
432 case OMAP_DSS_WB:
433 return 0x011C;
425 default: 434 default:
426 BUG(); 435 BUG();
427 return 0; 436 return 0;
@@ -451,6 +460,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
451 case OMAP_DSS_VIDEO2: 460 case OMAP_DSS_VIDEO2:
452 return 0x000C; 461 return 0x000C;
453 case OMAP_DSS_VIDEO3: 462 case OMAP_DSS_VIDEO3:
463 case OMAP_DSS_WB:
454 return 0x00A8; 464 return 0x00A8;
455 default: 465 default:
456 BUG(); 466 BUG();
@@ -467,6 +477,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
467 case OMAP_DSS_VIDEO2: 477 case OMAP_DSS_VIDEO2:
468 return 0x0010; 478 return 0x0010;
469 case OMAP_DSS_VIDEO3: 479 case OMAP_DSS_VIDEO3:
480 case OMAP_DSS_WB:
470 return 0x0070; 481 return 0x0070;
471 default: 482 default:
472 BUG(); 483 BUG();
@@ -486,6 +497,8 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
486 return 0x04DC; 497 return 0x04DC;
487 case OMAP_DSS_VIDEO3: 498 case OMAP_DSS_VIDEO3:
488 return 0x032C; 499 return 0x032C;
500 case OMAP_DSS_WB:
501 return 0x0310;
489 default: 502 default:
490 BUG(); 503 BUG();
491 return 0; 504 return 0;
@@ -501,6 +514,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
501 case OMAP_DSS_VIDEO2: 514 case OMAP_DSS_VIDEO2:
502 return 0x0014; 515 return 0x0014;
503 case OMAP_DSS_VIDEO3: 516 case OMAP_DSS_VIDEO3:
517 case OMAP_DSS_WB:
504 return 0x008C; 518 return 0x008C;
505 default: 519 default:
506 BUG(); 520 BUG();
@@ -517,6 +531,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
517 case OMAP_DSS_VIDEO2: 531 case OMAP_DSS_VIDEO2:
518 return 0x0018; 532 return 0x0018;
519 case OMAP_DSS_VIDEO3: 533 case OMAP_DSS_VIDEO3:
534 case OMAP_DSS_WB:
520 return 0x0088; 535 return 0x0088;
521 default: 536 default:
522 BUG(); 537 BUG();
@@ -533,6 +548,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
533 case OMAP_DSS_VIDEO2: 548 case OMAP_DSS_VIDEO2:
534 return 0x001C; 549 return 0x001C;
535 case OMAP_DSS_VIDEO3: 550 case OMAP_DSS_VIDEO3:
551 case OMAP_DSS_WB:
536 return 0x00A4; 552 return 0x00A4;
537 default: 553 default:
538 BUG(); 554 BUG();
@@ -549,6 +565,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
549 case OMAP_DSS_VIDEO2: 565 case OMAP_DSS_VIDEO2:
550 return 0x0020; 566 return 0x0020;
551 case OMAP_DSS_VIDEO3: 567 case OMAP_DSS_VIDEO3:
568 case OMAP_DSS_WB:
552 return 0x0098; 569 return 0x0098;
553 default: 570 default:
554 BUG(); 571 BUG();
@@ -598,6 +615,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
598 case OMAP_DSS_VIDEO2: 615 case OMAP_DSS_VIDEO2:
599 return 0x0024; 616 return 0x0024;
600 case OMAP_DSS_VIDEO3: 617 case OMAP_DSS_VIDEO3:
618 case OMAP_DSS_WB:
601 return 0x0090; 619 return 0x0090;
602 default: 620 default:
603 BUG(); 621 BUG();
@@ -617,6 +635,8 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
617 return 0x055C; 635 return 0x055C;
618 case OMAP_DSS_VIDEO3: 636 case OMAP_DSS_VIDEO3:
619 return 0x0424; 637 return 0x0424;
638 case OMAP_DSS_WB:
639 return 0x290;
620 default: 640 default:
621 BUG(); 641 BUG();
622 return 0; 642 return 0;
@@ -633,6 +653,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
633 case OMAP_DSS_VIDEO2: 653 case OMAP_DSS_VIDEO2:
634 return 0x0028; 654 return 0x0028;
635 case OMAP_DSS_VIDEO3: 655 case OMAP_DSS_VIDEO3:
656 case OMAP_DSS_WB:
636 return 0x0094; 657 return 0x0094;
637 default: 658 default:
638 BUG(); 659 BUG();
@@ -651,6 +672,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
651 case OMAP_DSS_VIDEO2: 672 case OMAP_DSS_VIDEO2:
652 return 0x002C; 673 return 0x002C;
653 case OMAP_DSS_VIDEO3: 674 case OMAP_DSS_VIDEO3:
675 case OMAP_DSS_WB:
654 return 0x0000; 676 return 0x0000;
655 default: 677 default:
656 BUG(); 678 BUG();
@@ -670,6 +692,8 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
670 return 0x0560; 692 return 0x0560;
671 case OMAP_DSS_VIDEO3: 693 case OMAP_DSS_VIDEO3:
672 return 0x0428; 694 return 0x0428;
695 case OMAP_DSS_WB:
696 return 0x0294;
673 default: 697 default:
674 BUG(); 698 BUG();
675 return 0; 699 return 0;
@@ -686,6 +710,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
686 case OMAP_DSS_VIDEO2: 710 case OMAP_DSS_VIDEO2:
687 return 0x0030; 711 return 0x0030;
688 case OMAP_DSS_VIDEO3: 712 case OMAP_DSS_VIDEO3:
713 case OMAP_DSS_WB:
689 return 0x0004; 714 return 0x0004;
690 default: 715 default:
691 BUG(); 716 BUG();
@@ -705,6 +730,8 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
705 return 0x0564; 730 return 0x0564;
706 case OMAP_DSS_VIDEO3: 731 case OMAP_DSS_VIDEO3:
707 return 0x042C; 732 return 0x042C;
733 case OMAP_DSS_WB:
734 return 0x0298;
708 default: 735 default:
709 BUG(); 736 BUG();
710 return 0; 737 return 0;
@@ -722,6 +749,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
722 case OMAP_DSS_VIDEO2: 749 case OMAP_DSS_VIDEO2:
723 return 0x0034 + i * 0x8; 750 return 0x0034 + i * 0x8;
724 case OMAP_DSS_VIDEO3: 751 case OMAP_DSS_VIDEO3:
752 case OMAP_DSS_WB:
725 return 0x0010 + i * 0x8; 753 return 0x0010 + i * 0x8;
726 default: 754 default:
727 BUG(); 755 BUG();
@@ -742,6 +770,8 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
742 return 0x0568 + i * 0x8; 770 return 0x0568 + i * 0x8;
743 case OMAP_DSS_VIDEO3: 771 case OMAP_DSS_VIDEO3:
744 return 0x0430 + i * 0x8; 772 return 0x0430 + i * 0x8;
773 case OMAP_DSS_WB:
774 return 0x02A0 + i * 0x8;
745 default: 775 default:
746 BUG(); 776 BUG();
747 return 0; 777 return 0;
@@ -759,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
759 case OMAP_DSS_VIDEO2: 789 case OMAP_DSS_VIDEO2:
760 return 0x0038 + i * 0x8; 790 return 0x0038 + i * 0x8;
761 case OMAP_DSS_VIDEO3: 791 case OMAP_DSS_VIDEO3:
792 case OMAP_DSS_WB:
762 return 0x0014 + i * 0x8; 793 return 0x0014 + i * 0x8;
763 default: 794 default:
764 BUG(); 795 BUG();
@@ -779,6 +810,8 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
779 return 0x056C + i * 0x8; 810 return 0x056C + i * 0x8;
780 case OMAP_DSS_VIDEO3: 811 case OMAP_DSS_VIDEO3:
781 return 0x0434 + i * 0x8; 812 return 0x0434 + i * 0x8;
813 case OMAP_DSS_WB:
814 return 0x02A4 + i * 0x8;
782 default: 815 default:
783 BUG(); 816 BUG();
784 return 0; 817 return 0;
@@ -795,6 +828,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
795 case OMAP_DSS_VIDEO1: 828 case OMAP_DSS_VIDEO1:
796 case OMAP_DSS_VIDEO2: 829 case OMAP_DSS_VIDEO2:
797 case OMAP_DSS_VIDEO3: 830 case OMAP_DSS_VIDEO3:
831 case OMAP_DSS_WB:
798 return 0x0074 + i * 0x4; 832 return 0x0074 + i * 0x4;
799 default: 833 default:
800 BUG(); 834 BUG();
@@ -814,6 +848,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
814 case OMAP_DSS_VIDEO2: 848 case OMAP_DSS_VIDEO2:
815 return 0x00B4 + i * 0x4; 849 return 0x00B4 + i * 0x4;
816 case OMAP_DSS_VIDEO3: 850 case OMAP_DSS_VIDEO3:
851 case OMAP_DSS_WB:
817 return 0x0050 + i * 0x4; 852 return 0x0050 + i * 0x4;
818 default: 853 default:
819 BUG(); 854 BUG();
@@ -834,6 +869,8 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
834 return 0x05A8 + i * 0x4; 869 return 0x05A8 + i * 0x4;
835 case OMAP_DSS_VIDEO3: 870 case OMAP_DSS_VIDEO3:
836 return 0x0470 + i * 0x4; 871 return 0x0470 + i * 0x4;
872 case OMAP_DSS_WB:
873 return 0x02E0 + i * 0x4;
837 default: 874 default:
838 BUG(); 875 BUG();
839 return 0; 876 return 0;
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 5bd957e85505..ccf8550fafde 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -142,7 +142,11 @@ static ssize_t display_timings_store(struct device *dev,
142 if (r) 142 if (r)
143 return r; 143 return r;
144 144
145 dssdev->driver->disable(dssdev);
145 dssdev->driver->set_timings(dssdev, &t); 146 dssdev->driver->set_timings(dssdev, &t);
147 r = dssdev->driver->enable(dssdev);
148 if (r)
149 return r;
146 150
147 return size; 151 return size;
148} 152}
@@ -316,26 +320,117 @@ void omapdss_default_get_timings(struct omap_dss_device *dssdev,
316} 320}
317EXPORT_SYMBOL(omapdss_default_get_timings); 321EXPORT_SYMBOL(omapdss_default_get_timings);
318 322
319void dss_init_device(struct platform_device *pdev, 323/*
324 * Connect dssdev to a manager if the manager is free or if force is specified.
325 * Connect all overlays to that manager if they are free or if force is
326 * specified.
327 */
328static int dss_init_connections(struct omap_dss_device *dssdev, bool force)
329{
330 struct omap_dss_output *out;
331 struct omap_overlay_manager *mgr;
332 int i, r;
333
334 out = omapdss_get_output_from_dssdev(dssdev);
335
336 WARN_ON(dssdev->output);
337 WARN_ON(out->device);
338
339 r = omapdss_output_set_device(out, dssdev);
340 if (r) {
341 DSSERR("failed to connect output to new device\n");
342 return r;
343 }
344
345 mgr = omap_dss_get_overlay_manager(dssdev->channel);
346
347 if (mgr->output && !force)
348 return 0;
349
350 if (mgr->output)
351 mgr->unset_output(mgr);
352
353 r = mgr->set_output(mgr, out);
354 if (r) {
355 DSSERR("failed to connect manager to output of new device\n");
356
357 /* remove the output-device connection we just made */
358 omapdss_output_unset_device(out);
359 return r;
360 }
361
362 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
363 struct omap_overlay *ovl = omap_dss_get_overlay(i);
364
365 if (!ovl->manager || force) {
366 if (ovl->manager)
367 ovl->unset_manager(ovl);
368
369 r = ovl->set_manager(ovl, mgr);
370 if (r) {
371 DSSERR("failed to set initial overlay\n");
372 return r;
373 }
374 }
375 }
376
377 return 0;
378}
379
380static void dss_uninit_connections(struct omap_dss_device *dssdev)
381{
382 if (dssdev->output) {
383 struct omap_overlay_manager *mgr = dssdev->output->manager;
384
385 if (mgr)
386 mgr->unset_output(mgr);
387
388 omapdss_output_unset_device(dssdev->output);
389 }
390}
391
392int dss_init_device(struct platform_device *pdev,
320 struct omap_dss_device *dssdev) 393 struct omap_dss_device *dssdev)
321{ 394{
322 struct device_attribute *attr; 395 struct device_attribute *attr;
323 int i; 396 int i, r;
324 int r; 397 const char *def_disp_name = dss_get_default_display_name();
398 bool force;
399
400 force = def_disp_name && strcmp(def_disp_name, dssdev->name) == 0;
401 dss_init_connections(dssdev, force);
325 402
326 /* create device sysfs files */ 403 /* create device sysfs files */
327 i = 0; 404 i = 0;
328 while ((attr = display_sysfs_attrs[i++]) != NULL) { 405 while ((attr = display_sysfs_attrs[i++]) != NULL) {
329 r = device_create_file(&dssdev->dev, attr); 406 r = device_create_file(&dssdev->dev, attr);
330 if (r) 407 if (r) {
408 for (i = i - 2; i >= 0; i--) {
409 attr = display_sysfs_attrs[i];
410 device_remove_file(&dssdev->dev, attr);
411 }
412
413 dss_uninit_connections(dssdev);
414
331 DSSERR("failed to create sysfs file\n"); 415 DSSERR("failed to create sysfs file\n");
416 return r;
417 }
332 } 418 }
333 419
334 /* create display? sysfs links */ 420 /* create display? sysfs links */
335 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj, 421 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
336 dev_name(&dssdev->dev)); 422 dev_name(&dssdev->dev));
337 if (r) 423 if (r) {
424 while ((attr = display_sysfs_attrs[i++]) != NULL)
425 device_remove_file(&dssdev->dev, attr);
426
427 dss_uninit_connections(dssdev);
428
338 DSSERR("failed to create sysfs display link\n"); 429 DSSERR("failed to create sysfs display link\n");
430 return r;
431 }
432
433 return 0;
339} 434}
340 435
341void dss_uninit_device(struct platform_device *pdev, 436void dss_uninit_device(struct platform_device *pdev,
@@ -349,8 +444,7 @@ void dss_uninit_device(struct platform_device *pdev,
349 while ((attr = display_sysfs_attrs[i++]) != NULL) 444 while ((attr = display_sysfs_attrs[i++]) != NULL)
350 device_remove_file(&dssdev->dev, attr); 445 device_remove_file(&dssdev->dev, attr);
351 446
352 if (dssdev->manager) 447 dss_uninit_connections(dssdev);
353 dssdev->manager->unset_device(dssdev->manager);
354} 448}
355 449
356static int dss_suspend_device(struct device *dev, void *data) 450static int dss_suspend_device(struct device *dev, void *data)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 3266be23fc0d..56748cf8760e 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -29,17 +29,24 @@
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32#include <linux/string.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
34#include <plat/cpu.h>
35 35
36#include "dss.h" 36#include "dss.h"
37#include "dss_features.h"
37 38
38static struct { 39static struct {
39 struct regulator *vdds_dsi_reg; 40 struct regulator *vdds_dsi_reg;
40 struct platform_device *dsidev; 41 struct platform_device *dsidev;
41 42
43 struct mutex lock;
44
45 struct omap_video_timings timings;
42 struct dss_lcd_mgr_config mgr_config; 46 struct dss_lcd_mgr_config mgr_config;
47 int data_lines;
48
49 struct omap_dss_output output;
43} dpi; 50} dpi;
44 51
45static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) 52static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
@@ -121,7 +128,8 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
121 128
122static int dpi_set_mode(struct omap_dss_device *dssdev) 129static int dpi_set_mode(struct omap_dss_device *dssdev)
123{ 130{
124 struct omap_video_timings *t = &dssdev->panel.timings; 131 struct omap_video_timings *t = &dpi.timings;
132 struct omap_overlay_manager *mgr = dssdev->output->manager;
125 int lck_div = 0, pck_div = 0; 133 int lck_div = 0, pck_div = 0;
126 unsigned long fck = 0; 134 unsigned long fck = 0;
127 unsigned long pck; 135 unsigned long pck;
@@ -146,37 +154,44 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
146 t->pixel_clock = pck; 154 t->pixel_clock = pck;
147 } 155 }
148 156
149 dss_mgr_set_timings(dssdev->manager, t); 157 dss_mgr_set_timings(mgr, t);
150 158
151 return 0; 159 return 0;
152} 160}
153 161
154static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) 162static void dpi_config_lcd_manager(struct omap_dss_device *dssdev)
155{ 163{
164 struct omap_overlay_manager *mgr = dssdev->output->manager;
165
156 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 166 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
157 167
158 dpi.mgr_config.stallmode = false; 168 dpi.mgr_config.stallmode = false;
159 dpi.mgr_config.fifohandcheck = false; 169 dpi.mgr_config.fifohandcheck = false;
160 170
161 dpi.mgr_config.video_port_width = dssdev->phy.dpi.data_lines; 171 dpi.mgr_config.video_port_width = dpi.data_lines;
162 172
163 dpi.mgr_config.lcden_sig_polarity = 0; 173 dpi.mgr_config.lcden_sig_polarity = 0;
164 174
165 dss_mgr_set_lcd_config(dssdev->manager, &dpi.mgr_config); 175 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
166} 176}
167 177
168int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 178int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
169{ 179{
180 struct omap_dss_output *out = dssdev->output;
170 int r; 181 int r;
171 182
172 if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { 183 mutex_lock(&dpi.lock);
184
185 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
173 DSSERR("no VDSS_DSI regulator\n"); 186 DSSERR("no VDSS_DSI regulator\n");
174 return -ENODEV; 187 r = -ENODEV;
188 goto err_no_reg;
175 } 189 }
176 190
177 if (dssdev->manager == NULL) { 191 if (out == NULL || out->manager == NULL) {
178 DSSERR("failed to enable display: no manager\n"); 192 DSSERR("failed to enable display: no output/manager\n");
179 return -ENODEV; 193 r = -ENODEV;
194 goto err_no_out_mgr;
180 } 195 }
181 196
182 r = omap_dss_start_device(dssdev); 197 r = omap_dss_start_device(dssdev);
@@ -185,7 +200,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
185 goto err_start_dev; 200 goto err_start_dev;
186 } 201 }
187 202
188 if (cpu_is_omap34xx()) { 203 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
189 r = regulator_enable(dpi.vdds_dsi_reg); 204 r = regulator_enable(dpi.vdds_dsi_reg);
190 if (r) 205 if (r)
191 goto err_reg_enable; 206 goto err_reg_enable;
@@ -195,6 +210,10 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
195 if (r) 210 if (r)
196 goto err_get_dispc; 211 goto err_get_dispc;
197 212
213 r = dss_dpi_select_source(dssdev->channel);
214 if (r)
215 goto err_src_sel;
216
198 if (dpi_use_dsi_pll(dssdev)) { 217 if (dpi_use_dsi_pll(dssdev)) {
199 r = dsi_runtime_get(dpi.dsidev); 218 r = dsi_runtime_get(dpi.dsidev);
200 if (r) 219 if (r)
@@ -213,10 +232,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
213 232
214 mdelay(2); 233 mdelay(2);
215 234
216 r = dss_mgr_enable(dssdev->manager); 235 r = dss_mgr_enable(out->manager);
217 if (r) 236 if (r)
218 goto err_mgr_enable; 237 goto err_mgr_enable;
219 238
239 mutex_unlock(&dpi.lock);
240
220 return 0; 241 return 0;
221 242
222err_mgr_enable: 243err_mgr_enable:
@@ -227,20 +248,28 @@ err_dsi_pll_init:
227 if (dpi_use_dsi_pll(dssdev)) 248 if (dpi_use_dsi_pll(dssdev))
228 dsi_runtime_put(dpi.dsidev); 249 dsi_runtime_put(dpi.dsidev);
229err_get_dsi: 250err_get_dsi:
251err_src_sel:
230 dispc_runtime_put(); 252 dispc_runtime_put();
231err_get_dispc: 253err_get_dispc:
232 if (cpu_is_omap34xx()) 254 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
233 regulator_disable(dpi.vdds_dsi_reg); 255 regulator_disable(dpi.vdds_dsi_reg);
234err_reg_enable: 256err_reg_enable:
235 omap_dss_stop_device(dssdev); 257 omap_dss_stop_device(dssdev);
236err_start_dev: 258err_start_dev:
259err_no_out_mgr:
260err_no_reg:
261 mutex_unlock(&dpi.lock);
237 return r; 262 return r;
238} 263}
239EXPORT_SYMBOL(omapdss_dpi_display_enable); 264EXPORT_SYMBOL(omapdss_dpi_display_enable);
240 265
241void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 266void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
242{ 267{
243 dss_mgr_disable(dssdev->manager); 268 struct omap_overlay_manager *mgr = dssdev->output->manager;
269
270 mutex_lock(&dpi.lock);
271
272 dss_mgr_disable(mgr);
244 273
245 if (dpi_use_dsi_pll(dssdev)) { 274 if (dpi_use_dsi_pll(dssdev)) {
246 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 275 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
@@ -250,44 +279,39 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
250 279
251 dispc_runtime_put(); 280 dispc_runtime_put();
252 281
253 if (cpu_is_omap34xx()) 282 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
254 regulator_disable(dpi.vdds_dsi_reg); 283 regulator_disable(dpi.vdds_dsi_reg);
255 284
256 omap_dss_stop_device(dssdev); 285 omap_dss_stop_device(dssdev);
286
287 mutex_unlock(&dpi.lock);
257} 288}
258EXPORT_SYMBOL(omapdss_dpi_display_disable); 289EXPORT_SYMBOL(omapdss_dpi_display_disable);
259 290
260void dpi_set_timings(struct omap_dss_device *dssdev, 291void omapdss_dpi_set_timings(struct omap_dss_device *dssdev,
261 struct omap_video_timings *timings) 292 struct omap_video_timings *timings)
262{ 293{
263 int r;
264
265 DSSDBG("dpi_set_timings\n"); 294 DSSDBG("dpi_set_timings\n");
266 dssdev->panel.timings = *timings;
267 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
268 r = dispc_runtime_get();
269 if (r)
270 return;
271 295
272 dpi_set_mode(dssdev); 296 mutex_lock(&dpi.lock);
273 297
274 dispc_runtime_put(); 298 dpi.timings = *timings;
275 } else { 299
276 dss_mgr_set_timings(dssdev->manager, timings); 300 mutex_unlock(&dpi.lock);
277 }
278} 301}
279EXPORT_SYMBOL(dpi_set_timings); 302EXPORT_SYMBOL(omapdss_dpi_set_timings);
280 303
281int dpi_check_timings(struct omap_dss_device *dssdev, 304int dpi_check_timings(struct omap_dss_device *dssdev,
282 struct omap_video_timings *timings) 305 struct omap_video_timings *timings)
283{ 306{
284 int r; 307 int r;
308 struct omap_overlay_manager *mgr = dssdev->output->manager;
285 int lck_div, pck_div; 309 int lck_div, pck_div;
286 unsigned long fck; 310 unsigned long fck;
287 unsigned long pck; 311 unsigned long pck;
288 struct dispc_clock_info dispc_cinfo; 312 struct dispc_clock_info dispc_cinfo;
289 313
290 if (dss_mgr_check_timings(dssdev->manager, timings)) 314 if (dss_mgr_check_timings(mgr, timings))
291 return -EINVAL; 315 return -EINVAL;
292 316
293 if (timings->pixel_clock == 0) 317 if (timings->pixel_clock == 0)
@@ -325,11 +349,22 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
325} 349}
326EXPORT_SYMBOL(dpi_check_timings); 350EXPORT_SYMBOL(dpi_check_timings);
327 351
352void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
353{
354 mutex_lock(&dpi.lock);
355
356 dpi.data_lines = data_lines;
357
358 mutex_unlock(&dpi.lock);
359}
360EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
361
328static int __init dpi_init_display(struct omap_dss_device *dssdev) 362static int __init dpi_init_display(struct omap_dss_device *dssdev)
329{ 363{
330 DSSDBG("init_display\n"); 364 DSSDBG("init_display\n");
331 365
332 if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { 366 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) &&
367 dpi.vdds_dsi_reg == NULL) {
333 struct regulator *vdds_dsi; 368 struct regulator *vdds_dsi;
334 369
335 vdds_dsi = dss_get_vdds_dsi(); 370 vdds_dsi = dss_get_vdds_dsi();
@@ -351,10 +386,14 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
351 return 0; 386 return 0;
352} 387}
353 388
354static void __init dpi_probe_pdata(struct platform_device *pdev) 389static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
355{ 390{
356 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 391 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
357 int i, r; 392 const char *def_disp_name = dss_get_default_display_name();
393 struct omap_dss_device *def_dssdev;
394 int i;
395
396 def_dssdev = NULL;
358 397
359 for (i = 0; i < pdata->num_devices; ++i) { 398 for (i = 0; i < pdata->num_devices; ++i) {
360 struct omap_dss_device *dssdev = pdata->devices[i]; 399 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -362,21 +401,75 @@ static void __init dpi_probe_pdata(struct platform_device *pdev)
362 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI) 401 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
363 continue; 402 continue;
364 403
365 r = dpi_init_display(dssdev); 404 if (def_dssdev == NULL)
366 if (r) { 405 def_dssdev = dssdev;
367 DSSERR("device %s init failed: %d\n", dssdev->name, r); 406
368 continue; 407 if (def_disp_name != NULL &&
408 strcmp(dssdev->name, def_disp_name) == 0) {
409 def_dssdev = dssdev;
410 break;
369 } 411 }
412 }
370 413
371 r = omap_dss_register_device(dssdev, &pdev->dev, i); 414 return def_dssdev;
372 if (r) 415}
373 DSSERR("device %s register failed: %d\n", 416
374 dssdev->name, r); 417static void __init dpi_probe_pdata(struct platform_device *dpidev)
418{
419 struct omap_dss_device *plat_dssdev;
420 struct omap_dss_device *dssdev;
421 int r;
422
423 plat_dssdev = dpi_find_dssdev(dpidev);
424
425 if (!plat_dssdev)
426 return;
427
428 dssdev = dss_alloc_and_init_device(&dpidev->dev);
429 if (!dssdev)
430 return;
431
432 dss_copy_device_pdata(dssdev, plat_dssdev);
433
434 r = dpi_init_display(dssdev);
435 if (r) {
436 DSSERR("device %s init failed: %d\n", dssdev->name, r);
437 dss_put_device(dssdev);
438 return;
439 }
440
441 r = dss_add_device(dssdev);
442 if (r) {
443 DSSERR("device %s register failed: %d\n", dssdev->name, r);
444 dss_put_device(dssdev);
445 return;
375 } 446 }
376} 447}
377 448
449static void __init dpi_init_output(struct platform_device *pdev)
450{
451 struct omap_dss_output *out = &dpi.output;
452
453 out->pdev = pdev;
454 out->id = OMAP_DSS_OUTPUT_DPI;
455 out->type = OMAP_DISPLAY_TYPE_DPI;
456
457 dss_register_output(out);
458}
459
460static void __exit dpi_uninit_output(struct platform_device *pdev)
461{
462 struct omap_dss_output *out = &dpi.output;
463
464 dss_unregister_output(out);
465}
466
378static int __init omap_dpi_probe(struct platform_device *pdev) 467static int __init omap_dpi_probe(struct platform_device *pdev)
379{ 468{
469 mutex_init(&dpi.lock);
470
471 dpi_init_output(pdev);
472
380 dpi_probe_pdata(pdev); 473 dpi_probe_pdata(pdev);
381 474
382 return 0; 475 return 0;
@@ -384,7 +477,9 @@ static int __init omap_dpi_probe(struct platform_device *pdev)
384 477
385static int __exit omap_dpi_remove(struct platform_device *pdev) 478static int __exit omap_dpi_remove(struct platform_device *pdev)
386{ 479{
387 omap_dss_unregister_child_devices(&pdev->dev); 480 dss_unregister_child_devices(&pdev->dev);
481
482 dpi_uninit_output(pdev);
388 483
389 return 0; 484 return 0;
390} 485}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 05ee04667af1..d64ac3842884 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -41,7 +41,6 @@
41 41
42#include <video/omapdss.h> 42#include <video/omapdss.h>
43#include <video/mipi_display.h> 43#include <video/mipi_display.h>
44#include <plat/clock.h>
45 44
46#include "dss.h" 45#include "dss.h"
47#include "dss_features.h" 46#include "dss_features.h"
@@ -333,6 +332,12 @@ struct dsi_data {
333 unsigned scp_clk_refcount; 332 unsigned scp_clk_refcount;
334 333
335 struct dss_lcd_mgr_config mgr_config; 334 struct dss_lcd_mgr_config mgr_config;
335 struct omap_video_timings timings;
336 enum omap_dss_dsi_pixel_format pix_fmt;
337 enum omap_dss_dsi_mode mode;
338 struct omap_dss_dsi_videomode_timings vm_timings;
339
340 struct omap_dss_output output;
336}; 341};
337 342
338struct dsi_packet_sent_handler_data { 343struct dsi_packet_sent_handler_data {
@@ -340,8 +345,6 @@ struct dsi_packet_sent_handler_data {
340 struct completion *completion; 345 struct completion *completion;
341}; 346};
342 347
343static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
344
345#ifdef DEBUG 348#ifdef DEBUG
346static bool dsi_perf; 349static bool dsi_perf;
347module_param(dsi_perf, bool, 0644); 350module_param(dsi_perf, bool, 0644);
@@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
354 357
355static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) 358static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
356{ 359{
357 return dsi_pdev_map[dssdev->phy.dsi.module]; 360 return dssdev->output->pdev;
358} 361}
359 362
360struct platform_device *dsi_get_dsidev_from_id(int module) 363struct platform_device *dsi_get_dsidev_from_id(int module)
361{ 364{
362 return dsi_pdev_map[module]; 365 struct omap_dss_output *out;
366 enum omap_dss_output_id id;
367
368 id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
369
370 out = omap_dss_get_output(id);
371
372 return out->pdev;
363} 373}
364 374
365static inline void dsi_write_reg(struct platform_device *dsidev, 375static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -1450,6 +1460,148 @@ found:
1450 return 0; 1460 return 0;
1451} 1461}
1452 1462
1463static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1464 unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
1465{
1466 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1467 struct dsi_clock_info cur, best;
1468
1469 DSSDBG("dsi_pll_calc_ddrfreq\n");
1470
1471 memset(&best, 0, sizeof(best));
1472 memset(&cur, 0, sizeof(cur));
1473
1474 cur.clkin = clk_get_rate(dsi->sys_clk);
1475
1476 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1477 cur.fint = cur.clkin / cur.regn;
1478
1479 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1480 continue;
1481
1482 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1483 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1484 unsigned long a, b;
1485
1486 a = 2 * cur.regm * (cur.clkin/1000);
1487 b = cur.regn;
1488 cur.clkin4ddr = a / b * 1000;
1489
1490 if (cur.clkin4ddr > 1800 * 1000 * 1000)
1491 break;
1492
1493 if (abs(cur.clkin4ddr - req_clkin4ddr) <
1494 abs(best.clkin4ddr - req_clkin4ddr)) {
1495 best = cur;
1496 DSSDBG("best %ld\n", best.clkin4ddr);
1497 }
1498
1499 if (cur.clkin4ddr == req_clkin4ddr)
1500 goto found;
1501 }
1502 }
1503found:
1504 if (cinfo)
1505 *cinfo = best;
1506
1507 return 0;
1508}
1509
1510static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1511 struct dsi_clock_info *cinfo)
1512{
1513 unsigned long max_dsi_fck;
1514
1515 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1516
1517 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
1518 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1519}
1520
1521static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
1522 unsigned long req_pck, struct dsi_clock_info *cinfo,
1523 struct dispc_clock_info *dispc_cinfo)
1524{
1525 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1526 unsigned regm_dispc, best_regm_dispc;
1527 unsigned long dispc_clk, best_dispc_clk;
1528 int min_fck_per_pck;
1529 unsigned long max_dss_fck;
1530 struct dispc_clock_info best_dispc;
1531 bool match;
1532
1533 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1534
1535 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1536
1537 if (min_fck_per_pck &&
1538 req_pck * min_fck_per_pck > max_dss_fck) {
1539 DSSERR("Requested pixel clock not possible with the current "
1540 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1541 "the constraint off.\n");
1542 min_fck_per_pck = 0;
1543 }
1544
1545retry:
1546 best_regm_dispc = 0;
1547 best_dispc_clk = 0;
1548 memset(&best_dispc, 0, sizeof(best_dispc));
1549 match = false;
1550
1551 for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
1552 struct dispc_clock_info cur_dispc;
1553
1554 dispc_clk = cinfo->clkin4ddr / regm_dispc;
1555
1556 /* this will narrow down the search a bit,
1557 * but still give pixclocks below what was
1558 * requested */
1559 if (dispc_clk < req_pck)
1560 break;
1561
1562 if (dispc_clk > max_dss_fck)
1563 continue;
1564
1565 if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
1566 continue;
1567
1568 match = true;
1569
1570 dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
1571
1572 if (abs(cur_dispc.pck - req_pck) <
1573 abs(best_dispc.pck - req_pck)) {
1574 best_regm_dispc = regm_dispc;
1575 best_dispc_clk = dispc_clk;
1576 best_dispc = cur_dispc;
1577
1578 if (cur_dispc.pck == req_pck)
1579 goto found;
1580 }
1581 }
1582
1583 if (!match) {
1584 if (min_fck_per_pck) {
1585 DSSERR("Could not find suitable clock settings.\n"
1586 "Turning FCK/PCK constraint off and"
1587 "trying again.\n");
1588 min_fck_per_pck = 0;
1589 goto retry;
1590 }
1591
1592 DSSERR("Could not find suitable clock settings.\n");
1593
1594 return -EINVAL;
1595 }
1596found:
1597 cinfo->regm_dispc = best_regm_dispc;
1598 cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
1599
1600 *dispc_cinfo = best_dispc;
1601
1602 return 0;
1603}
1604
1453int dsi_pll_set_clock_div(struct platform_device *dsidev, 1605int dsi_pll_set_clock_div(struct platform_device *dsidev,
1454 struct dsi_clock_info *cinfo) 1606 struct dsi_clock_info *cinfo)
1455{ 1607{
@@ -1526,21 +1678,27 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1526 1678
1527 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); 1679 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1528 1680
1681 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1682
1529 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { 1683 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1530 f = cinfo->fint < 1000000 ? 0x3 : 1684 f = cinfo->fint < 1000000 ? 0x3 :
1531 cinfo->fint < 1250000 ? 0x4 : 1685 cinfo->fint < 1250000 ? 0x4 :
1532 cinfo->fint < 1500000 ? 0x5 : 1686 cinfo->fint < 1500000 ? 0x5 :
1533 cinfo->fint < 1750000 ? 0x6 : 1687 cinfo->fint < 1750000 ? 0x6 :
1534 0x7; 1688 0x7;
1535 }
1536 1689
1537 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1538
1539 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1540 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ 1690 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1691 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1692 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1693
1694 l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
1695 }
1696
1541 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1697 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1542 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1698 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1543 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1699 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1700 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1701 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1544 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); 1702 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1545 1703
1546 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ 1704 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
@@ -2004,15 +2162,16 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2004 return 1194 * 3; /* 1194x24 bits */ 2162 return 1194 * 3; /* 1194x24 bits */
2005 case 6: 2163 case 6:
2006 return 1365 * 3; /* 1365x24 bits */ 2164 return 1365 * 3; /* 1365x24 bits */
2165 case 7:
2166 return 1920 * 3; /* 1920x24 bits */
2007 default: 2167 default:
2008 BUG(); 2168 BUG();
2009 return 0; 2169 return 0;
2010 } 2170 }
2011} 2171}
2012 2172
2013static int dsi_set_lane_config(struct omap_dss_device *dssdev) 2173static int dsi_set_lane_config(struct platform_device *dsidev)
2014{ 2174{
2015 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2016 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2175 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2017 static const u8 offsets[] = { 0, 4, 8, 12, 16 }; 2176 static const u8 offsets[] = { 0, 4, 8, 12, 16 };
2018 static const enum dsi_lane_function functions[] = { 2177 static const enum dsi_lane_function functions[] = {
@@ -2136,9 +2295,16 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2136 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r); 2295 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
2137 2296
2138 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 2297 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
2139 r = FLD_MOD(r, tlpx_half, 22, 16); 2298 r = FLD_MOD(r, tlpx_half, 20, 16);
2140 r = FLD_MOD(r, tclk_trail, 15, 8); 2299 r = FLD_MOD(r, tclk_trail, 15, 8);
2141 r = FLD_MOD(r, tclk_zero, 7, 0); 2300 r = FLD_MOD(r, tclk_zero, 7, 0);
2301
2302 if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
2303 r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
2304 r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
2305 r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
2306 }
2307
2142 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); 2308 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
2143 2309
2144 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); 2310 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
@@ -2147,10 +2313,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2147} 2313}
2148 2314
2149/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ 2315/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
2150static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, 2316static void dsi_cio_enable_lane_override(struct platform_device *dsidev,
2151 unsigned mask_p, unsigned mask_n) 2317 unsigned mask_p, unsigned mask_n)
2152{ 2318{
2153 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2154 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2319 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2155 int i; 2320 int i;
2156 u32 l; 2321 u32 l;
@@ -2197,9 +2362,8 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2197 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); 2362 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
2198} 2363}
2199 2364
2200static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) 2365static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
2201{ 2366{
2202 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2203 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2367 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2204 int t, i; 2368 int t, i;
2205 bool in_use[DSI_MAX_NR_LANES]; 2369 bool in_use[DSI_MAX_NR_LANES];
@@ -2247,9 +2411,8 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2247} 2411}
2248 2412
2249/* return bitmask of enabled lanes, lane0 being the lsb */ 2413/* return bitmask of enabled lanes, lane0 being the lsb */
2250static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) 2414static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
2251{ 2415{
2252 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2253 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2416 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2254 unsigned mask = 0; 2417 unsigned mask = 0;
2255 int i; 2418 int i;
@@ -2262,16 +2425,15 @@ static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
2262 return mask; 2425 return mask;
2263} 2426}
2264 2427
2265static int dsi_cio_init(struct omap_dss_device *dssdev) 2428static int dsi_cio_init(struct platform_device *dsidev)
2266{ 2429{
2267 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2268 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2430 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2269 int r; 2431 int r;
2270 u32 l; 2432 u32 l;
2271 2433
2272 DSSDBGF(); 2434 DSSDBGF();
2273 2435
2274 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2436 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2275 if (r) 2437 if (r)
2276 return r; 2438 return r;
2277 2439
@@ -2288,7 +2450,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2288 goto err_scp_clk_dom; 2450 goto err_scp_clk_dom;
2289 } 2451 }
2290 2452
2291 r = dsi_set_lane_config(dssdev); 2453 r = dsi_set_lane_config(dsidev);
2292 if (r) 2454 if (r)
2293 goto err_scp_clk_dom; 2455 goto err_scp_clk_dom;
2294 2456
@@ -2323,7 +2485,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2323 mask_p |= 1 << i; 2485 mask_p |= 1 << i;
2324 } 2486 }
2325 2487
2326 dsi_cio_enable_lane_override(dssdev, mask_p, 0); 2488 dsi_cio_enable_lane_override(dsidev, mask_p, 0);
2327 } 2489 }
2328 2490
2329 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); 2491 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2340,7 +2502,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2340 dsi_if_enable(dsidev, false); 2502 dsi_if_enable(dsidev, false);
2341 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ 2503 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
2342 2504
2343 r = dsi_cio_wait_tx_clk_esc_reset(dssdev); 2505 r = dsi_cio_wait_tx_clk_esc_reset(dsidev);
2344 if (r) 2506 if (r)
2345 goto err_tx_clk_esc_rst; 2507 goto err_tx_clk_esc_rst;
2346 2508
@@ -2360,10 +2522,10 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2360 2522
2361 dsi_cio_timings(dsidev); 2523 dsi_cio_timings(dsidev);
2362 2524
2363 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 2525 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
2364 /* DDR_CLK_ALWAYS_ON */ 2526 /* DDR_CLK_ALWAYS_ON */
2365 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 2527 REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
2366 dssdev->panel.dsi_vm_data.ddr_clk_always_on, 13, 13); 2528 dsi->vm_timings.ddr_clk_always_on, 13, 13);
2367 } 2529 }
2368 2530
2369 dsi->ulps_enabled = false; 2531 dsi->ulps_enabled = false;
@@ -2381,13 +2543,12 @@ err_cio_pwr:
2381 dsi_cio_disable_lane_override(dsidev); 2543 dsi_cio_disable_lane_override(dsidev);
2382err_scp_clk_dom: 2544err_scp_clk_dom:
2383 dsi_disable_scp_clk(dsidev); 2545 dsi_disable_scp_clk(dsidev);
2384 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2546 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2385 return r; 2547 return r;
2386} 2548}
2387 2549
2388static void dsi_cio_uninit(struct omap_dss_device *dssdev) 2550static void dsi_cio_uninit(struct platform_device *dsidev)
2389{ 2551{
2390 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2391 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2552 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2392 2553
2393 /* DDR_CLK_ALWAYS_ON */ 2554 /* DDR_CLK_ALWAYS_ON */
@@ -2395,7 +2556,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)
2395 2556
2396 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); 2557 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2397 dsi_disable_scp_clk(dsidev); 2558 dsi_disable_scp_clk(dsidev);
2398 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev)); 2559 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev));
2399} 2560}
2400 2561
2401static void dsi_config_tx_fifo(struct platform_device *dsidev, 2562static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2685,6 +2846,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2685 bool enable) 2846 bool enable)
2686{ 2847{
2687 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2848 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2849 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2688 2850
2689 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); 2851 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
2690 2852
@@ -2701,7 +2863,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2701 dsi_force_tx_stop_mode_io(dsidev); 2863 dsi_force_tx_stop_mode_io(dsidev);
2702 2864
2703 /* start the DDR clock by sending a NULL packet */ 2865 /* start the DDR clock by sending a NULL packet */
2704 if (dssdev->panel.dsi_vm_data.ddr_clk_always_on && enable) 2866 if (dsi->vm_timings.ddr_clk_always_on && enable)
2705 dsi_vc_send_null(dssdev, channel); 2867 dsi_vc_send_null(dssdev, channel);
2706} 2868}
2707EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); 2869EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
@@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
2987} 3149}
2988EXPORT_SYMBOL(dsi_vc_send_null); 3150EXPORT_SYMBOL(dsi_vc_send_null);
2989 3151
2990static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, 3152static int dsi_vc_write_nosync_common(struct platform_device *dsidev,
2991 int channel, u8 *data, int len, enum dss_dsi_content_type type) 3153 int channel, u8 *data, int len, enum dss_dsi_content_type type)
2992{ 3154{
2993 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2994 int r; 3155 int r;
2995 3156
2996 if (len == 0) { 3157 if (len == 0) {
@@ -3021,7 +3182,9 @@ static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev,
3021int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, 3182int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3022 u8 *data, int len) 3183 u8 *data, int len)
3023{ 3184{
3024 return dsi_vc_write_nosync_common(dssdev, channel, data, len, 3185 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3186
3187 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3025 DSS_DSI_CONTENT_DCS); 3188 DSS_DSI_CONTENT_DCS);
3026} 3189}
3027EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); 3190EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
@@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
3029int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, 3192int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel,
3030 u8 *data, int len) 3193 u8 *data, int len)
3031{ 3194{
3032 return dsi_vc_write_nosync_common(dssdev, channel, data, len, 3195 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3196
3197 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3033 DSS_DSI_CONTENT_GENERIC); 3198 DSS_DSI_CONTENT_GENERIC);
3034} 3199}
3035EXPORT_SYMBOL(dsi_vc_generic_write_nosync); 3200EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
@@ -3040,7 +3205,7 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3040 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3205 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3041 int r; 3206 int r;
3042 3207
3043 r = dsi_vc_write_nosync_common(dssdev, channel, data, len, type); 3208 r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type);
3044 if (r) 3209 if (r)
3045 goto err; 3210 goto err;
3046 3211
@@ -3118,10 +3283,9 @@ int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
3118} 3283}
3119EXPORT_SYMBOL(dsi_vc_generic_write_2); 3284EXPORT_SYMBOL(dsi_vc_generic_write_2);
3120 3285
3121static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, 3286static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
3122 int channel, u8 dcs_cmd) 3287 int channel, u8 dcs_cmd)
3123{ 3288{
3124 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3125 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3289 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3126 int r; 3290 int r;
3127 3291
@@ -3139,10 +3303,9 @@ static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev,
3139 return 0; 3303 return 0;
3140} 3304}
3141 3305
3142static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, 3306static int dsi_vc_generic_send_read_request(struct platform_device *dsidev,
3143 int channel, u8 *reqdata, int reqlen) 3307 int channel, u8 *reqdata, int reqlen)
3144{ 3308{
3145 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3146 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3309 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3147 u16 data; 3310 u16 data;
3148 u8 data_type; 3311 u8 data_type;
@@ -3291,7 +3454,7 @@ int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3291 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3454 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3292 int r; 3455 int r;
3293 3456
3294 r = dsi_vc_dcs_send_read_request(dssdev, channel, dcs_cmd); 3457 r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
3295 if (r) 3458 if (r)
3296 goto err; 3459 goto err;
3297 3460
@@ -3322,7 +3485,7 @@ static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel,
3322 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3485 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3323 int r; 3486 int r;
3324 3487
3325 r = dsi_vc_generic_send_read_request(dssdev, channel, reqdata, reqlen); 3488 r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen);
3326 if (r) 3489 if (r)
3327 return r; 3490 return r;
3328 3491
@@ -3604,15 +3767,15 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3604 (total_ticks * 1000) / (fck / 1000 / 1000)); 3767 (total_ticks * 1000) / (fck / 1000 / 1000));
3605} 3768}
3606 3769
3607static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) 3770static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3608{ 3771{
3609 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3772 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3610 int num_line_buffers; 3773 int num_line_buffers;
3611 3774
3612 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3775 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3613 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3776 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3614 unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 3777 unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
3615 struct omap_video_timings *timings = &dssdev->panel.timings; 3778 struct omap_video_timings *timings = &dsi->timings;
3616 /* 3779 /*
3617 * Don't use line buffers if width is greater than the video 3780 * Don't use line buffers if width is greater than the video
3618 * port's line buffer size 3781 * port's line buffer size
@@ -3630,11 +3793,11 @@ static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev)
3630 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12); 3793 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
3631} 3794}
3632 3795
3633static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) 3796static void dsi_config_vp_sync_events(struct platform_device *dsidev)
3634{ 3797{
3635 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3798 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3636 bool vsync_end = dssdev->panel.dsi_vm_data.vp_vsync_end; 3799 bool vsync_end = dsi->vm_timings.vp_vsync_end;
3637 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; 3800 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3638 u32 r; 3801 u32 r;
3639 3802
3640 r = dsi_read_reg(dsidev, DSI_CTRL); 3803 r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -3648,13 +3811,13 @@ static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev)
3648 dsi_write_reg(dsidev, DSI_CTRL, r); 3811 dsi_write_reg(dsidev, DSI_CTRL, r);
3649} 3812}
3650 3813
3651static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) 3814static void dsi_config_blanking_modes(struct platform_device *dsidev)
3652{ 3815{
3653 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3816 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3654 int blanking_mode = dssdev->panel.dsi_vm_data.blanking_mode; 3817 int blanking_mode = dsi->vm_timings.blanking_mode;
3655 int hfp_blanking_mode = dssdev->panel.dsi_vm_data.hfp_blanking_mode; 3818 int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
3656 int hbp_blanking_mode = dssdev->panel.dsi_vm_data.hbp_blanking_mode; 3819 int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
3657 int hsa_blanking_mode = dssdev->panel.dsi_vm_data.hsa_blanking_mode; 3820 int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
3658 u32 r; 3821 u32 r;
3659 3822
3660 /* 3823 /*
@@ -3741,8 +3904,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3741 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat; 3904 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3742 int tclk_trail, ths_exit, exiths_clk; 3905 int tclk_trail, ths_exit, exiths_clk;
3743 bool ddr_alwon; 3906 bool ddr_alwon;
3744 struct omap_video_timings *timings = &dssdev->panel.timings; 3907 struct omap_video_timings *timings = &dsi->timings;
3745 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3908 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3746 int ndl = dsi->num_lanes_used - 1; 3909 int ndl = dsi->num_lanes_used - 1;
3747 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; 3910 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
3748 int hsa_interleave_hs = 0, hsa_interleave_lp = 0; 3911 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
@@ -3852,6 +4015,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3852static int dsi_proto_config(struct omap_dss_device *dssdev) 4015static int dsi_proto_config(struct omap_dss_device *dssdev)
3853{ 4016{
3854 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4017 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4018 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3855 u32 r; 4019 u32 r;
3856 int buswidth = 0; 4020 int buswidth = 0;
3857 4021
@@ -3871,7 +4035,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3871 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); 4035 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
3872 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); 4036 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
3873 4037
3874 switch (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt)) { 4038 switch (dsi_get_pixel_size(dsi->pix_fmt)) {
3875 case 16: 4039 case 16:
3876 buswidth = 0; 4040 buswidth = 0;
3877 break; 4041 break;
@@ -3903,11 +4067,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3903 4067
3904 dsi_write_reg(dsidev, DSI_CTRL, r); 4068 dsi_write_reg(dsidev, DSI_CTRL, r);
3905 4069
3906 dsi_config_vp_num_line_buffers(dssdev); 4070 dsi_config_vp_num_line_buffers(dsidev);
3907 4071
3908 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4072 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3909 dsi_config_vp_sync_events(dssdev); 4073 dsi_config_vp_sync_events(dsidev);
3910 dsi_config_blanking_modes(dssdev); 4074 dsi_config_blanking_modes(dsidev);
3911 dsi_config_cmd_mode_interleaving(dssdev); 4075 dsi_config_cmd_mode_interleaving(dssdev);
3912 } 4076 }
3913 4077
@@ -3919,9 +4083,8 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3919 return 0; 4083 return 0;
3920} 4084}
3921 4085
3922static void dsi_proto_timings(struct omap_dss_device *dssdev) 4086static void dsi_proto_timings(struct platform_device *dsidev)
3923{ 4087{
3924 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3925 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4088 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3926 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 4089 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
3927 unsigned tclk_pre, tclk_post; 4090 unsigned tclk_pre, tclk_post;
@@ -3941,7 +4104,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3941 ths_exit = FLD_GET(r, 7, 0); 4104 ths_exit = FLD_GET(r, 7, 0);
3942 4105
3943 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 4106 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3944 tlpx = FLD_GET(r, 22, 16) * 2; 4107 tlpx = FLD_GET(r, 20, 16) * 2;
3945 tclk_trail = FLD_GET(r, 15, 8); 4108 tclk_trail = FLD_GET(r, 15, 8);
3946 tclk_zero = FLD_GET(r, 7, 0); 4109 tclk_zero = FLD_GET(r, 7, 0);
3947 4110
@@ -3984,18 +4147,18 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3984 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", 4147 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
3985 enter_hs_mode_lat, exit_hs_mode_lat); 4148 enter_hs_mode_lat, exit_hs_mode_lat);
3986 4149
3987 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4150 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3988 /* TODO: Implement a video mode check_timings function */ 4151 /* TODO: Implement a video mode check_timings function */
3989 int hsa = dssdev->panel.dsi_vm_data.hsa; 4152 int hsa = dsi->vm_timings.hsa;
3990 int hfp = dssdev->panel.dsi_vm_data.hfp; 4153 int hfp = dsi->vm_timings.hfp;
3991 int hbp = dssdev->panel.dsi_vm_data.hbp; 4154 int hbp = dsi->vm_timings.hbp;
3992 int vsa = dssdev->panel.dsi_vm_data.vsa; 4155 int vsa = dsi->vm_timings.vsa;
3993 int vfp = dssdev->panel.dsi_vm_data.vfp; 4156 int vfp = dsi->vm_timings.vfp;
3994 int vbp = dssdev->panel.dsi_vm_data.vbp; 4157 int vbp = dsi->vm_timings.vbp;
3995 int window_sync = dssdev->panel.dsi_vm_data.window_sync; 4158 int window_sync = dsi->vm_timings.window_sync;
3996 bool hsync_end = dssdev->panel.dsi_vm_data.vp_hsync_end; 4159 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3997 struct omap_video_timings *timings = &dssdev->panel.timings; 4160 struct omap_video_timings *timings = &dsi->timings;
3998 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4161 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3999 int tl, t_he, width_bytes; 4162 int tl, t_he, width_bytes;
4000 4163
4001 t_he = hsync_end ? 4164 t_he = hsync_end ?
@@ -4100,16 +4263,84 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
4100} 4263}
4101EXPORT_SYMBOL(omapdss_dsi_configure_pins); 4264EXPORT_SYMBOL(omapdss_dsi_configure_pins);
4102 4265
4103int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 4266int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev,
4267 unsigned long ddr_clk, unsigned long lp_clk)
4104{ 4268{
4105 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4269 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4270 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4271 struct dsi_clock_info cinfo;
4272 struct dispc_clock_info dispc_cinfo;
4273 unsigned lp_clk_div;
4274 unsigned long dsi_fclk;
4106 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4275 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
4276 unsigned long pck;
4277 int r;
4278
4279 DSSDBGF("ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk);
4280
4281 mutex_lock(&dsi->lock);
4282
4283 /* Calculate PLL output clock */
4284 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo);
4285 if (r)
4286 goto err;
4287
4288 /* Calculate PLL's DSI clock */
4289 dsi_pll_calc_dsi_fck(dsidev, &cinfo);
4290
4291 /* Calculate PLL's DISPC clock and pck & lck divs */
4292 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp;
4293 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4294 r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
4295 if (r)
4296 goto err;
4297
4298 /* Calculate LP clock */
4299 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk;
4300 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2);
4301
4302 dssdev->clocks.dsi.regn = cinfo.regn;
4303 dssdev->clocks.dsi.regm = cinfo.regm;
4304 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4305 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4306
4307 dssdev->clocks.dsi.lp_clk_div = lp_clk_div;
4308
4309 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div;
4310 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
4311
4312 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK;
4313
4314 dssdev->clocks.dispc.channel.lcd_clk_src =
4315 dsi->module_id == 0 ?
4316 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4317 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
4318
4319 dssdev->clocks.dsi.dsi_fclk_src =
4320 dsi->module_id == 0 ?
4321 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4322 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
4323
4324 mutex_unlock(&dsi->lock);
4325 return 0;
4326err:
4327 mutex_unlock(&dsi->lock);
4328 return r;
4329}
4330EXPORT_SYMBOL(omapdss_dsi_set_clocks);
4331
4332int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4333{
4334 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4335 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4336 struct omap_overlay_manager *mgr = dssdev->output->manager;
4337 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4107 u8 data_type; 4338 u8 data_type;
4108 u16 word_count; 4339 u16 word_count;
4109 int r; 4340 int r;
4110 4341
4111 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4342 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4112 switch (dssdev->panel.dsi_pix_fmt) { 4343 switch (dsi->pix_fmt) {
4113 case OMAP_DSS_DSI_FMT_RGB888: 4344 case OMAP_DSS_DSI_FMT_RGB888:
4114 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 4345 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
4115 break; 4346 break;
@@ -4133,7 +4364,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4133 /* MODE, 1 = video mode */ 4364 /* MODE, 1 = video mode */
4134 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 4365 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
4135 4366
4136 word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); 4367 word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
4137 4368
4138 dsi_vc_write_long_header(dsidev, channel, data_type, 4369 dsi_vc_write_long_header(dsidev, channel, data_type,
4139 word_count, 0); 4370 word_count, 0);
@@ -4142,9 +4373,9 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
4142 dsi_if_enable(dsidev, true); 4373 dsi_if_enable(dsidev, true);
4143 } 4374 }
4144 4375
4145 r = dss_mgr_enable(dssdev->manager); 4376 r = dss_mgr_enable(mgr);
4146 if (r) { 4377 if (r) {
4147 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4378 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4148 dsi_if_enable(dsidev, false); 4379 dsi_if_enable(dsidev, false);
4149 dsi_vc_enable(dsidev, channel, false); 4380 dsi_vc_enable(dsidev, channel, false);
4150 } 4381 }
@@ -4159,8 +4390,10 @@ EXPORT_SYMBOL(dsi_enable_video_output);
4159void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) 4390void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4160{ 4391{
4161 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4392 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4393 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4394 struct omap_overlay_manager *mgr = dssdev->output->manager;
4162 4395
4163 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4396 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4164 dsi_if_enable(dsidev, false); 4397 dsi_if_enable(dsidev, false);
4165 dsi_vc_enable(dsidev, channel, false); 4398 dsi_vc_enable(dsidev, channel, false);
4166 4399
@@ -4171,15 +4404,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
4171 dsi_if_enable(dsidev, true); 4404 dsi_if_enable(dsidev, true);
4172 } 4405 }
4173 4406
4174 dss_mgr_disable(dssdev->manager); 4407 dss_mgr_disable(mgr);
4175} 4408}
4176EXPORT_SYMBOL(dsi_disable_video_output); 4409EXPORT_SYMBOL(dsi_disable_video_output);
4177 4410
4178static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 4411static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4179 u16 w, u16 h)
4180{ 4412{
4181 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4413 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4182 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4414 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4415 struct omap_overlay_manager *mgr = dssdev->output->manager;
4183 unsigned bytespp; 4416 unsigned bytespp;
4184 unsigned bytespl; 4417 unsigned bytespl;
4185 unsigned bytespf; 4418 unsigned bytespf;
@@ -4190,12 +4423,14 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4190 int r; 4423 int r;
4191 const unsigned channel = dsi->update_channel; 4424 const unsigned channel = dsi->update_channel;
4192 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 4425 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
4426 u16 w = dsi->timings.x_res;
4427 u16 h = dsi->timings.y_res;
4193 4428
4194 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); 4429 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
4195 4430
4196 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); 4431 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
4197 4432
4198 bytespp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4433 bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8;
4199 bytespl = w * bytespp; 4434 bytespl = w * bytespp;
4200 bytespf = bytespl * h; 4435 bytespf = bytespl * h;
4201 4436
@@ -4239,7 +4474,9 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4239 msecs_to_jiffies(250)); 4474 msecs_to_jiffies(250));
4240 BUG_ON(r == 0); 4475 BUG_ON(r == 0);
4241 4476
4242 dss_mgr_start_update(dssdev->manager); 4477 dss_mgr_set_timings(mgr, &dsi->timings);
4478
4479 dss_mgr_start_update(mgr);
4243 4480
4244 if (dsi->te_enabled) { 4481 if (dsi->te_enabled) {
4245 /* disable LP_RX_TO, so that we can receive TE. Time to wait 4482 /* disable LP_RX_TO, so that we can receive TE. Time to wait
@@ -4297,8 +4534,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4297 4534
4298static void dsi_framedone_irq_callback(void *data, u32 mask) 4535static void dsi_framedone_irq_callback(void *data, u32 mask)
4299{ 4536{
4300 struct omap_dss_device *dssdev = (struct omap_dss_device *) data; 4537 struct platform_device *dsidev = (struct platform_device *) data;
4301 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4302 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4538 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4303 4539
4304 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 4540 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
@@ -4325,13 +4561,14 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
4325 dsi->framedone_callback = callback; 4561 dsi->framedone_callback = callback;
4326 dsi->framedone_data = data; 4562 dsi->framedone_data = data;
4327 4563
4328 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4564 dw = dsi->timings.x_res;
4565 dh = dsi->timings.y_res;
4329 4566
4330#ifdef DEBUG 4567#ifdef DEBUG
4331 dsi->update_bytes = dw * dh * 4568 dsi->update_bytes = dw * dh *
4332 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4569 dsi_get_pixel_size(dsi->pix_fmt) / 8;
4333#endif 4570#endif
4334 dsi_update_screen_dispc(dssdev, dw, dh); 4571 dsi_update_screen_dispc(dssdev);
4335 4572
4336 return 0; 4573 return 0;
4337} 4574}
@@ -4367,28 +4604,22 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4367{ 4604{
4368 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4605 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4369 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4606 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4370 struct omap_video_timings timings; 4607 struct omap_overlay_manager *mgr = dssdev->output->manager;
4371 int r; 4608 int r;
4372 u32 irq = 0; 4609 u32 irq = 0;
4373 4610
4374 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4611 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4375 u16 dw, dh; 4612 dsi->timings.hsw = 1;
4376 4613 dsi->timings.hfp = 1;
4377 dssdev->driver->get_resolution(dssdev, &dw, &dh); 4614 dsi->timings.hbp = 1;
4378 4615 dsi->timings.vsw = 1;
4379 timings.x_res = dw; 4616 dsi->timings.vfp = 0;
4380 timings.y_res = dh; 4617 dsi->timings.vbp = 0;
4381 timings.hsw = 1;
4382 timings.hfp = 1;
4383 timings.hbp = 1;
4384 timings.vsw = 1;
4385 timings.vfp = 0;
4386 timings.vbp = 0;
4387 4618
4388 irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); 4619 irq = dispc_mgr_get_framedone_irq(mgr->id);
4389 4620
4390 r = omap_dispc_register_isr(dsi_framedone_irq_callback, 4621 r = omap_dispc_register_isr(dsi_framedone_irq_callback,
4391 (void *) dssdev, irq); 4622 (void *) dsidev, irq);
4392 if (r) { 4623 if (r) {
4393 DSSERR("can't get FRAMEDONE irq\n"); 4624 DSSERR("can't get FRAMEDONE irq\n");
4394 goto err; 4625 goto err;
@@ -4397,8 +4628,6 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4397 dsi->mgr_config.stallmode = true; 4628 dsi->mgr_config.stallmode = true;
4398 dsi->mgr_config.fifohandcheck = true; 4629 dsi->mgr_config.fifohandcheck = true;
4399 } else { 4630 } else {
4400 timings = dssdev->panel.timings;
4401
4402 dsi->mgr_config.stallmode = false; 4631 dsi->mgr_config.stallmode = false;
4403 dsi->mgr_config.fifohandcheck = false; 4632 dsi->mgr_config.fifohandcheck = false;
4404 } 4633 }
@@ -4407,14 +4636,14 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4407 * override interlace, logic level and edge related parameters in 4636 * override interlace, logic level and edge related parameters in
4408 * omap_video_timings with default values 4637 * omap_video_timings with default values
4409 */ 4638 */
4410 timings.interlace = false; 4639 dsi->timings.interlace = false;
4411 timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH; 4640 dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4412 timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH; 4641 dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4413 timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 4642 dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
4414 timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH; 4643 dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
4415 timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; 4644 dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
4416 4645
4417 dss_mgr_set_timings(dssdev->manager, &timings); 4646 dss_mgr_set_timings(mgr, &dsi->timings);
4418 4647
4419 r = dsi_configure_dispc_clocks(dssdev); 4648 r = dsi_configure_dispc_clocks(dssdev);
4420 if (r) 4649 if (r)
@@ -4422,29 +4651,33 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4422 4651
4423 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 4652 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
4424 dsi->mgr_config.video_port_width = 4653 dsi->mgr_config.video_port_width =
4425 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 4654 dsi_get_pixel_size(dsi->pix_fmt);
4426 dsi->mgr_config.lcden_sig_polarity = 0; 4655 dsi->mgr_config.lcden_sig_polarity = 0;
4427 4656
4428 dss_mgr_set_lcd_config(dssdev->manager, &dsi->mgr_config); 4657 dss_mgr_set_lcd_config(mgr, &dsi->mgr_config);
4429 4658
4430 return 0; 4659 return 0;
4431err1: 4660err1:
4432 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) 4661 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4433 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4662 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4434 (void *) dssdev, irq); 4663 (void *) dsidev, irq);
4435err: 4664err:
4436 return r; 4665 return r;
4437} 4666}
4438 4667
4439static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4668static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4440{ 4669{
4441 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4670 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4672 struct omap_overlay_manager *mgr = dssdev->output->manager;
4673
4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) {
4442 u32 irq; 4675 u32 irq;
4443 4676
4444 irq = dispc_mgr_get_framedone_irq(dssdev->manager->id); 4677 irq = dispc_mgr_get_framedone_irq(mgr->id);
4445 4678
4446 omap_dispc_unregister_isr(dsi_framedone_irq_callback, 4679 omap_dispc_unregister_isr(dsi_framedone_irq_callback,
4447 (void *) dssdev, irq); 4680 (void *) dsidev, irq);
4448 } 4681 }
4449} 4682}
4450 4683
@@ -4477,6 +4710,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4477{ 4710{
4478 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4711 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4479 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4712 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4713 struct omap_overlay_manager *mgr = dssdev->output->manager;
4480 int r; 4714 int r;
4481 4715
4482 r = dsi_pll_init(dsidev, true, true); 4716 r = dsi_pll_init(dsidev, true, true);
@@ -4489,18 +4723,18 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4489 4723
4490 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 4724 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
4491 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); 4725 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
4492 dss_select_lcd_clk_source(dssdev->manager->id, 4726 dss_select_lcd_clk_source(mgr->id,
4493 dssdev->clocks.dispc.channel.lcd_clk_src); 4727 dssdev->clocks.dispc.channel.lcd_clk_src);
4494 4728
4495 DSSDBG("PLL OK\n"); 4729 DSSDBG("PLL OK\n");
4496 4730
4497 r = dsi_cio_init(dssdev); 4731 r = dsi_cio_init(dsidev);
4498 if (r) 4732 if (r)
4499 goto err2; 4733 goto err2;
4500 4734
4501 _dsi_print_reset_status(dsidev); 4735 _dsi_print_reset_status(dsidev);
4502 4736
4503 dsi_proto_timings(dssdev); 4737 dsi_proto_timings(dsidev);
4504 dsi_set_lp_clk_divisor(dssdev); 4738 dsi_set_lp_clk_divisor(dssdev);
4505 4739
4506 if (1) 4740 if (1)
@@ -4520,11 +4754,11 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4520 4754
4521 return 0; 4755 return 0;
4522err3: 4756err3:
4523 dsi_cio_uninit(dssdev); 4757 dsi_cio_uninit(dsidev);
4524err2: 4758err2:
4525 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4759 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4526 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4760 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4527 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4761 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4528 4762
4529err1: 4763err1:
4530 dsi_pll_uninit(dsidev, true); 4764 dsi_pll_uninit(dsidev, true);
@@ -4537,6 +4771,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4537{ 4771{
4538 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4772 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4539 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4773 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4774 struct omap_overlay_manager *mgr = dssdev->output->manager;
4540 4775
4541 if (enter_ulps && !dsi->ulps_enabled) 4776 if (enter_ulps && !dsi->ulps_enabled)
4542 dsi_enter_ulps(dsidev); 4777 dsi_enter_ulps(dsidev);
@@ -4550,8 +4785,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4550 4785
4551 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4786 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4552 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4787 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4553 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4788 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
4554 dsi_cio_uninit(dssdev); 4789 dsi_cio_uninit(dsidev);
4555 dsi_pll_uninit(dsidev, disconnect_lanes); 4790 dsi_pll_uninit(dsidev, disconnect_lanes);
4556} 4791}
4557 4792
@@ -4559,6 +4794,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4559{ 4794{
4560 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4795 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4561 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4796 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4797 struct omap_dss_output *out = dssdev->output;
4562 int r = 0; 4798 int r = 0;
4563 4799
4564 DSSDBG("dsi_display_enable\n"); 4800 DSSDBG("dsi_display_enable\n");
@@ -4567,8 +4803,8 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4567 4803
4568 mutex_lock(&dsi->lock); 4804 mutex_lock(&dsi->lock);
4569 4805
4570 if (dssdev->manager == NULL) { 4806 if (out == NULL || out->manager == NULL) {
4571 DSSERR("failed to enable display: no manager\n"); 4807 DSSERR("failed to enable display: no output/manager\n");
4572 r = -ENODEV; 4808 r = -ENODEV;
4573 goto err_start_dev; 4809 goto err_start_dev;
4574 } 4810 }
@@ -4653,17 +4889,83 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4653} 4889}
4654EXPORT_SYMBOL(omapdss_dsi_enable_te); 4890EXPORT_SYMBOL(omapdss_dsi_enable_te);
4655 4891
4656static int __init dsi_init_display(struct omap_dss_device *dssdev) 4892void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
4893 struct omap_video_timings *timings)
4657{ 4894{
4658 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4895 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4659 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4896 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4660 4897
4661 DSSDBG("DSI init\n"); 4898 mutex_lock(&dsi->lock);
4662 4899
4663 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4900 dsi->timings = *timings;
4664 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | 4901
4665 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; 4902 mutex_unlock(&dsi->lock);
4666 } 4903}
4904EXPORT_SYMBOL(omapdss_dsi_set_timings);
4905
4906void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
4907{
4908 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4909 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4910
4911 mutex_lock(&dsi->lock);
4912
4913 dsi->timings.x_res = w;
4914 dsi->timings.y_res = h;
4915
4916 mutex_unlock(&dsi->lock);
4917}
4918EXPORT_SYMBOL(omapdss_dsi_set_size);
4919
4920void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
4921 enum omap_dss_dsi_pixel_format fmt)
4922{
4923 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4924 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4925
4926 mutex_lock(&dsi->lock);
4927
4928 dsi->pix_fmt = fmt;
4929
4930 mutex_unlock(&dsi->lock);
4931}
4932EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
4933
4934void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
4935 enum omap_dss_dsi_mode mode)
4936{
4937 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4938 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4939
4940 mutex_lock(&dsi->lock);
4941
4942 dsi->mode = mode;
4943
4944 mutex_unlock(&dsi->lock);
4945}
4946EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
4947
4948void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
4949 struct omap_dss_dsi_videomode_timings *timings)
4950{
4951 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4952 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4953
4954 mutex_lock(&dsi->lock);
4955
4956 dsi->vm_timings = *timings;
4957
4958 mutex_unlock(&dsi->lock);
4959}
4960EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
4961
4962static int __init dsi_init_display(struct omap_dss_device *dssdev)
4963{
4964 struct platform_device *dsidev =
4965 dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
4966 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4967
4968 DSSDBG("DSI init\n");
4667 4969
4668 if (dsi->vdds_dsi_reg == NULL) { 4970 if (dsi->vdds_dsi_reg == NULL) {
4669 struct regulator *vdds_dsi; 4971 struct regulator *vdds_dsi;
@@ -4806,11 +5108,15 @@ static void dsi_put_clocks(struct platform_device *dsidev)
4806 clk_put(dsi->sys_clk); 5108 clk_put(dsi->sys_clk);
4807} 5109}
4808 5110
4809static void __init dsi_probe_pdata(struct platform_device *dsidev) 5111static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
4810{ 5112{
4811 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5113 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
4812 struct omap_dss_board_info *pdata = dsidev->dev.platform_data; 5114 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
4813 int i, r; 5115 const char *def_disp_name = dss_get_default_display_name();
5116 struct omap_dss_device *def_dssdev;
5117 int i;
5118
5119 def_dssdev = NULL;
4814 5120
4815 for (i = 0; i < pdata->num_devices; ++i) { 5121 for (i = 0; i < pdata->num_devices; ++i) {
4816 struct omap_dss_device *dssdev = pdata->devices[i]; 5122 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -4821,19 +5127,73 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev)
4821 if (dssdev->phy.dsi.module != dsi->module_id) 5127 if (dssdev->phy.dsi.module != dsi->module_id)
4822 continue; 5128 continue;
4823 5129
4824 r = dsi_init_display(dssdev); 5130 if (def_dssdev == NULL)
4825 if (r) { 5131 def_dssdev = dssdev;
4826 DSSERR("device %s init failed: %d\n", dssdev->name, r); 5132
4827 continue; 5133 if (def_disp_name != NULL &&
5134 strcmp(dssdev->name, def_disp_name) == 0) {
5135 def_dssdev = dssdev;
5136 break;
4828 } 5137 }
5138 }
4829 5139
4830 r = omap_dss_register_device(dssdev, &dsidev->dev, i); 5140 return def_dssdev;
4831 if (r) 5141}
4832 DSSERR("device %s register failed: %d\n", 5142
4833 dssdev->name, r); 5143static void __init dsi_probe_pdata(struct platform_device *dsidev)
5144{
5145 struct omap_dss_device *plat_dssdev;
5146 struct omap_dss_device *dssdev;
5147 int r;
5148
5149 plat_dssdev = dsi_find_dssdev(dsidev);
5150
5151 if (!plat_dssdev)
5152 return;
5153
5154 dssdev = dss_alloc_and_init_device(&dsidev->dev);
5155 if (!dssdev)
5156 return;
5157
5158 dss_copy_device_pdata(dssdev, plat_dssdev);
5159
5160 r = dsi_init_display(dssdev);
5161 if (r) {
5162 DSSERR("device %s init failed: %d\n", dssdev->name, r);
5163 dss_put_device(dssdev);
5164 return;
5165 }
5166
5167 r = dss_add_device(dssdev);
5168 if (r) {
5169 DSSERR("device %s register failed: %d\n", dssdev->name, r);
5170 dss_put_device(dssdev);
5171 return;
4834 } 5172 }
4835} 5173}
4836 5174
5175static void __init dsi_init_output(struct platform_device *dsidev)
5176{
5177 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5178 struct omap_dss_output *out = &dsi->output;
5179
5180 out->pdev = dsidev;
5181 out->id = dsi->module_id == 0 ?
5182 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
5183
5184 out->type = OMAP_DISPLAY_TYPE_DSI;
5185
5186 dss_register_output(out);
5187}
5188
5189static void __exit dsi_uninit_output(struct platform_device *dsidev)
5190{
5191 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5192 struct omap_dss_output *out = &dsi->output;
5193
5194 dss_unregister_output(out);
5195}
5196
4837/* DSI1 HW IP initialisation */ 5197/* DSI1 HW IP initialisation */
4838static int __init omap_dsihw_probe(struct platform_device *dsidev) 5198static int __init omap_dsihw_probe(struct platform_device *dsidev)
4839{ 5199{
@@ -4848,7 +5208,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
4848 5208
4849 dsi->module_id = dsidev->id; 5209 dsi->module_id = dsidev->id;
4850 dsi->pdev = dsidev; 5210 dsi->pdev = dsidev;
4851 dsi_pdev_map[dsi->module_id] = dsidev;
4852 dev_set_drvdata(&dsidev->dev, dsi); 5211 dev_set_drvdata(&dsidev->dev, dsi);
4853 5212
4854 spin_lock_init(&dsi->irq_lock); 5213 spin_lock_init(&dsi->irq_lock);
@@ -4928,6 +5287,8 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
4928 else 5287 else
4929 dsi->num_lanes_supported = 3; 5288 dsi->num_lanes_supported = 3;
4930 5289
5290 dsi_init_output(dsidev);
5291
4931 dsi_probe_pdata(dsidev); 5292 dsi_probe_pdata(dsidev);
4932 5293
4933 dsi_runtime_put(dsidev); 5294 dsi_runtime_put(dsidev);
@@ -4957,7 +5318,9 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
4957 5318
4958 WARN_ON(dsi->scp_clk_refcount > 0); 5319 WARN_ON(dsi->scp_clk_refcount > 0);
4959 5320
4960 omap_dss_unregister_child_devices(&dsidev->dev); 5321 dss_unregister_child_devices(&dsidev->dev);
5322
5323 dsi_uninit_output(dsidev);
4961 5324
4962 pm_runtime_disable(&dsidev->dev); 5325 pm_runtime_disable(&dsidev->dev);
4963 5326
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 04b4586113e3..2ab1c3e96553 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -31,11 +31,11 @@
31#include <linux/clk.h> 31#include <linux/clk.h>
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/gfp.h>
34 35
35#include <video/omapdss.h> 36#include <video/omapdss.h>
36 37
37#include <plat/cpu.h> 38#include <plat/cpu.h>
38#include <plat/clock.h>
39 39
40#include "dss.h" 40#include "dss.h"
41#include "dss_features.h" 41#include "dss_features.h"
@@ -65,6 +65,13 @@ struct dss_reg {
65static int dss_runtime_get(void); 65static int dss_runtime_get(void);
66static void dss_runtime_put(void); 66static void dss_runtime_put(void);
67 67
68struct dss_features {
69 u8 fck_div_max;
70 u8 dss_fck_multiplier;
71 const char *clk_name;
72 int (*dpi_select_source)(enum omap_channel channel);
73};
74
68static struct { 75static struct {
69 struct platform_device *pdev; 76 struct platform_device *pdev;
70 void __iomem *base; 77 void __iomem *base;
@@ -83,6 +90,8 @@ static struct {
83 90
84 bool ctx_valid; 91 bool ctx_valid;
85 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 92 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
93
94 const struct dss_features *feat;
86} dss; 95} dss;
87 96
88static const char * const dss_generic_clk_source_names[] = { 97static const char * const dss_generic_clk_source_names[] = {
@@ -144,7 +153,7 @@ static void dss_restore_context(void)
144#undef SR 153#undef SR
145#undef RR 154#undef RR
146 155
147void dss_sdi_init(u8 datapairs) 156void dss_sdi_init(int datapairs)
148{ 157{
149 u32 l; 158 u32 l;
150 159
@@ -236,7 +245,6 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
236 return dss_generic_clk_source_names[clk_src]; 245 return dss_generic_clk_source_names[clk_src];
237} 246}
238 247
239
240void dss_dump_clocks(struct seq_file *s) 248void dss_dump_clocks(struct seq_file *s)
241{ 249{
242 unsigned long dpll4_ck_rate; 250 unsigned long dpll4_ck_rate;
@@ -259,18 +267,10 @@ void dss_dump_clocks(struct seq_file *s)
259 267
260 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 268 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
261 269
262 if (cpu_is_omap3630() || cpu_is_omap44xx()) 270 seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n",
263 seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", 271 fclk_name, fclk_real_name, dpll4_ck_rate,
264 fclk_name, fclk_real_name, 272 dpll4_ck_rate / dpll4_m4_ck_rate,
265 dpll4_ck_rate, 273 dss.feat->dss_fck_multiplier, fclk_rate);
266 dpll4_ck_rate / dpll4_m4_ck_rate,
267 fclk_rate);
268 else
269 seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
270 fclk_name, fclk_real_name,
271 dpll4_ck_rate,
272 dpll4_ck_rate / dpll4_m4_ck_rate,
273 fclk_rate);
274 } else { 274 } else {
275 seq_printf(s, "%s (%s) = %lu\n", 275 seq_printf(s, "%s (%s) = %lu\n",
276 fclk_name, fclk_real_name, 276 fclk_name, fclk_real_name,
@@ -431,31 +431,6 @@ enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
431 } 431 }
432} 432}
433 433
434/* calculate clock rates using dividers in cinfo */
435int dss_calc_clock_rates(struct dss_clock_info *cinfo)
436{
437 if (dss.dpll4_m4_ck) {
438 unsigned long prate;
439 u16 fck_div_max = 16;
440
441 if (cpu_is_omap3630() || cpu_is_omap44xx())
442 fck_div_max = 32;
443
444 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
445 return -EINVAL;
446
447 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
448
449 cinfo->fck = prate / cinfo->fck_div;
450 } else {
451 if (cinfo->fck_div != 0)
452 return -EINVAL;
453 cinfo->fck = clk_get_rate(dss.dss_clk);
454 }
455
456 return 0;
457}
458
459int dss_set_clock_div(struct dss_clock_info *cinfo) 434int dss_set_clock_div(struct dss_clock_info *cinfo)
460{ 435{
461 if (dss.dpll4_m4_ck) { 436 if (dss.dpll4_m4_ck) {
@@ -478,26 +453,6 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
478 return 0; 453 return 0;
479} 454}
480 455
481int dss_get_clock_div(struct dss_clock_info *cinfo)
482{
483 cinfo->fck = clk_get_rate(dss.dss_clk);
484
485 if (dss.dpll4_m4_ck) {
486 unsigned long prate;
487
488 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
489
490 if (cpu_is_omap3630() || cpu_is_omap44xx())
491 cinfo->fck_div = prate / (cinfo->fck);
492 else
493 cinfo->fck_div = prate / (cinfo->fck / 2);
494 } else {
495 cinfo->fck_div = 0;
496 }
497
498 return 0;
499}
500
501unsigned long dss_get_dpll4_rate(void) 456unsigned long dss_get_dpll4_rate(void)
502{ 457{
503 if (dss.dpll4_m4_ck) 458 if (dss.dpll4_m4_ck)
@@ -515,7 +470,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
515 470
516 unsigned long fck, max_dss_fck; 471 unsigned long fck, max_dss_fck;
517 472
518 u16 fck_div, fck_div_max = 16; 473 u16 fck_div;
519 474
520 int match = 0; 475 int match = 0;
521 int min_fck_per_pck; 476 int min_fck_per_pck;
@@ -525,9 +480,8 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
525 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 480 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
526 481
527 fck = clk_get_rate(dss.dss_clk); 482 fck = clk_get_rate(dss.dss_clk);
528 if (req_pck == dss.cache_req_pck && 483 if (req_pck == dss.cache_req_pck && prate == dss.cache_prate &&
529 ((cpu_is_omap34xx() && prate == dss.cache_prate) || 484 dss.cache_dss_cinfo.fck == fck) {
530 dss.cache_dss_cinfo.fck == fck)) {
531 DSSDBG("dispc clock info found from cache.\n"); 485 DSSDBG("dispc clock info found from cache.\n");
532 *dss_cinfo = dss.cache_dss_cinfo; 486 *dss_cinfo = dss.cache_dss_cinfo;
533 *dispc_cinfo = dss.cache_dispc_cinfo; 487 *dispc_cinfo = dss.cache_dispc_cinfo;
@@ -564,16 +518,10 @@ retry:
564 518
565 goto found; 519 goto found;
566 } else { 520 } else {
567 if (cpu_is_omap3630() || cpu_is_omap44xx()) 521 for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) {
568 fck_div_max = 32;
569
570 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
571 struct dispc_clock_info cur_dispc; 522 struct dispc_clock_info cur_dispc;
572 523
573 if (fck_div_max == 32) 524 fck = prate / fck_div * dss.feat->dss_fck_multiplier;
574 fck = prate / fck_div;
575 else
576 fck = prate / fck_div * 2;
577 525
578 if (fck > max_dss_fck) 526 if (fck > max_dss_fck)
579 continue; 527 continue;
@@ -648,9 +596,18 @@ void dss_set_dac_pwrdn_bgz(bool enable)
648 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ 596 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
649} 597}
650 598
651void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) 599void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src)
652{ 600{
653 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ 601 enum omap_display_type dp;
602 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
603
604 /* Complain about invalid selections */
605 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
606 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
607
608 /* Select only if we have options */
609 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
610 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
654} 611}
655 612
656enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) 613enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
@@ -661,9 +618,71 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
661 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) 618 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
662 return DSS_VENC_TV_CLK; 619 return DSS_VENC_TV_CLK;
663 620
621 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
622 return DSS_HDMI_M_PCLK;
623
664 return REG_GET(DSS_CONTROL, 15, 15); 624 return REG_GET(DSS_CONTROL, 15, 15);
665} 625}
666 626
627static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
628{
629 if (channel != OMAP_DSS_CHANNEL_LCD)
630 return -EINVAL;
631
632 return 0;
633}
634
635static int dss_dpi_select_source_omap4(enum omap_channel channel)
636{
637 int val;
638
639 switch (channel) {
640 case OMAP_DSS_CHANNEL_LCD2:
641 val = 0;
642 break;
643 case OMAP_DSS_CHANNEL_DIGIT:
644 val = 1;
645 break;
646 default:
647 return -EINVAL;
648 }
649
650 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
651
652 return 0;
653}
654
655static int dss_dpi_select_source_omap5(enum omap_channel channel)
656{
657 int val;
658
659 switch (channel) {
660 case OMAP_DSS_CHANNEL_LCD:
661 val = 1;
662 break;
663 case OMAP_DSS_CHANNEL_LCD2:
664 val = 2;
665 break;
666 case OMAP_DSS_CHANNEL_LCD3:
667 val = 3;
668 break;
669 case OMAP_DSS_CHANNEL_DIGIT:
670 val = 0;
671 break;
672 default:
673 return -EINVAL;
674 }
675
676 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
677
678 return 0;
679}
680
681int dss_dpi_select_source(enum omap_channel channel)
682{
683 return dss.feat->dpi_select_source(channel);
684}
685
667static int dss_get_clocks(void) 686static int dss_get_clocks(void)
668{ 687{
669 struct clk *clk; 688 struct clk *clk;
@@ -678,22 +697,11 @@ static int dss_get_clocks(void)
678 697
679 dss.dss_clk = clk; 698 dss.dss_clk = clk;
680 699
681 if (cpu_is_omap34xx()) { 700 clk = clk_get(NULL, dss.feat->clk_name);
682 clk = clk_get(NULL, "dpll4_m4_ck"); 701 if (IS_ERR(clk)) {
683 if (IS_ERR(clk)) { 702 DSSERR("Failed to get %s\n", dss.feat->clk_name);
684 DSSERR("Failed to get dpll4_m4_ck\n"); 703 r = PTR_ERR(clk);
685 r = PTR_ERR(clk); 704 goto err;
686 goto err;
687 }
688 } else if (cpu_is_omap44xx()) {
689 clk = clk_get(NULL, "dpll_per_m5x2_ck");
690 if (IS_ERR(clk)) {
691 DSSERR("Failed to get dpll_per_m5x2_ck\n");
692 r = PTR_ERR(clk);
693 goto err;
694 }
695 } else { /* omap24xx */
696 clk = NULL;
697 } 705 }
698 706
699 dss.dpll4_m4_ck = clk; 707 dss.dpll4_m4_ck = clk;
@@ -749,6 +757,71 @@ void dss_debug_dump_clocks(struct seq_file *s)
749} 757}
750#endif 758#endif
751 759
760static const struct dss_features omap24xx_dss_feats __initconst = {
761 .fck_div_max = 16,
762 .dss_fck_multiplier = 2,
763 .clk_name = NULL,
764 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
765};
766
767static const struct dss_features omap34xx_dss_feats __initconst = {
768 .fck_div_max = 16,
769 .dss_fck_multiplier = 2,
770 .clk_name = "dpll4_m4_ck",
771 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
772};
773
774static const struct dss_features omap3630_dss_feats __initconst = {
775 .fck_div_max = 32,
776 .dss_fck_multiplier = 1,
777 .clk_name = "dpll4_m4_ck",
778 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
779};
780
781static const struct dss_features omap44xx_dss_feats __initconst = {
782 .fck_div_max = 32,
783 .dss_fck_multiplier = 1,
784 .clk_name = "dpll_per_m5x2_ck",
785 .dpi_select_source = &dss_dpi_select_source_omap4,
786};
787
788static const struct dss_features omap54xx_dss_feats __initconst = {
789 .fck_div_max = 64,
790 .dss_fck_multiplier = 1,
791 .clk_name = "dpll_per_h12x2_ck",
792 .dpi_select_source = &dss_dpi_select_source_omap5,
793};
794
795static int __init dss_init_features(struct device *dev)
796{
797 const struct dss_features *src;
798 struct dss_features *dst;
799
800 dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
801 if (!dst) {
802 dev_err(dev, "Failed to allocate local DSS Features\n");
803 return -ENOMEM;
804 }
805
806 if (cpu_is_omap24xx())
807 src = &omap24xx_dss_feats;
808 else if (cpu_is_omap34xx())
809 src = &omap34xx_dss_feats;
810 else if (cpu_is_omap3630())
811 src = &omap3630_dss_feats;
812 else if (cpu_is_omap44xx())
813 src = &omap44xx_dss_feats;
814 else if (soc_is_omap54xx())
815 src = &omap54xx_dss_feats;
816 else
817 return -ENODEV;
818
819 memcpy(dst, src, sizeof(*dst));
820 dss.feat = dst;
821
822 return 0;
823}
824
752/* DSS HW IP initialisation */ 825/* DSS HW IP initialisation */
753static int __init omap_dsshw_probe(struct platform_device *pdev) 826static int __init omap_dsshw_probe(struct platform_device *pdev)
754{ 827{
@@ -758,6 +831,10 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
758 831
759 dss.pdev = pdev; 832 dss.pdev = pdev;
760 833
834 r = dss_init_features(&dss.pdev->dev);
835 if (r)
836 return r;
837
761 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 838 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
762 if (!dss_mem) { 839 if (!dss_mem) {
763 DSSERR("can't get IORESOURCE_MEM DSS\n"); 840 DSSERR("can't get IORESOURCE_MEM DSS\n");
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index f67afe76f217..6728892f9dad 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -113,6 +113,17 @@ enum dss_dsi_content_type {
113 DSS_DSI_CONTENT_GENERIC, 113 DSS_DSI_CONTENT_GENERIC,
114}; 114};
115 115
116enum dss_writeback_channel {
117 DSS_WB_LCD1_MGR = 0,
118 DSS_WB_LCD2_MGR = 1,
119 DSS_WB_TV_MGR = 2,
120 DSS_WB_OVL0 = 3,
121 DSS_WB_OVL1 = 4,
122 DSS_WB_OVL2 = 5,
123 DSS_WB_OVL3 = 6,
124 DSS_WB_LCD3_MGR = 7,
125};
126
116struct dss_clock_info { 127struct dss_clock_info {
117 /* rates that we get with dividers below */ 128 /* rates that we get with dividers below */
118 unsigned long fck; 129 unsigned long fck;
@@ -175,6 +186,7 @@ struct seq_file;
175struct platform_device; 186struct platform_device;
176 187
177/* core */ 188/* core */
189const char *dss_get_default_display_name(void);
178struct bus_type *dss_get_bus(void); 190struct bus_type *dss_get_bus(void);
179struct regulator *dss_get_vdds_dsi(void); 191struct regulator *dss_get_vdds_dsi(void);
180struct regulator *dss_get_vdds_sdi(void); 192struct regulator *dss_get_vdds_sdi(void);
@@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
184int dss_set_min_bus_tput(struct device *dev, unsigned long tput); 196int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
185int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); 197int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
186 198
187int omap_dss_register_device(struct omap_dss_device *dssdev, 199struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
188 struct device *parent, int disp_num); 200int dss_add_device(struct omap_dss_device *dssdev);
189void omap_dss_unregister_device(struct omap_dss_device *dssdev); 201void dss_unregister_device(struct omap_dss_device *dssdev);
190void omap_dss_unregister_child_devices(struct device *parent); 202void dss_unregister_child_devices(struct device *parent);
203void dss_put_device(struct omap_dss_device *dssdev);
204void dss_copy_device_pdata(struct omap_dss_device *dst,
205 const struct omap_dss_device *src);
191 206
192/* apply */ 207/* apply */
193void dss_apply_init(void); 208void dss_apply_init(void);
@@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
205int dss_mgr_set_device(struct omap_overlay_manager *mgr, 220int dss_mgr_set_device(struct omap_overlay_manager *mgr,
206 struct omap_dss_device *dssdev); 221 struct omap_dss_device *dssdev);
207int dss_mgr_unset_device(struct omap_overlay_manager *mgr); 222int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
223int dss_mgr_set_output(struct omap_overlay_manager *mgr,
224 struct omap_dss_output *output);
225int dss_mgr_unset_output(struct omap_overlay_manager *mgr);
208void dss_mgr_set_timings(struct omap_overlay_manager *mgr, 226void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
209 struct omap_video_timings *timings); 227 const struct omap_video_timings *timings);
210void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, 228void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
211 const struct dss_lcd_mgr_config *config); 229 const struct dss_lcd_mgr_config *config);
212const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); 230const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
@@ -222,12 +240,17 @@ int dss_ovl_set_manager(struct omap_overlay *ovl,
222 struct omap_overlay_manager *mgr); 240 struct omap_overlay_manager *mgr);
223int dss_ovl_unset_manager(struct omap_overlay *ovl); 241int dss_ovl_unset_manager(struct omap_overlay *ovl);
224 242
243/* output */
244void dss_register_output(struct omap_dss_output *out);
245void dss_unregister_output(struct omap_dss_output *out);
246struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev);
247
225/* display */ 248/* display */
226int dss_suspend_all_devices(void); 249int dss_suspend_all_devices(void);
227int dss_resume_all_devices(void); 250int dss_resume_all_devices(void);
228void dss_disable_all_devices(void); 251void dss_disable_all_devices(void);
229 252
230void dss_init_device(struct platform_device *pdev, 253int dss_init_device(struct platform_device *pdev,
231 struct omap_dss_device *dssdev); 254 struct omap_dss_device *dssdev);
232void dss_uninit_device(struct platform_device *pdev, 255void dss_uninit_device(struct platform_device *pdev,
233 struct omap_dss_device *dssdev); 256 struct omap_dss_device *dssdev);
@@ -254,22 +277,29 @@ static inline bool dss_mgr_is_lcd(enum omap_channel id)
254 return false; 277 return false;
255} 278}
256 279
280int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
281 struct platform_device *pdev);
282void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
283
257/* overlay */ 284/* overlay */
258void dss_init_overlays(struct platform_device *pdev); 285void dss_init_overlays(struct platform_device *pdev);
259void dss_uninit_overlays(struct platform_device *pdev); 286void dss_uninit_overlays(struct platform_device *pdev);
260void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 287void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
261void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
262int dss_ovl_simple_check(struct omap_overlay *ovl, 288int dss_ovl_simple_check(struct omap_overlay *ovl,
263 const struct omap_overlay_info *info); 289 const struct omap_overlay_info *info);
264int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 290int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
265 const struct omap_video_timings *mgr_timings); 291 const struct omap_video_timings *mgr_timings);
266bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, 292bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
267 enum omap_color_mode mode); 293 enum omap_color_mode mode);
294int dss_overlay_kobj_init(struct omap_overlay *ovl,
295 struct platform_device *pdev);
296void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
268 297
269/* DSS */ 298/* DSS */
270int dss_init_platform_driver(void) __init; 299int dss_init_platform_driver(void) __init;
271void dss_uninit_platform_driver(void); 300void dss_uninit_platform_driver(void);
272 301
302int dss_dpi_select_source(enum omap_channel channel);
273void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 303void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
274enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 304enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
275const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 305const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
@@ -279,7 +309,7 @@ void dss_dump_clocks(struct seq_file *s);
279void dss_debug_dump_clocks(struct seq_file *s); 309void dss_debug_dump_clocks(struct seq_file *s);
280#endif 310#endif
281 311
282void dss_sdi_init(u8 datapairs); 312void dss_sdi_init(int datapairs);
283int dss_sdi_enable(void); 313int dss_sdi_enable(void);
284void dss_sdi_disable(void); 314void dss_sdi_disable(void);
285 315
@@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type);
296void dss_set_dac_pwrdn_bgz(bool enable); 326void dss_set_dac_pwrdn_bgz(bool enable);
297 327
298unsigned long dss_get_dpll4_rate(void); 328unsigned long dss_get_dpll4_rate(void);
299int dss_calc_clock_rates(struct dss_clock_info *cinfo);
300int dss_set_clock_div(struct dss_clock_info *cinfo); 329int dss_set_clock_div(struct dss_clock_info *cinfo);
301int dss_get_clock_div(struct dss_clock_info *cinfo);
302int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 330int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
303 struct dispc_clock_info *dispc_cinfo); 331 struct dispc_clock_info *dispc_cinfo);
304 332
@@ -427,8 +455,9 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
427void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 455void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
428 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, 456 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
429 bool manual_update); 457 bool manual_update);
430int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 458int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
431 bool replication, const struct omap_video_timings *mgr_timings); 459 bool replication, const struct omap_video_timings *mgr_timings,
460 bool mem_to_mem);
432int dispc_ovl_enable(enum omap_plane plane, bool enable); 461int dispc_ovl_enable(enum omap_plane plane, bool enable);
433void dispc_ovl_set_channel_out(enum omap_plane plane, 462void dispc_ovl_set_channel_out(enum omap_plane plane,
434 enum omap_channel channel); 463 enum omap_channel channel);
@@ -457,6 +486,15 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
457void dispc_mgr_setup(enum omap_channel channel, 486void dispc_mgr_setup(enum omap_channel channel,
458 struct omap_overlay_manager_info *info); 487 struct omap_overlay_manager_info *info);
459 488
489u32 dispc_wb_get_framedone_irq(void);
490bool dispc_wb_go_busy(void);
491void dispc_wb_go(void);
492void dispc_wb_enable(bool enable);
493bool dispc_wb_is_enabled(void);
494void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
495int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
496 bool mem_to_mem, const struct omap_video_timings *timings);
497
460/* VENC */ 498/* VENC */
461#ifdef CONFIG_OMAP2_DSS_VENC 499#ifdef CONFIG_OMAP2_DSS_VENC
462int venc_init_platform_driver(void) __init; 500int venc_init_platform_driver(void) __init;
@@ -469,6 +507,20 @@ static inline unsigned long venc_get_pixel_clock(void)
469 return 0; 507 return 0;
470} 508}
471#endif 509#endif
510int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
511void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
512void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
513 struct omap_video_timings *timings);
514int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
515 struct omap_video_timings *timings);
516u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
517int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
518void omapdss_venc_set_type(struct omap_dss_device *dssdev,
519 enum omap_dss_venc_type type);
520void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
521 bool invert_polarity);
522int venc_panel_init(void);
523void venc_panel_exit(void);
472 524
473/* HDMI */ 525/* HDMI */
474#ifdef CONFIG_OMAP4_DSS_HDMI 526#ifdef CONFIG_OMAP4_DSS_HDMI
@@ -484,7 +536,8 @@ static inline unsigned long hdmi_get_pixel_clock(void)
484#endif 536#endif
485int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); 537int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
486void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); 538void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
487void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); 539void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
540 struct omap_video_timings *timings);
488int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 541int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
489 struct omap_video_timings *timings); 542 struct omap_video_timings *timings);
490int omapdss_hdmi_read_edid(u8 *buf, int len); 543int omapdss_hdmi_read_edid(u8 *buf, int len);
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 938709724f0c..acbc1e1efba3 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -46,7 +46,9 @@ struct omap_dss_features {
46 46
47 const int num_mgrs; 47 const int num_mgrs;
48 const int num_ovls; 48 const int num_ovls;
49 const int num_wbs;
49 const enum omap_display_type *supported_displays; 50 const enum omap_display_type *supported_displays;
51 const enum omap_dss_output_id *supported_outputs;
50 const enum omap_color_mode *supported_color_modes; 52 const enum omap_color_mode *supported_color_modes;
51 const enum omap_overlay_caps *overlay_caps; 53 const enum omap_overlay_caps *overlay_caps;
52 const char * const *clksrc_names; 54 const char * const *clksrc_names;
@@ -106,6 +108,21 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
106 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, 108 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
107}; 109};
108 110
111static const struct dss_reg_field omap5_dss_reg_fields[] = {
112 [FEAT_REG_FIRHINC] = { 12, 0 },
113 [FEAT_REG_FIRVINC] = { 28, 16 },
114 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
115 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
116 [FEAT_REG_FIFOSIZE] = { 15, 0 },
117 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
118 [FEAT_REG_VERTICALACCU] = { 26, 16 },
119 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
120 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
121 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
122 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
123 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
124};
125
109static const enum omap_display_type omap2_dss_supported_displays[] = { 126static const enum omap_display_type omap2_dss_supported_displays[] = {
110 /* OMAP_DSS_CHANNEL_LCD */ 127 /* OMAP_DSS_CHANNEL_LCD */
111 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, 128 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
@@ -144,6 +161,76 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
144 OMAP_DISPLAY_TYPE_DSI, 161 OMAP_DISPLAY_TYPE_DSI,
145}; 162};
146 163
164static const enum omap_display_type omap5_dss_supported_displays[] = {
165 /* OMAP_DSS_CHANNEL_LCD */
166 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
167 OMAP_DISPLAY_TYPE_DSI,
168
169 /* OMAP_DSS_CHANNEL_DIGIT */
170 OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
171
172 /* OMAP_DSS_CHANNEL_LCD2 */
173 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
174 OMAP_DISPLAY_TYPE_DSI,
175};
176
177static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
178 /* OMAP_DSS_CHANNEL_LCD */
179 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
180
181 /* OMAP_DSS_CHANNEL_DIGIT */
182 OMAP_DSS_OUTPUT_VENC,
183};
184
185static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
186 /* OMAP_DSS_CHANNEL_LCD */
187 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
188 OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
189
190 /* OMAP_DSS_CHANNEL_DIGIT */
191 OMAP_DSS_OUTPUT_VENC,
192};
193
194static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
195 /* OMAP_DSS_CHANNEL_LCD */
196 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
197 OMAP_DSS_OUTPUT_DSI1,
198
199 /* OMAP_DSS_CHANNEL_DIGIT */
200 OMAP_DSS_OUTPUT_VENC,
201};
202
203static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
204 /* OMAP_DSS_CHANNEL_LCD */
205 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
206 OMAP_DSS_OUTPUT_DSI1,
207
208 /* OMAP_DSS_CHANNEL_DIGIT */
209 OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
210 OMAP_DSS_OUTPUT_DPI,
211
212 /* OMAP_DSS_CHANNEL_LCD2 */
213 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
214 OMAP_DSS_OUTPUT_DSI2,
215};
216
217static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
218 /* OMAP_DSS_CHANNEL_LCD */
219 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
220 OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
221
222 /* OMAP_DSS_CHANNEL_DIGIT */
223 OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
224
225 /* OMAP_DSS_CHANNEL_LCD2 */
226 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
227 OMAP_DSS_OUTPUT_DSI1,
228
229 /* OMAP_DSS_CHANNEL_LCD3 */
230 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
231 OMAP_DSS_OUTPUT_DSI2,
232};
233
147static const enum omap_color_mode omap2_dss_supported_color_modes[] = { 234static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
148 /* OMAP_DSS_GFX */ 235 /* OMAP_DSS_GFX */
149 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | 236 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
@@ -224,58 +311,80 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
224 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | 311 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
225 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | 312 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
226 OMAP_DSS_COLOR_RGBX32, 313 OMAP_DSS_COLOR_RGBX32,
314
315 /* OMAP_DSS_WB */
316 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
317 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
318 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
319 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
320 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
321 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
322 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
323 OMAP_DSS_COLOR_RGBX32,
227}; 324};
228 325
229static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { 326static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
230 /* OMAP_DSS_GFX */ 327 /* OMAP_DSS_GFX */
231 0, 328 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
232 329
233 /* OMAP_DSS_VIDEO1 */ 330 /* OMAP_DSS_VIDEO1 */
234 OMAP_DSS_OVL_CAP_SCALE, 331 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
332 OMAP_DSS_OVL_CAP_REPLICATION,
235 333
236 /* OMAP_DSS_VIDEO2 */ 334 /* OMAP_DSS_VIDEO2 */
237 OMAP_DSS_OVL_CAP_SCALE, 335 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
336 OMAP_DSS_OVL_CAP_REPLICATION,
238}; 337};
239 338
240static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { 339static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
241 /* OMAP_DSS_GFX */ 340 /* OMAP_DSS_GFX */
242 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 341 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
342 OMAP_DSS_OVL_CAP_REPLICATION,
243 343
244 /* OMAP_DSS_VIDEO1 */ 344 /* OMAP_DSS_VIDEO1 */
245 OMAP_DSS_OVL_CAP_SCALE, 345 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
346 OMAP_DSS_OVL_CAP_REPLICATION,
246 347
247 /* OMAP_DSS_VIDEO2 */ 348 /* OMAP_DSS_VIDEO2 */
248 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA, 349 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
350 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
249}; 351};
250 352
251static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { 353static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
252 /* OMAP_DSS_GFX */ 354 /* OMAP_DSS_GFX */
253 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 355 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
356 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
254 357
255 /* OMAP_DSS_VIDEO1 */ 358 /* OMAP_DSS_VIDEO1 */
256 OMAP_DSS_OVL_CAP_SCALE, 359 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
360 OMAP_DSS_OVL_CAP_REPLICATION,
257 361
258 /* OMAP_DSS_VIDEO2 */ 362 /* OMAP_DSS_VIDEO2 */
259 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 363 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
260 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA, 364 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
365 OMAP_DSS_OVL_CAP_REPLICATION,
261}; 366};
262 367
263static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { 368static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
264 /* OMAP_DSS_GFX */ 369 /* OMAP_DSS_GFX */
265 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | 370 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
266 OMAP_DSS_OVL_CAP_ZORDER, 371 OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
372 OMAP_DSS_OVL_CAP_REPLICATION,
267 373
268 /* OMAP_DSS_VIDEO1 */ 374 /* OMAP_DSS_VIDEO1 */
269 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 375 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
270 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 376 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
377 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
271 378
272 /* OMAP_DSS_VIDEO2 */ 379 /* OMAP_DSS_VIDEO2 */
273 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 380 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
274 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 381 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
382 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
275 383
276 /* OMAP_DSS_VIDEO3 */ 384 /* OMAP_DSS_VIDEO3 */
277 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | 385 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
278 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER, 386 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
387 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
279}; 388};
280 389
281static const char * const omap2_dss_clk_source_names[] = { 390static const char * const omap2_dss_clk_source_names[] = {
@@ -298,6 +407,14 @@ static const char * const omap4_dss_clk_source_names[] = {
298 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", 407 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
299}; 408};
300 409
410static const char * const omap5_dss_clk_source_names[] = {
411 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
412 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
413 [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
414 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
415 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
416};
417
301static const struct dss_param_range omap2_dss_param_range[] = { 418static const struct dss_param_range omap2_dss_param_range[] = {
302 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 419 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
303 [FEAT_PARAM_DSS_PCD] = { 2, 255 }, 420 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
@@ -326,6 +443,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
326 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, 443 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
327 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 444 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
328 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 445 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
446 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
329 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 447 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
330 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 448 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
331 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, 449 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
@@ -341,6 +459,23 @@ static const struct dss_param_range omap4_dss_param_range[] = {
341 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, 459 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
342 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 460 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
343 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 461 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
462 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
463 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
464 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
465 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
466 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
467};
468
469static const struct dss_param_range omap5_dss_param_range[] = {
470 [FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
471 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
472 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
473 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
474 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
475 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
476 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
477 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
478 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
344 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 479 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
345 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 480 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
346 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 }, 481 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
@@ -373,6 +508,26 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
373 FEAT_ALPHA_FIXED_ZORDER, 508 FEAT_ALPHA_FIXED_ZORDER,
374 FEAT_FIFO_MERGE, 509 FEAT_FIFO_MERGE,
375 FEAT_OMAP3_DSI_FIFO_BUG, 510 FEAT_OMAP3_DSI_FIFO_BUG,
511 FEAT_DPI_USES_VDDS_DSI,
512};
513
514static const enum dss_feat_id am35xx_dss_feat_list[] = {
515 FEAT_LCDENABLEPOL,
516 FEAT_LCDENABLESIGNAL,
517 FEAT_PCKFREEENABLE,
518 FEAT_FUNCGATED,
519 FEAT_LINEBUFFERSPLIT,
520 FEAT_ROWREPEATENABLE,
521 FEAT_RESIZECONF,
522 FEAT_DSI_PLL_FREQSEL,
523 FEAT_DSI_REVERSE_TXCLKESC,
524 FEAT_VENC_REQUIRES_TV_DAC_CLK,
525 FEAT_CPR,
526 FEAT_PRELOAD,
527 FEAT_FIR_COEF_V,
528 FEAT_ALPHA_FIXED_ZORDER,
529 FEAT_FIFO_MERGE,
530 FEAT_OMAP3_DSI_FIFO_BUG,
376}; 531};
377 532
378static const enum dss_feat_id omap3630_dss_feat_list[] = { 533static const enum dss_feat_id omap3630_dss_feat_list[] = {
@@ -447,6 +602,28 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
447 FEAT_BURST_2D, 602 FEAT_BURST_2D,
448}; 603};
449 604
605static const enum dss_feat_id omap5_dss_feat_list[] = {
606 FEAT_MGR_LCD2,
607 FEAT_CORE_CLK_DIV,
608 FEAT_LCD_CLK_SRC,
609 FEAT_DSI_DCS_CMD_CONFIG_VC,
610 FEAT_DSI_VC_OCP_WIDTH,
611 FEAT_DSI_GNQ,
612 FEAT_HDMI_CTS_SWMODE,
613 FEAT_HDMI_AUDIO_USE_MCLK,
614 FEAT_HANDLE_UV_SEPARATE,
615 FEAT_ATTR2,
616 FEAT_CPR,
617 FEAT_PRELOAD,
618 FEAT_FIR_COEF_V,
619 FEAT_ALPHA_FREE_ZORDER,
620 FEAT_FIFO_MERGE,
621 FEAT_BURST_2D,
622 FEAT_DSI_PLL_SELFREQDCO,
623 FEAT_DSI_PLL_REFSEL,
624 FEAT_DSI_PHY_DCC,
625};
626
450/* OMAP2 DSS Features */ 627/* OMAP2 DSS Features */
451static const struct omap_dss_features omap2_dss_features = { 628static const struct omap_dss_features omap2_dss_features = {
452 .reg_fields = omap2_dss_reg_fields, 629 .reg_fields = omap2_dss_reg_fields,
@@ -458,6 +635,7 @@ static const struct omap_dss_features omap2_dss_features = {
458 .num_mgrs = 2, 635 .num_mgrs = 2,
459 .num_ovls = 3, 636 .num_ovls = 3,
460 .supported_displays = omap2_dss_supported_displays, 637 .supported_displays = omap2_dss_supported_displays,
638 .supported_outputs = omap2_dss_supported_outputs,
461 .supported_color_modes = omap2_dss_supported_color_modes, 639 .supported_color_modes = omap2_dss_supported_color_modes,
462 .overlay_caps = omap2_dss_overlay_caps, 640 .overlay_caps = omap2_dss_overlay_caps,
463 .clksrc_names = omap2_dss_clk_source_names, 641 .clksrc_names = omap2_dss_clk_source_names,
@@ -478,6 +656,31 @@ static const struct omap_dss_features omap3430_dss_features = {
478 .num_mgrs = 2, 656 .num_mgrs = 2,
479 .num_ovls = 3, 657 .num_ovls = 3,
480 .supported_displays = omap3430_dss_supported_displays, 658 .supported_displays = omap3430_dss_supported_displays,
659 .supported_outputs = omap3430_dss_supported_outputs,
660 .supported_color_modes = omap3_dss_supported_color_modes,
661 .overlay_caps = omap3430_dss_overlay_caps,
662 .clksrc_names = omap3_dss_clk_source_names,
663 .dss_params = omap3_dss_param_range,
664 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
665 .buffer_size_unit = 1,
666 .burst_size_unit = 8,
667};
668
669/*
670 * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
671 * vdds_dsi regulator.
672 */
673static const struct omap_dss_features am35xx_dss_features = {
674 .reg_fields = omap3_dss_reg_fields,
675 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
676
677 .features = am35xx_dss_feat_list,
678 .num_features = ARRAY_SIZE(am35xx_dss_feat_list),
679
680 .num_mgrs = 2,
681 .num_ovls = 3,
682 .supported_displays = omap3430_dss_supported_displays,
683 .supported_outputs = omap3430_dss_supported_outputs,
481 .supported_color_modes = omap3_dss_supported_color_modes, 684 .supported_color_modes = omap3_dss_supported_color_modes,
482 .overlay_caps = omap3430_dss_overlay_caps, 685 .overlay_caps = omap3430_dss_overlay_caps,
483 .clksrc_names = omap3_dss_clk_source_names, 686 .clksrc_names = omap3_dss_clk_source_names,
@@ -497,6 +700,7 @@ static const struct omap_dss_features omap3630_dss_features = {
497 .num_mgrs = 2, 700 .num_mgrs = 2,
498 .num_ovls = 3, 701 .num_ovls = 3,
499 .supported_displays = omap3630_dss_supported_displays, 702 .supported_displays = omap3630_dss_supported_displays,
703 .supported_outputs = omap3630_dss_supported_outputs,
500 .supported_color_modes = omap3_dss_supported_color_modes, 704 .supported_color_modes = omap3_dss_supported_color_modes,
501 .overlay_caps = omap3630_dss_overlay_caps, 705 .overlay_caps = omap3630_dss_overlay_caps,
502 .clksrc_names = omap3_dss_clk_source_names, 706 .clksrc_names = omap3_dss_clk_source_names,
@@ -517,7 +721,9 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
517 721
518 .num_mgrs = 3, 722 .num_mgrs = 3,
519 .num_ovls = 4, 723 .num_ovls = 4,
724 .num_wbs = 1,
520 .supported_displays = omap4_dss_supported_displays, 725 .supported_displays = omap4_dss_supported_displays,
726 .supported_outputs = omap4_dss_supported_outputs,
521 .supported_color_modes = omap4_dss_supported_color_modes, 727 .supported_color_modes = omap4_dss_supported_color_modes,
522 .overlay_caps = omap4_dss_overlay_caps, 728 .overlay_caps = omap4_dss_overlay_caps,
523 .clksrc_names = omap4_dss_clk_source_names, 729 .clksrc_names = omap4_dss_clk_source_names,
@@ -537,7 +743,9 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
537 743
538 .num_mgrs = 3, 744 .num_mgrs = 3,
539 .num_ovls = 4, 745 .num_ovls = 4,
746 .num_wbs = 1,
540 .supported_displays = omap4_dss_supported_displays, 747 .supported_displays = omap4_dss_supported_displays,
748 .supported_outputs = omap4_dss_supported_outputs,
541 .supported_color_modes = omap4_dss_supported_color_modes, 749 .supported_color_modes = omap4_dss_supported_color_modes,
542 .overlay_caps = omap4_dss_overlay_caps, 750 .overlay_caps = omap4_dss_overlay_caps,
543 .clksrc_names = omap4_dss_clk_source_names, 751 .clksrc_names = omap4_dss_clk_source_names,
@@ -557,7 +765,9 @@ static const struct omap_dss_features omap4_dss_features = {
557 765
558 .num_mgrs = 3, 766 .num_mgrs = 3,
559 .num_ovls = 4, 767 .num_ovls = 4,
768 .num_wbs = 1,
560 .supported_displays = omap4_dss_supported_displays, 769 .supported_displays = omap4_dss_supported_displays,
770 .supported_outputs = omap4_dss_supported_outputs,
561 .supported_color_modes = omap4_dss_supported_color_modes, 771 .supported_color_modes = omap4_dss_supported_color_modes,
562 .overlay_caps = omap4_dss_overlay_caps, 772 .overlay_caps = omap4_dss_overlay_caps,
563 .clksrc_names = omap4_dss_clk_source_names, 773 .clksrc_names = omap4_dss_clk_source_names,
@@ -567,6 +777,27 @@ static const struct omap_dss_features omap4_dss_features = {
567 .burst_size_unit = 16, 777 .burst_size_unit = 16,
568}; 778};
569 779
780/* OMAP5 DSS Features */
781static const struct omap_dss_features omap5_dss_features = {
782 .reg_fields = omap5_dss_reg_fields,
783 .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
784
785 .features = omap5_dss_feat_list,
786 .num_features = ARRAY_SIZE(omap5_dss_feat_list),
787
788 .num_mgrs = 3,
789 .num_ovls = 4,
790 .supported_displays = omap5_dss_supported_displays,
791 .supported_outputs = omap5_dss_supported_outputs,
792 .supported_color_modes = omap4_dss_supported_color_modes,
793 .overlay_caps = omap4_dss_overlay_caps,
794 .clksrc_names = omap5_dss_clk_source_names,
795 .dss_params = omap5_dss_param_range,
796 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
797 .buffer_size_unit = 16,
798 .burst_size_unit = 16,
799};
800
570#if defined(CONFIG_OMAP4_DSS_HDMI) 801#if defined(CONFIG_OMAP4_DSS_HDMI)
571/* HDMI OMAP4 Functions*/ 802/* HDMI OMAP4 Functions*/
572static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { 803static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
@@ -612,6 +843,11 @@ int dss_feat_get_num_ovls(void)
612 return omap_current_dss_features->num_ovls; 843 return omap_current_dss_features->num_ovls;
613} 844}
614 845
846int dss_feat_get_num_wbs(void)
847{
848 return omap_current_dss_features->num_wbs;
849}
850
615unsigned long dss_feat_get_param_min(enum dss_range_param param) 851unsigned long dss_feat_get_param_min(enum dss_range_param param)
616{ 852{
617 return omap_current_dss_features->dss_params[param].min; 853 return omap_current_dss_features->dss_params[param].min;
@@ -627,6 +863,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
627 return omap_current_dss_features->supported_displays[channel]; 863 return omap_current_dss_features->supported_displays[channel];
628} 864}
629 865
866enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
867{
868 return omap_current_dss_features->supported_outputs[channel];
869}
870
630enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) 871enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
631{ 872{
632 return omap_current_dss_features->supported_color_modes[plane]; 873 return omap_current_dss_features->supported_color_modes[plane];
@@ -694,8 +935,13 @@ void dss_features_init(void)
694 omap_current_dss_features = &omap2_dss_features; 935 omap_current_dss_features = &omap2_dss_features;
695 else if (cpu_is_omap3630()) 936 else if (cpu_is_omap3630())
696 omap_current_dss_features = &omap3630_dss_features; 937 omap_current_dss_features = &omap3630_dss_features;
697 else if (cpu_is_omap34xx()) 938 else if (cpu_is_omap34xx()) {
698 omap_current_dss_features = &omap3430_dss_features; 939 if (soc_is_am35xx()) {
940 omap_current_dss_features = &am35xx_dss_features;
941 } else {
942 omap_current_dss_features = &omap3430_dss_features;
943 }
944 }
699 else if (omap_rev() == OMAP4430_REV_ES1_0) 945 else if (omap_rev() == OMAP4430_REV_ES1_0)
700 omap_current_dss_features = &omap4430_es1_0_dss_features; 946 omap_current_dss_features = &omap4430_es1_0_dss_features;
701 else if (omap_rev() == OMAP4430_REV_ES2_0 || 947 else if (omap_rev() == OMAP4430_REV_ES2_0 ||
@@ -704,6 +950,8 @@ void dss_features_init(void)
704 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features; 950 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
705 else if (cpu_is_omap44xx()) 951 else if (cpu_is_omap44xx())
706 omap_current_dss_features = &omap4_dss_features; 952 omap_current_dss_features = &omap4_dss_features;
953 else if (soc_is_omap54xx())
954 omap_current_dss_features = &omap5_dss_features;
707 else 955 else
708 DSSWARN("Unsupported OMAP version"); 956 DSSWARN("Unsupported OMAP version");
709} 957}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 996ffcbfed58..9218113b5e88 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -50,6 +50,7 @@ enum dss_feat_id {
50 FEAT_DSI_VC_OCP_WIDTH, 50 FEAT_DSI_VC_OCP_WIDTH,
51 FEAT_DSI_REVERSE_TXCLKESC, 51 FEAT_DSI_REVERSE_TXCLKESC,
52 FEAT_DSI_GNQ, 52 FEAT_DSI_GNQ,
53 FEAT_DPI_USES_VDDS_DSI,
53 FEAT_HDMI_CTS_SWMODE, 54 FEAT_HDMI_CTS_SWMODE,
54 FEAT_HDMI_AUDIO_USE_MCLK, 55 FEAT_HDMI_AUDIO_USE_MCLK,
55 FEAT_HANDLE_UV_SEPARATE, 56 FEAT_HANDLE_UV_SEPARATE,
@@ -64,6 +65,9 @@ enum dss_feat_id {
64 /* An unknown HW bug causing the normal FIFO thresholds not to work */ 65 /* An unknown HW bug causing the normal FIFO thresholds not to work */
65 FEAT_OMAP3_DSI_FIFO_BUG, 66 FEAT_OMAP3_DSI_FIFO_BUG,
66 FEAT_BURST_2D, 67 FEAT_BURST_2D,
68 FEAT_DSI_PLL_SELFREQDCO,
69 FEAT_DSI_PLL_REFSEL,
70 FEAT_DSI_PHY_DCC,
67}; 71};
68 72
69/* DSS register field id */ 73/* DSS register field id */
@@ -91,6 +95,7 @@ enum dss_range_param {
91 FEAT_PARAM_DSIPLL_REGM_DSI, 95 FEAT_PARAM_DSIPLL_REGM_DSI,
92 FEAT_PARAM_DSIPLL_FINT, 96 FEAT_PARAM_DSIPLL_FINT,
93 FEAT_PARAM_DSIPLL_LPDIV, 97 FEAT_PARAM_DSIPLL_LPDIV,
98 FEAT_PARAM_DSI_FCK,
94 FEAT_PARAM_DOWNSCALE, 99 FEAT_PARAM_DOWNSCALE,
95 FEAT_PARAM_LINEWIDTH, 100 FEAT_PARAM_LINEWIDTH,
96 FEAT_PARAM_MGR_WIDTH, 101 FEAT_PARAM_MGR_WIDTH,
@@ -100,9 +105,11 @@ enum dss_range_param {
100/* DSS Feature Functions */ 105/* DSS Feature Functions */
101int dss_feat_get_num_mgrs(void); 106int dss_feat_get_num_mgrs(void);
102int dss_feat_get_num_ovls(void); 107int dss_feat_get_num_ovls(void);
108int dss_feat_get_num_wbs(void);
103unsigned long dss_feat_get_param_min(enum dss_range_param param); 109unsigned long dss_feat_get_param_min(enum dss_range_param param);
104unsigned long dss_feat_get_param_max(enum dss_range_param param); 110unsigned long dss_feat_get_param_max(enum dss_range_param param);
105enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); 111enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
112enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel);
106enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); 113enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
107enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 114enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane);
108bool dss_feat_color_mode_supported(enum omap_plane plane, 115bool dss_feat_color_mode_supported(enum omap_plane plane,
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 060216fdc578..a48a7dd75b33 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -32,6 +32,8 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#include <linux/gpio.h>
36#include <linux/regulator/consumer.h>
35#include <video/omapdss.h> 37#include <video/omapdss.h>
36 38
37#include "ti_hdmi.h" 39#include "ti_hdmi.h"
@@ -61,6 +63,13 @@ static struct {
61 struct hdmi_ip_data ip_data; 63 struct hdmi_ip_data ip_data;
62 64
63 struct clk *sys_clk; 65 struct clk *sys_clk;
66 struct regulator *vdda_hdmi_dac_reg;
67
68 int ct_cp_hpd_gpio;
69 int ls_oe_gpio;
70 int hpd_gpio;
71
72 struct omap_dss_output output;
64} hdmi; 73} hdmi;
65 74
66/* 75/*
@@ -314,12 +323,47 @@ static void hdmi_runtime_put(void)
314 323
315static int __init hdmi_init_display(struct omap_dss_device *dssdev) 324static int __init hdmi_init_display(struct omap_dss_device *dssdev)
316{ 325{
326 int r;
327
328 struct gpio gpios[] = {
329 { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" },
330 { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
331 { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
332 };
333
317 DSSDBG("init_display\n"); 334 DSSDBG("init_display\n");
318 335
319 dss_init_hdmi_ip_ops(&hdmi.ip_data); 336 dss_init_hdmi_ip_ops(&hdmi.ip_data);
337
338 if (hdmi.vdda_hdmi_dac_reg == NULL) {
339 struct regulator *reg;
340
341 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac");
342
343 if (IS_ERR(reg)) {
344 DSSERR("can't get VDDA_HDMI_DAC regulator\n");
345 return PTR_ERR(reg);
346 }
347
348 hdmi.vdda_hdmi_dac_reg = reg;
349 }
350
351 r = gpio_request_array(gpios, ARRAY_SIZE(gpios));
352 if (r)
353 return r;
354
320 return 0; 355 return 0;
321} 356}
322 357
358static void __exit hdmi_uninit_display(struct omap_dss_device *dssdev)
359{
360 DSSDBG("uninit_display\n");
361
362 gpio_free(hdmi.ct_cp_hpd_gpio);
363 gpio_free(hdmi.ls_oe_gpio);
364 gpio_free(hdmi.hpd_gpio);
365}
366
323static const struct hdmi_config *hdmi_find_timing( 367static const struct hdmi_config *hdmi_find_timing(
324 const struct hdmi_config *timings_arr, 368 const struct hdmi_config *timings_arr,
325 int len) 369 int len)
@@ -459,32 +503,30 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
459static int hdmi_power_on(struct omap_dss_device *dssdev) 503static int hdmi_power_on(struct omap_dss_device *dssdev)
460{ 504{
461 int r; 505 int r;
462 const struct hdmi_config *timing;
463 struct omap_video_timings *p; 506 struct omap_video_timings *p;
507 struct omap_overlay_manager *mgr = dssdev->output->manager;
464 unsigned long phy; 508 unsigned long phy;
465 509
510 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
511 gpio_set_value(hdmi.ls_oe_gpio, 1);
512
513 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
514 udelay(300);
515
516 r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
517 if (r)
518 goto err_vdac_enable;
519
466 r = hdmi_runtime_get(); 520 r = hdmi_runtime_get();
467 if (r) 521 if (r)
468 return r; 522 goto err_runtime_get;
469 523
470 dss_mgr_disable(dssdev->manager); 524 dss_mgr_disable(mgr);
471 525
472 p = &dssdev->panel.timings; 526 p = &hdmi.ip_data.cfg.timings;
473 527
474 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", 528 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
475 dssdev->panel.timings.x_res,
476 dssdev->panel.timings.y_res);
477 529
478 timing = hdmi_get_timings();
479 if (timing == NULL) {
480 /* HDMI code 4 corresponds to 640 * 480 VGA */
481 hdmi.ip_data.cfg.cm.code = 4;
482 /* DVI mode 1 corresponds to HDMI 0 to DVI */
483 hdmi.ip_data.cfg.cm.mode = HDMI_DVI;
484 hdmi.ip_data.cfg = vesa_timings[0];
485 } else {
486 hdmi.ip_data.cfg = *timing;
487 }
488 phy = p->pixel_clock; 530 phy = p->pixel_clock;
489 531
490 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 532 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
@@ -495,13 +537,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
495 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 537 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
496 if (r) { 538 if (r) {
497 DSSDBG("Failed to lock PLL\n"); 539 DSSDBG("Failed to lock PLL\n");
498 goto err; 540 goto err_pll_enable;
499 } 541 }
500 542
501 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); 543 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);
502 if (r) { 544 if (r) {
503 DSSDBG("Failed to start PHY\n"); 545 DSSDBG("Failed to start PHY\n");
504 goto err; 546 goto err_phy_enable;
505 } 547 }
506 548
507 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 549 hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
@@ -521,13 +563,13 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
521 dispc_enable_gamma_table(0); 563 dispc_enable_gamma_table(0);
522 564
523 /* tv size */ 565 /* tv size */
524 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 566 dss_mgr_set_timings(mgr, p);
525 567
526 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); 568 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
527 if (r) 569 if (r)
528 goto err_vid_enable; 570 goto err_vid_enable;
529 571
530 r = dss_mgr_enable(dssdev->manager); 572 r = dss_mgr_enable(mgr);
531 if (r) 573 if (r)
532 goto err_mgr_enable; 574 goto err_mgr_enable;
533 575
@@ -537,20 +579,33 @@ err_mgr_enable:
537 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 579 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
538err_vid_enable: 580err_vid_enable:
539 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 581 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
582err_phy_enable:
540 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 583 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
541err: 584err_pll_enable:
542 hdmi_runtime_put(); 585 hdmi_runtime_put();
586err_runtime_get:
587 regulator_disable(hdmi.vdda_hdmi_dac_reg);
588err_vdac_enable:
589 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
590 gpio_set_value(hdmi.ls_oe_gpio, 0);
543 return -EIO; 591 return -EIO;
544} 592}
545 593
546static void hdmi_power_off(struct omap_dss_device *dssdev) 594static void hdmi_power_off(struct omap_dss_device *dssdev)
547{ 595{
548 dss_mgr_disable(dssdev->manager); 596 struct omap_overlay_manager *mgr = dssdev->output->manager;
597
598 dss_mgr_disable(mgr);
549 599
550 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 600 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
551 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 601 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
552 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 602 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
553 hdmi_runtime_put(); 603 hdmi_runtime_put();
604
605 regulator_disable(hdmi.vdda_hdmi_dac_reg);
606
607 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
608 gpio_set_value(hdmi.ls_oe_gpio, 0);
554} 609}
555 610
556int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 611int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -567,25 +622,22 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
567 622
568} 623}
569 624
570void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) 625void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
626 struct omap_video_timings *timings)
571{ 627{
572 struct hdmi_cm cm; 628 struct hdmi_cm cm;
629 const struct hdmi_config *t;
573 630
574 cm = hdmi_get_code(&dssdev->panel.timings); 631 mutex_lock(&hdmi.lock);
575 hdmi.ip_data.cfg.cm.code = cm.code;
576 hdmi.ip_data.cfg.cm.mode = cm.mode;
577 632
578 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 633 cm = hdmi_get_code(timings);
579 int r; 634 hdmi.ip_data.cfg.cm = cm;
580 635
581 hdmi_power_off(dssdev); 636 t = hdmi_get_timings();
637 if (t != NULL)
638 hdmi.ip_data.cfg = *t;
582 639
583 r = hdmi_power_on(dssdev); 640 mutex_unlock(&hdmi.lock);
584 if (r)
585 DSSERR("failed to power on device\n");
586 } else {
587 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
588 }
589} 641}
590 642
591static void hdmi_dump_regs(struct seq_file *s) 643static void hdmi_dump_regs(struct seq_file *s)
@@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void)
640 692
641int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) 693int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
642{ 694{
643 struct omap_dss_hdmi_data *priv = dssdev->data; 695 struct omap_dss_output *out = dssdev->output;
644 int r = 0; 696 int r = 0;
645 697
646 DSSDBG("ENTER hdmi_display_enable\n"); 698 DSSDBG("ENTER hdmi_display_enable\n");
647 699
648 mutex_lock(&hdmi.lock); 700 mutex_lock(&hdmi.lock);
649 701
650 if (dssdev->manager == NULL) { 702 if (out == NULL || out->manager == NULL) {
651 DSSERR("failed to enable display: no manager\n"); 703 DSSERR("failed to enable display: no output/manager\n");
652 r = -ENODEV; 704 r = -ENODEV;
653 goto err0; 705 goto err0;
654 } 706 }
655 707
656 hdmi.ip_data.hpd_gpio = priv->hpd_gpio; 708 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
657 709
658 r = omap_dss_start_device(dssdev); 710 r = omap_dss_start_device(dssdev);
659 if (r) { 711 if (r) {
@@ -661,26 +713,15 @@ int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
661 goto err0; 713 goto err0;
662 } 714 }
663 715
664 if (dssdev->platform_enable) {
665 r = dssdev->platform_enable(dssdev);
666 if (r) {
667 DSSERR("failed to enable GPIO's\n");
668 goto err1;
669 }
670 }
671
672 r = hdmi_power_on(dssdev); 716 r = hdmi_power_on(dssdev);
673 if (r) { 717 if (r) {
674 DSSERR("failed to power on device\n"); 718 DSSERR("failed to power on device\n");
675 goto err2; 719 goto err1;
676 } 720 }
677 721
678 mutex_unlock(&hdmi.lock); 722 mutex_unlock(&hdmi.lock);
679 return 0; 723 return 0;
680 724
681err2:
682 if (dssdev->platform_disable)
683 dssdev->platform_disable(dssdev);
684err1: 725err1:
685 omap_dss_stop_device(dssdev); 726 omap_dss_stop_device(dssdev);
686err0: 727err0:
@@ -696,9 +737,6 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
696 737
697 hdmi_power_off(dssdev); 738 hdmi_power_off(dssdev);
698 739
699 if (dssdev->platform_disable)
700 dssdev->platform_disable(dssdev);
701
702 omap_dss_stop_device(dssdev); 740 omap_dss_stop_device(dssdev);
703 741
704 mutex_unlock(&hdmi.lock); 742 mutex_unlock(&hdmi.lock);
@@ -869,10 +907,14 @@ int hdmi_audio_config(struct omap_dss_audio *audio)
869 907
870#endif 908#endif
871 909
872static void __init hdmi_probe_pdata(struct platform_device *pdev) 910static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
873{ 911{
874 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 912 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
875 int r, i; 913 const char *def_disp_name = dss_get_default_display_name();
914 struct omap_dss_device *def_dssdev;
915 int i;
916
917 def_dssdev = NULL;
876 918
877 for (i = 0; i < pdata->num_devices; ++i) { 919 for (i = 0; i < pdata->num_devices; ++i) {
878 struct omap_dss_device *dssdev = pdata->devices[i]; 920 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -880,17 +922,76 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev)
880 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI) 922 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
881 continue; 923 continue;
882 924
883 r = hdmi_init_display(dssdev); 925 if (def_dssdev == NULL)
884 if (r) { 926 def_dssdev = dssdev;
885 DSSERR("device %s init failed: %d\n", dssdev->name, r); 927
886 continue; 928 if (def_disp_name != NULL &&
929 strcmp(dssdev->name, def_disp_name) == 0) {
930 def_dssdev = dssdev;
931 break;
887 } 932 }
933 }
888 934
889 r = omap_dss_register_device(dssdev, &pdev->dev, i); 935 return def_dssdev;
890 if (r) 936}
891 DSSERR("device %s register failed: %d\n", 937
892 dssdev->name, r); 938static void __init hdmi_probe_pdata(struct platform_device *pdev)
939{
940 struct omap_dss_device *plat_dssdev;
941 struct omap_dss_device *dssdev;
942 struct omap_dss_hdmi_data *priv;
943 int r;
944
945 plat_dssdev = hdmi_find_dssdev(pdev);
946
947 if (!plat_dssdev)
948 return;
949
950 dssdev = dss_alloc_and_init_device(&pdev->dev);
951 if (!dssdev)
952 return;
953
954 dss_copy_device_pdata(dssdev, plat_dssdev);
955
956 priv = dssdev->data;
957
958 hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio;
959 hdmi.ls_oe_gpio = priv->ls_oe_gpio;
960 hdmi.hpd_gpio = priv->hpd_gpio;
961
962 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
963
964 r = hdmi_init_display(dssdev);
965 if (r) {
966 DSSERR("device %s init failed: %d\n", dssdev->name, r);
967 dss_put_device(dssdev);
968 return;
893 } 969 }
970
971 r = dss_add_device(dssdev);
972 if (r) {
973 DSSERR("device %s register failed: %d\n", dssdev->name, r);
974 dss_put_device(dssdev);
975 return;
976 }
977}
978
979static void __init hdmi_init_output(struct platform_device *pdev)
980{
981 struct omap_dss_output *out = &hdmi.output;
982
983 out->pdev = pdev;
984 out->id = OMAP_DSS_OUTPUT_HDMI;
985 out->type = OMAP_DISPLAY_TYPE_HDMI;
986
987 dss_register_output(out);
988}
989
990static void __exit hdmi_uninit_output(struct platform_device *pdev)
991{
992 struct omap_dss_output *out = &hdmi.output;
993
994 dss_unregister_output(out);
894} 995}
895 996
896/* HDMI HW IP initialisation */ 997/* HDMI HW IP initialisation */
@@ -929,23 +1030,37 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
929 hdmi.ip_data.core_av_offset = HDMI_CORE_AV; 1030 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
930 hdmi.ip_data.pll_offset = HDMI_PLLCTRL; 1031 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
931 hdmi.ip_data.phy_offset = HDMI_PHY; 1032 hdmi.ip_data.phy_offset = HDMI_PHY;
1033
932 mutex_init(&hdmi.ip_data.lock); 1034 mutex_init(&hdmi.ip_data.lock);
933 1035
934 hdmi_panel_init(); 1036 hdmi_panel_init();
935 1037
936 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 1038 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
937 1039
1040 hdmi_init_output(pdev);
1041
938 hdmi_probe_pdata(pdev); 1042 hdmi_probe_pdata(pdev);
939 1043
940 return 0; 1044 return 0;
941} 1045}
942 1046
1047static int __exit hdmi_remove_child(struct device *dev, void *data)
1048{
1049 struct omap_dss_device *dssdev = to_dss_device(dev);
1050 hdmi_uninit_display(dssdev);
1051 return 0;
1052}
1053
943static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) 1054static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
944{ 1055{
945 omap_dss_unregister_child_devices(&pdev->dev); 1056 device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
1057
1058 dss_unregister_child_devices(&pdev->dev);
946 1059
947 hdmi_panel_exit(); 1060 hdmi_panel_exit();
948 1061
1062 hdmi_uninit_output(pdev);
1063
949 pm_runtime_disable(&pdev->dev); 1064 pm_runtime_disable(&pdev->dev);
950 1065
951 hdmi_put_clocks(); 1066 hdmi_put_clocks();
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index e10844faadf9..69fb115bab32 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -41,17 +41,34 @@ static struct {
41 41
42static int hdmi_panel_probe(struct omap_dss_device *dssdev) 42static int hdmi_panel_probe(struct omap_dss_device *dssdev)
43{ 43{
44 /* Initialize default timings to VGA in DVI mode */
45 const struct omap_video_timings default_timings = {
46 .x_res = 640,
47 .y_res = 480,
48 .pixel_clock = 25175,
49 .hsw = 96,
50 .hfp = 16,
51 .hbp = 48,
52 .vsw = 2,
53 .vfp = 11,
54 .vbp = 31,
55
56 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
57 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
58
59 .interlace = false,
60 };
61
44 DSSDBG("ENTER hdmi_panel_probe\n"); 62 DSSDBG("ENTER hdmi_panel_probe\n");
45 63
46 dssdev->panel.timings = (struct omap_video_timings) 64 dssdev->panel.timings = default_timings;
47 { 640, 480, 25175, 96, 16, 48, 2, 11, 31,
48 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
49 false,
50 };
51 65
52 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", 66 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
53 dssdev->panel.timings.x_res, 67 dssdev->panel.timings.x_res,
54 dssdev->panel.timings.y_res); 68 dssdev->panel.timings.y_res);
69
70 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
71
55 return 0; 72 return 0;
56} 73}
57 74
@@ -228,6 +245,8 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
228 goto err; 245 goto err;
229 } 246 }
230 247
248 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
249
231 r = omapdss_hdmi_display_enable(dssdev); 250 r = omapdss_hdmi_display_enable(dssdev);
232 if (r) { 251 if (r) {
233 DSSERR("failed to power on\n"); 252 DSSERR("failed to power on\n");
@@ -336,8 +355,8 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
336 */ 355 */
337 hdmi_panel_audio_disable(dssdev); 356 hdmi_panel_audio_disable(dssdev);
338 357
358 omapdss_hdmi_display_set_timing(dssdev, timings);
339 dssdev->panel.timings = *timings; 359 dssdev->panel.timings = *timings;
340 omapdss_hdmi_display_set_timing(dssdev);
341 360
342 mutex_unlock(&hdmi.lock); 361 mutex_unlock(&hdmi.lock);
343} 362}
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
new file mode 100644
index 000000000000..9a2fb59b6f89
--- /dev/null
+++ b/drivers/video/omap2/dss/manager-sysfs.c
@@ -0,0 +1,512 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
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#define DSS_SUBSYS_NAME "MANAGER"
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/jiffies.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
37}
38
39static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 struct omap_dss_device *dssdev = mgr->get_device(mgr);
42
43 return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
44 dssdev->name : "<none>");
45}
46
47static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
48 const char *buf, size_t size)
49{
50 int r = 0;
51 size_t len = size;
52 struct omap_dss_device *dssdev = NULL;
53
54 int match(struct omap_dss_device *dssdev, void *data)
55 {
56 const char *str = data;
57 return sysfs_streq(dssdev->name, str);
58 }
59
60 if (buf[size-1] == '\n')
61 --len;
62
63 if (len > 0)
64 dssdev = omap_dss_find_device((void *)buf, match);
65
66 if (len > 0 && dssdev == NULL)
67 return -EINVAL;
68
69 if (dssdev)
70 DSSDBG("display %s found\n", dssdev->name);
71
72 if (mgr->output) {
73 r = mgr->unset_output(mgr);
74 if (r) {
75 DSSERR("failed to unset current output\n");
76 goto put_device;
77 }
78 }
79
80 if (dssdev) {
81 struct omap_dss_output *out = dssdev->output;
82
83 /*
84 * a registered device should have an output connected to it
85 * already
86 */
87 if (!out) {
88 DSSERR("device has no output connected to it\n");
89 goto put_device;
90 }
91
92 r = mgr->set_output(mgr, out);
93 if (r) {
94 DSSERR("failed to set manager output\n");
95 goto put_device;
96 }
97
98 r = mgr->apply(mgr);
99 if (r) {
100 DSSERR("failed to apply dispc config\n");
101 goto put_device;
102 }
103 }
104
105put_device:
106 if (dssdev)
107 omap_dss_put_device(dssdev);
108
109 return r ? r : size;
110}
111
112static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
113 char *buf)
114{
115 struct omap_overlay_manager_info info;
116
117 mgr->get_manager_info(mgr, &info);
118
119 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
120}
121
122static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
123 const char *buf, size_t size)
124{
125 struct omap_overlay_manager_info info;
126 u32 color;
127 int r;
128
129 r = kstrtouint(buf, 0, &color);
130 if (r)
131 return r;
132
133 mgr->get_manager_info(mgr, &info);
134
135 info.default_color = color;
136
137 r = mgr->set_manager_info(mgr, &info);
138 if (r)
139 return r;
140
141 r = mgr->apply(mgr);
142 if (r)
143 return r;
144
145 return size;
146}
147
148static const char *trans_key_type_str[] = {
149 "gfx-destination",
150 "video-source",
151};
152
153static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
154 char *buf)
155{
156 enum omap_dss_trans_key_type key_type;
157 struct omap_overlay_manager_info info;
158
159 mgr->get_manager_info(mgr, &info);
160
161 key_type = info.trans_key_type;
162 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
163
164 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
165}
166
167static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
168 const char *buf, size_t size)
169{
170 enum omap_dss_trans_key_type key_type;
171 struct omap_overlay_manager_info info;
172 int r;
173
174 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
175 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
176 if (sysfs_streq(buf, trans_key_type_str[key_type]))
177 break;
178 }
179
180 if (key_type == ARRAY_SIZE(trans_key_type_str))
181 return -EINVAL;
182
183 mgr->get_manager_info(mgr, &info);
184
185 info.trans_key_type = key_type;
186
187 r = mgr->set_manager_info(mgr, &info);
188 if (r)
189 return r;
190
191 r = mgr->apply(mgr);
192 if (r)
193 return r;
194
195 return size;
196}
197
198static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
199 char *buf)
200{
201 struct omap_overlay_manager_info info;
202
203 mgr->get_manager_info(mgr, &info);
204
205 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
206}
207
208static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
209 const char *buf, size_t size)
210{
211 struct omap_overlay_manager_info info;
212 u32 key_value;
213 int r;
214
215 r = kstrtouint(buf, 0, &key_value);
216 if (r)
217 return r;
218
219 mgr->get_manager_info(mgr, &info);
220
221 info.trans_key = key_value;
222
223 r = mgr->set_manager_info(mgr, &info);
224 if (r)
225 return r;
226
227 r = mgr->apply(mgr);
228 if (r)
229 return r;
230
231 return size;
232}
233
234static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
235 char *buf)
236{
237 struct omap_overlay_manager_info info;
238
239 mgr->get_manager_info(mgr, &info);
240
241 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
242}
243
244static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
245 const char *buf, size_t size)
246{
247 struct omap_overlay_manager_info info;
248 bool enable;
249 int r;
250
251 r = strtobool(buf, &enable);
252 if (r)
253 return r;
254
255 mgr->get_manager_info(mgr, &info);
256
257 info.trans_enabled = enable;
258
259 r = mgr->set_manager_info(mgr, &info);
260 if (r)
261 return r;
262
263 r = mgr->apply(mgr);
264 if (r)
265 return r;
266
267 return size;
268}
269
270static ssize_t manager_alpha_blending_enabled_show(
271 struct omap_overlay_manager *mgr, char *buf)
272{
273 struct omap_overlay_manager_info info;
274
275 mgr->get_manager_info(mgr, &info);
276
277 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
278
279 return snprintf(buf, PAGE_SIZE, "%d\n",
280 info.partial_alpha_enabled);
281}
282
283static ssize_t manager_alpha_blending_enabled_store(
284 struct omap_overlay_manager *mgr,
285 const char *buf, size_t size)
286{
287 struct omap_overlay_manager_info info;
288 bool enable;
289 int r;
290
291 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
292
293 r = strtobool(buf, &enable);
294 if (r)
295 return r;
296
297 mgr->get_manager_info(mgr, &info);
298
299 info.partial_alpha_enabled = enable;
300
301 r = mgr->set_manager_info(mgr, &info);
302 if (r)
303 return r;
304
305 r = mgr->apply(mgr);
306 if (r)
307 return r;
308
309 return size;
310}
311
312static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
313 char *buf)
314{
315 struct omap_overlay_manager_info info;
316
317 mgr->get_manager_info(mgr, &info);
318
319 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
320}
321
322static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
323 const char *buf, size_t size)
324{
325 struct omap_overlay_manager_info info;
326 int r;
327 bool enable;
328
329 if (!dss_has_feature(FEAT_CPR))
330 return -ENODEV;
331
332 r = strtobool(buf, &enable);
333 if (r)
334 return r;
335
336 mgr->get_manager_info(mgr, &info);
337
338 if (info.cpr_enable == enable)
339 return size;
340
341 info.cpr_enable = enable;
342
343 r = mgr->set_manager_info(mgr, &info);
344 if (r)
345 return r;
346
347 r = mgr->apply(mgr);
348 if (r)
349 return r;
350
351 return size;
352}
353
354static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
355 char *buf)
356{
357 struct omap_overlay_manager_info info;
358
359 mgr->get_manager_info(mgr, &info);
360
361 return snprintf(buf, PAGE_SIZE,
362 "%d %d %d %d %d %d %d %d %d\n",
363 info.cpr_coefs.rr,
364 info.cpr_coefs.rg,
365 info.cpr_coefs.rb,
366 info.cpr_coefs.gr,
367 info.cpr_coefs.gg,
368 info.cpr_coefs.gb,
369 info.cpr_coefs.br,
370 info.cpr_coefs.bg,
371 info.cpr_coefs.bb);
372}
373
374static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
375 const char *buf, size_t size)
376{
377 struct omap_overlay_manager_info info;
378 struct omap_dss_cpr_coefs coefs;
379 int r, i;
380 s16 *arr;
381
382 if (!dss_has_feature(FEAT_CPR))
383 return -ENODEV;
384
385 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
386 &coefs.rr, &coefs.rg, &coefs.rb,
387 &coefs.gr, &coefs.gg, &coefs.gb,
388 &coefs.br, &coefs.bg, &coefs.bb) != 9)
389 return -EINVAL;
390
391 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
392 coefs.gr, coefs.gg, coefs.gb,
393 coefs.br, coefs.bg, coefs.bb };
394
395 for (i = 0; i < 9; ++i) {
396 if (arr[i] < -512 || arr[i] > 511)
397 return -EINVAL;
398 }
399
400 mgr->get_manager_info(mgr, &info);
401
402 info.cpr_coefs = coefs;
403
404 r = mgr->set_manager_info(mgr, &info);
405 if (r)
406 return r;
407
408 r = mgr->apply(mgr);
409 if (r)
410 return r;
411
412 return size;
413}
414
415struct manager_attribute {
416 struct attribute attr;
417 ssize_t (*show)(struct omap_overlay_manager *, char *);
418 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
419};
420
421#define MANAGER_ATTR(_name, _mode, _show, _store) \
422 struct manager_attribute manager_attr_##_name = \
423 __ATTR(_name, _mode, _show, _store)
424
425static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
426static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
427 manager_display_show, manager_display_store);
428static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
429 manager_default_color_show, manager_default_color_store);
430static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
431 manager_trans_key_type_show, manager_trans_key_type_store);
432static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
433 manager_trans_key_value_show, manager_trans_key_value_store);
434static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
435 manager_trans_key_enabled_show,
436 manager_trans_key_enabled_store);
437static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
438 manager_alpha_blending_enabled_show,
439 manager_alpha_blending_enabled_store);
440static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
441 manager_cpr_enable_show,
442 manager_cpr_enable_store);
443static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
444 manager_cpr_coef_show,
445 manager_cpr_coef_store);
446
447
448static struct attribute *manager_sysfs_attrs[] = {
449 &manager_attr_name.attr,
450 &manager_attr_display.attr,
451 &manager_attr_default_color.attr,
452 &manager_attr_trans_key_type.attr,
453 &manager_attr_trans_key_value.attr,
454 &manager_attr_trans_key_enabled.attr,
455 &manager_attr_alpha_blending_enabled.attr,
456 &manager_attr_cpr_enable.attr,
457 &manager_attr_cpr_coef.attr,
458 NULL
459};
460
461static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
462 char *buf)
463{
464 struct omap_overlay_manager *manager;
465 struct manager_attribute *manager_attr;
466
467 manager = container_of(kobj, struct omap_overlay_manager, kobj);
468 manager_attr = container_of(attr, struct manager_attribute, attr);
469
470 if (!manager_attr->show)
471 return -ENOENT;
472
473 return manager_attr->show(manager, buf);
474}
475
476static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
477 const char *buf, size_t size)
478{
479 struct omap_overlay_manager *manager;
480 struct manager_attribute *manager_attr;
481
482 manager = container_of(kobj, struct omap_overlay_manager, kobj);
483 manager_attr = container_of(attr, struct manager_attribute, attr);
484
485 if (!manager_attr->store)
486 return -ENOENT;
487
488 return manager_attr->store(manager, buf, size);
489}
490
491static const struct sysfs_ops manager_sysfs_ops = {
492 .show = manager_attr_show,
493 .store = manager_attr_store,
494};
495
496static struct kobj_type manager_ktype = {
497 .sysfs_ops = &manager_sysfs_ops,
498 .default_attrs = manager_sysfs_attrs,
499};
500
501int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
502 struct platform_device *pdev)
503{
504 return kobject_init_and_add(&mgr->kobj, &manager_ktype,
505 &pdev->dev.kobj, "manager%d", mgr->id);
506}
507
508void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
509{
510 kobject_del(&mgr->kobj);
511 kobject_put(&mgr->kobj);
512}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 53710fadc82d..c54d2f620ce3 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -36,463 +36,15 @@
36static int num_managers; 36static int num_managers;
37static struct omap_overlay_manager *managers; 37static struct omap_overlay_manager *managers;
38 38
39static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 39static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
40{ 40{
41 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name); 41 return mgr->output ? mgr->output->device : NULL;
42} 42}
43 43
44static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
45{
46 return snprintf(buf, PAGE_SIZE, "%s\n",
47 mgr->device ? mgr->device->name : "<none>");
48}
49
50static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
51 const char *buf, size_t size)
52{
53 int r = 0;
54 size_t len = size;
55 struct omap_dss_device *dssdev = NULL;
56
57 int match(struct omap_dss_device *dssdev, void *data)
58 {
59 const char *str = data;
60 return sysfs_streq(dssdev->name, str);
61 }
62
63 if (buf[size-1] == '\n')
64 --len;
65
66 if (len > 0)
67 dssdev = omap_dss_find_device((void *)buf, match);
68
69 if (len > 0 && dssdev == NULL)
70 return -EINVAL;
71
72 if (dssdev)
73 DSSDBG("display %s found\n", dssdev->name);
74
75 if (mgr->device) {
76 r = mgr->unset_device(mgr);
77 if (r) {
78 DSSERR("failed to unset display\n");
79 goto put_device;
80 }
81 }
82
83 if (dssdev) {
84 r = mgr->set_device(mgr, dssdev);
85 if (r) {
86 DSSERR("failed to set manager\n");
87 goto put_device;
88 }
89
90 r = mgr->apply(mgr);
91 if (r) {
92 DSSERR("failed to apply dispc config\n");
93 goto put_device;
94 }
95 }
96
97put_device:
98 if (dssdev)
99 omap_dss_put_device(dssdev);
100
101 return r ? r : size;
102}
103
104static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
105 char *buf)
106{
107 struct omap_overlay_manager_info info;
108
109 mgr->get_manager_info(mgr, &info);
110
111 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
112}
113
114static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
115 const char *buf, size_t size)
116{
117 struct omap_overlay_manager_info info;
118 u32 color;
119 int r;
120
121 r = kstrtouint(buf, 0, &color);
122 if (r)
123 return r;
124
125 mgr->get_manager_info(mgr, &info);
126
127 info.default_color = color;
128
129 r = mgr->set_manager_info(mgr, &info);
130 if (r)
131 return r;
132
133 r = mgr->apply(mgr);
134 if (r)
135 return r;
136
137 return size;
138}
139
140static const char *trans_key_type_str[] = {
141 "gfx-destination",
142 "video-source",
143};
144
145static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
146 char *buf)
147{
148 enum omap_dss_trans_key_type key_type;
149 struct omap_overlay_manager_info info;
150
151 mgr->get_manager_info(mgr, &info);
152
153 key_type = info.trans_key_type;
154 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
155
156 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
157}
158
159static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
160 const char *buf, size_t size)
161{
162 enum omap_dss_trans_key_type key_type;
163 struct omap_overlay_manager_info info;
164 int r;
165
166 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
167 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
168 if (sysfs_streq(buf, trans_key_type_str[key_type]))
169 break;
170 }
171
172 if (key_type == ARRAY_SIZE(trans_key_type_str))
173 return -EINVAL;
174
175 mgr->get_manager_info(mgr, &info);
176
177 info.trans_key_type = key_type;
178
179 r = mgr->set_manager_info(mgr, &info);
180 if (r)
181 return r;
182
183 r = mgr->apply(mgr);
184 if (r)
185 return r;
186
187 return size;
188}
189
190static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
191 char *buf)
192{
193 struct omap_overlay_manager_info info;
194
195 mgr->get_manager_info(mgr, &info);
196
197 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
198}
199
200static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
201 const char *buf, size_t size)
202{
203 struct omap_overlay_manager_info info;
204 u32 key_value;
205 int r;
206
207 r = kstrtouint(buf, 0, &key_value);
208 if (r)
209 return r;
210
211 mgr->get_manager_info(mgr, &info);
212
213 info.trans_key = key_value;
214
215 r = mgr->set_manager_info(mgr, &info);
216 if (r)
217 return r;
218
219 r = mgr->apply(mgr);
220 if (r)
221 return r;
222
223 return size;
224}
225
226static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
227 char *buf)
228{
229 struct omap_overlay_manager_info info;
230
231 mgr->get_manager_info(mgr, &info);
232
233 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
234}
235
236static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
237 const char *buf, size_t size)
238{
239 struct omap_overlay_manager_info info;
240 bool enable;
241 int r;
242
243 r = strtobool(buf, &enable);
244 if (r)
245 return r;
246
247 mgr->get_manager_info(mgr, &info);
248
249 info.trans_enabled = enable;
250
251 r = mgr->set_manager_info(mgr, &info);
252 if (r)
253 return r;
254
255 r = mgr->apply(mgr);
256 if (r)
257 return r;
258
259 return size;
260}
261
262static ssize_t manager_alpha_blending_enabled_show(
263 struct omap_overlay_manager *mgr, char *buf)
264{
265 struct omap_overlay_manager_info info;
266
267 mgr->get_manager_info(mgr, &info);
268
269 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
270
271 return snprintf(buf, PAGE_SIZE, "%d\n",
272 info.partial_alpha_enabled);
273}
274
275static ssize_t manager_alpha_blending_enabled_store(
276 struct omap_overlay_manager *mgr,
277 const char *buf, size_t size)
278{
279 struct omap_overlay_manager_info info;
280 bool enable;
281 int r;
282
283 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
284
285 r = strtobool(buf, &enable);
286 if (r)
287 return r;
288
289 mgr->get_manager_info(mgr, &info);
290
291 info.partial_alpha_enabled = enable;
292
293 r = mgr->set_manager_info(mgr, &info);
294 if (r)
295 return r;
296
297 r = mgr->apply(mgr);
298 if (r)
299 return r;
300
301 return size;
302}
303
304static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
305 char *buf)
306{
307 struct omap_overlay_manager_info info;
308
309 mgr->get_manager_info(mgr, &info);
310
311 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
312}
313
314static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
315 const char *buf, size_t size)
316{
317 struct omap_overlay_manager_info info;
318 int r;
319 bool enable;
320
321 if (!dss_has_feature(FEAT_CPR))
322 return -ENODEV;
323
324 r = strtobool(buf, &enable);
325 if (r)
326 return r;
327
328 mgr->get_manager_info(mgr, &info);
329
330 if (info.cpr_enable == enable)
331 return size;
332
333 info.cpr_enable = enable;
334
335 r = mgr->set_manager_info(mgr, &info);
336 if (r)
337 return r;
338
339 r = mgr->apply(mgr);
340 if (r)
341 return r;
342
343 return size;
344}
345
346static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
347 char *buf)
348{
349 struct omap_overlay_manager_info info;
350
351 mgr->get_manager_info(mgr, &info);
352
353 return snprintf(buf, PAGE_SIZE,
354 "%d %d %d %d %d %d %d %d %d\n",
355 info.cpr_coefs.rr,
356 info.cpr_coefs.rg,
357 info.cpr_coefs.rb,
358 info.cpr_coefs.gr,
359 info.cpr_coefs.gg,
360 info.cpr_coefs.gb,
361 info.cpr_coefs.br,
362 info.cpr_coefs.bg,
363 info.cpr_coefs.bb);
364}
365
366static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
367 const char *buf, size_t size)
368{
369 struct omap_overlay_manager_info info;
370 struct omap_dss_cpr_coefs coefs;
371 int r, i;
372 s16 *arr;
373
374 if (!dss_has_feature(FEAT_CPR))
375 return -ENODEV;
376
377 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
378 &coefs.rr, &coefs.rg, &coefs.rb,
379 &coefs.gr, &coefs.gg, &coefs.gb,
380 &coefs.br, &coefs.bg, &coefs.bb) != 9)
381 return -EINVAL;
382
383 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
384 coefs.gr, coefs.gg, coefs.gb,
385 coefs.br, coefs.bg, coefs.bb };
386
387 for (i = 0; i < 9; ++i) {
388 if (arr[i] < -512 || arr[i] > 511)
389 return -EINVAL;
390 }
391
392 mgr->get_manager_info(mgr, &info);
393
394 info.cpr_coefs = coefs;
395
396 r = mgr->set_manager_info(mgr, &info);
397 if (r)
398 return r;
399
400 r = mgr->apply(mgr);
401 if (r)
402 return r;
403
404 return size;
405}
406
407struct manager_attribute {
408 struct attribute attr;
409 ssize_t (*show)(struct omap_overlay_manager *, char *);
410 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
411};
412
413#define MANAGER_ATTR(_name, _mode, _show, _store) \
414 struct manager_attribute manager_attr_##_name = \
415 __ATTR(_name, _mode, _show, _store)
416
417static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
418static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
419 manager_display_show, manager_display_store);
420static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
421 manager_default_color_show, manager_default_color_store);
422static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
423 manager_trans_key_type_show, manager_trans_key_type_store);
424static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
425 manager_trans_key_value_show, manager_trans_key_value_store);
426static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
427 manager_trans_key_enabled_show,
428 manager_trans_key_enabled_store);
429static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
430 manager_alpha_blending_enabled_show,
431 manager_alpha_blending_enabled_store);
432static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
433 manager_cpr_enable_show,
434 manager_cpr_enable_store);
435static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
436 manager_cpr_coef_show,
437 manager_cpr_coef_store);
438
439
440static struct attribute *manager_sysfs_attrs[] = {
441 &manager_attr_name.attr,
442 &manager_attr_display.attr,
443 &manager_attr_default_color.attr,
444 &manager_attr_trans_key_type.attr,
445 &manager_attr_trans_key_value.attr,
446 &manager_attr_trans_key_enabled.attr,
447 &manager_attr_alpha_blending_enabled.attr,
448 &manager_attr_cpr_enable.attr,
449 &manager_attr_cpr_coef.attr,
450 NULL
451};
452
453static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
454 char *buf)
455{
456 struct omap_overlay_manager *manager;
457 struct manager_attribute *manager_attr;
458
459 manager = container_of(kobj, struct omap_overlay_manager, kobj);
460 manager_attr = container_of(attr, struct manager_attribute, attr);
461
462 if (!manager_attr->show)
463 return -ENOENT;
464
465 return manager_attr->show(manager, buf);
466}
467
468static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
469 const char *buf, size_t size)
470{
471 struct omap_overlay_manager *manager;
472 struct manager_attribute *manager_attr;
473
474 manager = container_of(kobj, struct omap_overlay_manager, kobj);
475 manager_attr = container_of(attr, struct manager_attribute, attr);
476
477 if (!manager_attr->store)
478 return -ENOENT;
479
480 return manager_attr->store(manager, buf, size);
481}
482
483static const struct sysfs_ops manager_sysfs_ops = {
484 .show = manager_attr_show,
485 .store = manager_attr_store,
486};
487
488static struct kobj_type manager_ktype = {
489 .sysfs_ops = &manager_sysfs_ops,
490 .default_attrs = manager_sysfs_attrs,
491};
492
493static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 44static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
494{ 45{
495 unsigned long timeout = msecs_to_jiffies(500); 46 unsigned long timeout = msecs_to_jiffies(500);
47 struct omap_dss_device *dssdev = mgr->get_device(mgr);
496 u32 irq; 48 u32 irq;
497 int r; 49 int r;
498 50
@@ -500,9 +52,9 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
500 if (r) 52 if (r)
501 return r; 53 return r;
502 54
503 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) 55 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
504 irq = DISPC_IRQ_EVSYNC_ODD; 56 irq = DISPC_IRQ_EVSYNC_ODD;
505 else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) 57 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
506 irq = DISPC_IRQ_EVSYNC_EVEN; 58 irq = DISPC_IRQ_EVSYNC_EVEN;
507 else 59 else
508 irq = dispc_mgr_get_vsync_irq(mgr->id); 60 irq = dispc_mgr_get_vsync_irq(mgr->id);
@@ -547,23 +99,24 @@ int dss_init_overlay_managers(struct platform_device *pdev)
547 break; 99 break;
548 } 100 }
549 101
550 mgr->set_device = &dss_mgr_set_device; 102 mgr->set_output = &dss_mgr_set_output;
551 mgr->unset_device = &dss_mgr_unset_device; 103 mgr->unset_output = &dss_mgr_unset_output;
552 mgr->apply = &omap_dss_mgr_apply; 104 mgr->apply = &omap_dss_mgr_apply;
553 mgr->set_manager_info = &dss_mgr_set_info; 105 mgr->set_manager_info = &dss_mgr_set_info;
554 mgr->get_manager_info = &dss_mgr_get_info; 106 mgr->get_manager_info = &dss_mgr_get_info;
555 mgr->wait_for_go = &dss_mgr_wait_for_go; 107 mgr->wait_for_go = &dss_mgr_wait_for_go;
556 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; 108 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
109 mgr->get_device = &dss_mgr_get_device;
557 110
558 mgr->caps = 0; 111 mgr->caps = 0;
559 mgr->supported_displays = 112 mgr->supported_displays =
560 dss_feat_get_supported_displays(mgr->id); 113 dss_feat_get_supported_displays(mgr->id);
114 mgr->supported_outputs =
115 dss_feat_get_supported_outputs(mgr->id);
561 116
562 INIT_LIST_HEAD(&mgr->overlays); 117 INIT_LIST_HEAD(&mgr->overlays);
563 118
564 r = kobject_init_and_add(&mgr->kobj, &manager_ktype, 119 r = dss_manager_kobj_init(mgr, pdev);
565 &pdev->dev.kobj, "manager%d", i);
566
567 if (r) 120 if (r)
568 DSSERR("failed to create sysfs file\n"); 121 DSSERR("failed to create sysfs file\n");
569 } 122 }
@@ -577,9 +130,7 @@ void dss_uninit_overlay_managers(struct platform_device *pdev)
577 130
578 for (i = 0; i < num_managers; ++i) { 131 for (i = 0; i < num_managers; ++i) {
579 struct omap_overlay_manager *mgr = &managers[i]; 132 struct omap_overlay_manager *mgr = &managers[i];
580 133 dss_manager_kobj_uninit(mgr);
581 kobject_del(&mgr->kobj);
582 kobject_put(&mgr->kobj);
583 } 134 }
584 135
585 kfree(managers); 136 kfree(managers);
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
new file mode 100644
index 000000000000..813f26682b7a
--- /dev/null
+++ b/drivers/video/omap2/dss/output.c
@@ -0,0 +1,148 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Ltd
3 * Author: Archit Taneja <archit@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23#include <video/omapdss.h>
24
25#include "dss.h"
26
27static LIST_HEAD(output_list);
28static DEFINE_MUTEX(output_lock);
29
30int omapdss_output_set_device(struct omap_dss_output *out,
31 struct omap_dss_device *dssdev)
32{
33 int r;
34
35 mutex_lock(&output_lock);
36
37 if (out->device) {
38 DSSERR("output already has device %s connected to it\n",
39 out->device->name);
40 r = -EINVAL;
41 goto err;
42 }
43
44 if (out->type != dssdev->type) {
45 DSSERR("output type and display type don't match\n");
46 r = -EINVAL;
47 goto err;
48 }
49
50 out->device = dssdev;
51 dssdev->output = out;
52
53 mutex_unlock(&output_lock);
54
55 return 0;
56err:
57 mutex_unlock(&output_lock);
58
59 return r;
60}
61EXPORT_SYMBOL(omapdss_output_set_device);
62
63int omapdss_output_unset_device(struct omap_dss_output *out)
64{
65 int r;
66
67 mutex_lock(&output_lock);
68
69 if (!out->device) {
70 DSSERR("output doesn't have a device connected to it\n");
71 r = -EINVAL;
72 goto err;
73 }
74
75 if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
76 DSSERR("device %s is not disabled, cannot unset device\n",
77 out->device->name);
78 r = -EINVAL;
79 goto err;
80 }
81
82 out->device->output = NULL;
83 out->device = NULL;
84
85 mutex_unlock(&output_lock);
86
87 return 0;
88err:
89 mutex_unlock(&output_lock);
90
91 return r;
92}
93EXPORT_SYMBOL(omapdss_output_unset_device);
94
95void dss_register_output(struct omap_dss_output *out)
96{
97 list_add_tail(&out->list, &output_list);
98}
99
100void dss_unregister_output(struct omap_dss_output *out)
101{
102 list_del(&out->list);
103}
104
105struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
106{
107 struct omap_dss_output *out;
108
109 list_for_each_entry(out, &output_list, list) {
110 if (out->id == id)
111 return out;
112 }
113
114 return NULL;
115}
116
117struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev)
118{
119 struct omap_dss_output *out = NULL;
120 enum omap_dss_output_id id;
121
122 switch (dssdev->type) {
123 case OMAP_DISPLAY_TYPE_DPI:
124 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DPI);
125 break;
126 case OMAP_DISPLAY_TYPE_DBI:
127 out = omap_dss_get_output(OMAP_DSS_OUTPUT_DBI);
128 break;
129 case OMAP_DISPLAY_TYPE_SDI:
130 out = omap_dss_get_output(OMAP_DSS_OUTPUT_SDI);
131 break;
132 case OMAP_DISPLAY_TYPE_VENC:
133 out = omap_dss_get_output(OMAP_DSS_OUTPUT_VENC);
134 break;
135 case OMAP_DISPLAY_TYPE_HDMI:
136 out = omap_dss_get_output(OMAP_DSS_OUTPUT_HDMI);
137 break;
138 case OMAP_DISPLAY_TYPE_DSI:
139 id = dssdev->phy.dsi.module == 0 ? OMAP_DSS_OUTPUT_DSI1 :
140 OMAP_DSS_OUTPUT_DSI2;
141 out = omap_dss_get_output(id);
142 break;
143 default:
144 break;
145 }
146
147 return out;
148}
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
new file mode 100644
index 000000000000..4cc5ddebfb34
--- /dev/null
+++ b/drivers/video/omap2/dss/overlay-sysfs.c
@@ -0,0 +1,456 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
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#define DSS_SUBSYS_NAME "OVERLAY"
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/sysfs.h>
26#include <linux/kobject.h>
27#include <linux/platform_device.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
37}
38
39static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n",
42 ovl->manager ? ovl->manager->name : "<none>");
43}
44
45static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
46 size_t size)
47{
48 int i, r;
49 struct omap_overlay_manager *mgr = NULL;
50 struct omap_overlay_manager *old_mgr;
51 int len = size;
52
53 if (buf[size-1] == '\n')
54 --len;
55
56 if (len > 0) {
57 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
58 mgr = omap_dss_get_overlay_manager(i);
59
60 if (sysfs_streq(buf, mgr->name))
61 break;
62
63 mgr = NULL;
64 }
65 }
66
67 if (len > 0 && mgr == NULL)
68 return -EINVAL;
69
70 if (mgr)
71 DSSDBG("manager %s found\n", mgr->name);
72
73 if (mgr == ovl->manager)
74 return size;
75
76 old_mgr = ovl->manager;
77
78 r = dispc_runtime_get();
79 if (r)
80 return r;
81
82 /* detach old manager */
83 if (old_mgr) {
84 r = ovl->unset_manager(ovl);
85 if (r) {
86 DSSERR("detach failed\n");
87 goto err;
88 }
89
90 r = old_mgr->apply(old_mgr);
91 if (r)
92 goto err;
93 }
94
95 if (mgr) {
96 r = ovl->set_manager(ovl, mgr);
97 if (r) {
98 DSSERR("Failed to attach overlay\n");
99 goto err;
100 }
101
102 r = mgr->apply(mgr);
103 if (r)
104 goto err;
105 }
106
107 dispc_runtime_put();
108
109 return size;
110
111err:
112 dispc_runtime_put();
113 return r;
114}
115
116static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
117{
118 struct omap_overlay_info info;
119
120 ovl->get_overlay_info(ovl, &info);
121
122 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
123 info.width, info.height);
124}
125
126static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
127{
128 struct omap_overlay_info info;
129
130 ovl->get_overlay_info(ovl, &info);
131
132 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
133}
134
135static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
142 info.pos_x, info.pos_y);
143}
144
145static ssize_t overlay_position_store(struct omap_overlay *ovl,
146 const char *buf, size_t size)
147{
148 int r;
149 char *last;
150 struct omap_overlay_info info;
151
152 ovl->get_overlay_info(ovl, &info);
153
154 info.pos_x = simple_strtoul(buf, &last, 10);
155 ++last;
156 if (last - buf >= size)
157 return -EINVAL;
158
159 info.pos_y = simple_strtoul(last, &last, 10);
160
161 r = ovl->set_overlay_info(ovl, &info);
162 if (r)
163 return r;
164
165 if (ovl->manager) {
166 r = ovl->manager->apply(ovl->manager);
167 if (r)
168 return r;
169 }
170
171 return size;
172}
173
174static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
175{
176 struct omap_overlay_info info;
177
178 ovl->get_overlay_info(ovl, &info);
179
180 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
181 info.out_width, info.out_height);
182}
183
184static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
185 const char *buf, size_t size)
186{
187 int r;
188 char *last;
189 struct omap_overlay_info info;
190
191 ovl->get_overlay_info(ovl, &info);
192
193 info.out_width = simple_strtoul(buf, &last, 10);
194 ++last;
195 if (last - buf >= size)
196 return -EINVAL;
197
198 info.out_height = simple_strtoul(last, &last, 10);
199
200 r = ovl->set_overlay_info(ovl, &info);
201 if (r)
202 return r;
203
204 if (ovl->manager) {
205 r = ovl->manager->apply(ovl->manager);
206 if (r)
207 return r;
208 }
209
210 return size;
211}
212
213static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
214{
215 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
216}
217
218static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
219 size_t size)
220{
221 int r;
222 bool enable;
223
224 r = strtobool(buf, &enable);
225 if (r)
226 return r;
227
228 if (enable)
229 r = ovl->enable(ovl);
230 else
231 r = ovl->disable(ovl);
232
233 if (r)
234 return r;
235
236 return size;
237}
238
239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240{
241 struct omap_overlay_info info;
242
243 ovl->get_overlay_info(ovl, &info);
244
245 return snprintf(buf, PAGE_SIZE, "%d\n",
246 info.global_alpha);
247}
248
249static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
250 const char *buf, size_t size)
251{
252 int r;
253 u8 alpha;
254 struct omap_overlay_info info;
255
256 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
257 return -ENODEV;
258
259 r = kstrtou8(buf, 0, &alpha);
260 if (r)
261 return r;
262
263 ovl->get_overlay_info(ovl, &info);
264
265 info.global_alpha = alpha;
266
267 r = ovl->set_overlay_info(ovl, &info);
268 if (r)
269 return r;
270
271 if (ovl->manager) {
272 r = ovl->manager->apply(ovl->manager);
273 if (r)
274 return r;
275 }
276
277 return size;
278}
279
280static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
281 char *buf)
282{
283 struct omap_overlay_info info;
284
285 ovl->get_overlay_info(ovl, &info);
286
287 return snprintf(buf, PAGE_SIZE, "%d\n",
288 info.pre_mult_alpha);
289}
290
291static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
292 const char *buf, size_t size)
293{
294 int r;
295 u8 alpha;
296 struct omap_overlay_info info;
297
298 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
299 return -ENODEV;
300
301 r = kstrtou8(buf, 0, &alpha);
302 if (r)
303 return r;
304
305 ovl->get_overlay_info(ovl, &info);
306
307 info.pre_mult_alpha = alpha;
308
309 r = ovl->set_overlay_info(ovl, &info);
310 if (r)
311 return r;
312
313 if (ovl->manager) {
314 r = ovl->manager->apply(ovl->manager);
315 if (r)
316 return r;
317 }
318
319 return size;
320}
321
322static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
323{
324 struct omap_overlay_info info;
325
326 ovl->get_overlay_info(ovl, &info);
327
328 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
329}
330
331static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
332 const char *buf, size_t size)
333{
334 int r;
335 u8 zorder;
336 struct omap_overlay_info info;
337
338 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
339 return -ENODEV;
340
341 r = kstrtou8(buf, 0, &zorder);
342 if (r)
343 return r;
344
345 ovl->get_overlay_info(ovl, &info);
346
347 info.zorder = zorder;
348
349 r = ovl->set_overlay_info(ovl, &info);
350 if (r)
351 return r;
352
353 if (ovl->manager) {
354 r = ovl->manager->apply(ovl->manager);
355 if (r)
356 return r;
357 }
358
359 return size;
360}
361
362struct overlay_attribute {
363 struct attribute attr;
364 ssize_t (*show)(struct omap_overlay *, char *);
365 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
366};
367
368#define OVERLAY_ATTR(_name, _mode, _show, _store) \
369 struct overlay_attribute overlay_attr_##_name = \
370 __ATTR(_name, _mode, _show, _store)
371
372static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
373static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
374 overlay_manager_show, overlay_manager_store);
375static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
376static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
377static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
378 overlay_position_show, overlay_position_store);
379static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
380 overlay_output_size_show, overlay_output_size_store);
381static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
382 overlay_enabled_show, overlay_enabled_store);
383static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
384 overlay_global_alpha_show, overlay_global_alpha_store);
385static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
386 overlay_pre_mult_alpha_show,
387 overlay_pre_mult_alpha_store);
388static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
389 overlay_zorder_show, overlay_zorder_store);
390
391static struct attribute *overlay_sysfs_attrs[] = {
392 &overlay_attr_name.attr,
393 &overlay_attr_manager.attr,
394 &overlay_attr_input_size.attr,
395 &overlay_attr_screen_width.attr,
396 &overlay_attr_position.attr,
397 &overlay_attr_output_size.attr,
398 &overlay_attr_enabled.attr,
399 &overlay_attr_global_alpha.attr,
400 &overlay_attr_pre_mult_alpha.attr,
401 &overlay_attr_zorder.attr,
402 NULL
403};
404
405static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
406 char *buf)
407{
408 struct omap_overlay *overlay;
409 struct overlay_attribute *overlay_attr;
410
411 overlay = container_of(kobj, struct omap_overlay, kobj);
412 overlay_attr = container_of(attr, struct overlay_attribute, attr);
413
414 if (!overlay_attr->show)
415 return -ENOENT;
416
417 return overlay_attr->show(overlay, buf);
418}
419
420static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
421 const char *buf, size_t size)
422{
423 struct omap_overlay *overlay;
424 struct overlay_attribute *overlay_attr;
425
426 overlay = container_of(kobj, struct omap_overlay, kobj);
427 overlay_attr = container_of(attr, struct overlay_attribute, attr);
428
429 if (!overlay_attr->store)
430 return -ENOENT;
431
432 return overlay_attr->store(overlay, buf, size);
433}
434
435static const struct sysfs_ops overlay_sysfs_ops = {
436 .show = overlay_attr_show,
437 .store = overlay_attr_store,
438};
439
440static struct kobj_type overlay_ktype = {
441 .sysfs_ops = &overlay_sysfs_ops,
442 .default_attrs = overlay_sysfs_attrs,
443};
444
445int dss_overlay_kobj_init(struct omap_overlay *ovl,
446 struct platform_device *pdev)
447{
448 return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
449 &pdev->dev.kobj, "overlay%d", ovl->id);
450}
451
452void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
453{
454 kobject_del(&ovl->kobj);
455 kobject_put(&ovl->kobj);
456}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 952c6fad9a81..45f4994bc6b0 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -26,13 +26,11 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/sysfs.h> 28#include <linux/sysfs.h>
29#include <linux/kobject.h>
30#include <linux/platform_device.h> 29#include <linux/platform_device.h>
31#include <linux/delay.h> 30#include <linux/delay.h>
32#include <linux/slab.h> 31#include <linux/slab.h>
33 32
34#include <video/omapdss.h> 33#include <video/omapdss.h>
35#include <plat/cpu.h>
36 34
37#include "dss.h" 35#include "dss.h"
38#include "dss_features.h" 36#include "dss_features.h"
@@ -40,417 +38,13 @@
40static int num_overlays; 38static int num_overlays;
41static struct omap_overlay *overlays; 39static struct omap_overlay *overlays;
42 40
43static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) 41static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
44{ 42{
45 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); 43 return ovl->manager ?
44 (ovl->manager->output ? ovl->manager->output->device : NULL) :
45 NULL;
46} 46}
47 47
48static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
49{
50 return snprintf(buf, PAGE_SIZE, "%s\n",
51 ovl->manager ? ovl->manager->name : "<none>");
52}
53
54static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
55 size_t size)
56{
57 int i, r;
58 struct omap_overlay_manager *mgr = NULL;
59 struct omap_overlay_manager *old_mgr;
60 int len = size;
61
62 if (buf[size-1] == '\n')
63 --len;
64
65 if (len > 0) {
66 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
67 mgr = omap_dss_get_overlay_manager(i);
68
69 if (sysfs_streq(buf, mgr->name))
70 break;
71
72 mgr = NULL;
73 }
74 }
75
76 if (len > 0 && mgr == NULL)
77 return -EINVAL;
78
79 if (mgr)
80 DSSDBG("manager %s found\n", mgr->name);
81
82 if (mgr == ovl->manager)
83 return size;
84
85 old_mgr = ovl->manager;
86
87 r = dispc_runtime_get();
88 if (r)
89 return r;
90
91 /* detach old manager */
92 if (old_mgr) {
93 r = ovl->unset_manager(ovl);
94 if (r) {
95 DSSERR("detach failed\n");
96 goto err;
97 }
98
99 r = old_mgr->apply(old_mgr);
100 if (r)
101 goto err;
102 }
103
104 if (mgr) {
105 r = ovl->set_manager(ovl, mgr);
106 if (r) {
107 DSSERR("Failed to attach overlay\n");
108 goto err;
109 }
110
111 r = mgr->apply(mgr);
112 if (r)
113 goto err;
114 }
115
116 dispc_runtime_put();
117
118 return size;
119
120err:
121 dispc_runtime_put();
122 return r;
123}
124
125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
126{
127 struct omap_overlay_info info;
128
129 ovl->get_overlay_info(ovl, &info);
130
131 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
132 info.width, info.height);
133}
134
135static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
142}
143
144static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
145{
146 struct omap_overlay_info info;
147
148 ovl->get_overlay_info(ovl, &info);
149
150 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
151 info.pos_x, info.pos_y);
152}
153
154static ssize_t overlay_position_store(struct omap_overlay *ovl,
155 const char *buf, size_t size)
156{
157 int r;
158 char *last;
159 struct omap_overlay_info info;
160
161 ovl->get_overlay_info(ovl, &info);
162
163 info.pos_x = simple_strtoul(buf, &last, 10);
164 ++last;
165 if (last - buf >= size)
166 return -EINVAL;
167
168 info.pos_y = simple_strtoul(last, &last, 10);
169
170 r = ovl->set_overlay_info(ovl, &info);
171 if (r)
172 return r;
173
174 if (ovl->manager) {
175 r = ovl->manager->apply(ovl->manager);
176 if (r)
177 return r;
178 }
179
180 return size;
181}
182
183static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
184{
185 struct omap_overlay_info info;
186
187 ovl->get_overlay_info(ovl, &info);
188
189 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
190 info.out_width, info.out_height);
191}
192
193static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
194 const char *buf, size_t size)
195{
196 int r;
197 char *last;
198 struct omap_overlay_info info;
199
200 ovl->get_overlay_info(ovl, &info);
201
202 info.out_width = simple_strtoul(buf, &last, 10);
203 ++last;
204 if (last - buf >= size)
205 return -EINVAL;
206
207 info.out_height = simple_strtoul(last, &last, 10);
208
209 r = ovl->set_overlay_info(ovl, &info);
210 if (r)
211 return r;
212
213 if (ovl->manager) {
214 r = ovl->manager->apply(ovl->manager);
215 if (r)
216 return r;
217 }
218
219 return size;
220}
221
222static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
223{
224 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
225}
226
227static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
228 size_t size)
229{
230 int r;
231 bool enable;
232
233 r = strtobool(buf, &enable);
234 if (r)
235 return r;
236
237 if (enable)
238 r = ovl->enable(ovl);
239 else
240 r = ovl->disable(ovl);
241
242 if (r)
243 return r;
244
245 return size;
246}
247
248static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
249{
250 struct omap_overlay_info info;
251
252 ovl->get_overlay_info(ovl, &info);
253
254 return snprintf(buf, PAGE_SIZE, "%d\n",
255 info.global_alpha);
256}
257
258static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
259 const char *buf, size_t size)
260{
261 int r;
262 u8 alpha;
263 struct omap_overlay_info info;
264
265 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
266 return -ENODEV;
267
268 r = kstrtou8(buf, 0, &alpha);
269 if (r)
270 return r;
271
272 ovl->get_overlay_info(ovl, &info);
273
274 info.global_alpha = alpha;
275
276 r = ovl->set_overlay_info(ovl, &info);
277 if (r)
278 return r;
279
280 if (ovl->manager) {
281 r = ovl->manager->apply(ovl->manager);
282 if (r)
283 return r;
284 }
285
286 return size;
287}
288
289static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
290 char *buf)
291{
292 struct omap_overlay_info info;
293
294 ovl->get_overlay_info(ovl, &info);
295
296 return snprintf(buf, PAGE_SIZE, "%d\n",
297 info.pre_mult_alpha);
298}
299
300static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
301 const char *buf, size_t size)
302{
303 int r;
304 u8 alpha;
305 struct omap_overlay_info info;
306
307 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
308 return -ENODEV;
309
310 r = kstrtou8(buf, 0, &alpha);
311 if (r)
312 return r;
313
314 ovl->get_overlay_info(ovl, &info);
315
316 info.pre_mult_alpha = alpha;
317
318 r = ovl->set_overlay_info(ovl, &info);
319 if (r)
320 return r;
321
322 if (ovl->manager) {
323 r = ovl->manager->apply(ovl->manager);
324 if (r)
325 return r;
326 }
327
328 return size;
329}
330
331static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
332{
333 struct omap_overlay_info info;
334
335 ovl->get_overlay_info(ovl, &info);
336
337 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
338}
339
340static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
341 const char *buf, size_t size)
342{
343 int r;
344 u8 zorder;
345 struct omap_overlay_info info;
346
347 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
348 return -ENODEV;
349
350 r = kstrtou8(buf, 0, &zorder);
351 if (r)
352 return r;
353
354 ovl->get_overlay_info(ovl, &info);
355
356 info.zorder = zorder;
357
358 r = ovl->set_overlay_info(ovl, &info);
359 if (r)
360 return r;
361
362 if (ovl->manager) {
363 r = ovl->manager->apply(ovl->manager);
364 if (r)
365 return r;
366 }
367
368 return size;
369}
370
371struct overlay_attribute {
372 struct attribute attr;
373 ssize_t (*show)(struct omap_overlay *, char *);
374 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
375};
376
377#define OVERLAY_ATTR(_name, _mode, _show, _store) \
378 struct overlay_attribute overlay_attr_##_name = \
379 __ATTR(_name, _mode, _show, _store)
380
381static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
382static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
383 overlay_manager_show, overlay_manager_store);
384static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
385static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
386static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
387 overlay_position_show, overlay_position_store);
388static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
389 overlay_output_size_show, overlay_output_size_store);
390static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
391 overlay_enabled_show, overlay_enabled_store);
392static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
393 overlay_global_alpha_show, overlay_global_alpha_store);
394static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
395 overlay_pre_mult_alpha_show,
396 overlay_pre_mult_alpha_store);
397static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
398 overlay_zorder_show, overlay_zorder_store);
399
400static struct attribute *overlay_sysfs_attrs[] = {
401 &overlay_attr_name.attr,
402 &overlay_attr_manager.attr,
403 &overlay_attr_input_size.attr,
404 &overlay_attr_screen_width.attr,
405 &overlay_attr_position.attr,
406 &overlay_attr_output_size.attr,
407 &overlay_attr_enabled.attr,
408 &overlay_attr_global_alpha.attr,
409 &overlay_attr_pre_mult_alpha.attr,
410 &overlay_attr_zorder.attr,
411 NULL
412};
413
414static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
415 char *buf)
416{
417 struct omap_overlay *overlay;
418 struct overlay_attribute *overlay_attr;
419
420 overlay = container_of(kobj, struct omap_overlay, kobj);
421 overlay_attr = container_of(attr, struct overlay_attribute, attr);
422
423 if (!overlay_attr->show)
424 return -ENOENT;
425
426 return overlay_attr->show(overlay, buf);
427}
428
429static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
430 const char *buf, size_t size)
431{
432 struct omap_overlay *overlay;
433 struct overlay_attribute *overlay_attr;
434
435 overlay = container_of(kobj, struct omap_overlay, kobj);
436 overlay_attr = container_of(attr, struct overlay_attribute, attr);
437
438 if (!overlay_attr->store)
439 return -ENOENT;
440
441 return overlay_attr->store(overlay, buf, size);
442}
443
444static const struct sysfs_ops overlay_sysfs_ops = {
445 .show = overlay_attr_show,
446 .store = overlay_attr_store,
447};
448
449static struct kobj_type overlay_ktype = {
450 .sysfs_ops = &overlay_sysfs_ops,
451 .default_attrs = overlay_sysfs_attrs,
452};
453
454int omap_dss_get_num_overlays(void) 48int omap_dss_get_num_overlays(void)
455{ 49{
456 return num_overlays; 50 return num_overlays;
@@ -507,97 +101,25 @@ void dss_init_overlays(struct platform_device *pdev)
507 ovl->set_overlay_info = &dss_ovl_set_info; 101 ovl->set_overlay_info = &dss_ovl_set_info;
508 ovl->get_overlay_info = &dss_ovl_get_info; 102 ovl->get_overlay_info = &dss_ovl_get_info;
509 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; 103 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
104 ovl->get_device = &dss_ovl_get_device;
510 105
511 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 106 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
512 ovl->supported_modes = 107 ovl->supported_modes =
513 dss_feat_get_supported_color_modes(ovl->id); 108 dss_feat_get_supported_color_modes(ovl->id);
514 109
515 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 110 r = dss_overlay_kobj_init(ovl, pdev);
516 &pdev->dev.kobj, "overlay%d", i);
517
518 if (r) 111 if (r)
519 DSSERR("failed to create sysfs file\n"); 112 DSSERR("failed to create sysfs file\n");
520 } 113 }
521} 114}
522 115
523/* connect overlays to the new device, if not already connected. if force
524 * selected, connect always. */
525void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
526{
527 int i;
528 struct omap_overlay_manager *lcd_mgr;
529 struct omap_overlay_manager *tv_mgr;
530 struct omap_overlay_manager *lcd2_mgr = NULL;
531 struct omap_overlay_manager *lcd3_mgr = NULL;
532 struct omap_overlay_manager *mgr = NULL;
533
534 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD);
535 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_DIGIT);
536 if (dss_has_feature(FEAT_MGR_LCD3))
537 lcd3_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD3);
538 if (dss_has_feature(FEAT_MGR_LCD2))
539 lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_CHANNEL_LCD2);
540
541 if (dssdev->channel == OMAP_DSS_CHANNEL_LCD3) {
542 if (!lcd3_mgr->device || force) {
543 if (lcd3_mgr->device)
544 lcd3_mgr->unset_device(lcd3_mgr);
545 lcd3_mgr->set_device(lcd3_mgr, dssdev);
546 mgr = lcd3_mgr;
547 }
548 } else if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
549 if (!lcd2_mgr->device || force) {
550 if (lcd2_mgr->device)
551 lcd2_mgr->unset_device(lcd2_mgr);
552 lcd2_mgr->set_device(lcd2_mgr, dssdev);
553 mgr = lcd2_mgr;
554 }
555 } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
556 && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
557 if (!lcd_mgr->device || force) {
558 if (lcd_mgr->device)
559 lcd_mgr->unset_device(lcd_mgr);
560 lcd_mgr->set_device(lcd_mgr, dssdev);
561 mgr = lcd_mgr;
562 }
563 }
564
565 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
566 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
567 if (!tv_mgr->device || force) {
568 if (tv_mgr->device)
569 tv_mgr->unset_device(tv_mgr);
570 tv_mgr->set_device(tv_mgr, dssdev);
571 mgr = tv_mgr;
572 }
573 }
574
575 if (mgr) {
576 dispc_runtime_get();
577
578 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
579 struct omap_overlay *ovl;
580 ovl = omap_dss_get_overlay(i);
581 if (!ovl->manager || force) {
582 if (ovl->manager)
583 ovl->unset_manager(ovl);
584 ovl->set_manager(ovl, mgr);
585 }
586 }
587
588 dispc_runtime_put();
589 }
590}
591
592void dss_uninit_overlays(struct platform_device *pdev) 116void dss_uninit_overlays(struct platform_device *pdev)
593{ 117{
594 int i; 118 int i;
595 119
596 for (i = 0; i < num_overlays; ++i) { 120 for (i = 0; i < num_overlays; ++i) {
597 struct omap_overlay *ovl = &overlays[i]; 121 struct omap_overlay *ovl = &overlays[i];
598 122 dss_overlay_kobj_uninit(ovl);
599 kobject_del(&ovl->kobj);
600 kobject_put(&ovl->kobj);
601 } 123 }
602 124
603 kfree(overlays); 125 kfree(overlays);
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 7c087424b634..7282e5af3e1a 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -111,6 +111,13 @@ static struct {
111 struct omap_dss_device *dssdev[2]; 111 struct omap_dss_device *dssdev[2];
112 112
113 struct semaphore bus_lock; 113 struct semaphore bus_lock;
114
115 struct omap_video_timings timings;
116 int pixel_size;
117 int data_lines;
118 struct rfbi_timings intf_timings;
119
120 struct omap_dss_output output;
114} rfbi; 121} rfbi;
115 122
116static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 123static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -300,30 +307,23 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
300} 307}
301EXPORT_SYMBOL(omap_rfbi_write_pixels); 308EXPORT_SYMBOL(omap_rfbi_write_pixels);
302 309
303static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, 310static int rfbi_transfer_area(struct omap_dss_device *dssdev,
304 u16 height, void (*callback)(void *data), void *data) 311 void (*callback)(void *data), void *data)
305{ 312{
306 u32 l; 313 u32 l;
307 int r; 314 int r;
308 struct omap_video_timings timings = { 315 struct omap_overlay_manager *mgr = dssdev->output->manager;
309 .hsw = 1, 316 u16 width = rfbi.timings.x_res;
310 .hfp = 1, 317 u16 height = rfbi.timings.y_res;
311 .hbp = 1,
312 .vsw = 1,
313 .vfp = 0,
314 .vbp = 0,
315 .x_res = width,
316 .y_res = height,
317 };
318 318
319 /*BUG_ON(callback == 0);*/ 319 /*BUG_ON(callback == 0);*/
320 BUG_ON(rfbi.framedone_callback != NULL); 320 BUG_ON(rfbi.framedone_callback != NULL);
321 321
322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
323 323
324 dss_mgr_set_timings(dssdev->manager, &timings); 324 dss_mgr_set_timings(mgr, &rfbi.timings);
325 325
326 r = dss_mgr_enable(dssdev->manager); 326 r = dss_mgr_enable(mgr);
327 if (r) 327 if (r)
328 return r; 328 return r;
329 329
@@ -770,62 +770,45 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
770 return 0; 770 return 0;
771} 771}
772 772
773int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, 773int omap_rfbi_configure(struct omap_dss_device *dssdev)
774 int data_lines)
775{ 774{
776 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); 775 return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
776 rfbi.data_lines);
777} 777}
778EXPORT_SYMBOL(omap_rfbi_configure); 778EXPORT_SYMBOL(omap_rfbi_configure);
779 779
780int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, 780int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *),
781 u16 *x, u16 *y, u16 *w, u16 *h) 781 void *data)
782{ 782{
783 u16 dw, dh; 783 return rfbi_transfer_area(dssdev, callback, data);
784 struct omap_video_timings timings = { 784}
785 .hsw = 1, 785EXPORT_SYMBOL(omap_rfbi_update);
786 .hfp = 1,
787 .hbp = 1,
788 .vsw = 1,
789 .vfp = 0,
790 .vbp = 0,
791 .x_res = *w,
792 .y_res = *h,
793 };
794
795 dssdev->driver->get_resolution(dssdev, &dw, &dh);
796
797 if (*x > dw || *y > dh)
798 return -EINVAL;
799
800 if (*x + *w > dw)
801 return -EINVAL;
802
803 if (*y + *h > dh)
804 return -EINVAL;
805
806 if (*w == 1)
807 return -EINVAL;
808
809 if (*w == 0 || *h == 0)
810 return -EINVAL;
811
812 dss_mgr_set_timings(dssdev->manager, &timings);
813 786
814 return 0; 787void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
788{
789 rfbi.timings.x_res = w;
790 rfbi.timings.y_res = h;
815} 791}
816EXPORT_SYMBOL(omap_rfbi_prepare_update); 792EXPORT_SYMBOL(omapdss_rfbi_set_size);
817 793
818int omap_rfbi_update(struct omap_dss_device *dssdev, 794void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
819 u16 x, u16 y, u16 w, u16 h,
820 void (*callback)(void *), void *data)
821{ 795{
822 int r; 796 rfbi.pixel_size = pixel_size;
797}
798EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
823 799
824 r = rfbi_transfer_area(dssdev, w, h, callback, data); 800void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
801{
802 rfbi.data_lines = data_lines;
803}
804EXPORT_SYMBOL(omapdss_rfbi_set_data_lines);
825 805
826 return r; 806void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev,
807 struct rfbi_timings *timings)
808{
809 rfbi.intf_timings = *timings;
827} 810}
828EXPORT_SYMBOL(omap_rfbi_update); 811EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings);
829 812
830static void rfbi_dump_regs(struct seq_file *s) 813static void rfbi_dump_regs(struct seq_file *s)
831{ 814{
@@ -869,6 +852,7 @@ static void rfbi_dump_regs(struct seq_file *s)
869 852
870static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) 853static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
871{ 854{
855 struct omap_overlay_manager *mgr = dssdev->output->manager;
872 struct dss_lcd_mgr_config mgr_config; 856 struct dss_lcd_mgr_config mgr_config;
873 857
874 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI; 858 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
@@ -877,18 +861,40 @@ static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
877 /* Do we need fifohandcheck for RFBI? */ 861 /* Do we need fifohandcheck for RFBI? */
878 mgr_config.fifohandcheck = false; 862 mgr_config.fifohandcheck = false;
879 863
880 mgr_config.video_port_width = dssdev->ctrl.pixel_size; 864 mgr_config.video_port_width = rfbi.pixel_size;
881 mgr_config.lcden_sig_polarity = 0; 865 mgr_config.lcden_sig_polarity = 0;
882 866
883 dss_mgr_set_lcd_config(dssdev->manager, &mgr_config); 867 dss_mgr_set_lcd_config(mgr, &mgr_config);
868
869 /*
870 * Set rfbi.timings with default values, the x_res and y_res fields
871 * are expected to be already configured by the panel driver via
872 * omapdss_rfbi_set_size()
873 */
874 rfbi.timings.hsw = 1;
875 rfbi.timings.hfp = 1;
876 rfbi.timings.hbp = 1;
877 rfbi.timings.vsw = 1;
878 rfbi.timings.vfp = 0;
879 rfbi.timings.vbp = 0;
880
881 rfbi.timings.interlace = false;
882 rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
883 rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
884 rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
885 rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
886 rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
887
888 dss_mgr_set_timings(mgr, &rfbi.timings);
884} 889}
885 890
886int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 891int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
887{ 892{
893 struct omap_dss_output *out = dssdev->output;
888 int r; 894 int r;
889 895
890 if (dssdev->manager == NULL) { 896 if (out == NULL || out->manager == NULL) {
891 DSSERR("failed to enable display: no manager\n"); 897 DSSERR("failed to enable display: no output/manager\n");
892 return -ENODEV; 898 return -ENODEV;
893 } 899 }
894 900
@@ -911,13 +917,10 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
911 917
912 rfbi_config_lcd_manager(dssdev); 918 rfbi_config_lcd_manager(dssdev);
913 919
914 rfbi_configure(dssdev->phy.rfbi.channel, 920 rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size,
915 dssdev->ctrl.pixel_size, 921 rfbi.data_lines);
916 dssdev->phy.rfbi.data_lines);
917
918 rfbi_set_timings(dssdev->phy.rfbi.channel,
919 &dssdev->ctrl.rfbi_timings);
920 922
923 rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
921 924
922 return 0; 925 return 0;
923err1: 926err1:
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable);
941static int __init rfbi_init_display(struct omap_dss_device *dssdev) 944static int __init rfbi_init_display(struct omap_dss_device *dssdev)
942{ 945{
943 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 946 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
944 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
945 return 0; 947 return 0;
946} 948}
947 949
948static void __init rfbi_probe_pdata(struct platform_device *pdev) 950static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
949{ 951{
950 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 952 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
951 int i, r; 953 const char *def_disp_name = dss_get_default_display_name();
954 struct omap_dss_device *def_dssdev;
955 int i;
956
957 def_dssdev = NULL;
952 958
953 for (i = 0; i < pdata->num_devices; ++i) { 959 for (i = 0; i < pdata->num_devices; ++i) {
954 struct omap_dss_device *dssdev = pdata->devices[i]; 960 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -956,17 +962,67 @@ static void __init rfbi_probe_pdata(struct platform_device *pdev)
956 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI) 962 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
957 continue; 963 continue;
958 964
959 r = rfbi_init_display(dssdev); 965 if (def_dssdev == NULL)
960 if (r) { 966 def_dssdev = dssdev;
961 DSSERR("device %s init failed: %d\n", dssdev->name, r); 967
962 continue; 968 if (def_disp_name != NULL &&
969 strcmp(dssdev->name, def_disp_name) == 0) {
970 def_dssdev = dssdev;
971 break;
963 } 972 }
973 }
974
975 return def_dssdev;
976}
977
978static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
979{
980 struct omap_dss_device *plat_dssdev;
981 struct omap_dss_device *dssdev;
982 int r;
983
984 plat_dssdev = rfbi_find_dssdev(rfbidev);
985
986 if (!plat_dssdev)
987 return;
988
989 dssdev = dss_alloc_and_init_device(&rfbidev->dev);
990 if (!dssdev)
991 return;
992
993 dss_copy_device_pdata(dssdev, plat_dssdev);
964 994
965 r = omap_dss_register_device(dssdev, &pdev->dev, i); 995 r = rfbi_init_display(dssdev);
966 if (r) 996 if (r) {
967 DSSERR("device %s register failed: %d\n", 997 DSSERR("device %s init failed: %d\n", dssdev->name, r);
968 dssdev->name, r); 998 dss_put_device(dssdev);
999 return;
969 } 1000 }
1001
1002 r = dss_add_device(dssdev);
1003 if (r) {
1004 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1005 dss_put_device(dssdev);
1006 return;
1007 }
1008}
1009
1010static void __init rfbi_init_output(struct platform_device *pdev)
1011{
1012 struct omap_dss_output *out = &rfbi.output;
1013
1014 out->pdev = pdev;
1015 out->id = OMAP_DSS_OUTPUT_DBI;
1016 out->type = OMAP_DISPLAY_TYPE_DBI;
1017
1018 dss_register_output(out);
1019}
1020
1021static void __exit rfbi_uninit_output(struct platform_device *pdev)
1022{
1023 struct omap_dss_output *out = &rfbi.output;
1024
1025 dss_unregister_output(out);
970} 1026}
971 1027
972/* RFBI HW IP initialisation */ 1028/* RFBI HW IP initialisation */
@@ -1020,6 +1076,8 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
1020 1076
1021 dss_debugfs_create_file("rfbi", rfbi_dump_regs); 1077 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1022 1078
1079 rfbi_init_output(pdev);
1080
1023 rfbi_probe_pdata(pdev); 1081 rfbi_probe_pdata(pdev);
1024 1082
1025 return 0; 1083 return 0;
@@ -1031,8 +1089,12 @@ err_runtime_get:
1031 1089
1032static int __exit omap_rfbihw_remove(struct platform_device *pdev) 1090static int __exit omap_rfbihw_remove(struct platform_device *pdev)
1033{ 1091{
1034 omap_dss_unregister_child_devices(&pdev->dev); 1092 dss_unregister_child_devices(&pdev->dev);
1093
1094 rfbi_uninit_output(pdev);
1095
1035 pm_runtime_disable(&pdev->dev); 1096 pm_runtime_disable(&pdev->dev);
1097
1036 return 0; 1098 return 0;
1037} 1099}
1038 1100
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index f43bfe17b3b6..7760851f6e5d 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -25,6 +25,7 @@
25#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
26#include <linux/export.h> 26#include <linux/export.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/string.h>
28 29
29#include <video/omapdss.h> 30#include <video/omapdss.h>
30#include "dss.h" 31#include "dss.h"
@@ -34,10 +35,16 @@ static struct {
34 struct regulator *vdds_sdi_reg; 35 struct regulator *vdds_sdi_reg;
35 36
36 struct dss_lcd_mgr_config mgr_config; 37 struct dss_lcd_mgr_config mgr_config;
38 struct omap_video_timings timings;
39 int datapairs;
40
41 struct omap_dss_output output;
37} sdi; 42} sdi;
38 43
39static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) 44static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
40{ 45{
46 struct omap_overlay_manager *mgr = dssdev->output->manager;
47
41 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 48 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
42 49
43 sdi.mgr_config.stallmode = false; 50 sdi.mgr_config.stallmode = false;
@@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev)
46 sdi.mgr_config.video_port_width = 24; 53 sdi.mgr_config.video_port_width = 24;
47 sdi.mgr_config.lcden_sig_polarity = 1; 54 sdi.mgr_config.lcden_sig_polarity = 1;
48 55
49 dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config); 56 dss_mgr_set_lcd_config(mgr, &sdi.mgr_config);
50} 57}
51 58
52int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) 59int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
53{ 60{
54 struct omap_video_timings *t = &dssdev->panel.timings; 61 struct omap_dss_output *out = dssdev->output;
62 struct omap_video_timings *t = &sdi.timings;
55 struct dss_clock_info dss_cinfo; 63 struct dss_clock_info dss_cinfo;
56 struct dispc_clock_info dispc_cinfo; 64 struct dispc_clock_info dispc_cinfo;
57 unsigned long pck; 65 unsigned long pck;
58 int r; 66 int r;
59 67
60 if (dssdev->manager == NULL) { 68 if (out == NULL || out->manager == NULL) {
61 DSSERR("failed to enable display: no manager\n"); 69 DSSERR("failed to enable display: no output/manager\n");
62 return -ENODEV; 70 return -ENODEV;
63 } 71 }
64 72
@@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
77 goto err_get_dispc; 85 goto err_get_dispc;
78 86
79 /* 15.5.9.1.2 */ 87 /* 15.5.9.1.2 */
80 dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 88 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
81 dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 89 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
82 90
83 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); 91 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo);
84 if (r) 92 if (r)
@@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
97 } 105 }
98 106
99 107
100 dss_mgr_set_timings(dssdev->manager, t); 108 dss_mgr_set_timings(out->manager, t);
101 109
102 r = dss_set_clock_div(&dss_cinfo); 110 r = dss_set_clock_div(&dss_cinfo);
103 if (r) 111 if (r)
@@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
116 * need to care about the shadow register mechanism for pck-free. The 124 * need to care about the shadow register mechanism for pck-free. The
117 * exact reason for this is unknown. 125 * exact reason for this is unknown.
118 */ 126 */
119 dispc_mgr_set_clock_div(dssdev->manager->id, 127 dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
120 &sdi.mgr_config.clock_info);
121 128
122 dss_sdi_init(dssdev->phy.sdi.datapairs); 129 dss_sdi_init(sdi.datapairs);
123 r = dss_sdi_enable(); 130 r = dss_sdi_enable();
124 if (r) 131 if (r)
125 goto err_sdi_enable; 132 goto err_sdi_enable;
126 mdelay(2); 133 mdelay(2);
127 134
128 r = dss_mgr_enable(dssdev->manager); 135 r = dss_mgr_enable(out->manager);
129 if (r) 136 if (r)
130 goto err_mgr_enable; 137 goto err_mgr_enable;
131 138
@@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
148 155
149void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 156void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
150{ 157{
151 dss_mgr_disable(dssdev->manager); 158 struct omap_overlay_manager *mgr = dssdev->output->manager;
159
160 dss_mgr_disable(mgr);
152 161
153 dss_sdi_disable(); 162 dss_sdi_disable();
154 163
@@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
160} 169}
161EXPORT_SYMBOL(omapdss_sdi_display_disable); 170EXPORT_SYMBOL(omapdss_sdi_display_disable);
162 171
172void omapdss_sdi_set_timings(struct omap_dss_device *dssdev,
173 struct omap_video_timings *timings)
174{
175 sdi.timings = *timings;
176}
177EXPORT_SYMBOL(omapdss_sdi_set_timings);
178
179void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
180{
181 sdi.datapairs = datapairs;
182}
183EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
184
163static int __init sdi_init_display(struct omap_dss_device *dssdev) 185static int __init sdi_init_display(struct omap_dss_device *dssdev)
164{ 186{
165 DSSDBG("SDI init\n"); 187 DSSDBG("SDI init\n");
@@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
180 return 0; 202 return 0;
181} 203}
182 204
183static void __init sdi_probe_pdata(struct platform_device *pdev) 205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
184{ 206{
185 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 207 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
186 int i, r; 208 const char *def_disp_name = dss_get_default_display_name();
209 struct omap_dss_device *def_dssdev;
210 int i;
211
212 def_dssdev = NULL;
187 213
188 for (i = 0; i < pdata->num_devices; ++i) { 214 for (i = 0; i < pdata->num_devices; ++i) {
189 struct omap_dss_device *dssdev = pdata->devices[i]; 215 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev)
191 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) 217 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
192 continue; 218 continue;
193 219
194 r = sdi_init_display(dssdev); 220 if (def_dssdev == NULL)
195 if (r) { 221 def_dssdev = dssdev;
196 DSSERR("device %s init failed: %d\n", dssdev->name, r); 222
197 continue; 223 if (def_disp_name != NULL &&
224 strcmp(dssdev->name, def_disp_name) == 0) {
225 def_dssdev = dssdev;
226 break;
198 } 227 }
228 }
229
230 return def_dssdev;
231}
232
233static void __init sdi_probe_pdata(struct platform_device *sdidev)
234{
235 struct omap_dss_device *plat_dssdev;
236 struct omap_dss_device *dssdev;
237 int r;
238
239 plat_dssdev = sdi_find_dssdev(sdidev);
199 240
200 r = omap_dss_register_device(dssdev, &pdev->dev, i); 241 if (!plat_dssdev)
201 if (r) 242 return;
202 DSSERR("device %s register failed: %d\n", 243
203 dssdev->name, r); 244 dssdev = dss_alloc_and_init_device(&sdidev->dev);
245 if (!dssdev)
246 return;
247
248 dss_copy_device_pdata(dssdev, plat_dssdev);
249
250 r = sdi_init_display(dssdev);
251 if (r) {
252 DSSERR("device %s init failed: %d\n", dssdev->name, r);
253 dss_put_device(dssdev);
254 return;
204 } 255 }
256
257 r = dss_add_device(dssdev);
258 if (r) {
259 DSSERR("device %s register failed: %d\n", dssdev->name, r);
260 dss_put_device(dssdev);
261 return;
262 }
263}
264
265static void __init sdi_init_output(struct platform_device *pdev)
266{
267 struct omap_dss_output *out = &sdi.output;
268
269 out->pdev = pdev;
270 out->id = OMAP_DSS_OUTPUT_SDI;
271 out->type = OMAP_DISPLAY_TYPE_SDI;
272
273 dss_register_output(out);
274}
275
276static void __exit sdi_uninit_output(struct platform_device *pdev)
277{
278 struct omap_dss_output *out = &sdi.output;
279
280 dss_unregister_output(out);
205} 281}
206 282
207static int __init omap_sdi_probe(struct platform_device *pdev) 283static int __init omap_sdi_probe(struct platform_device *pdev)
208{ 284{
285 sdi_init_output(pdev);
286
209 sdi_probe_pdata(pdev); 287 sdi_probe_pdata(pdev);
210 288
211 return 0; 289 return 0;
@@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev)
213 291
214static int __exit omap_sdi_remove(struct platform_device *pdev) 292static int __exit omap_sdi_remove(struct platform_device *pdev)
215{ 293{
216 omap_dss_unregister_child_devices(&pdev->dev); 294 dss_unregister_child_devices(&pdev->dev);
295
296 sdi_uninit_output(pdev);
217 297
218 return 0; 298 return 0;
219} 299}
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 3a220877461a..56efa3bb465d 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -36,7 +36,6 @@
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37 37
38#include <video/omapdss.h> 38#include <video/omapdss.h>
39#include <plat/cpu.h>
40 39
41#include "dss.h" 40#include "dss.h"
42#include "dss_features.h" 41#include "dss_features.h"
@@ -300,6 +299,12 @@ static struct {
300 struct regulator *vdda_dac_reg; 299 struct regulator *vdda_dac_reg;
301 300
302 struct clk *tv_dac_clk; 301 struct clk *tv_dac_clk;
302
303 struct omap_video_timings timings;
304 enum omap_dss_venc_type type;
305 bool invert_polarity;
306
307 struct omap_dss_output output;
303} venc; 308} venc;
304 309
305static inline void venc_write_reg(int idx, u32 val) 310static inline void venc_write_reg(int idx, u32 val)
@@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config(
424 429
425static int venc_power_on(struct omap_dss_device *dssdev) 430static int venc_power_on(struct omap_dss_device *dssdev)
426{ 431{
432 struct omap_overlay_manager *mgr = dssdev->output->manager;
427 u32 l; 433 u32 l;
428 int r; 434 int r;
429 435
436 r = venc_runtime_get();
437 if (r)
438 goto err0;
439
430 venc_reset(); 440 venc_reset();
431 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); 441 venc_write_config(venc_timings_to_config(&venc.timings));
432 442
433 dss_set_venc_output(dssdev->phy.venc.type); 443 dss_set_venc_output(venc.type);
434 dss_set_dac_pwrdn_bgz(1); 444 dss_set_dac_pwrdn_bgz(1);
435 445
436 l = 0; 446 l = 0;
437 447
438 if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) 448 if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
439 l |= 1 << 1; 449 l |= 1 << 1;
440 else /* S-Video */ 450 else /* S-Video */
441 l |= (1 << 0) | (1 << 2); 451 l |= (1 << 0) | (1 << 2);
442 452
443 if (dssdev->phy.venc.invert_polarity == false) 453 if (venc.invert_polarity == false)
444 l |= 1 << 3; 454 l |= 1 << 3;
445 455
446 venc_write_reg(VENC_OUTPUT_CONTROL, l); 456 venc_write_reg(VENC_OUTPUT_CONTROL, l);
447 457
448 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings); 458 dss_mgr_set_timings(mgr, &venc.timings);
449 459
450 r = regulator_enable(venc.vdda_dac_reg); 460 r = regulator_enable(venc.vdda_dac_reg);
451 if (r) 461 if (r)
452 goto err; 462 goto err1;
453
454 if (dssdev->platform_enable)
455 dssdev->platform_enable(dssdev);
456 463
457 r = dss_mgr_enable(dssdev->manager); 464 r = dss_mgr_enable(mgr);
458 if (r) 465 if (r)
459 goto err; 466 goto err2;
460 467
461 return 0; 468 return 0;
462 469
463err: 470err2:
471 regulator_disable(venc.vdda_dac_reg);
472err1:
464 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 473 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
465 dss_set_dac_pwrdn_bgz(0); 474 dss_set_dac_pwrdn_bgz(0);
466 475
467 if (dssdev->platform_disable) 476 venc_runtime_put();
468 dssdev->platform_disable(dssdev); 477err0:
469
470 regulator_disable(venc.vdda_dac_reg);
471
472 return r; 478 return r;
473} 479}
474 480
475static void venc_power_off(struct omap_dss_device *dssdev) 481static void venc_power_off(struct omap_dss_device *dssdev)
476{ 482{
483 struct omap_overlay_manager *mgr = dssdev->output->manager;
484
477 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 485 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
478 dss_set_dac_pwrdn_bgz(0); 486 dss_set_dac_pwrdn_bgz(0);
479 487
480 dss_mgr_disable(dssdev->manager); 488 dss_mgr_disable(mgr);
481
482 if (dssdev->platform_disable)
483 dssdev->platform_disable(dssdev);
484 489
485 regulator_disable(venc.vdda_dac_reg); 490 regulator_disable(venc.vdda_dac_reg);
491
492 venc_runtime_put();
486} 493}
487 494
488unsigned long venc_get_pixel_clock(void) 495unsigned long venc_get_pixel_clock(void)
@@ -491,171 +498,83 @@ unsigned long venc_get_pixel_clock(void)
491 return 13500000; 498 return 13500000;
492} 499}
493 500
494static ssize_t display_output_type_show(struct device *dev, 501int omapdss_venc_display_enable(struct omap_dss_device *dssdev)
495 struct device_attribute *attr, char *buf)
496{ 502{
497 struct omap_dss_device *dssdev = to_dss_device(dev); 503 struct omap_dss_output *out = dssdev->output;
498 const char *ret; 504 int r;
499
500 switch (dssdev->phy.venc.type) {
501 case OMAP_DSS_VENC_TYPE_COMPOSITE:
502 ret = "composite";
503 break;
504 case OMAP_DSS_VENC_TYPE_SVIDEO:
505 ret = "svideo";
506 break;
507 default:
508 return -EINVAL;
509 }
510
511 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
512}
513 505
514static ssize_t display_output_type_store(struct device *dev, 506 DSSDBG("venc_display_enable\n");
515 struct device_attribute *attr, const char *buf, size_t size)
516{
517 struct omap_dss_device *dssdev = to_dss_device(dev);
518 enum omap_dss_venc_type new_type;
519
520 if (sysfs_streq("composite", buf))
521 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
522 else if (sysfs_streq("svideo", buf))
523 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
524 else
525 return -EINVAL;
526 507
527 mutex_lock(&venc.venc_lock); 508 mutex_lock(&venc.venc_lock);
528 509
529 if (dssdev->phy.venc.type != new_type) { 510 if (out == NULL || out->manager == NULL) {
530 dssdev->phy.venc.type = new_type; 511 DSSERR("Failed to enable display: no output/manager\n");
531 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 512 r = -ENODEV;
532 venc_power_off(dssdev); 513 goto err0;
533 venc_power_on(dssdev);
534 }
535 } 514 }
536 515
537 mutex_unlock(&venc.venc_lock);
538
539 return size;
540}
541
542static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
543 display_output_type_show, display_output_type_store);
544
545/* driver */
546static int venc_panel_probe(struct omap_dss_device *dssdev)
547{
548 dssdev->panel.timings = omap_dss_pal_timings;
549
550 return device_create_file(&dssdev->dev, &dev_attr_output_type);
551}
552
553static void venc_panel_remove(struct omap_dss_device *dssdev)
554{
555 device_remove_file(&dssdev->dev, &dev_attr_output_type);
556}
557
558static int venc_panel_enable(struct omap_dss_device *dssdev)
559{
560 int r = 0;
561
562 DSSDBG("venc_enable_display\n");
563
564 mutex_lock(&venc.venc_lock);
565
566 r = omap_dss_start_device(dssdev); 516 r = omap_dss_start_device(dssdev);
567 if (r) { 517 if (r) {
568 DSSERR("failed to start device\n"); 518 DSSERR("failed to start device\n");
569 goto err0; 519 goto err0;
570 } 520 }
571 521
572 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { 522 if (dssdev->platform_enable)
573 r = -EINVAL; 523 dssdev->platform_enable(dssdev);
574 goto err1;
575 }
576 524
577 r = venc_runtime_get();
578 if (r)
579 goto err1;
580 525
581 r = venc_power_on(dssdev); 526 r = venc_power_on(dssdev);
582 if (r) 527 if (r)
583 goto err2; 528 goto err1;
584 529
585 venc.wss_data = 0; 530 venc.wss_data = 0;
586 531
587 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
588
589 mutex_unlock(&venc.venc_lock); 532 mutex_unlock(&venc.venc_lock);
533
590 return 0; 534 return 0;
591err2:
592 venc_runtime_put();
593err1: 535err1:
536 if (dssdev->platform_disable)
537 dssdev->platform_disable(dssdev);
594 omap_dss_stop_device(dssdev); 538 omap_dss_stop_device(dssdev);
595err0: 539err0:
596 mutex_unlock(&venc.venc_lock); 540 mutex_unlock(&venc.venc_lock);
597
598 return r; 541 return r;
599} 542}
600 543
601static void venc_panel_disable(struct omap_dss_device *dssdev) 544void omapdss_venc_display_disable(struct omap_dss_device *dssdev)
602{ 545{
603 DSSDBG("venc_disable_display\n"); 546 DSSDBG("venc_display_disable\n");
604 547
605 mutex_lock(&venc.venc_lock); 548 mutex_lock(&venc.venc_lock);
606 549
607 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
608 goto end;
609
610 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
611 /* suspended is the same as disabled with venc */
612 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
613 goto end;
614 }
615
616 venc_power_off(dssdev); 550 venc_power_off(dssdev);
617 551
618 venc_runtime_put();
619
620 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
621
622 omap_dss_stop_device(dssdev); 552 omap_dss_stop_device(dssdev);
623end:
624 mutex_unlock(&venc.venc_lock);
625}
626 553
627static int venc_panel_suspend(struct omap_dss_device *dssdev) 554 if (dssdev->platform_disable)
628{ 555 dssdev->platform_disable(dssdev);
629 venc_panel_disable(dssdev);
630 return 0;
631}
632 556
633static int venc_panel_resume(struct omap_dss_device *dssdev) 557 mutex_unlock(&venc.venc_lock);
634{
635 return venc_panel_enable(dssdev);
636} 558}
637 559
638static void venc_set_timings(struct omap_dss_device *dssdev, 560void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
639 struct omap_video_timings *timings) 561 struct omap_video_timings *timings)
640{ 562{
641 DSSDBG("venc_set_timings\n"); 563 DSSDBG("venc_set_timings\n");
642 564
565 mutex_lock(&venc.venc_lock);
566
643 /* Reset WSS data when the TV standard changes. */ 567 /* Reset WSS data when the TV standard changes. */
644 if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings))) 568 if (memcmp(&venc.timings, timings, sizeof(*timings)))
645 venc.wss_data = 0; 569 venc.wss_data = 0;
646 570
647 dssdev->panel.timings = *timings; 571 venc.timings = *timings;
648 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 572
649 /* turn the venc off and on to get new timings to use */ 573 mutex_unlock(&venc.venc_lock);
650 venc_panel_disable(dssdev);
651 venc_panel_enable(dssdev);
652 } else {
653 dss_mgr_set_timings(dssdev->manager, timings);
654 }
655} 574}
656 575
657static int venc_check_timings(struct omap_dss_device *dssdev, 576int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
658 struct omap_video_timings *timings) 577 struct omap_video_timings *timings)
659{ 578{
660 DSSDBG("venc_check_timings\n"); 579 DSSDBG("venc_check_timings\n");
661 580
@@ -668,13 +587,13 @@ static int venc_check_timings(struct omap_dss_device *dssdev,
668 return -EINVAL; 587 return -EINVAL;
669} 588}
670 589
671static u32 venc_get_wss(struct omap_dss_device *dssdev) 590u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev)
672{ 591{
673 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 592 /* Invert due to VENC_L21_WC_CTL:INV=1 */
674 return (venc.wss_data >> 8) ^ 0xfffff; 593 return (venc.wss_data >> 8) ^ 0xfffff;
675} 594}
676 595
677static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 596int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
678{ 597{
679 const struct venc_config *config; 598 const struct venc_config *config;
680 int r; 599 int r;
@@ -683,7 +602,7 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
683 602
684 mutex_lock(&venc.venc_lock); 603 mutex_lock(&venc.venc_lock);
685 604
686 config = venc_timings_to_config(&dssdev->panel.timings); 605 config = venc_timings_to_config(&venc.timings);
687 606
688 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 607 /* Invert due to VENC_L21_WC_CTL:INV=1 */
689 venc.wss_data = (wss ^ 0xfffff) << 8; 608 venc.wss_data = (wss ^ 0xfffff) << 8;
@@ -703,30 +622,25 @@ err:
703 return r; 622 return r;
704} 623}
705 624
706static struct omap_dss_driver venc_driver = { 625void omapdss_venc_set_type(struct omap_dss_device *dssdev,
707 .probe = venc_panel_probe, 626 enum omap_dss_venc_type type)
708 .remove = venc_panel_remove, 627{
628 mutex_lock(&venc.venc_lock);
709 629
710 .enable = venc_panel_enable, 630 venc.type = type;
711 .disable = venc_panel_disable,
712 .suspend = venc_panel_suspend,
713 .resume = venc_panel_resume,
714 631
715 .get_resolution = omapdss_default_get_resolution, 632 mutex_unlock(&venc.venc_lock);
716 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 633}
717 634
718 .set_timings = venc_set_timings, 635void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
719 .check_timings = venc_check_timings, 636 bool invert_polarity)
637{
638 mutex_lock(&venc.venc_lock);
720 639
721 .get_wss = venc_get_wss, 640 venc.invert_polarity = invert_polarity;
722 .set_wss = venc_set_wss,
723 641
724 .driver = { 642 mutex_unlock(&venc.venc_lock);
725 .name = "venc", 643}
726 .owner = THIS_MODULE,
727 },
728};
729/* driver end */
730 644
731static int __init venc_init_display(struct omap_dss_device *dssdev) 645static int __init venc_init_display(struct omap_dss_device *dssdev)
732{ 646{
@@ -752,11 +666,6 @@ static void venc_dump_regs(struct seq_file *s)
752{ 666{
753#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 667#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
754 668
755 if (cpu_is_omap44xx()) {
756 seq_printf(s, "VENC currently disabled on OMAP44xx\n");
757 return;
758 }
759
760 if (venc_runtime_get()) 669 if (venc_runtime_get())
761 return; 670 return;
762 671
@@ -832,10 +741,14 @@ static void venc_put_clocks(void)
832 clk_put(venc.tv_dac_clk); 741 clk_put(venc.tv_dac_clk);
833} 742}
834 743
835static void __init venc_probe_pdata(struct platform_device *pdev) 744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
836{ 745{
837 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 746 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
838 int r, i; 747 const char *def_disp_name = dss_get_default_display_name();
748 struct omap_dss_device *def_dssdev;
749 int i;
750
751 def_dssdev = NULL;
839 752
840 for (i = 0; i < pdata->num_devices; ++i) { 753 for (i = 0; i < pdata->num_devices; ++i) {
841 struct omap_dss_device *dssdev = pdata->devices[i]; 754 struct omap_dss_device *dssdev = pdata->devices[i];
@@ -843,17 +756,69 @@ static void __init venc_probe_pdata(struct platform_device *pdev)
843 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) 756 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
844 continue; 757 continue;
845 758
846 r = venc_init_display(dssdev); 759 if (def_dssdev == NULL)
847 if (r) { 760 def_dssdev = dssdev;
848 DSSERR("device %s init failed: %d\n", dssdev->name, r); 761
849 continue; 762 if (def_disp_name != NULL &&
763 strcmp(dssdev->name, def_disp_name) == 0) {
764 def_dssdev = dssdev;
765 break;
850 } 766 }
767 }
768
769 return def_dssdev;
770}
771
772static void __init venc_probe_pdata(struct platform_device *vencdev)
773{
774 struct omap_dss_device *plat_dssdev;
775 struct omap_dss_device *dssdev;
776 int r;
777
778 plat_dssdev = venc_find_dssdev(vencdev);
851 779
852 r = omap_dss_register_device(dssdev, &pdev->dev, i); 780 if (!plat_dssdev)
853 if (r) 781 return;
854 DSSERR("device %s register failed: %d\n", 782
855 dssdev->name, r); 783 dssdev = dss_alloc_and_init_device(&vencdev->dev);
784 if (!dssdev)
785 return;
786
787 dss_copy_device_pdata(dssdev, plat_dssdev);
788
789 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
790
791 r = venc_init_display(dssdev);
792 if (r) {
793 DSSERR("device %s init failed: %d\n", dssdev->name, r);
794 dss_put_device(dssdev);
795 return;
856 } 796 }
797
798 r = dss_add_device(dssdev);
799 if (r) {
800 DSSERR("device %s register failed: %d\n", dssdev->name, r);
801 dss_put_device(dssdev);
802 return;
803 }
804}
805
806static void __init venc_init_output(struct platform_device *pdev)
807{
808 struct omap_dss_output *out = &venc.output;
809
810 out->pdev = pdev;
811 out->id = OMAP_DSS_OUTPUT_VENC;
812 out->type = OMAP_DISPLAY_TYPE_VENC;
813
814 dss_register_output(out);
815}
816
817static void __exit venc_uninit_output(struct platform_device *pdev)
818{
819 struct omap_dss_output *out = &venc.output;
820
821 dss_unregister_output(out);
857} 822}
858 823
859/* VENC HW IP initialisation */ 824/* VENC HW IP initialisation */
@@ -897,17 +862,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
897 862
898 venc_runtime_put(); 863 venc_runtime_put();
899 864
900 r = omap_dss_register_driver(&venc_driver); 865 r = venc_panel_init();
901 if (r) 866 if (r)
902 goto err_reg_panel_driver; 867 goto err_panel_init;
903 868
904 dss_debugfs_create_file("venc", venc_dump_regs); 869 dss_debugfs_create_file("venc", venc_dump_regs);
905 870
871 venc_init_output(pdev);
872
906 venc_probe_pdata(pdev); 873 venc_probe_pdata(pdev);
907 874
908 return 0; 875 return 0;
909 876
910err_reg_panel_driver: 877err_panel_init:
911err_runtime_get: 878err_runtime_get:
912 pm_runtime_disable(&pdev->dev); 879 pm_runtime_disable(&pdev->dev);
913 venc_put_clocks(); 880 venc_put_clocks();
@@ -916,14 +883,16 @@ err_runtime_get:
916 883
917static int __exit omap_venchw_remove(struct platform_device *pdev) 884static int __exit omap_venchw_remove(struct platform_device *pdev)
918{ 885{
919 omap_dss_unregister_child_devices(&pdev->dev); 886 dss_unregister_child_devices(&pdev->dev);
920 887
921 if (venc.vdda_dac_reg != NULL) { 888 if (venc.vdda_dac_reg != NULL) {
922 regulator_put(venc.vdda_dac_reg); 889 regulator_put(venc.vdda_dac_reg);
923 venc.vdda_dac_reg = NULL; 890 venc.vdda_dac_reg = NULL;
924 } 891 }
925 892
926 omap_dss_unregister_driver(&venc_driver); 893 venc_panel_exit();
894
895 venc_uninit_output(pdev);
927 896
928 pm_runtime_disable(&pdev->dev); 897 pm_runtime_disable(&pdev->dev);
929 venc_put_clocks(); 898 venc_put_clocks();
@@ -971,16 +940,10 @@ static struct platform_driver omap_venchw_driver = {
971 940
972int __init venc_init_platform_driver(void) 941int __init venc_init_platform_driver(void)
973{ 942{
974 if (cpu_is_omap44xx())
975 return 0;
976
977 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); 943 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
978} 944}
979 945
980void __exit venc_uninit_platform_driver(void) 946void __exit venc_uninit_platform_driver(void)
981{ 947{
982 if (cpu_is_omap44xx())
983 return;
984
985 platform_driver_unregister(&omap_venchw_driver); 948 platform_driver_unregister(&omap_venchw_driver);
986} 949}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
new file mode 100644
index 000000000000..d55b8784ecfd
--- /dev/null
+++ b/drivers/video/omap2/dss/venc_panel.c
@@ -0,0 +1,251 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * VENC panel driver
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/kernel.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/mutex.h>
24#include <linux/module.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29
30static struct {
31 struct mutex lock;
32} venc_panel;
33
34static ssize_t display_output_type_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 const char *ret;
39
40 switch (dssdev->phy.venc.type) {
41 case OMAP_DSS_VENC_TYPE_COMPOSITE:
42 ret = "composite";
43 break;
44 case OMAP_DSS_VENC_TYPE_SVIDEO:
45 ret = "svideo";
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
52}
53
54static ssize_t display_output_type_store(struct device *dev,
55 struct device_attribute *attr, const char *buf, size_t size)
56{
57 struct omap_dss_device *dssdev = to_dss_device(dev);
58 enum omap_dss_venc_type new_type;
59
60 if (sysfs_streq("composite", buf))
61 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
62 else if (sysfs_streq("svideo", buf))
63 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
64 else
65 return -EINVAL;
66
67 mutex_lock(&venc_panel.lock);
68
69 if (dssdev->phy.venc.type != new_type) {
70 dssdev->phy.venc.type = new_type;
71 omapdss_venc_set_type(dssdev, new_type);
72 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
73 omapdss_venc_display_disable(dssdev);
74 omapdss_venc_display_enable(dssdev);
75 }
76 }
77
78 mutex_unlock(&venc_panel.lock);
79
80 return size;
81}
82
83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
84 display_output_type_show, display_output_type_store);
85
86static int venc_panel_probe(struct omap_dss_device *dssdev)
87{
88 /* set default timings to PAL */
89 const struct omap_video_timings default_timings = {
90 .x_res = 720,
91 .y_res = 574,
92 .pixel_clock = 13500,
93 .hsw = 64,
94 .hfp = 12,
95 .hbp = 68,
96 .vsw = 5,
97 .vfp = 5,
98 .vbp = 41,
99
100 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
101 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
102
103 .interlace = true,
104 };
105
106 mutex_init(&venc_panel.lock);
107
108 dssdev->panel.timings = default_timings;
109
110 return device_create_file(&dssdev->dev, &dev_attr_output_type);
111}
112
113static void venc_panel_remove(struct omap_dss_device *dssdev)
114{
115 device_remove_file(&dssdev->dev, &dev_attr_output_type);
116}
117
118static int venc_panel_enable(struct omap_dss_device *dssdev)
119{
120 int r;
121
122 dev_dbg(&dssdev->dev, "venc_panel_enable\n");
123
124 mutex_lock(&venc_panel.lock);
125
126 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
127 r = -EINVAL;
128 goto err;
129 }
130
131 omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
132 omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
133 omapdss_venc_invert_vid_out_polarity(dssdev,
134 dssdev->phy.venc.invert_polarity);
135
136 r = omapdss_venc_display_enable(dssdev);
137 if (r)
138 goto err;
139
140 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
141
142 mutex_unlock(&venc_panel.lock);
143
144 return 0;
145err:
146 mutex_unlock(&venc_panel.lock);
147
148 return r;
149}
150
151static void venc_panel_disable(struct omap_dss_device *dssdev)
152{
153 dev_dbg(&dssdev->dev, "venc_panel_disable\n");
154
155 mutex_lock(&venc_panel.lock);
156
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end;
159
160 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
161 /* suspended is the same as disabled with venc */
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163 goto end;
164 }
165
166 omapdss_venc_display_disable(dssdev);
167
168 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
169end:
170 mutex_unlock(&venc_panel.lock);
171}
172
173static int venc_panel_suspend(struct omap_dss_device *dssdev)
174{
175 venc_panel_disable(dssdev);
176 return 0;
177}
178
179static int venc_panel_resume(struct omap_dss_device *dssdev)
180{
181 return venc_panel_enable(dssdev);
182}
183
184static void venc_panel_set_timings(struct omap_dss_device *dssdev,
185 struct omap_video_timings *timings)
186{
187 dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
188
189 mutex_lock(&venc_panel.lock);
190
191 omapdss_venc_set_timings(dssdev, timings);
192 dssdev->panel.timings = *timings;
193
194 mutex_unlock(&venc_panel.lock);
195}
196
197static int venc_panel_check_timings(struct omap_dss_device *dssdev,
198 struct omap_video_timings *timings)
199{
200 dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
201
202 return omapdss_venc_check_timings(dssdev, timings);
203}
204
205static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
206{
207 dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
208
209 return omapdss_venc_get_wss(dssdev);
210}
211
212static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
213{
214 dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
215
216 return omapdss_venc_set_wss(dssdev, wss);
217}
218
219static struct omap_dss_driver venc_driver = {
220 .probe = venc_panel_probe,
221 .remove = venc_panel_remove,
222
223 .enable = venc_panel_enable,
224 .disable = venc_panel_disable,
225 .suspend = venc_panel_suspend,
226 .resume = venc_panel_resume,
227
228 .get_resolution = omapdss_default_get_resolution,
229 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
230
231 .set_timings = venc_panel_set_timings,
232 .check_timings = venc_panel_check_timings,
233
234 .get_wss = venc_panel_get_wss,
235 .set_wss = venc_panel_set_wss,
236
237 .driver = {
238 .name = "venc",
239 .owner = THIS_MODULE,
240 },
241};
242
243int venc_panel_init(void)
244{
245 return omap_dss_register_driver(&venc_driver);
246}
247
248void venc_panel_exit(void)
249{
250 omap_dss_unregister_driver(&venc_driver);
251}
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index c6cf372d22c5..606b89f12351 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -599,6 +599,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
599 struct omapfb_info *ofbi = FB2OFB(fbi); 599 struct omapfb_info *ofbi = FB2OFB(fbi);
600 struct omapfb2_device *fbdev = ofbi->fbdev; 600 struct omapfb2_device *fbdev = ofbi->fbdev;
601 struct omap_dss_device *display = fb2display(fbi); 601 struct omap_dss_device *display = fb2display(fbi);
602 struct omap_overlay_manager *mgr;
602 603
603 union { 604 union {
604 struct omapfb_update_window_old uwnd_o; 605 struct omapfb_update_window_old uwnd_o;
@@ -786,12 +787,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
786 787
787 case OMAPFB_WAITFORVSYNC: 788 case OMAPFB_WAITFORVSYNC:
788 DBG("ioctl WAITFORVSYNC\n"); 789 DBG("ioctl WAITFORVSYNC\n");
789 if (!display) { 790 if (!display && !display->output && !display->output->manager) {
790 r = -EINVAL; 791 r = -EINVAL;
791 break; 792 break;
792 } 793 }
793 794
794 r = display->manager->wait_for_vsync(display->manager); 795 mgr = display->output->manager;
796
797 r = mgr->wait_for_vsync(mgr);
795 break; 798 break;
796 799
797 case OMAPFB_WAITFORGO: 800 case OMAPFB_WAITFORGO:
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 15373f4aee19..16db1589bd91 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1593,6 +1593,20 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1593 return 0; 1593 return 0;
1594} 1594}
1595 1595
1596static void omapfb_clear_fb(struct fb_info *fbi)
1597{
1598 const struct fb_fillrect rect = {
1599 .dx = 0,
1600 .dy = 0,
1601 .width = fbi->var.xres_virtual,
1602 .height = fbi->var.yres_virtual,
1603 .color = 0,
1604 .rop = ROP_COPY,
1605 };
1606
1607 cfb_fillrect(fbi, &rect);
1608}
1609
1596int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) 1610int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1597{ 1611{
1598 struct omapfb_info *ofbi = FB2OFB(fbi); 1612 struct omapfb_info *ofbi = FB2OFB(fbi);
@@ -1662,6 +1676,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1662 goto err; 1676 goto err;
1663 } 1677 }
1664 1678
1679 omapfb_clear_fb(fbi);
1680
1665 return 0; 1681 return 0;
1666err: 1682err:
1667 omapfb_free_fbmem(fbi); 1683 omapfb_free_fbmem(fbi);
@@ -1946,6 +1962,16 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1946 } 1962 }
1947 } 1963 }
1948 1964
1965 for (i = 0; i < fbdev->num_fbs; i++) {
1966 struct fb_info *fbi = fbdev->fbs[i];
1967 struct omapfb_info *ofbi = FB2OFB(fbi);
1968
1969 if (ofbi->region->size == 0)
1970 continue;
1971
1972 omapfb_clear_fb(fbi);
1973 }
1974
1949 DBG("fb_infos initialized\n"); 1975 DBG("fb_infos initialized\n");
1950 1976
1951 for (i = 0; i < fbdev->num_fbs; i++) { 1977 for (i = 0; i < fbdev->num_fbs; i++) {
@@ -2354,6 +2380,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
2354 struct omap_overlay *ovl; 2380 struct omap_overlay *ovl;
2355 struct omap_dss_device *def_display; 2381 struct omap_dss_device *def_display;
2356 struct omap_dss_device *dssdev; 2382 struct omap_dss_device *dssdev;
2383 struct omap_dss_device *ovl_device;
2357 2384
2358 DBG("omapfb_probe\n"); 2385 DBG("omapfb_probe\n");
2359 2386
@@ -2427,8 +2454,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
2427 /* gfx overlay should be the default one. find a display 2454 /* gfx overlay should be the default one. find a display
2428 * connected to that, and use it as default display */ 2455 * connected to that, and use it as default display */
2429 ovl = omap_dss_get_overlay(0); 2456 ovl = omap_dss_get_overlay(0);
2430 if (ovl->manager && ovl->manager->device) { 2457 ovl_device = ovl->get_device(ovl);
2431 def_display = ovl->manager->device; 2458 if (ovl_device) {
2459 def_display = ovl_device;
2432 } else { 2460 } else {
2433 dev_warn(&pdev->dev, "cannot find default display\n"); 2461 dev_warn(&pdev->dev, "cannot find default display\n");
2434 def_display = NULL; 2462 def_display = NULL;
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 30361a09aecd..5ced9b334d35 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -148,8 +148,9 @@ static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
148 148
149 /* XXX: returns the display connected to first attached overlay */ 149 /* XXX: returns the display connected to first attached overlay */
150 for (i = 0; i < ofbi->num_overlays; i++) { 150 for (i = 0; i < ofbi->num_overlays; i++) {
151 if (ofbi->overlays[i]->manager) 151 struct omap_overlay *ovl = ofbi->overlays[i];
152 return ofbi->overlays[i]->manager->device; 152
153 return ovl->get_device(ovl);
153 } 154 }
154 155
155 return NULL; 156 return NULL;
diff --git a/drivers/video/omap2/vram.c b/drivers/video/omap2/vram.c
index 87e421e25afe..f2b15c4a75bc 100644
--- a/drivers/video/omap2/vram.c
+++ b/drivers/video/omap2/vram.c
@@ -34,7 +34,6 @@
34#include <asm/setup.h> 34#include <asm/setup.h>
35 35
36#include <plat/vram.h> 36#include <plat/vram.h>
37#include <plat/dma.h>
38 37
39#ifdef DEBUG 38#ifdef DEBUG
40#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) 39#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__)
@@ -250,59 +249,6 @@ int omap_vram_reserve(unsigned long paddr, size_t size)
250} 249}
251EXPORT_SYMBOL(omap_vram_reserve); 250EXPORT_SYMBOL(omap_vram_reserve);
252 251
253static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data)
254{
255 struct completion *compl = data;
256 complete(compl);
257}
258
259static int _omap_vram_clear(u32 paddr, unsigned pages)
260{
261 struct completion compl;
262 unsigned elem_count;
263 unsigned frame_count;
264 int r;
265 int lch;
266
267 init_completion(&compl);
268
269 r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA",
270 _omap_vram_dma_cb,
271 &compl, &lch);
272 if (r) {
273 pr_err("VRAM: request_dma failed for memory clear\n");
274 return -EBUSY;
275 }
276
277 elem_count = pages * PAGE_SIZE / 4;
278 frame_count = 1;
279
280 omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32,
281 elem_count, frame_count,
282 OMAP_DMA_SYNC_ELEMENT,
283 0, 0);
284
285 omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC,
286 paddr, 0, 0);
287
288 omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000);
289
290 omap_start_dma(lch);
291
292 if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) {
293 omap_stop_dma(lch);
294 pr_err("VRAM: dma timeout while clearing memory\n");
295 r = -EIO;
296 goto err;
297 }
298
299 r = 0;
300err:
301 omap_free_dma(lch);
302
303 return r;
304}
305
306static int _omap_vram_alloc(unsigned pages, unsigned long *paddr) 252static int _omap_vram_alloc(unsigned pages, unsigned long *paddr)
307{ 253{
308 struct vram_region *rm; 254 struct vram_region *rm;
@@ -337,8 +283,6 @@ found:
337 283
338 *paddr = start; 284 *paddr = start;
339 285
340 _omap_vram_clear(start, pages);
341
342 return 0; 286 return 0;
343 } 287 }
344 288
diff --git a/drivers/video/pnx4008/Makefile b/drivers/video/pnx4008/Makefile
deleted file mode 100644
index 636aaccf01fd..000000000000
--- a/drivers/video/pnx4008/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
1#
2# Makefile for the new PNX4008 framebuffer device driver
3#
4
5obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o
6obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnxrgbfb.o
7
diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h
deleted file mode 100644
index 1234d4375d92..000000000000
--- a/drivers/video/pnx4008/dum.h
+++ /dev/null
@@ -1,211 +0,0 @@
1/*
2 * linux/drivers/video/pnx4008/dum.h
3 *
4 * Internal header for SDUM
5 *
6 * 2005 (c) Koninklijke Philips N.V. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#ifndef __PNX008_DUM_H__
13#define __PNX008_DUM_H__
14
15#include <mach/platform.h>
16
17#define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE)
18#define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE)
19
20/* DUM CFG ADDRESSES */
21#define DUM_CH_BASE_ADR (PNX4008_DUMCONF_VA_BASE + 0x00)
22#define DUM_CH_MIN_ADR (PNX4008_DUMCONF_VA_BASE + 0x00)
23#define DUM_CH_MAX_ADR (PNX4008_DUMCONF_VA_BASE + 0x04)
24#define DUM_CH_CONF_ADR (PNX4008_DUMCONF_VA_BASE + 0x08)
25#define DUM_CH_STAT_ADR (PNX4008_DUMCONF_VA_BASE + 0x0C)
26#define DUM_CH_CTRL_ADR (PNX4008_DUMCONF_VA_BASE + 0x10)
27
28#define CH_MARG (0x100 / sizeof(u32))
29#define DUM_CH_MIN(i) (*((volatile u32 *)DUM_CH_MIN_ADR + (i) * CH_MARG))
30#define DUM_CH_MAX(i) (*((volatile u32 *)DUM_CH_MAX_ADR + (i) * CH_MARG))
31#define DUM_CH_CONF(i) (*((volatile u32 *)DUM_CH_CONF_ADR + (i) * CH_MARG))
32#define DUM_CH_STAT(i) (*((volatile u32 *)DUM_CH_STAT_ADR + (i) * CH_MARG))
33#define DUM_CH_CTRL(i) (*((volatile u32 *)DUM_CH_CTRL_ADR + (i) * CH_MARG))
34
35#define DUM_CONF_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x00)
36#define DUM_CTRL_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x04)
37#define DUM_STAT_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x08)
38#define DUM_DECODE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x0C)
39#define DUM_COM_BASE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x10)
40#define DUM_SYNC_C_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x14)
41#define DUM_CLK_DIV_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x18)
42#define DUM_DIRTY_LOW_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x20)
43#define DUM_DIRTY_HIGH_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x24)
44#define DUM_FORMAT_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x28)
45#define DUM_WTCFG1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x30)
46#define DUM_RTCFG1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x34)
47#define DUM_WTCFG2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x38)
48#define DUM_RTCFG2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x3C)
49#define DUM_TCFG_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x40)
50#define DUM_OUTP_FORMAT1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x44)
51#define DUM_OUTP_FORMAT2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x48)
52#define DUM_SYNC_MODE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x4C)
53#define DUM_SYNC_OUT_C_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x50)
54
55#define DUM_CONF (*(volatile u32 *)(DUM_CONF_ADR))
56#define DUM_CTRL (*(volatile u32 *)(DUM_CTRL_ADR))
57#define DUM_STAT (*(volatile u32 *)(DUM_STAT_ADR))
58#define DUM_DECODE (*(volatile u32 *)(DUM_DECODE_ADR))
59#define DUM_COM_BASE (*(volatile u32 *)(DUM_COM_BASE_ADR))
60#define DUM_SYNC_C (*(volatile u32 *)(DUM_SYNC_C_ADR))
61#define DUM_CLK_DIV (*(volatile u32 *)(DUM_CLK_DIV_ADR))
62#define DUM_DIRTY_LOW (*(volatile u32 *)(DUM_DIRTY_LOW_ADR))
63#define DUM_DIRTY_HIGH (*(volatile u32 *)(DUM_DIRTY_HIGH_ADR))
64#define DUM_FORMAT (*(volatile u32 *)(DUM_FORMAT_ADR))
65#define DUM_WTCFG1 (*(volatile u32 *)(DUM_WTCFG1_ADR))
66#define DUM_RTCFG1 (*(volatile u32 *)(DUM_RTCFG1_ADR))
67#define DUM_WTCFG2 (*(volatile u32 *)(DUM_WTCFG2_ADR))
68#define DUM_RTCFG2 (*(volatile u32 *)(DUM_RTCFG2_ADR))
69#define DUM_TCFG (*(volatile u32 *)(DUM_TCFG_ADR))
70#define DUM_OUTP_FORMAT1 (*(volatile u32 *)(DUM_OUTP_FORMAT1_ADR))
71#define DUM_OUTP_FORMAT2 (*(volatile u32 *)(DUM_OUTP_FORMAT2_ADR))
72#define DUM_SYNC_MODE (*(volatile u32 *)(DUM_SYNC_MODE_ADR))
73#define DUM_SYNC_OUT_C (*(volatile u32 *)(DUM_SYNC_OUT_C_ADR))
74
75/* DUM SLAVE ADDRESSES */
76#define DUM_SLAVE_WRITE_ADR (PNX4008_DUM_MAINCFG_BASE + 0x0000000)
77#define DUM_SLAVE_READ1_I_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000000)
78#define DUM_SLAVE_READ1_R_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000004)
79#define DUM_SLAVE_READ2_I_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000008)
80#define DUM_SLAVE_READ2_R_ADR (PNX4008_DUM_MAINCFG_BASE + 0x100000C)
81
82#define DUM_SLAVE_WRITE_W ((volatile u32 *)(DUM_SLAVE_WRITE_ADR))
83#define DUM_SLAVE_WRITE_HW ((volatile u16 *)(DUM_SLAVE_WRITE_ADR))
84#define DUM_SLAVE_READ1_I ((volatile u8 *)(DUM_SLAVE_READ1_I_ADR))
85#define DUM_SLAVE_READ1_R ((volatile u16 *)(DUM_SLAVE_READ1_R_ADR))
86#define DUM_SLAVE_READ2_I ((volatile u8 *)(DUM_SLAVE_READ2_I_ADR))
87#define DUM_SLAVE_READ2_R ((volatile u16 *)(DUM_SLAVE_READ2_R_ADR))
88
89/* Sony display register addresses */
90#define DISP_0_REG (0x00)
91#define DISP_1_REG (0x01)
92#define DISP_CAL_REG (0x20)
93#define DISP_ID_REG (0x2A)
94#define DISP_XMIN_L_REG (0x30)
95#define DISP_XMIN_H_REG (0x31)
96#define DISP_YMIN_REG (0x32)
97#define DISP_XMAX_L_REG (0x34)
98#define DISP_XMAX_H_REG (0x35)
99#define DISP_YMAX_REG (0x36)
100#define DISP_SYNC_EN_REG (0x38)
101#define DISP_SYNC_RISE_L_REG (0x3C)
102#define DISP_SYNC_RISE_H_REG (0x3D)
103#define DISP_SYNC_FALL_L_REG (0x3E)
104#define DISP_SYNC_FALL_H_REG (0x3F)
105#define DISP_PIXEL_REG (0x0B)
106#define DISP_DUMMY1_REG (0x28)
107#define DISP_DUMMY2_REG (0x29)
108#define DISP_TIMING_REG (0x98)
109#define DISP_DUMP_REG (0x99)
110
111/* Sony display constants */
112#define SONY_ID1 (0x22)
113#define SONY_ID2 (0x23)
114
115/* Philips display register addresses */
116#define PH_DISP_ORIENT_REG (0x003)
117#define PH_DISP_YPOINT_REG (0x200)
118#define PH_DISP_XPOINT_REG (0x201)
119#define PH_DISP_PIXEL_REG (0x202)
120#define PH_DISP_YMIN_REG (0x406)
121#define PH_DISP_YMAX_REG (0x407)
122#define PH_DISP_XMIN_REG (0x408)
123#define PH_DISP_XMAX_REG (0x409)
124
125/* Misc constants */
126#define NO_VALID_DISPLAY_FOUND (0)
127#define DISPLAY2_IS_NOT_CONNECTED (0)
128
129/* register values */
130#define V_BAC_ENABLE (BIT(0))
131#define V_BAC_DISABLE_IDLE (BIT(1))
132#define V_BAC_DISABLE_TRIG (BIT(2))
133#define V_DUM_RESET (BIT(3))
134#define V_MUX_RESET (BIT(4))
135#define BAC_ENABLED (BIT(0))
136#define BAC_DISABLED 0
137
138/* Sony LCD commands */
139#define V_LCD_STANDBY_OFF ((BIT(25)) | (0 << 16) | DISP_0_REG)
140#define V_LCD_USE_9BIT_BUS ((BIT(25)) | (2 << 16) | DISP_1_REG)
141#define V_LCD_SYNC_RISE_L ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_L_REG)
142#define V_LCD_SYNC_RISE_H ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_H_REG)
143#define V_LCD_SYNC_FALL_L ((BIT(25)) | (160 << 16) | DISP_SYNC_FALL_L_REG)
144#define V_LCD_SYNC_FALL_H ((BIT(25)) | (0 << 16) | DISP_SYNC_FALL_H_REG)
145#define V_LCD_SYNC_ENABLE ((BIT(25)) | (128 << 16) | DISP_SYNC_EN_REG)
146#define V_LCD_DISPLAY_ON ((BIT(25)) | (64 << 16) | DISP_0_REG)
147
148enum {
149 PAD_NONE,
150 PAD_512,
151 PAD_1024
152};
153
154enum {
155 RGB888,
156 RGB666,
157 RGB565,
158 BGR565,
159 ARGB1555,
160 ABGR1555,
161 ARGB4444,
162 ABGR4444
163};
164
165struct dum_setup {
166 int sync_neg_edge;
167 int round_robin;
168 int mux_int;
169 int synced_dirty_flag_int;
170 int dirty_flag_int;
171 int error_int;
172 int pf_empty_int;
173 int sf_empty_int;
174 int bac_dis_int;
175 u32 dirty_base_adr;
176 u32 command_base_adr;
177 u32 sync_clk_div;
178 int sync_output;
179 u32 sync_restart_val;
180 u32 set_sync_high;
181 u32 set_sync_low;
182};
183
184struct dum_ch_setup {
185 int disp_no;
186 u32 xmin;
187 u32 ymin;
188 u32 xmax;
189 u32 ymax;
190 int xmirror;
191 int ymirror;
192 int rotate;
193 u32 minadr;
194 u32 maxadr;
195 u32 dirtybuffer;
196 int pad;
197 int format;
198 int hwdirty;
199 int slave_trans;
200};
201
202struct disp_window {
203 u32 xmin_l;
204 u32 xmin_h;
205 u32 ymin;
206 u32 xmax_l;
207 u32 xmax_h;
208 u32 ymax;
209};
210
211#endif /* #ifndef __PNX008_DUM_H__ */
diff --git a/drivers/video/pnx4008/fbcommon.h b/drivers/video/pnx4008/fbcommon.h
deleted file mode 100644
index 4ebc87dafafb..000000000000
--- a/drivers/video/pnx4008/fbcommon.h
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * Copyright (C) 2005 Philips Semiconductors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
18*/
19
20#define QCIF_W (176)
21#define QCIF_H (144)
22
23#define CIF_W (352)
24#define CIF_H (288)
25
26#define LCD_X_RES 208
27#define LCD_Y_RES 320
28#define LCD_X_PAD 256
29#define LCD_BBP 4 /* Bytes Per Pixel */
30
31#define DISP_MAX_X_SIZE (320)
32#define DISP_MAX_Y_SIZE (208)
33
34#define RETURNVAL_BASE (0x400)
35
36enum fb_ioctl_returntype {
37 ENORESOURCESLEFT = RETURNVAL_BASE,
38 ERESOURCESNOTFREED,
39 EPROCNOTOWNER,
40 EFBNOTOWNER,
41 ECOPYFAILED,
42 EIOREMAPFAILED,
43};
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
deleted file mode 100644
index 6d30428e9cf9..000000000000
--- a/drivers/video/pnx4008/pnxrgbfb.c
+++ /dev/null
@@ -1,198 +0,0 @@
1/*
2 * drivers/video/pnx4008/pnxrgbfb.c
3 *
4 * PNX4008's framebuffer support
5 *
6 * Author: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
7 * Based on Philips Semiconductors's code
8 *
9 * Copyrght (c) 2005 MontaVista Software, Inc.
10 * Copyright (c) 2005 Philips Semiconductors
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
14 */
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/string.h>
20#include <linux/mm.h>
21#include <linux/vmalloc.h>
22#include <linux/delay.h>
23#include <linux/interrupt.h>
24#include <linux/fb.h>
25#include <linux/init.h>
26#include <linux/platform_device.h>
27
28#include "sdum.h"
29#include "fbcommon.h"
30
31static u32 colreg[16];
32
33static struct fb_var_screeninfo rgbfb_var __initdata = {
34 .xres = LCD_X_RES,
35 .yres = LCD_Y_RES,
36 .xres_virtual = LCD_X_RES,
37 .yres_virtual = LCD_Y_RES,
38 .bits_per_pixel = 32,
39 .red.offset = 16,
40 .red.length = 8,
41 .green.offset = 8,
42 .green.length = 8,
43 .blue.offset = 0,
44 .blue.length = 8,
45 .left_margin = 0,
46 .right_margin = 0,
47 .upper_margin = 0,
48 .lower_margin = 0,
49 .vmode = FB_VMODE_NONINTERLACED,
50};
51static struct fb_fix_screeninfo rgbfb_fix __initdata = {
52 .id = "RGBFB",
53 .line_length = LCD_X_RES * LCD_BBP,
54 .type = FB_TYPE_PACKED_PIXELS,
55 .visual = FB_VISUAL_TRUECOLOR,
56 .xpanstep = 0,
57 .ypanstep = 0,
58 .ywrapstep = 0,
59 .accel = FB_ACCEL_NONE,
60};
61
62static int channel_owned;
63
64static int no_cursor(struct fb_info *info, struct fb_cursor *cursor)
65{
66 return 0;
67}
68
69static int rgbfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
70 u_int transp, struct fb_info *info)
71{
72 if (regno > 15)
73 return 1;
74
75 colreg[regno] = ((red & 0xff00) << 8) | (green & 0xff00) |
76 ((blue & 0xff00) >> 8);
77 return 0;
78}
79
80static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
81{
82 return pnx4008_sdum_mmap(info, vma, NULL);
83}
84
85static struct fb_ops rgbfb_ops = {
86 .fb_mmap = rgbfb_mmap,
87 .fb_setcolreg = rgbfb_setcolreg,
88 .fb_fillrect = cfb_fillrect,
89 .fb_copyarea = cfb_copyarea,
90 .fb_imageblit = cfb_imageblit,
91};
92
93static int rgbfb_remove(struct platform_device *pdev)
94{
95 struct fb_info *info = platform_get_drvdata(pdev);
96
97 if (info) {
98 unregister_framebuffer(info);
99 fb_dealloc_cmap(&info->cmap);
100 framebuffer_release(info);
101 platform_set_drvdata(pdev, NULL);
102 }
103
104 pnx4008_free_dum_channel(channel_owned, pdev->id);
105 pnx4008_set_dum_exit_notification(pdev->id);
106
107 return 0;
108}
109
110static int __devinit rgbfb_probe(struct platform_device *pdev)
111{
112 struct fb_info *info;
113 struct dumchannel_uf chan_uf;
114 int ret;
115 char *option;
116
117 info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev);
118 if (!info) {
119 ret = -ENOMEM;
120 goto err;
121 }
122
123 pnx4008_get_fb_addresses(FB_TYPE_RGB, (void **)&info->screen_base,
124 (dma_addr_t *) &rgbfb_fix.smem_start,
125 &rgbfb_fix.smem_len);
126
127 if ((ret = pnx4008_alloc_dum_channel(pdev->id)) < 0)
128 goto err0;
129 else {
130 channel_owned = ret;
131 chan_uf.channelnr = channel_owned;
132 chan_uf.dirty = (u32 *) NULL;
133 chan_uf.source = (u32 *) rgbfb_fix.smem_start;
134 chan_uf.x_offset = 0;
135 chan_uf.y_offset = 0;
136 chan_uf.width = LCD_X_RES;
137 chan_uf.height = LCD_Y_RES;
138
139 if ((ret = pnx4008_put_dum_channel_uf(chan_uf, pdev->id))< 0)
140 goto err1;
141
142 if ((ret =
143 pnx4008_set_dum_channel_sync(channel_owned, CONF_SYNC_ON,
144 pdev->id)) < 0)
145 goto err1;
146
147 if ((ret =
148 pnx4008_set_dum_channel_dirty_detect(channel_owned,
149 CONF_DIRTYDETECTION_ON,
150 pdev->id)) < 0)
151 goto err1;
152 }
153
154 if (!fb_get_options("pnxrgbfb", &option) && option &&
155 !strcmp(option, "nocursor"))
156 rgbfb_ops.fb_cursor = no_cursor;
157
158 info->node = -1;
159 info->flags = FBINFO_FLAG_DEFAULT;
160 info->fbops = &rgbfb_ops;
161 info->fix = rgbfb_fix;
162 info->var = rgbfb_var;
163 info->screen_size = rgbfb_fix.smem_len;
164 info->pseudo_palette = info->par;
165 info->par = NULL;
166
167 ret = fb_alloc_cmap(&info->cmap, 256, 0);
168 if (ret < 0)
169 goto err1;
170
171 ret = register_framebuffer(info);
172 if (ret < 0)
173 goto err2;
174 platform_set_drvdata(pdev, info);
175
176 return 0;
177
178err2:
179 fb_dealloc_cmap(&info->cmap);
180err1:
181 pnx4008_free_dum_channel(channel_owned, pdev->id);
182err0:
183 framebuffer_release(info);
184err:
185 return ret;
186}
187
188static struct platform_driver rgbfb_driver = {
189 .driver = {
190 .name = "pnx4008-rgbfb",
191 },
192 .probe = rgbfb_probe,
193 .remove = rgbfb_remove,
194};
195
196module_platform_driver(rgbfb_driver);
197
198MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
deleted file mode 100644
index c5c741452cac..000000000000
--- a/drivers/video/pnx4008/sdum.c
+++ /dev/null
@@ -1,861 +0,0 @@
1/*
2 * drivers/video/pnx4008/sdum.c
3 *
4 * Display Update Master support
5 *
6 * Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com>
7 * Vitaly Wool <vitalywool@gmail.com>
8 * Based on Philips Semiconductors's code
9 *
10 * Copyrght (c) 2005-2006 MontaVista Software, Inc.
11 * Copyright (c) 2005 Philips Semiconductors
12 * This file is licensed under the terms of the GNU General Public License
13 * version 2. This program is licensed "as is" without any warranty of any
14 * kind, whether express or implied.
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/mm.h>
22#include <linux/tty.h>
23#include <linux/vmalloc.h>
24#include <linux/delay.h>
25#include <linux/interrupt.h>
26#include <linux/platform_device.h>
27#include <linux/fb.h>
28#include <linux/init.h>
29#include <linux/dma-mapping.h>
30#include <linux/clk.h>
31#include <linux/gfp.h>
32#include <asm/uaccess.h>
33#include <asm/gpio.h>
34
35#include "sdum.h"
36#include "fbcommon.h"
37#include "dum.h"
38
39/* Framebuffers we have */
40
41static struct pnx4008_fb_addr {
42 int fb_type;
43 long addr_offset;
44 long fb_length;
45} fb_addr[] = {
46 [0] = {
47 FB_TYPE_YUV, 0, 0xB0000
48 },
49 [1] = {
50 FB_TYPE_RGB, 0xB0000, 0x50000
51 },
52};
53
54static struct dum_data {
55 u32 lcd_phys_start;
56 u32 lcd_virt_start;
57 u32 slave_phys_base;
58 u32 *slave_virt_base;
59 int fb_owning_channel[MAX_DUM_CHANNELS];
60 struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS];
61} dum_data;
62
63/* Different local helper functions */
64
65static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup)
66{
67 return (ch_setup->xmax - ch_setup->xmin + 1);
68}
69
70static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup)
71{
72 return (ch_setup->ymax - ch_setup->ymin + 1);
73}
74
75static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup)
76{
77 return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup));
78}
79
80static u32 nof_bytes(struct dum_ch_setup *ch_setup)
81{
82 u32 r = nof_pixels_dxy(ch_setup);
83 switch (ch_setup->format) {
84 case RGB888:
85 case RGB666:
86 r *= 4;
87 break;
88
89 default:
90 r *= 2;
91 break;
92 }
93 return r;
94}
95
96static u32 build_command(int disp_no, u32 reg, u32 val)
97{
98 return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) |
99 (reg << 0));
100}
101
102static u32 build_double_index(int disp_no, u32 val)
103{
104 return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0));
105}
106
107static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw)
108{
109 dw->ymin = ch_setup->ymin;
110 dw->ymax = ch_setup->ymax;
111 dw->xmin_l = ch_setup->xmin & 0xFF;
112 dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8;
113 dw->xmax_l = ch_setup->xmax & 0xFF;
114 dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8;
115}
116
117static int put_channel(struct dumchannel chan)
118{
119 int i = chan.channelnr;
120
121 if (i < 0 || i > MAX_DUM_CHANNELS)
122 return -EINVAL;
123 else {
124 DUM_CH_MIN(i) = chan.dum_ch_min;
125 DUM_CH_MAX(i) = chan.dum_ch_max;
126 DUM_CH_CONF(i) = chan.dum_ch_conf;
127 DUM_CH_CTRL(i) = chan.dum_ch_ctrl;
128 }
129
130 return 0;
131}
132
133static void clear_channel(int channr)
134{
135 struct dumchannel chan;
136
137 chan.channelnr = channr;
138 chan.dum_ch_min = 0;
139 chan.dum_ch_max = 0;
140 chan.dum_ch_conf = 0;
141 chan.dum_ch_ctrl = 0;
142
143 put_channel(chan);
144}
145
146static int put_cmd_string(struct cmdstring cmds)
147{
148 u16 *cmd_str_virtaddr;
149 u32 *cmd_ptr0_virtaddr;
150 u32 cmd_str_physaddr;
151
152 int i = cmds.channelnr;
153
154 if (i < 0 || i > MAX_DUM_CHANNELS)
155 return -EINVAL;
156 else if ((cmd_ptr0_virtaddr =
157 (int *)ioremap_nocache(DUM_COM_BASE,
158 sizeof(int) * MAX_DUM_CHANNELS)) ==
159 NULL)
160 return -EIOREMAPFAILED;
161 else {
162 cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]);
163 if ((cmd_str_virtaddr =
164 (u16 *) ioremap_nocache(cmd_str_physaddr,
165 sizeof(cmds))) == NULL) {
166 iounmap(cmd_ptr0_virtaddr);
167 return -EIOREMAPFAILED;
168 } else {
169 int t;
170 for (t = 0; t < 8; t++)
171 iowrite16(*((u16 *)&cmds.prestringlen + t),
172 cmd_str_virtaddr + t);
173
174 for (t = 0; t < cmds.prestringlen / 2; t++)
175 iowrite16(*((u16 *)&cmds.precmd + t),
176 cmd_str_virtaddr + t + 8);
177
178 for (t = 0; t < cmds.poststringlen / 2; t++)
179 iowrite16(*((u16 *)&cmds.postcmd + t),
180 cmd_str_virtaddr + t + 8 +
181 cmds.prestringlen / 2);
182
183 iounmap(cmd_ptr0_virtaddr);
184 iounmap(cmd_str_virtaddr);
185 }
186 }
187
188 return 0;
189}
190
191static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup)
192{
193 struct cmdstring cmds_c;
194 struct cmdstring *cmds = &cmds_c;
195 struct disp_window dw;
196 int standard;
197 u32 orientation = 0;
198 struct dumchannel chan = { 0 };
199 int ret;
200
201 if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) {
202 standard = 0;
203
204 orientation = BIT(1); /* always set 9-bit-bus */
205 if (ch_setup->xmirror)
206 orientation |= BIT(4);
207 if (ch_setup->ymirror)
208 orientation |= BIT(3);
209 if (ch_setup->rotate)
210 orientation |= BIT(0);
211 } else
212 standard = 1;
213
214 cmds->channelnr = ch_no;
215
216 /* build command string header */
217 if (standard) {
218 cmds->prestringlen = 32;
219 cmds->poststringlen = 0;
220 } else {
221 cmds->prestringlen = 48;
222 cmds->poststringlen = 16;
223 }
224
225 cmds->format =
226 (u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format));
227 cmds->reserved = 0x0;
228 cmds->startaddr_low = (ch_setup->minadr & 0xFFFF);
229 cmds->startaddr_high = (ch_setup->minadr >> 16);
230
231 if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0)
232 && (ch_setup->xmin == 0)
233 && (ch_setup->ymin == 0) && (ch_setup->xmax == 0)
234 && (ch_setup->ymax == 0)) {
235 cmds->pixdatlen_low = 0;
236 cmds->pixdatlen_high = 0;
237 } else {
238 u32 nbytes = nof_bytes(ch_setup);
239 cmds->pixdatlen_low = (nbytes & 0xFFFF);
240 cmds->pixdatlen_high = (nbytes >> 16);
241 }
242
243 if (ch_setup->slave_trans)
244 cmds->pixdatlen_high |= BIT(15);
245
246 /* build pre-string */
247 build_disp_window(ch_setup, &dw);
248
249 if (standard) {
250 cmds->precmd[0] =
251 build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99);
252 cmds->precmd[1] =
253 build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
254 dw.xmin_l);
255 cmds->precmd[2] =
256 build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
257 dw.xmin_h);
258 cmds->precmd[3] =
259 build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
260 cmds->precmd[4] =
261 build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
262 dw.xmax_l);
263 cmds->precmd[5] =
264 build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
265 dw.xmax_h);
266 cmds->precmd[6] =
267 build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
268 cmds->precmd[7] =
269 build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
270 } else {
271 if (dw.xmin_l == ch_no)
272 cmds->precmd[0] =
273 build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
274 0x99);
275 else
276 cmds->precmd[0] =
277 build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
278 ch_no);
279
280 cmds->precmd[1] =
281 build_command(ch_setup->disp_no, DISP_XMIN_L_REG,
282 dw.xmin_l);
283 cmds->precmd[2] =
284 build_command(ch_setup->disp_no, DISP_XMIN_H_REG,
285 dw.xmin_h);
286 cmds->precmd[3] =
287 build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin);
288 cmds->precmd[4] =
289 build_command(ch_setup->disp_no, DISP_XMAX_L_REG,
290 dw.xmax_l);
291 cmds->precmd[5] =
292 build_command(ch_setup->disp_no, DISP_XMAX_H_REG,
293 dw.xmax_h);
294 cmds->precmd[6] =
295 build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax);
296 cmds->precmd[7] =
297 build_command(ch_setup->disp_no, DISP_1_REG, orientation);
298 cmds->precmd[8] =
299 build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
300 cmds->precmd[9] =
301 build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
302 cmds->precmd[0xA] =
303 build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
304 cmds->precmd[0xB] =
305 build_double_index(ch_setup->disp_no, DISP_PIXEL_REG);
306 cmds->postcmd[0] =
307 build_command(ch_setup->disp_no, DISP_1_REG, BIT(1));
308 cmds->postcmd[1] =
309 build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1);
310 cmds->postcmd[2] =
311 build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2);
312 cmds->postcmd[3] =
313 build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3);
314 }
315
316 if ((ret = put_cmd_string(cmds_c)) != 0) {
317 return ret;
318 }
319
320 chan.channelnr = cmds->channelnr;
321 chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr;
322 chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr;
323 chan.dum_ch_conf = 0x002;
324 chan.dum_ch_ctrl = 0x04;
325
326 put_channel(chan);
327
328 return 0;
329}
330
331static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer,
332 u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h)
333{
334
335 struct dum_ch_setup k;
336 int ret;
337
338 /* keep width & height within display area */
339 if ((xpos + w) > DISP_MAX_X_SIZE)
340 w = DISP_MAX_X_SIZE - xpos;
341
342 if ((ypos + h) > DISP_MAX_Y_SIZE)
343 h = DISP_MAX_Y_SIZE - ypos;
344
345 /* assume 1 display only */
346 k.disp_no = 0;
347 k.xmin = xpos;
348 k.ymin = ypos;
349 k.xmax = xpos + (w - 1);
350 k.ymax = ypos + (h - 1);
351
352 /* adjust min and max values if necessary */
353 if (k.xmin > DISP_MAX_X_SIZE - 1)
354 k.xmin = DISP_MAX_X_SIZE - 1;
355 if (k.ymin > DISP_MAX_Y_SIZE - 1)
356 k.ymin = DISP_MAX_Y_SIZE - 1;
357
358 if (k.xmax > DISP_MAX_X_SIZE - 1)
359 k.xmax = DISP_MAX_X_SIZE - 1;
360 if (k.ymax > DISP_MAX_Y_SIZE - 1)
361 k.ymax = DISP_MAX_Y_SIZE - 1;
362
363 k.xmirror = 0;
364 k.ymirror = 0;
365 k.rotate = 0;
366 k.minadr = (u32) frame_buffer;
367 k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2));
368 k.pad = PAD_1024;
369 k.dirtybuffer = (u32) dirty_buffer;
370 k.format = RGB888;
371 k.hwdirty = 0;
372 k.slave_trans = 0;
373
374 ret = dum_ch_setup(ch_no, &k);
375
376 return ret;
377}
378
379static void lcd_reset(void)
380{
381 u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE);
382
383 udelay(1);
384 iowrite32(BIT(19), &dum_pio_base[2]);
385 udelay(1);
386 iowrite32(BIT(19), &dum_pio_base[1]);
387 udelay(1);
388}
389
390static int dum_init(struct platform_device *pdev)
391{
392 struct clk *clk;
393
394 /* enable DUM clock */
395 clk = clk_get(&pdev->dev, "dum_ck");
396 if (IS_ERR(clk)) {
397 printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n");
398 return PTR_ERR(clk);
399 }
400
401 clk_set_rate(clk, 1);
402 clk_put(clk);
403
404 DUM_CTRL = V_DUM_RESET;
405
406 /* set priority to "round-robin". All other params to "false" */
407 DUM_CONF = BIT(9);
408
409 /* Display 1 */
410 DUM_WTCFG1 = PNX4008_DUM_WT_CFG;
411 DUM_RTCFG1 = PNX4008_DUM_RT_CFG;
412 DUM_TCFG = PNX4008_DUM_T_CFG;
413
414 return 0;
415}
416
417static void dum_chan_init(void)
418{
419 int i = 0, ch = 0;
420 u32 *cmdptrs;
421 u32 *cmdstrings;
422
423 DUM_COM_BASE =
424 CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS;
425
426 if ((cmdptrs =
427 (u32 *) ioremap_nocache(DUM_COM_BASE,
428 sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL)
429 return;
430
431 for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++)
432 iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch,
433 cmdptrs + ch);
434
435 for (ch = 0; ch < MAX_DUM_CHANNELS; ch++)
436 clear_channel(ch);
437
438 /* Clear the cmdstrings */
439 cmdstrings =
440 (u32 *)ioremap_nocache(*cmdptrs,
441 BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS);
442
443 if (!cmdstrings)
444 goto out;
445
446 for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32);
447 i++)
448 iowrite32(0, cmdstrings + i);
449
450 iounmap((u32 *)cmdstrings);
451
452out:
453 iounmap((u32 *)cmdptrs);
454}
455
456static void lcd_init(void)
457{
458 lcd_reset();
459
460 DUM_OUTP_FORMAT1 = 0; /* RGB666 */
461
462 udelay(1);
463 iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base);
464 udelay(1);
465 iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base);
466 udelay(1);
467 iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base);
468 udelay(1);
469 iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base);
470 udelay(1);
471 iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base);
472 udelay(1);
473 iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base);
474 udelay(1);
475 iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base);
476 udelay(1);
477 iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base);
478 udelay(1);
479}
480
481/* Interface exported to framebuffer drivers */
482
483int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
484 dma_addr_t *phys_addr, int *fb_length)
485{
486 int i;
487 int ret = -1;
488 for (i = 0; i < ARRAY_SIZE(fb_addr); i++)
489 if (fb_addr[i].fb_type == fb_type) {
490 *virt_addr = (void *)(dum_data.lcd_virt_start +
491 fb_addr[i].addr_offset);
492 *phys_addr =
493 dum_data.lcd_phys_start + fb_addr[i].addr_offset;
494 *fb_length = fb_addr[i].fb_length;
495 ret = 0;
496 break;
497 }
498
499 return ret;
500}
501
502EXPORT_SYMBOL(pnx4008_get_fb_addresses);
503
504int pnx4008_alloc_dum_channel(int dev_id)
505{
506 int i = 0;
507
508 while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1))
509 i++;
510
511 if (i == MAX_DUM_CHANNELS)
512 return -ENORESOURCESLEFT;
513 else {
514 dum_data.fb_owning_channel[i] = dev_id;
515 return i;
516 }
517}
518
519EXPORT_SYMBOL(pnx4008_alloc_dum_channel);
520
521int pnx4008_free_dum_channel(int channr, int dev_id)
522{
523 if (channr < 0 || channr > MAX_DUM_CHANNELS)
524 return -EINVAL;
525 else if (dum_data.fb_owning_channel[channr] != dev_id)
526 return -EFBNOTOWNER;
527 else {
528 clear_channel(channr);
529 dum_data.fb_owning_channel[channr] = -1;
530 }
531
532 return 0;
533}
534
535EXPORT_SYMBOL(pnx4008_free_dum_channel);
536
537int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id)
538{
539 int i = chan_uf.channelnr;
540 int ret;
541
542 if (i < 0 || i > MAX_DUM_CHANNELS)
543 return -EINVAL;
544 else if (dum_data.fb_owning_channel[i] != dev_id)
545 return -EFBNOTOWNER;
546 else if ((ret =
547 display_open(chan_uf.channelnr, 0, chan_uf.dirty,
548 chan_uf.source, chan_uf.y_offset,
549 chan_uf.x_offset, chan_uf.height,
550 chan_uf.width)) != 0)
551 return ret;
552 else {
553 dum_data.chan_uf_store[i].dirty = chan_uf.dirty;
554 dum_data.chan_uf_store[i].source = chan_uf.source;
555 dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset;
556 dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset;
557 dum_data.chan_uf_store[i].width = chan_uf.width;
558 dum_data.chan_uf_store[i].height = chan_uf.height;
559 }
560
561 return 0;
562}
563
564EXPORT_SYMBOL(pnx4008_put_dum_channel_uf);
565
566int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id)
567{
568 if (channr < 0 || channr > MAX_DUM_CHANNELS)
569 return -EINVAL;
570 else if (dum_data.fb_owning_channel[channr] != dev_id)
571 return -EFBNOTOWNER;
572 else {
573 if (val == CONF_SYNC_ON) {
574 DUM_CH_CONF(channr) |= CONF_SYNCENABLE;
575 DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK |
576 DUM_CHANNEL_CFG_SYNC_MASK_SET;
577 } else if (val == CONF_SYNC_OFF)
578 DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE;
579 else
580 return -EINVAL;
581 }
582
583 return 0;
584}
585
586EXPORT_SYMBOL(pnx4008_set_dum_channel_sync);
587
588int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id)
589{
590 if (channr < 0 || channr > MAX_DUM_CHANNELS)
591 return -EINVAL;
592 else if (dum_data.fb_owning_channel[channr] != dev_id)
593 return -EFBNOTOWNER;
594 else {
595 if (val == CONF_DIRTYDETECTION_ON)
596 DUM_CH_CONF(channr) |= CONF_DIRTYENABLE;
597 else if (val == CONF_DIRTYDETECTION_OFF)
598 DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE;
599 else
600 return -EINVAL;
601 }
602
603 return 0;
604}
605
606EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect);
607
608#if 0 /* Functions not used currently, but likely to be used in future */
609
610static int get_channel(struct dumchannel *p_chan)
611{
612 int i = p_chan->channelnr;
613
614 if (i < 0 || i > MAX_DUM_CHANNELS)
615 return -EINVAL;
616 else {
617 p_chan->dum_ch_min = DUM_CH_MIN(i);
618 p_chan->dum_ch_max = DUM_CH_MAX(i);
619 p_chan->dum_ch_conf = DUM_CH_CONF(i);
620 p_chan->dum_ch_stat = DUM_CH_STAT(i);
621 p_chan->dum_ch_ctrl = 0; /* WriteOnly control register */
622 }
623
624 return 0;
625}
626
627int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id)
628{
629 int i = p_chan_uf->channelnr;
630
631 if (i < 0 || i > MAX_DUM_CHANNELS)
632 return -EINVAL;
633 else if (dum_data.fb_owning_channel[i] != dev_id)
634 return -EFBNOTOWNER;
635 else {
636 p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty;
637 p_chan_uf->source = dum_data.chan_uf_store[i].source;
638 p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset;
639 p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset;
640 p_chan_uf->width = dum_data.chan_uf_store[i].width;
641 p_chan_uf->height = dum_data.chan_uf_store[i].height;
642 }
643
644 return 0;
645}
646
647EXPORT_SYMBOL(pnx4008_get_dum_channel_uf);
648
649int pnx4008_get_dum_channel_config(int channr, int dev_id)
650{
651 int ret;
652 struct dumchannel chan;
653
654 if (channr < 0 || channr > MAX_DUM_CHANNELS)
655 return -EINVAL;
656 else if (dum_data.fb_owning_channel[channr] != dev_id)
657 return -EFBNOTOWNER;
658 else {
659 chan.channelnr = channr;
660 if ((ret = get_channel(&chan)) != 0)
661 return ret;
662 }
663
664 return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK);
665}
666
667EXPORT_SYMBOL(pnx4008_get_dum_channel_config);
668
669int pnx4008_force_update_dum_channel(int channr, int dev_id)
670{
671 if (channr < 0 || channr > MAX_DUM_CHANNELS)
672 return -EINVAL;
673
674 else if (dum_data.fb_owning_channel[channr] != dev_id)
675 return -EFBNOTOWNER;
676 else
677 DUM_CH_CTRL(channr) = CTRL_SETDIRTY;
678
679 return 0;
680}
681
682EXPORT_SYMBOL(pnx4008_force_update_dum_channel);
683
684#endif
685
686int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma,
687 struct device *dev)
688{
689 unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
690
691 if (off < info->fix.smem_len) {
692 vma->vm_pgoff += 1;
693 return dma_mmap_writecombine(dev, vma,
694 (void *)dum_data.lcd_virt_start,
695 dum_data.lcd_phys_start,
696 FB_DMA_SIZE);
697 }
698 return -EINVAL;
699}
700
701EXPORT_SYMBOL(pnx4008_sdum_mmap);
702
703int pnx4008_set_dum_exit_notification(int dev_id)
704{
705 int i;
706
707 for (i = 0; i < MAX_DUM_CHANNELS; i++)
708 if (dum_data.fb_owning_channel[i] == dev_id)
709 return -ERESOURCESNOTFREED;
710
711 return 0;
712}
713
714EXPORT_SYMBOL(pnx4008_set_dum_exit_notification);
715
716/* Platform device driver for DUM */
717
718static int sdum_suspend(struct platform_device *pdev, pm_message_t state)
719{
720 int retval = 0;
721 struct clk *clk;
722
723 clk = clk_get(0, "dum_ck");
724 if (!IS_ERR(clk)) {
725 clk_set_rate(clk, 0);
726 clk_put(clk);
727 } else
728 retval = PTR_ERR(clk);
729
730 /* disable BAC */
731 DUM_CTRL = V_BAC_DISABLE_IDLE;
732
733 /* LCD standby & turn off display */
734 lcd_reset();
735
736 return retval;
737}
738
739static int sdum_resume(struct platform_device *pdev)
740{
741 int retval = 0;
742 struct clk *clk;
743
744 clk = clk_get(0, "dum_ck");
745 if (!IS_ERR(clk)) {
746 clk_set_rate(clk, 1);
747 clk_put(clk);
748 } else
749 retval = PTR_ERR(clk);
750
751 /* wait for BAC disable */
752 DUM_CTRL = V_BAC_DISABLE_TRIG;
753
754 while (DUM_CTRL & BAC_ENABLED)
755 udelay(10);
756
757 /* re-init LCD */
758 lcd_init();
759
760 /* enable BAC and reset MUX */
761 DUM_CTRL = V_BAC_ENABLE;
762 udelay(1);
763 DUM_CTRL = V_MUX_RESET;
764 return 0;
765}
766
767static int __devinit sdum_probe(struct platform_device *pdev)
768{
769 int ret = 0, i = 0;
770
771 /* map frame buffer */
772 dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev,
773 FB_DMA_SIZE,
774 &dum_data.lcd_phys_start,
775 GFP_KERNEL);
776
777 if (!dum_data.lcd_virt_start) {
778 ret = -ENOMEM;
779 goto out_3;
780 }
781
782 /* map slave registers */
783 dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE;
784 dum_data.slave_virt_base =
785 (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32));
786
787 if (dum_data.slave_virt_base == NULL) {
788 ret = -ENOMEM;
789 goto out_2;
790 }
791
792 /* initialize DUM and LCD display */
793 ret = dum_init(pdev);
794 if (ret)
795 goto out_1;
796
797 dum_chan_init();
798 lcd_init();
799
800 DUM_CTRL = V_BAC_ENABLE;
801 udelay(1);
802 DUM_CTRL = V_MUX_RESET;
803
804 /* set decode address and sync clock divider */
805 DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK;
806 DUM_CLK_DIV = PNX4008_DUM_CLK_DIV;
807
808 for (i = 0; i < MAX_DUM_CHANNELS; i++)
809 dum_data.fb_owning_channel[i] = -1;
810
811 /*setup wakeup interrupt */
812 start_int_set_rising_edge(SE_DISP_SYNC_INT);
813 start_int_ack(SE_DISP_SYNC_INT);
814 start_int_umask(SE_DISP_SYNC_INT);
815
816 return 0;
817
818out_1:
819 iounmap((void *)dum_data.slave_virt_base);
820out_2:
821 dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
822 (void *)dum_data.lcd_virt_start,
823 dum_data.lcd_phys_start);
824out_3:
825 return ret;
826}
827
828static int sdum_remove(struct platform_device *pdev)
829{
830 struct clk *clk;
831
832 start_int_mask(SE_DISP_SYNC_INT);
833
834 clk = clk_get(0, "dum_ck");
835 if (!IS_ERR(clk)) {
836 clk_set_rate(clk, 0);
837 clk_put(clk);
838 }
839
840 iounmap((void *)dum_data.slave_virt_base);
841
842 dma_free_writecombine(&pdev->dev, FB_DMA_SIZE,
843 (void *)dum_data.lcd_virt_start,
844 dum_data.lcd_phys_start);
845
846 return 0;
847}
848
849static struct platform_driver sdum_driver = {
850 .driver = {
851 .name = "pnx4008-sdum",
852 },
853 .probe = sdum_probe,
854 .remove = sdum_remove,
855 .suspend = sdum_suspend,
856 .resume = sdum_resume,
857};
858
859module_platform_driver(sdum_driver);
860
861MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.h b/drivers/video/pnx4008/sdum.h
deleted file mode 100644
index 189c3d641383..000000000000
--- a/drivers/video/pnx4008/sdum.h
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 * Copyright (C) 2005 Philips Semiconductors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html
18*/
19
20#define MAX_DUM_CHANNELS 64
21
22#define RGB_MEM_WINDOW(x) (0x10000000 + (x)*0x00100000)
23
24#define QCIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x30000: -1)
25#define CIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x60000: -1)
26
27#define CTRL_SETDIRTY (0x00000001)
28#define CONF_DIRTYENABLE (0x00000020)
29#define CONF_SYNCENABLE (0x00000004)
30
31#define DIRTY_ENABLED(conf) ((conf) & 0x0020)
32#define SYNC_ENABLED(conf) ((conf) & 0x0004)
33
34/* Display 1 & 2 Write Timing Configuration */
35#define PNX4008_DUM_WT_CFG 0x00372000
36
37/* Display 1 & 2 Read Timing Configuration */
38#define PNX4008_DUM_RT_CFG 0x00003A47
39
40/* DUM Transit State Timing Configuration */
41#define PNX4008_DUM_T_CFG 0x1D /* 29 HCLK cycles */
42
43/* DUM Sync count clock divider */
44#define PNX4008_DUM_CLK_DIV 0x02DD
45
46/* Memory size for framebuffer, allocated through dma_alloc_writecombine().
47 * Must be PAGE aligned
48 */
49#define FB_DMA_SIZE (PAGE_ALIGN(SZ_1M + PAGE_SIZE))
50
51#define OFFSET_RGBBUFFER (0xB0000)
52#define OFFSET_YUVBUFFER (0x00000)
53
54#define YUVBUFFER (lcd_video_start + OFFSET_YUVBUFFER)
55#define RGBBUFFER (lcd_video_start + OFFSET_RGBBUFFER)
56
57#define CMDSTRING_BASEADDR (0x00C000) /* iram */
58#define BYTES_PER_CMDSTRING (0x80)
59#define NR_OF_CMDSTRINGS (64)
60
61#define MAX_NR_PRESTRINGS (0x40)
62#define MAX_NR_POSTSTRINGS (0x40)
63
64/* various mask definitions */
65#define DUM_CLK_ENABLE 0x01
66#define DUM_CLK_DISABLE 0
67#define DUM_DECODE_MASK 0x1FFFFFFF
68#define DUM_CHANNEL_CFG_MASK 0x01FF
69#define DUM_CHANNEL_CFG_SYNC_MASK 0xFFFE00FF
70#define DUM_CHANNEL_CFG_SYNC_MASK_SET 0x0CA00
71
72#define SDUM_RETURNVAL_BASE (0x500)
73
74#define CONF_SYNC_OFF (0x602)
75#define CONF_SYNC_ON (0x603)
76
77#define CONF_DIRTYDETECTION_OFF (0x600)
78#define CONF_DIRTYDETECTION_ON (0x601)
79
80struct dumchannel_uf {
81 int channelnr;
82 u32 *dirty;
83 u32 *source;
84 u32 x_offset;
85 u32 y_offset;
86 u32 width;
87 u32 height;
88};
89
90enum {
91 FB_TYPE_YUV,
92 FB_TYPE_RGB
93};
94
95struct cmdstring {
96 int channelnr;
97 uint16_t prestringlen;
98 uint16_t poststringlen;
99 uint16_t format;
100 uint16_t reserved;
101 uint16_t startaddr_low;
102 uint16_t startaddr_high;
103 uint16_t pixdatlen_low;
104 uint16_t pixdatlen_high;
105 u32 precmd[MAX_NR_PRESTRINGS];
106 u32 postcmd[MAX_NR_POSTSTRINGS];
107
108};
109
110struct dumchannel {
111 int channelnr;
112 int dum_ch_min;
113 int dum_ch_max;
114 int dum_ch_conf;
115 int dum_ch_stat;
116 int dum_ch_ctrl;
117};
118
119int pnx4008_alloc_dum_channel(int dev_id);
120int pnx4008_free_dum_channel(int channr, int dev_id);
121
122int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id);
123int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id);
124
125int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id);
126int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id);
127
128int pnx4008_force_dum_update_channel(int channr, int dev_id);
129
130int pnx4008_get_dum_channel_config(int channr, int dev_id);
131
132int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev);
133int pnx4008_set_dum_exit_notification(int dev_id);
134
135int pnx4008_get_fb_addresses(int fb_type, void **virt_addr,
136 dma_addr_t * phys_addr, int *fb_length);
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 4e292f29bf5d..0b340d6ff8a4 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1034,6 +1034,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1034 if (status) { 1034 if (status) {
1035 dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n", 1035 dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n",
1036 __func__, status); 1036 __func__, status);
1037 retval = -ENOMEM;
1037 goto err_close_device; 1038 goto err_close_device;
1038 } 1039 }
1039 dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar); 1040 dev_dbg(&dev->core, "ddr:lpar:0x%llx\n", ddr_lpar);
@@ -1046,6 +1047,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1046 dev_err(&dev->core, 1047 dev_err(&dev->core,
1047 "%s: lv1_gpu_context_allocate failed: %d\n", __func__, 1048 "%s: lv1_gpu_context_allocate failed: %d\n", __func__,
1048 status); 1049 status);
1050 retval = -ENOMEM;
1049 goto err_gpu_memory_free; 1051 goto err_gpu_memory_free;
1050 } 1052 }
1051 1053
@@ -1053,6 +1055,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1053 dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); 1055 dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024);
1054 if (!dinfo) { 1056 if (!dinfo) {
1055 dev_err(&dev->core, "%s: ioremap failed\n", __func__); 1057 dev_err(&dev->core, "%s: ioremap failed\n", __func__);
1058 retval = -ENOMEM;
1056 goto err_gpu_context_free; 1059 goto err_gpu_context_free;
1057 } 1060 }
1058 1061
@@ -1121,8 +1124,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
1121 } 1124 }
1122 1125
1123 info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); 1126 info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core);
1124 if (!info) 1127 if (!info) {
1128 retval = -ENOMEM;
1125 goto err_context_fb_close; 1129 goto err_context_fb_close;
1130 }
1126 1131
1127 par = info->par; 1132 par = info->par;
1128 par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ 1133 par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 69bf9d07c237..2ed7b633bbd9 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -25,8 +25,8 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/pm_runtime.h> 26#include <linux/pm_runtime.h>
27 27
28#include <video/samsung_fimd.h>
28#include <mach/map.h> 29#include <mach/map.h>
29#include <plat/regs-fb-v4.h>
30#include <plat/fb.h> 30#include <plat/fb.h>
31 31
32/* This driver will export a number of framebuffer interfaces depending 32/* This driver will export a number of framebuffer interfaces depending
@@ -1398,35 +1398,28 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1398 1398
1399 spin_lock_init(&sfb->slock); 1399 spin_lock_init(&sfb->slock);
1400 1400
1401 sfb->bus_clk = clk_get(dev, "lcd"); 1401 sfb->bus_clk = devm_clk_get(dev, "lcd");
1402 if (IS_ERR(sfb->bus_clk)) { 1402 if (IS_ERR(sfb->bus_clk)) {
1403 dev_err(dev, "failed to get bus clock\n"); 1403 dev_err(dev, "failed to get bus clock\n");
1404 ret = PTR_ERR(sfb->bus_clk); 1404 return PTR_ERR(sfb->bus_clk);
1405 goto err_sfb;
1406 } 1405 }
1407 1406
1408 clk_enable(sfb->bus_clk); 1407 clk_prepare_enable(sfb->bus_clk);
1409 1408
1410 if (!sfb->variant.has_clksel) { 1409 if (!sfb->variant.has_clksel) {
1411 sfb->lcd_clk = clk_get(dev, "sclk_fimd"); 1410 sfb->lcd_clk = devm_clk_get(dev, "sclk_fimd");
1412 if (IS_ERR(sfb->lcd_clk)) { 1411 if (IS_ERR(sfb->lcd_clk)) {
1413 dev_err(dev, "failed to get lcd clock\n"); 1412 dev_err(dev, "failed to get lcd clock\n");
1414 ret = PTR_ERR(sfb->lcd_clk); 1413 ret = PTR_ERR(sfb->lcd_clk);
1415 goto err_bus_clk; 1414 goto err_bus_clk;
1416 } 1415 }
1417 1416
1418 clk_enable(sfb->lcd_clk); 1417 clk_prepare_enable(sfb->lcd_clk);
1419 } 1418 }
1420 1419
1421 pm_runtime_enable(sfb->dev); 1420 pm_runtime_enable(sfb->dev);
1422 1421
1423 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1422 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1424 if (!res) {
1425 dev_err(dev, "failed to find registers\n");
1426 ret = -ENOENT;
1427 goto err_lcd_clk;
1428 }
1429
1430 sfb->regs = devm_request_and_ioremap(dev, res); 1423 sfb->regs = devm_request_and_ioremap(dev, res);
1431 if (!sfb->regs) { 1424 if (!sfb->regs) {
1432 dev_err(dev, "failed to map registers\n"); 1425 dev_err(dev, "failed to map registers\n");
@@ -1510,16 +1503,12 @@ err_pm_runtime:
1510err_lcd_clk: 1503err_lcd_clk:
1511 pm_runtime_disable(sfb->dev); 1504 pm_runtime_disable(sfb->dev);
1512 1505
1513 if (!sfb->variant.has_clksel) { 1506 if (!sfb->variant.has_clksel)
1514 clk_disable(sfb->lcd_clk); 1507 clk_disable_unprepare(sfb->lcd_clk);
1515 clk_put(sfb->lcd_clk);
1516 }
1517 1508
1518err_bus_clk: 1509err_bus_clk:
1519 clk_disable(sfb->bus_clk); 1510 clk_disable_unprepare(sfb->bus_clk);
1520 clk_put(sfb->bus_clk);
1521 1511
1522err_sfb:
1523 return ret; 1512 return ret;
1524} 1513}
1525 1514
@@ -1541,13 +1530,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1541 if (sfb->windows[win]) 1530 if (sfb->windows[win])
1542 s3c_fb_release_win(sfb, sfb->windows[win]); 1531 s3c_fb_release_win(sfb, sfb->windows[win]);
1543 1532
1544 if (!sfb->variant.has_clksel) { 1533 if (!sfb->variant.has_clksel)
1545 clk_disable(sfb->lcd_clk); 1534 clk_disable_unprepare(sfb->lcd_clk);
1546 clk_put(sfb->lcd_clk);
1547 }
1548 1535
1549 clk_disable(sfb->bus_clk); 1536 clk_disable_unprepare(sfb->bus_clk);
1550 clk_put(sfb->bus_clk);
1551 1537
1552 pm_runtime_put_sync(sfb->dev); 1538 pm_runtime_put_sync(sfb->dev);
1553 pm_runtime_disable(sfb->dev); 1539 pm_runtime_disable(sfb->dev);
@@ -1575,9 +1561,9 @@ static int s3c_fb_suspend(struct device *dev)
1575 } 1561 }
1576 1562
1577 if (!sfb->variant.has_clksel) 1563 if (!sfb->variant.has_clksel)
1578 clk_disable(sfb->lcd_clk); 1564 clk_disable_unprepare(sfb->lcd_clk);
1579 1565
1580 clk_disable(sfb->bus_clk); 1566 clk_disable_unprepare(sfb->bus_clk);
1581 1567
1582 pm_runtime_put_sync(sfb->dev); 1568 pm_runtime_put_sync(sfb->dev);
1583 1569
@@ -1595,10 +1581,10 @@ static int s3c_fb_resume(struct device *dev)
1595 1581
1596 pm_runtime_get_sync(sfb->dev); 1582 pm_runtime_get_sync(sfb->dev);
1597 1583
1598 clk_enable(sfb->bus_clk); 1584 clk_prepare_enable(sfb->bus_clk);
1599 1585
1600 if (!sfb->variant.has_clksel) 1586 if (!sfb->variant.has_clksel)
1601 clk_enable(sfb->lcd_clk); 1587 clk_prepare_enable(sfb->lcd_clk);
1602 1588
1603 /* setup gpio and output polarity controls */ 1589 /* setup gpio and output polarity controls */
1604 pd->setup_gpio(); 1590 pd->setup_gpio();
@@ -1654,9 +1640,9 @@ static int s3c_fb_runtime_suspend(struct device *dev)
1654 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1640 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1655 1641
1656 if (!sfb->variant.has_clksel) 1642 if (!sfb->variant.has_clksel)
1657 clk_disable(sfb->lcd_clk); 1643 clk_disable_unprepare(sfb->lcd_clk);
1658 1644
1659 clk_disable(sfb->bus_clk); 1645 clk_disable_unprepare(sfb->bus_clk);
1660 1646
1661 return 0; 1647 return 0;
1662} 1648}
@@ -1667,10 +1653,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
1667 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1653 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1668 struct s3c_fb_platdata *pd = sfb->pdata; 1654 struct s3c_fb_platdata *pd = sfb->pdata;
1669 1655
1670 clk_enable(sfb->bus_clk); 1656 clk_prepare_enable(sfb->bus_clk);
1671 1657
1672 if (!sfb->variant.has_clksel) 1658 if (!sfb->variant.has_clksel)
1673 clk_enable(sfb->lcd_clk); 1659 clk_prepare_enable(sfb->lcd_clk);
1674 1660
1675 /* setup gpio and output polarity controls */ 1661 /* setup gpio and output polarity controls */
1676 pd->setup_gpio(); 1662 pd->setup_gpio();
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 77f34c614c86..1083bb9469ee 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -11,6 +11,8 @@
11 * Driver based on skeletonfb.c, sa1100fb.c and others. 11 * Driver based on skeletonfb.c, sa1100fb.c and others.
12*/ 12*/
13 13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
14#include <linux/module.h> 16#include <linux/module.h>
15#include <linux/kernel.h> 17#include <linux/kernel.h>
16#include <linux/err.h> 18#include <linux/err.h>
@@ -48,7 +50,11 @@ static int debug = 1;
48static int debug; 50static int debug;
49#endif 51#endif
50 52
51#define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg); 53#define dprintk(msg...) \
54do { \
55 if (debug) \
56 pr_debug(msg); \
57} while (0)
52 58
53/* useful functions */ 59/* useful functions */
54 60
@@ -598,11 +604,11 @@ static int s3c2410fb_debug_store(struct device *dev,
598 if (strnicmp(buf, "on", 2) == 0 || 604 if (strnicmp(buf, "on", 2) == 0 ||
599 strnicmp(buf, "1", 1) == 0) { 605 strnicmp(buf, "1", 1) == 0) {
600 debug = 1; 606 debug = 1;
601 printk(KERN_DEBUG "s3c2410fb: Debug On"); 607 dev_dbg(dev, "s3c2410fb: Debug On");
602 } else if (strnicmp(buf, "off", 3) == 0 || 608 } else if (strnicmp(buf, "off", 3) == 0 ||
603 strnicmp(buf, "0", 1) == 0) { 609 strnicmp(buf, "0", 1) == 0) {
604 debug = 0; 610 debug = 0;
605 printk(KERN_DEBUG "s3c2410fb: Debug Off"); 611 dev_dbg(dev, "s3c2410fb: Debug Off");
606 } else { 612 } else {
607 return -EINVAL; 613 return -EINVAL;
608 } 614 }
@@ -921,7 +927,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
921 927
922 info->clk = clk_get(NULL, "lcd"); 928 info->clk = clk_get(NULL, "lcd");
923 if (IS_ERR(info->clk)) { 929 if (IS_ERR(info->clk)) {
924 printk(KERN_ERR "failed to get lcd clock source\n"); 930 dev_err(&pdev->dev, "failed to get lcd clock source\n");
925 ret = PTR_ERR(info->clk); 931 ret = PTR_ERR(info->clk);
926 goto release_irq; 932 goto release_irq;
927 } 933 }
@@ -929,7 +935,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
929 clk_enable(info->clk); 935 clk_enable(info->clk);
930 dprintk("got and enabled clock\n"); 936 dprintk("got and enabled clock\n");
931 937
932 usleep_range(1000, 1000); 938 usleep_range(1000, 1100);
933 939
934 info->clk_rate = clk_get_rate(info->clk); 940 info->clk_rate = clk_get_rate(info->clk);
935 941
@@ -947,7 +953,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
947 /* Initialize video memory */ 953 /* Initialize video memory */
948 ret = s3c2410fb_map_video_memory(fbinfo); 954 ret = s3c2410fb_map_video_memory(fbinfo);
949 if (ret) { 955 if (ret) {
950 printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret); 956 dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret);
951 ret = -ENOMEM; 957 ret = -ENOMEM;
952 goto release_clock; 958 goto release_clock;
953 } 959 }
@@ -970,7 +976,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
970 976
971 ret = register_framebuffer(fbinfo); 977 ret = register_framebuffer(fbinfo);
972 if (ret < 0) { 978 if (ret < 0) {
973 printk(KERN_ERR "Failed to register framebuffer device: %d\n", 979 dev_err(&pdev->dev, "Failed to register framebuffer device: %d\n",
974 ret); 980 ret);
975 goto free_cpufreq; 981 goto free_cpufreq;
976 } 982 }
@@ -978,9 +984,9 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
978 /* create device files */ 984 /* create device files */
979 ret = device_create_file(&pdev->dev, &dev_attr_debug); 985 ret = device_create_file(&pdev->dev, &dev_attr_debug);
980 if (ret) 986 if (ret)
981 printk(KERN_ERR "failed to add debug attribute\n"); 987 dev_err(&pdev->dev, "failed to add debug attribute\n");
982 988
983 printk(KERN_INFO "fb%d: %s frame buffer device\n", 989 dev_info(&pdev->dev, "fb%d: %s frame buffer device\n",
984 fbinfo->node, fbinfo->fix.id); 990 fbinfo->node, fbinfo->fix.id);
985 991
986 return 0; 992 return 0;
@@ -1028,7 +1034,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
1028 s3c2410fb_cpufreq_deregister(info); 1034 s3c2410fb_cpufreq_deregister(info);
1029 1035
1030 s3c2410fb_lcd_enable(info, 0); 1036 s3c2410fb_lcd_enable(info, 0);
1031 usleep_range(1000, 1000); 1037 usleep_range(1000, 1100);
1032 1038
1033 s3c2410fb_unmap_video_memory(fbinfo); 1039 s3c2410fb_unmap_video_memory(fbinfo);
1034 1040
@@ -1065,7 +1071,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
1065 * the LCD DMA engine is not going to get back on the bus 1071 * the LCD DMA engine is not going to get back on the bus
1066 * before the clock goes off again (bjd) */ 1072 * before the clock goes off again (bjd) */
1067 1073
1068 usleep_range(1000, 1000); 1074 usleep_range(1000, 1100);
1069 clk_disable(info->clk); 1075 clk_disable(info->clk);
1070 1076
1071 return 0; 1077 return 0;
@@ -1077,7 +1083,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
1077 struct s3c2410fb_info *info = fbinfo->par; 1083 struct s3c2410fb_info *info = fbinfo->par;
1078 1084
1079 clk_enable(info->clk); 1085 clk_enable(info->clk);
1080 usleep_range(1000, 1000); 1086 usleep_range(1000, 1100);
1081 1087
1082 s3c2410fb_init_registers(fbinfo); 1088 s3c2410fb_init_registers(fbinfo);
1083 1089
@@ -1134,8 +1140,8 @@ static void __exit s3c2410fb_cleanup(void)
1134module_init(s3c2410fb_init); 1140module_init(s3c2410fb_init);
1135module_exit(s3c2410fb_cleanup); 1141module_exit(s3c2410fb_cleanup);
1136 1142
1137MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " 1143MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
1138 "Ben Dooks <ben-linux@fluff.org>"); 1144MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
1139MODULE_DESCRIPTION("Framebuffer driver for the s3c2410"); 1145MODULE_DESCRIPTION("Framebuffer driver for the s3c2410");
1140MODULE_LICENSE("GPL"); 1146MODULE_LICENSE("GPL");
1141MODULE_ALIAS("platform:s3c2410-lcd"); 1147MODULE_ALIAS("platform:s3c2410-lcd");
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 0d0f52c18fd8..f4f53b082d05 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -2266,8 +2266,10 @@ static int __devinit savagefb_probe(struct pci_dev* dev,
2266 lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3); 2266 lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
2267 info->var.yres_virtual = info->fix.smem_len/lpitch; 2267 info->var.yres_virtual = info->fix.smem_len/lpitch;
2268 2268
2269 if (info->var.yres_virtual < info->var.yres) 2269 if (info->var.yres_virtual < info->var.yres) {
2270 err = -ENOMEM;
2270 goto failed; 2271 goto failed;
2272 }
2271 2273
2272#if defined(CONFIG_FB_SAVAGE_ACCEL) 2274#if defined(CONFIG_FB_SAVAGE_ACCEL)
2273 /* 2275 /*
diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/sis/initextlfb.c
index 9dec64da4015..3ab18f5a3759 100644
--- a/drivers/video/sis/initextlfb.c
+++ b/drivers/video/sis/initextlfb.c
@@ -65,7 +65,7 @@ sisfb_mode_rate_to_dclock(struct SiS_Private *SiS_Pr, unsigned char modeno,
65 } 65 }
66#endif 66#endif
67 67
68 if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {; 68 if(!(SiS_SearchModeID(SiS_Pr, &ModeNo, &ModeIdIndex))) {
69 printk(KERN_ERR "Could not find mode %x\n", ModeNo); 69 printk(KERN_ERR "Could not find mode %x\n", ModeNo);
70 return 65000; 70 return 65000;
71 } 71 }
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index b7f27acaf817..729a50722bdf 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -141,8 +141,10 @@ static int __devinit gfb_probe(struct platform_device *op)
141 141
142 gp->fb_base = of_ioremap(&op->resource[6], 0, 142 gp->fb_base = of_ioremap(&op->resource[6], 0,
143 gp->fb_size, "gfb fb"); 143 gp->fb_size, "gfb fb");
144 if (!gp->fb_base) 144 if (!gp->fb_base) {
145 err = -ENOMEM;
145 goto err_release_fb; 146 goto err_release_fb;
147 }
146 148
147 err = gfb_set_fbinfo(gp); 149 err = gfb_set_fbinfo(gp);
148 if (err) 150 if (err)
diff --git a/drivers/video/sunxvr2500.c b/drivers/video/sunxvr2500.c
index 5848436c19da..7fbcba86d1a2 100644
--- a/drivers/video/sunxvr2500.c
+++ b/drivers/video/sunxvr2500.c
@@ -181,8 +181,10 @@ static int __devinit s3d_pci_register(struct pci_dev *pdev,
181 sp->fb_size = info->fix.line_length * sp->height; 181 sp->fb_size = info->fix.line_length * sp->height;
182 182
183 sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size); 183 sp->fb_base = ioremap(sp->fb_base_phys, sp->fb_size);
184 if (!sp->fb_base) 184 if (!sp->fb_base) {
185 err = -ENOMEM;
185 goto err_release_pci; 186 goto err_release_pci;
187 }
186 188
187 err = s3d_set_fbinfo(sp); 189 err = s3d_set_fbinfo(sp);
188 if (err) 190 if (err)
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c
index eb931b8626fa..6c71b1b44477 100644
--- a/drivers/video/sunxvr500.c
+++ b/drivers/video/sunxvr500.c
@@ -298,8 +298,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
298 goto err_release_fb; 298 goto err_release_fb;
299 } 299 }
300 ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000); 300 ep->ramdac = ioremap(ep->regs_base_phys + 0x8000, 0x1000);
301 if (!ep->ramdac) 301 if (!ep->ramdac) {
302 err = -ENOMEM;
302 goto err_release_pci1; 303 goto err_release_pci1;
304 }
303 305
304 ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0); 306 ep->fb8_0_off = readl(ep->ramdac + RAMDAC_VID_8FB_0);
305 ep->fb8_0_off -= ep->fb_base_reg; 307 ep->fb8_0_off -= ep->fb_base_reg;
@@ -343,8 +345,10 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev,
343 ep->fb_size = info->fix.line_length * ep->height; 345 ep->fb_size = info->fix.line_length * ep->height;
344 346
345 ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size); 347 ep->fb_base = ioremap(ep->fb_base_phys, ep->fb_size);
346 if (!ep->fb_base) 348 if (!ep->fb_base) {
349 err = -ENOMEM;
347 goto err_release_pci0; 350 goto err_release_pci0;
351 }
348 352
349 err = e3d_set_fbinfo(ep); 353 err = e3d_set_fbinfo(ep);
350 if (err) 354 if (err)
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index f45eba3d6150..86d449ea3169 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -646,7 +646,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
646 result = fb_sys_write(info, buf, count, ppos); 646 result = fb_sys_write(info, buf, count, ppos);
647 647
648 if (result > 0) { 648 if (result > 0) {
649 int start = max((int)(offset / info->fix.line_length) - 1, 0); 649 int start = max((int)(offset / info->fix.line_length), 0);
650 int lines = min((u32)((result / info->fix.line_length) + 1), 650 int lines = min((u32)((result / info->fix.line_length) + 1),
651 (u32)info->var.yres); 651 (u32)info->var.yres);
652 652
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index b0e2a4261afe..2f8f82d874a1 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -659,6 +659,8 @@ static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
659 task->t.flags = TF_BUF_RET | TF_BUF_ESDI; 659 task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
660 task->t.buf_len = EDID_LENGTH; 660 task->t.buf_len = EDID_LENGTH;
661 task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL); 661 task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
662 if (!task->buf)
663 return -ENOMEM;
662 664
663 err = uvesafb_exec(task); 665 err = uvesafb_exec(task);
664 666
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index 89aef343e295..4709edc3cb7f 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -1167,8 +1167,7 @@ void vmlfb_unregister_subsys(struct vml_sys *sys)
1167 list_for_each_entry_safe(entry, next, &global_has_mode, head) { 1167 list_for_each_entry_safe(entry, next, &global_has_mode, head) {
1168 printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n"); 1168 printk(KERN_DEBUG MODULE_NAME ": subsys disable pipe\n");
1169 vmlfb_disable_pipe(entry); 1169 vmlfb_disable_pipe(entry);
1170 list_del(&entry->head); 1170 list_move_tail(&entry->head, &global_no_mode);
1171 list_add_tail(&entry->head, &global_no_mode);
1172 } 1171 }
1173 mutex_unlock(&vml_mutex); 1172 mutex_unlock(&vml_mutex);
1174} 1173}
diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c
index af8f26b643c1..db1e39277e32 100644
--- a/drivers/video/via/via_clock.c
+++ b/drivers/video/via/via_clock.c
@@ -25,6 +25,7 @@
25 25
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/via-core.h> 27#include <linux/via-core.h>
28#include <asm/olpc.h>
28#include "via_clock.h" 29#include "via_clock.h"
29#include "global.h" 30#include "global.h"
30#include "debug.h" 31#include "debug.h"
@@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config)
289 printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap); 290 printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap);
290} 291}
291 292
293static void noop_set_clock_state(u8 state)
294{
295}
296
292void via_clock_init(struct via_clock *clock, int gfx_chip) 297void via_clock_init(struct via_clock *clock, int gfx_chip)
293{ 298{
294 switch (gfx_chip) { 299 switch (gfx_chip) {
@@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip)
346 break; 351 break;
347 352
348 } 353 }
354
355 if (machine_is_olpc()) {
356 /* The OLPC XO-1.5 cannot suspend/resume reliably if the
357 * IGA1/IGA2 clocks are set as on or off (memory rot
358 * occasionally happens during suspend under such
359 * configurations).
360 *
361 * The only known stable scenario is to leave this bits as-is,
362 * which in their default states are documented to enable the
363 * clock only when it is needed.
364 */
365 clock->set_primary_clock_state = noop_set_clock_state;
366 clock->set_secondary_clock_state = noop_set_clock_state;
367 }
349} 368}