diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-11 21:21:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-11 21:21:02 -0400 |
commit | 5f76945a9c978b8b8bf8eb7fe3b17b9981240a97 (patch) | |
tree | df61aca168df657bc71ce8b578bcb0c81b0622ee /drivers/video | |
parent | 940e3a8dd6683a3787faf769b3df7a06f1c2fa31 (diff) | |
parent | cd9d6f10d07f26dd8a70e519c22b6b4f8a9e3e7a (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')
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 | ||
2142 | config 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 | |||
2148 | config 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 | |||
2157 | config FB_IBM_GXT4500 | 2142 | config 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 | |||
127 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o | 127 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o |
128 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o | 128 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o |
129 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o | 129 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o |
130 | obj-$(CONFIG_FB_PNX4008_DUM) += pnx4008/ | ||
131 | obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnx4008/ | ||
132 | obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | 130 | obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o |
133 | obj-$(CONFIG_FB_PS3) += ps3fb.o | 131 | obj-$(CONFIG_FB_PS3) += ps3fb.o |
134 | obj-$(CONFIG_FB_SM501) += sm501fb.o | 132 | obj-$(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 | ||
951 | static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ | 951 | static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ |
952 | static int amifb_inverse = 0; | ||
953 | 952 | ||
954 | static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */ | 953 | static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */ |
955 | static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */ | 954 | static 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); |
805 | out_reg: | 807 | out_reg: |
806 | fb_dealloc_cmap(&bfin_lq035_fb.cmap); | 808 | fb_dealloc_cmap(&bfin_lq035_fb.cmap); |
807 | out_cmap: | ||
808 | kfree(bfin_lq035_fb.pseudo_palette); | ||
809 | out_palette: | ||
810 | out_table: | 809 | out_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); |
672 | out6: | 674 | out6: |
673 | fb_dealloc_cmap(&fbinfo->cmap); | 675 | fb_dealloc_cmap(&fbinfo->cmap); |
674 | out5: | ||
675 | kfree(fbinfo->pseudo_palette); | ||
676 | out4: | 676 | out4: |
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 | ||
856 | static int __init bfin_lq035q1_driver_init(void) | 857 | module_platform_driver(bfin_lq035q1_driver); |
857 | { | ||
858 | return platform_driver_register(&bfin_lq035q1_driver); | ||
859 | } | ||
860 | module_init(bfin_lq035q1_driver_init); | ||
861 | |||
862 | static void __exit bfin_lq035q1_driver_cleanup(void) | ||
863 | { | ||
864 | platform_driver_unregister(&bfin_lq035q1_driver); | ||
865 | } | ||
866 | module_exit(bfin_lq035q1_driver_cleanup); | ||
867 | 858 | ||
868 | MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); | 859 | MODULE_DESCRIPTION("Blackfin TFT LCD Driver"); |
869 | MODULE_LICENSE("GPL"); | 860 | MODULE_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; | |||
135 | static struct resource *lcdc_regs; | 140 | static struct resource *lcdc_regs; |
136 | static unsigned int lcd_revision; | 141 | static unsigned int lcd_revision; |
137 | static irq_handler_t lcdc_irq_handler; | 142 | static irq_handler_t lcdc_irq_handler; |
143 | static wait_queue_head_t frame_done_wq; | ||
144 | static int frame_done_flag; | ||
138 | 145 | ||
139 | static inline unsigned int lcdc_read(unsigned int addr) | 146 | static 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 */ |
291 | static inline void lcd_disable_raster(void) | 298 | static 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 | ||
300 | static void lcd_blit(int load_mode, struct da8xx_fb_par *par) | 320 | static 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) | ||
566 | static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, | 598 | static 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 | ||
638 | static void lcd_reset(struct da8xx_fb_par *par) | 696 | static 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: | |||
1385 | err_release_fb: | 1477 | err_release_fb: |
1386 | framebuffer_release(da8xx_fb_info); | 1478 | framebuffer_release(da8xx_fb_info); |
1387 | 1479 | ||
1388 | err_clk_disable: | 1480 | err_pm_runtime_disable: |
1389 | clk_disable(fb_clk); | 1481 | pm_runtime_put_sync(&device->dev); |
1390 | 1482 | pm_runtime_disable(&device->dev); | |
1391 | err_clk_put: | ||
1392 | clk_put(fb_clk); | ||
1393 | 1483 | ||
1394 | err_ioremap: | 1484 | err_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 |
1494 | struct 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 | |||
1509 | static 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 | |||
1533 | static 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 | |||
1404 | static int fb_suspend(struct platform_device *dev, pm_message_t state) | 1557 | static 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 | ||
587 | failed: | ||
588 | clk_put(fbi->clk); | ||
589 | failed_check: | 588 | failed_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); |
592 | failed_mode: | ||
593 | iounmap(fbi->mmio_base); | ||
594 | failed_resource: | 591 | failed_resource: |
595 | ep93xxfb_dealloc_videomem(info); | 592 | ep93xxfb_dealloc_videomem(info); |
596 | failed_videomem: | 593 | failed_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 | ||
261 | static void exynos_dp_link_start(struct exynos_dp_device *dp) | 264 | static 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 | ||
311 | static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane) | 314 | static 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 | ||
319 | static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count) | 322 | static 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 | ||
332 | static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count) | 335 | static 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 | ||
418 | static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) | 422 | static 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 | ||
434 | static 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 | |||
461 | static 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 | ||
476 | static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | 430 | static 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 | |||
538 | reduce_link_rate: | ||
539 | exynos_dp_reduce_link_rate(dp); | ||
540 | return -EIO; | ||
562 | } | 541 | } |
563 | 542 | ||
564 | static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | 543 | static 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 | |||
634 | reduce_link_rate: | ||
635 | exynos_dp_reduce_link_rate(dp); | ||
636 | return -EIO; | ||
628 | } | 637 | } |
629 | 638 | ||
630 | static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, | 639 | static 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 | ||
643 | static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, | 652 | static 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, | |||
693 | static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) | 702 | static 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 | |||
950 | err_clock: | ||
951 | clk_put(dp->clock); | ||
952 | |||
953 | return ret; | ||
954 | } | 949 | } |
955 | 950 | ||
956 | static int __devexit exynos_dp_remove(struct platform_device *pdev) | 951 | static 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); | |||
43 | void exynos_dp_reset(struct exynos_dp_device *dp); | 43 | void exynos_dp_reset(struct exynos_dp_device *dp); |
44 | void exynos_dp_swreset(struct exynos_dp_device *dp); | 44 | void exynos_dp_swreset(struct exynos_dp_device *dp); |
45 | void exynos_dp_config_interrupt(struct exynos_dp_device *dp); | 45 | void exynos_dp_config_interrupt(struct exynos_dp_device *dp); |
46 | u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); | 46 | enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); |
47 | void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); | 47 | void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); |
48 | void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, | 48 | void 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); | |||
105 | u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); | 105 | u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); |
106 | u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); | 106 | u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); |
107 | void exynos_dp_reset_macro(struct exynos_dp_device *dp); | 107 | void exynos_dp_reset_macro(struct exynos_dp_device *dp); |
108 | int exynos_dp_init_video(struct exynos_dp_device *dp); | 108 | void exynos_dp_init_video(struct exynos_dp_device *dp); |
109 | 109 | ||
110 | void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, | 110 | void 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 | ||
156 | void exynos_dp_swreset(struct exynos_dp_device *dp) | 153 | void 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 | ||
182 | u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp) | 179 | enum 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 | ||
997 | int exynos_dp_init_video(struct exynos_dp_device *dp) | 1017 | void 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 | ||
1019 | void exynos_dp_set_video_color_format(struct exynos_dp_device *dp, | 1037 | void 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 | ||
208 | struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv) | 208 | static 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 | ||
268 | struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim, | 269 | static 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 | ||
296 | static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim, | 288 | static 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) | |||
1241 | out_gbe_unmap: | 1243 | out_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); | ||
1246 | out_tiles_free: | 1246 | out_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); |
1249 | out_unmap: | ||
1250 | iounmap(gbe); | ||
1251 | out_release_mem_region: | 1249 | out_release_mem_region: |
1252 | release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); | 1250 | release_mem_region(GBE_BASE, sizeof(struct sgi_gbe)); |
1253 | out_release_framebuffer: | 1251 | out_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 | |||
307 | dealloc_cmap: | ||
308 | fb_dealloc_cmap(&fb_info.cmap); | ||
309 | |||
310 | unmap_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 | ||
350 | static struct dio_device_id hpfb_dio_tbl[] = { | 364 | static 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); |
737 | err_iounmap: | ||
738 | iounmap(jzfb->base); | ||
739 | err_put_lpclk: | ||
740 | clk_put(jzfb->lpclk); | ||
741 | err_put_ldclk: | ||
742 | clk_put(jzfb->ldclk); | ||
743 | err_framebuffer_release: | 723 | err_framebuffer_release: |
744 | framebuffer_release(fb); | 724 | framebuffer_release(fb); |
745 | err_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 | ||
997 | err6: | 997 | err6: |
998 | fb_dealloc_cmap(&fbi->cmap); | 998 | fb_dealloc_cmap(&fbi->cmap); |
999 | err5: | ||
1000 | iounmap(mfbi->fb_virt_addr); | ||
1001 | err4: | ||
1002 | iounmap(mfbi->reg_virt_addr); | ||
1003 | err3: | 999 | err3: |
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)); |
1005 | err2: | 1001 | err2: |
@@ -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 | ||
21 | struct mdp_info { | 20 | struct 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 | ||
1569 | static struct platform_driver mx3fb_driver = { | 1569 | static 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 | */ |
390 | static int __init nuc900fb_map_video_memory(struct fb_info *info) | 390 | static 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 | ||
29 | static int palmte_panel_init(struct lcd_panel *panel, | 28 | static 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. */ | ||
135 | static 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) | |||
731 | static void acx_panel_set_timings(struct omap_dss_device *dssdev, | 734 | static 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 | ||
748 | static int acx_panel_check_timings(struct omap_dss_device *dssdev, | 742 | static 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 | ||
550 | static inline struct panel_generic_dpi_data | 552 | static 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 | ||
653 | static int generic_dpi_panel_enable(struct omap_dss_device *dssdev) | 660 | static 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; |
672 | err: | ||
673 | mutex_unlock(&drv_data->lock); | ||
662 | 674 | ||
663 | return 0; | 675 | return r; |
664 | } | 676 | } |
665 | 677 | ||
666 | static void generic_dpi_panel_disable(struct omap_dss_device *dssdev) | 678 | static 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 | ||
673 | static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev) | 691 | static 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 | ||
682 | static int generic_dpi_panel_resume(struct omap_dss_device *dssdev) | 706 | static 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; | 719 | err: |
720 | mutex_unlock(&drv_data->lock); | ||
721 | |||
722 | return r; | ||
693 | } | 723 | } |
694 | 724 | ||
695 | static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, | 725 | static 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 | |||
739 | static 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 | ||
701 | static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, | 751 | static 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 | ||
707 | static struct omap_dss_driver dpi_driver = { | 766 | static 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 | ||
160 | static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf, | 166 | static 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 | ||
152 | static 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 | |||
158 | static void taal_esd_work(struct work_struct *work); | 162 | static void taal_esd_work(struct work_struct *work); |
159 | static void taal_ulps_work(struct work_struct *work); | 163 | static 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) | |||
371 | static int taal_enter_ulps(struct omap_dss_device *dssdev) | 375 | static 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: | |||
405 | static int taal_exit_ulps(struct omap_dss_device *dssdev) | 409 | static 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 | } |
444 | err1: | 449 | err1: |
@@ -835,94 +840,135 @@ static struct attribute_group taal_attr_group = { | |||
835 | static void taal_hw_reset(struct omap_dss_device *dssdev) | 840 | static 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 | ||
861 | static 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 | |||
857 | static int taal_probe(struct omap_dss_device *dssdev) | 879 | static 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) | |||
991 | err_vc_id: | 1012 | err_vc_id: |
992 | omap_dsi_release_vc(dssdev, td->channel); | 1013 | omap_dsi_release_vc(dssdev, td->channel); |
993 | err_req_vc: | 1014 | err_req_vc: |
994 | if (panel_data->use_ext_te) | ||
995 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); | ||
996 | err_irq: | ||
997 | if (panel_data->use_ext_te) | ||
998 | gpio_free(panel_data->ext_te_gpio); | ||
999 | err_gpio: | ||
1000 | if (bldev != NULL) | 1015 | if (bldev != NULL) |
1001 | backlight_device_unregister(bldev); | 1016 | backlight_device_unregister(bldev); |
1002 | err_bl: | 1017 | err_bl: |
1003 | if (gpio_is_valid(panel_data->reset_gpio)) | ||
1004 | gpio_free(panel_data->reset_gpio); | ||
1005 | err_rst_gpio: | ||
1006 | destroy_workqueue(td->workqueue); | 1018 | destroy_workqueue(td->workqueue); |
1007 | err_wq: | ||
1008 | kfree(td); | ||
1009 | err: | ||
1010 | return r; | 1019 | return r; |
1011 | } | 1020 | } |
1012 | 1021 | ||
1013 | static void __exit taal_remove(struct omap_dss_device *dssdev) | 1022 | static 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 | ||
1050 | static int taal_power_on(struct omap_dss_device *dssdev) | 1047 | static 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) | |||
1419 | static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | 1425 | static 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) | |||
1487 | static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | 1492 | static 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; |
145 | err_i2c: | ||
146 | if (gpio_is_valid(ddata->pd_gpio)) | ||
147 | gpio_free(ddata->pd_gpio); | ||
148 | return r; | ||
149 | } | 147 | } |
150 | 148 | ||
151 | static void __exit tfp410_remove(struct omap_dss_device *dssdev) | 149 | static 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) | |||
480 | static void tpo_td043_set_timings(struct omap_dss_device *dssdev, | 483 | static 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 | ||
486 | static int tpo_td043_check_timings(struct omap_dss_device *dssdev, | 491 | static 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 | ||
85 | config OMAP2_DSS_DSI | 85 | config 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 @@ | |||
1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o | 1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o |
2 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ | 2 | omapdss-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 |
4 | omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o | 4 | omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o |
5 | omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o | 5 | omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o |
6 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o | 6 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o |
7 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | 7 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o |
8 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 8 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
9 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | 9 | omapdss-$(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) | |||
424 | int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | 421 | int 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 | ||
680 | static 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 | |||
707 | static void dss_write_regs(void) | 691 | static 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 | ||
987 | static void dss_apply_fifo_merge(bool use_fifo_merge) | 967 | static 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 | |||
996 | static 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 | ||
1011 | static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr, | 982 | static 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 | |||
1026 | static 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 | ||
1038 | static int get_num_used_managers(void) | 996 | static 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 | |||
1061 | static 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 | |||
1090 | static 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 | ||
1113 | int dss_mgr_enable(struct omap_overlay_manager *mgr) | 1008 | int 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(); | ||
1202 | out: | 1075 | out: |
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 | ||
1240 | int dss_mgr_set_device(struct omap_overlay_manager *mgr, | 1113 | int 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 | ||
1272 | int dss_mgr_unset_device(struct omap_overlay_manager *mgr) | 1145 | int 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; |
1175 | err1: | ||
1176 | spin_unlock_irqrestore(&data_lock, flags); | ||
1299 | err: | 1177 | err: |
1300 | mutex_unlock(&apply_lock); | 1178 | mutex_unlock(&apply_lock); |
1179 | |||
1301 | return r; | 1180 | return r; |
1302 | } | 1181 | } |
1303 | 1182 | ||
1304 | static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr, | 1183 | static 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 | ||
1313 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | 1192 | void 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); | ||
1207 | out: | ||
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 | ||
1334 | static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr, | 1211 | static 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 | |||
1368 | out: | 1235 | out: |
1369 | mutex_unlock(&apply_lock); | 1236 | spin_unlock_irqrestore(&data_lock, flags); |
1370 | } | 1237 | } |
1371 | 1238 | ||
1372 | int dss_ovl_set_info(struct omap_overlay *ovl, | 1239 | int 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; | |||
57 | module_param_named(debug, dss_debug, bool, 0644); | 58 | module_param_named(debug, dss_debug, bool, 0644); |
58 | #endif | 59 | #endif |
59 | 60 | ||
61 | const char *dss_get_default_display_name(void) | ||
62 | { | ||
63 | return core.default_display_name; | ||
64 | } | ||
65 | |||
60 | /* REGULATORS */ | 66 | /* REGULATORS */ |
61 | 67 | ||
62 | struct regulator *dss_get_vdds_dsi(void) | 68 | struct 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) | |||
416 | EXPORT_SYMBOL(omap_dss_unregister_driver); | 419 | EXPORT_SYMBOL(omap_dss_unregister_driver); |
417 | 420 | ||
418 | /* DEVICE */ | 421 | /* DEVICE */ |
419 | static 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 | ||
448 | static void omap_dss_dev_release(struct device *dev) | 423 | static 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 | ||
453 | int omap_dss_register_device(struct omap_dss_device *dssdev, | 429 | static int disp_num_counter; |
454 | struct device *parent, int disp_num) | 430 | |
431 | struct 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 | |||
449 | int dss_add_device(struct omap_dss_device *dssdev) | ||
450 | { | ||
451 | return device_add(&dssdev->dev); | ||
452 | } | ||
453 | |||
454 | void dss_put_device(struct omap_dss_device *dssdev) | ||
455 | { | ||
456 | put_device(&dssdev->dev); | ||
464 | } | 457 | } |
465 | 458 | ||
466 | void omap_dss_unregister_device(struct omap_dss_device *dssdev) | 459 | void 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) | |||
471 | static int dss_unregister_dss_dev(struct device *dev, void *data) | 464 | static 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 | ||
478 | void omap_dss_unregister_child_devices(struct device *parent) | 471 | void 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 | ||
476 | void 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 */ |
484 | static int __init omap_dss_bus_register(void) | 487 | static 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 | ||
84 | struct 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 | |||
85 | static struct { | 108 | static 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 | ||
241 | struct color_conv_coef { | ||
242 | int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; | ||
243 | int full_range; | ||
244 | }; | ||
245 | |||
214 | static void _omap_dispc_set_irqs(void); | 246 | static void _omap_dispc_set_irqs(void); |
247 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); | ||
248 | static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); | ||
215 | 249 | ||
216 | static inline void dispc_write_reg(const u16 idx, u32 val) | 250 | static 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 | ||
546 | u32 dispc_wb_get_framedone_irq(void) | ||
547 | { | ||
548 | return DISPC_IRQ_FRAMEDONEWB; | ||
549 | } | ||
550 | |||
512 | bool dispc_mgr_go_busy(enum omap_channel channel) | 551 | bool 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 | ||
578 | bool dispc_wb_go_busy(void) | ||
579 | { | ||
580 | return REG_GET(DISPC_CONTROL2, 6, 6) == 1; | ||
581 | } | ||
582 | |||
583 | void 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 | |||
539 | static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) | 602 | static 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 | ||
621 | static 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 | ||
685 | static 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 | ||
701 | static 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 | ||
657 | static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) | 720 | static 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 | ||
677 | static void dispc_ovl_set_pos(enum omap_plane plane, int x, int y) | 740 | static 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 | ||
684 | static void dispc_ovl_set_pic_size(enum omap_plane plane, int width, int height) | 753 | static 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 | ||
694 | static void dispc_ovl_set_vid_size(enum omap_plane plane, int width, int height) | 764 | static 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 | ||
705 | static void dispc_ovl_set_zorder(enum omap_plane plane, u8 zorder) | 779 | static 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 | ||
726 | static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, bool enable) | 799 | static 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 | ||
736 | static void dispc_ovl_setup_global_alpha(enum omap_plane plane, u8 global_alpha) | 808 | static 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 | ||
1022 | void 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 | |||
950 | static void dispc_ovl_set_burst_size(enum omap_plane plane, | 1029 | static 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 | ||
1030 | static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable) | 1109 | static 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 | ||
1048 | static void dispc_read_plane_fifo_sizes(void) | 1131 | static 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 | ||
1066 | static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) | 1178 | static 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 | ||
1071 | void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) | 1191 | void 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 | */ |
1851 | static int check_horiz_timing_omap3(enum omap_channel channel, | 1994 | static 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 | ||
1903 | static unsigned long calc_core_clk_five_taps(enum omap_channel channel, | 2043 | static 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 | ||
1943 | static unsigned long calc_core_clk(enum omap_channel channel, u16 width, | 2084 | static 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 | |||
2095 | static 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 | 2122 | static 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 | |||
2144 | static 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 | ||
1983 | static int dispc_ovl_calc_scaling(enum omap_plane plane, | 2185 | static 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 | |||
2251 | static 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 | |||
2293 | static 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 | ||
2150 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | 2358 | static 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 | ||
2503 | int 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 | |||
2528 | int 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 | |||
2302 | int dispc_ovl_enable(enum omap_plane plane, bool enable) | 2579 | int 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 | ||
2731 | void 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 | |||
2765 | bool 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 | |||
2454 | void dispc_lcd_enable_signal_polarity(bool act_high) | 2772 | void 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) | |||
2605 | static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | 2923 | static 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 | ||
3175 | static 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 | |||
3182 | static 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 | } | ||
2875 | static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel) | 3192 | static 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 | ||
3996 | static 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 | |||
4008 | static 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 | |||
4020 | static 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 | |||
4032 | static 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 | |||
4045 | static 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 */ |
3676 | static int __init omap_dispchw_probe(struct platform_device *pdev) | 4078 | static 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 | } |
317 | EXPORT_SYMBOL(omapdss_default_get_timings); | 321 | EXPORT_SYMBOL(omapdss_default_get_timings); |
318 | 322 | ||
319 | void 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 | */ | ||
328 | static 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 | |||
380 | static 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 | |||
392 | int 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 | ||
341 | void dss_uninit_device(struct platform_device *pdev, | 436 | void 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 | ||
356 | static int dss_suspend_device(struct device *dev, void *data) | 450 | static 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 | ||
38 | static struct { | 39 | static 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 | ||
45 | static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) | 52 | static 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 | ||
122 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 129 | static 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 | ||
154 | static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) | 162 | static 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 | ||
168 | int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | 178 | int 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 | ||
222 | err_mgr_enable: | 243 | err_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); |
229 | err_get_dsi: | 250 | err_get_dsi: |
251 | err_src_sel: | ||
230 | dispc_runtime_put(); | 252 | dispc_runtime_put(); |
231 | err_get_dispc: | 253 | err_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); |
234 | err_reg_enable: | 256 | err_reg_enable: |
235 | omap_dss_stop_device(dssdev); | 257 | omap_dss_stop_device(dssdev); |
236 | err_start_dev: | 258 | err_start_dev: |
259 | err_no_out_mgr: | ||
260 | err_no_reg: | ||
261 | mutex_unlock(&dpi.lock); | ||
237 | return r; | 262 | return r; |
238 | } | 263 | } |
239 | EXPORT_SYMBOL(omapdss_dpi_display_enable); | 264 | EXPORT_SYMBOL(omapdss_dpi_display_enable); |
240 | 265 | ||
241 | void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | 266 | void 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 | } |
258 | EXPORT_SYMBOL(omapdss_dpi_display_disable); | 289 | EXPORT_SYMBOL(omapdss_dpi_display_disable); |
259 | 290 | ||
260 | void dpi_set_timings(struct omap_dss_device *dssdev, | 291 | void 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 | } |
279 | EXPORT_SYMBOL(dpi_set_timings); | 302 | EXPORT_SYMBOL(omapdss_dpi_set_timings); |
280 | 303 | ||
281 | int dpi_check_timings(struct omap_dss_device *dssdev, | 304 | int 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 | } |
326 | EXPORT_SYMBOL(dpi_check_timings); | 350 | EXPORT_SYMBOL(dpi_check_timings); |
327 | 351 | ||
352 | void 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 | } | ||
360 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); | ||
361 | |||
328 | static int __init dpi_init_display(struct omap_dss_device *dssdev) | 362 | static 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 | ||
354 | static void __init dpi_probe_pdata(struct platform_device *pdev) | 389 | static 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); | 417 | static 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 | ||
449 | static 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 | |||
460 | static 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 | |||
378 | static int __init omap_dpi_probe(struct platform_device *pdev) | 467 | static 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 | ||
385 | static int __exit omap_dpi_remove(struct platform_device *pdev) | 478 | static 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 | ||
338 | struct dsi_packet_sent_handler_data { | 343 | struct 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 | ||
343 | static struct platform_device *dsi_pdev_map[MAX_NUM_DSI]; | ||
344 | |||
345 | #ifdef DEBUG | 348 | #ifdef DEBUG |
346 | static bool dsi_perf; | 349 | static bool dsi_perf; |
347 | module_param(dsi_perf, bool, 0644); | 350 | module_param(dsi_perf, bool, 0644); |
@@ -354,12 +357,19 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside | |||
354 | 357 | ||
355 | static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) | 358 | static 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 | ||
360 | struct platform_device *dsi_get_dsidev_from_id(int module) | 363 | struct 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 | ||
365 | static inline void dsi_write_reg(struct platform_device *dsidev, | 375 | static inline void dsi_write_reg(struct platform_device *dsidev, |
@@ -1450,6 +1460,148 @@ found: | |||
1450 | return 0; | 1460 | return 0; |
1451 | } | 1461 | } |
1452 | 1462 | ||
1463 | static 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 | } | ||
1503 | found: | ||
1504 | if (cinfo) | ||
1505 | *cinfo = best; | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1509 | |||
1510 | static 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 | |||
1521 | static 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 | |||
1545 | retry: | ||
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 | } | ||
1596 | found: | ||
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 | |||
1453 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 1605 | int 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 | ||
2013 | static int dsi_set_lane_config(struct omap_dss_device *dssdev) | 2173 | static 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 */ |
2150 | static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, | 2316 | static 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 | ||
2200 | static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) | 2365 | static 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 */ |
2250 | static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) | 2414 | static 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 | ||
2265 | static int dsi_cio_init(struct omap_dss_device *dssdev) | 2428 | static 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); |
2382 | err_scp_clk_dom: | 2544 | err_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 | ||
2388 | static void dsi_cio_uninit(struct omap_dss_device *dssdev) | 2550 | static 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 | ||
2401 | static void dsi_config_tx_fifo(struct platform_device *dsidev, | 2562 | static 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 | } |
2707 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); | 2869 | EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); |
@@ -2987,10 +3149,9 @@ int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) | |||
2987 | } | 3149 | } |
2988 | EXPORT_SYMBOL(dsi_vc_send_null); | 3150 | EXPORT_SYMBOL(dsi_vc_send_null); |
2989 | 3151 | ||
2990 | static int dsi_vc_write_nosync_common(struct omap_dss_device *dssdev, | 3152 | static 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, | |||
3021 | int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel, | 3182 | int 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 | } |
3027 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); | 3190 | EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); |
@@ -3029,7 +3192,9 @@ EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); | |||
3029 | int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, | 3192 | int 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 | } |
3035 | EXPORT_SYMBOL(dsi_vc_generic_write_nosync); | 3200 | EXPORT_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 | } |
3119 | EXPORT_SYMBOL(dsi_vc_generic_write_2); | 3284 | EXPORT_SYMBOL(dsi_vc_generic_write_2); |
3120 | 3285 | ||
3121 | static int dsi_vc_dcs_send_read_request(struct omap_dss_device *dssdev, | 3286 | static 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 | ||
3142 | static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev, | 3306 | static 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 | ||
3607 | static void dsi_config_vp_num_line_buffers(struct omap_dss_device *dssdev) | 3770 | static 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 | ||
3633 | static void dsi_config_vp_sync_events(struct omap_dss_device *dssdev) | 3796 | static 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 | ||
3651 | static void dsi_config_blanking_modes(struct omap_dss_device *dssdev) | 3814 | static 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) | |||
3852 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 4015 | static 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 | ||
3922 | static void dsi_proto_timings(struct omap_dss_device *dssdev) | 4086 | static 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 | } |
4101 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); | 4264 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); |
4102 | 4265 | ||
4103 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | 4266 | int 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; | ||
4326 | err: | ||
4327 | mutex_unlock(&dsi->lock); | ||
4328 | return r; | ||
4329 | } | ||
4330 | EXPORT_SYMBOL(omapdss_dsi_set_clocks); | ||
4331 | |||
4332 | int 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); | |||
4159 | void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) | 4390 | void 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 | } |
4176 | EXPORT_SYMBOL(dsi_disable_video_output); | 4409 | EXPORT_SYMBOL(dsi_disable_video_output); |
4177 | 4410 | ||
4178 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, | 4411 | static 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 | ||
4298 | static void dsi_framedone_irq_callback(void *data, u32 mask) | 4535 | static 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; |
4431 | err1: | 4660 | err1: |
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); |
4435 | err: | 4664 | err: |
4436 | return r; | 4665 | return r; |
4437 | } | 4666 | } |
4438 | 4667 | ||
4439 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4668 | static 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; |
4522 | err3: | 4756 | err3: |
4523 | dsi_cio_uninit(dssdev); | 4757 | dsi_cio_uninit(dsidev); |
4524 | err2: | 4758 | err2: |
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 | ||
4529 | err1: | 4763 | err1: |
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 | } |
4654 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4890 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
4655 | 4891 | ||
4656 | static int __init dsi_init_display(struct omap_dss_device *dssdev) | 4892 | void 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 | } |
4904 | EXPORT_SYMBOL(omapdss_dsi_set_timings); | ||
4905 | |||
4906 | void 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 | } | ||
4918 | EXPORT_SYMBOL(omapdss_dsi_set_size); | ||
4919 | |||
4920 | void 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 | } | ||
4932 | EXPORT_SYMBOL(omapdss_dsi_set_pixel_format); | ||
4933 | |||
4934 | void 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 | } | ||
4946 | EXPORT_SYMBOL(omapdss_dsi_set_operation_mode); | ||
4947 | |||
4948 | void 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 | } | ||
4960 | EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); | ||
4961 | |||
4962 | static 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 | ||
4809 | static void __init dsi_probe_pdata(struct platform_device *dsidev) | 5111 | static 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); | 5143 | static 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 | ||
5175 | static 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 | |||
5189 | static 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 */ |
4838 | static int __init omap_dsihw_probe(struct platform_device *dsidev) | 5198 | static 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 { | |||
65 | static int dss_runtime_get(void); | 65 | static int dss_runtime_get(void); |
66 | static void dss_runtime_put(void); | 66 | static void dss_runtime_put(void); |
67 | 67 | ||
68 | struct 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 | |||
68 | static struct { | 75 | static 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 | ||
88 | static const char * const dss_generic_clk_source_names[] = { | 97 | static 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 | ||
147 | void dss_sdi_init(u8 datapairs) | 156 | void 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 | |||
240 | void dss_dump_clocks(struct seq_file *s) | 248 | void 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 */ | ||
435 | int 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 | |||
459 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 434 | int 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 | ||
481 | int 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 | |||
501 | unsigned long dss_get_dpll4_rate(void) | 456 | unsigned 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 | ||
651 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) | 599 | void 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 | ||
656 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) | 613 | enum 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 | ||
627 | static 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 | |||
635 | static 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 | |||
655 | static 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 | |||
681 | int dss_dpi_select_source(enum omap_channel channel) | ||
682 | { | ||
683 | return dss.feat->dpi_select_source(channel); | ||
684 | } | ||
685 | |||
667 | static int dss_get_clocks(void) | 686 | static 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 | ||
760 | static 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 | |||
767 | static 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 | |||
774 | static 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 | |||
781 | static 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 | |||
788 | static 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 | |||
795 | static 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 */ |
753 | static int __init omap_dsshw_probe(struct platform_device *pdev) | 826 | static 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 | ||
116 | enum 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 | |||
116 | struct dss_clock_info { | 127 | struct 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; | |||
175 | struct platform_device; | 186 | struct platform_device; |
176 | 187 | ||
177 | /* core */ | 188 | /* core */ |
189 | const char *dss_get_default_display_name(void); | ||
178 | struct bus_type *dss_get_bus(void); | 190 | struct bus_type *dss_get_bus(void); |
179 | struct regulator *dss_get_vdds_dsi(void); | 191 | struct regulator *dss_get_vdds_dsi(void); |
180 | struct regulator *dss_get_vdds_sdi(void); | 192 | struct regulator *dss_get_vdds_sdi(void); |
@@ -184,10 +196,13 @@ void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask); | |||
184 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput); | 196 | int dss_set_min_bus_tput(struct device *dev, unsigned long tput); |
185 | int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); | 197 | int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)); |
186 | 198 | ||
187 | int omap_dss_register_device(struct omap_dss_device *dssdev, | 199 | struct omap_dss_device *dss_alloc_and_init_device(struct device *parent); |
188 | struct device *parent, int disp_num); | 200 | int dss_add_device(struct omap_dss_device *dssdev); |
189 | void omap_dss_unregister_device(struct omap_dss_device *dssdev); | 201 | void dss_unregister_device(struct omap_dss_device *dssdev); |
190 | void omap_dss_unregister_child_devices(struct device *parent); | 202 | void dss_unregister_child_devices(struct device *parent); |
203 | void dss_put_device(struct omap_dss_device *dssdev); | ||
204 | void dss_copy_device_pdata(struct omap_dss_device *dst, | ||
205 | const struct omap_dss_device *src); | ||
191 | 206 | ||
192 | /* apply */ | 207 | /* apply */ |
193 | void dss_apply_init(void); | 208 | void dss_apply_init(void); |
@@ -205,8 +220,11 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr, | |||
205 | int dss_mgr_set_device(struct omap_overlay_manager *mgr, | 220 | int dss_mgr_set_device(struct omap_overlay_manager *mgr, |
206 | struct omap_dss_device *dssdev); | 221 | struct omap_dss_device *dssdev); |
207 | int dss_mgr_unset_device(struct omap_overlay_manager *mgr); | 222 | int dss_mgr_unset_device(struct omap_overlay_manager *mgr); |
223 | int dss_mgr_set_output(struct omap_overlay_manager *mgr, | ||
224 | struct omap_dss_output *output); | ||
225 | int dss_mgr_unset_output(struct omap_overlay_manager *mgr); | ||
208 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, | 226 | void dss_mgr_set_timings(struct omap_overlay_manager *mgr, |
209 | struct omap_video_timings *timings); | 227 | const struct omap_video_timings *timings); |
210 | void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr, | 228 | void 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); |
212 | const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr); | 230 | const 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); |
223 | int dss_ovl_unset_manager(struct omap_overlay *ovl); | 241 | int dss_ovl_unset_manager(struct omap_overlay *ovl); |
224 | 242 | ||
243 | /* output */ | ||
244 | void dss_register_output(struct omap_dss_output *out); | ||
245 | void dss_unregister_output(struct omap_dss_output *out); | ||
246 | struct omap_dss_output *omapdss_get_output_from_dssdev(struct omap_dss_device *dssdev); | ||
247 | |||
225 | /* display */ | 248 | /* display */ |
226 | int dss_suspend_all_devices(void); | 249 | int dss_suspend_all_devices(void); |
227 | int dss_resume_all_devices(void); | 250 | int dss_resume_all_devices(void); |
228 | void dss_disable_all_devices(void); | 251 | void dss_disable_all_devices(void); |
229 | 252 | ||
230 | void dss_init_device(struct platform_device *pdev, | 253 | int dss_init_device(struct platform_device *pdev, |
231 | struct omap_dss_device *dssdev); | 254 | struct omap_dss_device *dssdev); |
232 | void dss_uninit_device(struct platform_device *pdev, | 255 | void 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 | ||
280 | int dss_manager_kobj_init(struct omap_overlay_manager *mgr, | ||
281 | struct platform_device *pdev); | ||
282 | void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr); | ||
283 | |||
257 | /* overlay */ | 284 | /* overlay */ |
258 | void dss_init_overlays(struct platform_device *pdev); | 285 | void dss_init_overlays(struct platform_device *pdev); |
259 | void dss_uninit_overlays(struct platform_device *pdev); | 286 | void dss_uninit_overlays(struct platform_device *pdev); |
260 | void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); | 287 | void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); |
261 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); | ||
262 | int dss_ovl_simple_check(struct omap_overlay *ovl, | 288 | int dss_ovl_simple_check(struct omap_overlay *ovl, |
263 | const struct omap_overlay_info *info); | 289 | const struct omap_overlay_info *info); |
264 | int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, | 290 | int 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); |
266 | bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, | 292 | bool dss_ovl_use_replication(struct dss_lcd_mgr_config config, |
267 | enum omap_color_mode mode); | 293 | enum omap_color_mode mode); |
294 | int dss_overlay_kobj_init(struct omap_overlay *ovl, | ||
295 | struct platform_device *pdev); | ||
296 | void dss_overlay_kobj_uninit(struct omap_overlay *ovl); | ||
268 | 297 | ||
269 | /* DSS */ | 298 | /* DSS */ |
270 | int dss_init_platform_driver(void) __init; | 299 | int dss_init_platform_driver(void) __init; |
271 | void dss_uninit_platform_driver(void); | 300 | void dss_uninit_platform_driver(void); |
272 | 301 | ||
302 | int dss_dpi_select_source(enum omap_channel channel); | ||
273 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 303 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
274 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | 304 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); |
275 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 305 | const 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); | |||
279 | void dss_debug_dump_clocks(struct seq_file *s); | 309 | void dss_debug_dump_clocks(struct seq_file *s); |
280 | #endif | 310 | #endif |
281 | 311 | ||
282 | void dss_sdi_init(u8 datapairs); | 312 | void dss_sdi_init(int datapairs); |
283 | int dss_sdi_enable(void); | 313 | int dss_sdi_enable(void); |
284 | void dss_sdi_disable(void); | 314 | void dss_sdi_disable(void); |
285 | 315 | ||
@@ -296,9 +326,7 @@ void dss_set_venc_output(enum omap_dss_venc_type type); | |||
296 | void dss_set_dac_pwrdn_bgz(bool enable); | 326 | void dss_set_dac_pwrdn_bgz(bool enable); |
297 | 327 | ||
298 | unsigned long dss_get_dpll4_rate(void); | 328 | unsigned long dss_get_dpll4_rate(void); |
299 | int dss_calc_clock_rates(struct dss_clock_info *cinfo); | ||
300 | int dss_set_clock_div(struct dss_clock_info *cinfo); | 329 | int dss_set_clock_div(struct dss_clock_info *cinfo); |
301 | int dss_get_clock_div(struct dss_clock_info *cinfo); | ||
302 | int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, | 330 | int 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); | |||
427 | void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, | 455 | void 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); |
430 | int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, | 458 | int 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); | ||
432 | int dispc_ovl_enable(enum omap_plane plane, bool enable); | 461 | int dispc_ovl_enable(enum omap_plane plane, bool enable); |
433 | void dispc_ovl_set_channel_out(enum omap_plane plane, | 462 | void 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, | |||
457 | void dispc_mgr_setup(enum omap_channel channel, | 486 | void dispc_mgr_setup(enum omap_channel channel, |
458 | struct omap_overlay_manager_info *info); | 487 | struct omap_overlay_manager_info *info); |
459 | 488 | ||
489 | u32 dispc_wb_get_framedone_irq(void); | ||
490 | bool dispc_wb_go_busy(void); | ||
491 | void dispc_wb_go(void); | ||
492 | void dispc_wb_enable(bool enable); | ||
493 | bool dispc_wb_is_enabled(void); | ||
494 | void dispc_wb_set_channel_in(enum dss_writeback_channel channel); | ||
495 | int 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 |
462 | int venc_init_platform_driver(void) __init; | 500 | int 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 |
510 | int omapdss_venc_display_enable(struct omap_dss_device *dssdev); | ||
511 | void omapdss_venc_display_disable(struct omap_dss_device *dssdev); | ||
512 | void omapdss_venc_set_timings(struct omap_dss_device *dssdev, | ||
513 | struct omap_video_timings *timings); | ||
514 | int omapdss_venc_check_timings(struct omap_dss_device *dssdev, | ||
515 | struct omap_video_timings *timings); | ||
516 | u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev); | ||
517 | int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss); | ||
518 | void omapdss_venc_set_type(struct omap_dss_device *dssdev, | ||
519 | enum omap_dss_venc_type type); | ||
520 | void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, | ||
521 | bool invert_polarity); | ||
522 | int venc_panel_init(void); | ||
523 | void 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 |
485 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | 537 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); |
486 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | 538 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); |
487 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); | 539 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, |
540 | struct omap_video_timings *timings); | ||
488 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 541 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, |
489 | struct omap_video_timings *timings); | 542 | struct omap_video_timings *timings); |
490 | int omapdss_hdmi_read_edid(u8 *buf, int len); | 543 | int 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 | ||
111 | static 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 | |||
109 | static const enum omap_display_type omap2_dss_supported_displays[] = { | 126 | static 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 | ||
164 | static 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 | |||
177 | static 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 | |||
185 | static 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 | |||
194 | static 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 | |||
203 | static 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 | |||
217 | static 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 | |||
147 | static const enum omap_color_mode omap2_dss_supported_color_modes[] = { | 234 | static 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 | ||
229 | static const enum omap_overlay_caps omap2_dss_overlay_caps[] = { | 326 | static 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 | ||
240 | static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = { | 339 | static 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 | ||
251 | static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = { | 353 | static 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 | ||
263 | static const enum omap_overlay_caps omap4_dss_overlay_caps[] = { | 368 | static 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 | ||
281 | static const char * const omap2_dss_clk_source_names[] = { | 390 | static 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 | ||
410 | static 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 | |||
301 | static const struct dss_param_range omap2_dss_param_range[] = { | 418 | static 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 | |||
469 | static 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 | |||
514 | static 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 | ||
378 | static const enum dss_feat_id omap3630_dss_feat_list[] = { | 533 | static 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 | ||
605 | static 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 */ |
451 | static const struct omap_dss_features omap2_dss_features = { | 628 | static 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 | */ | ||
673 | static 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 */ | ||
781 | static 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*/ |
572 | static const struct ti_hdmi_ip_ops omap4_hdmi_functions = { | 803 | static 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 | ||
846 | int dss_feat_get_num_wbs(void) | ||
847 | { | ||
848 | return omap_current_dss_features->num_wbs; | ||
849 | } | ||
850 | |||
615 | unsigned long dss_feat_get_param_min(enum dss_range_param param) | 851 | unsigned 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 | ||
866 | enum 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 | |||
630 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) | 871 | enum 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 */ |
101 | int dss_feat_get_num_mgrs(void); | 106 | int dss_feat_get_num_mgrs(void); |
102 | int dss_feat_get_num_ovls(void); | 107 | int dss_feat_get_num_ovls(void); |
108 | int dss_feat_get_num_wbs(void); | ||
103 | unsigned long dss_feat_get_param_min(enum dss_range_param param); | 109 | unsigned long dss_feat_get_param_min(enum dss_range_param param); |
104 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | 110 | unsigned long dss_feat_get_param_max(enum dss_range_param param); |
105 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | 111 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); |
112 | enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel); | ||
106 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 113 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
107 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); | 114 | enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); |
108 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 115 | bool 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 | ||
315 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) | 324 | static 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 | ||
358 | static 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 | |||
323 | static const struct hdmi_config *hdmi_find_timing( | 367 | static 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, | |||
459 | static int hdmi_power_on(struct omap_dss_device *dssdev) | 503 | static 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); |
538 | err_vid_enable: | 580 | err_vid_enable: |
539 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); | 581 | hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); |
582 | err_phy_enable: | ||
540 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); | 583 | hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); |
541 | err: | 584 | err_pll_enable: |
542 | hdmi_runtime_put(); | 585 | hdmi_runtime_put(); |
586 | err_runtime_get: | ||
587 | regulator_disable(hdmi.vdda_hdmi_dac_reg); | ||
588 | err_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 | ||
546 | static void hdmi_power_off(struct omap_dss_device *dssdev) | 594 | static 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 | ||
556 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | 611 | int 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 | ||
570 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | 625 | void 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 | ||
591 | static void hdmi_dump_regs(struct seq_file *s) | 643 | static void hdmi_dump_regs(struct seq_file *s) |
@@ -640,20 +692,20 @@ bool omapdss_hdmi_detect(void) | |||
640 | 692 | ||
641 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | 693 | int 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 | ||
681 | err2: | ||
682 | if (dssdev->platform_disable) | ||
683 | dssdev->platform_disable(dssdev); | ||
684 | err1: | 725 | err1: |
685 | omap_dss_stop_device(dssdev); | 726 | omap_dss_stop_device(dssdev); |
686 | err0: | 727 | err0: |
@@ -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 | ||
872 | static void __init hdmi_probe_pdata(struct platform_device *pdev) | 910 | static 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); | 938 | static 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 | |||
979 | static 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 | |||
990 | static 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 | ||
1047 | static 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 | |||
943 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 1054 | static 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 | ||
42 | static int hdmi_panel_probe(struct omap_dss_device *dssdev) | 42 | static 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 | |||
34 | static 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 | |||
39 | static 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 | |||
47 | static 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 | |||
105 | put_device: | ||
106 | if (dssdev) | ||
107 | omap_dss_put_device(dssdev); | ||
108 | |||
109 | return r ? r : size; | ||
110 | } | ||
111 | |||
112 | static 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 | |||
122 | static 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 | |||
148 | static const char *trans_key_type_str[] = { | ||
149 | "gfx-destination", | ||
150 | "video-source", | ||
151 | }; | ||
152 | |||
153 | static 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 | |||
167 | static 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 | |||
198 | static 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 | |||
208 | static 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 | |||
234 | static 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 | |||
244 | static 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 | |||
270 | static 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 | |||
283 | static 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 | |||
312 | static 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 | |||
322 | static 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 | |||
354 | static 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 | |||
374 | static 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 | |||
415 | struct 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 | |||
425 | static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); | ||
426 | static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, | ||
427 | manager_display_show, manager_display_store); | ||
428 | static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, | ||
429 | manager_default_color_show, manager_default_color_store); | ||
430 | static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, | ||
431 | manager_trans_key_type_show, manager_trans_key_type_store); | ||
432 | static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, | ||
433 | manager_trans_key_value_show, manager_trans_key_value_store); | ||
434 | static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, | ||
435 | manager_trans_key_enabled_show, | ||
436 | manager_trans_key_enabled_store); | ||
437 | static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, | ||
438 | manager_alpha_blending_enabled_show, | ||
439 | manager_alpha_blending_enabled_store); | ||
440 | static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, | ||
441 | manager_cpr_enable_show, | ||
442 | manager_cpr_enable_store); | ||
443 | static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, | ||
444 | manager_cpr_coef_show, | ||
445 | manager_cpr_coef_store); | ||
446 | |||
447 | |||
448 | static 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 | |||
461 | static 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 | |||
476 | static 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 | |||
491 | static const struct sysfs_ops manager_sysfs_ops = { | ||
492 | .show = manager_attr_show, | ||
493 | .store = manager_attr_store, | ||
494 | }; | ||
495 | |||
496 | static struct kobj_type manager_ktype = { | ||
497 | .sysfs_ops = &manager_sysfs_ops, | ||
498 | .default_attrs = manager_sysfs_attrs, | ||
499 | }; | ||
500 | |||
501 | int 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 | |||
508 | void 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 @@ | |||
36 | static int num_managers; | 36 | static int num_managers; |
37 | static struct omap_overlay_manager *managers; | 37 | static struct omap_overlay_manager *managers; |
38 | 38 | ||
39 | static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) | 39 | static 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 | ||
44 | static 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 | |||
50 | static 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 | |||
97 | put_device: | ||
98 | if (dssdev) | ||
99 | omap_dss_put_device(dssdev); | ||
100 | |||
101 | return r ? r : size; | ||
102 | } | ||
103 | |||
104 | static 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 | |||
114 | static 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 | |||
140 | static const char *trans_key_type_str[] = { | ||
141 | "gfx-destination", | ||
142 | "video-source", | ||
143 | }; | ||
144 | |||
145 | static 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 | |||
159 | static 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 | |||
190 | static 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 | |||
200 | static 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 | |||
226 | static 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 | |||
236 | static 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 | |||
262 | static 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 | |||
275 | static 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 | |||
304 | static 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 | |||
314 | static 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 | |||
346 | static 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 | |||
366 | static 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 | |||
407 | struct 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 | |||
417 | static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL); | ||
418 | static MANAGER_ATTR(display, S_IRUGO|S_IWUSR, | ||
419 | manager_display_show, manager_display_store); | ||
420 | static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR, | ||
421 | manager_default_color_show, manager_default_color_store); | ||
422 | static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR, | ||
423 | manager_trans_key_type_show, manager_trans_key_type_store); | ||
424 | static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR, | ||
425 | manager_trans_key_value_show, manager_trans_key_value_store); | ||
426 | static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR, | ||
427 | manager_trans_key_enabled_show, | ||
428 | manager_trans_key_enabled_store); | ||
429 | static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR, | ||
430 | manager_alpha_blending_enabled_show, | ||
431 | manager_alpha_blending_enabled_store); | ||
432 | static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR, | ||
433 | manager_cpr_enable_show, | ||
434 | manager_cpr_enable_store); | ||
435 | static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR, | ||
436 | manager_cpr_coef_show, | ||
437 | manager_cpr_coef_store); | ||
438 | |||
439 | |||
440 | static 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 | |||
453 | static 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 | |||
468 | static 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 | |||
483 | static const struct sysfs_ops manager_sysfs_ops = { | ||
484 | .show = manager_attr_show, | ||
485 | .store = manager_attr_store, | ||
486 | }; | ||
487 | |||
488 | static struct kobj_type manager_ktype = { | ||
489 | .sysfs_ops = &manager_sysfs_ops, | ||
490 | .default_attrs = manager_sysfs_attrs, | ||
491 | }; | ||
492 | |||
493 | static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | 44 | static 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 | |||
27 | static LIST_HEAD(output_list); | ||
28 | static DEFINE_MUTEX(output_lock); | ||
29 | |||
30 | int 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; | ||
56 | err: | ||
57 | mutex_unlock(&output_lock); | ||
58 | |||
59 | return r; | ||
60 | } | ||
61 | EXPORT_SYMBOL(omapdss_output_set_device); | ||
62 | |||
63 | int 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; | ||
88 | err: | ||
89 | mutex_unlock(&output_lock); | ||
90 | |||
91 | return r; | ||
92 | } | ||
93 | EXPORT_SYMBOL(omapdss_output_unset_device); | ||
94 | |||
95 | void dss_register_output(struct omap_dss_output *out) | ||
96 | { | ||
97 | list_add_tail(&out->list, &output_list); | ||
98 | } | ||
99 | |||
100 | void dss_unregister_output(struct omap_dss_output *out) | ||
101 | { | ||
102 | list_del(&out->list); | ||
103 | } | ||
104 | |||
105 | struct 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 | |||
117 | struct 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 | |||
34 | static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) | ||
35 | { | ||
36 | return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); | ||
37 | } | ||
38 | |||
39 | static 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 | |||
45 | static 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 | |||
111 | err: | ||
112 | dispc_runtime_put(); | ||
113 | return r; | ||
114 | } | ||
115 | |||
116 | static 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 | |||
126 | static 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 | |||
135 | static 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 | |||
145 | static 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 | |||
174 | static 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 | |||
184 | static 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 | |||
213 | static 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 | |||
218 | static 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 | |||
239 | static 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 | |||
249 | static 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 | |||
280 | static 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 | |||
291 | static 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 | |||
322 | static 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 | |||
331 | static 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 | |||
362 | struct 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 | |||
372 | static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); | ||
373 | static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, | ||
374 | overlay_manager_show, overlay_manager_store); | ||
375 | static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); | ||
376 | static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); | ||
377 | static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, | ||
378 | overlay_position_show, overlay_position_store); | ||
379 | static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, | ||
380 | overlay_output_size_show, overlay_output_size_store); | ||
381 | static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, | ||
382 | overlay_enabled_show, overlay_enabled_store); | ||
383 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | ||
384 | overlay_global_alpha_show, overlay_global_alpha_store); | ||
385 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | ||
386 | overlay_pre_mult_alpha_show, | ||
387 | overlay_pre_mult_alpha_store); | ||
388 | static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, | ||
389 | overlay_zorder_show, overlay_zorder_store); | ||
390 | |||
391 | static 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 | |||
405 | static 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 | |||
420 | static 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 | |||
435 | static const struct sysfs_ops overlay_sysfs_ops = { | ||
436 | .show = overlay_attr_show, | ||
437 | .store = overlay_attr_store, | ||
438 | }; | ||
439 | |||
440 | static struct kobj_type overlay_ktype = { | ||
441 | .sysfs_ops = &overlay_sysfs_ops, | ||
442 | .default_attrs = overlay_sysfs_attrs, | ||
443 | }; | ||
444 | |||
445 | int 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 | |||
452 | void 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 @@ | |||
40 | static int num_overlays; | 38 | static int num_overlays; |
41 | static struct omap_overlay *overlays; | 39 | static struct omap_overlay *overlays; |
42 | 40 | ||
43 | static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) | 41 | static 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 | ||
48 | static 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 | |||
54 | static 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 | |||
120 | err: | ||
121 | dispc_runtime_put(); | ||
122 | return r; | ||
123 | } | ||
124 | |||
125 | static 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 | |||
135 | static 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 | |||
144 | static 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 | |||
154 | static 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 | |||
183 | static 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 | |||
193 | static 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 | |||
222 | static 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 | |||
227 | static 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 | |||
248 | static 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 | |||
258 | static 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 | |||
289 | static 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 | |||
300 | static 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 | |||
331 | static 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 | |||
340 | static 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 | |||
371 | struct 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 | |||
381 | static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); | ||
382 | static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, | ||
383 | overlay_manager_show, overlay_manager_store); | ||
384 | static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); | ||
385 | static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); | ||
386 | static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, | ||
387 | overlay_position_show, overlay_position_store); | ||
388 | static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, | ||
389 | overlay_output_size_show, overlay_output_size_store); | ||
390 | static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, | ||
391 | overlay_enabled_show, overlay_enabled_store); | ||
392 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | ||
393 | overlay_global_alpha_show, overlay_global_alpha_store); | ||
394 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | ||
395 | overlay_pre_mult_alpha_show, | ||
396 | overlay_pre_mult_alpha_store); | ||
397 | static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, | ||
398 | overlay_zorder_show, overlay_zorder_store); | ||
399 | |||
400 | static 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 | |||
414 | static 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 | |||
429 | static 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 | |||
444 | static const struct sysfs_ops overlay_sysfs_ops = { | ||
445 | .show = overlay_attr_show, | ||
446 | .store = overlay_attr_store, | ||
447 | }; | ||
448 | |||
449 | static struct kobj_type overlay_ktype = { | ||
450 | .sysfs_ops = &overlay_sysfs_ops, | ||
451 | .default_attrs = overlay_sysfs_attrs, | ||
452 | }; | ||
453 | |||
454 | int omap_dss_get_num_overlays(void) | 48 | int 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. */ | ||
525 | void 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 | |||
592 | void dss_uninit_overlays(struct platform_device *pdev) | 116 | void 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 | ||
116 | static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) | 123 | static 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 | } |
301 | EXPORT_SYMBOL(omap_rfbi_write_pixels); | 308 | EXPORT_SYMBOL(omap_rfbi_write_pixels); |
302 | 309 | ||
303 | static int rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, | 310 | static 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 | ||
773 | int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, | 773 | int 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 | } |
778 | EXPORT_SYMBOL(omap_rfbi_configure); | 778 | EXPORT_SYMBOL(omap_rfbi_configure); |
779 | 779 | ||
780 | int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, | 780 | int 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, | 785 | EXPORT_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; | 787 | void 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 | } |
816 | EXPORT_SYMBOL(omap_rfbi_prepare_update); | 792 | EXPORT_SYMBOL(omapdss_rfbi_set_size); |
817 | 793 | ||
818 | int omap_rfbi_update(struct omap_dss_device *dssdev, | 794 | void 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 | } | ||
798 | EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size); | ||
823 | 799 | ||
824 | r = rfbi_transfer_area(dssdev, w, h, callback, data); | 800 | void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) |
801 | { | ||
802 | rfbi.data_lines = data_lines; | ||
803 | } | ||
804 | EXPORT_SYMBOL(omapdss_rfbi_set_data_lines); | ||
825 | 805 | ||
826 | return r; | 806 | void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, |
807 | struct rfbi_timings *timings) | ||
808 | { | ||
809 | rfbi.intf_timings = *timings; | ||
827 | } | 810 | } |
828 | EXPORT_SYMBOL(omap_rfbi_update); | 811 | EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings); |
829 | 812 | ||
830 | static void rfbi_dump_regs(struct seq_file *s) | 813 | static 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 | ||
870 | static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev) | 853 | static 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 | ||
886 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | 891 | int 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; |
923 | err1: | 926 | err1: |
@@ -941,14 +944,17 @@ EXPORT_SYMBOL(omapdss_rfbi_display_disable); | |||
941 | static int __init rfbi_init_display(struct omap_dss_device *dssdev) | 944 | static 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 | ||
948 | static void __init rfbi_probe_pdata(struct platform_device *pdev) | 950 | static 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 | |||
978 | static 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 | |||
1010 | static 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 | |||
1021 | static 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 | ||
1032 | static int __exit omap_rfbihw_remove(struct platform_device *pdev) | 1090 | static 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 | ||
39 | static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) | 44 | static 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 | ||
52 | int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | 59 | int 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 | ||
149 | void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | 156 | void 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 | } |
161 | EXPORT_SYMBOL(omapdss_sdi_display_disable); | 170 | EXPORT_SYMBOL(omapdss_sdi_display_disable); |
162 | 171 | ||
172 | void omapdss_sdi_set_timings(struct omap_dss_device *dssdev, | ||
173 | struct omap_video_timings *timings) | ||
174 | { | ||
175 | sdi.timings = *timings; | ||
176 | } | ||
177 | EXPORT_SYMBOL(omapdss_sdi_set_timings); | ||
178 | |||
179 | void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs) | ||
180 | { | ||
181 | sdi.datapairs = datapairs; | ||
182 | } | ||
183 | EXPORT_SYMBOL(omapdss_sdi_set_datapairs); | ||
184 | |||
163 | static int __init sdi_init_display(struct omap_dss_device *dssdev) | 185 | static 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 | ||
183 | static void __init sdi_probe_pdata(struct platform_device *pdev) | 205 | static 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 | |||
233 | static 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 | |||
265 | static 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 | |||
276 | static 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 | ||
207 | static int __init omap_sdi_probe(struct platform_device *pdev) | 283 | static 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 | ||
214 | static int __exit omap_sdi_remove(struct platform_device *pdev) | 292 | static 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 | ||
305 | static inline void venc_write_reg(int idx, u32 val) | 310 | static inline void venc_write_reg(int idx, u32 val) |
@@ -424,65 +429,67 @@ static const struct venc_config *venc_timings_to_config( | |||
424 | 429 | ||
425 | static int venc_power_on(struct omap_dss_device *dssdev) | 430 | static 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 | ||
463 | err: | 470 | err2: |
471 | regulator_disable(venc.vdda_dac_reg); | ||
472 | err1: | ||
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); | 477 | err0: |
469 | |||
470 | regulator_disable(venc.vdda_dac_reg); | ||
471 | |||
472 | return r; | 478 | return r; |
473 | } | 479 | } |
474 | 480 | ||
475 | static void venc_power_off(struct omap_dss_device *dssdev) | 481 | static 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 | ||
488 | unsigned long venc_get_pixel_clock(void) | 495 | unsigned 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 | ||
494 | static ssize_t display_output_type_show(struct device *dev, | 501 | int 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 | ||
514 | static 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 | |||
542 | static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, | ||
543 | display_output_type_show, display_output_type_store); | ||
544 | |||
545 | /* driver */ | ||
546 | static 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 | |||
553 | static void venc_panel_remove(struct omap_dss_device *dssdev) | ||
554 | { | ||
555 | device_remove_file(&dssdev->dev, &dev_attr_output_type); | ||
556 | } | ||
557 | |||
558 | static 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; |
591 | err2: | ||
592 | venc_runtime_put(); | ||
593 | err1: | 535 | err1: |
536 | if (dssdev->platform_disable) | ||
537 | dssdev->platform_disable(dssdev); | ||
594 | omap_dss_stop_device(dssdev); | 538 | omap_dss_stop_device(dssdev); |
595 | err0: | 539 | err0: |
596 | mutex_unlock(&venc.venc_lock); | 540 | mutex_unlock(&venc.venc_lock); |
597 | |||
598 | return r; | 541 | return r; |
599 | } | 542 | } |
600 | 543 | ||
601 | static void venc_panel_disable(struct omap_dss_device *dssdev) | 544 | void 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); |
623 | end: | ||
624 | mutex_unlock(&venc.venc_lock); | ||
625 | } | ||
626 | 553 | ||
627 | static 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 | ||
633 | static 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 | ||
638 | static void venc_set_timings(struct omap_dss_device *dssdev, | 560 | void 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 | ||
657 | static int venc_check_timings(struct omap_dss_device *dssdev, | 576 | int 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 | ||
671 | static u32 venc_get_wss(struct omap_dss_device *dssdev) | 590 | u32 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 | ||
677 | static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss) | 596 | int 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 | ||
706 | static struct omap_dss_driver venc_driver = { | 625 | void 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, | 635 | void 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 | ||
731 | static int __init venc_init_display(struct omap_dss_device *dssdev) | 645 | static 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 | ||
835 | static void __init venc_probe_pdata(struct platform_device *pdev) | 744 | static 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 | |||
772 | static 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 | |||
806 | static 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 | |||
817 | static 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 | ||
910 | err_reg_panel_driver: | 877 | err_panel_init: |
911 | err_runtime_get: | 878 | err_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 | ||
917 | static int __exit omap_venchw_remove(struct platform_device *pdev) | 884 | static 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 | ||
972 | int __init venc_init_platform_driver(void) | 941 | int __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 | ||
980 | void __exit venc_uninit_platform_driver(void) | 946 | void __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 | |||
30 | static struct { | ||
31 | struct mutex lock; | ||
32 | } venc_panel; | ||
33 | |||
34 | static 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 | |||
54 | static 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 | |||
83 | static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR, | ||
84 | display_output_type_show, display_output_type_store); | ||
85 | |||
86 | static 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 | |||
113 | static void venc_panel_remove(struct omap_dss_device *dssdev) | ||
114 | { | ||
115 | device_remove_file(&dssdev->dev, &dev_attr_output_type); | ||
116 | } | ||
117 | |||
118 | static 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; | ||
145 | err: | ||
146 | mutex_unlock(&venc_panel.lock); | ||
147 | |||
148 | return r; | ||
149 | } | ||
150 | |||
151 | static 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; | ||
169 | end: | ||
170 | mutex_unlock(&venc_panel.lock); | ||
171 | } | ||
172 | |||
173 | static int venc_panel_suspend(struct omap_dss_device *dssdev) | ||
174 | { | ||
175 | venc_panel_disable(dssdev); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int venc_panel_resume(struct omap_dss_device *dssdev) | ||
180 | { | ||
181 | return venc_panel_enable(dssdev); | ||
182 | } | ||
183 | |||
184 | static 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 | |||
197 | static 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 | |||
205 | static 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 | |||
212 | static 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 | |||
219 | static 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 | |||
243 | int venc_panel_init(void) | ||
244 | { | ||
245 | return omap_dss_register_driver(&venc_driver); | ||
246 | } | ||
247 | |||
248 | void 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 | ||
1596 | static 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 | |||
1596 | int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) | 1610 | int 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; |
1666 | err: | 1682 | err: |
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 | } |
251 | EXPORT_SYMBOL(omap_vram_reserve); | 250 | EXPORT_SYMBOL(omap_vram_reserve); |
252 | 251 | ||
253 | static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) | ||
254 | { | ||
255 | struct completion *compl = data; | ||
256 | complete(compl); | ||
257 | } | ||
258 | |||
259 | static 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; | ||
300 | err: | ||
301 | omap_free_dma(lch); | ||
302 | |||
303 | return r; | ||
304 | } | ||
305 | |||
306 | static int _omap_vram_alloc(unsigned pages, unsigned long *paddr) | 252 | static 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 | |||
5 | obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o | ||
6 | obj-$(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 | |||
148 | enum { | ||
149 | PAD_NONE, | ||
150 | PAD_512, | ||
151 | PAD_1024 | ||
152 | }; | ||
153 | |||
154 | enum { | ||
155 | RGB888, | ||
156 | RGB666, | ||
157 | RGB565, | ||
158 | BGR565, | ||
159 | ARGB1555, | ||
160 | ABGR1555, | ||
161 | ARGB4444, | ||
162 | ABGR4444 | ||
163 | }; | ||
164 | |||
165 | struct 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 | |||
184 | struct 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 | |||
202 | struct 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 | |||
36 | enum 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 | |||
31 | static u32 colreg[16]; | ||
32 | |||
33 | static 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 | }; | ||
51 | static 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 | |||
62 | static int channel_owned; | ||
63 | |||
64 | static int no_cursor(struct fb_info *info, struct fb_cursor *cursor) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static 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 | |||
80 | static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
81 | { | ||
82 | return pnx4008_sdum_mmap(info, vma, NULL); | ||
83 | } | ||
84 | |||
85 | static 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 | |||
93 | static 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 | |||
110 | static 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 | |||
178 | err2: | ||
179 | fb_dealloc_cmap(&info->cmap); | ||
180 | err1: | ||
181 | pnx4008_free_dum_channel(channel_owned, pdev->id); | ||
182 | err0: | ||
183 | framebuffer_release(info); | ||
184 | err: | ||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static struct platform_driver rgbfb_driver = { | ||
189 | .driver = { | ||
190 | .name = "pnx4008-rgbfb", | ||
191 | }, | ||
192 | .probe = rgbfb_probe, | ||
193 | .remove = rgbfb_remove, | ||
194 | }; | ||
195 | |||
196 | module_platform_driver(rgbfb_driver); | ||
197 | |||
198 | MODULE_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 | |||
41 | static 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 | |||
54 | static 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 | |||
65 | static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup) | ||
66 | { | ||
67 | return (ch_setup->xmax - ch_setup->xmin + 1); | ||
68 | } | ||
69 | |||
70 | static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup) | ||
71 | { | ||
72 | return (ch_setup->ymax - ch_setup->ymin + 1); | ||
73 | } | ||
74 | |||
75 | static 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 | |||
80 | static 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 | |||
96 | static 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 | |||
102 | static u32 build_double_index(int disp_no, u32 val) | ||
103 | { | ||
104 | return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0)); | ||
105 | } | ||
106 | |||
107 | static 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 | |||
117 | static 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 | |||
133 | static 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 | |||
146 | static 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 | |||
191 | static 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 | |||
331 | static 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 | |||
379 | static 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 | |||
390 | static 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 | |||
417 | static 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 | |||
452 | out: | ||
453 | iounmap((u32 *)cmdptrs); | ||
454 | } | ||
455 | |||
456 | static 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 | |||
483 | int 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 | |||
502 | EXPORT_SYMBOL(pnx4008_get_fb_addresses); | ||
503 | |||
504 | int 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 | |||
519 | EXPORT_SYMBOL(pnx4008_alloc_dum_channel); | ||
520 | |||
521 | int 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 | |||
535 | EXPORT_SYMBOL(pnx4008_free_dum_channel); | ||
536 | |||
537 | int 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 | |||
564 | EXPORT_SYMBOL(pnx4008_put_dum_channel_uf); | ||
565 | |||
566 | int 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 | |||
586 | EXPORT_SYMBOL(pnx4008_set_dum_channel_sync); | ||
587 | |||
588 | int 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 | |||
606 | EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect); | ||
607 | |||
608 | #if 0 /* Functions not used currently, but likely to be used in future */ | ||
609 | |||
610 | static 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 | |||
627 | int 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 | |||
647 | EXPORT_SYMBOL(pnx4008_get_dum_channel_uf); | ||
648 | |||
649 | int 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 | |||
667 | EXPORT_SYMBOL(pnx4008_get_dum_channel_config); | ||
668 | |||
669 | int 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 | |||
682 | EXPORT_SYMBOL(pnx4008_force_update_dum_channel); | ||
683 | |||
684 | #endif | ||
685 | |||
686 | int 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 | |||
701 | EXPORT_SYMBOL(pnx4008_sdum_mmap); | ||
702 | |||
703 | int 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 | |||
714 | EXPORT_SYMBOL(pnx4008_set_dum_exit_notification); | ||
715 | |||
716 | /* Platform device driver for DUM */ | ||
717 | |||
718 | static 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 | |||
739 | static 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 | |||
767 | static 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 | |||
818 | out_1: | ||
819 | iounmap((void *)dum_data.slave_virt_base); | ||
820 | out_2: | ||
821 | dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, | ||
822 | (void *)dum_data.lcd_virt_start, | ||
823 | dum_data.lcd_phys_start); | ||
824 | out_3: | ||
825 | return ret; | ||
826 | } | ||
827 | |||
828 | static 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 | |||
849 | static 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 | |||
859 | module_platform_driver(sdum_driver); | ||
860 | |||
861 | MODULE_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 | |||
80 | struct 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 | |||
90 | enum { | ||
91 | FB_TYPE_YUV, | ||
92 | FB_TYPE_RGB | ||
93 | }; | ||
94 | |||
95 | struct 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 | |||
110 | struct 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 | |||
119 | int pnx4008_alloc_dum_channel(int dev_id); | ||
120 | int pnx4008_free_dum_channel(int channr, int dev_id); | ||
121 | |||
122 | int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id); | ||
123 | int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id); | ||
124 | |||
125 | int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id); | ||
126 | int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id); | ||
127 | |||
128 | int pnx4008_force_dum_update_channel(int channr, int dev_id); | ||
129 | |||
130 | int pnx4008_get_dum_channel_config(int channr, int dev_id); | ||
131 | |||
132 | int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev); | ||
133 | int pnx4008_set_dum_exit_notification(int dev_id); | ||
134 | |||
135 | int 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: | |||
1510 | err_lcd_clk: | 1503 | err_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 | ||
1518 | err_bus_clk: | 1509 | err_bus_clk: |
1519 | clk_disable(sfb->bus_clk); | 1510 | clk_disable_unprepare(sfb->bus_clk); |
1520 | clk_put(sfb->bus_clk); | ||
1521 | 1511 | ||
1522 | err_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; | |||
48 | static int debug; | 50 | static int debug; |
49 | #endif | 51 | #endif |
50 | 52 | ||
51 | #define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg); | 53 | #define dprintk(msg...) \ |
54 | do { \ | ||
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) | |||
1134 | module_init(s3c2410fb_init); | 1140 | module_init(s3c2410fb_init); |
1135 | module_exit(s3c2410fb_cleanup); | 1141 | module_exit(s3c2410fb_cleanup); |
1136 | 1142 | ||
1137 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " | 1143 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); |
1138 | "Ben Dooks <ben-linux@fluff.org>"); | 1144 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); |
1139 | MODULE_DESCRIPTION("Framebuffer driver for the s3c2410"); | 1145 | MODULE_DESCRIPTION("Framebuffer driver for the s3c2410"); |
1140 | MODULE_LICENSE("GPL"); | 1146 | MODULE_LICENSE("GPL"); |
1141 | MODULE_ALIAS("platform:s3c2410-lcd"); | 1147 | MODULE_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 | ||
293 | static void noop_set_clock_state(u8 state) | ||
294 | { | ||
295 | } | ||
296 | |||
292 | void via_clock_init(struct via_clock *clock, int gfx_chip) | 297 | void 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 | } |