aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS24
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c24
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c290
-rw-r--r--arch/arm/mach-shmobile/board-bonito.c6
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c106
-rw-r--r--arch/arm/plat-samsung/include/plat/regs-fb.h33
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c22
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c20
-rw-r--r--arch/sh/boards/mach-kfr2r09/lcd_wqvga.c10
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c8
-rw-r--r--arch/sh/boards/mach-migor/lcd_qvga.c3
-rw-r--r--arch/sh/boards/mach-migor/setup.c16
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c12
-rw-r--r--arch/sh/include/mach-kfr2r09/mach/kfr2r09.h16
-rw-r--r--arch/sh/include/mach-migor/mach/migor.h2
-rw-r--r--drivers/video/Kconfig16
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/atmel_lcdfb.c12
-rw-r--r--drivers/video/au1100fb.c32
-rw-r--r--drivers/video/au1200fb.c9
-rw-r--r--drivers/video/bf537-lq035.c12
-rw-r--r--drivers/video/bf54x-lq043fb.c4
-rw-r--r--drivers/video/bfin-lq035q1-fb.c8
-rw-r--r--drivers/video/bfin_adv7393fb.c5
-rw-r--r--drivers/video/da8xx-fb.c79
-rw-r--r--drivers/video/exynos/Kconfig37
-rw-r--r--drivers/video/exynos/Makefile8
-rw-r--r--drivers/video/exynos/exynos_dp_core.c1058
-rw-r--r--drivers/video/exynos/exynos_dp_core.h206
-rw-r--r--drivers/video/exynos/exynos_dp_reg.c1173
-rw-r--r--drivers/video/exynos/exynos_dp_reg.h335
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi.c600
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_common.c896
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_common.h46
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_lowlevel.c618
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_lowlevel.h112
-rw-r--r--drivers/video/exynos/exynos_mipi_dsi_regs.h149
-rw-r--r--drivers/video/exynos/s6e8ax0.c898
-rw-r--r--drivers/video/exynos/s6e8ax0.h21
-rw-r--r--drivers/video/fbmem.c18
-rw-r--r--drivers/video/i740_reg.h309
-rw-r--r--drivers/video/i740fb.c1337
-rw-r--r--drivers/video/msm/mddi_client_nt35399.c7
-rw-r--r--drivers/video/msm/mddi_client_toshiba.c7
-rw-r--r--drivers/video/omap/lcd_inn1610.c10
-rw-r--r--drivers/video/omap/lcd_mipid.c14
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c13
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c12
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c12
-rw-r--r--drivers/video/omap2/displays/panel-taal.c4
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c24
-rw-r--r--drivers/video/pvr2fb.c4
-rw-r--r--drivers/video/pxa168fb.c15
-rw-r--r--drivers/video/pxafb.c6
-rw-r--r--drivers/video/riva/fbdev.c5
-rw-r--r--drivers/video/s3c-fb.c133
-rw-r--r--drivers/video/sh_mipi_dsi.c97
-rw-r--r--drivers/video/sh_mobile_hdmi.c297
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c1280
-rw-r--r--drivers/video/sh_mobile_lcdcfb.h84
-rw-r--r--drivers/video/sh_mobile_meram.c690
-rw-r--r--drivers/video/udlfb.c180
-rw-r--r--drivers/video/uvesafb.c26
-rw-r--r--drivers/video/via/Makefile5
-rw-r--r--drivers/video/via/chip.h3
-rw-r--r--drivers/video/via/dvi.c7
-rw-r--r--drivers/video/via/dvi.h3
-rw-r--r--drivers/video/via/hw.c130
-rw-r--r--drivers/video/via/hw.h9
-rw-r--r--drivers/video/via/lcd.c82
-rw-r--r--drivers/video/via/lcd.h3
-rw-r--r--drivers/video/via/share.h331
-rw-r--r--drivers/video/via/via_aux.c88
-rw-r--r--drivers/video/via/via_aux.h93
-rw-r--r--drivers/video/via/via_aux_ch7301.c50
-rw-r--r--drivers/video/via/via_aux_edid.c100
-rw-r--r--drivers/video/via/via_aux_sii164.c54
-rw-r--r--drivers/video/via/via_aux_vt1621.c44
-rw-r--r--drivers/video/via/via_aux_vt1622.c50
-rw-r--r--drivers/video/via/via_aux_vt1625.c50
-rw-r--r--drivers/video/via/via_aux_vt1631.c46
-rw-r--r--drivers/video/via/via_aux_vt1632.c54
-rw-r--r--drivers/video/via/via_aux_vt1636.c46
-rw-r--r--drivers/video/via/via_i2c.c10
-rw-r--r--drivers/video/via/viafbdev.c87
-rw-r--r--drivers/video/via/viafbdev.h6
-rw-r--r--drivers/video/via/viamode.c713
-rw-r--r--drivers/video/via/viamode.h11
-rw-r--r--include/linux/fb.h1
-rw-r--r--include/video/exynos_dp.h131
-rw-r--r--include/video/exynos_mipi_dsim.h359
-rw-r--r--include/video/sh_mobile_hdmi.h2
-rw-r--r--include/video/sh_mobile_lcdc.h35
-rw-r--r--include/video/sh_mobile_meram.h45
-rw-r--r--include/video/udlfb.h1
95 files changed, 11248 insertions, 2914 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4e41d5255d72..609b12ba82ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2230,6 +2230,15 @@ F: Documentation/filesystems/quota.txt
2230F: fs/quota/ 2230F: fs/quota/
2231F: include/linux/quota*.h 2231F: include/linux/quota*.h
2232 2232
2233DISPLAYLINK USB 2.0 FRAMEBUFFER DRIVER (UDLFB)
2234M: Bernie Thompson <bernie@plugable.com>
2235L: linux-fbdev@vger.kernel.org
2236S: Maintained
2237W: http://plugable.com/category/projects/udlfb/
2238F: drivers/video/udlfb.c
2239F: include/video/udlfb.h
2240F: Documentation/fb/udlfb.txt
2241
2233DISTRIBUTED LOCK MANAGER (DLM) 2242DISTRIBUTED LOCK MANAGER (DLM)
2234M: Christine Caulfield <ccaulfie@redhat.com> 2243M: Christine Caulfield <ccaulfie@redhat.com>
2235M: David Teigland <teigland@redhat.com> 2244M: David Teigland <teigland@redhat.com>
@@ -2631,6 +2640,21 @@ M: Mimi Zohar <zohar@us.ibm.com>
2631S: Supported 2640S: Supported
2632F: security/integrity/evm/ 2641F: security/integrity/evm/
2633 2642
2643EXYNOS DP DRIVER
2644M: Jingoo Han <jg1.han@samsung.com>
2645L: linux-fbdev@vger.kernel.org
2646S: Maintained
2647F: drivers/video/exynos/exynos_dp*
2648
2649EXYNOS MIPI DISPLAY DRIVERS
2650M: Inki Dae <inki.dae@samsung.com>
2651M: Donghwa Lee <dh09.lee@samsung.com>
2652M: Kyungmin Park <kyungmin.park@samsung.com>
2653L: linux-fbdev@vger.kernel.org
2654S: Maintained
2655F: drivers/video/exynos/exynos_mipi*
2656F: include/video/exynos_mipi*
2657
2634F71805F HARDWARE MONITORING DRIVER 2658F71805F HARDWARE MONITORING DRIVER
2635M: Jean Delvare <khali@linux-fr.org> 2659M: Jean Delvare <khali@linux-fr.org>
2636L: lm-sensors@lm-sensors.org 2660L: lm-sensors@lm-sensors.org
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 068b754bc348..33dad1da9310 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -229,16 +229,6 @@ static void lcd_backlight_reset(void)
229 gpio_set_value(GPIO_PORT235, 1); 229 gpio_set_value(GPIO_PORT235, 1);
230} 230}
231 231
232static void lcd_on(void *board_data, struct fb_info *info)
233{
234 lcd_backlight_on();
235}
236
237static void lcd_off(void *board_data)
238{
239 lcd_backlight_reset();
240}
241
242/* LCDC0 */ 232/* LCDC0 */
243static const struct fb_videomode lcdc0_modes[] = { 233static const struct fb_videomode lcdc0_modes[] = {
244 { 234 {
@@ -262,14 +252,14 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
262 .interface_type = RGB24, 252 .interface_type = RGB24,
263 .clock_divider = 1, 253 .clock_divider = 1,
264 .flags = LCDC_FLAGS_DWPOL, 254 .flags = LCDC_FLAGS_DWPOL,
265 .lcd_size_cfg.width = 44,
266 .lcd_size_cfg.height = 79,
267 .fourcc = V4L2_PIX_FMT_RGB565, 255 .fourcc = V4L2_PIX_FMT_RGB565,
268 .lcd_cfg = lcdc0_modes, 256 .lcd_modes = lcdc0_modes,
269 .num_cfg = ARRAY_SIZE(lcdc0_modes), 257 .num_modes = ARRAY_SIZE(lcdc0_modes),
270 .board_cfg = { 258 .panel_cfg = {
271 .display_on = lcd_on, 259 .width = 44,
272 .display_off = lcd_off, 260 .height = 79,
261 .display_on = lcd_backlight_on,
262 .display_off = lcd_backlight_reset,
273 }, 263 },
274 } 264 }
275}; 265};
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index eeb4d9664584..d4cc2dec5734 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -258,10 +258,16 @@ static struct sh_mobile_meram_info meram_info = {
258 258
259static struct resource meram_resources[] = { 259static struct resource meram_resources[] = {
260 [0] = { 260 [0] = {
261 .name = "MERAM", 261 .name = "regs",
262 .start = 0xe8000000, 262 .start = 0xe8000000,
263 .end = 0xe81fffff, 263 .end = 0xe807ffff,
264 .flags = IORESOURCE_MEM, 264 .flags = IORESOURCE_MEM,
265 },
266 [1] = {
267 .name = "meram",
268 .start = 0xe8080000,
269 .end = 0xe81fffff,
270 .flags = IORESOURCE_MEM,
265 }, 271 },
266}; 272};
267 273
@@ -437,82 +443,6 @@ static struct platform_device usb1_host_device = {
437 .resource = usb1_host_resources, 443 .resource = usb1_host_resources,
438}; 444};
439 445
440static const struct fb_videomode ap4evb_lcdc_modes[] = {
441 {
442#ifdef CONFIG_AP4EVB_QHD
443 .name = "R63302(QHD)",
444 .xres = 544,
445 .yres = 961,
446 .left_margin = 72,
447 .right_margin = 600,
448 .hsync_len = 16,
449 .upper_margin = 8,
450 .lower_margin = 8,
451 .vsync_len = 2,
452 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
453#else
454 .name = "WVGA Panel",
455 .xres = 800,
456 .yres = 480,
457 .left_margin = 220,
458 .right_margin = 110,
459 .hsync_len = 70,
460 .upper_margin = 20,
461 .lower_margin = 5,
462 .vsync_len = 5,
463 .sync = 0,
464#endif
465 },
466};
467static struct sh_mobile_meram_cfg lcd_meram_cfg = {
468 .icb[0] = {
469 .marker_icb = 28,
470 .cache_icb = 24,
471 .meram_offset = 0x0,
472 .meram_size = 0x40,
473 },
474 .icb[1] = {
475 .marker_icb = 29,
476 .cache_icb = 25,
477 .meram_offset = 0x40,
478 .meram_size = 0x40,
479 },
480};
481
482static struct sh_mobile_lcdc_info lcdc_info = {
483 .meram_dev = &meram_info,
484 .ch[0] = {
485 .chan = LCDC_CHAN_MAINLCD,
486 .fourcc = V4L2_PIX_FMT_RGB565,
487 .lcd_cfg = ap4evb_lcdc_modes,
488 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
489 .meram_cfg = &lcd_meram_cfg,
490 }
491};
492
493static struct resource lcdc_resources[] = {
494 [0] = {
495 .name = "LCDC",
496 .start = 0xfe940000, /* P4-only space */
497 .end = 0xfe943fff,
498 .flags = IORESOURCE_MEM,
499 },
500 [1] = {
501 .start = intcs_evt2irq(0x580),
502 .flags = IORESOURCE_IRQ,
503 },
504};
505
506static struct platform_device lcdc_device = {
507 .name = "sh_mobile_lcdc_fb",
508 .num_resources = ARRAY_SIZE(lcdc_resources),
509 .resource = lcdc_resources,
510 .dev = {
511 .platform_data = &lcdc_info,
512 .coherent_dma_mask = ~0,
513 },
514};
515
516/* 446/*
517 * QHD display 447 * QHD display
518 */ 448 */
@@ -593,6 +523,8 @@ static struct resource mipidsi0_resources[] = {
593 }, 523 },
594}; 524};
595 525
526static struct sh_mobile_lcdc_info lcdc_info;
527
596static struct sh_mipi_dsi_info mipidsi0_info = { 528static struct sh_mipi_dsi_info mipidsi0_info = {
597 .data_format = MIPI_RGB888, 529 .data_format = MIPI_RGB888,
598 .lcd_chan = &lcdc_info.ch[0], 530 .lcd_chan = &lcdc_info.ch[0],
@@ -619,6 +551,81 @@ static struct platform_device *qhd_devices[] __initdata = {
619}; 551};
620#endif /* CONFIG_AP4EVB_QHD */ 552#endif /* CONFIG_AP4EVB_QHD */
621 553
554/* LCDC0 */
555static const struct fb_videomode ap4evb_lcdc_modes[] = {
556 {
557#ifdef CONFIG_AP4EVB_QHD
558 .name = "R63302(QHD)",
559 .xres = 544,
560 .yres = 961,
561 .left_margin = 72,
562 .right_margin = 600,
563 .hsync_len = 16,
564 .upper_margin = 8,
565 .lower_margin = 8,
566 .vsync_len = 2,
567 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
568#else
569 .name = "WVGA Panel",
570 .xres = 800,
571 .yres = 480,
572 .left_margin = 220,
573 .right_margin = 110,
574 .hsync_len = 70,
575 .upper_margin = 20,
576 .lower_margin = 5,
577 .vsync_len = 5,
578 .sync = 0,
579#endif
580 },
581};
582
583static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
584 .icb[0] = {
585 .meram_size = 0x40,
586 },
587 .icb[1] = {
588 .meram_size = 0x40,
589 },
590};
591
592static struct sh_mobile_lcdc_info lcdc_info = {
593 .meram_dev = &meram_info,
594 .ch[0] = {
595 .chan = LCDC_CHAN_MAINLCD,
596 .fourcc = V4L2_PIX_FMT_RGB565,
597 .lcd_modes = ap4evb_lcdc_modes,
598 .num_modes = ARRAY_SIZE(ap4evb_lcdc_modes),
599 .meram_cfg = &lcd_meram_cfg,
600#ifdef CONFIG_AP4EVB_QHD
601 .tx_dev = &mipidsi0_device,
602#endif
603 }
604};
605
606static struct resource lcdc_resources[] = {
607 [0] = {
608 .name = "LCDC",
609 .start = 0xfe940000, /* P4-only space */
610 .end = 0xfe943fff,
611 .flags = IORESOURCE_MEM,
612 },
613 [1] = {
614 .start = intcs_evt2irq(0x580),
615 .flags = IORESOURCE_IRQ,
616 },
617};
618
619static struct platform_device lcdc_device = {
620 .name = "sh_mobile_lcdc_fb",
621 .num_resources = ARRAY_SIZE(lcdc_resources),
622 .resource = lcdc_resources,
623 .dev = {
624 .platform_data = &lcdc_info,
625 .coherent_dma_mask = ~0,
626 },
627};
628
622/* FSI */ 629/* FSI */
623#define IRQ_FSI evt2irq(0x1840) 630#define IRQ_FSI evt2irq(0x1840)
624static int __fsi_set_rate(struct clk *clk, long rate, int enable) 631static int __fsi_set_rate(struct clk *clk, long rate, int enable)
@@ -798,65 +805,11 @@ static struct platform_device fsi_ak4643_device = {
798 }, 805 },
799}; 806};
800 807
801static struct sh_mobile_meram_cfg hdmi_meram_cfg = { 808/* LCDC1 */
802 .icb[0] = {
803 .marker_icb = 30,
804 .cache_icb = 26,
805 .meram_offset = 0x80,
806 .meram_size = 0x100,
807 },
808 .icb[1] = {
809 .marker_icb = 31,
810 .cache_icb = 27,
811 .meram_offset = 0x180,
812 .meram_size = 0x100,
813 },
814};
815
816static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
817 .clock_source = LCDC_CLK_EXTERNAL,
818 .meram_dev = &meram_info,
819 .ch[0] = {
820 .chan = LCDC_CHAN_MAINLCD,
821 .fourcc = V4L2_PIX_FMT_RGB565,
822 .interface_type = RGB24,
823 .clock_divider = 1,
824 .flags = LCDC_FLAGS_DWPOL,
825 .meram_cfg = &hdmi_meram_cfg,
826 }
827};
828
829static struct resource lcdc1_resources[] = {
830 [0] = {
831 .name = "LCDC1",
832 .start = 0xfe944000,
833 .end = 0xfe947fff,
834 .flags = IORESOURCE_MEM,
835 },
836 [1] = {
837 .start = intcs_evt2irq(0x1780),
838 .flags = IORESOURCE_IRQ,
839 },
840};
841
842static struct platform_device lcdc1_device = {
843 .name = "sh_mobile_lcdc_fb",
844 .num_resources = ARRAY_SIZE(lcdc1_resources),
845 .resource = lcdc1_resources,
846 .id = 1,
847 .dev = {
848 .platform_data = &sh_mobile_lcdc1_info,
849 .coherent_dma_mask = ~0,
850 },
851};
852
853static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq, 809static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
854 unsigned long *parent_freq); 810 unsigned long *parent_freq);
855 811
856
857static struct sh_mobile_hdmi_info hdmi_info = { 812static struct sh_mobile_hdmi_info hdmi_info = {
858 .lcd_chan = &sh_mobile_lcdc1_info.ch[0],
859 .lcd_dev = &lcdc1_device.dev,
860 .flags = HDMI_SND_SRC_SPDIF, 813 .flags = HDMI_SND_SRC_SPDIF,
861 .clk_optimize_parent = ap4evb_clk_optimize, 814 .clk_optimize_parent = ap4evb_clk_optimize,
862}; 815};
@@ -885,10 +838,6 @@ static struct platform_device hdmi_device = {
885 }, 838 },
886}; 839};
887 840
888static struct platform_device fsi_hdmi_device = {
889 .name = "sh_fsi2_b_hdmi",
890};
891
892static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq, 841static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
893 unsigned long *parent_freq) 842 unsigned long *parent_freq)
894{ 843{
@@ -908,6 +857,57 @@ static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
908 return error; 857 return error;
909} 858}
910 859
860static const struct sh_mobile_meram_cfg hdmi_meram_cfg = {
861 .icb[0] = {
862 .meram_size = 0x100,
863 },
864 .icb[1] = {
865 .meram_size = 0x100,
866 },
867};
868
869static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
870 .clock_source = LCDC_CLK_EXTERNAL,
871 .meram_dev = &meram_info,
872 .ch[0] = {
873 .chan = LCDC_CHAN_MAINLCD,
874 .fourcc = V4L2_PIX_FMT_RGB565,
875 .interface_type = RGB24,
876 .clock_divider = 1,
877 .flags = LCDC_FLAGS_DWPOL,
878 .meram_cfg = &hdmi_meram_cfg,
879 .tx_dev = &hdmi_device,
880 }
881};
882
883static struct resource lcdc1_resources[] = {
884 [0] = {
885 .name = "LCDC1",
886 .start = 0xfe944000,
887 .end = 0xfe947fff,
888 .flags = IORESOURCE_MEM,
889 },
890 [1] = {
891 .start = intcs_evt2irq(0x1780),
892 .flags = IORESOURCE_IRQ,
893 },
894};
895
896static struct platform_device lcdc1_device = {
897 .name = "sh_mobile_lcdc_fb",
898 .num_resources = ARRAY_SIZE(lcdc1_resources),
899 .resource = lcdc1_resources,
900 .id = 1,
901 .dev = {
902 .platform_data = &sh_mobile_lcdc1_info,
903 .coherent_dma_mask = ~0,
904 },
905};
906
907static struct platform_device fsi_hdmi_device = {
908 .name = "sh_fsi2_b_hdmi",
909};
910
911static struct gpio_led ap4evb_leds[] = { 911static struct gpio_led ap4evb_leds[] = {
912 { 912 {
913 .name = "led4", 913 .name = "led4",
@@ -1042,9 +1042,9 @@ static struct platform_device *ap4evb_devices[] __initdata = {
1042 &fsi_ak4643_device, 1042 &fsi_ak4643_device,
1043 &fsi_hdmi_device, 1043 &fsi_hdmi_device,
1044 &sh_mmcif_device, 1044 &sh_mmcif_device,
1045 &lcdc1_device,
1046 &lcdc_device,
1047 &hdmi_device, 1045 &hdmi_device,
1046 &lcdc_device,
1047 &lcdc1_device,
1048 &ceu_device, 1048 &ceu_device,
1049 &ap4evb_camera, 1049 &ap4evb_camera,
1050 &meram_device, 1050 &meram_device,
@@ -1355,8 +1355,8 @@ static void __init ap4evb_init(void)
1355 lcdc_info.ch[0].interface_type = RGB24; 1355 lcdc_info.ch[0].interface_type = RGB24;
1356 lcdc_info.ch[0].clock_divider = 1; 1356 lcdc_info.ch[0].clock_divider = 1;
1357 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL; 1357 lcdc_info.ch[0].flags = LCDC_FLAGS_DWPOL;
1358 lcdc_info.ch[0].lcd_size_cfg.width = 44; 1358 lcdc_info.ch[0].panel_cfg.width = 44;
1359 lcdc_info.ch[0].lcd_size_cfg.height = 79; 1359 lcdc_info.ch[0].panel_cfg.height = 79;
1360 1360
1361 platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices)); 1361 platform_add_devices(qhd_devices, ARRAY_SIZE(qhd_devices));
1362 1362
@@ -1397,8 +1397,8 @@ static void __init ap4evb_init(void)
1397 lcdc_info.ch[0].interface_type = RGB18; 1397 lcdc_info.ch[0].interface_type = RGB18;
1398 lcdc_info.ch[0].clock_divider = 3; 1398 lcdc_info.ch[0].clock_divider = 3;
1399 lcdc_info.ch[0].flags = 0; 1399 lcdc_info.ch[0].flags = 0;
1400 lcdc_info.ch[0].lcd_size_cfg.width = 152; 1400 lcdc_info.ch[0].panel_cfg.width = 152;
1401 lcdc_info.ch[0].lcd_size_cfg.height = 91; 1401 lcdc_info.ch[0].panel_cfg.height = 91;
1402 1402
1403 /* enable TouchScreen */ 1403 /* enable TouchScreen */
1404 irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW); 1404 irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
index 4d2201622323..fb90f0898d9c 100644
--- a/arch/arm/mach-shmobile/board-bonito.c
+++ b/arch/arm/mach-shmobile/board-bonito.c
@@ -245,9 +245,9 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
245 .interface_type = RGB24, 245 .interface_type = RGB24,
246 .clock_divider = 5, 246 .clock_divider = 5,
247 .flags = 0, 247 .flags = 0,
248 .lcd_cfg = &lcdc0_mode, 248 .lcd_modes = &lcdc0_mode,
249 .num_cfg = 1, 249 .num_modes = 1,
250 .lcd_size_cfg = { 250 .panel_cfg = {
251 .width = 152, 251 .width = 152,
252 .height = 91, 252 .height = 91,
253 }, 253 },
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index a2813247b455..e761b280a602 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -318,8 +318,14 @@ static struct sh_mobile_meram_info mackerel_meram_info = {
318 318
319static struct resource meram_resources[] = { 319static struct resource meram_resources[] = {
320 [0] = { 320 [0] = {
321 .name = "MERAM", 321 .name = "regs",
322 .start = 0xe8000000, 322 .start = 0xe8000000,
323 .end = 0xe807ffff,
324 .flags = IORESOURCE_MEM,
325 },
326 [1] = {
327 .name = "meram",
328 .start = 0xe8080000,
323 .end = 0xe81fffff, 329 .end = 0xe81fffff,
324 .flags = IORESOURCE_MEM, 330 .flags = IORESOURCE_MEM,
325 }, 331 },
@@ -351,29 +357,23 @@ static struct fb_videomode mackerel_lcdc_modes[] = {
351 }, 357 },
352}; 358};
353 359
354static int mackerel_set_brightness(void *board_data, int brightness) 360static int mackerel_set_brightness(int brightness)
355{ 361{
356 gpio_set_value(GPIO_PORT31, brightness); 362 gpio_set_value(GPIO_PORT31, brightness);
357 363
358 return 0; 364 return 0;
359} 365}
360 366
361static int mackerel_get_brightness(void *board_data) 367static int mackerel_get_brightness(void)
362{ 368{
363 return gpio_get_value(GPIO_PORT31); 369 return gpio_get_value(GPIO_PORT31);
364} 370}
365 371
366static struct sh_mobile_meram_cfg lcd_meram_cfg = { 372static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
367 .icb[0] = { 373 .icb[0] = {
368 .marker_icb = 28,
369 .cache_icb = 24,
370 .meram_offset = 0x0,
371 .meram_size = 0x40, 374 .meram_size = 0x40,
372 }, 375 },
373 .icb[1] = { 376 .icb[1] = {
374 .marker_icb = 29,
375 .cache_icb = 25,
376 .meram_offset = 0x40,
377 .meram_size = 0x40, 377 .meram_size = 0x40,
378 }, 378 },
379}; 379};
@@ -384,20 +384,20 @@ static struct sh_mobile_lcdc_info lcdc_info = {
384 .ch[0] = { 384 .ch[0] = {
385 .chan = LCDC_CHAN_MAINLCD, 385 .chan = LCDC_CHAN_MAINLCD,
386 .fourcc = V4L2_PIX_FMT_RGB565, 386 .fourcc = V4L2_PIX_FMT_RGB565,
387 .lcd_cfg = mackerel_lcdc_modes, 387 .lcd_modes = mackerel_lcdc_modes,
388 .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes), 388 .num_modes = ARRAY_SIZE(mackerel_lcdc_modes),
389 .interface_type = RGB24, 389 .interface_type = RGB24,
390 .clock_divider = 3, 390 .clock_divider = 3,
391 .flags = 0, 391 .flags = 0,
392 .lcd_size_cfg.width = 152, 392 .panel_cfg = {
393 .lcd_size_cfg.height = 91, 393 .width = 152,
394 .board_cfg = { 394 .height = 91,
395 .set_brightness = mackerel_set_brightness,
396 .get_brightness = mackerel_get_brightness,
397 }, 395 },
398 .bl_info = { 396 .bl_info = {
399 .name = "sh_mobile_lcdc_bl", 397 .name = "sh_mobile_lcdc_bl",
400 .max_brightness = 1, 398 .max_brightness = 1,
399 .set_brightness = mackerel_set_brightness,
400 .get_brightness = mackerel_get_brightness,
401 }, 401 },
402 .meram_cfg = &lcd_meram_cfg, 402 .meram_cfg = &lcd_meram_cfg,
403 } 403 }
@@ -426,21 +426,44 @@ static struct platform_device lcdc_device = {
426 }, 426 },
427}; 427};
428 428
429static struct sh_mobile_meram_cfg hdmi_meram_cfg = { 429/* HDMI */
430static struct sh_mobile_hdmi_info hdmi_info = {
431 .flags = HDMI_SND_SRC_SPDIF,
432};
433
434static struct resource hdmi_resources[] = {
435 [0] = {
436 .name = "HDMI",
437 .start = 0xe6be0000,
438 .end = 0xe6be00ff,
439 .flags = IORESOURCE_MEM,
440 },
441 [1] = {
442 /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
443 .start = evt2irq(0x17e0),
444 .flags = IORESOURCE_IRQ,
445 },
446};
447
448static struct platform_device hdmi_device = {
449 .name = "sh-mobile-hdmi",
450 .num_resources = ARRAY_SIZE(hdmi_resources),
451 .resource = hdmi_resources,
452 .id = -1,
453 .dev = {
454 .platform_data = &hdmi_info,
455 },
456};
457
458static const struct sh_mobile_meram_cfg hdmi_meram_cfg = {
430 .icb[0] = { 459 .icb[0] = {
431 .marker_icb = 30,
432 .cache_icb = 26,
433 .meram_offset = 0x80,
434 .meram_size = 0x100, 460 .meram_size = 0x100,
435 }, 461 },
436 .icb[1] = { 462 .icb[1] = {
437 .marker_icb = 31,
438 .cache_icb = 27,
439 .meram_offset = 0x180,
440 .meram_size = 0x100, 463 .meram_size = 0x100,
441 }, 464 },
442}; 465};
443/* HDMI */ 466
444static struct sh_mobile_lcdc_info hdmi_lcdc_info = { 467static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
445 .meram_dev = &mackerel_meram_info, 468 .meram_dev = &mackerel_meram_info,
446 .clock_source = LCDC_CLK_EXTERNAL, 469 .clock_source = LCDC_CLK_EXTERNAL,
@@ -451,6 +474,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
451 .clock_divider = 1, 474 .clock_divider = 1,
452 .flags = LCDC_FLAGS_DWPOL, 475 .flags = LCDC_FLAGS_DWPOL,
453 .meram_cfg = &hdmi_meram_cfg, 476 .meram_cfg = &hdmi_meram_cfg,
477 .tx_dev = &hdmi_device,
454 } 478 }
455}; 479};
456 480
@@ -478,36 +502,6 @@ static struct platform_device hdmi_lcdc_device = {
478 }, 502 },
479}; 503};
480 504
481static struct sh_mobile_hdmi_info hdmi_info = {
482 .lcd_chan = &hdmi_lcdc_info.ch[0],
483 .lcd_dev = &hdmi_lcdc_device.dev,
484 .flags = HDMI_SND_SRC_SPDIF,
485};
486
487static struct resource hdmi_resources[] = {
488 [0] = {
489 .name = "HDMI",
490 .start = 0xe6be0000,
491 .end = 0xe6be00ff,
492 .flags = IORESOURCE_MEM,
493 },
494 [1] = {
495 /* There's also an HDMI interrupt on INTCS @ 0x18e0 */
496 .start = evt2irq(0x17e0),
497 .flags = IORESOURCE_IRQ,
498 },
499};
500
501static struct platform_device hdmi_device = {
502 .name = "sh-mobile-hdmi",
503 .num_resources = ARRAY_SIZE(hdmi_resources),
504 .resource = hdmi_resources,
505 .id = -1,
506 .dev = {
507 .platform_data = &hdmi_info,
508 },
509};
510
511static struct platform_device fsi_hdmi_device = { 505static struct platform_device fsi_hdmi_device = {
512 .name = "sh_fsi2_b_hdmi", 506 .name = "sh_fsi2_b_hdmi",
513}; 507};
@@ -1276,8 +1270,8 @@ static struct platform_device *mackerel_devices[] __initdata = {
1276 &sh_mmcif_device, 1270 &sh_mmcif_device,
1277 &ceu_device, 1271 &ceu_device,
1278 &mackerel_camera, 1272 &mackerel_camera,
1279 &hdmi_lcdc_device,
1280 &hdmi_device, 1273 &hdmi_device,
1274 &hdmi_lcdc_device,
1281 &meram_device, 1275 &meram_device,
1282}; 1276};
1283 1277
diff --git a/arch/arm/plat-samsung/include/plat/regs-fb.h b/arch/arm/plat-samsung/include/plat/regs-fb.h
index 8f39aa5b26ea..9a78012d6f43 100644
--- a/arch/arm/plat-samsung/include/plat/regs-fb.h
+++ b/arch/arm/plat-samsung/include/plat/regs-fb.h
@@ -91,6 +91,9 @@
91#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13) 91#define VIDCON1_VSTATUS_BACKPORCH (0x1 << 13)
92#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13) 92#define VIDCON1_VSTATUS_ACTIVE (0x2 << 13)
93#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13) 93#define VIDCON1_VSTATUS_FRONTPORCH (0x0 << 13)
94#define VIDCON1_VCLK_MASK (0x3 << 9)
95#define VIDCON1_VCLK_HOLD (0x0 << 9)
96#define VIDCON1_VCLK_RUN (0x1 << 9)
94 97
95#define VIDCON1_INV_VCLK (1 << 7) 98#define VIDCON1_INV_VCLK (1 << 7)
96#define VIDCON1_INV_HSYNC (1 << 6) 99#define VIDCON1_INV_HSYNC (1 << 6)
@@ -164,15 +167,17 @@
164#define VIDTCON1_HSPW(_x) ((_x) << 0) 167#define VIDTCON1_HSPW(_x) ((_x) << 0)
165 168
166#define VIDTCON2 (0x18) 169#define VIDTCON2 (0x18)
170#define VIDTCON2_LINEVAL_E(_x) ((((_x) & 0x800) >> 11) << 23)
167#define VIDTCON2_LINEVAL_MASK (0x7ff << 11) 171#define VIDTCON2_LINEVAL_MASK (0x7ff << 11)
168#define VIDTCON2_LINEVAL_SHIFT (11) 172#define VIDTCON2_LINEVAL_SHIFT (11)
169#define VIDTCON2_LINEVAL_LIMIT (0x7ff) 173#define VIDTCON2_LINEVAL_LIMIT (0x7ff)
170#define VIDTCON2_LINEVAL(_x) ((_x) << 11) 174#define VIDTCON2_LINEVAL(_x) (((_x) & 0x7ff) << 11)
171 175
176#define VIDTCON2_HOZVAL_E(_x) ((((_x) & 0x800) >> 11) << 22)
172#define VIDTCON2_HOZVAL_MASK (0x7ff << 0) 177#define VIDTCON2_HOZVAL_MASK (0x7ff << 0)
173#define VIDTCON2_HOZVAL_SHIFT (0) 178#define VIDTCON2_HOZVAL_SHIFT (0)
174#define VIDTCON2_HOZVAL_LIMIT (0x7ff) 179#define VIDTCON2_HOZVAL_LIMIT (0x7ff)
175#define VIDTCON2_HOZVAL(_x) ((_x) << 0) 180#define VIDTCON2_HOZVAL(_x) (((_x) & 0x7ff) << 0)
176 181
177/* WINCONx */ 182/* WINCONx */
178 183
@@ -228,25 +233,29 @@
228/* Local input channels (windows 0-2) */ 233/* Local input channels (windows 0-2) */
229#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win))) 234#define SHADOWCON_CHx_LOCAL_ENABLE(_win) (1 << (5 + (_win)))
230 235
236#define VIDOSDxA_TOPLEFT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
231#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11) 237#define VIDOSDxA_TOPLEFT_X_MASK (0x7ff << 11)
232#define VIDOSDxA_TOPLEFT_X_SHIFT (11) 238#define VIDOSDxA_TOPLEFT_X_SHIFT (11)
233#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff) 239#define VIDOSDxA_TOPLEFT_X_LIMIT (0x7ff)
234#define VIDOSDxA_TOPLEFT_X(_x) ((_x) << 11) 240#define VIDOSDxA_TOPLEFT_X(_x) (((_x) & 0x7ff) << 11)
235 241
242#define VIDOSDxA_TOPLEFT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
236#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0) 243#define VIDOSDxA_TOPLEFT_Y_MASK (0x7ff << 0)
237#define VIDOSDxA_TOPLEFT_Y_SHIFT (0) 244#define VIDOSDxA_TOPLEFT_Y_SHIFT (0)
238#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff) 245#define VIDOSDxA_TOPLEFT_Y_LIMIT (0x7ff)
239#define VIDOSDxA_TOPLEFT_Y(_x) ((_x) << 0) 246#define VIDOSDxA_TOPLEFT_Y(_x) (((_x) & 0x7ff) << 0)
240 247
248#define VIDOSDxB_BOTRIGHT_X_E(_x) ((((_x) & 0x800) >> 11) << 23)
241#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11) 249#define VIDOSDxB_BOTRIGHT_X_MASK (0x7ff << 11)
242#define VIDOSDxB_BOTRIGHT_X_SHIFT (11) 250#define VIDOSDxB_BOTRIGHT_X_SHIFT (11)
243#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff) 251#define VIDOSDxB_BOTRIGHT_X_LIMIT (0x7ff)
244#define VIDOSDxB_BOTRIGHT_X(_x) ((_x) << 11) 252#define VIDOSDxB_BOTRIGHT_X(_x) (((_x) & 0x7ff) << 11)
245 253
254#define VIDOSDxB_BOTRIGHT_Y_E(_x) ((((_x) & 0x800) >> 11) << 22)
246#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0) 255#define VIDOSDxB_BOTRIGHT_Y_MASK (0x7ff << 0)
247#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0) 256#define VIDOSDxB_BOTRIGHT_Y_SHIFT (0)
248#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff) 257#define VIDOSDxB_BOTRIGHT_Y_LIMIT (0x7ff)
249#define VIDOSDxB_BOTRIGHT_Y(_x) ((_x) << 0) 258#define VIDOSDxB_BOTRIGHT_Y(_x) (((_x) & 0x7ff) << 0)
250 259
251/* For VIDOSD[1..4]C */ 260/* For VIDOSD[1..4]C */
252#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20) 261#define VIDISD14C_ALPHA0_R(_x) ((_x) << 20)
@@ -278,15 +287,17 @@
278#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8)) 287#define VIDW_BUF_END1(_buff) (0xD4 + ((_buff) * 8))
279#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4)) 288#define VIDW_BUF_SIZE(_buff) (0x100 + ((_buff) * 4))
280 289
290#define VIDW_BUF_SIZE_OFFSET_E(_x) ((((_x) & 0x2000) >> 13) << 27)
281#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13) 291#define VIDW_BUF_SIZE_OFFSET_MASK (0x1fff << 13)
282#define VIDW_BUF_SIZE_OFFSET_SHIFT (13) 292#define VIDW_BUF_SIZE_OFFSET_SHIFT (13)
283#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff) 293#define VIDW_BUF_SIZE_OFFSET_LIMIT (0x1fff)
284#define VIDW_BUF_SIZE_OFFSET(_x) ((_x) << 13) 294#define VIDW_BUF_SIZE_OFFSET(_x) (((_x) & 0x1fff) << 13)
285 295
296#define VIDW_BUF_SIZE_PAGEWIDTH_E(_x) ((((_x) & 0x2000) >> 13) << 26)
286#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0) 297#define VIDW_BUF_SIZE_PAGEWIDTH_MASK (0x1fff << 0)
287#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0) 298#define VIDW_BUF_SIZE_PAGEWIDTH_SHIFT (0)
288#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff) 299#define VIDW_BUF_SIZE_PAGEWIDTH_LIMIT (0x1fff)
289#define VIDW_BUF_SIZE_PAGEWIDTH(_x) ((_x) << 0) 300#define VIDW_BUF_SIZE_PAGEWIDTH(_x) (((_x) & 0x1fff) << 0)
290 301
291/* Interrupt controls and status */ 302/* Interrupt controls and status */
292 303
@@ -384,3 +395,9 @@
384#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0) 395#define WPALCON_W0PAL_16BPP_A555 (0x5 << 0)
385#define WPALCON_W0PAL_16BPP_565 (0x6 << 0) 396#define WPALCON_W0PAL_16BPP_565 (0x6 << 0)
386 397
398/* Blending equation control */
399#define BLENDCON (0x260)
400#define BLENDCON_NEW_MASK (1 << 0)
401#define BLENDCON_NEW_8BIT_ALPHA_VALUE (1 << 0)
402#define BLENDCON_NEW_4BIT_ALPHA_VALUE (0 << 0)
403
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index ebd0f818a25f..8cf02e343333 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -157,7 +157,7 @@ static struct platform_device nand_flash_device = {
157#define PORT_DRVCRA 0xA405018A 157#define PORT_DRVCRA 0xA405018A
158#define PORT_DRVCRB 0xA405018C 158#define PORT_DRVCRB 0xA405018C
159 159
160static int ap320_wvga_set_brightness(void *board_data, int brightness) 160static int ap320_wvga_set_brightness(int brightness)
161{ 161{
162 if (brightness) { 162 if (brightness) {
163 gpio_set_value(GPIO_PTS3, 0); 163 gpio_set_value(GPIO_PTS3, 0);
@@ -170,12 +170,12 @@ static int ap320_wvga_set_brightness(void *board_data, int brightness)
170 return 0; 170 return 0;
171} 171}
172 172
173static int ap320_wvga_get_brightness(void *board_data) 173static int ap320_wvga_get_brightness(void)
174{ 174{
175 return gpio_get_value(GPIO_PTS3); 175 return gpio_get_value(GPIO_PTS3);
176} 176}
177 177
178static void ap320_wvga_power_on(void *board_data, struct fb_info *info) 178static void ap320_wvga_power_on(void)
179{ 179{
180 msleep(100); 180 msleep(100);
181 181
@@ -183,7 +183,7 @@ static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
183 __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG); 183 __raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
184} 184}
185 185
186static void ap320_wvga_power_off(void *board_data) 186static void ap320_wvga_power_off(void)
187{ 187{
188 /* ASD AP-320/325 LCD OFF */ 188 /* ASD AP-320/325 LCD OFF */
189 __raw_writew(0, FPGA_LCDREG); 189 __raw_writew(0, FPGA_LCDREG);
@@ -211,21 +211,19 @@ static struct sh_mobile_lcdc_info lcdc_info = {
211 .fourcc = V4L2_PIX_FMT_RGB565, 211 .fourcc = V4L2_PIX_FMT_RGB565,
212 .interface_type = RGB18, 212 .interface_type = RGB18,
213 .clock_divider = 1, 213 .clock_divider = 1,
214 .lcd_cfg = ap325rxa_lcdc_modes, 214 .lcd_modes = ap325rxa_lcdc_modes,
215 .num_cfg = ARRAY_SIZE(ap325rxa_lcdc_modes), 215 .num_modes = ARRAY_SIZE(ap325rxa_lcdc_modes),
216 .lcd_size_cfg = { /* 7.0 inch */ 216 .panel_cfg = {
217 .width = 152, 217 .width = 152, /* 7.0 inch */
218 .height = 91, 218 .height = 91,
219 },
220 .board_cfg = {
221 .display_on = ap320_wvga_power_on, 219 .display_on = ap320_wvga_power_on,
222 .display_off = ap320_wvga_power_off, 220 .display_off = ap320_wvga_power_off,
223 .set_brightness = ap320_wvga_set_brightness,
224 .get_brightness = ap320_wvga_get_brightness,
225 }, 221 },
226 .bl_info = { 222 .bl_info = {
227 .name = "sh_mobile_lcdc_bl", 223 .name = "sh_mobile_lcdc_bl",
228 .max_brightness = 1, 224 .max_brightness = 1,
225 .set_brightness = ap320_wvga_set_brightness,
226 .get_brightness = ap320_wvga_get_brightness,
229 }, 227 },
230 } 228 }
231}; 229};
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index cde7c0085ced..0b08230546e7 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -310,14 +310,14 @@ static const struct fb_videomode ecovec_dvi_modes[] = {
310 }, 310 },
311}; 311};
312 312
313static int ecovec24_set_brightness(void *board_data, int brightness) 313static int ecovec24_set_brightness(int brightness)
314{ 314{
315 gpio_set_value(GPIO_PTR1, brightness); 315 gpio_set_value(GPIO_PTR1, brightness);
316 316
317 return 0; 317 return 0;
318} 318}
319 319
320static int ecovec24_get_brightness(void *board_data) 320static int ecovec24_get_brightness(void)
321{ 321{
322 return gpio_get_value(GPIO_PTR1); 322 return gpio_get_value(GPIO_PTR1);
323} 323}
@@ -327,17 +327,15 @@ static struct sh_mobile_lcdc_info lcdc_info = {
327 .interface_type = RGB18, 327 .interface_type = RGB18,
328 .chan = LCDC_CHAN_MAINLCD, 328 .chan = LCDC_CHAN_MAINLCD,
329 .fourcc = V4L2_PIX_FMT_RGB565, 329 .fourcc = V4L2_PIX_FMT_RGB565,
330 .lcd_size_cfg = { /* 7.0 inch */ 330 .panel_cfg = { /* 7.0 inch */
331 .width = 152, 331 .width = 152,
332 .height = 91, 332 .height = 91,
333 }, 333 },
334 .board_cfg = {
335 .set_brightness = ecovec24_set_brightness,
336 .get_brightness = ecovec24_get_brightness,
337 },
338 .bl_info = { 334 .bl_info = {
339 .name = "sh_mobile_lcdc_bl", 335 .name = "sh_mobile_lcdc_bl",
340 .max_brightness = 1, 336 .max_brightness = 1,
337 .set_brightness = ecovec24_set_brightness,
338 .get_brightness = ecovec24_get_brightness,
341 }, 339 },
342 } 340 }
343}; 341};
@@ -1116,8 +1114,8 @@ static int __init arch_setup(void)
1116 /* DVI */ 1114 /* DVI */
1117 lcdc_info.clock_source = LCDC_CLK_EXTERNAL; 1115 lcdc_info.clock_source = LCDC_CLK_EXTERNAL;
1118 lcdc_info.ch[0].clock_divider = 1; 1116 lcdc_info.ch[0].clock_divider = 1;
1119 lcdc_info.ch[0].lcd_cfg = ecovec_dvi_modes; 1117 lcdc_info.ch[0].lcd_modes = ecovec_dvi_modes;
1120 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_dvi_modes); 1118 lcdc_info.ch[0].num_modes = ARRAY_SIZE(ecovec_dvi_modes);
1121 1119
1122 gpio_set_value(GPIO_PTA2, 1); 1120 gpio_set_value(GPIO_PTA2, 1);
1123 gpio_set_value(GPIO_PTU1, 1); 1121 gpio_set_value(GPIO_PTU1, 1);
@@ -1125,8 +1123,8 @@ static int __init arch_setup(void)
1125 /* Panel */ 1123 /* Panel */
1126 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL; 1124 lcdc_info.clock_source = LCDC_CLK_PERIPHERAL;
1127 lcdc_info.ch[0].clock_divider = 2; 1125 lcdc_info.ch[0].clock_divider = 2;
1128 lcdc_info.ch[0].lcd_cfg = ecovec_lcd_modes; 1126 lcdc_info.ch[0].lcd_modes = ecovec_lcd_modes;
1129 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(ecovec_lcd_modes); 1127 lcdc_info.ch[0].num_modes = ARRAY_SIZE(ecovec_lcd_modes);
1130 1128
1131 gpio_set_value(GPIO_PTR1, 1); 1129 gpio_set_value(GPIO_PTR1, 1);
1132 1130
diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
index 25e145fb7087..c148b36ecb65 100644
--- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -251,8 +251,7 @@ static void display_on(void *sohandle,
251 write_memory_start(sohandle, so); 251 write_memory_start(sohandle, so);
252} 252}
253 253
254int kfr2r09_lcd_setup(void *board_data, void *sohandle, 254int kfr2r09_lcd_setup(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
255 struct sh_mobile_lcdc_sys_bus_ops *so)
256{ 255{
257 /* power on */ 256 /* power on */
258 gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */ 257 gpio_set_value(GPIO_PTF4, 0); /* PROTECT/ -> L */
@@ -273,8 +272,7 @@ int kfr2r09_lcd_setup(void *board_data, void *sohandle,
273 return 0; 272 return 0;
274} 273}
275 274
276void kfr2r09_lcd_start(void *board_data, void *sohandle, 275void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
277 struct sh_mobile_lcdc_sys_bus_ops *so)
278{ 276{
279 write_memory_start(sohandle, so); 277 write_memory_start(sohandle, so);
280} 278}
@@ -327,12 +325,12 @@ static int kfr2r09_lcd_backlight(int on)
327 return 0; 325 return 0;
328} 326}
329 327
330void kfr2r09_lcd_on(void *board_data, struct fb_info *info) 328void kfr2r09_lcd_on(void)
331{ 329{
332 kfr2r09_lcd_backlight(1); 330 kfr2r09_lcd_backlight(1);
333} 331}
334 332
335void kfr2r09_lcd_off(void *board_data) 333void kfr2r09_lcd_off(void)
336{ 334{
337 kfr2r09_lcd_backlight(0); 335 kfr2r09_lcd_backlight(0);
338} 336}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 5b382e1afaea..d04a55d3b877 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -148,13 +148,11 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
148 .interface_type = SYS18, 148 .interface_type = SYS18,
149 .clock_divider = 6, 149 .clock_divider = 6,
150 .flags = LCDC_FLAGS_DWPOL, 150 .flags = LCDC_FLAGS_DWPOL,
151 .lcd_cfg = kfr2r09_lcdc_modes, 151 .lcd_modes = kfr2r09_lcdc_modes,
152 .num_cfg = ARRAY_SIZE(kfr2r09_lcdc_modes), 152 .num_modes = ARRAY_SIZE(kfr2r09_lcdc_modes),
153 .lcd_size_cfg = { 153 .panel_cfg = {
154 .width = 35, 154 .width = 35,
155 .height = 58, 155 .height = 58,
156 },
157 .board_cfg = {
158 .setup_sys = kfr2r09_lcd_setup, 156 .setup_sys = kfr2r09_lcd_setup,
159 .start_transfer = kfr2r09_lcd_start, 157 .start_transfer = kfr2r09_lcd_start,
160 .display_on = kfr2r09_lcd_on, 158 .display_on = kfr2r09_lcd_on,
diff --git a/arch/sh/boards/mach-migor/lcd_qvga.c b/arch/sh/boards/mach-migor/lcd_qvga.c
index de9014a8a93e..8bccd345b69c 100644
--- a/arch/sh/boards/mach-migor/lcd_qvga.c
+++ b/arch/sh/boards/mach-migor/lcd_qvga.c
@@ -113,8 +113,7 @@ static const unsigned short magic3_data[] = {
113 0x0010, 0x16B0, 0x0011, 0x0111, 0x0007, 0x0061, 113 0x0010, 0x16B0, 0x0011, 0x0111, 0x0007, 0x0061,
114}; 114};
115 115
116int migor_lcd_qvga_setup(void *board_data, void *sohandle, 116int migor_lcd_qvga_setup(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
117 struct sh_mobile_lcdc_sys_bus_ops *so)
118{ 117{
119 unsigned long xres = 320; 118 unsigned long xres = 320;
120 unsigned long yres = 240; 119 unsigned long yres = 240;
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index d37ba2720527..ff6f69c6906e 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -246,9 +246,9 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
246 .fourcc = V4L2_PIX_FMT_RGB565, 246 .fourcc = V4L2_PIX_FMT_RGB565,
247 .interface_type = RGB16, 247 .interface_type = RGB16,
248 .clock_divider = 2, 248 .clock_divider = 2,
249 .lcd_cfg = migor_lcd_modes, 249 .lcd_modes = migor_lcd_modes,
250 .num_cfg = ARRAY_SIZE(migor_lcd_modes), 250 .num_modes = ARRAY_SIZE(migor_lcd_modes),
251 .lcd_size_cfg = { /* 7.0 inch */ 251 .panel_cfg = { /* 7.0 inch */
252 .width = 152, 252 .width = 152,
253 .height = 91, 253 .height = 91,
254 }, 254 },
@@ -260,13 +260,11 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
260 .fourcc = V4L2_PIX_FMT_RGB565, 260 .fourcc = V4L2_PIX_FMT_RGB565,
261 .interface_type = SYS16A, 261 .interface_type = SYS16A,
262 .clock_divider = 10, 262 .clock_divider = 10,
263 .lcd_cfg = migor_lcd_modes, 263 .lcd_modes = migor_lcd_modes,
264 .num_cfg = ARRAY_SIZE(migor_lcd_modes), 264 .num_modes = ARRAY_SIZE(migor_lcd_modes),
265 .lcd_size_cfg = { /* 2.4 inch */ 265 .panel_cfg = {
266 .width = 49, 266 .width = 49, /* 2.4 inch */
267 .height = 37, 267 .height = 37,
268 },
269 .board_cfg = {
270 .setup_sys = migor_lcd_qvga_setup, 268 .setup_sys = migor_lcd_qvga_setup,
271 }, 269 },
272 .sys_bus_cfg = { 270 .sys_bus_cfg = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 2b07fc016950..9bf528b4ae21 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -182,12 +182,10 @@ static struct sh_mobile_lcdc_info lcdc_info = {
182 .chan = LCDC_CHAN_MAINLCD, 182 .chan = LCDC_CHAN_MAINLCD,
183 .fourcc = V4L2_PIX_FMT_RGB565, 183 .fourcc = V4L2_PIX_FMT_RGB565,
184 .clock_divider = 1, 184 .clock_divider = 1,
185 .lcd_size_cfg = { /* 7.0 inch */ 185 .panel_cfg = { /* 7.0 inch */
186 .width = 152, 186 .width = 152,
187 .height = 91, 187 .height = 91,
188 }, 188 },
189 .board_cfg = {
190 },
191 } 189 }
192}; 190};
193 191
@@ -888,12 +886,12 @@ static int __init devices_setup(void)
888 886
889 if (sw & SW41_B) { 887 if (sw & SW41_B) {
890 /* 720p */ 888 /* 720p */
891 lcdc_info.ch[0].lcd_cfg = lcdc_720p_modes; 889 lcdc_info.ch[0].lcd_modes = lcdc_720p_modes;
892 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_720p_modes); 890 lcdc_info.ch[0].num_modes = ARRAY_SIZE(lcdc_720p_modes);
893 } else { 891 } else {
894 /* VGA */ 892 /* VGA */
895 lcdc_info.ch[0].lcd_cfg = lcdc_vga_modes; 893 lcdc_info.ch[0].lcd_modes = lcdc_vga_modes;
896 lcdc_info.ch[0].num_cfg = ARRAY_SIZE(lcdc_vga_modes); 894 lcdc_info.ch[0].num_modes = ARRAY_SIZE(lcdc_vga_modes);
897 } 895 }
898 896
899 if (sw & SW41_A) { 897 if (sw & SW41_A) {
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
index 07e635b0e04c..ba3d93d333f8 100644
--- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -4,21 +4,21 @@
4#include <video/sh_mobile_lcdc.h> 4#include <video/sh_mobile_lcdc.h>
5 5
6#if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE) 6#if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
7void kfr2r09_lcd_on(void *board_data, struct fb_info *info); 7void kfr2r09_lcd_on(void);
8void kfr2r09_lcd_off(void *board_data); 8void kfr2r09_lcd_off(void);
9int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle, 9int kfr2r09_lcd_setup(void *sys_ops_handle,
10 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 10 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
11void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle, 11void kfr2r09_lcd_start(void *sys_ops_handle,
12 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 12 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
13#else 13#else
14static void kfr2r09_lcd_on(void *board_data) {} 14static void kfr2r09_lcd_on(void) {}
15static void kfr2r09_lcd_off(void *board_data) {} 15static void kfr2r09_lcd_off(void) {}
16static int kfr2r09_lcd_setup(void *board_data, void *sys_ops_handle, 16static int kfr2r09_lcd_setup(void *sys_ops_handle,
17 struct sh_mobile_lcdc_sys_bus_ops *sys_ops) 17 struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
18{ 18{
19 return -ENODEV; 19 return -ENODEV;
20} 20}
21static void kfr2r09_lcd_start(void *board_data, void *sys_ops_handle, 21static void kfr2r09_lcd_start(void *sys_ops_handle,
22 struct sh_mobile_lcdc_sys_bus_ops *sys_ops) 22 struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
23{ 23{
24} 24}
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
index 42fccf93412e..7de7bb74c290 100644
--- a/arch/sh/include/mach-migor/mach/migor.h
+++ b/arch/sh/include/mach-migor/mach/migor.h
@@ -9,7 +9,7 @@
9 9
10#include <video/sh_mobile_lcdc.h> 10#include <video/sh_mobile_lcdc.h>
11 11
12int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle, 12int migor_lcd_qvga_setup(void *sys_ops_handle,
13 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 13 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
14 14
15#endif /* __ASM_SH_MIGOR_H */ 15#endif /* __ASM_SH_MIGOR_H */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6ca0c407c144..005347a35b61 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1123,6 +1123,18 @@ config FB_RIVA_BACKLIGHT
1123 help 1123 help
1124 Say Y here if you want to control the backlight of your display. 1124 Say Y here if you want to control the backlight of your display.
1125 1125
1126config FB_I740
1127 tristate "Intel740 support (EXPERIMENTAL)"
1128 depends on EXPERIMENTAL && FB && PCI
1129 select FB_MODE_HELPERS
1130 select FB_CFB_FILLRECT
1131 select FB_CFB_COPYAREA
1132 select FB_CFB_IMAGEBLIT
1133 select VGASTATE
1134 select FB_DDC
1135 help
1136 This driver supports graphics cards based on Intel740 chip.
1137
1126config FB_I810 1138config FB_I810
1127 tristate "Intel 810/815 support (EXPERIMENTAL)" 1139 tristate "Intel 810/815 support (EXPERIMENTAL)"
1128 depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL 1140 depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
@@ -2004,6 +2016,7 @@ config FB_SH_MOBILE_HDMI
2004config FB_SH_MOBILE_MERAM 2016config FB_SH_MOBILE_MERAM
2005 tristate "SuperH Mobile MERAM read ahead support for LCDC" 2017 tristate "SuperH Mobile MERAM read ahead support for LCDC"
2006 depends on FB_SH_MOBILE_LCDC 2018 depends on FB_SH_MOBILE_LCDC
2019 select GENERIC_ALLOCATOR
2007 default y 2020 default y
2008 ---help--- 2021 ---help---
2009 Enable MERAM support for the SH-Mobile LCD controller. 2022 Enable MERAM support for the SH-Mobile LCD controller.
@@ -2233,6 +2246,7 @@ config FB_DA8XX
2233 select FB_CFB_FILLRECT 2246 select FB_CFB_FILLRECT
2234 select FB_CFB_COPYAREA 2247 select FB_CFB_COPYAREA
2235 select FB_CFB_IMAGEBLIT 2248 select FB_CFB_IMAGEBLIT
2249 select FB_CFB_REV_PIXELS_IN_BYTE
2236 ---help--- 2250 ---help---
2237 This is the frame buffer device driver for the TI LCD controller 2251 This is the frame buffer device driver for the TI LCD controller
2238 found on DA8xx/OMAP-L1xx SoCs. 2252 found on DA8xx/OMAP-L1xx SoCs.
@@ -2411,7 +2425,7 @@ config FB_PUV3_UNIGFX
2411 2425
2412source "drivers/video/omap/Kconfig" 2426source "drivers/video/omap/Kconfig"
2413source "drivers/video/omap2/Kconfig" 2427source "drivers/video/omap2/Kconfig"
2414 2428source "drivers/video/exynos/Kconfig"
2415source "drivers/video/backlight/Kconfig" 2429source "drivers/video/backlight/Kconfig"
2416 2430
2417if VT 2431if VT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 142606814d98..9356add945b3 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -15,6 +15,8 @@ obj-$(CONFIG_VT) += console/
15obj-$(CONFIG_LOGO) += logo/ 15obj-$(CONFIG_LOGO) += logo/
16obj-y += backlight/ 16obj-y += backlight/
17 17
18obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
19
18obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o 20obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
19obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o 21obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
20obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o 22obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
@@ -37,6 +39,7 @@ obj-$(CONFIG_FB_GRVGA) += grvga.o
37obj-$(CONFIG_FB_PM2) += pm2fb.o 39obj-$(CONFIG_FB_PM2) += pm2fb.o
38obj-$(CONFIG_FB_PM3) += pm3fb.o 40obj-$(CONFIG_FB_PM3) += pm3fb.o
39 41
42obj-$(CONFIG_FB_I740) += i740fb.o
40obj-$(CONFIG_FB_MATROX) += matrox/ 43obj-$(CONFIG_FB_MATROX) += matrox/
41obj-$(CONFIG_FB_RIVA) += riva/ 44obj-$(CONFIG_FB_RIVA) += riva/
42obj-$(CONFIG_FB_NVIDIA) += nvidia/ 45obj-$(CONFIG_FB_NVIDIA) += nvidia/
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index e40c00f2c2ba..d99505b16374 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -421,24 +421,18 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
421 var->red.length = var->green.length = var->blue.length 421 var->red.length = var->green.length = var->blue.length
422 = var->bits_per_pixel; 422 = var->bits_per_pixel;
423 break; 423 break;
424 case 15:
425 case 16: 424 case 16:
426 if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { 425 if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
427 /* RGB:565 mode */ 426 /* RGB:565 mode */
428 var->red.offset = 11; 427 var->red.offset = 11;
429 var->blue.offset = 0; 428 var->blue.offset = 0;
430 var->green.length = 6;
431 } else if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB555) {
432 var->red.offset = 10;
433 var->blue.offset = 0;
434 var->green.length = 5;
435 } else { 429 } else {
436 /* BGR:555 mode */ 430 /* BGR:565 mode */
437 var->red.offset = 0; 431 var->red.offset = 0;
438 var->blue.offset = 10; 432 var->blue.offset = 11;
439 var->green.length = 5;
440 } 433 }
441 var->green.offset = 5; 434 var->green.offset = 5;
435 var->green.length = 6;
442 var->red.length = var->blue.length = 5; 436 var->red.length = var->blue.length = 5;
443 break; 437 break;
444 case 32: 438 case 32:
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index de9da6774fd9..befcbd8ef019 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -477,7 +477,8 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
477 u32 sys_clksrc; 477 u32 sys_clksrc;
478 478
479 /* Allocate new device private */ 479 /* Allocate new device private */
480 fbdev = kzalloc(sizeof(struct au1100fb_device), GFP_KERNEL); 480 fbdev = devm_kzalloc(&dev->dev, sizeof(struct au1100fb_device),
481 GFP_KERNEL);
481 if (!fbdev) { 482 if (!fbdev) {
482 print_err("fail to allocate device private record"); 483 print_err("fail to allocate device private record");
483 return -ENOMEM; 484 return -ENOMEM;
@@ -498,8 +499,9 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
498 au1100fb_fix.mmio_start = regs_res->start; 499 au1100fb_fix.mmio_start = regs_res->start;
499 au1100fb_fix.mmio_len = resource_size(regs_res); 500 au1100fb_fix.mmio_len = resource_size(regs_res);
500 501
501 if (!request_mem_region(au1100fb_fix.mmio_start, au1100fb_fix.mmio_len, 502 if (!devm_request_mem_region(au1100fb_fix.mmio_start,
502 DRIVER_NAME)) { 503 au1100fb_fix.mmio_len,
504 DRIVER_NAME)) {
503 print_err("fail to lock memory region at 0x%08lx", 505 print_err("fail to lock memory region at 0x%08lx",
504 au1100fb_fix.mmio_start); 506 au1100fb_fix.mmio_start);
505 return -EBUSY; 507 return -EBUSY;
@@ -514,8 +516,9 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
514 fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres * 516 fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
515 (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS; 517 (fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
516 518
517 fbdev->fb_mem = dma_alloc_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), 519 fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, &dev->dev,
518 &fbdev->fb_phys, GFP_KERNEL); 520 PAGE_ALIGN(fbdev->fb_len),
521 &fbdev->fb_phys, GFP_KERNEL);
519 if (!fbdev->fb_mem) { 522 if (!fbdev->fb_mem) {
520 print_err("fail to allocate frambuffer (size: %dK))", 523 print_err("fail to allocate frambuffer (size: %dK))",
521 fbdev->fb_len / 1024); 524 fbdev->fb_len / 1024);
@@ -557,14 +560,14 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
557 fbdev->info.fbops = &au1100fb_ops; 560 fbdev->info.fbops = &au1100fb_ops;
558 fbdev->info.fix = au1100fb_fix; 561 fbdev->info.fix = au1100fb_fix;
559 562
560 if (!(fbdev->info.pseudo_palette = kzalloc(sizeof(u32) * 16, GFP_KERNEL))) { 563 fbdev->info.pseudo_palette =
564 devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL);
565 if (!fbdev->info.pseudo_palette)
561 return -ENOMEM; 566 return -ENOMEM;
562 }
563 567
564 if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { 568 if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
565 print_err("Fail to allocate colormap (%d entries)", 569 print_err("Fail to allocate colormap (%d entries)",
566 AU1100_LCD_NBR_PALETTE_ENTRIES); 570 AU1100_LCD_NBR_PALETTE_ENTRIES);
567 kfree(fbdev->info.pseudo_palette);
568 return -EFAULT; 571 return -EFAULT;
569 } 572 }
570 573
@@ -582,9 +585,6 @@ static int __devinit au1100fb_drv_probe(struct platform_device *dev)
582 return 0; 585 return 0;
583 586
584failed: 587failed:
585 if (fbdev->regs) {
586 release_mem_region(fbdev->regs_phys, fbdev->regs_len);
587 }
588 if (fbdev->fb_mem) { 588 if (fbdev->fb_mem) {
589 dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem, 589 dma_free_noncoherent(&dev->dev, fbdev->fb_len, fbdev->fb_mem,
590 fbdev->fb_phys); 590 fbdev->fb_phys);
@@ -592,10 +592,9 @@ failed:
592 if (fbdev->info.cmap.len != 0) { 592 if (fbdev->info.cmap.len != 0) {
593 fb_dealloc_cmap(&fbdev->info.cmap); 593 fb_dealloc_cmap(&fbdev->info.cmap);
594 } 594 }
595 kfree(fbdev);
596 platform_set_drvdata(dev, NULL); 595 platform_set_drvdata(dev, NULL);
597 596
598 return 0; 597 return -ENODEV;
599} 598}
600 599
601int au1100fb_drv_remove(struct platform_device *dev) 600int au1100fb_drv_remove(struct platform_device *dev)
@@ -615,14 +614,7 @@ int au1100fb_drv_remove(struct platform_device *dev)
615 /* Clean up all probe data */ 614 /* Clean up all probe data */
616 unregister_framebuffer(&fbdev->info); 615 unregister_framebuffer(&fbdev->info);
617 616
618 release_mem_region(fbdev->regs_phys, fbdev->regs_len);
619
620 dma_free_coherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem,
621 fbdev->fb_phys);
622
623 fb_dealloc_cmap(&fbdev->info.cmap); 617 fb_dealloc_cmap(&fbdev->info.cmap);
624 kfree(fbdev->info.pseudo_palette);
625 kfree((void*)fbdev);
626 618
627 return 0; 619 return 0;
628} 620}
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 04e4479d5afd..3e9a773db09f 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1724,7 +1724,7 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
1724 /* Allocate the framebuffer to the maximum screen size */ 1724 /* Allocate the framebuffer to the maximum screen size */
1725 fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; 1725 fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
1726 1726
1727 fbdev->fb_mem = dma_alloc_noncoherent(&dev->dev, 1727 fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, &dev->dev,
1728 PAGE_ALIGN(fbdev->fb_len), 1728 PAGE_ALIGN(fbdev->fb_len),
1729 &fbdev->fb_phys, GFP_KERNEL); 1729 &fbdev->fb_phys, GFP_KERNEL);
1730 if (!fbdev->fb_mem) { 1730 if (!fbdev->fb_mem) {
@@ -1788,9 +1788,6 @@ static int __devinit au1200fb_drv_probe(struct platform_device *dev)
1788 1788
1789failed: 1789failed:
1790 /* NOTE: This only does the current plane/window that failed; others are still active */ 1790 /* NOTE: This only does the current plane/window that failed; others are still active */
1791 if (fbdev->fb_mem)
1792 dma_free_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len),
1793 fbdev->fb_mem, fbdev->fb_phys);
1794 if (fbi) { 1791 if (fbi) {
1795 if (fbi->cmap.len != 0) 1792 if (fbi->cmap.len != 0)
1796 fb_dealloc_cmap(&fbi->cmap); 1793 fb_dealloc_cmap(&fbi->cmap);
@@ -1817,10 +1814,6 @@ static int __devexit au1200fb_drv_remove(struct platform_device *dev)
1817 1814
1818 /* Clean up all probe data */ 1815 /* Clean up all probe data */
1819 unregister_framebuffer(fbi); 1816 unregister_framebuffer(fbi);
1820 if (fbdev->fb_mem)
1821 dma_free_noncoherent(&dev->dev,
1822 PAGE_ALIGN(fbdev->fb_len),
1823 fbdev->fb_mem, fbdev->fb_phys);
1824 if (fbi->cmap.len != 0) 1817 if (fbi->cmap.len != 0)
1825 fb_dealloc_cmap(&fbi->cmap); 1818 fb_dealloc_cmap(&fbi->cmap);
1826 kfree(fbi->pseudo_palette); 1819 kfree(fbi->pseudo_palette);
diff --git a/drivers/video/bf537-lq035.c b/drivers/video/bf537-lq035.c
index bea53c1a4950..befbc80d11fc 100644
--- a/drivers/video/bf537-lq035.c
+++ b/drivers/video/bf537-lq035.c
@@ -383,23 +383,19 @@ static int __devinit request_ports(void)
383 } 383 }
384 384
385#if (defined(UD) && defined(LBR)) 385#if (defined(UD) && defined(LBR))
386 if (gpio_request(UD, KBUILD_MODNAME)) { 386 if (gpio_request_one(UD, GPIOF_OUT_INIT_LOW, KBUILD_MODNAME)) {
387 pr_err("requesting GPIO %d failed\n", UD); 387 pr_err("requesting GPIO %d failed\n", UD);
388 return -EBUSY; 388 return -EBUSY;
389 } 389 }
390 390
391 if (gpio_request(LBR, KBUILD_MODNAME)) { 391 if (gpio_request_one(LBR, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
392 pr_err("requesting GPIO %d failed\n", LBR); 392 pr_err("requesting GPIO %d failed\n", LBR);
393 gpio_free(UD); 393 gpio_free(UD);
394 return -EBUSY; 394 return -EBUSY;
395 } 395 }
396
397 gpio_direction_output(UD, 0);
398 gpio_direction_output(LBR, 1);
399
400#endif 396#endif
401 397
402 if (gpio_request(MOD, KBUILD_MODNAME)) { 398 if (gpio_request_one(MOD, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME)) {
403 pr_err("requesting GPIO %d failed\n", MOD); 399 pr_err("requesting GPIO %d failed\n", MOD);
404#if (defined(UD) && defined(LBR)) 400#if (defined(UD) && defined(LBR))
405 gpio_free(LBR); 401 gpio_free(LBR);
@@ -408,8 +404,6 @@ static int __devinit request_ports(void)
408 return -EBUSY; 404 return -EBUSY;
409 } 405 }
410 406
411 gpio_direction_output(MOD, 1);
412
413 SSYNC(); 407 SSYNC();
414 return 0; 408 return 0;
415} 409}
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index 46b03f53985f..dc2f0047769b 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -240,7 +240,7 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
240 u16 eppi_req_18[] = EPPI0_18; 240 u16 eppi_req_18[] = EPPI0_18;
241 u16 disp = fbi->mach_info->disp; 241 u16 disp = fbi->mach_info->disp;
242 242
243 if (gpio_request(disp, DRIVER_NAME)) { 243 if (gpio_request_one(disp, GPIOF_OUT_INIT_HIGH, DRIVER_NAME)) {
244 printk(KERN_ERR "Requesting GPIO %d failed\n", disp); 244 printk(KERN_ERR "Requesting GPIO %d failed\n", disp);
245 return -EFAULT; 245 return -EFAULT;
246 } 246 }
@@ -263,8 +263,6 @@ static int request_ports(struct bfin_bf54xfb_info *fbi)
263 } 263 }
264 } 264 }
265 265
266 gpio_direction_output(disp, 1);
267
268 return 0; 266 return 0;
269} 267}
270 268
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index c633068372c9..86922ac84412 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -365,10 +365,10 @@ static int __devinit bfin_lq035q1_request_ports(struct platform_device *pdev,
365 * Drive PPI_FS3 Low 365 * Drive PPI_FS3 Low
366 */ 366 */
367 if (ANOMALY_05000400) { 367 if (ANOMALY_05000400) {
368 int ret = gpio_request(P_IDENT(P_PPI0_FS3), "PPI_FS3"); 368 int ret = gpio_request_one(P_IDENT(P_PPI0_FS3),
369 GPIOF_OUT_INIT_LOW, "PPI_FS3");
369 if (ret) 370 if (ret)
370 return ret; 371 return ret;
371 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
372 } 372 }
373 373
374 if (ppi16) 374 if (ppi16)
@@ -716,14 +716,14 @@ static int __devinit bfin_lq035q1_probe(struct platform_device *pdev)
716 } 716 }
717 717
718 if (info->disp_info->use_bl) { 718 if (info->disp_info->use_bl) {
719 ret = gpio_request(info->disp_info->gpio_bl, "LQ035 Backlight"); 719 ret = gpio_request_one(info->disp_info->gpio_bl,
720 GPIOF_OUT_INIT_LOW, "LQ035 Backlight");
720 721
721 if (ret) { 722 if (ret) {
722 dev_err(&pdev->dev, "failed to request GPIO %d\n", 723 dev_err(&pdev->dev, "failed to request GPIO %d\n",
723 info->disp_info->gpio_bl); 724 info->disp_info->gpio_bl);
724 goto out9; 725 goto out9;
725 } 726 }
726 gpio_direction_output(info->disp_info->gpio_bl, 0);
727 } 727 }
728 728
729 ret = register_framebuffer(fbinfo); 729 ret = register_framebuffer(fbinfo);
diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/bfin_adv7393fb.c
index 811dd7f6aa41..c99281429214 100644
--- a/drivers/video/bfin_adv7393fb.c
+++ b/drivers/video/bfin_adv7393fb.c
@@ -411,12 +411,13 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
411 411
412 /* Workaround "PPI Does Not Start Properly In Specific Mode" */ 412 /* Workaround "PPI Does Not Start Properly In Specific Mode" */
413 if (ANOMALY_05000400) { 413 if (ANOMALY_05000400) {
414 if (gpio_request(P_IDENT(P_PPI0_FS3), "PPI0_FS3")) { 414 ret = gpio_request_one(P_IDENT(P_PPI0_FS3), GPIOF_OUT_INIT_LOW,
415 "PPI0_FS3")
416 if (ret) {
415 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n"); 417 dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
416 ret = -EBUSY; 418 ret = -EBUSY;
417 goto out_8; 419 goto out_8;
418 } 420 }
419 gpio_direction_output(P_IDENT(P_PPI0_FS3), 0);
420 } 421 }
421 422
422 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) { 423 if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c
index 29577bf1f559..47118c75a4c0 100644
--- a/drivers/video/da8xx-fb.c
+++ b/drivers/video/da8xx-fb.c
@@ -32,6 +32,7 @@
32#include <linux/console.h> 32#include <linux/console.h>
33#include <linux/slab.h> 33#include <linux/slab.h>
34#include <video/da8xx-fb.h> 34#include <video/da8xx-fb.h>
35#include <asm/div64.h>
35 36
36#define DRIVER_NAME "da8xx_lcdc" 37#define DRIVER_NAME "da8xx_lcdc"
37 38
@@ -161,6 +162,7 @@ struct da8xx_fb_par {
161 int vsync_timeout; 162 int vsync_timeout;
162#ifdef CONFIG_CPU_FREQ 163#ifdef CONFIG_CPU_FREQ
163 struct notifier_block freq_transition; 164 struct notifier_block freq_transition;
165 unsigned int lcd_fck_rate;
164#endif 166#endif
165 void (*panel_power_ctrl)(int); 167 void (*panel_power_ctrl)(int);
166}; 168};
@@ -174,7 +176,6 @@ static struct fb_var_screeninfo da8xx_fb_var __devinitdata = {
174 .activate = 0, 176 .activate = 0,
175 .height = -1, 177 .height = -1,
176 .width = -1, 178 .width = -1,
177 .pixclock = 46666, /* 46us - AUO display */
178 .accel_flags = 0, 179 .accel_flags = 0,
179 .left_margin = LEFT_MARGIN, 180 .left_margin = LEFT_MARGIN,
180 .right_margin = RIGHT_MARGIN, 181 .right_margin = RIGHT_MARGIN,
@@ -238,6 +239,20 @@ static struct da8xx_panel known_lcd_panels[] = {
238 .pxl_clk = 7833600, 239 .pxl_clk = 7833600,
239 .invert_pxl_clk = 0, 240 .invert_pxl_clk = 0,
240 }, 241 },
242 [2] = {
243 /* Hitachi SP10Q010 */
244 .name = "SP10Q010",
245 .width = 320,
246 .height = 240,
247 .hfp = 10,
248 .hbp = 10,
249 .hsw = 10,
250 .vfp = 10,
251 .vbp = 10,
252 .vsw = 10,
253 .pxl_clk = 7833600,
254 .invert_pxl_clk = 0,
255 },
241}; 256};
242 257
243/* Enable the Raster Engine of the LCD Controller */ 258/* Enable the Raster Engine of the LCD Controller */
@@ -546,7 +561,26 @@ static int fb_setcolreg(unsigned regno, unsigned red, unsigned green,
546 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 561 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR)
547 return 1; 562 return 1;
548 563
549 if (info->var.bits_per_pixel == 8) { 564 if (info->var.bits_per_pixel == 4) {
565 if (regno > 15)
566 return 1;
567
568 if (info->var.grayscale) {
569 pal = regno;
570 } else {
571 red >>= 4;
572 green >>= 8;
573 blue >>= 12;
574
575 pal = (red & 0x0f00);
576 pal |= (green & 0x00f0);
577 pal |= (blue & 0x000f);
578 }
579 if (regno == 0)
580 pal |= 0x2000;
581 palette[regno] = pal;
582
583 } else if (info->var.bits_per_pixel == 8) {
550 red >>= 4; 584 red >>= 4;
551 green >>= 8; 585 green >>= 8;
552 blue >>= 12; 586 blue >>= 12;
@@ -801,6 +835,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
801 var->blue.length = 8; 835 var->blue.length = 8;
802 var->transp.offset = 0; 836 var->transp.offset = 0;
803 var->transp.length = 0; 837 var->transp.length = 0;
838 var->nonstd = 0;
804 break; 839 break;
805 case 4: 840 case 4:
806 var->red.offset = 0; 841 var->red.offset = 0;
@@ -811,6 +846,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
811 var->blue.length = 4; 846 var->blue.length = 4;
812 var->transp.offset = 0; 847 var->transp.offset = 0;
813 var->transp.length = 0; 848 var->transp.length = 0;
849 var->nonstd = FB_NONSTD_REV_PIX_IN_B;
814 break; 850 break;
815 case 16: /* RGB 565 */ 851 case 16: /* RGB 565 */
816 var->red.offset = 11; 852 var->red.offset = 11;
@@ -821,6 +857,7 @@ static int fb_check_var(struct fb_var_screeninfo *var,
821 var->blue.length = 5; 857 var->blue.length = 5;
822 var->transp.offset = 0; 858 var->transp.offset = 0;
823 var->transp.length = 0; 859 var->transp.length = 0;
860 var->nonstd = 0;
824 break; 861 break;
825 default: 862 default:
826 err = -EINVAL; 863 err = -EINVAL;
@@ -840,11 +877,13 @@ static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb,
840 struct da8xx_fb_par *par; 877 struct da8xx_fb_par *par;
841 878
842 par = container_of(nb, struct da8xx_fb_par, freq_transition); 879 par = container_of(nb, struct da8xx_fb_par, freq_transition);
843 if (val == CPUFREQ_PRECHANGE) { 880 if (val == CPUFREQ_POSTCHANGE) {
844 lcd_disable_raster(); 881 if (par->lcd_fck_rate != clk_get_rate(par->lcdc_clk)) {
845 } else if (val == CPUFREQ_POSTCHANGE) { 882 par->lcd_fck_rate = clk_get_rate(par->lcdc_clk);
846 lcd_calc_clk_divider(par); 883 lcd_disable_raster();
847 lcd_enable_raster(); 884 lcd_calc_clk_divider(par);
885 lcd_enable_raster();
886 }
848 } 887 }
849 888
850 return 0; 889 return 0;
@@ -1048,6 +1087,22 @@ static struct fb_ops da8xx_fb_ops = {
1048 .fb_blank = cfb_blank, 1087 .fb_blank = cfb_blank,
1049}; 1088};
1050 1089
1090/* Calculate and return pixel clock period in pico seconds */
1091static unsigned int da8xxfb_pixel_clk_period(struct da8xx_fb_par *par)
1092{
1093 unsigned int lcd_clk, div;
1094 unsigned int configured_pix_clk;
1095 unsigned long long pix_clk_period_picosec = 1000000000000ULL;
1096
1097 lcd_clk = clk_get_rate(par->lcdc_clk);
1098 div = lcd_clk / par->pxl_clk;
1099 configured_pix_clk = (lcd_clk / div);
1100
1101 do_div(pix_clk_period_picosec, configured_pix_clk);
1102
1103 return pix_clk_period_picosec;
1104}
1105
1051static int __devinit fb_probe(struct platform_device *device) 1106static int __devinit fb_probe(struct platform_device *device)
1052{ 1107{
1053 struct da8xx_lcdc_platform_data *fb_pdata = 1108 struct da8xx_lcdc_platform_data *fb_pdata =
@@ -1137,6 +1192,9 @@ static int __devinit fb_probe(struct platform_device *device)
1137 1192
1138 par = da8xx_fb_info->par; 1193 par = da8xx_fb_info->par;
1139 par->lcdc_clk = fb_clk; 1194 par->lcdc_clk = fb_clk;
1195#ifdef CONFIG_CPU_FREQ
1196 par->lcd_fck_rate = clk_get_rate(fb_clk);
1197#endif
1140 par->pxl_clk = lcdc_info->pxl_clk; 1198 par->pxl_clk = lcdc_info->pxl_clk;
1141 if (fb_pdata->panel_power_ctrl) { 1199 if (fb_pdata->panel_power_ctrl) {
1142 par->panel_power_ctrl = fb_pdata->panel_power_ctrl; 1200 par->panel_power_ctrl = fb_pdata->panel_power_ctrl;
@@ -1209,6 +1267,11 @@ static int __devinit fb_probe(struct platform_device *device)
1209 1267
1210 da8xx_fb_var.hsync_len = lcdc_info->hsw; 1268 da8xx_fb_var.hsync_len = lcdc_info->hsw;
1211 da8xx_fb_var.vsync_len = lcdc_info->vsw; 1269 da8xx_fb_var.vsync_len = lcdc_info->vsw;
1270 da8xx_fb_var.right_margin = lcdc_info->hfp;
1271 da8xx_fb_var.left_margin = lcdc_info->hbp;
1272 da8xx_fb_var.lower_margin = lcdc_info->vfp;
1273 da8xx_fb_var.upper_margin = lcdc_info->vbp;
1274 da8xx_fb_var.pixclock = da8xxfb_pixel_clk_period(par);
1212 1275
1213 /* Initialize fbinfo */ 1276 /* Initialize fbinfo */
1214 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT; 1277 da8xx_fb_info->flags = FBINFO_FLAG_DEFAULT;
@@ -1264,8 +1327,8 @@ static int __devinit fb_probe(struct platform_device *device)
1264irq_freq: 1327irq_freq:
1265#ifdef CONFIG_CPU_FREQ 1328#ifdef CONFIG_CPU_FREQ
1266 lcd_da8xx_cpufreq_deregister(par); 1329 lcd_da8xx_cpufreq_deregister(par);
1267#endif
1268err_cpu_freq: 1330err_cpu_freq:
1331#endif
1269 unregister_framebuffer(da8xx_fb_info); 1332 unregister_framebuffer(da8xx_fb_info);
1270 1333
1271err_dealloc_cmap: 1334err_dealloc_cmap:
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
new file mode 100644
index 000000000000..1b035b2eb6b6
--- /dev/null
+++ b/drivers/video/exynos/Kconfig
@@ -0,0 +1,37 @@
1#
2# Exynos Video configuration
3#
4
5menuconfig EXYNOS_VIDEO
6 bool "Exynos Video driver support"
7 help
8 This enables support for EXYNOS Video device.
9
10if EXYNOS_VIDEO
11
12#
13# MIPI DSI driver
14#
15
16config EXYNOS_MIPI_DSI
17 bool "EXYNOS MIPI DSI driver support."
18 depends on ARCH_S5PV210 || ARCH_EXYNOS
19 help
20 This enables support for MIPI-DSI device.
21
22config EXYNOS_LCD_S6E8AX0
23 bool "S6E8AX0 MIPI AMOLED LCD Driver"
24 depends on (EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE)
25 default n
26 help
27 If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
28 LCD control driver.
29
30config EXYNOS_DP
31 bool "EXYNOS DP driver support"
32 depends on ARCH_EXYNOS
33 default n
34 help
35 This enables support for DP device.
36
37endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
new file mode 100644
index 000000000000..ec7772e452a9
--- /dev/null
+++ b/drivers/video/exynos/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for the exynos video drivers.
3#
4
5obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
6 exynos_mipi_dsi_lowlevel.o
7obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o
8obj-$(CONFIG_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
new file mode 100644
index 000000000000..2a4481cf260c
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -0,0 +1,1058 @@
1/*
2 * Samsung SoC DP (Display Port) interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/err.h>
17#include <linux/clk.h>
18#include <linux/io.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21
22#include <video/exynos_dp.h>
23
24#include <plat/cpu.h>
25
26#include "exynos_dp_core.h"
27
28static int exynos_dp_init_dp(struct exynos_dp_device *dp)
29{
30 exynos_dp_reset(dp);
31
32 /* SW defined function Normal operation */
33 exynos_dp_enable_sw_function(dp);
34
35 exynos_dp_config_interrupt(dp);
36 exynos_dp_init_analog_func(dp);
37
38 exynos_dp_init_hpd(dp);
39 exynos_dp_init_aux(dp);
40
41 return 0;
42}
43
44static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
45{
46 int timeout_loop = 0;
47
48 exynos_dp_init_hpd(dp);
49
50 udelay(200);
51
52 while (exynos_dp_get_plug_in_status(dp) != 0) {
53 timeout_loop++;
54 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
55 dev_err(dp->dev, "failed to get hpd plug status\n");
56 return -ETIMEDOUT;
57 }
58 udelay(10);
59 }
60
61 return 0;
62}
63
64static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
65{
66 int i;
67 unsigned char sum = 0;
68
69 for (i = 0; i < EDID_BLOCK_LENGTH; i++)
70 sum = sum + edid_data[i];
71
72 return sum;
73}
74
75static int exynos_dp_read_edid(struct exynos_dp_device *dp)
76{
77 unsigned char edid[EDID_BLOCK_LENGTH * 2];
78 unsigned int extend_block = 0;
79 unsigned char sum;
80 unsigned char test_vector;
81 int retval;
82
83 /*
84 * EDID device address is 0x50.
85 * However, if necessary, you must have set upper address
86 * into E-EDID in I2C device, 0x30.
87 */
88
89 /* Read Extension Flag, Number of 128-byte EDID extension blocks */
90 exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
91 EDID_EXTENSION_FLAG,
92 &extend_block);
93
94 if (extend_block > 0) {
95 dev_dbg(dp->dev, "EDID data includes a single extension!\n");
96
97 /* Read EDID data */
98 retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
99 EDID_HEADER_PATTERN,
100 EDID_BLOCK_LENGTH,
101 &edid[EDID_HEADER_PATTERN]);
102 if (retval != 0) {
103 dev_err(dp->dev, "EDID Read failed!\n");
104 return -EIO;
105 }
106 sum = exynos_dp_calc_edid_check_sum(edid);
107 if (sum != 0) {
108 dev_err(dp->dev, "EDID bad checksum!\n");
109 return -EIO;
110 }
111
112 /* Read additional EDID data */
113 retval = exynos_dp_read_bytes_from_i2c(dp,
114 I2C_EDID_DEVICE_ADDR,
115 EDID_BLOCK_LENGTH,
116 EDID_BLOCK_LENGTH,
117 &edid[EDID_BLOCK_LENGTH]);
118 if (retval != 0) {
119 dev_err(dp->dev, "EDID Read failed!\n");
120 return -EIO;
121 }
122 sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
123 if (sum != 0) {
124 dev_err(dp->dev, "EDID bad checksum!\n");
125 return -EIO;
126 }
127
128 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
129 &test_vector);
130 if (test_vector & DPCD_TEST_EDID_READ) {
131 exynos_dp_write_byte_to_dpcd(dp,
132 DPCD_ADDR_TEST_EDID_CHECKSUM,
133 edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
134 exynos_dp_write_byte_to_dpcd(dp,
135 DPCD_ADDR_TEST_RESPONSE,
136 DPCD_TEST_EDID_CHECKSUM_WRITE);
137 }
138 } else {
139 dev_info(dp->dev, "EDID data does not include any extensions.\n");
140
141 /* Read EDID data */
142 retval = exynos_dp_read_bytes_from_i2c(dp,
143 I2C_EDID_DEVICE_ADDR,
144 EDID_HEADER_PATTERN,
145 EDID_BLOCK_LENGTH,
146 &edid[EDID_HEADER_PATTERN]);
147 if (retval != 0) {
148 dev_err(dp->dev, "EDID Read failed!\n");
149 return -EIO;
150 }
151 sum = exynos_dp_calc_edid_check_sum(edid);
152 if (sum != 0) {
153 dev_err(dp->dev, "EDID bad checksum!\n");
154 return -EIO;
155 }
156
157 exynos_dp_read_byte_from_dpcd(dp,
158 DPCD_ADDR_TEST_REQUEST,
159 &test_vector);
160 if (test_vector & DPCD_TEST_EDID_READ) {
161 exynos_dp_write_byte_to_dpcd(dp,
162 DPCD_ADDR_TEST_EDID_CHECKSUM,
163 edid[EDID_CHECKSUM]);
164 exynos_dp_write_byte_to_dpcd(dp,
165 DPCD_ADDR_TEST_RESPONSE,
166 DPCD_TEST_EDID_CHECKSUM_WRITE);
167 }
168 }
169
170 dev_err(dp->dev, "EDID Read success!\n");
171 return 0;
172}
173
174static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
175{
176 u8 buf[12];
177 int i;
178 int retval;
179
180 /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
181 exynos_dp_read_bytes_from_dpcd(dp,
182 DPCD_ADDR_DPCD_REV,
183 12, buf);
184
185 /* Read EDID */
186 for (i = 0; i < 3; i++) {
187 retval = exynos_dp_read_edid(dp);
188 if (retval == 0)
189 break;
190 }
191
192 return retval;
193}
194
195static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
196 bool enable)
197{
198 u8 data;
199
200 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
201
202 if (enable)
203 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
204 DPCD_ENHANCED_FRAME_EN |
205 DPCD_LANE_COUNT_SET(data));
206 else
207 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
208 DPCD_LANE_COUNT_SET(data));
209}
210
211static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
212{
213 u8 data;
214 int retval;
215
216 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
217 retval = DPCD_ENHANCED_FRAME_CAP(data);
218
219 return retval;
220}
221
222static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
223{
224 u8 data;
225
226 data = exynos_dp_is_enhanced_mode_available(dp);
227 exynos_dp_enable_rx_to_enhanced_mode(dp, data);
228 exynos_dp_enable_enhanced_mode(dp, data);
229}
230
231static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
232{
233 exynos_dp_set_training_pattern(dp, DP_NONE);
234
235 exynos_dp_write_byte_to_dpcd(dp,
236 DPCD_ADDR_TRAINING_PATTERN_SET,
237 DPCD_TRAINING_PATTERN_DISABLED);
238}
239
240static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
241 int pre_emphasis, int lane)
242{
243 switch (lane) {
244 case 0:
245 exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
246 break;
247 case 1:
248 exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
249 break;
250
251 case 2:
252 exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
253 break;
254
255 case 3:
256 exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
257 break;
258 }
259}
260
261static void exynos_dp_link_start(struct exynos_dp_device *dp)
262{
263 u8 buf[5];
264 int lane;
265 int lane_count;
266
267 lane_count = dp->link_train.lane_count;
268
269 dp->link_train.lt_state = CLOCK_RECOVERY;
270 dp->link_train.eq_loop = 0;
271
272 for (lane = 0; lane < lane_count; lane++)
273 dp->link_train.cr_loop[lane] = 0;
274
275 /* Set sink to D0 (Sink Not Ready) mode. */
276 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
277 DPCD_SET_POWER_STATE_D0);
278
279 /* Set link rate and count as you want to establish*/
280 exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
281 exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
282
283 /* Setup RX configuration */
284 buf[0] = dp->link_train.link_rate;
285 buf[1] = dp->link_train.lane_count;
286 exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
287 2, buf);
288
289 /* Set TX pre-emphasis to minimum */
290 for (lane = 0; lane < lane_count; lane++)
291 exynos_dp_set_lane_lane_pre_emphasis(dp,
292 PRE_EMPHASIS_LEVEL_0, lane);
293
294 /* Set training pattern 1 */
295 exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
296
297 /* Set RX training pattern */
298 buf[0] = DPCD_SCRAMBLING_DISABLED |
299 DPCD_TRAINING_PATTERN_1;
300 exynos_dp_write_byte_to_dpcd(dp,
301 DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
302
303 for (lane = 0; lane < lane_count; lane++)
304 buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
305 DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
306 exynos_dp_write_bytes_to_dpcd(dp,
307 DPCD_ADDR_TRAINING_PATTERN_SET,
308 lane_count, buf);
309}
310
311static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
312{
313 int shift = (lane & 1) * 4;
314 u8 link_value = link_status[lane>>1];
315
316 return (link_value >> shift) & 0xf;
317}
318
319static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
320{
321 int lane;
322 u8 lane_status;
323
324 for (lane = 0; lane < lane_count; lane++) {
325 lane_status = exynos_dp_get_lane_status(link_status, lane);
326 if ((lane_status & DPCD_LANE_CR_DONE) == 0)
327 return -EINVAL;
328 }
329 return 0;
330}
331
332static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
333{
334 int lane;
335 u8 lane_align;
336 u8 lane_status;
337
338 lane_align = link_status[2];
339 if ((lane_align == DPCD_INTERLANE_ALIGN_DONE) == 0)
340 return -EINVAL;
341
342 for (lane = 0; lane < lane_count; lane++) {
343 lane_status = exynos_dp_get_lane_status(link_status, lane);
344 lane_status &= DPCD_CHANNEL_EQ_BITS;
345 if (lane_status != DPCD_CHANNEL_EQ_BITS)
346 return -EINVAL;
347 }
348 return 0;
349}
350
351static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
352 int lane)
353{
354 int shift = (lane & 1) * 4;
355 u8 link_value = adjust_request[lane>>1];
356
357 return (link_value >> shift) & 0x3;
358}
359
360static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
361 u8 adjust_request[2],
362 int lane)
363{
364 int shift = (lane & 1) * 4;
365 u8 link_value = adjust_request[lane>>1];
366
367 return ((link_value >> shift) & 0xc) >> 2;
368}
369
370static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
371 u8 training_lane_set, int lane)
372{
373 switch (lane) {
374 case 0:
375 exynos_dp_set_lane0_link_training(dp, training_lane_set);
376 break;
377 case 1:
378 exynos_dp_set_lane1_link_training(dp, training_lane_set);
379 break;
380
381 case 2:
382 exynos_dp_set_lane2_link_training(dp, training_lane_set);
383 break;
384
385 case 3:
386 exynos_dp_set_lane3_link_training(dp, training_lane_set);
387 break;
388 }
389}
390
391static unsigned int exynos_dp_get_lane_link_training(
392 struct exynos_dp_device *dp,
393 int lane)
394{
395 u32 reg;
396
397 switch (lane) {
398 case 0:
399 reg = exynos_dp_get_lane0_link_training(dp);
400 break;
401 case 1:
402 reg = exynos_dp_get_lane1_link_training(dp);
403 break;
404 case 2:
405 reg = exynos_dp_get_lane2_link_training(dp);
406 break;
407 case 3:
408 reg = exynos_dp_get_lane3_link_training(dp);
409 break;
410 }
411
412 return reg;
413}
414
415static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
416{
417 if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) {
418 /* set to reduced bit rate */
419 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
420 dev_err(dp->dev, "set to bandwidth %.2x\n",
421 dp->link_train.link_rate);
422 dp->link_train.lt_state = START;
423 } else {
424 exynos_dp_training_pattern_dis(dp);
425 /* set enhanced mode if available */
426 exynos_dp_set_enhanced_mode(dp);
427 dp->link_train.lt_state = FAILED;
428 }
429}
430
431static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
432 u8 adjust_request[2])
433{
434 int lane;
435 int lane_count;
436 u8 voltage_swing;
437 u8 pre_emphasis;
438 u8 training_lane;
439
440 lane_count = dp->link_train.lane_count;
441 for (lane = 0; lane < lane_count; lane++) {
442 voltage_swing = exynos_dp_get_adjust_request_voltage(
443 adjust_request, lane);
444 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
445 adjust_request, lane);
446 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
447 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
448
449 if (voltage_swing == VOLTAGE_LEVEL_3 ||
450 pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
451 training_lane |= DPCD_MAX_SWING_REACHED;
452 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
453 }
454 dp->link_train.training_lane[lane] = training_lane;
455 }
456}
457
458static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
459 u8 voltage_swing)
460{
461 int lane;
462 int lane_count;
463
464 lane_count = dp->link_train.lane_count;
465 for (lane = 0; lane < lane_count; lane++) {
466 if (voltage_swing == VOLTAGE_LEVEL_3 ||
467 dp->link_train.cr_loop[lane] == MAX_CR_LOOP)
468 return -EINVAL;
469 }
470 return 0;
471}
472
473static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
474{
475 u8 data;
476 u8 link_status[6];
477 int lane;
478 int lane_count;
479 u8 buf[5];
480
481 u8 *adjust_request;
482 u8 voltage_swing;
483 u8 pre_emphasis;
484 u8 training_lane;
485
486 udelay(100);
487
488 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
489 6, link_status);
490 lane_count = dp->link_train.lane_count;
491
492 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
493 /* set training pattern 2 for EQ */
494 exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
495
496 adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
497 - DPCD_ADDR_LANE0_1_STATUS);
498
499 exynos_dp_get_adjust_train(dp, adjust_request);
500
501 buf[0] = DPCD_SCRAMBLING_DISABLED |
502 DPCD_TRAINING_PATTERN_2;
503 exynos_dp_write_byte_to_dpcd(dp,
504 DPCD_ADDR_TRAINING_LANE0_SET,
505 buf[0]);
506
507 for (lane = 0; lane < lane_count; lane++) {
508 exynos_dp_set_lane_link_training(dp,
509 dp->link_train.training_lane[lane],
510 lane);
511 buf[lane] = dp->link_train.training_lane[lane];
512 exynos_dp_write_byte_to_dpcd(dp,
513 DPCD_ADDR_TRAINING_LANE0_SET + lane,
514 buf[lane]);
515 }
516 dp->link_train.lt_state = EQUALIZER_TRAINING;
517 } else {
518 exynos_dp_read_byte_from_dpcd(dp,
519 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
520 &data);
521 adjust_request[0] = data;
522
523 exynos_dp_read_byte_from_dpcd(dp,
524 DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
525 &data);
526 adjust_request[1] = data;
527
528 for (lane = 0; lane < lane_count; lane++) {
529 training_lane = exynos_dp_get_lane_link_training(
530 dp, lane);
531 voltage_swing = exynos_dp_get_adjust_request_voltage(
532 adjust_request, lane);
533 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
534 adjust_request, lane);
535 if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
536 (DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
537 dp->link_train.cr_loop[lane]++;
538 dp->link_train.training_lane[lane] = training_lane;
539 }
540
541 if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
542 exynos_dp_reduce_link_rate(dp);
543 } else {
544 exynos_dp_get_adjust_train(dp, adjust_request);
545
546 for (lane = 0; lane < lane_count; lane++) {
547 exynos_dp_set_lane_link_training(dp,
548 dp->link_train.training_lane[lane],
549 lane);
550 buf[lane] = dp->link_train.training_lane[lane];
551 exynos_dp_write_byte_to_dpcd(dp,
552 DPCD_ADDR_TRAINING_LANE0_SET + lane,
553 buf[lane]);
554 }
555 }
556 }
557
558 return 0;
559}
560
561static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
562{
563 u8 link_status[6];
564 int lane;
565 int lane_count;
566 u8 buf[5];
567 u32 reg;
568
569 u8 *adjust_request;
570
571 udelay(400);
572
573 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
574 6, link_status);
575 lane_count = dp->link_train.lane_count;
576
577 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
578 adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
579 - DPCD_ADDR_LANE0_1_STATUS);
580
581 if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) {
582 /* traing pattern Set to Normal */
583 exynos_dp_training_pattern_dis(dp);
584
585 dev_info(dp->dev, "Link Training success!\n");
586
587 exynos_dp_get_link_bandwidth(dp, &reg);
588 dp->link_train.link_rate = reg;
589 dev_dbg(dp->dev, "final bandwidth = %.2x\n",
590 dp->link_train.link_rate);
591
592 exynos_dp_get_lane_count(dp, &reg);
593 dp->link_train.lane_count = reg;
594 dev_dbg(dp->dev, "final lane count = %.2x\n",
595 dp->link_train.lane_count);
596 /* set enhanced mode if available */
597 exynos_dp_set_enhanced_mode(dp);
598
599 dp->link_train.lt_state = FINISHED;
600 } else {
601 /* not all locked */
602 dp->link_train.eq_loop++;
603
604 if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
605 exynos_dp_reduce_link_rate(dp);
606 } else {
607 exynos_dp_get_adjust_train(dp, adjust_request);
608
609 for (lane = 0; lane < lane_count; lane++) {
610 exynos_dp_set_lane_link_training(dp,
611 dp->link_train.training_lane[lane],
612 lane);
613 buf[lane] = dp->link_train.training_lane[lane];
614 exynos_dp_write_byte_to_dpcd(dp,
615 DPCD_ADDR_TRAINING_LANE0_SET + lane,
616 buf[lane]);
617 }
618 }
619 }
620 } else {
621 exynos_dp_reduce_link_rate(dp);
622 }
623
624 return 0;
625}
626
627static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
628 u8 *bandwidth)
629{
630 u8 data;
631
632 /*
633 * For DP rev.1.1, Maximum link rate of Main Link lanes
634 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
635 */
636 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
637 *bandwidth = data;
638}
639
640static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
641 u8 *lane_count)
642{
643 u8 data;
644
645 /*
646 * For DP rev.1.1, Maximum number of Main Link lanes
647 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
648 */
649 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
650 *lane_count = DPCD_MAX_LANE_COUNT(data);
651}
652
653static void exynos_dp_init_training(struct exynos_dp_device *dp,
654 enum link_lane_count_type max_lane,
655 enum link_rate_type max_rate)
656{
657 /*
658 * MACRO_RST must be applied after the PLL_LOCK to avoid
659 * the DP inter pair skew issue for at least 10 us
660 */
661 exynos_dp_reset_macro(dp);
662
663 /* Initialize by reading RX's DPCD */
664 exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
665 exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
666
667 if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
668 (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
669 dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
670 dp->link_train.link_rate);
671 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
672 }
673
674 if (dp->link_train.lane_count == 0) {
675 dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
676 dp->link_train.lane_count);
677 dp->link_train.lane_count = (u8)LANE_COUNT1;
678 }
679
680 /* Setup TX lane count & rate */
681 if (dp->link_train.lane_count > max_lane)
682 dp->link_train.lane_count = max_lane;
683 if (dp->link_train.link_rate > max_rate)
684 dp->link_train.link_rate = max_rate;
685
686 /* All DP analog module power up */
687 exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
688}
689
690static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
691{
692 int retval = 0;
693 int training_finished;
694
695 /* Turn off unnecessary lane */
696 if (dp->link_train.lane_count == 1)
697 exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
698
699 training_finished = 0;
700
701 dp->link_train.lt_state = START;
702
703 /* Process here */
704 while (!training_finished) {
705 switch (dp->link_train.lt_state) {
706 case START:
707 exynos_dp_link_start(dp);
708 break;
709 case CLOCK_RECOVERY:
710 exynos_dp_process_clock_recovery(dp);
711 break;
712 case EQUALIZER_TRAINING:
713 exynos_dp_process_equalizer_training(dp);
714 break;
715 case FINISHED:
716 training_finished = 1;
717 break;
718 case FAILED:
719 return -EREMOTEIO;
720 }
721 }
722
723 return retval;
724}
725
726static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
727 u32 count,
728 u32 bwtype)
729{
730 int i;
731 int retval;
732
733 for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
734 exynos_dp_init_training(dp, count, bwtype);
735 retval = exynos_dp_sw_link_training(dp);
736 if (retval == 0)
737 break;
738
739 udelay(100);
740 }
741
742 return retval;
743}
744
745static int exynos_dp_config_video(struct exynos_dp_device *dp,
746 struct video_info *video_info)
747{
748 int retval = 0;
749 int timeout_loop = 0;
750 int done_count = 0;
751
752 exynos_dp_config_video_slave_mode(dp, video_info);
753
754 exynos_dp_set_video_color_format(dp, video_info->color_depth,
755 video_info->color_space,
756 video_info->dynamic_range,
757 video_info->ycbcr_coeff);
758
759 if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
760 dev_err(dp->dev, "PLL is not locked yet.\n");
761 return -EINVAL;
762 }
763
764 for (;;) {
765 timeout_loop++;
766 if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
767 break;
768 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
769 dev_err(dp->dev, "Timeout of video streamclk ok\n");
770 return -ETIMEDOUT;
771 }
772
773 mdelay(100);
774 }
775
776 /* Set to use the register calculated M/N video */
777 exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
778
779 /* For video bist, Video timing must be generated by register */
780 exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
781
782 /* Disable video mute */
783 exynos_dp_enable_video_mute(dp, 0);
784
785 /* Configure video slave mode */
786 exynos_dp_enable_video_master(dp, 0);
787
788 /* Enable video */
789 exynos_dp_start_video(dp);
790
791 timeout_loop = 0;
792
793 for (;;) {
794 timeout_loop++;
795 if (exynos_dp_is_video_stream_on(dp) == 0) {
796 done_count++;
797 if (done_count > 10)
798 break;
799 } else if (done_count) {
800 done_count = 0;
801 }
802 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
803 dev_err(dp->dev, "Timeout of video streamclk ok\n");
804 return -ETIMEDOUT;
805 }
806
807 mdelay(100);
808 }
809
810 if (retval != 0)
811 dev_err(dp->dev, "Video stream is not detected!\n");
812
813 return retval;
814}
815
816static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
817{
818 u8 data;
819
820 if (enable) {
821 exynos_dp_enable_scrambling(dp);
822
823 exynos_dp_read_byte_from_dpcd(dp,
824 DPCD_ADDR_TRAINING_PATTERN_SET,
825 &data);
826 exynos_dp_write_byte_to_dpcd(dp,
827 DPCD_ADDR_TRAINING_PATTERN_SET,
828 (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
829 } else {
830 exynos_dp_disable_scrambling(dp);
831
832 exynos_dp_read_byte_from_dpcd(dp,
833 DPCD_ADDR_TRAINING_PATTERN_SET,
834 &data);
835 exynos_dp_write_byte_to_dpcd(dp,
836 DPCD_ADDR_TRAINING_PATTERN_SET,
837 (u8)(data | DPCD_SCRAMBLING_DISABLED));
838 }
839}
840
841static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
842{
843 struct exynos_dp_device *dp = arg;
844
845 dev_err(dp->dev, "exynos_dp_irq_handler\n");
846 return IRQ_HANDLED;
847}
848
849static int __devinit exynos_dp_probe(struct platform_device *pdev)
850{
851 struct resource *res;
852 struct exynos_dp_device *dp;
853 struct exynos_dp_platdata *pdata;
854
855 int ret = 0;
856
857 pdata = pdev->dev.platform_data;
858 if (!pdata) {
859 dev_err(&pdev->dev, "no platform data\n");
860 return -EINVAL;
861 }
862
863 dp = kzalloc(sizeof(struct exynos_dp_device), GFP_KERNEL);
864 if (!dp) {
865 dev_err(&pdev->dev, "no memory for device data\n");
866 return -ENOMEM;
867 }
868
869 dp->dev = &pdev->dev;
870
871 dp->clock = clk_get(&pdev->dev, "dp");
872 if (IS_ERR(dp->clock)) {
873 dev_err(&pdev->dev, "failed to get clock\n");
874 ret = PTR_ERR(dp->clock);
875 goto err_dp;
876 }
877
878 clk_enable(dp->clock);
879
880 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
881 if (!res) {
882 dev_err(&pdev->dev, "failed to get registers\n");
883 ret = -EINVAL;
884 goto err_clock;
885 }
886
887 res = request_mem_region(res->start, resource_size(res),
888 dev_name(&pdev->dev));
889 if (!res) {
890 dev_err(&pdev->dev, "failed to request registers region\n");
891 ret = -EINVAL;
892 goto err_clock;
893 }
894
895 dp->res = res;
896
897 dp->reg_base = ioremap(res->start, resource_size(res));
898 if (!dp->reg_base) {
899 dev_err(&pdev->dev, "failed to ioremap\n");
900 ret = -ENOMEM;
901 goto err_req_region;
902 }
903
904 dp->irq = platform_get_irq(pdev, 0);
905 if (!dp->irq) {
906 dev_err(&pdev->dev, "failed to get irq\n");
907 ret = -ENODEV;
908 goto err_ioremap;
909 }
910
911 ret = request_irq(dp->irq, exynos_dp_irq_handler, 0,
912 "exynos-dp", dp);
913 if (ret) {
914 dev_err(&pdev->dev, "failed to request irq\n");
915 goto err_ioremap;
916 }
917
918 dp->video_info = pdata->video_info;
919 if (pdata->phy_init)
920 pdata->phy_init();
921
922 exynos_dp_init_dp(dp);
923
924 ret = exynos_dp_detect_hpd(dp);
925 if (ret) {
926 dev_err(&pdev->dev, "unable to detect hpd\n");
927 goto err_irq;
928 }
929
930 exynos_dp_handle_edid(dp);
931
932 ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
933 dp->video_info->link_rate);
934 if (ret) {
935 dev_err(&pdev->dev, "unable to do link train\n");
936 goto err_irq;
937 }
938
939 exynos_dp_enable_scramble(dp, 1);
940 exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
941 exynos_dp_enable_enhanced_mode(dp, 1);
942
943 exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
944 exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
945
946 exynos_dp_init_video(dp);
947 ret = exynos_dp_config_video(dp, dp->video_info);
948 if (ret) {
949 dev_err(&pdev->dev, "unable to config video\n");
950 goto err_irq;
951 }
952
953 platform_set_drvdata(pdev, dp);
954
955 return 0;
956
957err_irq:
958 free_irq(dp->irq, dp);
959err_ioremap:
960 iounmap(dp->reg_base);
961err_req_region:
962 release_mem_region(res->start, resource_size(res));
963err_clock:
964 clk_put(dp->clock);
965err_dp:
966 kfree(dp);
967
968 return ret;
969}
970
971static int __devexit exynos_dp_remove(struct platform_device *pdev)
972{
973 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
974 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
975
976 if (pdata && pdata->phy_exit)
977 pdata->phy_exit();
978
979 free_irq(dp->irq, dp);
980 iounmap(dp->reg_base);
981
982 clk_disable(dp->clock);
983 clk_put(dp->clock);
984
985 release_mem_region(dp->res->start, resource_size(dp->res));
986
987 kfree(dp);
988
989 return 0;
990}
991
992#ifdef CONFIG_PM_SLEEP
993static int exynos_dp_suspend(struct device *dev)
994{
995 struct platform_device *pdev = to_platform_device(dev);
996 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
997 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
998
999 if (pdata && pdata->phy_exit)
1000 pdata->phy_exit();
1001
1002 clk_disable(dp->clock);
1003
1004 return 0;
1005}
1006
1007static int exynos_dp_resume(struct device *dev)
1008{
1009 struct platform_device *pdev = to_platform_device(dev);
1010 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
1011 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
1012
1013 if (pdata && pdata->phy_init)
1014 pdata->phy_init();
1015
1016 clk_enable(dp->clock);
1017
1018 exynos_dp_init_dp(dp);
1019
1020 exynos_dp_detect_hpd(dp);
1021 exynos_dp_handle_edid(dp);
1022
1023 exynos_dp_set_link_train(dp, dp->video_info->lane_count,
1024 dp->video_info->link_rate);
1025
1026 exynos_dp_enable_scramble(dp, 1);
1027 exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
1028 exynos_dp_enable_enhanced_mode(dp, 1);
1029
1030 exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
1031 exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
1032
1033 exynos_dp_init_video(dp);
1034 exynos_dp_config_video(dp, dp->video_info);
1035
1036 return 0;
1037}
1038#endif
1039
1040static const struct dev_pm_ops exynos_dp_pm_ops = {
1041 SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
1042};
1043
1044static struct platform_driver exynos_dp_driver = {
1045 .probe = exynos_dp_probe,
1046 .remove = __devexit_p(exynos_dp_remove),
1047 .driver = {
1048 .name = "exynos-dp",
1049 .owner = THIS_MODULE,
1050 .pm = &exynos_dp_pm_ops,
1051 },
1052};
1053
1054module_platform_driver(exynos_dp_driver);
1055
1056MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
1057MODULE_DESCRIPTION("Samsung SoC DP Driver");
1058MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
new file mode 100644
index 000000000000..90ceaca0fa24
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -0,0 +1,206 @@
1/*
2 * Header file for Samsung DP (Display Port) interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef _EXYNOS_DP_CORE_H
14#define _EXYNOS_DP_CORE_H
15
16struct link_train {
17 int eq_loop;
18 int cr_loop[4];
19
20 u8 link_rate;
21 u8 lane_count;
22 u8 training_lane[4];
23
24 enum link_training_state lt_state;
25};
26
27struct exynos_dp_device {
28 struct device *dev;
29 struct resource *res;
30 struct clk *clock;
31 unsigned int irq;
32 void __iomem *reg_base;
33
34 struct video_info *video_info;
35 struct link_train link_train;
36};
37
38/* exynos_dp_reg.c */
39void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
40void exynos_dp_stop_video(struct exynos_dp_device *dp);
41void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
42void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
43void exynos_dp_reset(struct exynos_dp_device *dp);
44void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
45u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
46void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
47void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
48 enum analog_power_block block,
49 bool enable);
50void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
51void exynos_dp_init_hpd(struct exynos_dp_device *dp);
52void exynos_dp_reset_aux(struct exynos_dp_device *dp);
53void exynos_dp_init_aux(struct exynos_dp_device *dp);
54int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
55void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
56int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
57int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
58 unsigned int reg_addr,
59 unsigned char data);
60int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
61 unsigned int reg_addr,
62 unsigned char *data);
63int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
64 unsigned int reg_addr,
65 unsigned int count,
66 unsigned char data[]);
67int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
68 unsigned int reg_addr,
69 unsigned int count,
70 unsigned char data[]);
71int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
72 unsigned int device_addr,
73 unsigned int reg_addr);
74int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
75 unsigned int device_addr,
76 unsigned int reg_addr,
77 unsigned int *data);
78int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
79 unsigned int device_addr,
80 unsigned int reg_addr,
81 unsigned int count,
82 unsigned char edid[]);
83void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
84void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
85void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
86void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
87void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
88void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
89void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
90void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
91void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
92void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
93 enum pattern_set pattern);
94void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
95void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
96void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
97void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
98void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
99 u32 training_lane);
100void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
101 u32 training_lane);
102void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
103 u32 training_lane);
104void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
105 u32 training_lane);
106u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
107u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
108u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
109u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
110void exynos_dp_reset_macro(struct exynos_dp_device *dp);
111int exynos_dp_init_video(struct exynos_dp_device *dp);
112
113void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
114 u32 color_depth,
115 u32 color_space,
116 u32 dynamic_range,
117 u32 ycbcr_coeff);
118int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
119void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
120 enum clock_recovery_m_value_type type,
121 u32 m_value,
122 u32 n_value);
123void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
124void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
125void exynos_dp_start_video(struct exynos_dp_device *dp);
126int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
127void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
128 struct video_info *video_info);
129void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
130void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
131
132/* I2C EDID Chip ID, Slave Address */
133#define I2C_EDID_DEVICE_ADDR 0x50
134#define I2C_E_EDID_DEVICE_ADDR 0x30
135
136#define EDID_BLOCK_LENGTH 0x80
137#define EDID_HEADER_PATTERN 0x00
138#define EDID_EXTENSION_FLAG 0x7e
139#define EDID_CHECKSUM 0x7f
140
141/* Definition for DPCD Register */
142#define DPCD_ADDR_DPCD_REV 0x0000
143#define DPCD_ADDR_MAX_LINK_RATE 0x0001
144#define DPCD_ADDR_MAX_LANE_COUNT 0x0002
145#define DPCD_ADDR_LINK_BW_SET 0x0100
146#define DPCD_ADDR_LANE_COUNT_SET 0x0101
147#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
148#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
149#define DPCD_ADDR_LANE0_1_STATUS 0x0202
150#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
151#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
152#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
153#define DPCD_ADDR_TEST_REQUEST 0x0218
154#define DPCD_ADDR_TEST_RESPONSE 0x0260
155#define DPCD_ADDR_TEST_EDID_CHECKSUM 0x0261
156#define DPCD_ADDR_SINK_POWER_STATE 0x0600
157
158/* DPCD_ADDR_MAX_LANE_COUNT */
159#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
160#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
161
162/* DPCD_ADDR_LANE_COUNT_SET */
163#define DPCD_ENHANCED_FRAME_EN (0x1 << 7)
164#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
165
166/* DPCD_ADDR_TRAINING_PATTERN_SET */
167#define DPCD_SCRAMBLING_DISABLED (0x1 << 5)
168#define DPCD_SCRAMBLING_ENABLED (0x0 << 5)
169#define DPCD_TRAINING_PATTERN_2 (0x2 << 0)
170#define DPCD_TRAINING_PATTERN_1 (0x1 << 0)
171#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0)
172
173/* DPCD_ADDR_TRAINING_LANE0_SET */
174#define DPCD_MAX_PRE_EMPHASIS_REACHED (0x1 << 5)
175#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
176#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
177#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 (0x0 << 3)
178#define DPCD_MAX_SWING_REACHED (0x1 << 2)
179#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
180#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
181#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0 (0x0 << 0)
182
183/* DPCD_ADDR_LANE0_1_STATUS */
184#define DPCD_LANE_SYMBOL_LOCKED (0x1 << 2)
185#define DPCD_LANE_CHANNEL_EQ_DONE (0x1 << 1)
186#define DPCD_LANE_CR_DONE (0x1 << 0)
187#define DPCD_CHANNEL_EQ_BITS (DPCD_LANE_CR_DONE| \
188 DPCD_LANE_CHANNEL_EQ_DONE|\
189 DPCD_LANE_SYMBOL_LOCKED)
190
191/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
192#define DPCD_LINK_STATUS_UPDATED (0x1 << 7)
193#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6)
194#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0)
195
196/* DPCD_ADDR_TEST_REQUEST */
197#define DPCD_TEST_EDID_READ (0x1 << 2)
198
199/* DPCD_ADDR_TEST_RESPONSE */
200#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2)
201
202/* DPCD_ADDR_SINK_POWER_STATE */
203#define DPCD_SET_POWER_STATE_D0 (0x1 << 0)
204#define DPCD_SET_POWER_STATE_D4 (0x2 << 0)
205
206#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
new file mode 100644
index 000000000000..6548afa0e3d2
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -0,0 +1,1173 @@
1/*
2 * Samsung DP (Display port) register interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/device.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16
17#include <video/exynos_dp.h>
18
19#include <plat/cpu.h>
20
21#include "exynos_dp_core.h"
22#include "exynos_dp_reg.h"
23
24#define COMMON_INT_MASK_1 (0)
25#define COMMON_INT_MASK_2 (0)
26#define COMMON_INT_MASK_3 (0)
27#define COMMON_INT_MASK_4 (0)
28#define INT_STA_MASK (0)
29
30void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
31{
32 u32 reg;
33
34 if (enable) {
35 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
36 reg |= HDCP_VIDEO_MUTE;
37 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
38 } else {
39 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
40 reg &= ~HDCP_VIDEO_MUTE;
41 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
42 }
43}
44
45void exynos_dp_stop_video(struct exynos_dp_device *dp)
46{
47 u32 reg;
48
49 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
50 reg &= ~VIDEO_EN;
51 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
52}
53
54void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
55{
56 u32 reg;
57
58 if (enable)
59 reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
60 LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
61 else
62 reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
63 LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
64
65 writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
66}
67
68void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
69{
70 /* Set interrupt pin assertion polarity as high */
71 writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
72
73 /* Clear pending regisers */
74 writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
75 writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
76 writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
77 writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
78 writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
79
80 /* 0:mask,1: unmask */
81 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
82 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
83 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
84 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
85 writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
86}
87
88void exynos_dp_reset(struct exynos_dp_device *dp)
89{
90 u32 reg;
91
92 writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
93
94 exynos_dp_stop_video(dp);
95 exynos_dp_enable_video_mute(dp, 0);
96
97 reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
98 AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
99 HDCP_FUNC_EN_N | SW_FUNC_EN_N;
100 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
101
102 reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
103 SERDES_FIFO_FUNC_EN_N |
104 LS_CLK_DOMAIN_FUNC_EN_N;
105 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
106
107 udelay(20);
108
109 exynos_dp_lane_swap(dp, 0);
110
111 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
112 writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
113 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
114 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
115
116 writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
117 writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
118
119 writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
120 writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
121
122 writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
123
124 writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
125
126 writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
127 writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
128
129 writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
130 writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
131
132 writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
133
134 exynos_dp_init_interrupt(dp);
135}
136
137void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
138{
139 u32 reg;
140
141 /* 0: mask, 1: unmask */
142 reg = COMMON_INT_MASK_1;
143 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
144
145 reg = COMMON_INT_MASK_2;
146 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
147
148 reg = COMMON_INT_MASK_3;
149 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
150
151 reg = COMMON_INT_MASK_4;
152 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
153
154 reg = INT_STA_MASK;
155 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
156}
157
158u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
159{
160 u32 reg;
161
162 reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
163 if (reg & PLL_LOCK)
164 return PLL_LOCKED;
165 else
166 return PLL_UNLOCKED;
167}
168
169void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
170{
171 u32 reg;
172
173 if (enable) {
174 reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
175 reg |= DP_PLL_PD;
176 writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
177 } else {
178 reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
179 reg &= ~DP_PLL_PD;
180 writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
181 }
182}
183
184void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
185 enum analog_power_block block,
186 bool enable)
187{
188 u32 reg;
189
190 switch (block) {
191 case AUX_BLOCK:
192 if (enable) {
193 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
194 reg |= AUX_PD;
195 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
196 } else {
197 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
198 reg &= ~AUX_PD;
199 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
200 }
201 break;
202 case CH0_BLOCK:
203 if (enable) {
204 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
205 reg |= CH0_PD;
206 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
207 } else {
208 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
209 reg &= ~CH0_PD;
210 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
211 }
212 break;
213 case CH1_BLOCK:
214 if (enable) {
215 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
216 reg |= CH1_PD;
217 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
218 } else {
219 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
220 reg &= ~CH1_PD;
221 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
222 }
223 break;
224 case CH2_BLOCK:
225 if (enable) {
226 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
227 reg |= CH2_PD;
228 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
229 } else {
230 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
231 reg &= ~CH2_PD;
232 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
233 }
234 break;
235 case CH3_BLOCK:
236 if (enable) {
237 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
238 reg |= CH3_PD;
239 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
240 } else {
241 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
242 reg &= ~CH3_PD;
243 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
244 }
245 break;
246 case ANALOG_TOTAL:
247 if (enable) {
248 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
249 reg |= DP_PHY_PD;
250 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
251 } else {
252 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
253 reg &= ~DP_PHY_PD;
254 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
255 }
256 break;
257 case POWER_ALL:
258 if (enable) {
259 reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
260 CH1_PD | CH0_PD;
261 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
262 } else {
263 writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
264 }
265 break;
266 default:
267 break;
268 }
269}
270
271void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
272{
273 u32 reg;
274
275 exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
276
277 reg = PLL_LOCK_CHG;
278 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
279
280 reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
281 reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
282 writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
283
284 /* Power up PLL */
285 if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED)
286 exynos_dp_set_pll_power_down(dp, 0);
287
288 /* Enable Serdes FIFO function and Link symbol clock domain module */
289 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
290 reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
291 | AUX_FUNC_EN_N);
292 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
293}
294
295void exynos_dp_init_hpd(struct exynos_dp_device *dp)
296{
297 u32 reg;
298
299 reg = HOTPLUG_CHG | HPD_LOST | PLUG;
300 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
301
302 reg = INT_HPD;
303 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
304
305 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
306 reg &= ~(F_HPD | HPD_CTRL);
307 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
308}
309
310void exynos_dp_reset_aux(struct exynos_dp_device *dp)
311{
312 u32 reg;
313
314 /* Disable AUX channel module */
315 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
316 reg |= AUX_FUNC_EN_N;
317 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
318}
319
320void exynos_dp_init_aux(struct exynos_dp_device *dp)
321{
322 u32 reg;
323
324 /* Clear inerrupts related to AUX channel */
325 reg = RPLY_RECEIV | AUX_ERR;
326 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
327
328 exynos_dp_reset_aux(dp);
329
330 /* Disable AUX transaction H/W retry */
331 reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
332 AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
333 writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
334
335 /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
336 reg = DEFER_CTRL_EN | DEFER_COUNT(1);
337 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
338
339 /* Enable AUX channel module */
340 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
341 reg &= ~AUX_FUNC_EN_N;
342 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
343}
344
345int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
346{
347 u32 reg;
348
349 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
350 if (reg & HPD_STATUS)
351 return 0;
352
353 return -EINVAL;
354}
355
356void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
357{
358 u32 reg;
359
360 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
361 reg &= ~SW_FUNC_EN_N;
362 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
363}
364
365int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
366{
367 int reg;
368 int retval = 0;
369
370 /* Enable AUX CH operation */
371 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
372 reg |= AUX_EN;
373 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
374
375 /* Is AUX CH command reply received? */
376 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
377 while (!(reg & RPLY_RECEIV))
378 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
379
380 /* Clear interrupt source for AUX CH command reply */
381 writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
382
383 /* Clear interrupt source for AUX CH access error */
384 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
385 if (reg & AUX_ERR) {
386 writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
387 return -EREMOTEIO;
388 }
389
390 /* Check AUX CH error access status */
391 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
392 if ((reg & AUX_STATUS_MASK) != 0) {
393 dev_err(dp->dev, "AUX CH error happens: %d\n\n",
394 reg & AUX_STATUS_MASK);
395 return -EREMOTEIO;
396 }
397
398 return retval;
399}
400
401int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
402 unsigned int reg_addr,
403 unsigned char data)
404{
405 u32 reg;
406 int i;
407 int retval;
408
409 for (i = 0; i < 3; i++) {
410 /* Clear AUX CH data buffer */
411 reg = BUF_CLR;
412 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
413
414 /* Select DPCD device address */
415 reg = AUX_ADDR_7_0(reg_addr);
416 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
417 reg = AUX_ADDR_15_8(reg_addr);
418 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
419 reg = AUX_ADDR_19_16(reg_addr);
420 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
421
422 /* Write data buffer */
423 reg = (unsigned int)data;
424 writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
425
426 /*
427 * Set DisplayPort transaction and write 1 byte
428 * If bit 3 is 1, DisplayPort transaction.
429 * If Bit 3 is 0, I2C transaction.
430 */
431 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
432 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
433
434 /* Start AUX transaction */
435 retval = exynos_dp_start_aux_transaction(dp);
436 if (retval == 0)
437 break;
438 else
439 dev_err(dp->dev, "Aux Transaction fail!\n");
440 }
441
442 return retval;
443}
444
445int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
446 unsigned int reg_addr,
447 unsigned char *data)
448{
449 u32 reg;
450 int i;
451 int retval;
452
453 for (i = 0; i < 10; i++) {
454 /* Clear AUX CH data buffer */
455 reg = BUF_CLR;
456 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
457
458 /* Select DPCD device address */
459 reg = AUX_ADDR_7_0(reg_addr);
460 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
461 reg = AUX_ADDR_15_8(reg_addr);
462 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
463 reg = AUX_ADDR_19_16(reg_addr);
464 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
465
466 /*
467 * Set DisplayPort transaction and read 1 byte
468 * If bit 3 is 1, DisplayPort transaction.
469 * If Bit 3 is 0, I2C transaction.
470 */
471 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
472 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
473
474 /* Start AUX transaction */
475 retval = exynos_dp_start_aux_transaction(dp);
476 if (retval == 0)
477 break;
478 else
479 dev_err(dp->dev, "Aux Transaction fail!\n");
480 }
481
482 /* Read data buffer */
483 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
484 *data = (unsigned char)(reg & 0xff);
485
486 return retval;
487}
488
489int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
490 unsigned int reg_addr,
491 unsigned int count,
492 unsigned char data[])
493{
494 u32 reg;
495 unsigned int start_offset;
496 unsigned int cur_data_count;
497 unsigned int cur_data_idx;
498 int i;
499 int retval = 0;
500
501 /* Clear AUX CH data buffer */
502 reg = BUF_CLR;
503 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
504
505 start_offset = 0;
506 while (start_offset < count) {
507 /* Buffer size of AUX CH is 16 * 4bytes */
508 if ((count - start_offset) > 16)
509 cur_data_count = 16;
510 else
511 cur_data_count = count - start_offset;
512
513 for (i = 0; i < 10; i++) {
514 /* Select DPCD device address */
515 reg = AUX_ADDR_7_0(reg_addr + start_offset);
516 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
517 reg = AUX_ADDR_15_8(reg_addr + start_offset);
518 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
519 reg = AUX_ADDR_19_16(reg_addr + start_offset);
520 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
521
522 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
523 cur_data_idx++) {
524 reg = data[start_offset + cur_data_idx];
525 writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
526 + 4 * cur_data_idx);
527 }
528
529 /*
530 * Set DisplayPort transaction and write
531 * If bit 3 is 1, DisplayPort transaction.
532 * If Bit 3 is 0, I2C transaction.
533 */
534 reg = AUX_LENGTH(cur_data_count) |
535 AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
536 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
537
538 /* Start AUX transaction */
539 retval = exynos_dp_start_aux_transaction(dp);
540 if (retval == 0)
541 break;
542 else
543 dev_err(dp->dev, "Aux Transaction fail!\n");
544 }
545
546 start_offset += cur_data_count;
547 }
548
549 return retval;
550}
551
552int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
553 unsigned int reg_addr,
554 unsigned int count,
555 unsigned char data[])
556{
557 u32 reg;
558 unsigned int start_offset;
559 unsigned int cur_data_count;
560 unsigned int cur_data_idx;
561 int i;
562 int retval = 0;
563
564 /* Clear AUX CH data buffer */
565 reg = BUF_CLR;
566 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
567
568 start_offset = 0;
569 while (start_offset < count) {
570 /* Buffer size of AUX CH is 16 * 4bytes */
571 if ((count - start_offset) > 16)
572 cur_data_count = 16;
573 else
574 cur_data_count = count - start_offset;
575
576 /* AUX CH Request Transaction process */
577 for (i = 0; i < 10; i++) {
578 /* Select DPCD device address */
579 reg = AUX_ADDR_7_0(reg_addr + start_offset);
580 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
581 reg = AUX_ADDR_15_8(reg_addr + start_offset);
582 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
583 reg = AUX_ADDR_19_16(reg_addr + start_offset);
584 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
585
586 /*
587 * Set DisplayPort transaction and read
588 * If bit 3 is 1, DisplayPort transaction.
589 * If Bit 3 is 0, I2C transaction.
590 */
591 reg = AUX_LENGTH(cur_data_count) |
592 AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
593 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
594
595 /* Start AUX transaction */
596 retval = exynos_dp_start_aux_transaction(dp);
597 if (retval == 0)
598 break;
599 else
600 dev_err(dp->dev, "Aux Transaction fail!\n");
601 }
602
603 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
604 cur_data_idx++) {
605 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
606 + 4 * cur_data_idx);
607 data[start_offset + cur_data_idx] =
608 (unsigned char)reg;
609 }
610
611 start_offset += cur_data_count;
612 }
613
614 return retval;
615}
616
617int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
618 unsigned int device_addr,
619 unsigned int reg_addr)
620{
621 u32 reg;
622 int retval;
623
624 /* Set EDID device address */
625 reg = device_addr;
626 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
627 writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
628 writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
629
630 /* Set offset from base address of EDID device */
631 writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
632
633 /*
634 * Set I2C transaction and write address
635 * If bit 3 is 1, DisplayPort transaction.
636 * If Bit 3 is 0, I2C transaction.
637 */
638 reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
639 AUX_TX_COMM_WRITE;
640 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
641
642 /* Start AUX transaction */
643 retval = exynos_dp_start_aux_transaction(dp);
644 if (retval != 0)
645 dev_err(dp->dev, "Aux Transaction fail!\n");
646
647 return retval;
648}
649
650int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
651 unsigned int device_addr,
652 unsigned int reg_addr,
653 unsigned int *data)
654{
655 u32 reg;
656 int i;
657 int retval;
658
659 for (i = 0; i < 10; i++) {
660 /* Clear AUX CH data buffer */
661 reg = BUF_CLR;
662 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
663
664 /* Select EDID device */
665 retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
666 if (retval != 0) {
667 dev_err(dp->dev, "Select EDID device fail!\n");
668 continue;
669 }
670
671 /*
672 * Set I2C transaction and read data
673 * If bit 3 is 1, DisplayPort transaction.
674 * If Bit 3 is 0, I2C transaction.
675 */
676 reg = AUX_TX_COMM_I2C_TRANSACTION |
677 AUX_TX_COMM_READ;
678 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
679
680 /* Start AUX transaction */
681 retval = exynos_dp_start_aux_transaction(dp);
682 if (retval == 0)
683 break;
684 else
685 dev_err(dp->dev, "Aux Transaction fail!\n");
686 }
687
688 /* Read data */
689 if (retval == 0)
690 *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
691
692 return retval;
693}
694
695int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
696 unsigned int device_addr,
697 unsigned int reg_addr,
698 unsigned int count,
699 unsigned char edid[])
700{
701 u32 reg;
702 unsigned int i, j;
703 unsigned int cur_data_idx;
704 unsigned int defer = 0;
705 int retval = 0;
706
707 for (i = 0; i < count; i += 16) {
708 for (j = 0; j < 100; j++) {
709 /* Clear AUX CH data buffer */
710 reg = BUF_CLR;
711 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
712
713 /* Set normal AUX CH command */
714 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
715 reg &= ~ADDR_ONLY;
716 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
717
718 /*
719 * If Rx sends defer, Tx sends only reads
720 * request without sending addres
721 */
722 if (!defer)
723 retval = exynos_dp_select_i2c_device(dp,
724 device_addr, reg_addr + i);
725 else
726 defer = 0;
727
728 if (retval == 0) {
729 /*
730 * Set I2C transaction and write data
731 * If bit 3 is 1, DisplayPort transaction.
732 * If Bit 3 is 0, I2C transaction.
733 */
734 reg = AUX_LENGTH(16) |
735 AUX_TX_COMM_I2C_TRANSACTION |
736 AUX_TX_COMM_READ;
737 writel(reg, dp->reg_base +
738 EXYNOS_DP_AUX_CH_CTL_1);
739
740 /* Start AUX transaction */
741 retval = exynos_dp_start_aux_transaction(dp);
742 if (retval == 0)
743 break;
744 else
745 dev_err(dp->dev, "Aux Transaction fail!\n");
746 }
747 /* Check if Rx sends defer */
748 reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
749 if (reg == AUX_RX_COMM_AUX_DEFER ||
750 reg == AUX_RX_COMM_I2C_DEFER) {
751 dev_err(dp->dev, "Defer: %d\n\n", reg);
752 defer = 1;
753 }
754 }
755
756 for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
757 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
758 + 4 * cur_data_idx);
759 edid[i + cur_data_idx] = (unsigned char)reg;
760 }
761 }
762
763 return retval;
764}
765
766void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
767{
768 u32 reg;
769
770 reg = bwtype;
771 if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
772 writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
773}
774
775void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
776{
777 u32 reg;
778
779 reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
780 *bwtype = reg;
781}
782
783void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
784{
785 u32 reg;
786
787 reg = count;
788 writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
789}
790
791void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
792{
793 u32 reg;
794
795 reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
796 *count = reg;
797}
798
799void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
800{
801 u32 reg;
802
803 if (enable) {
804 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
805 reg |= ENHANCED;
806 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
807 } else {
808 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
809 reg &= ~ENHANCED;
810 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
811 }
812}
813
814void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
815 enum pattern_set pattern)
816{
817 u32 reg;
818
819 switch (pattern) {
820 case PRBS7:
821 reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
822 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
823 break;
824 case D10_2:
825 reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
826 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
827 break;
828 case TRAINING_PTN1:
829 reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
830 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
831 break;
832 case TRAINING_PTN2:
833 reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
834 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
835 break;
836 case DP_NONE:
837 reg = SCRAMBLING_ENABLE |
838 LINK_QUAL_PATTERN_SET_DISABLE |
839 SW_TRAINING_PATTERN_SET_NORMAL;
840 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
841 break;
842 default:
843 break;
844 }
845}
846
847void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
848{
849 u32 reg;
850
851 reg = level << PRE_EMPHASIS_SET_SHIFT;
852 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
853}
854
855void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
856{
857 u32 reg;
858
859 reg = level << PRE_EMPHASIS_SET_SHIFT;
860 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
861}
862
863void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
864{
865 u32 reg;
866
867 reg = level << PRE_EMPHASIS_SET_SHIFT;
868 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
869}
870
871void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
872{
873 u32 reg;
874
875 reg = level << PRE_EMPHASIS_SET_SHIFT;
876 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
877}
878
879void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
880 u32 training_lane)
881{
882 u32 reg;
883
884 reg = training_lane;
885 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
886}
887
888void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
889 u32 training_lane)
890{
891 u32 reg;
892
893 reg = training_lane;
894 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
895}
896
897void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
898 u32 training_lane)
899{
900 u32 reg;
901
902 reg = training_lane;
903 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
904}
905
906void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
907 u32 training_lane)
908{
909 u32 reg;
910
911 reg = training_lane;
912 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
913}
914
915u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
916{
917 u32 reg;
918
919 reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
920 return reg;
921}
922
923u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
924{
925 u32 reg;
926
927 reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
928 return reg;
929}
930
931u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
932{
933 u32 reg;
934
935 reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
936 return reg;
937}
938
939u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
940{
941 u32 reg;
942
943 reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
944 return reg;
945}
946
947void exynos_dp_reset_macro(struct exynos_dp_device *dp)
948{
949 u32 reg;
950
951 reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
952 reg |= MACRO_RST;
953 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
954
955 /* 10 us is the minimum reset time. */
956 udelay(10);
957
958 reg &= ~MACRO_RST;
959 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
960}
961
962int exynos_dp_init_video(struct exynos_dp_device *dp)
963{
964 u32 reg;
965
966 reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
967 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
968
969 reg = 0x0;
970 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
971
972 reg = CHA_CRI(4) | CHA_CTRL;
973 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
974
975 reg = 0x0;
976 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
977
978 reg = VID_HRES_TH(2) | VID_VRES_TH(0);
979 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
980
981 return 0;
982}
983
984void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
985 u32 color_depth,
986 u32 color_space,
987 u32 dynamic_range,
988 u32 ycbcr_coeff)
989{
990 u32 reg;
991
992 /* Configure the input color depth, color space, dynamic range */
993 reg = (dynamic_range << IN_D_RANGE_SHIFT) |
994 (color_depth << IN_BPC_SHIFT) |
995 (color_space << IN_COLOR_F_SHIFT);
996 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
997
998 /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
999 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1000 reg &= ~IN_YC_COEFFI_MASK;
1001 if (ycbcr_coeff)
1002 reg |= IN_YC_COEFFI_ITU709;
1003 else
1004 reg |= IN_YC_COEFFI_ITU601;
1005 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1006}
1007
1008int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
1009{
1010 u32 reg;
1011
1012 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1013 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1014
1015 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1016
1017 if (!(reg & DET_STA)) {
1018 dev_dbg(dp->dev, "Input stream clock not detected.\n");
1019 return -EINVAL;
1020 }
1021
1022 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1023 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1024
1025 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1026 dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
1027
1028 if (reg & CHA_STA) {
1029 dev_dbg(dp->dev, "Input stream clk is changing\n");
1030 return -EINVAL;
1031 }
1032
1033 return 0;
1034}
1035
1036void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
1037 enum clock_recovery_m_value_type type,
1038 u32 m_value,
1039 u32 n_value)
1040{
1041 u32 reg;
1042
1043 if (type == REGISTER_M) {
1044 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1045 reg |= FIX_M_VID;
1046 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1047 reg = m_value & 0xff;
1048 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
1049 reg = (m_value >> 8) & 0xff;
1050 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
1051 reg = (m_value >> 16) & 0xff;
1052 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
1053
1054 reg = n_value & 0xff;
1055 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
1056 reg = (n_value >> 8) & 0xff;
1057 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
1058 reg = (n_value >> 16) & 0xff;
1059 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
1060 } else {
1061 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1062 reg &= ~FIX_M_VID;
1063 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1064
1065 writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
1066 writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
1067 writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
1068 }
1069}
1070
1071void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
1072{
1073 u32 reg;
1074
1075 if (type == VIDEO_TIMING_FROM_CAPTURE) {
1076 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1077 reg &= ~FORMAT_SEL;
1078 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1079 } else {
1080 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1081 reg |= FORMAT_SEL;
1082 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1083 }
1084}
1085
1086void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
1087{
1088 u32 reg;
1089
1090 if (enable) {
1091 reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1092 reg &= ~VIDEO_MODE_MASK;
1093 reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
1094 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1095 } else {
1096 reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1097 reg &= ~VIDEO_MODE_MASK;
1098 reg |= VIDEO_MODE_SLAVE_MODE;
1099 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1100 }
1101}
1102
1103void exynos_dp_start_video(struct exynos_dp_device *dp)
1104{
1105 u32 reg;
1106
1107 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1108 reg |= VIDEO_EN;
1109 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1110}
1111
1112int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
1113{
1114 u32 reg;
1115
1116 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1117 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1118
1119 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1120 if (!(reg & STRM_VALID)) {
1121 dev_dbg(dp->dev, "Input video stream is not detected.\n");
1122 return -EINVAL;
1123 }
1124
1125 return 0;
1126}
1127
1128void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
1129 struct video_info *video_info)
1130{
1131 u32 reg;
1132
1133 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1134 reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
1135 reg |= MASTER_VID_FUNC_EN_N;
1136 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1137
1138 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1139 reg &= ~INTERACE_SCAN_CFG;
1140 reg |= (video_info->interlaced << 2);
1141 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1142
1143 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1144 reg &= ~VSYNC_POLARITY_CFG;
1145 reg |= (video_info->v_sync_polarity << 1);
1146 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1147
1148 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1149 reg &= ~HSYNC_POLARITY_CFG;
1150 reg |= (video_info->h_sync_polarity << 0);
1151 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1152
1153 reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
1154 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1155}
1156
1157void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
1158{
1159 u32 reg;
1160
1161 reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1162 reg &= ~SCRAMBLING_DISABLE;
1163 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1164}
1165
1166void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
1167{
1168 u32 reg;
1169
1170 reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1171 reg |= SCRAMBLING_DISABLE;
1172 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1173}
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
new file mode 100644
index 000000000000..42f608e2a43e
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_reg.h
@@ -0,0 +1,335 @@
1/*
2 * Register definition file for Samsung DP driver
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_DP_REG_H
13#define _EXYNOS_DP_REG_H
14
15#define EXYNOS_DP_TX_SW_RESET 0x14
16#define EXYNOS_DP_FUNC_EN_1 0x18
17#define EXYNOS_DP_FUNC_EN_2 0x1C
18#define EXYNOS_DP_VIDEO_CTL_1 0x20
19#define EXYNOS_DP_VIDEO_CTL_2 0x24
20#define EXYNOS_DP_VIDEO_CTL_3 0x28
21
22#define EXYNOS_DP_VIDEO_CTL_8 0x3C
23#define EXYNOS_DP_VIDEO_CTL_10 0x44
24
25#define EXYNOS_DP_LANE_MAP 0x35C
26
27#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390
28
29#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4
30#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8
31#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC
32#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0
33#define EXYNOS_DP_INT_STA 0x3DC
34#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0
35#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4
36#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8
37#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC
38#define EXYNOS_DP_INT_STA_MASK 0x3F8
39#define EXYNOS_DP_INT_CTL 0x3FC
40
41#define EXYNOS_DP_SYS_CTL_1 0x600
42#define EXYNOS_DP_SYS_CTL_2 0x604
43#define EXYNOS_DP_SYS_CTL_3 0x608
44#define EXYNOS_DP_SYS_CTL_4 0x60C
45
46#define EXYNOS_DP_PKT_SEND_CTL 0x640
47#define EXYNOS_DP_HDCP_CTL 0x648
48
49#define EXYNOS_DP_LINK_BW_SET 0x680
50#define EXYNOS_DP_LANE_COUNT_SET 0x684
51#define EXYNOS_DP_TRAINING_PTN_SET 0x688
52#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C
53#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690
54#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694
55#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698
56
57#define EXYNOS_DP_DEBUG_CTL 0x6C0
58#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4
59#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8
60#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0
61
62#define EXYNOS_DP_M_VID_0 0x700
63#define EXYNOS_DP_M_VID_1 0x704
64#define EXYNOS_DP_M_VID_2 0x708
65#define EXYNOS_DP_N_VID_0 0x70C
66#define EXYNOS_DP_N_VID_1 0x710
67#define EXYNOS_DP_N_VID_2 0x714
68
69#define EXYNOS_DP_PLL_CTL 0x71C
70#define EXYNOS_DP_PHY_PD 0x720
71#define EXYNOS_DP_PHY_TEST 0x724
72
73#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730
74#define EXYNOS_DP_AUDIO_MARGIN 0x73C
75
76#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764
77#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778
78#define EXYNOS_DP_AUX_CH_STA 0x780
79#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788
80#define EXYNOS_DP_AUX_RX_COMM 0x78C
81#define EXYNOS_DP_BUFFER_DATA_CTL 0x790
82#define EXYNOS_DP_AUX_CH_CTL_1 0x794
83#define EXYNOS_DP_AUX_ADDR_7_0 0x798
84#define EXYNOS_DP_AUX_ADDR_15_8 0x79C
85#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0
86#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4
87
88#define EXYNOS_DP_BUF_DATA_0 0x7C0
89
90#define EXYNOS_DP_SOC_GENERAL_CTL 0x800
91
92/* EXYNOS_DP_TX_SW_RESET */
93#define RESET_DP_TX (0x1 << 0)
94
95/* EXYNOS_DP_FUNC_EN_1 */
96#define MASTER_VID_FUNC_EN_N (0x1 << 7)
97#define SLAVE_VID_FUNC_EN_N (0x1 << 5)
98#define AUD_FIFO_FUNC_EN_N (0x1 << 4)
99#define AUD_FUNC_EN_N (0x1 << 3)
100#define HDCP_FUNC_EN_N (0x1 << 2)
101#define CRC_FUNC_EN_N (0x1 << 1)
102#define SW_FUNC_EN_N (0x1 << 0)
103
104/* EXYNOS_DP_FUNC_EN_2 */
105#define SSC_FUNC_EN_N (0x1 << 7)
106#define AUX_FUNC_EN_N (0x1 << 2)
107#define SERDES_FIFO_FUNC_EN_N (0x1 << 1)
108#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
109
110/* EXYNOS_DP_VIDEO_CTL_1 */
111#define VIDEO_EN (0x1 << 7)
112#define HDCP_VIDEO_MUTE (0x1 << 6)
113
114/* EXYNOS_DP_VIDEO_CTL_1 */
115#define IN_D_RANGE_MASK (0x1 << 7)
116#define IN_D_RANGE_SHIFT (7)
117#define IN_D_RANGE_CEA (0x1 << 7)
118#define IN_D_RANGE_VESA (0x0 << 7)
119#define IN_BPC_MASK (0x7 << 4)
120#define IN_BPC_SHIFT (4)
121#define IN_BPC_12_BITS (0x3 << 4)
122#define IN_BPC_10_BITS (0x2 << 4)
123#define IN_BPC_8_BITS (0x1 << 4)
124#define IN_BPC_6_BITS (0x0 << 4)
125#define IN_COLOR_F_MASK (0x3 << 0)
126#define IN_COLOR_F_SHIFT (0)
127#define IN_COLOR_F_YCBCR444 (0x2 << 0)
128#define IN_COLOR_F_YCBCR422 (0x1 << 0)
129#define IN_COLOR_F_RGB (0x0 << 0)
130
131/* EXYNOS_DP_VIDEO_CTL_3 */
132#define IN_YC_COEFFI_MASK (0x1 << 7)
133#define IN_YC_COEFFI_SHIFT (7)
134#define IN_YC_COEFFI_ITU709 (0x1 << 7)
135#define IN_YC_COEFFI_ITU601 (0x0 << 7)
136#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4)
137#define VID_CHK_UPDATE_TYPE_SHIFT (4)
138#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4)
139#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
140
141/* EXYNOS_DP_VIDEO_CTL_8 */
142#define VID_HRES_TH(x) (((x) & 0xf) << 4)
143#define VID_VRES_TH(x) (((x) & 0xf) << 0)
144
145/* EXYNOS_DP_VIDEO_CTL_10 */
146#define FORMAT_SEL (0x1 << 4)
147#define INTERACE_SCAN_CFG (0x1 << 2)
148#define VSYNC_POLARITY_CFG (0x1 << 1)
149#define HSYNC_POLARITY_CFG (0x1 << 0)
150
151/* EXYNOS_DP_LANE_MAP */
152#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
153#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6)
154#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6)
155#define LANE3_MAP_LOGIC_LANE_3 (0x3 << 6)
156#define LANE2_MAP_LOGIC_LANE_0 (0x0 << 4)
157#define LANE2_MAP_LOGIC_LANE_1 (0x1 << 4)
158#define LANE2_MAP_LOGIC_LANE_2 (0x2 << 4)
159#define LANE2_MAP_LOGIC_LANE_3 (0x3 << 4)
160#define LANE1_MAP_LOGIC_LANE_0 (0x0 << 2)
161#define LANE1_MAP_LOGIC_LANE_1 (0x1 << 2)
162#define LANE1_MAP_LOGIC_LANE_2 (0x2 << 2)
163#define LANE1_MAP_LOGIC_LANE_3 (0x3 << 2)
164#define LANE0_MAP_LOGIC_LANE_0 (0x0 << 0)
165#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0)
166#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0)
167#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
168
169/* EXYNOS_DP_AUX_HW_RETRY_CTL */
170#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8)
171#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3)
172#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
173#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3)
174#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3)
175#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3)
176#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0)
177
178/* EXYNOS_DP_COMMON_INT_STA_1 */
179#define VSYNC_DET (0x1 << 7)
180#define PLL_LOCK_CHG (0x1 << 6)
181#define SPDIF_ERR (0x1 << 5)
182#define SPDIF_UNSTBL (0x1 << 4)
183#define VID_FORMAT_CHG (0x1 << 3)
184#define AUD_CLK_CHG (0x1 << 2)
185#define VID_CLK_CHG (0x1 << 1)
186#define SW_INT (0x1 << 0)
187
188/* EXYNOS_DP_COMMON_INT_STA_2 */
189#define ENC_EN_CHG (0x1 << 6)
190#define HW_BKSV_RDY (0x1 << 3)
191#define HW_SHA_DONE (0x1 << 2)
192#define HW_AUTH_STATE_CHG (0x1 << 1)
193#define HW_AUTH_DONE (0x1 << 0)
194
195/* EXYNOS_DP_COMMON_INT_STA_3 */
196#define AFIFO_UNDER (0x1 << 7)
197#define AFIFO_OVER (0x1 << 6)
198#define R0_CHK_FLAG (0x1 << 5)
199
200/* EXYNOS_DP_COMMON_INT_STA_4 */
201#define PSR_ACTIVE (0x1 << 7)
202#define PSR_INACTIVE (0x1 << 6)
203#define SPDIF_BI_PHASE_ERR (0x1 << 5)
204#define HOTPLUG_CHG (0x1 << 2)
205#define HPD_LOST (0x1 << 1)
206#define PLUG (0x1 << 0)
207
208/* EXYNOS_DP_INT_STA */
209#define INT_HPD (0x1 << 6)
210#define HW_TRAINING_FINISH (0x1 << 5)
211#define RPLY_RECEIV (0x1 << 1)
212#define AUX_ERR (0x1 << 0)
213
214/* EXYNOS_DP_INT_CTL */
215#define SOFT_INT_CTRL (0x1 << 2)
216#define INT_POL (0x1 << 0)
217
218/* EXYNOS_DP_SYS_CTL_1 */
219#define DET_STA (0x1 << 2)
220#define FORCE_DET (0x1 << 1)
221#define DET_CTRL (0x1 << 0)
222
223/* EXYNOS_DP_SYS_CTL_2 */
224#define CHA_CRI(x) (((x) & 0xf) << 4)
225#define CHA_STA (0x1 << 2)
226#define FORCE_CHA (0x1 << 1)
227#define CHA_CTRL (0x1 << 0)
228
229/* EXYNOS_DP_SYS_CTL_3 */
230#define HPD_STATUS (0x1 << 6)
231#define F_HPD (0x1 << 5)
232#define HPD_CTRL (0x1 << 4)
233#define HDCP_RDY (0x1 << 3)
234#define STRM_VALID (0x1 << 2)
235#define F_VALID (0x1 << 1)
236#define VALID_CTRL (0x1 << 0)
237
238/* EXYNOS_DP_SYS_CTL_4 */
239#define FIX_M_AUD (0x1 << 4)
240#define ENHANCED (0x1 << 3)
241#define FIX_M_VID (0x1 << 2)
242#define M_VID_UPDATE_CTRL (0x3 << 0)
243
244/* EXYNOS_DP_TRAINING_PTN_SET */
245#define SCRAMBLER_TYPE (0x1 << 9)
246#define HW_LINK_TRAINING_PATTERN (0x1 << 8)
247#define SCRAMBLING_DISABLE (0x1 << 5)
248#define SCRAMBLING_ENABLE (0x0 << 5)
249#define LINK_QUAL_PATTERN_SET_MASK (0x3 << 2)
250#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2)
251#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2)
252#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2)
253#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0)
254#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0)
255#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0)
256#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
257
258/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
259#define PRE_EMPHASIS_SET_SHIFT (3)
260
261/* EXYNOS_DP_DEBUG_CTL */
262#define PLL_LOCK (0x1 << 4)
263#define F_PLL_LOCK (0x1 << 3)
264#define PLL_LOCK_CTRL (0x1 << 2)
265#define PN_INV (0x1 << 0)
266
267/* EXYNOS_DP_PLL_CTL */
268#define DP_PLL_PD (0x1 << 7)
269#define DP_PLL_RESET (0x1 << 6)
270#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4)
271#define DP_PLL_REF_BIT_1_1250V (0x5 << 0)
272#define DP_PLL_REF_BIT_1_2500V (0x7 << 0)
273
274/* EXYNOS_DP_PHY_PD */
275#define DP_PHY_PD (0x1 << 5)
276#define AUX_PD (0x1 << 4)
277#define CH3_PD (0x1 << 3)
278#define CH2_PD (0x1 << 2)
279#define CH1_PD (0x1 << 1)
280#define CH0_PD (0x1 << 0)
281
282/* EXYNOS_DP_PHY_TEST */
283#define MACRO_RST (0x1 << 5)
284#define CH1_TEST (0x1 << 1)
285#define CH0_TEST (0x1 << 0)
286
287/* EXYNOS_DP_AUX_CH_STA */
288#define AUX_BUSY (0x1 << 4)
289#define AUX_STATUS_MASK (0xf << 0)
290
291/* EXYNOS_DP_AUX_CH_DEFER_CTL */
292#define DEFER_CTRL_EN (0x1 << 7)
293#define DEFER_COUNT(x) (((x) & 0x7f) << 0)
294
295/* EXYNOS_DP_AUX_RX_COMM */
296#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
297#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
298
299/* EXYNOS_DP_BUFFER_DATA_CTL */
300#define BUF_CLR (0x1 << 7)
301#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0)
302
303/* EXYNOS_DP_AUX_CH_CTL_1 */
304#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4)
305#define AUX_TX_COMM_MASK (0xf << 0)
306#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3)
307#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3)
308#define AUX_TX_COMM_MOT (0x1 << 2)
309#define AUX_TX_COMM_WRITE (0x0 << 0)
310#define AUX_TX_COMM_READ (0x1 << 0)
311
312/* EXYNOS_DP_AUX_ADDR_7_0 */
313#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
314
315/* EXYNOS_DP_AUX_ADDR_15_8 */
316#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
317
318/* EXYNOS_DP_AUX_ADDR_19_16 */
319#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
320
321/* EXYNOS_DP_AUX_CH_CTL_2 */
322#define ADDR_ONLY (0x1 << 1)
323#define AUX_EN (0x1 << 0)
324
325/* EXYNOS_DP_SOC_GENERAL_CTL */
326#define AUDIO_MODE_SPDIF_MODE (0x1 << 8)
327#define AUDIO_MODE_MASTER_MODE (0x0 << 8)
328#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4)
329#define VIDEO_MASTER_CLK_SEL (0x1 << 2)
330#define VIDEO_MASTER_MODE_EN (0x1 << 1)
331#define VIDEO_MODE_MASK (0x1 << 0)
332#define VIDEO_MODE_SLAVE_MODE (0x1 << 0)
333#define VIDEO_MODE_MASTER_MODE (0x0 << 0)
334
335#endif /* _EXYNOS_DP_REG_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
new file mode 100644
index 000000000000..557091dc0e97
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -0,0 +1,600 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi.c
2 *
3 * Samsung SoC MIPI-DSIM driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae, <inki.dae@samsung.com>
8 * Donghwa Lee, <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/clk.h>
19#include <linux/mutex.h>
20#include <linux/wait.h>
21#include <linux/fs.h>
22#include <linux/mm.h>
23#include <linux/fb.h>
24#include <linux/ctype.h>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/irq.h>
28#include <linux/memory.h>
29#include <linux/delay.h>
30#include <linux/interrupt.h>
31#include <linux/kthread.h>
32#include <linux/notifier.h>
33#include <linux/regulator/consumer.h>
34#include <linux/pm_runtime.h>
35
36#include <video/exynos_mipi_dsim.h>
37
38#include <plat/fb.h>
39
40#include "exynos_mipi_dsi_common.h"
41#include "exynos_mipi_dsi_lowlevel.h"
42
43struct mipi_dsim_ddi {
44 int bus_id;
45 struct list_head list;
46 struct mipi_dsim_lcd_device *dsim_lcd_dev;
47 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
48};
49
50static LIST_HEAD(dsim_ddi_list);
51
52static DEFINE_MUTEX(mipi_dsim_lock);
53
54static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
55 *pdev)
56{
57 return pdev->dev.platform_data;
58}
59
60static struct regulator_bulk_data supplies[] = {
61 { .supply = "vdd10", },
62 { .supply = "vdd18", },
63};
64
65static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
66{
67 int ret;
68
69 mutex_lock(&dsim->lock);
70 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
71 mutex_unlock(&dsim->lock);
72
73 return ret;
74}
75
76static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
77{
78 int ret;
79
80 mutex_lock(&dsim->lock);
81 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
82 mutex_unlock(&dsim->lock);
83
84 return ret;
85}
86
87/* update all register settings to MIPI DSI controller. */
88static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
89{
90 /*
91 * data from Display controller(FIMD) is not transferred in video mode
92 * but in case of command mode, all settings is not updated to
93 * registers.
94 */
95 exynos_mipi_dsi_stand_by(dsim, 0);
96
97 exynos_mipi_dsi_init_dsim(dsim);
98 exynos_mipi_dsi_init_link(dsim);
99
100 exynos_mipi_dsi_set_hs_enable(dsim);
101
102 /* set display timing. */
103 exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
104
105 /*
106 * data from Display controller(FIMD) is transferred in video mode
107 * but in case of command mode, all settigs is updated to registers.
108 */
109 exynos_mipi_dsi_stand_by(dsim, 1);
110}
111
112static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
113 int power)
114{
115 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
116 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
117
118 switch (power) {
119 case FB_BLANK_POWERDOWN:
120 if (dsim->suspended)
121 return 0;
122
123 if (client_drv && client_drv->suspend)
124 client_drv->suspend(client_dev);
125
126 clk_disable(dsim->clock);
127
128 exynos_mipi_regulator_disable(dsim);
129
130 dsim->suspended = true;
131
132 break;
133 default:
134 break;
135 }
136
137 return 0;
138}
139
140static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
141{
142 struct platform_device *pdev = to_platform_device(dsim->dev);
143 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
144 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
145
146 switch (power) {
147 case FB_BLANK_UNBLANK:
148 if (!dsim->suspended)
149 return 0;
150
151 /* lcd panel power on. */
152 if (client_drv && client_drv->power_on)
153 client_drv->power_on(client_dev, 1);
154
155 exynos_mipi_regulator_disable(dsim);
156
157 /* enable MIPI-DSI PHY. */
158 if (dsim->pd->phy_enable)
159 dsim->pd->phy_enable(pdev, true);
160
161 clk_enable(dsim->clock);
162
163 exynos_mipi_update_cfg(dsim);
164
165 /* set lcd panel sequence commands. */
166 if (client_drv && client_drv->set_sequence)
167 client_drv->set_sequence(client_dev);
168
169 dsim->suspended = false;
170
171 break;
172 case FB_BLANK_NORMAL:
173 /* TODO. */
174 break;
175 default:
176 break;
177 }
178
179 return 0;
180}
181
182int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
183{
184 struct mipi_dsim_ddi *dsim_ddi;
185
186 if (!lcd_dev->name) {
187 pr_err("dsim_lcd_device name is NULL.\n");
188 return -EFAULT;
189 }
190
191 dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
192 if (!dsim_ddi) {
193 pr_err("failed to allocate dsim_ddi object.\n");
194 return -ENOMEM;
195 }
196
197 dsim_ddi->dsim_lcd_dev = lcd_dev;
198
199 mutex_lock(&mipi_dsim_lock);
200 list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
201 mutex_unlock(&mipi_dsim_lock);
202
203 return 0;
204}
205
206struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
207{
208 struct mipi_dsim_ddi *dsim_ddi, *next;
209 struct mipi_dsim_lcd_device *lcd_dev;
210
211 mutex_lock(&mipi_dsim_lock);
212
213 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
214 if (!dsim_ddi)
215 goto out;
216
217 lcd_dev = dsim_ddi->dsim_lcd_dev;
218 if (!lcd_dev)
219 continue;
220
221 if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
222 /**
223 * bus_id would be used to identify
224 * connected bus.
225 */
226 dsim_ddi->bus_id = lcd_dev->bus_id;
227 mutex_unlock(&mipi_dsim_lock);
228
229 return dsim_ddi;
230 }
231
232 list_del(&dsim_ddi->list);
233 kfree(dsim_ddi);
234 }
235
236out:
237 mutex_unlock(&mipi_dsim_lock);
238
239 return NULL;
240}
241
242int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
243{
244 struct mipi_dsim_ddi *dsim_ddi;
245
246 if (!lcd_drv->name) {
247 pr_err("dsim_lcd_driver name is NULL.\n");
248 return -EFAULT;
249 }
250
251 dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
252 if (!dsim_ddi) {
253 pr_err("mipi_dsim_ddi object not found.\n");
254 return -EFAULT;
255 }
256
257 dsim_ddi->dsim_lcd_drv = lcd_drv;
258
259 pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
260 lcd_drv->name);
261
262 return 0;
263
264}
265
266struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
267 const char *name)
268{
269 struct mipi_dsim_ddi *dsim_ddi, *next;
270 struct mipi_dsim_lcd_driver *lcd_drv;
271 struct mipi_dsim_lcd_device *lcd_dev;
272 int ret;
273
274 mutex_lock(&dsim->lock);
275
276 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
277 lcd_drv = dsim_ddi->dsim_lcd_drv;
278 lcd_dev = dsim_ddi->dsim_lcd_dev;
279 if (!lcd_drv || !lcd_dev ||
280 (dsim->id != dsim_ddi->bus_id))
281 continue;
282
283 dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
284 lcd_drv->id, lcd_dev->id);
285 dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
286 lcd_dev->bus_id, dsim->id);
287
288 if ((strcmp(lcd_drv->name, name) == 0)) {
289 lcd_dev->master = dsim;
290
291 lcd_dev->dev.parent = dsim->dev;
292 dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
293
294 ret = device_register(&lcd_dev->dev);
295 if (ret < 0) {
296 dev_err(dsim->dev,
297 "can't register %s, status %d\n",
298 dev_name(&lcd_dev->dev), ret);
299 mutex_unlock(&dsim->lock);
300
301 return NULL;
302 }
303
304 dsim->dsim_lcd_dev = lcd_dev;
305 dsim->dsim_lcd_drv = lcd_drv;
306
307 mutex_unlock(&dsim->lock);
308
309 return dsim_ddi;
310 }
311 }
312
313 mutex_unlock(&dsim->lock);
314
315 return NULL;
316}
317
318/* define MIPI-DSI Master operations. */
319static struct mipi_dsim_master_ops master_ops = {
320 .cmd_read = exynos_mipi_dsi_rd_data,
321 .cmd_write = exynos_mipi_dsi_wr_data,
322 .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status,
323 .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done,
324 .set_early_blank_mode = exynos_mipi_dsi_early_blank_mode,
325 .set_blank_mode = exynos_mipi_dsi_blank_mode,
326};
327
328static int exynos_mipi_dsi_probe(struct platform_device *pdev)
329{
330 struct resource *res;
331 struct mipi_dsim_device *dsim;
332 struct mipi_dsim_config *dsim_config;
333 struct mipi_dsim_platform_data *dsim_pd;
334 struct mipi_dsim_ddi *dsim_ddi;
335 int ret = -EINVAL;
336
337 dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
338 if (!dsim) {
339 dev_err(&pdev->dev, "failed to allocate dsim object.\n");
340 return -ENOMEM;
341 }
342
343 dsim->pd = to_dsim_plat(pdev);
344 dsim->dev = &pdev->dev;
345 dsim->id = pdev->id;
346
347 /* get mipi_dsim_platform_data. */
348 dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
349 if (dsim_pd == NULL) {
350 dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
351 goto err_clock_get;
352 }
353 /* get mipi_dsim_config. */
354 dsim_config = dsim_pd->dsim_config;
355 if (dsim_config == NULL) {
356 dev_err(&pdev->dev, "failed to get dsim config data.\n");
357 goto err_clock_get;
358 }
359
360 dsim->dsim_config = dsim_config;
361 dsim->master_ops = &master_ops;
362
363 mutex_init(&dsim->lock);
364
365 ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies), supplies);
366 if (ret) {
367 dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
368 goto err_clock_get;
369 }
370
371 dsim->clock = clk_get(&pdev->dev, "dsim0");
372 if (IS_ERR(dsim->clock)) {
373 dev_err(&pdev->dev, "failed to get dsim clock source\n");
374 goto err_clock_get;
375 }
376
377 clk_enable(dsim->clock);
378
379 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
380 if (!res) {
381 dev_err(&pdev->dev, "failed to get io memory region\n");
382 goto err_platform_get;
383 }
384
385 dsim->res = request_mem_region(res->start, resource_size(res),
386 dev_name(&pdev->dev));
387 if (!dsim->res) {
388 dev_err(&pdev->dev, "failed to request io memory region\n");
389 ret = -ENOMEM;
390 goto err_mem_region;
391 }
392
393 dsim->reg_base = ioremap(res->start, resource_size(res));
394 if (!dsim->reg_base) {
395 dev_err(&pdev->dev, "failed to remap io region\n");
396 ret = -ENOMEM;
397 goto err_ioremap;
398 }
399
400 mutex_init(&dsim->lock);
401
402 /* bind lcd ddi matched with panel name. */
403 dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
404 if (!dsim_ddi) {
405 dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
406 goto err_bind;
407 }
408
409 dsim->irq = platform_get_irq(pdev, 0);
410 if (dsim->irq < 0) {
411 dev_err(&pdev->dev, "failed to request dsim irq resource\n");
412 ret = -EINVAL;
413 goto err_platform_get_irq;
414 }
415
416 ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler,
417 IRQF_SHARED, pdev->name, dsim);
418 if (ret != 0) {
419 dev_err(&pdev->dev, "failed to request dsim irq\n");
420 ret = -EINVAL;
421 goto err_bind;
422 }
423
424 init_completion(&dsim_wr_comp);
425 init_completion(&dsim_rd_comp);
426
427 /* enable interrupt */
428 exynos_mipi_dsi_init_interrupt(dsim);
429
430 /* initialize mipi-dsi client(lcd panel). */
431 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
432 dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
433
434 /* in case that mipi got enabled at bootloader. */
435 if (dsim_pd->enabled)
436 goto out;
437
438 /* lcd panel power on. */
439 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
440 dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
441
442 exynos_mipi_regulator_enable(dsim);
443
444 /* enable MIPI-DSI PHY. */
445 if (dsim->pd->phy_enable)
446 dsim->pd->phy_enable(pdev, true);
447
448 exynos_mipi_update_cfg(dsim);
449
450 /* set lcd panel sequence commands. */
451 if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
452 dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
453
454 dsim->suspended = false;
455
456out:
457 platform_set_drvdata(pdev, dsim);
458
459 dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n",
460 (dsim_config->e_interface == DSIM_COMMAND) ?
461 "CPU" : "RGB");
462
463 return 0;
464
465err_bind:
466 iounmap(dsim->reg_base);
467
468err_ioremap:
469 release_mem_region(dsim->res->start, resource_size(dsim->res));
470
471err_mem_region:
472 release_resource(dsim->res);
473
474err_platform_get:
475 clk_disable(dsim->clock);
476 clk_put(dsim->clock);
477err_clock_get:
478 kfree(dsim);
479
480err_platform_get_irq:
481 return ret;
482}
483
484static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev)
485{
486 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
487 struct mipi_dsim_ddi *dsim_ddi, *next;
488 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
489
490 iounmap(dsim->reg_base);
491
492 clk_disable(dsim->clock);
493 clk_put(dsim->clock);
494
495 release_resource(dsim->res);
496 release_mem_region(dsim->res->start, resource_size(dsim->res));
497
498 list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
499 if (dsim_ddi) {
500 if (dsim->id != dsim_ddi->bus_id)
501 continue;
502
503 dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
504
505 if (dsim_lcd_drv->remove)
506 dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
507
508 kfree(dsim_ddi);
509 }
510 }
511
512 regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
513 kfree(dsim);
514
515 return 0;
516}
517
518#ifdef CONFIG_PM
519static int exynos_mipi_dsi_suspend(struct platform_device *pdev,
520 pm_message_t state)
521{
522 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
523 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
524 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
525
526 disable_irq(dsim->irq);
527
528 if (dsim->suspended)
529 return 0;
530
531 if (client_drv && client_drv->suspend)
532 client_drv->suspend(client_dev);
533
534 /* enable MIPI-DSI PHY. */
535 if (dsim->pd->phy_enable)
536 dsim->pd->phy_enable(pdev, false);
537
538 clk_disable(dsim->clock);
539
540 exynos_mipi_regulator_disable(dsim);
541
542 dsim->suspended = true;
543
544 return 0;
545}
546
547static int exynos_mipi_dsi_resume(struct platform_device *pdev)
548{
549 struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
550 struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
551 struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
552
553 enable_irq(dsim->irq);
554
555 if (!dsim->suspended)
556 return 0;
557
558 /* lcd panel power on. */
559 if (client_drv && client_drv->power_on)
560 client_drv->power_on(client_dev, 1);
561
562 exynos_mipi_regulator_enable(dsim);
563
564 /* enable MIPI-DSI PHY. */
565 if (dsim->pd->phy_enable)
566 dsim->pd->phy_enable(pdev, true);
567
568 clk_enable(dsim->clock);
569
570 exynos_mipi_update_cfg(dsim);
571
572 /* set lcd panel sequence commands. */
573 if (client_drv && client_drv->set_sequence)
574 client_drv->set_sequence(client_dev);
575
576 dsim->suspended = false;
577
578 return 0;
579}
580#else
581#define exynos_mipi_dsi_suspend NULL
582#define exynos_mipi_dsi_resume NULL
583#endif
584
585static struct platform_driver exynos_mipi_dsi_driver = {
586 .probe = exynos_mipi_dsi_probe,
587 .remove = __devexit_p(exynos_mipi_dsi_remove),
588 .suspend = exynos_mipi_dsi_suspend,
589 .resume = exynos_mipi_dsi_resume,
590 .driver = {
591 .name = "exynos-mipi-dsim",
592 .owner = THIS_MODULE,
593 },
594};
595
596module_platform_driver(exynos_mipi_dsi_driver);
597
598MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
599MODULE_DESCRIPTION("Samusung SoC MIPI-DSI driver");
600MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
new file mode 100644
index 000000000000..14909c1d3832
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -0,0 +1,896 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi_common.c
2 *
3 * Samsung SoC MIPI-DSI common driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae, <inki.dae@samsung.com>
8 * Donghwa Lee, <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/mutex.h>
19#include <linux/wait.h>
20#include <linux/fs.h>
21#include <linux/mm.h>
22#include <linux/fb.h>
23#include <linux/ctype.h>
24#include <linux/platform_device.h>
25#include <linux/io.h>
26#include <linux/memory.h>
27#include <linux/delay.h>
28#include <linux/kthread.h>
29
30#include <video/mipi_display.h>
31#include <video/exynos_mipi_dsim.h>
32
33#include <mach/map.h>
34
35#include "exynos_mipi_dsi_regs.h"
36#include "exynos_mipi_dsi_lowlevel.h"
37#include "exynos_mipi_dsi_common.h"
38
39#define MIPI_FIFO_TIMEOUT msecs_to_jiffies(250)
40#define MIPI_RX_FIFO_READ_DONE 0x30800002
41#define MIPI_MAX_RX_FIFO 20
42#define MHZ (1000 * 1000)
43#define FIN_HZ (24 * MHZ)
44
45#define DFIN_PLL_MIN_HZ (6 * MHZ)
46#define DFIN_PLL_MAX_HZ (12 * MHZ)
47
48#define DFVCO_MIN_HZ (500 * MHZ)
49#define DFVCO_MAX_HZ (1000 * MHZ)
50
51#define TRY_GET_FIFO_TIMEOUT (5000 * 2)
52#define TRY_FIFO_CLEAR (10)
53
54/* MIPI-DSIM status types. */
55enum {
56 DSIM_STATE_INIT, /* should be initialized. */
57 DSIM_STATE_STOP, /* CPU and LCDC are LP mode. */
58 DSIM_STATE_HSCLKEN, /* HS clock was enabled. */
59 DSIM_STATE_ULPS
60};
61
62/* define DSI lane types. */
63enum {
64 DSIM_LANE_CLOCK = (1 << 0),
65 DSIM_LANE_DATA0 = (1 << 1),
66 DSIM_LANE_DATA1 = (1 << 2),
67 DSIM_LANE_DATA2 = (1 << 3),
68 DSIM_LANE_DATA3 = (1 << 4)
69};
70
71static unsigned int dpll_table[15] = {
72 100, 120, 170, 220, 270,
73 320, 390, 450, 510, 560,
74 640, 690, 770, 870, 950
75};
76
77irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
78{
79 unsigned int intsrc = 0;
80 unsigned int intmsk = 0;
81 struct mipi_dsim_device *dsim = NULL;
82
83 dsim = dev_id;
84 if (!dsim) {
85 dev_dbg(dsim->dev, KERN_ERR "%s:error: wrong parameter\n",
86 __func__);
87 return IRQ_HANDLED;
88 }
89
90 intsrc = exynos_mipi_dsi_read_interrupt(dsim);
91 intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
92
93 intmsk = ~(intmsk) & intsrc;
94
95 switch (intmsk) {
96 case INTMSK_RX_DONE:
97 complete(&dsim_rd_comp);
98 dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n");
99 break;
100 case INTMSK_FIFO_EMPTY:
101 complete(&dsim_wr_comp);
102 dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n");
103 break;
104 default:
105 break;
106 }
107
108 exynos_mipi_dsi_clear_interrupt(dsim, intmsk);
109
110 return IRQ_HANDLED;
111}
112
113/*
114 * write long packet to mipi dsi slave
115 * @dsim: mipi dsim device structure.
116 * @data0: packet data to send.
117 * @data1: size of packet data
118 */
119static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim,
120 const unsigned char *data0, unsigned int data_size)
121{
122 unsigned int data_cnt = 0, payload = 0;
123
124 /* in case that data count is more then 4 */
125 for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
126 /*
127 * after sending 4bytes per one time,
128 * send remainder data less then 4.
129 */
130 if ((data_size - data_cnt) < 4) {
131 if ((data_size - data_cnt) == 3) {
132 payload = data0[data_cnt] |
133 data0[data_cnt + 1] << 8 |
134 data0[data_cnt + 2] << 16;
135 dev_dbg(dsim->dev, "count = 3 payload = %x, %x %x %x\n",
136 payload, data0[data_cnt],
137 data0[data_cnt + 1],
138 data0[data_cnt + 2]);
139 } else if ((data_size - data_cnt) == 2) {
140 payload = data0[data_cnt] |
141 data0[data_cnt + 1] << 8;
142 dev_dbg(dsim->dev,
143 "count = 2 payload = %x, %x %x\n", payload,
144 data0[data_cnt],
145 data0[data_cnt + 1]);
146 } else if ((data_size - data_cnt) == 1) {
147 payload = data0[data_cnt];
148 }
149
150 exynos_mipi_dsi_wr_tx_data(dsim, payload);
151 /* send 4bytes per one time. */
152 } else {
153 payload = data0[data_cnt] |
154 data0[data_cnt + 1] << 8 |
155 data0[data_cnt + 2] << 16 |
156 data0[data_cnt + 3] << 24;
157
158 dev_dbg(dsim->dev,
159 "count = 4 payload = %x, %x %x %x %x\n",
160 payload, *(u8 *)(data0 + data_cnt),
161 data0[data_cnt + 1],
162 data0[data_cnt + 2],
163 data0[data_cnt + 3]);
164
165 exynos_mipi_dsi_wr_tx_data(dsim, payload);
166 }
167 }
168}
169
170int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
171 const unsigned char *data0, unsigned int data_size)
172{
173 unsigned int check_rx_ack = 0;
174
175 if (dsim->state == DSIM_STATE_ULPS) {
176 dev_err(dsim->dev, "state is ULPS.\n");
177
178 return -EINVAL;
179 }
180
181 /* FIXME!!! why does it need this delay? */
182 msleep(20);
183
184 mutex_lock(&dsim->lock);
185
186 switch (data_id) {
187 /* short packet types of packet types for command. */
188 case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
189 case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
190 case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
191 case MIPI_DSI_DCS_SHORT_WRITE:
192 case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
193 case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
194 exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
195 if (check_rx_ack) {
196 /* process response func should be implemented */
197 mutex_unlock(&dsim->lock);
198 return 0;
199 } else {
200 mutex_unlock(&dsim->lock);
201 return -EINVAL;
202 }
203
204 /* general command */
205 case MIPI_DSI_COLOR_MODE_OFF:
206 case MIPI_DSI_COLOR_MODE_ON:
207 case MIPI_DSI_SHUTDOWN_PERIPHERAL:
208 case MIPI_DSI_TURN_ON_PERIPHERAL:
209 exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]);
210 if (check_rx_ack) {
211 /* process response func should be implemented. */
212 mutex_unlock(&dsim->lock);
213 return 0;
214 } else {
215 mutex_unlock(&dsim->lock);
216 return -EINVAL;
217 }
218
219 /* packet types for video data */
220 case MIPI_DSI_V_SYNC_START:
221 case MIPI_DSI_V_SYNC_END:
222 case MIPI_DSI_H_SYNC_START:
223 case MIPI_DSI_H_SYNC_END:
224 case MIPI_DSI_END_OF_TRANSMISSION:
225 mutex_unlock(&dsim->lock);
226 return 0;
227
228 /* long packet type and null packet */
229 case MIPI_DSI_NULL_PACKET:
230 case MIPI_DSI_BLANKING_PACKET:
231 mutex_unlock(&dsim->lock);
232 return 0;
233 case MIPI_DSI_GENERIC_LONG_WRITE:
234 case MIPI_DSI_DCS_LONG_WRITE:
235 {
236 unsigned int size, payload = 0;
237 INIT_COMPLETION(dsim_wr_comp);
238
239 size = data_size * 4;
240
241 /* if data count is less then 4, then send 3bytes data. */
242 if (data_size < 4) {
243 payload = data0[0] |
244 data0[1] << 8 |
245 data0[2] << 16;
246
247 exynos_mipi_dsi_wr_tx_data(dsim, payload);
248
249 dev_dbg(dsim->dev, "count = %d payload = %x,%x %x %x\n",
250 data_size, payload, data0[0],
251 data0[1], data0[2]);
252
253 /* in case that data count is more then 4 */
254 } else
255 exynos_mipi_dsi_long_data_wr(dsim, data0, data_size);
256
257 /* put data into header fifo */
258 exynos_mipi_dsi_wr_tx_header(dsim, data_id, data_size & 0xff,
259 (data_size & 0xff00) >> 8);
260
261 if (!wait_for_completion_interruptible_timeout(&dsim_wr_comp,
262 MIPI_FIFO_TIMEOUT)) {
263 dev_warn(dsim->dev, "command write timeout.\n");
264 mutex_unlock(&dsim->lock);
265 return -EAGAIN;
266 }
267
268 if (check_rx_ack) {
269 /* process response func should be implemented. */
270 mutex_unlock(&dsim->lock);
271 return 0;
272 } else {
273 mutex_unlock(&dsim->lock);
274 return -EINVAL;
275 }
276 }
277
278 /* packet typo for video data */
279 case MIPI_DSI_PACKED_PIXEL_STREAM_16:
280 case MIPI_DSI_PACKED_PIXEL_STREAM_18:
281 case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
282 case MIPI_DSI_PACKED_PIXEL_STREAM_24:
283 if (check_rx_ack) {
284 /* process response func should be implemented. */
285 mutex_unlock(&dsim->lock);
286 return 0;
287 } else {
288 mutex_unlock(&dsim->lock);
289 return -EINVAL;
290 }
291 default:
292 dev_warn(dsim->dev,
293 "data id %x is not supported current DSI spec.\n",
294 data_id);
295
296 mutex_unlock(&dsim->lock);
297 return -EINVAL;
298 }
299
300 mutex_unlock(&dsim->lock);
301 return 0;
302}
303
304static unsigned int exynos_mipi_dsi_long_data_rd(struct mipi_dsim_device *dsim,
305 unsigned int req_size, unsigned int rx_data, u8 *rx_buf)
306{
307 unsigned int rcv_pkt, i, j;
308 u16 rxsize;
309
310 /* for long packet */
311 rxsize = (u16)((rx_data & 0x00ffff00) >> 8);
312 dev_dbg(dsim->dev, "mipi dsi rx size : %d\n", rxsize);
313 if (rxsize != req_size) {
314 dev_dbg(dsim->dev,
315 "received size mismatch received: %d, requested: %d\n",
316 rxsize, req_size);
317 goto err;
318 }
319
320 for (i = 0; i < (rxsize >> 2); i++) {
321 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
322 dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
323 for (j = 0; j < 4; j++) {
324 rx_buf[(i * 4) + j] =
325 (u8)(rcv_pkt >> (j * 8)) & 0xff;
326 dev_dbg(dsim->dev, "received value : %02x\n",
327 (rcv_pkt >> (j * 8)) & 0xff);
328 }
329 }
330 if (rxsize % 4) {
331 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
332 dev_dbg(dsim->dev, "received pkt : %08x\n", rcv_pkt);
333 for (j = 0; j < (rxsize % 4); j++) {
334 rx_buf[(i * 4) + j] =
335 (u8)(rcv_pkt >> (j * 8)) & 0xff;
336 dev_dbg(dsim->dev, "received value : %02x\n",
337 (rcv_pkt >> (j * 8)) & 0xff);
338 }
339 }
340
341 return rxsize;
342
343err:
344 return -EINVAL;
345}
346
347static unsigned int exynos_mipi_dsi_response_size(unsigned int req_size)
348{
349 switch (req_size) {
350 case 1:
351 return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE;
352 case 2:
353 return MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE;
354 default:
355 return MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE;
356 }
357}
358
359int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
360 unsigned int data0, unsigned int req_size, u8 *rx_buf)
361{
362 unsigned int rx_data, rcv_pkt, i;
363 u8 response = 0;
364 u16 rxsize;
365
366 if (dsim->state == DSIM_STATE_ULPS) {
367 dev_err(dsim->dev, "state is ULPS.\n");
368
369 return -EINVAL;
370 }
371
372 /* FIXME!!! */
373 msleep(20);
374
375 mutex_lock(&dsim->lock);
376 INIT_COMPLETION(dsim_rd_comp);
377 exynos_mipi_dsi_rd_tx_header(dsim,
378 MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, req_size);
379
380 response = exynos_mipi_dsi_response_size(req_size);
381
382 switch (data_id) {
383 case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
384 case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
385 case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
386 case MIPI_DSI_DCS_READ:
387 exynos_mipi_dsi_rd_tx_header(dsim,
388 data_id, data0);
389 /* process response func should be implemented. */
390 break;
391 default:
392 dev_warn(dsim->dev,
393 "data id %x is not supported current DSI spec.\n",
394 data_id);
395
396 return -EINVAL;
397 }
398
399 if (!wait_for_completion_interruptible_timeout(&dsim_rd_comp,
400 MIPI_FIFO_TIMEOUT)) {
401 pr_err("RX done interrupt timeout\n");
402 mutex_unlock(&dsim->lock);
403 return 0;
404 }
405
406 msleep(20);
407
408 rx_data = exynos_mipi_dsi_rd_rx_fifo(dsim);
409
410 if ((u8)(rx_data & 0xff) != response) {
411 printk(KERN_ERR
412 "mipi dsi wrong response rx_data : %x, response:%x\n",
413 rx_data, response);
414 goto clear_rx_fifo;
415 }
416
417 if (req_size <= 2) {
418 /* for short packet */
419 for (i = 0; i < req_size; i++)
420 rx_buf[i] = (rx_data >> (8 + (i * 8))) & 0xff;
421 rxsize = req_size;
422 } else {
423 /* for long packet */
424 rxsize = exynos_mipi_dsi_long_data_rd(dsim, req_size, rx_data,
425 rx_buf);
426 if (rxsize != req_size)
427 goto clear_rx_fifo;
428 }
429
430 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
431
432 msleep(20);
433
434 if (rcv_pkt != MIPI_RX_FIFO_READ_DONE) {
435 dev_info(dsim->dev,
436 "Can't found RX FIFO READ DONE FLAG : %x\n", rcv_pkt);
437 goto clear_rx_fifo;
438 }
439
440 mutex_unlock(&dsim->lock);
441
442 return rxsize;
443
444clear_rx_fifo:
445 i = 0;
446 while (1) {
447 rcv_pkt = exynos_mipi_dsi_rd_rx_fifo(dsim);
448 if ((rcv_pkt == MIPI_RX_FIFO_READ_DONE)
449 || (i > MIPI_MAX_RX_FIFO))
450 break;
451 dev_dbg(dsim->dev,
452 "mipi dsi clear rx fifo : %08x\n", rcv_pkt);
453 i++;
454 }
455 dev_info(dsim->dev,
456 "mipi dsi rx done count : %d, rcv_pkt : %08x\n", i, rcv_pkt);
457
458 mutex_unlock(&dsim->lock);
459
460 return 0;
461}
462
463static int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim,
464 unsigned int enable)
465{
466 int sw_timeout;
467
468 if (enable) {
469 sw_timeout = 1000;
470
471 exynos_mipi_dsi_enable_pll(dsim, 1);
472 while (1) {
473 sw_timeout--;
474 if (exynos_mipi_dsi_is_pll_stable(dsim))
475 return 0;
476 if (sw_timeout == 0)
477 return -EINVAL;
478 }
479 } else
480 exynos_mipi_dsi_enable_pll(dsim, 0);
481
482 return 0;
483}
484
485static unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim,
486 unsigned int pre_divider, unsigned int main_divider,
487 unsigned int scaler)
488{
489 unsigned long dfin_pll, dfvco, dpll_out;
490 unsigned int i, freq_band = 0xf;
491
492 dfin_pll = (FIN_HZ / pre_divider);
493
494 /******************************************************
495 * Serial Clock(=ByteClk X 8) FreqBand[3:0] *
496 ******************************************************
497 * ~ 99.99 MHz 0000
498 * 100 ~ 119.99 MHz 0001
499 * 120 ~ 159.99 MHz 0010
500 * 160 ~ 199.99 MHz 0011
501 * 200 ~ 239.99 MHz 0100
502 * 140 ~ 319.99 MHz 0101
503 * 320 ~ 389.99 MHz 0110
504 * 390 ~ 449.99 MHz 0111
505 * 450 ~ 509.99 MHz 1000
506 * 510 ~ 559.99 MHz 1001
507 * 560 ~ 639.99 MHz 1010
508 * 640 ~ 689.99 MHz 1011
509 * 690 ~ 769.99 MHz 1100
510 * 770 ~ 869.99 MHz 1101
511 * 870 ~ 949.99 MHz 1110
512 * 950 ~ 1000 MHz 1111
513 ******************************************************/
514 if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) {
515 dev_warn(dsim->dev, "fin_pll range should be 6MHz ~ 12MHz\n");
516 exynos_mipi_dsi_enable_afc(dsim, 0, 0);
517 } else {
518 if (dfin_pll < 7 * MHZ)
519 exynos_mipi_dsi_enable_afc(dsim, 1, 0x1);
520 else if (dfin_pll < 8 * MHZ)
521 exynos_mipi_dsi_enable_afc(dsim, 1, 0x0);
522 else if (dfin_pll < 9 * MHZ)
523 exynos_mipi_dsi_enable_afc(dsim, 1, 0x3);
524 else if (dfin_pll < 10 * MHZ)
525 exynos_mipi_dsi_enable_afc(dsim, 1, 0x2);
526 else if (dfin_pll < 11 * MHZ)
527 exynos_mipi_dsi_enable_afc(dsim, 1, 0x5);
528 else
529 exynos_mipi_dsi_enable_afc(dsim, 1, 0x4);
530 }
531
532 dfvco = dfin_pll * main_divider;
533 dev_dbg(dsim->dev, "dfvco = %lu, dfin_pll = %lu, main_divider = %d\n",
534 dfvco, dfin_pll, main_divider);
535 if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ)
536 dev_warn(dsim->dev, "fvco range should be 500MHz ~ 1000MHz\n");
537
538 dpll_out = dfvco / (1 << scaler);
539 dev_dbg(dsim->dev, "dpll_out = %lu, dfvco = %lu, scaler = %d\n",
540 dpll_out, dfvco, scaler);
541
542 for (i = 0; i < ARRAY_SIZE(dpll_table); i++) {
543 if (dpll_out < dpll_table[i] * MHZ) {
544 freq_band = i;
545 break;
546 }
547 }
548
549 dev_dbg(dsim->dev, "freq_band = %d\n", freq_band);
550
551 exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler);
552
553 exynos_mipi_dsi_hs_zero_ctrl(dsim, 0);
554 exynos_mipi_dsi_prep_ctrl(dsim, 0);
555
556 /* Freq Band */
557 exynos_mipi_dsi_pll_freq_band(dsim, freq_band);
558
559 /* Stable time */
560 exynos_mipi_dsi_pll_stable_time(dsim, dsim->dsim_config->pll_stable_time);
561
562 /* Enable PLL */
563 dev_dbg(dsim->dev, "FOUT of mipi dphy pll is %luMHz\n",
564 (dpll_out / MHZ));
565
566 return dpll_out;
567}
568
569static int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim,
570 unsigned int byte_clk_sel, unsigned int enable)
571{
572 unsigned int esc_div;
573 unsigned long esc_clk_error_rate;
574 unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0;
575
576 if (enable) {
577 dsim->e_clk_src = byte_clk_sel;
578
579 /* Escape mode clock and byte clock source */
580 exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel);
581
582 /* DPHY, DSIM Link : D-PHY clock out */
583 if (byte_clk_sel == DSIM_PLL_OUT_DIV8) {
584 hs_clk = exynos_mipi_dsi_change_pll(dsim,
585 dsim->dsim_config->p, dsim->dsim_config->m,
586 dsim->dsim_config->s);
587 if (hs_clk == 0) {
588 dev_err(dsim->dev,
589 "failed to get hs clock.\n");
590 return -EINVAL;
591 }
592
593 byte_clk = hs_clk / 8;
594 exynos_mipi_dsi_enable_pll_bypass(dsim, 0);
595 exynos_mipi_dsi_pll_on(dsim, 1);
596 /* DPHY : D-PHY clock out, DSIM link : external clock out */
597 } else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) {
598 dev_warn(dsim->dev, "this project is not support\n");
599 dev_warn(dsim->dev,
600 "external clock source for MIPI DSIM.\n");
601 } else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) {
602 dev_warn(dsim->dev, "this project is not support\n");
603 dev_warn(dsim->dev,
604 "external clock source for MIPI DSIM\n");
605 }
606
607 /* escape clock divider */
608 esc_div = byte_clk / (dsim->dsim_config->esc_clk);
609 dev_dbg(dsim->dev,
610 "esc_div = %d, byte_clk = %lu, esc_clk = %lu\n",
611 esc_div, byte_clk, dsim->dsim_config->esc_clk);
612 if ((byte_clk / esc_div) >= (20 * MHZ) ||
613 (byte_clk / esc_div) >
614 dsim->dsim_config->esc_clk)
615 esc_div += 1;
616
617 escape_clk = byte_clk / esc_div;
618 dev_dbg(dsim->dev,
619 "escape_clk = %lu, byte_clk = %lu, esc_div = %d\n",
620 escape_clk, byte_clk, esc_div);
621
622 /* enable escape clock. */
623 exynos_mipi_dsi_enable_byte_clock(dsim, 1);
624
625 /* enable byte clk and escape clock */
626 exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div);
627 /* escape clock on lane */
628 exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
629 (DSIM_LANE_CLOCK | dsim->data_lane), 1);
630
631 dev_dbg(dsim->dev, "byte clock is %luMHz\n",
632 (byte_clk / MHZ));
633 dev_dbg(dsim->dev, "escape clock that user's need is %lu\n",
634 (dsim->dsim_config->esc_clk / MHZ));
635 dev_dbg(dsim->dev, "escape clock divider is %x\n", esc_div);
636 dev_dbg(dsim->dev, "escape clock is %luMHz\n",
637 ((byte_clk / esc_div) / MHZ));
638
639 if ((byte_clk / esc_div) > escape_clk) {
640 esc_clk_error_rate = escape_clk /
641 (byte_clk / esc_div);
642 dev_warn(dsim->dev, "error rate is %lu over.\n",
643 (esc_clk_error_rate / 100));
644 } else if ((byte_clk / esc_div) < (escape_clk)) {
645 esc_clk_error_rate = (byte_clk / esc_div) /
646 escape_clk;
647 dev_warn(dsim->dev, "error rate is %lu under.\n",
648 (esc_clk_error_rate / 100));
649 }
650 } else {
651 exynos_mipi_dsi_enable_esc_clk_on_lane(dsim,
652 (DSIM_LANE_CLOCK | dsim->data_lane), 0);
653 exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0);
654
655 /* disable escape clock. */
656 exynos_mipi_dsi_enable_byte_clock(dsim, 0);
657
658 if (byte_clk_sel == DSIM_PLL_OUT_DIV8)
659 exynos_mipi_dsi_pll_on(dsim, 0);
660 }
661
662 return 0;
663}
664
665int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim)
666{
667 dsim->state = DSIM_STATE_INIT;
668
669 switch (dsim->dsim_config->e_no_data_lane) {
670 case DSIM_DATA_LANE_1:
671 dsim->data_lane = DSIM_LANE_DATA0;
672 break;
673 case DSIM_DATA_LANE_2:
674 dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1;
675 break;
676 case DSIM_DATA_LANE_3:
677 dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
678 DSIM_LANE_DATA2;
679 break;
680 case DSIM_DATA_LANE_4:
681 dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 |
682 DSIM_LANE_DATA2 | DSIM_LANE_DATA3;
683 break;
684 default:
685 dev_info(dsim->dev, "data lane is invalid.\n");
686 return -EINVAL;
687 };
688
689 exynos_mipi_dsi_sw_reset(dsim);
690 exynos_mipi_dsi_func_reset(dsim);
691
692 exynos_mipi_dsi_dp_dn_swap(dsim, 0);
693
694 return 0;
695}
696
697void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim)
698{
699 unsigned int src = 0;
700
701 src = (INTSRC_SFR_FIFO_EMPTY | INTSRC_RX_DATA_DONE);
702 exynos_mipi_dsi_set_interrupt(dsim, src, 1);
703
704 src = 0;
705 src = ~(INTMSK_RX_DONE | INTMSK_FIFO_EMPTY);
706 exynos_mipi_dsi_set_interrupt_mask(dsim, src, 1);
707}
708
709int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
710 unsigned int enable)
711{
712 /* enable only frame done interrupt */
713 exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable);
714
715 return 0;
716}
717
718void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
719 unsigned int enable)
720{
721
722 /* consider Main display and Sub display. */
723
724 exynos_mipi_dsi_set_main_stand_by(dsim, enable);
725}
726
727int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
728 struct mipi_dsim_config *dsim_config)
729{
730 struct mipi_dsim_platform_data *dsim_pd;
731 struct fb_videomode *timing;
732
733 dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
734 timing = (struct fb_videomode *)dsim_pd->lcd_panel_info;
735
736 /* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */
737 if (dsim_config->e_interface == (u32) DSIM_VIDEO) {
738 if (dsim_config->auto_vertical_cnt == 0) {
739 exynos_mipi_dsi_set_main_disp_vporch(dsim,
740 dsim_config->cmd_allow,
741 timing->upper_margin,
742 timing->lower_margin);
743 exynos_mipi_dsi_set_main_disp_hporch(dsim,
744 timing->left_margin,
745 timing->right_margin);
746 exynos_mipi_dsi_set_main_disp_sync_area(dsim,
747 timing->vsync_len,
748 timing->hsync_len);
749 }
750 }
751
752 exynos_mipi_dsi_set_main_disp_resol(dsim, timing->xres,
753 timing->yres);
754
755 exynos_mipi_dsi_display_config(dsim, dsim_config);
756
757 dev_info(dsim->dev, "lcd panel ==> width = %d, height = %d\n",
758 timing->xres, timing->yres);
759
760 return 0;
761}
762
763int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim)
764{
765 unsigned int time_out = 100;
766
767 switch (dsim->state) {
768 case DSIM_STATE_INIT:
769 exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f);
770
771 /* dsi configuration */
772 exynos_mipi_dsi_init_config(dsim);
773 exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1);
774 exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1);
775
776 /* set clock configuration */
777 exynos_mipi_dsi_set_clock(dsim, dsim->dsim_config->e_byte_clk, 1);
778
779 /* check clock and data lane state are stop state */
780 while (!(exynos_mipi_dsi_is_lane_state(dsim))) {
781 time_out--;
782 if (time_out == 0) {
783 dev_err(dsim->dev,
784 "DSI Master is not stop state.\n");
785 dev_err(dsim->dev,
786 "Check initialization process\n");
787
788 return -EINVAL;
789 }
790 }
791 if (time_out != 0) {
792 dev_info(dsim->dev,
793 "DSI Master driver has been completed.\n");
794 dev_info(dsim->dev, "DSI Master state is stop state\n");
795 }
796
797 dsim->state = DSIM_STATE_STOP;
798
799 /* BTA sequence counters */
800 exynos_mipi_dsi_set_stop_state_counter(dsim,
801 dsim->dsim_config->stop_holding_cnt);
802 exynos_mipi_dsi_set_bta_timeout(dsim,
803 dsim->dsim_config->bta_timeout);
804 exynos_mipi_dsi_set_lpdr_timeout(dsim,
805 dsim->dsim_config->rx_timeout);
806
807 return 0;
808 default:
809 dev_info(dsim->dev, "DSI Master is already init.\n");
810 return 0;
811 }
812
813 return 0;
814}
815
816int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim)
817{
818 if (dsim->state != DSIM_STATE_STOP) {
819 dev_warn(dsim->dev, "DSIM is not in stop state.\n");
820 return 0;
821 }
822
823 if (dsim->e_clk_src == DSIM_EXT_CLK_BYPASS) {
824 dev_warn(dsim->dev, "clock source is external bypass.\n");
825 return 0;
826 }
827
828 dsim->state = DSIM_STATE_HSCLKEN;
829
830 /* set LCDC and CPU transfer mode to HS. */
831 exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
832 exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
833 exynos_mipi_dsi_enable_hs_clock(dsim, 1);
834
835 return 0;
836}
837
838int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
839 unsigned int mode)
840{
841 if (mode) {
842 if (dsim->state != DSIM_STATE_HSCLKEN) {
843 dev_err(dsim->dev, "HS Clock lane is not enabled.\n");
844 return -EINVAL;
845 }
846
847 exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0);
848 } else {
849 if (dsim->state == DSIM_STATE_INIT || dsim->state ==
850 DSIM_STATE_ULPS) {
851 dev_err(dsim->dev,
852 "DSI Master is not STOP or HSDT state.\n");
853 return -EINVAL;
854 }
855
856 exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0);
857 }
858
859 return 0;
860}
861
862int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
863{
864 return _exynos_mipi_dsi_get_frame_done_status(dsim);
865}
866
867int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
868{
869 _exynos_mipi_dsi_clear_frame_done(dsim);
870
871 return 0;
872}
873
874int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
875 unsigned int val)
876{
877 int try = TRY_FIFO_CLEAR;
878
879 exynos_mipi_dsi_sw_reset_release(dsim);
880 exynos_mipi_dsi_func_reset(dsim);
881
882 do {
883 if (exynos_mipi_dsi_get_sw_reset_release(dsim)) {
884 exynos_mipi_dsi_init_interrupt(dsim);
885 dev_dbg(dsim->dev, "reset release done.\n");
886 return 0;
887 }
888 } while (--try);
889
890 dev_err(dsim->dev, "failed to clear dsim fifo.\n");
891 return -EAGAIN;
892}
893
894MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
895MODULE_DESCRIPTION("Samusung SoC MIPI-DSI common driver");
896MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/exynos/exynos_mipi_dsi_common.h
new file mode 100644
index 000000000000..412552274df3
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.h
@@ -0,0 +1,46 @@
1/* linux/drivers/video/exynos_mipi_dsi_common.h
2 *
3 * Header file for Samsung SoC MIPI-DSI common driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSI_COMMON_H
16#define _EXYNOS_MIPI_DSI_COMMON_H
17
18static DECLARE_COMPLETION(dsim_rd_comp);
19static DECLARE_COMPLETION(dsim_wr_comp);
20
21int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
22 const unsigned char *data0, unsigned int data_size);
23int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
24 unsigned int data0, unsigned int req_size, u8 *rx_buf);
25irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id);
26void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim);
27int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim);
28void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
29 unsigned int enable);
30int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
31 struct mipi_dsim_config *dsim_info);
32int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim);
33int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim);
34int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
35 unsigned int mode);
36int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
37 unsigned int enable);
38int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
39int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
40
41extern struct fb_info *registered_fb[FB_MAX] __read_mostly;
42
43int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
44 unsigned int val);
45
46#endif /* _EXYNOS_MIPI_DSI_COMMON_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
new file mode 100644
index 000000000000..0ef38ce72af6
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
@@ -0,0 +1,618 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
2 *
3 * Samsung SoC MIPI-DSI lowlevel driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae, <inki.dae@samsung.com>
8 * Donghwa Lee, <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/errno.h>
18#include <linux/mutex.h>
19#include <linux/wait.h>
20#include <linux/delay.h>
21#include <linux/fs.h>
22#include <linux/mm.h>
23#include <linux/ctype.h>
24#include <linux/io.h>
25
26#include <video/exynos_mipi_dsim.h>
27
28#include <mach/map.h>
29
30#include "exynos_mipi_dsi_regs.h"
31
32void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
33{
34 unsigned int reg;
35
36 reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
37
38 reg |= DSIM_FUNCRST;
39
40 writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
41}
42
43void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim)
44{
45 unsigned int reg;
46
47 reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
48
49 reg |= DSIM_SWRST;
50
51 writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
52}
53
54void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim)
55{
56 unsigned int reg;
57
58 reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
59
60 reg |= INTSRC_SW_RST_RELEASE;
61
62 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
63}
64
65int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim)
66{
67 return (readl(dsim->reg_base + EXYNOS_DSIM_INTSRC)) &
68 INTSRC_SW_RST_RELEASE;
69}
70
71unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim)
72{
73 unsigned int reg;
74
75 reg = readl(dsim->reg_base + EXYNOS_DSIM_INTMSK);
76
77 return reg;
78}
79
80void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
81 unsigned int mode, unsigned int mask)
82{
83 unsigned int reg = 0;
84
85 if (mask)
86 reg |= mode;
87 else
88 reg &= ~mode;
89
90 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTMSK);
91}
92
93void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
94 unsigned int cfg)
95{
96 unsigned int reg;
97
98 reg = readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
99
100 writel(reg & ~(cfg), dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
101 mdelay(10);
102 reg |= cfg;
103
104 writel(reg, dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
105}
106
107/*
108 * this function set PLL P, M and S value in D-PHY
109 */
110void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
111 unsigned int value)
112{
113 writel(DSIM_AFC_CTL(value), dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
114}
115
116void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
117 unsigned int enable)
118{
119 unsigned int reg;
120
121 reg = readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL);
122
123 reg &= ~DSIM_MAIN_STAND_BY;
124
125 if (enable)
126 reg |= DSIM_MAIN_STAND_BY;
127
128 writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
129}
130
131void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
132 unsigned int width_resol, unsigned int height_resol)
133{
134 unsigned int reg;
135
136 /* standby should be set after configuration so set to not ready*/
137 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL)) &
138 ~(DSIM_MAIN_STAND_BY);
139 writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
140
141 reg &= ~((0x7ff << 16) | (0x7ff << 0));
142 reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol);
143
144 reg |= DSIM_MAIN_STAND_BY;
145 writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
146}
147
148void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
149 unsigned int cmd_allow, unsigned int vfront, unsigned int vback)
150{
151 unsigned int reg;
152
153 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MVPORCH)) &
154 ~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) |
155 (DSIM_MAIN_VBP_MASK));
156
157 reg |= (DSIM_CMD_ALLOW_SHIFT(cmd_allow & 0xf) |
158 DSIM_STABLE_VFP_SHIFT(vfront & 0x7ff) |
159 DSIM_MAIN_VBP_SHIFT(vback & 0x7ff));
160
161 writel(reg, dsim->reg_base + EXYNOS_DSIM_MVPORCH);
162}
163
164void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
165 unsigned int front, unsigned int back)
166{
167 unsigned int reg;
168
169 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MHPORCH)) &
170 ~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK));
171
172 reg |= DSIM_MAIN_HFP_SHIFT(front) | DSIM_MAIN_HBP_SHIFT(back);
173
174 writel(reg, dsim->reg_base + EXYNOS_DSIM_MHPORCH);
175}
176
177void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
178 unsigned int vert, unsigned int hori)
179{
180 unsigned int reg;
181
182 reg = (readl(dsim->reg_base + EXYNOS_DSIM_MSYNC)) &
183 ~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK));
184
185 reg |= (DSIM_MAIN_VSA_SHIFT(vert & 0x3ff) |
186 DSIM_MAIN_HSA_SHIFT(hori));
187
188 writel(reg, dsim->reg_base + EXYNOS_DSIM_MSYNC);
189}
190
191void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
192 unsigned int vert, unsigned int hori)
193{
194 unsigned int reg;
195
196 reg = (readl(dsim->reg_base + EXYNOS_DSIM_SDRESOL)) &
197 ~(DSIM_SUB_STANDY_MASK);
198
199 writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
200
201 reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK);
202 reg |= (DSIM_SUB_VRESOL_SHIFT(vert & 0x7ff) |
203 DSIM_SUB_HRESOL_SHIFT(hori & 0x7ff));
204 writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
205
206 reg |= DSIM_SUB_STANDY_SHIFT(1);
207 writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
208}
209
210void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim)
211{
212 struct mipi_dsim_config *dsim_config = dsim->dsim_config;
213
214 unsigned int cfg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
215 ~((1 << 28) | (0x1f << 20) | (0x3 << 5));
216
217 cfg = ((DSIM_AUTO_FLUSH(dsim_config->auto_flush)) |
218 (DSIM_EOT_DISABLE(dsim_config->eot_disable)) |
219 (DSIM_AUTO_MODE_SHIFT(dsim_config->auto_vertical_cnt)) |
220 (DSIM_HSE_MODE_SHIFT(dsim_config->hse)) |
221 (DSIM_HFP_MODE_SHIFT(dsim_config->hfp)) |
222 (DSIM_HBP_MODE_SHIFT(dsim_config->hbp)) |
223 (DSIM_HSA_MODE_SHIFT(dsim_config->hsa)) |
224 (DSIM_NUM_OF_DATALANE_SHIFT(dsim_config->e_no_data_lane)));
225
226 writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
227}
228
229void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
230 struct mipi_dsim_config *dsim_config)
231{
232 u32 reg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
233 ~((0x3 << 26) | (1 << 25) | (0x3 << 18) | (0x7 << 12) |
234 (0x3 << 16) | (0x7 << 8));
235
236 if (dsim_config->e_interface == DSIM_VIDEO)
237 reg |= (1 << 25);
238 else if (dsim_config->e_interface == DSIM_COMMAND)
239 reg &= ~(1 << 25);
240 else {
241 dev_err(dsim->dev, "unknown lcd type.\n");
242 return;
243 }
244
245 /* main lcd */
246 reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << 26 |
247 ((u8) (dsim_config->e_virtual_ch) & 0x3) << 18 |
248 ((u8) (dsim_config->e_pixel_format) & 0x7) << 12;
249
250 writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
251}
252
253void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
254 unsigned int enable)
255{
256 unsigned int reg;
257
258 reg = readl(dsim->reg_base + EXYNOS_DSIM_CONFIG);
259
260 if (enable)
261 reg |= DSIM_LANE_ENx(lane);
262 else
263 reg &= ~DSIM_LANE_ENx(lane);
264
265 writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
266}
267
268
269void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
270 unsigned int count)
271{
272 unsigned int cfg;
273
274 /* get the data lane number. */
275 cfg = DSIM_NUM_OF_DATALANE_SHIFT(count);
276
277 writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
278}
279
280void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
281 unsigned int afc_code)
282{
283 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
284
285 if (enable) {
286 reg |= (1 << 14);
287 reg &= ~(0x7 << 5);
288 reg |= (afc_code & 0x7) << 5;
289 } else
290 reg &= ~(1 << 14);
291
292 writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
293}
294
295void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
296 unsigned int enable)
297{
298 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
299 ~(DSIM_PLL_BYPASS_SHIFT(0x1));
300
301 reg |= DSIM_PLL_BYPASS_SHIFT(enable);
302
303 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
304}
305
306void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
307 unsigned int m, unsigned int s)
308{
309 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
310
311 reg |= ((p & 0x3f) << 13) | ((m & 0x1ff) << 4) | ((s & 0x7) << 1);
312
313 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
314}
315
316void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
317 unsigned int freq_band)
318{
319 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
320 ~(DSIM_FREQ_BAND_SHIFT(0x1f));
321
322 reg |= DSIM_FREQ_BAND_SHIFT(freq_band & 0x1f);
323
324 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
325}
326
327void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
328 unsigned int pre_divider, unsigned int main_divider,
329 unsigned int scaler)
330{
331 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
332 ~(0x7ffff << 1);
333
334 reg |= (pre_divider & 0x3f) << 13 | (main_divider & 0x1ff) << 4 |
335 (scaler & 0x7) << 1;
336
337 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
338}
339
340void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
341 unsigned int lock_time)
342{
343 writel(lock_time, dsim->reg_base + EXYNOS_DSIM_PLLTMR);
344}
345
346void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, unsigned int enable)
347{
348 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
349 ~(DSIM_PLL_EN_SHIFT(0x1));
350
351 reg |= DSIM_PLL_EN_SHIFT(enable & 0x1);
352
353 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
354}
355
356void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
357 unsigned int src)
358{
359 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
360 ~(DSIM_BYTE_CLK_SRC_SHIFT(0x3));
361
362 reg |= (DSIM_BYTE_CLK_SRC_SHIFT(src));
363
364 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
365}
366
367void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
368 unsigned int enable)
369{
370 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
371 ~(DSIM_BYTE_CLKEN_SHIFT(0x1));
372
373 reg |= DSIM_BYTE_CLKEN_SHIFT(enable);
374
375 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
376}
377
378void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
379 unsigned int enable, unsigned int prs_val)
380{
381 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
382 ~(DSIM_ESC_CLKEN_SHIFT(0x1) | 0xffff);
383
384 reg |= DSIM_ESC_CLKEN_SHIFT(enable);
385 if (enable)
386 reg |= prs_val;
387
388 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
389}
390
391void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
392 unsigned int lane_sel, unsigned int enable)
393{
394 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
395
396 if (enable)
397 reg |= DSIM_LANE_ESC_CLKEN(lane_sel);
398 else
399
400 reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel);
401
402 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
403}
404
405void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
406 unsigned int enable)
407{
408 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
409 ~(DSIM_FORCE_STOP_STATE_SHIFT(0x1));
410
411 reg |= (DSIM_FORCE_STOP_STATE_SHIFT(enable & 0x1));
412
413 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
414}
415
416unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim)
417{
418 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
419
420 /**
421 * check clock and data lane states.
422 * if MIPI-DSI controller was enabled at bootloader then
423 * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK.
424 * so it should be checked for two case.
425 */
426 if ((reg & DSIM_STOP_STATE_DAT(0xf)) &&
427 ((reg & DSIM_STOP_STATE_CLK) ||
428 (reg & DSIM_TX_READY_HS_CLK)))
429 return 1;
430
431 return 0;
432}
433
434void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
435 unsigned int cnt_val)
436{
437 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
438 ~(DSIM_STOP_STATE_CNT_SHIFT(0x7ff));
439
440 reg |= (DSIM_STOP_STATE_CNT_SHIFT(cnt_val & 0x7ff));
441
442 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
443}
444
445void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
446 unsigned int timeout)
447{
448 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
449 ~(DSIM_BTA_TOUT_SHIFT(0xff));
450
451 reg |= (DSIM_BTA_TOUT_SHIFT(timeout));
452
453 writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
454}
455
456void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
457 unsigned int timeout)
458{
459 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
460 ~(DSIM_LPDR_TOUT_SHIFT(0xffff));
461
462 reg |= (DSIM_LPDR_TOUT_SHIFT(timeout));
463
464 writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
465}
466
467void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
468 unsigned int lp)
469{
470 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
471
472 reg &= ~DSIM_CMD_LPDT_LP;
473
474 if (lp)
475 reg |= DSIM_CMD_LPDT_LP;
476
477 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
478}
479
480void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
481 unsigned int lp)
482{
483 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
484
485 reg &= ~DSIM_TX_LPDT_LP;
486
487 if (lp)
488 reg |= DSIM_TX_LPDT_LP;
489
490 writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
491}
492
493void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
494 unsigned int enable)
495{
496 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
497 ~(DSIM_TX_REQUEST_HSCLK_SHIFT(0x1));
498
499 reg |= DSIM_TX_REQUEST_HSCLK_SHIFT(enable);
500
501 writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
502}
503
504void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
505 unsigned int swap_en)
506{
507 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
508
509 reg &= ~(0x3 << 0);
510 reg |= (swap_en & 0x3) << 0;
511
512 writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
513}
514
515void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
516 unsigned int hs_zero)
517{
518 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
519 ~(0xf << 28);
520
521 reg |= ((hs_zero & 0xf) << 28);
522
523 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
524}
525
526void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
527{
528 unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
529 ~(0x7 << 20);
530
531 reg |= ((prep & 0x7) << 20);
532
533 writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
534}
535
536unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim)
537{
538 return readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
539}
540
541void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
542 unsigned int src)
543{
544 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
545
546 reg |= src;
547
548 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
549}
550
551void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
552 unsigned int src, unsigned int enable)
553{
554 unsigned int reg = 0;
555
556 if (enable)
557 reg |= src;
558 else
559 reg &= ~src;
560
561 writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
562}
563
564unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim)
565{
566 unsigned int reg;
567
568 reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
569
570 return reg & (1 << 31) ? 1 : 0;
571}
572
573unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
574{
575 return readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL) & ~(0x1f);
576}
577
578void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
579 unsigned int di, unsigned int data0, unsigned int data1)
580{
581 unsigned int reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
582
583 writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
584}
585
586void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
587 unsigned int di, unsigned int data0)
588{
589 unsigned int reg = (data0 << 8) | (di << 0);
590
591 writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
592}
593
594unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim)
595{
596 return readl(dsim->reg_base + EXYNOS_DSIM_RXFIFO);
597}
598
599unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
600{
601 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
602
603 return (reg & INTSRC_FRAME_DONE) ? 1 : 0;
604}
605
606void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
607{
608 unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
609
610 writel(reg | INTSRC_FRAME_DONE, dsim->reg_base +
611 EXYNOS_DSIM_INTSRC);
612}
613
614void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
615 unsigned int tx_data)
616{
617 writel(tx_data, dsim->reg_base + EXYNOS_DSIM_PAYLOAD);
618}
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
new file mode 100644
index 000000000000..85460701c7ea
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
@@ -0,0 +1,112 @@
1/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
2 *
3 * Header file for Samsung SoC MIPI-DSI lowlevel driver.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H
16#define _EXYNOS_MIPI_DSI_LOWLEVEL_H
17
18void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim);
19void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim);
20void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim);
21int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim);
22void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
23 unsigned int mode, unsigned int mask);
24void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
25 unsigned int count);
26void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
27 unsigned int cfg);
28void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
29 unsigned int value);
30void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
31 unsigned int value);
32void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
33 unsigned int enable);
34void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
35 unsigned int width_resol, unsigned int height_resol);
36void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
37 unsigned int cmd_allow, unsigned int vfront, unsigned int vback);
38void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
39 unsigned int front, unsigned int back);
40void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
41 unsigned int vert, unsigned int hori);
42void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
43 unsigned int vert, unsigned int hori);
44void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim);
45void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
46 struct mipi_dsim_config *dsim_config);
47void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
48 unsigned int count);
49void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
50 unsigned int enable);
51void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
52 unsigned int afc_code);
53void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
54 unsigned int enable);
55void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
56 unsigned int m, unsigned int s);
57void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
58 unsigned int freq_band);
59void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
60 unsigned int pre_divider, unsigned int main_divider,
61 unsigned int scaler);
62void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
63 unsigned int lock_time);
64void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim,
65 unsigned int enable);
66void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
67 unsigned int src);
68void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
69 unsigned int enable);
70void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
71 unsigned int enable, unsigned int prs_val);
72void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
73 unsigned int lane_sel, unsigned int enable);
74void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
75 unsigned int enable);
76unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim);
77void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
78 unsigned int cnt_val);
79void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
80 unsigned int timeout);
81void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
82 unsigned int timeout);
83void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
84 unsigned int lp);
85void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
86 unsigned int lp);
87void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
88 unsigned int enable);
89void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
90 unsigned int swap_en);
91void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
92 unsigned int hs_zero);
93void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep);
94unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim);
95unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim);
96void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
97 unsigned int src);
98void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
99 unsigned int src, unsigned int enable);
100unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
101unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);
102unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
103void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
104void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, unsigned int di,
105 unsigned int data0, unsigned int data1);
106void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
107 unsigned int tx_data);
108void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
109 unsigned int data0, unsigned int data1);
110unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim);
111
112#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */
diff --git a/drivers/video/exynos/exynos_mipi_dsi_regs.h b/drivers/video/exynos/exynos_mipi_dsi_regs.h
new file mode 100644
index 000000000000..4227106d3fd0
--- /dev/null
+++ b/drivers/video/exynos/exynos_mipi_dsi_regs.h
@@ -0,0 +1,149 @@
1/* linux/driver/video/exynos/exynos_mipi_dsi_regs.h
2 *
3 * Register definition file for Samsung MIPI-DSIM driver
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSI_REGS_H
16#define _EXYNOS_MIPI_DSI_REGS_H
17
18#define EXYNOS_DSIM_STATUS 0x0 /* Status register */
19#define EXYNOS_DSIM_SWRST 0x4 /* Software reset register */
20#define EXYNOS_DSIM_CLKCTRL 0x8 /* Clock control register */
21#define EXYNOS_DSIM_TIMEOUT 0xc /* Time out register */
22#define EXYNOS_DSIM_CONFIG 0x10 /* Configuration register */
23#define EXYNOS_DSIM_ESCMODE 0x14 /* Escape mode register */
24
25/* Main display image resolution register */
26#define EXYNOS_DSIM_MDRESOL 0x18
27#define EXYNOS_DSIM_MVPORCH 0x1c /* Main display Vporch register */
28#define EXYNOS_DSIM_MHPORCH 0x20 /* Main display Hporch register */
29#define EXYNOS_DSIM_MSYNC 0x24 /* Main display sync area register */
30
31/* Sub display image resolution register */
32#define EXYNOS_DSIM_SDRESOL 0x28
33#define EXYNOS_DSIM_INTSRC 0x2c /* Interrupt source register */
34#define EXYNOS_DSIM_INTMSK 0x30 /* Interrupt mask register */
35#define EXYNOS_DSIM_PKTHDR 0x34 /* Packet Header FIFO register */
36#define EXYNOS_DSIM_PAYLOAD 0x38 /* Payload FIFO register */
37#define EXYNOS_DSIM_RXFIFO 0x3c /* Read FIFO register */
38#define EXYNOS_DSIM_FIFOTHLD 0x40 /* FIFO threshold level register */
39#define EXYNOS_DSIM_FIFOCTRL 0x44 /* FIFO status and control register */
40
41/* FIFO memory AC characteristic register */
42#define EXYNOS_DSIM_PLLCTRL 0x4c /* PLL control register */
43#define EXYNOS_DSIM_PLLTMR 0x50 /* PLL timer register */
44#define EXYNOS_DSIM_PHYACCHR 0x54 /* D-PHY AC characteristic register */
45#define EXYNOS_DSIM_PHYACCHR1 0x58 /* D-PHY AC characteristic register1 */
46
47/* DSIM_STATUS */
48#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
49#define DSIM_STOP_STATE_CLK (1 << 8)
50#define DSIM_TX_READY_HS_CLK (1 << 10)
51
52/* DSIM_SWRST */
53#define DSIM_FUNCRST (1 << 16)
54#define DSIM_SWRST (1 << 0)
55
56/* EXYNOS_DSIM_TIMEOUT */
57#define DSIM_LPDR_TOUT_SHIFT(x) ((x) << 0)
58#define DSIM_BTA_TOUT_SHIFT(x) ((x) << 16)
59
60/* EXYNOS_DSIM_CLKCTRL */
61#define DSIM_LANE_ESC_CLKEN(x) (((x) & 0x1f) << 19)
62#define DSIM_BYTE_CLKEN_SHIFT(x) ((x) << 24)
63#define DSIM_BYTE_CLK_SRC_SHIFT(x) ((x) << 25)
64#define DSIM_PLL_BYPASS_SHIFT(x) ((x) << 27)
65#define DSIM_ESC_CLKEN_SHIFT(x) ((x) << 28)
66#define DSIM_TX_REQUEST_HSCLK_SHIFT(x) ((x) << 31)
67
68/* EXYNOS_DSIM_CONFIG */
69#define DSIM_LANE_ENx(x) (((x) & 0x1f) << 0)
70#define DSIM_NUM_OF_DATALANE_SHIFT(x) ((x) << 5)
71#define DSIM_HSA_MODE_SHIFT(x) ((x) << 20)
72#define DSIM_HBP_MODE_SHIFT(x) ((x) << 21)
73#define DSIM_HFP_MODE_SHIFT(x) ((x) << 22)
74#define DSIM_HSE_MODE_SHIFT(x) ((x) << 23)
75#define DSIM_AUTO_MODE_SHIFT(x) ((x) << 24)
76#define DSIM_EOT_DISABLE(x) ((x) << 28)
77#define DSIM_AUTO_FLUSH(x) ((x) << 29)
78
79#define DSIM_NUM_OF_DATA_LANE(x) ((x) << DSIM_NUM_OF_DATALANE_SHIFT)
80
81/* EXYNOS_DSIM_ESCMODE */
82#define DSIM_TX_LPDT_LP (1 << 6)
83#define DSIM_CMD_LPDT_LP (1 << 7)
84#define DSIM_FORCE_STOP_STATE_SHIFT(x) ((x) << 20)
85#define DSIM_STOP_STATE_CNT_SHIFT(x) ((x) << 21)
86
87/* EXYNOS_DSIM_MDRESOL */
88#define DSIM_MAIN_STAND_BY (1 << 31)
89#define DSIM_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
90#define DSIM_MAIN_HRESOL(x) (((x) & 0X7ff) << 0)
91
92/* EXYNOS_DSIM_MVPORCH */
93#define DSIM_CMD_ALLOW_SHIFT(x) ((x) << 28)
94#define DSIM_STABLE_VFP_SHIFT(x) ((x) << 16)
95#define DSIM_MAIN_VBP_SHIFT(x) ((x) << 0)
96#define DSIM_CMD_ALLOW_MASK (0xf << 28)
97#define DSIM_STABLE_VFP_MASK (0x7ff << 16)
98#define DSIM_MAIN_VBP_MASK (0x7ff << 0)
99
100/* EXYNOS_DSIM_MHPORCH */
101#define DSIM_MAIN_HFP_SHIFT(x) ((x) << 16)
102#define DSIM_MAIN_HBP_SHIFT(x) ((x) << 0)
103#define DSIM_MAIN_HFP_MASK ((0xffff) << 16)
104#define DSIM_MAIN_HBP_MASK ((0xffff) << 0)
105
106/* EXYNOS_DSIM_MSYNC */
107#define DSIM_MAIN_VSA_SHIFT(x) ((x) << 22)
108#define DSIM_MAIN_HSA_SHIFT(x) ((x) << 0)
109#define DSIM_MAIN_VSA_MASK ((0x3ff) << 22)
110#define DSIM_MAIN_HSA_MASK ((0xffff) << 0)
111
112/* EXYNOS_DSIM_SDRESOL */
113#define DSIM_SUB_STANDY_SHIFT(x) ((x) << 31)
114#define DSIM_SUB_VRESOL_SHIFT(x) ((x) << 16)
115#define DSIM_SUB_HRESOL_SHIFT(x) ((x) << 0)
116#define DSIM_SUB_STANDY_MASK ((0x1) << 31)
117#define DSIM_SUB_VRESOL_MASK ((0x7ff) << 16)
118#define DSIM_SUB_HRESOL_MASK ((0x7ff) << 0)
119
120/* EXYNOS_DSIM_INTSRC */
121#define INTSRC_PLL_STABLE (1 << 31)
122#define INTSRC_SW_RST_RELEASE (1 << 30)
123#define INTSRC_SFR_FIFO_EMPTY (1 << 29)
124#define INTSRC_FRAME_DONE (1 << 24)
125#define INTSRC_RX_DATA_DONE (1 << 18)
126
127/* EXYNOS_DSIM_INTMSK */
128#define INTMSK_FIFO_EMPTY (1 << 29)
129#define INTMSK_BTA (1 << 25)
130#define INTMSK_FRAME_DONE (1 << 24)
131#define INTMSK_RX_TIMEOUT (1 << 21)
132#define INTMSK_BTA_TIMEOUT (1 << 20)
133#define INTMSK_RX_DONE (1 << 18)
134#define INTMSK_RX_TE (1 << 17)
135#define INTMSK_RX_ACK (1 << 16)
136#define INTMSK_RX_ECC_ERR (1 << 15)
137#define INTMSK_RX_CRC_ERR (1 << 14)
138
139/* EXYNOS_DSIM_FIFOCTRL */
140#define SFR_HEADER_EMPTY (1 << 22)
141
142/* EXYNOS_DSIM_PHYACCHR */
143#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
144
145/* EXYNOS_DSIM_PLLCTRL */
146#define DSIM_PLL_EN_SHIFT(x) ((x) << 23)
147#define DSIM_FREQ_BAND_SHIFT(x) ((x) << 24)
148
149#endif /* _EXYNOS_MIPI_DSI_REGS_H */
diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/exynos/s6e8ax0.c
new file mode 100644
index 000000000000..4aa9ac6218bf
--- /dev/null
+++ b/drivers/video/exynos/s6e8ax0.c
@@ -0,0 +1,898 @@
1/* linux/drivers/video/exynos/s6e8ax0.c
2 *
3 * MIPI-DSI based s6e8ax0 AMOLED lcd 4.65 inch panel driver.
4 *
5 * Inki Dae, <inki.dae@samsung.com>
6 * Donghwa Lee, <dh09.lee@samsung.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11*/
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/mutex.h>
17#include <linux/wait.h>
18#include <linux/ctype.h>
19#include <linux/io.h>
20#include <linux/delay.h>
21#include <linux/irq.h>
22#include <linux/interrupt.h>
23#include <linux/lcd.h>
24#include <linux/fb.h>
25#include <linux/backlight.h>
26#include <linux/regulator/consumer.h>
27
28#include <video/mipi_display.h>
29#include <video/exynos_mipi_dsim.h>
30
31#define LDI_MTP_LENGTH 24
32#define DSIM_PM_STABLE_TIME 10
33#define MIN_BRIGHTNESS 0
34#define MAX_BRIGHTNESS 24
35#define GAMMA_TABLE_COUNT 26
36
37#define POWER_IS_ON(pwr) ((pwr) == FB_BLANK_UNBLANK)
38#define POWER_IS_OFF(pwr) ((pwr) == FB_BLANK_POWERDOWN)
39#define POWER_IS_NRM(pwr) ((pwr) == FB_BLANK_NORMAL)
40
41#define lcd_to_master(a) (a->dsim_dev->master)
42#define lcd_to_master_ops(a) ((lcd_to_master(a))->master_ops)
43
44enum {
45 DSIM_NONE_STATE = 0,
46 DSIM_RESUME_COMPLETE = 1,
47 DSIM_FRAME_DONE = 2,
48};
49
50struct s6e8ax0 {
51 struct device *dev;
52 unsigned int power;
53 unsigned int id;
54 unsigned int gamma;
55 unsigned int acl_enable;
56 unsigned int cur_acl;
57
58 struct lcd_device *ld;
59 struct backlight_device *bd;
60
61 struct mipi_dsim_lcd_device *dsim_dev;
62 struct lcd_platform_data *ddi_pd;
63 struct mutex lock;
64 bool enabled;
65};
66
67
68static struct regulator_bulk_data supplies[] = {
69 { .supply = "vdd3", },
70 { .supply = "vci", },
71};
72
73static void s6e8ax0_regulator_enable(struct s6e8ax0 *lcd)
74{
75 int ret = 0;
76 struct lcd_platform_data *pd = NULL;
77
78 pd = lcd->ddi_pd;
79 mutex_lock(&lcd->lock);
80 if (!lcd->enabled) {
81 ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
82 if (ret)
83 goto out;
84
85 lcd->enabled = true;
86 }
87 msleep(pd->power_on_delay);
88out:
89 mutex_unlock(&lcd->lock);
90}
91
92static void s6e8ax0_regulator_disable(struct s6e8ax0 *lcd)
93{
94 int ret = 0;
95
96 mutex_lock(&lcd->lock);
97 if (lcd->enabled) {
98 ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
99 if (ret)
100 goto out;
101
102 lcd->enabled = false;
103 }
104out:
105 mutex_unlock(&lcd->lock);
106}
107
108static const unsigned char s6e8ax0_22_gamma_30[] = {
109 0xfa, 0x01, 0x60, 0x10, 0x60, 0xf5, 0x00, 0xff, 0xad, 0xaf,
110 0xbA, 0xc3, 0xd8, 0xc5, 0x9f, 0xc6, 0x9e, 0xc1, 0xdc, 0xc0,
111 0x00, 0x61, 0x00, 0x5a, 0x00, 0x74,
112};
113
114static const unsigned char s6e8ax0_22_gamma_50[] = {
115 0xfa, 0x01, 0x60, 0x10, 0x60, 0xe8, 0x1f, 0xf7, 0xad, 0xc0,
116 0xb5, 0xc4, 0xdc, 0xc4, 0x9e, 0xc6, 0x9c, 0xbb, 0xd8, 0xbb,
117 0x00, 0x70, 0x00, 0x68, 0x00, 0x86,
118};
119
120static const unsigned char s6e8ax0_22_gamma_60[] = {
121 0xfa, 0x01, 0x60, 0x10, 0x60, 0xde, 0x1f, 0xef, 0xad, 0xc4,
122 0xb3, 0xc3, 0xdd, 0xc4, 0x9e, 0xc6, 0x9c, 0xbc, 0xd6, 0xba,
123 0x00, 0x75, 0x00, 0x6e, 0x00, 0x8d,
124};
125
126static const unsigned char s6e8ax0_22_gamma_70[] = {
127 0xfa, 0x01, 0x60, 0x10, 0x60, 0xd8, 0x1f, 0xe7, 0xaf, 0xc8,
128 0xb4, 0xc4, 0xdd, 0xc3, 0x9d, 0xc6, 0x9c, 0xbb, 0xd6, 0xb9,
129 0x00, 0x7a, 0x00, 0x72, 0x00, 0x93,
130};
131
132static const unsigned char s6e8ax0_22_gamma_80[] = {
133 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc9, 0x1f, 0xde, 0xae, 0xc9,
134 0xb1, 0xc3, 0xdd, 0xc2, 0x9d, 0xc5, 0x9b, 0xbc, 0xd6, 0xbb,
135 0x00, 0x7f, 0x00, 0x77, 0x00, 0x99,
136};
137
138static const unsigned char s6e8ax0_22_gamma_90[] = {
139 0xfa, 0x01, 0x60, 0x10, 0x60, 0xc7, 0x1f, 0xd9, 0xb0, 0xcc,
140 0xb2, 0xc3, 0xdc, 0xc1, 0x9c, 0xc6, 0x9c, 0xbc, 0xd4, 0xb9,
141 0x00, 0x83, 0x00, 0x7b, 0x00, 0x9e,
142};
143
144static const unsigned char s6e8ax0_22_gamma_100[] = {
145 0xfa, 0x01, 0x60, 0x10, 0x60, 0xbd, 0x80, 0xcd, 0xba, 0xce,
146 0xb3, 0xc4, 0xde, 0xc3, 0x9c, 0xc4, 0x9, 0xb8, 0xd3, 0xb6,
147 0x00, 0x88, 0x00, 0x80, 0x00, 0xa5,
148};
149
150static const unsigned char s6e8ax0_22_gamma_120[] = {
151 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb9, 0x95, 0xc8, 0xb1, 0xcf,
152 0xb2, 0xc6, 0xdf, 0xc5, 0x9b, 0xc3, 0x99, 0xb6, 0xd2, 0xb6,
153 0x00, 0x8f, 0x00, 0x86, 0x00, 0xac,
154};
155
156static const unsigned char s6e8ax0_22_gamma_130[] = {
157 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc7, 0xb1, 0xd0,
158 0xb2, 0xc4, 0xdd, 0xc3, 0x9a, 0xc3, 0x98, 0xb6, 0xd0, 0xb4,
159 0x00, 0x92, 0x00, 0x8a, 0x00, 0xb1,
160};
161
162static const unsigned char s6e8ax0_22_gamma_140[] = {
163 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb7, 0xa0, 0xc5, 0xb2, 0xd0,
164 0xb3, 0xc3, 0xde, 0xc3, 0x9b, 0xc2, 0x98, 0xb6, 0xd0, 0xb4,
165 0x00, 0x95, 0x00, 0x8d, 0x00, 0xb5,
166};
167
168static const unsigned char s6e8ax0_22_gamma_150[] = {
169 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xa0, 0xc2, 0xb2, 0xd0,
170 0xb2, 0xc1, 0xdd, 0xc2, 0x9b, 0xc2, 0x98, 0xb4, 0xcf, 0xb1,
171 0x00, 0x99, 0x00, 0x90, 0x00, 0xba,
172};
173
174static const unsigned char s6e8ax0_22_gamma_160[] = {
175 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xa5, 0xbf, 0xb0, 0xd0,
176 0xb1, 0xc3, 0xde, 0xc2, 0x99, 0xc1, 0x97, 0xb4, 0xce, 0xb1,
177 0x00, 0x9c, 0x00, 0x93, 0x00, 0xbe,
178};
179
180static const unsigned char s6e8ax0_22_gamma_170[] = {
181 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb5, 0xbf, 0xb1, 0xd1,
182 0xb1, 0xc3, 0xde, 0xc3, 0x99, 0xc0, 0x96, 0xb4, 0xce, 0xb1,
183 0x00, 0x9f, 0x00, 0x96, 0x00, 0xc2,
184};
185
186static const unsigned char s6e8ax0_22_gamma_180[] = {
187 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb7, 0xbe, 0xb3, 0xd2,
188 0xb3, 0xc3, 0xde, 0xc2, 0x97, 0xbf, 0x95, 0xb4, 0xcd, 0xb1,
189 0x00, 0xa2, 0x00, 0x99, 0x00, 0xc5,
190};
191
192static const unsigned char s6e8ax0_22_gamma_190[] = {
193 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbe, 0xb2, 0xd2,
194 0xb2, 0xc3, 0xdd, 0xc3, 0x98, 0xbf, 0x95, 0xb2, 0xcc, 0xaf,
195 0x00, 0xa5, 0x00, 0x9c, 0x00, 0xc9,
196};
197
198static const unsigned char s6e8ax0_22_gamma_200[] = {
199 0xfa, 0x01, 0x60, 0x10, 0x60, 0xaf, 0xb9, 0xbc, 0xb2, 0xd2,
200 0xb1, 0xc4, 0xdd, 0xc3, 0x97, 0xbe, 0x95, 0xb1, 0xcb, 0xae,
201 0x00, 0xa8, 0x00, 0x9f, 0x00, 0xcd,
202};
203
204static const unsigned char s6e8ax0_22_gamma_210[] = {
205 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc1, 0xbd, 0xb1, 0xd1,
206 0xb1, 0xc2, 0xde, 0xc2, 0x97, 0xbe, 0x94, 0xB0, 0xc9, 0xad,
207 0x00, 0xae, 0x00, 0xa4, 0x00, 0xd4,
208};
209
210static const unsigned char s6e8ax0_22_gamma_220[] = {
211 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc7, 0xbd, 0xb1, 0xd1,
212 0xb1, 0xc2, 0xdd, 0xc2, 0x97, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
213 0x00, 0xad, 0x00, 0xa2, 0x00, 0xd3,
214};
215
216static const unsigned char s6e8ax0_22_gamma_230[] = {
217 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xc3, 0xbd, 0xb2, 0xd1,
218 0xb1, 0xc3, 0xdd, 0xc1, 0x96, 0xbd, 0x94, 0xb0, 0xc9, 0xad,
219 0x00, 0xb0, 0x00, 0xa7, 0x00, 0xd7,
220};
221
222static const unsigned char s6e8ax0_22_gamma_240[] = {
223 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb1, 0xcb, 0xbd, 0xb1, 0xd2,
224 0xb1, 0xc3, 0xdD, 0xc2, 0x95, 0xbd, 0x93, 0xaf, 0xc8, 0xab,
225 0x00, 0xb3, 0x00, 0xa9, 0x00, 0xdb,
226};
227
228static const unsigned char s6e8ax0_22_gamma_250[] = {
229 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xcc, 0xbe, 0xb0, 0xd2,
230 0xb0, 0xc3, 0xdD, 0xc2, 0x94, 0xbc, 0x92, 0xae, 0xc8, 0xab,
231 0x00, 0xb6, 0x00, 0xab, 0x00, 0xde,
232};
233
234static const unsigned char s6e8ax0_22_gamma_260[] = {
235 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb3, 0xd0, 0xbe, 0xaf, 0xd1,
236 0xaf, 0xc2, 0xdd, 0xc1, 0x96, 0xbc, 0x93, 0xaf, 0xc8, 0xac,
237 0x00, 0xb7, 0x00, 0xad, 0x00, 0xe0,
238};
239
240static const unsigned char s6e8ax0_22_gamma_270[] = {
241 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xcF, 0xbd, 0xb0, 0xd2,
242 0xaf, 0xc2, 0xdc, 0xc1, 0x95, 0xbd, 0x93, 0xae, 0xc6, 0xaa,
243 0x00, 0xba, 0x00, 0xb0, 0x00, 0xe4,
244};
245
246static const unsigned char s6e8ax0_22_gamma_280[] = {
247 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb2, 0xd0, 0xbd, 0xaf, 0xd0,
248 0xad, 0xc4, 0xdd, 0xc3, 0x95, 0xbd, 0x93, 0xac, 0xc5, 0xa9,
249 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xe7,
250};
251
252static const unsigned char s6e8ax0_22_gamma_300[] = {
253 0xfa, 0x01, 0x60, 0x10, 0x60, 0xb5, 0xd3, 0xbd, 0xb1, 0xd2,
254 0xb0, 0xc0, 0xdc, 0xc0, 0x94, 0xba, 0x91, 0xac, 0xc5, 0xa9,
255 0x00, 0xc2, 0x00, 0xb7, 0x00, 0xed,
256};
257
258static const unsigned char *s6e8ax0_22_gamma_table[] = {
259 s6e8ax0_22_gamma_30,
260 s6e8ax0_22_gamma_50,
261 s6e8ax0_22_gamma_60,
262 s6e8ax0_22_gamma_70,
263 s6e8ax0_22_gamma_80,
264 s6e8ax0_22_gamma_90,
265 s6e8ax0_22_gamma_100,
266 s6e8ax0_22_gamma_120,
267 s6e8ax0_22_gamma_130,
268 s6e8ax0_22_gamma_140,
269 s6e8ax0_22_gamma_150,
270 s6e8ax0_22_gamma_160,
271 s6e8ax0_22_gamma_170,
272 s6e8ax0_22_gamma_180,
273 s6e8ax0_22_gamma_190,
274 s6e8ax0_22_gamma_200,
275 s6e8ax0_22_gamma_210,
276 s6e8ax0_22_gamma_220,
277 s6e8ax0_22_gamma_230,
278 s6e8ax0_22_gamma_240,
279 s6e8ax0_22_gamma_250,
280 s6e8ax0_22_gamma_260,
281 s6e8ax0_22_gamma_270,
282 s6e8ax0_22_gamma_280,
283 s6e8ax0_22_gamma_300,
284};
285
286static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd)
287{
288 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
289
290 static const unsigned char data_to_send[] = {
291 0xf8, 0x3d, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
292 0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
293 0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
294 0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8
295 };
296
297 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
298 data_to_send, ARRAY_SIZE(data_to_send));
299}
300
301static void s6e8ax0_display_cond(struct s6e8ax0 *lcd)
302{
303 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
304 static const unsigned char data_to_send[] = {
305 0xf2, 0x80, 0x03, 0x0d
306 };
307
308 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
309 data_to_send, ARRAY_SIZE(data_to_send));
310}
311
312/* Gamma 2.2 Setting (200cd, 7500K, 10MPCD) */
313static void s6e8ax0_gamma_cond(struct s6e8ax0 *lcd)
314{
315 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
316 unsigned int gamma = lcd->bd->props.brightness;
317
318 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
319 s6e8ax0_22_gamma_table[gamma],
320 GAMMA_TABLE_COUNT);
321}
322
323static void s6e8ax0_gamma_update(struct s6e8ax0 *lcd)
324{
325 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
326 static const unsigned char data_to_send[] = {
327 0xf7, 0x03
328 };
329
330 ops->cmd_write(lcd_to_master(lcd),
331 MIPI_DSI_DCS_SHORT_WRITE_PARAM, data_to_send,
332 ARRAY_SIZE(data_to_send));
333}
334
335static void s6e8ax0_etc_cond1(struct s6e8ax0 *lcd)
336{
337 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
338 static const unsigned char data_to_send[] = {
339 0xd1, 0xfe, 0x80, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x40,
340 0x0d, 0x00, 0x00
341 };
342
343 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
344 data_to_send, ARRAY_SIZE(data_to_send));
345}
346
347static void s6e8ax0_etc_cond2(struct s6e8ax0 *lcd)
348{
349 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
350 static const unsigned char data_to_send[] = {
351 0xb6, 0x0c, 0x02, 0x03, 0x32, 0xff, 0x44, 0x44, 0xc0,
352 0x00
353 };
354
355 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
356 data_to_send, ARRAY_SIZE(data_to_send));
357}
358
359static void s6e8ax0_etc_cond3(struct s6e8ax0 *lcd)
360{
361 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
362 static const unsigned char data_to_send[] = {
363 0xe1, 0x10, 0x1c, 0x17, 0x08, 0x1d
364 };
365
366 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
367 data_to_send, ARRAY_SIZE(data_to_send));
368}
369
370static void s6e8ax0_etc_cond4(struct s6e8ax0 *lcd)
371{
372 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
373 static const unsigned char data_to_send[] = {
374 0xe2, 0xed, 0x07, 0xc3, 0x13, 0x0d, 0x03
375 };
376
377 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
378 data_to_send, ARRAY_SIZE(data_to_send));
379}
380
381static void s6e8ax0_etc_cond5(struct s6e8ax0 *lcd)
382{
383 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
384 static const unsigned char data_to_send[] = {
385 0xf4, 0xcf, 0x0a, 0x12, 0x10, 0x19, 0x33, 0x02
386 };
387
388 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
389 data_to_send, ARRAY_SIZE(data_to_send));
390}
391static void s6e8ax0_etc_cond6(struct s6e8ax0 *lcd)
392{
393 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
394 static const unsigned char data_to_send[] = {
395 0xe3, 0x40
396 };
397
398 ops->cmd_write(lcd_to_master(lcd),
399 MIPI_DSI_DCS_SHORT_WRITE_PARAM,
400 data_to_send, ARRAY_SIZE(data_to_send));
401}
402
403static void s6e8ax0_etc_cond7(struct s6e8ax0 *lcd)
404{
405 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
406 static const unsigned char data_to_send[] = {
407 0xe4, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00
408 };
409
410 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
411 data_to_send, ARRAY_SIZE(data_to_send));
412}
413
414static void s6e8ax0_elvss_set(struct s6e8ax0 *lcd)
415{
416 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
417 static const unsigned char data_to_send[] = {
418 0xb1, 0x04, 0x00
419 };
420
421 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
422 data_to_send, ARRAY_SIZE(data_to_send));
423}
424
425static void s6e8ax0_elvss_nvm_set(struct s6e8ax0 *lcd)
426{
427 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
428 static const unsigned char data_to_send[] = {
429 0xd9, 0x5c, 0x20, 0x0c, 0x0f, 0x41, 0x00, 0x10, 0x11,
430 0x12, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcb, 0xed,
431 0x64, 0xaf
432 };
433
434 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
435 data_to_send, ARRAY_SIZE(data_to_send));
436}
437
438static void s6e8ax0_sleep_in(struct s6e8ax0 *lcd)
439{
440 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
441 static const unsigned char data_to_send[] = {
442 0x10, 0x00
443 };
444
445 ops->cmd_write(lcd_to_master(lcd),
446 MIPI_DSI_DCS_SHORT_WRITE,
447 data_to_send, ARRAY_SIZE(data_to_send));
448}
449
450static void s6e8ax0_sleep_out(struct s6e8ax0 *lcd)
451{
452 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
453 static const unsigned char data_to_send[] = {
454 0x11, 0x00
455 };
456
457 ops->cmd_write(lcd_to_master(lcd),
458 MIPI_DSI_DCS_SHORT_WRITE,
459 data_to_send, ARRAY_SIZE(data_to_send));
460}
461
462static void s6e8ax0_display_on(struct s6e8ax0 *lcd)
463{
464 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
465 static const unsigned char data_to_send[] = {
466 0x29, 0x00
467 };
468
469 ops->cmd_write(lcd_to_master(lcd),
470 MIPI_DSI_DCS_SHORT_WRITE,
471 data_to_send, ARRAY_SIZE(data_to_send));
472}
473
474static void s6e8ax0_display_off(struct s6e8ax0 *lcd)
475{
476 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
477 static const unsigned char data_to_send[] = {
478 0x28, 0x00
479 };
480
481 ops->cmd_write(lcd_to_master(lcd),
482 MIPI_DSI_DCS_SHORT_WRITE,
483 data_to_send, ARRAY_SIZE(data_to_send));
484}
485
486static void s6e8ax0_apply_level2_key(struct s6e8ax0 *lcd)
487{
488 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
489 static const unsigned char data_to_send[] = {
490 0xf0, 0x5a, 0x5a
491 };
492
493 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
494 data_to_send, ARRAY_SIZE(data_to_send));
495}
496
497static void s6e8ax0_acl_on(struct s6e8ax0 *lcd)
498{
499 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
500 static const unsigned char data_to_send[] = {
501 0xc0, 0x01
502 };
503
504 ops->cmd_write(lcd_to_master(lcd),
505 MIPI_DSI_DCS_SHORT_WRITE,
506 data_to_send, ARRAY_SIZE(data_to_send));
507}
508
509static void s6e8ax0_acl_off(struct s6e8ax0 *lcd)
510{
511 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
512 static const unsigned char data_to_send[] = {
513 0xc0, 0x00
514 };
515
516 ops->cmd_write(lcd_to_master(lcd),
517 MIPI_DSI_DCS_SHORT_WRITE,
518 data_to_send, ARRAY_SIZE(data_to_send));
519}
520
521/* Full white 50% reducing setting */
522static void s6e8ax0_acl_ctrl_set(struct s6e8ax0 *lcd)
523{
524 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
525 /* Full white 50% reducing setting */
526 static const unsigned char cutoff_50[] = {
527 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
528 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
529 0x01, 0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2a, 0x31, 0x38,
530 0x3f, 0x46
531 };
532 /* Full white 45% reducing setting */
533 static const unsigned char cutoff_45[] = {
534 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
535 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
536 0x01, 0x07, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b, 0x31,
537 0x37, 0x3d
538 };
539 /* Full white 40% reducing setting */
540 static const unsigned char cutoff_40[] = {
541 0xc1, 0x47, 0x53, 0x13, 0x53, 0x00, 0x00, 0x02, 0xcf,
542 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
543 0x01, 0x06, 0x0c, 0x11, 0x16, 0x1c, 0x21, 0x26, 0x2b,
544 0x31, 0x36
545 };
546
547 if (lcd->acl_enable) {
548 if (lcd->cur_acl == 0) {
549 if (lcd->gamma == 0 || lcd->gamma == 1) {
550 s6e8ax0_acl_off(lcd);
551 dev_dbg(&lcd->ld->dev,
552 "cur_acl=%d\n", lcd->cur_acl);
553 } else
554 s6e8ax0_acl_on(lcd);
555 }
556 switch (lcd->gamma) {
557 case 0: /* 30cd */
558 s6e8ax0_acl_off(lcd);
559 lcd->cur_acl = 0;
560 break;
561 case 1 ... 3: /* 50cd ~ 90cd */
562 ops->cmd_write(lcd_to_master(lcd),
563 MIPI_DSI_DCS_LONG_WRITE,
564 cutoff_40,
565 ARRAY_SIZE(cutoff_40));
566 lcd->cur_acl = 40;
567 break;
568 case 4 ... 7: /* 120cd ~ 210cd */
569 ops->cmd_write(lcd_to_master(lcd),
570 MIPI_DSI_DCS_LONG_WRITE,
571 cutoff_45,
572 ARRAY_SIZE(cutoff_45));
573 lcd->cur_acl = 45;
574 break;
575 case 8 ... 10: /* 220cd ~ 300cd */
576 ops->cmd_write(lcd_to_master(lcd),
577 MIPI_DSI_DCS_LONG_WRITE,
578 cutoff_50,
579 ARRAY_SIZE(cutoff_50));
580 lcd->cur_acl = 50;
581 break;
582 default:
583 break;
584 }
585 } else {
586 s6e8ax0_acl_off(lcd);
587 lcd->cur_acl = 0;
588 dev_dbg(&lcd->ld->dev, "cur_acl = %d\n", lcd->cur_acl);
589 }
590}
591
592static void s6e8ax0_read_id(struct s6e8ax0 *lcd, u8 *mtp_id)
593{
594 unsigned int ret;
595 unsigned int addr = 0xd1; /* MTP ID */
596 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
597
598 ret = ops->cmd_read(lcd_to_master(lcd),
599 MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM,
600 addr, 3, mtp_id);
601}
602
603static int s6e8ax0_panel_init(struct s6e8ax0 *lcd)
604{
605 s6e8ax0_apply_level2_key(lcd);
606 s6e8ax0_sleep_out(lcd);
607 msleep(1);
608 s6e8ax0_panel_cond(lcd);
609 s6e8ax0_display_cond(lcd);
610 s6e8ax0_gamma_cond(lcd);
611 s6e8ax0_gamma_update(lcd);
612
613 s6e8ax0_etc_cond1(lcd);
614 s6e8ax0_etc_cond2(lcd);
615 s6e8ax0_etc_cond3(lcd);
616 s6e8ax0_etc_cond4(lcd);
617 s6e8ax0_etc_cond5(lcd);
618 s6e8ax0_etc_cond6(lcd);
619 s6e8ax0_etc_cond7(lcd);
620
621 s6e8ax0_elvss_nvm_set(lcd);
622 s6e8ax0_elvss_set(lcd);
623
624 s6e8ax0_acl_ctrl_set(lcd);
625 s6e8ax0_acl_on(lcd);
626
627 /* if ID3 value is not 33h, branch private elvss mode */
628 msleep(lcd->ddi_pd->power_on_delay);
629
630 return 0;
631}
632
633static int s6e8ax0_update_gamma_ctrl(struct s6e8ax0 *lcd, int brightness)
634{
635 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
636
637 ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
638 s6e8ax0_22_gamma_table[brightness],
639 ARRAY_SIZE(s6e8ax0_22_gamma_table));
640
641 /* update gamma table. */
642 s6e8ax0_gamma_update(lcd);
643 lcd->gamma = brightness;
644
645 return 0;
646}
647
648static int s6e8ax0_gamma_ctrl(struct s6e8ax0 *lcd, int gamma)
649{
650 s6e8ax0_update_gamma_ctrl(lcd, gamma);
651
652 return 0;
653}
654
655static int s6e8ax0_set_power(struct lcd_device *ld, int power)
656{
657 struct s6e8ax0 *lcd = lcd_get_data(ld);
658 struct mipi_dsim_master_ops *ops = lcd_to_master_ops(lcd);
659 int ret = 0;
660
661 if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
662 power != FB_BLANK_NORMAL) {
663 dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
664 return -EINVAL;
665 }
666
667 if ((power == FB_BLANK_UNBLANK) && ops->set_blank_mode) {
668 /* LCD power on */
669 if ((POWER_IS_ON(power) && POWER_IS_OFF(lcd->power))
670 || (POWER_IS_ON(power) && POWER_IS_NRM(lcd->power))) {
671 ret = ops->set_blank_mode(lcd_to_master(lcd), power);
672 if (!ret && lcd->power != power)
673 lcd->power = power;
674 }
675 } else if ((power == FB_BLANK_POWERDOWN) && ops->set_early_blank_mode) {
676 /* LCD power off */
677 if ((POWER_IS_OFF(power) && POWER_IS_ON(lcd->power)) ||
678 (POWER_IS_ON(lcd->power) && POWER_IS_NRM(power))) {
679 ret = ops->set_early_blank_mode(lcd_to_master(lcd),
680 power);
681 if (!ret && lcd->power != power)
682 lcd->power = power;
683 }
684 }
685
686 return ret;
687}
688
689static int s6e8ax0_get_power(struct lcd_device *ld)
690{
691 struct s6e8ax0 *lcd = lcd_get_data(ld);
692
693 return lcd->power;
694}
695
696static int s6e8ax0_get_brightness(struct backlight_device *bd)
697{
698 return bd->props.brightness;
699}
700
701static int s6e8ax0_set_brightness(struct backlight_device *bd)
702{
703 int ret = 0, brightness = bd->props.brightness;
704 struct s6e8ax0 *lcd = bl_get_data(bd);
705
706 if (brightness < MIN_BRIGHTNESS ||
707 brightness > bd->props.max_brightness) {
708 dev_err(lcd->dev, "lcd brightness should be %d to %d.\n",
709 MIN_BRIGHTNESS, MAX_BRIGHTNESS);
710 return -EINVAL;
711 }
712
713 ret = s6e8ax0_gamma_ctrl(lcd, brightness);
714 if (ret) {
715 dev_err(&bd->dev, "lcd brightness setting failed.\n");
716 return -EIO;
717 }
718
719 return ret;
720}
721
722static struct lcd_ops s6e8ax0_lcd_ops = {
723 .set_power = s6e8ax0_set_power,
724 .get_power = s6e8ax0_get_power,
725};
726
727static const struct backlight_ops s6e8ax0_backlight_ops = {
728 .get_brightness = s6e8ax0_get_brightness,
729 .update_status = s6e8ax0_set_brightness,
730};
731
732static void s6e8ax0_power_on(struct mipi_dsim_lcd_device *dsim_dev, int power)
733{
734 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
735
736 msleep(lcd->ddi_pd->power_on_delay);
737
738 /* lcd power on */
739 if (power)
740 s6e8ax0_regulator_enable(lcd);
741 else
742 s6e8ax0_regulator_disable(lcd);
743
744 msleep(lcd->ddi_pd->reset_delay);
745
746 /* lcd reset */
747 if (lcd->ddi_pd->reset)
748 lcd->ddi_pd->reset(lcd->ld);
749 msleep(5);
750}
751
752static void s6e8ax0_set_sequence(struct mipi_dsim_lcd_device *dsim_dev)
753{
754 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
755
756 s6e8ax0_panel_init(lcd);
757 s6e8ax0_display_on(lcd);
758
759 lcd->power = FB_BLANK_UNBLANK;
760}
761
762static int s6e8ax0_probe(struct mipi_dsim_lcd_device *dsim_dev)
763{
764 struct s6e8ax0 *lcd;
765 int ret;
766 u8 mtp_id[3] = {0, };
767
768 lcd = kzalloc(sizeof(struct s6e8ax0), GFP_KERNEL);
769 if (!lcd) {
770 dev_err(&dsim_dev->dev, "failed to allocate s6e8ax0 structure.\n");
771 return -ENOMEM;
772 }
773
774 lcd->dsim_dev = dsim_dev;
775 lcd->ddi_pd = (struct lcd_platform_data *)dsim_dev->platform_data;
776 lcd->dev = &dsim_dev->dev;
777
778 mutex_init(&lcd->lock);
779
780 ret = regulator_bulk_get(lcd->dev, ARRAY_SIZE(supplies), supplies);
781 if (ret) {
782 dev_err(lcd->dev, "Failed to get regulators: %d\n", ret);
783 goto err_lcd_register;
784 }
785
786 lcd->ld = lcd_device_register("s6e8ax0", lcd->dev, lcd,
787 &s6e8ax0_lcd_ops);
788 if (IS_ERR(lcd->ld)) {
789 dev_err(lcd->dev, "failed to register lcd ops.\n");
790 ret = PTR_ERR(lcd->ld);
791 goto err_lcd_register;
792 }
793
794 lcd->bd = backlight_device_register("s6e8ax0-bl", lcd->dev, lcd,
795 &s6e8ax0_backlight_ops, NULL);
796 if (IS_ERR(lcd->bd)) {
797 dev_err(lcd->dev, "failed to register backlight ops.\n");
798 ret = PTR_ERR(lcd->bd);
799 goto err_backlight_register;
800 }
801
802 lcd->bd->props.max_brightness = MAX_BRIGHTNESS;
803 lcd->bd->props.brightness = MAX_BRIGHTNESS;
804
805 s6e8ax0_read_id(lcd, mtp_id);
806 if (mtp_id[0] == 0x00)
807 dev_err(lcd->dev, "read id failed\n");
808
809 dev_info(lcd->dev, "Read ID : %x, %x, %x\n",
810 mtp_id[0], mtp_id[1], mtp_id[2]);
811
812 if (mtp_id[2] == 0x33)
813 dev_info(lcd->dev,
814 "ID-3 is 0xff does not support dynamic elvss\n");
815 else
816 dev_info(lcd->dev,
817 "ID-3 is 0x%x support dynamic elvss\n", mtp_id[2]);
818
819 lcd->acl_enable = 1;
820 lcd->cur_acl = 0;
821
822 dev_set_drvdata(&dsim_dev->dev, lcd);
823
824 dev_dbg(lcd->dev, "probed s6e8ax0 panel driver.\n");
825
826 return 0;
827
828err_backlight_register:
829 lcd_device_unregister(lcd->ld);
830
831err_lcd_register:
832 regulator_bulk_free(ARRAY_SIZE(supplies), supplies);
833 kfree(lcd);
834
835 return ret;
836}
837
838#ifdef CONFIG_PM
839static int s6e8ax0_suspend(struct mipi_dsim_lcd_device *dsim_dev)
840{
841 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
842
843 s6e8ax0_sleep_in(lcd);
844 msleep(lcd->ddi_pd->power_off_delay);
845 s6e8ax0_display_off(lcd);
846
847 s6e8ax0_regulator_disable(lcd);
848
849 return 0;
850}
851
852static int s6e8ax0_resume(struct mipi_dsim_lcd_device *dsim_dev)
853{
854 struct s6e8ax0 *lcd = dev_get_drvdata(&dsim_dev->dev);
855
856 s6e8ax0_sleep_out(lcd);
857 msleep(lcd->ddi_pd->power_on_delay);
858
859 s6e8ax0_regulator_enable(lcd);
860 s6e8ax0_set_sequence(dsim_dev);
861
862 return 0;
863}
864#else
865#define s6e8ax0_suspend NULL
866#define s6e8ax0_resume NULL
867#endif
868
869static struct mipi_dsim_lcd_driver s6e8ax0_dsim_ddi_driver = {
870 .name = "s6e8ax0",
871 .id = -1,
872
873 .power_on = s6e8ax0_power_on,
874 .set_sequence = s6e8ax0_set_sequence,
875 .probe = s6e8ax0_probe,
876 .suspend = s6e8ax0_suspend,
877 .resume = s6e8ax0_resume,
878};
879
880static int s6e8ax0_init(void)
881{
882 exynos_mipi_dsi_register_lcd_driver(&s6e8ax0_dsim_ddi_driver);
883
884 return 0;
885}
886
887static void s6e8ax0_exit(void)
888{
889 return;
890}
891
892module_init(s6e8ax0_init);
893module_exit(s6e8ax0_exit);
894
895MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
896MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
897MODULE_DESCRIPTION("MIPI-DSI based s6e8ax0 AMOLED LCD Panel Driver");
898MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/s6e8ax0.h b/drivers/video/exynos/s6e8ax0.h
new file mode 100644
index 000000000000..1f1b270484b0
--- /dev/null
+++ b/drivers/video/exynos/s6e8ax0.h
@@ -0,0 +1,21 @@
1/* linux/drivers/video/backlight/s6e8ax0.h
2 *
3 * MIPI-DSI based s6e8ax0 AMOLED LCD Panel definitions.
4 *
5 * Copyright (c) 2011 Samsung Electronics
6 *
7 * Inki Dae, <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _S6E8AX0_H
16#define _S6E8AX0_H
17
18extern void s6e8ax0_init(void);
19
20#endif
21
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ac9141b85356..c6ce416ab587 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1665,6 +1665,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
1665 if (ret) 1665 if (ret)
1666 return -EINVAL; 1666 return -EINVAL;
1667 1667
1668 unlink_framebuffer(fb_info);
1668 if (fb_info->pixmap.addr && 1669 if (fb_info->pixmap.addr &&
1669 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) 1670 (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
1670 kfree(fb_info->pixmap.addr); 1671 kfree(fb_info->pixmap.addr);
@@ -1672,7 +1673,6 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
1672 registered_fb[i] = NULL; 1673 registered_fb[i] = NULL;
1673 num_registered_fb--; 1674 num_registered_fb--;
1674 fb_cleanup_device(fb_info); 1675 fb_cleanup_device(fb_info);
1675 device_destroy(fb_class, MKDEV(FB_MAJOR, i));
1676 event.info = fb_info; 1676 event.info = fb_info;
1677 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); 1677 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
1678 1678
@@ -1681,6 +1681,22 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
1681 return 0; 1681 return 0;
1682} 1682}
1683 1683
1684int unlink_framebuffer(struct fb_info *fb_info)
1685{
1686 int i;
1687
1688 i = fb_info->node;
1689 if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
1690 return -EINVAL;
1691
1692 if (fb_info->dev) {
1693 device_destroy(fb_class, MKDEV(FB_MAJOR, i));
1694 fb_info->dev = NULL;
1695 }
1696 return 0;
1697}
1698EXPORT_SYMBOL(unlink_framebuffer);
1699
1684void remove_conflicting_framebuffers(struct apertures_struct *a, 1700void remove_conflicting_framebuffers(struct apertures_struct *a,
1685 const char *name, bool primary) 1701 const char *name, bool primary)
1686{ 1702{
diff --git a/drivers/video/i740_reg.h b/drivers/video/i740_reg.h
new file mode 100644
index 000000000000..91bac76549d7
--- /dev/null
+++ b/drivers/video/i740_reg.h
@@ -0,0 +1,309 @@
1/**************************************************************************
2
3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4All Rights Reserved.
5
6Permission is hereby granted, free of charge, to any person obtaining a
7copy of this software and associated documentation files (the
8"Software"), to deal in the Software without restriction, including
9without limitation the rights to use, copy, modify, merge, publish,
10distribute, sub license, and/or sell copies of the Software, and to
11permit persons to whom the Software is furnished to do so, subject to
12the following conditions:
13
14The above copyright notice and this permission notice (including the
15next paragraph) shall be included in all copies or substantial portions
16of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26**************************************************************************/
27
28/*
29 * Authors:
30 * Kevin E. Martin <kevin@precisioninsight.com>
31 */
32
33/* I/O register offsets */
34#define SRX VGA_SEQ_I
35#define GRX VGA_GFX_I
36#define ARX VGA_ATT_IW
37#define XRX 0x3D6
38#define MRX 0x3D2
39
40/* VGA Color Palette Registers */
41#define DACMASK 0x3C6
42#define DACSTATE 0x3C7
43#define DACRX 0x3C7
44#define DACWX 0x3C8
45#define DACDATA 0x3C9
46
47/* CRT Controller Registers (CRX) */
48#define START_ADDR_HI 0x0C
49#define START_ADDR_LO 0x0D
50#define VERT_SYNC_END 0x11
51#define EXT_VERT_TOTAL 0x30
52#define EXT_VERT_DISPLAY 0x31
53#define EXT_VERT_SYNC_START 0x32
54#define EXT_VERT_BLANK_START 0x33
55#define EXT_HORIZ_TOTAL 0x35
56#define EXT_HORIZ_BLANK 0x39
57#define EXT_START_ADDR 0x40
58#define EXT_START_ADDR_ENABLE 0x80
59#define EXT_OFFSET 0x41
60#define EXT_START_ADDR_HI 0x42
61#define INTERLACE_CNTL 0x70
62#define INTERLACE_ENABLE 0x80
63#define INTERLACE_DISABLE 0x00
64
65/* Miscellaneous Output Register */
66#define MSR_R 0x3CC
67#define MSR_W 0x3C2
68#define IO_ADDR_SELECT 0x01
69
70#define MDA_BASE 0x3B0
71#define CGA_BASE 0x3D0
72
73/* System Configuration Extension Registers (XRX) */
74#define IO_CTNL 0x09
75#define EXTENDED_ATTR_CNTL 0x02
76#define EXTENDED_CRTC_CNTL 0x01
77
78#define ADDRESS_MAPPING 0x0A
79#define PACKED_MODE_ENABLE 0x04
80#define LINEAR_MODE_ENABLE 0x02
81#define PAGE_MAPPING_ENABLE 0x01
82
83#define BITBLT_CNTL 0x20
84#define COLEXP_MODE 0x30
85#define COLEXP_8BPP 0x00
86#define COLEXP_16BPP 0x10
87#define COLEXP_24BPP 0x20
88#define COLEXP_RESERVED 0x30
89#define CHIP_RESET 0x02
90#define BITBLT_STATUS 0x01
91
92#define DISPLAY_CNTL 0x40
93#define VGA_WRAP_MODE 0x02
94#define VGA_WRAP_AT_256KB 0x00
95#define VGA_NO_WRAP 0x02
96#define GUI_MODE 0x01
97#define STANDARD_VGA_MODE 0x00
98#define HIRES_MODE 0x01
99
100#define DRAM_ROW_TYPE 0x50
101#define DRAM_ROW_0 0x07
102#define DRAM_ROW_0_SDRAM 0x00
103#define DRAM_ROW_0_EMPTY 0x07
104#define DRAM_ROW_1 0x38
105#define DRAM_ROW_1_SDRAM 0x00
106#define DRAM_ROW_1_EMPTY 0x38
107#define DRAM_ROW_CNTL_LO 0x51
108#define DRAM_CAS_LATENCY 0x10
109#define DRAM_RAS_TIMING 0x08
110#define DRAM_RAS_PRECHARGE 0x04
111#define DRAM_ROW_CNTL_HI 0x52
112#define DRAM_EXT_CNTL 0x53
113#define DRAM_REFRESH_RATE 0x03
114#define DRAM_REFRESH_DISABLE 0x00
115#define DRAM_REFRESH_60HZ 0x01
116#define DRAM_REFRESH_FAST_TEST 0x02
117#define DRAM_REFRESH_RESERVED 0x03
118#define DRAM_TIMING 0x54
119#define DRAM_ROW_BNDRY_0 0x55
120#define DRAM_ROW_BNDRY_1 0x56
121
122#define DPMS_SYNC_SELECT 0x61
123#define VSYNC_CNTL 0x08
124#define VSYNC_ON 0x00
125#define VSYNC_OFF 0x08
126#define HSYNC_CNTL 0x02
127#define HSYNC_ON 0x00
128#define HSYNC_OFF 0x02
129
130#define PIXPIPE_CONFIG_0 0x80
131#define DAC_8_BIT 0x80
132#define DAC_6_BIT 0x00
133#define HW_CURSOR_ENABLE 0x10
134#define EXTENDED_PALETTE 0x01
135
136#define PIXPIPE_CONFIG_1 0x81
137#define DISPLAY_COLOR_MODE 0x0F
138#define DISPLAY_VGA_MODE 0x00
139#define DISPLAY_8BPP_MODE 0x02
140#define DISPLAY_15BPP_MODE 0x04
141#define DISPLAY_16BPP_MODE 0x05
142#define DISPLAY_24BPP_MODE 0x06
143#define DISPLAY_32BPP_MODE 0x07
144
145#define PIXPIPE_CONFIG_2 0x82
146#define DISPLAY_GAMMA_ENABLE 0x08
147#define DISPLAY_GAMMA_DISABLE 0x00
148#define OVERLAY_GAMMA_ENABLE 0x04
149#define OVERLAY_GAMMA_DISABLE 0x00
150
151#define CURSOR_CONTROL 0xA0
152#define CURSOR_ORIGIN_SCREEN 0x00
153#define CURSOR_ORIGIN_DISPLAY 0x10
154#define CURSOR_MODE 0x07
155#define CURSOR_MODE_DISABLE 0x00
156#define CURSOR_MODE_32_4C_AX 0x01
157#define CURSOR_MODE_128_2C 0x02
158#define CURSOR_MODE_128_1C 0x03
159#define CURSOR_MODE_64_3C 0x04
160#define CURSOR_MODE_64_4C_AX 0x05
161#define CURSOR_MODE_64_4C 0x06
162#define CURSOR_MODE_RESERVED 0x07
163#define CURSOR_BASEADDR_LO 0xA2
164#define CURSOR_BASEADDR_HI 0xA3
165#define CURSOR_X_LO 0xA4
166#define CURSOR_X_HI 0xA5
167#define CURSOR_X_POS 0x00
168#define CURSOR_X_NEG 0x80
169#define CURSOR_Y_LO 0xA6
170#define CURSOR_Y_HI 0xA7
171#define CURSOR_Y_POS 0x00
172#define CURSOR_Y_NEG 0x80
173
174#define VCLK2_VCO_M 0xC8
175#define VCLK2_VCO_N 0xC9
176#define VCLK2_VCO_MN_MSBS 0xCA
177#define VCO_N_MSBS 0x30
178#define VCO_M_MSBS 0x03
179#define VCLK2_VCO_DIV_SEL 0xCB
180#define POST_DIV_SELECT 0x70
181#define POST_DIV_1 0x00
182#define POST_DIV_2 0x10
183#define POST_DIV_4 0x20
184#define POST_DIV_8 0x30
185#define POST_DIV_16 0x40
186#define POST_DIV_32 0x50
187#define VCO_LOOP_DIV_BY_4M 0x00
188#define VCO_LOOP_DIV_BY_16M 0x04
189#define REF_CLK_DIV_BY_5 0x02
190#define REF_DIV_4 0x00
191#define REF_DIV_1 0x01
192
193#define PLL_CNTL 0xCE
194#define PLL_MEMCLK_SEL 0x03
195#define PLL_MEMCLK__66667KHZ 0x00
196#define PLL_MEMCLK__75000KHZ 0x01
197#define PLL_MEMCLK__88889KHZ 0x02
198#define PLL_MEMCLK_100000KHZ 0x03
199
200/* Multimedia Extension Registers (MRX) */
201#define ACQ_CNTL_1 0x02
202#define ACQ_CNTL_2 0x03
203#define FRAME_CAP_MODE 0x01
204#define CONT_CAP_MODE 0x00
205#define SINGLE_CAP_MODE 0x01
206#define ACQ_CNTL_3 0x04
207#define COL_KEY_CNTL_1 0x3C
208#define BLANK_DISP_OVERLAY 0x20
209
210/* FIFOs */
211#define LP_FIFO 0x1000
212#define HP_FIFO 0x2000
213#define INSTPNT 0x3040
214#define LP_FIFO_COUNT 0x3040
215#define HP_FIFO_COUNT 0x3041
216
217/* FIFO Commands */
218#define CLIENT 0xE0000000
219#define CLIENT_2D 0x60000000
220
221/* Command Parser Mode Register */
222#define COMPARS 0x3038
223#define TWO_D_INST_DISABLE 0x08
224#define THREE_D_INST_DISABLE 0x04
225#define STATE_VAR_UPDATE_DISABLE 0x02
226#define PAL_STIP_DISABLE 0x01
227
228/* Interrupt Control Registers */
229#define IER 0x3030
230#define IIR 0x3032
231#define IMR 0x3034
232#define ISR 0x3036
233#define VMIINTB_EVENT 0x2000
234#define GPIO4_INT 0x1000
235#define DISP_FLIP_EVENT 0x0800
236#define DVD_PORT_DMA 0x0400
237#define DISP_VBLANK 0x0200
238#define FIFO_EMPTY_DMA_DONE 0x0100
239#define INST_PARSER_ERROR 0x0080
240#define USER_DEFINED 0x0040
241#define BREAKPOINT 0x0020
242#define DISP_HORIZ_COUNT 0x0010
243#define DISP_VSYNC 0x0008
244#define CAPTURE_HORIZ_COUNT 0x0004
245#define CAPTURE_VSYNC 0x0002
246#define THREE_D_PIPE_FLUSHED 0x0001
247
248/* FIFO Watermark and Burst Length Control Register */
249#define FWATER_BLC 0x00006000
250#define LMI_BURST_LENGTH 0x7F000000
251#define LMI_FIFO_WATERMARK 0x003F0000
252#define AGP_BURST_LENGTH 0x00007F00
253#define AGP_FIFO_WATERMARK 0x0000003F
254
255/* BitBLT Registers */
256#define SRC_DST_PITCH 0x00040000
257#define DST_PITCH 0x1FFF0000
258#define SRC_PITCH 0x00001FFF
259#define COLEXP_BG_COLOR 0x00040004
260#define COLEXP_FG_COLOR 0x00040008
261#define MONO_SRC_CNTL 0x0004000C
262#define MONO_USE_COLEXP 0x00000000
263#define MONO_USE_SRCEXP 0x08000000
264#define MONO_DATA_ALIGN 0x07000000
265#define MONO_BIT_ALIGN 0x01000000
266#define MONO_BYTE_ALIGN 0x02000000
267#define MONO_WORD_ALIGN 0x03000000
268#define MONO_DWORD_ALIGN 0x04000000
269#define MONO_QWORD_ALIGN 0x05000000
270#define MONO_SRC_INIT_DSCRD 0x003F0000
271#define MONO_SRC_RIGHT_CLIP 0x00003F00
272#define MONO_SRC_LEFT_CLIP 0x0000003F
273#define BITBLT_CONTROL 0x00040010
274#define BLTR_STATUS 0x80000000
275#define DYN_DEPTH 0x03000000
276#define DYN_DEPTH_8BPP 0x00000000
277#define DYN_DEPTH_16BPP 0x01000000
278#define DYN_DEPTH_24BPP 0x02000000
279#define DYN_DEPTH_32BPP 0x03000000 /* Unimplemented on the i740 */
280#define DYN_DEPTH_ENABLE 0x00800000
281#define PAT_VERT_ALIGN 0x00700000
282#define SOLID_PAT_SELECT 0x00080000
283#define PAT_IS_IN_COLOR 0x00000000
284#define PAT_IS_MONO 0x00040000
285#define MONO_PAT_TRANSP 0x00020000
286#define COLOR_TRANSP_ROP 0x00000000
287#define COLOR_TRANSP_DST 0x00008000
288#define COLOR_TRANSP_EQ 0x00000000
289#define COLOR_TRANSP_NOT_EQ 0x00010000
290#define COLOR_TRANSP_ENABLE 0x00004000
291#define MONO_SRC_TRANSP 0x00002000
292#define SRC_IS_IN_COLOR 0x00000000
293#define SRC_IS_MONO 0x00001000
294#define SRC_USE_SRC_ADDR 0x00000000
295#define SRC_USE_BLTDATA 0x00000400
296#define BLT_TOP_TO_BOT 0x00000000
297#define BLT_BOT_TO_TOP 0x00000200
298#define BLT_LEFT_TO_RIGHT 0x00000000
299#define BLT_RIGHT_TO_LEFT 0x00000100
300#define BLT_ROP 0x000000FF
301#define BLT_PAT_ADDR 0x00040014
302#define BLT_SRC_ADDR 0x00040018
303#define BLT_DST_ADDR 0x0004001C
304#define BLT_DST_H_W 0x00040020
305#define BLT_DST_HEIGHT 0x1FFF0000
306#define BLT_DST_WIDTH 0x00001FFF
307#define SRCEXP_BG_COLOR 0x00040024
308#define SRCEXP_FG_COLOR 0x00040028
309#define BLTDATA 0x00050000
diff --git a/drivers/video/i740fb.c b/drivers/video/i740fb.c
new file mode 100644
index 000000000000..fe574d84ed99
--- /dev/null
+++ b/drivers/video/i740fb.c
@@ -0,0 +1,1337 @@
1/*
2 * i740fb - framebuffer driver for Intel740
3 * Copyright (c) 2011 Ondrej Zary
4 *
5 * Based on old i740fb driver (c) 2001-2002 Andrey Ulanov <drey@rt.mipt.ru>
6 * which was partially based on:
7 * VGA 16-color framebuffer driver (c) 1999 Ben Pfaff <pfaffben@debian.org>
8 * and Petr Vandrovec <VANDROVE@vc.cvut.cz>
9 * i740 driver from XFree86 (c) 1998-1999 Precision Insight, Inc., Cedar Park,
10 * Texas.
11 * i740fb by Patrick LERDA, v0.9
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/string.h>
18#include <linux/mm.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/fb.h>
22#include <linux/init.h>
23#include <linux/pci.h>
24#include <linux/pci_ids.h>
25#include <linux/i2c.h>
26#include <linux/i2c-algo-bit.h>
27#include <linux/console.h>
28#include <video/vga.h>
29
30#ifdef CONFIG_MTRR
31#include <asm/mtrr.h>
32#endif
33
34#include "i740_reg.h"
35
36static char *mode_option __devinitdata;
37
38#ifdef CONFIG_MTRR
39static int mtrr __devinitdata = 1;
40#endif
41
42struct i740fb_par {
43 unsigned char __iomem *regs;
44 bool has_sgram;
45#ifdef CONFIG_MTRR
46 int mtrr_reg;
47#endif
48 bool ddc_registered;
49 struct i2c_adapter ddc_adapter;
50 struct i2c_algo_bit_data ddc_algo;
51 u32 pseudo_palette[16];
52 struct mutex open_lock;
53 unsigned int ref_count;
54
55 u8 crtc[VGA_CRT_C];
56 u8 atc[VGA_ATT_C];
57 u8 gdc[VGA_GFX_C];
58 u8 seq[VGA_SEQ_C];
59 u8 misc;
60 u8 vss;
61
62 /* i740 specific registers */
63 u8 display_cntl;
64 u8 pixelpipe_cfg0;
65 u8 pixelpipe_cfg1;
66 u8 pixelpipe_cfg2;
67 u8 video_clk2_m;
68 u8 video_clk2_n;
69 u8 video_clk2_mn_msbs;
70 u8 video_clk2_div_sel;
71 u8 pll_cntl;
72 u8 address_mapping;
73 u8 io_cntl;
74 u8 bitblt_cntl;
75 u8 ext_vert_total;
76 u8 ext_vert_disp_end;
77 u8 ext_vert_sync_start;
78 u8 ext_vert_blank_start;
79 u8 ext_horiz_total;
80 u8 ext_horiz_blank;
81 u8 ext_offset;
82 u8 interlace_cntl;
83 u32 lmi_fifo_watermark;
84 u8 ext_start_addr;
85 u8 ext_start_addr_hi;
86};
87
88#define DACSPEED8 203
89#define DACSPEED16 163
90#define DACSPEED24_SG 136
91#define DACSPEED24_SD 128
92#define DACSPEED32 86
93
94static struct fb_fix_screeninfo i740fb_fix __devinitdata = {
95 .id = "i740fb",
96 .type = FB_TYPE_PACKED_PIXELS,
97 .visual = FB_VISUAL_TRUECOLOR,
98 .xpanstep = 8,
99 .ypanstep = 1,
100 .accel = FB_ACCEL_NONE,
101};
102
103static inline void i740outb(struct i740fb_par *par, u16 port, u8 val)
104{
105 vga_mm_w(par->regs, port, val);
106}
107static inline u8 i740inb(struct i740fb_par *par, u16 port)
108{
109 return vga_mm_r(par->regs, port);
110}
111static inline void i740outreg(struct i740fb_par *par, u16 port, u8 reg, u8 val)
112{
113 vga_mm_w_fast(par->regs, port, reg, val);
114}
115static inline u8 i740inreg(struct i740fb_par *par, u16 port, u8 reg)
116{
117 vga_mm_w(par->regs, port, reg);
118 return vga_mm_r(par->regs, port+1);
119}
120static inline void i740outreg_mask(struct i740fb_par *par, u16 port, u8 reg,
121 u8 val, u8 mask)
122{
123 vga_mm_w_fast(par->regs, port, reg, (val & mask)
124 | (i740inreg(par, port, reg) & ~mask));
125}
126
127#define REG_DDC_DRIVE 0x62
128#define REG_DDC_STATE 0x63
129#define DDC_SCL (1 << 3)
130#define DDC_SDA (1 << 2)
131
132static void i740fb_ddc_setscl(void *data, int val)
133{
134 struct i740fb_par *par = data;
135
136 i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SCL, DDC_SCL);
137 i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SCL : 0, DDC_SCL);
138}
139
140static void i740fb_ddc_setsda(void *data, int val)
141{
142 struct i740fb_par *par = data;
143
144 i740outreg_mask(par, XRX, REG_DDC_DRIVE, DDC_SDA, DDC_SDA);
145 i740outreg_mask(par, XRX, REG_DDC_STATE, val ? DDC_SDA : 0, DDC_SDA);
146}
147
148static int i740fb_ddc_getscl(void *data)
149{
150 struct i740fb_par *par = data;
151
152 i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SCL);
153
154 return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SCL);
155}
156
157static int i740fb_ddc_getsda(void *data)
158{
159 struct i740fb_par *par = data;
160
161 i740outreg_mask(par, XRX, REG_DDC_DRIVE, 0, DDC_SDA);
162
163 return !!(i740inreg(par, XRX, REG_DDC_STATE) & DDC_SDA);
164}
165
166static int __devinit i740fb_setup_ddc_bus(struct fb_info *info)
167{
168 struct i740fb_par *par = info->par;
169
170 strlcpy(par->ddc_adapter.name, info->fix.id,
171 sizeof(par->ddc_adapter.name));
172 par->ddc_adapter.owner = THIS_MODULE;
173 par->ddc_adapter.class = I2C_CLASS_DDC;
174 par->ddc_adapter.algo_data = &par->ddc_algo;
175 par->ddc_adapter.dev.parent = info->device;
176 par->ddc_algo.setsda = i740fb_ddc_setsda;
177 par->ddc_algo.setscl = i740fb_ddc_setscl;
178 par->ddc_algo.getsda = i740fb_ddc_getsda;
179 par->ddc_algo.getscl = i740fb_ddc_getscl;
180 par->ddc_algo.udelay = 10;
181 par->ddc_algo.timeout = 20;
182 par->ddc_algo.data = par;
183
184 i2c_set_adapdata(&par->ddc_adapter, par);
185
186 return i2c_bit_add_bus(&par->ddc_adapter);
187}
188
189static int i740fb_open(struct fb_info *info, int user)
190{
191 struct i740fb_par *par = info->par;
192
193 mutex_lock(&(par->open_lock));
194 par->ref_count++;
195 mutex_unlock(&(par->open_lock));
196
197 return 0;
198}
199
200static int i740fb_release(struct fb_info *info, int user)
201{
202 struct i740fb_par *par = info->par;
203
204 mutex_lock(&(par->open_lock));
205 if (par->ref_count == 0) {
206 printk(KERN_ERR "fb%d: release called with zero refcount\n",
207 info->node);
208 mutex_unlock(&(par->open_lock));
209 return -EINVAL;
210 }
211
212 par->ref_count--;
213 mutex_unlock(&(par->open_lock));
214
215 return 0;
216}
217
218static u32 i740_calc_fifo(struct i740fb_par *par, u32 freq, int bpp)
219{
220 /*
221 * Would like to calculate these values automatically, but a generic
222 * algorithm does not seem possible. Note: These FIFO water mark
223 * values were tested on several cards and seem to eliminate the
224 * all of the snow and vertical banding, but fine adjustments will
225 * probably be required for other cards.
226 */
227
228 u32 wm;
229
230 switch (bpp) {
231 case 8:
232 if (freq > 200)
233 wm = 0x18120000;
234 else if (freq > 175)
235 wm = 0x16110000;
236 else if (freq > 135)
237 wm = 0x120E0000;
238 else
239 wm = 0x100D0000;
240 break;
241 case 15:
242 case 16:
243 if (par->has_sgram) {
244 if (freq > 140)
245 wm = 0x2C1D0000;
246 else if (freq > 120)
247 wm = 0x2C180000;
248 else if (freq > 100)
249 wm = 0x24160000;
250 else if (freq > 90)
251 wm = 0x18120000;
252 else if (freq > 50)
253 wm = 0x16110000;
254 else if (freq > 32)
255 wm = 0x13100000;
256 else
257 wm = 0x120E0000;
258 } else {
259 if (freq > 160)
260 wm = 0x28200000;
261 else if (freq > 140)
262 wm = 0x2A1E0000;
263 else if (freq > 130)
264 wm = 0x2B1A0000;
265 else if (freq > 120)
266 wm = 0x2C180000;
267 else if (freq > 100)
268 wm = 0x24180000;
269 else if (freq > 90)
270 wm = 0x18120000;
271 else if (freq > 50)
272 wm = 0x16110000;
273 else if (freq > 32)
274 wm = 0x13100000;
275 else
276 wm = 0x120E0000;
277 }
278 break;
279 case 24:
280 if (par->has_sgram) {
281 if (freq > 130)
282 wm = 0x31200000;
283 else if (freq > 120)
284 wm = 0x2E200000;
285 else if (freq > 100)
286 wm = 0x2C1D0000;
287 else if (freq > 80)
288 wm = 0x25180000;
289 else if (freq > 64)
290 wm = 0x24160000;
291 else if (freq > 49)
292 wm = 0x18120000;
293 else if (freq > 32)
294 wm = 0x16110000;
295 else
296 wm = 0x13100000;
297 } else {
298 if (freq > 120)
299 wm = 0x311F0000;
300 else if (freq > 100)
301 wm = 0x2C1D0000;
302 else if (freq > 80)
303 wm = 0x25180000;
304 else if (freq > 64)
305 wm = 0x24160000;
306 else if (freq > 49)
307 wm = 0x18120000;
308 else if (freq > 32)
309 wm = 0x16110000;
310 else
311 wm = 0x13100000;
312 }
313 break;
314 case 32:
315 if (par->has_sgram) {
316 if (freq > 80)
317 wm = 0x2A200000;
318 else if (freq > 60)
319 wm = 0x281A0000;
320 else if (freq > 49)
321 wm = 0x25180000;
322 else if (freq > 32)
323 wm = 0x18120000;
324 else
325 wm = 0x16110000;
326 } else {
327 if (freq > 80)
328 wm = 0x29200000;
329 else if (freq > 60)
330 wm = 0x281A0000;
331 else if (freq > 49)
332 wm = 0x25180000;
333 else if (freq > 32)
334 wm = 0x18120000;
335 else
336 wm = 0x16110000;
337 }
338 break;
339 }
340
341 return wm;
342}
343
344/* clock calculation from i740fb by Patrick LERDA */
345
346#define I740_RFREQ 1000000
347#define TARGET_MAX_N 30
348#define I740_FFIX (1 << 8)
349#define I740_RFREQ_FIX (I740_RFREQ / I740_FFIX)
350#define I740_REF_FREQ (6667 * I740_FFIX / 100) /* 66.67 MHz */
351#define I740_MAX_VCO_FREQ (450 * I740_FFIX) /* 450 MHz */
352
353static void i740_calc_vclk(u32 freq, struct i740fb_par *par)
354{
355 const u32 err_max = freq / (200 * I740_RFREQ / I740_FFIX);
356 const u32 err_target = freq / (1000 * I740_RFREQ / I740_FFIX);
357 u32 err_best = 512 * I740_FFIX;
358 u32 f_err, f_vco;
359 int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
360 int m, n;
361
362 p_best = min(15, ilog2(I740_MAX_VCO_FREQ / (freq / I740_RFREQ_FIX)));
363 d_best = 0;
364 f_vco = (freq * (1 << p_best)) / I740_RFREQ_FIX;
365 freq = freq / I740_RFREQ_FIX;
366
367 n = 2;
368 do {
369 n++;
370 m = ((f_vco * n) / I740_REF_FREQ + 2) / 4;
371
372 if (m < 3)
373 m = 3;
374
375 {
376 u32 f_out = (((m * I740_REF_FREQ * (4 << 2 * d_best))
377 / n) + ((1 << p_best) / 2)) / (1 << p_best);
378
379 f_err = (freq - f_out);
380
381 if (abs(f_err) < err_max) {
382 m_best = m;
383 n_best = n;
384 err_best = f_err;
385 }
386 }
387 } while ((abs(f_err) >= err_target) &&
388 ((n <= TARGET_MAX_N) || (abs(err_best) > err_max)));
389
390 if (abs(f_err) < err_target) {
391 m_best = m;
392 n_best = n;
393 }
394
395 par->video_clk2_m = (m_best - 2) & 0xFF;
396 par->video_clk2_n = (n_best - 2) & 0xFF;
397 par->video_clk2_mn_msbs = ((((n_best - 2) >> 4) & VCO_N_MSBS)
398 | (((m_best - 2) >> 8) & VCO_M_MSBS));
399 par->video_clk2_div_sel =
400 ((p_best << 4) | (d_best ? 4 : 0) | REF_DIV_1);
401}
402
403static int i740fb_decode_var(const struct fb_var_screeninfo *var,
404 struct i740fb_par *par, struct fb_info *info)
405{
406 /*
407 * Get the video params out of 'var'.
408 * If a value doesn't fit, round it up, if it's too big, return -EINVAL.
409 */
410
411 u32 xres, right, hslen, left, xtotal;
412 u32 yres, lower, vslen, upper, ytotal;
413 u32 vxres, xoffset, vyres, yoffset;
414 u32 bpp, base, dacspeed24, mem;
415 u8 r7;
416 int i;
417
418 dev_dbg(info->device, "decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
419 var->xres, var->yres, var->xres_virtual, var->xres_virtual);
420 dev_dbg(info->device, " xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
421 var->xoffset, var->yoffset, var->bits_per_pixel,
422 var->grayscale);
423 dev_dbg(info->device, " activate: %i, nonstd: %i, vmode: %i\n",
424 var->activate, var->nonstd, var->vmode);
425 dev_dbg(info->device, " pixclock: %i, hsynclen:%i, vsynclen:%i\n",
426 var->pixclock, var->hsync_len, var->vsync_len);
427 dev_dbg(info->device, " left: %i, right: %i, up:%i, lower:%i\n",
428 var->left_margin, var->right_margin, var->upper_margin,
429 var->lower_margin);
430
431
432 bpp = var->bits_per_pixel;
433 switch (bpp) {
434 case 1 ... 8:
435 bpp = 8;
436 if ((1000000 / var->pixclock) > DACSPEED8) {
437 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
438 1000000 / var->pixclock, DACSPEED8);
439 return -EINVAL;
440 }
441 break;
442 case 9 ... 15:
443 bpp = 15;
444 case 16:
445 if ((1000000 / var->pixclock) > DACSPEED16) {
446 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
447 1000000 / var->pixclock, DACSPEED16);
448 return -EINVAL;
449 }
450 break;
451 case 17 ... 24:
452 bpp = 24;
453 dacspeed24 = par->has_sgram ? DACSPEED24_SG : DACSPEED24_SD;
454 if ((1000000 / var->pixclock) > dacspeed24) {
455 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
456 1000000 / var->pixclock, dacspeed24);
457 return -EINVAL;
458 }
459 break;
460 case 25 ... 32:
461 bpp = 32;
462 if ((1000000 / var->pixclock) > DACSPEED32) {
463 dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
464 1000000 / var->pixclock, DACSPEED32);
465 return -EINVAL;
466 }
467 break;
468 default:
469 return -EINVAL;
470 }
471
472 xres = ALIGN(var->xres, 8);
473 vxres = ALIGN(var->xres_virtual, 16);
474 if (vxres < xres)
475 vxres = xres;
476
477 xoffset = ALIGN(var->xoffset, 8);
478 if (xres + xoffset > vxres)
479 xoffset = vxres - xres;
480
481 left = ALIGN(var->left_margin, 8);
482 right = ALIGN(var->right_margin, 8);
483 hslen = ALIGN(var->hsync_len, 8);
484
485 yres = var->yres;
486 vyres = var->yres_virtual;
487 if (yres > vyres)
488 vyres = yres;
489
490 yoffset = var->yoffset;
491 if (yres + yoffset > vyres)
492 yoffset = vyres - yres;
493
494 lower = var->lower_margin;
495 vslen = var->vsync_len;
496 upper = var->upper_margin;
497
498 mem = vxres * vyres * ((bpp + 1) / 8);
499 if (mem > info->screen_size) {
500 dev_err(info->device, "not enough video memory (%d KB requested, %ld KB avaliable)\n",
501 mem >> 10, info->screen_size >> 10);
502 return -ENOMEM;
503 }
504
505 if (yoffset + yres > vyres)
506 yoffset = vyres - yres;
507
508 xtotal = xres + right + hslen + left;
509 ytotal = yres + lower + vslen + upper;
510
511 par->crtc[VGA_CRTC_H_TOTAL] = (xtotal >> 3) - 5;
512 par->crtc[VGA_CRTC_H_DISP] = (xres >> 3) - 1;
513 par->crtc[VGA_CRTC_H_BLANK_START] = ((xres + right) >> 3) - 1;
514 par->crtc[VGA_CRTC_H_SYNC_START] = (xres + right) >> 3;
515 par->crtc[VGA_CRTC_H_SYNC_END] = (((xres + right + hslen) >> 3) & 0x1F)
516 | ((((xres + right + hslen) >> 3) & 0x20) << 2);
517 par->crtc[VGA_CRTC_H_BLANK_END] = ((xres + right + hslen) >> 3 & 0x1F)
518 | 0x80;
519
520 par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
521
522 r7 = 0x10; /* disable linecompare */
523 if (ytotal & 0x100)
524 r7 |= 0x01;
525 if (ytotal & 0x200)
526 r7 |= 0x20;
527
528 par->crtc[VGA_CRTC_PRESET_ROW] = 0;
529 par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */
530 if (var->vmode & FB_VMODE_DOUBLE)
531 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
532 par->crtc[VGA_CRTC_CURSOR_START] = 0x00;
533 par->crtc[VGA_CRTC_CURSOR_END] = 0x00;
534 par->crtc[VGA_CRTC_CURSOR_HI] = 0x00;
535 par->crtc[VGA_CRTC_CURSOR_LO] = 0x00;
536 par->crtc[VGA_CRTC_V_DISP_END] = yres-1;
537 if ((yres-1) & 0x100)
538 r7 |= 0x02;
539 if ((yres-1) & 0x200)
540 r7 |= 0x40;
541
542 par->crtc[VGA_CRTC_V_BLANK_START] = yres + lower - 1;
543 par->crtc[VGA_CRTC_V_SYNC_START] = yres + lower - 1;
544 if ((yres + lower - 1) & 0x100)
545 r7 |= 0x0C;
546 if ((yres + lower - 1) & 0x200) {
547 par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20;
548 r7 |= 0x80;
549 }
550
551 /* disabled IRQ */
552 par->crtc[VGA_CRTC_V_SYNC_END] =
553 ((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
554 /* 0x7F for VGA, but some SVGA chips require all 8 bits to be set */
555 par->crtc[VGA_CRTC_V_BLANK_END] = (yres + lower - 1 + vslen) & 0xFF;
556
557 par->crtc[VGA_CRTC_UNDERLINE] = 0x00;
558 par->crtc[VGA_CRTC_MODE] = 0xC3 ;
559 par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
560 par->crtc[VGA_CRTC_OVERFLOW] = r7;
561
562 par->vss = 0x00; /* 3DA */
563
564 for (i = 0x00; i < 0x10; i++)
565 par->atc[i] = i;
566 par->atc[VGA_ATC_MODE] = 0x81;
567 par->atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */
568 par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
569 par->atc[VGA_ATC_COLOR_PAGE] = 0x00;
570
571 par->misc = 0xC3;
572 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
573 par->misc &= ~0x40;
574 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
575 par->misc &= ~0x80;
576
577 par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;
578 par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
579 par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
580 par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;
581
582 par->gdc[VGA_GFX_SR_VALUE] = 0x00;
583 par->gdc[VGA_GFX_SR_ENABLE] = 0x00;
584 par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
585 par->gdc[VGA_GFX_DATA_ROTATE] = 0x00;
586 par->gdc[VGA_GFX_PLANE_READ] = 0;
587 par->gdc[VGA_GFX_MODE] = 0x02;
588 par->gdc[VGA_GFX_MISC] = 0x05;
589 par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
590 par->gdc[VGA_GFX_BIT_MASK] = 0xFF;
591
592 base = (yoffset * vxres + (xoffset & ~7)) >> 2;
593 switch (bpp) {
594 case 8:
595 par->crtc[VGA_CRTC_OFFSET] = vxres >> 3;
596 par->ext_offset = vxres >> 11;
597 par->pixelpipe_cfg1 = DISPLAY_8BPP_MODE;
598 par->bitblt_cntl = COLEXP_8BPP;
599 break;
600 case 15: /* 0rrrrrgg gggbbbbb */
601 case 16: /* rrrrrggg gggbbbbb */
602 par->pixelpipe_cfg1 = (var->green.length == 6) ?
603 DISPLAY_16BPP_MODE : DISPLAY_15BPP_MODE;
604 par->crtc[VGA_CRTC_OFFSET] = vxres >> 2;
605 par->ext_offset = vxres >> 10;
606 par->bitblt_cntl = COLEXP_16BPP;
607 base *= 2;
608 break;
609 case 24:
610 par->crtc[VGA_CRTC_OFFSET] = (vxres * 3) >> 3;
611 par->ext_offset = (vxres * 3) >> 11;
612 par->pixelpipe_cfg1 = DISPLAY_24BPP_MODE;
613 par->bitblt_cntl = COLEXP_24BPP;
614 base &= 0xFFFFFFFE; /* ...ignore the last bit. */
615 base *= 3;
616 break;
617 case 32:
618 par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
619 par->ext_offset = vxres >> 9;
620 par->pixelpipe_cfg1 = DISPLAY_32BPP_MODE;
621 par->bitblt_cntl = COLEXP_RESERVED; /* Unimplemented on i740 */
622 base *= 4;
623 break;
624 }
625
626 par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
627 par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
628 par->ext_start_addr =
629 ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
630 par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
631
632 par->pixelpipe_cfg0 = DAC_8_BIT;
633
634 par->pixelpipe_cfg2 = DISPLAY_GAMMA_ENABLE | OVERLAY_GAMMA_ENABLE;
635 par->io_cntl = EXTENDED_CRTC_CNTL;
636 par->address_mapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE;
637 par->display_cntl = HIRES_MODE;
638
639 /* Set the MCLK freq */
640 par->pll_cntl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */
641
642 /* Calculate the extended CRTC regs */
643 par->ext_vert_total = (ytotal - 2) >> 8;
644 par->ext_vert_disp_end = (yres - 1) >> 8;
645 par->ext_vert_sync_start = (yres + lower) >> 8;
646 par->ext_vert_blank_start = (yres + lower) >> 8;
647 par->ext_horiz_total = ((xtotal >> 3) - 5) >> 8;
648 par->ext_horiz_blank = (((xres + right) >> 3) & 0x40) >> 6;
649
650 par->interlace_cntl = INTERLACE_DISABLE;
651
652 /* Set the overscan color to 0. (NOTE: This only affects >8bpp mode) */
653 par->atc[VGA_ATC_OVERSCAN] = 0;
654
655 /* Calculate VCLK that most closely matches the requested dot clock */
656 i740_calc_vclk((((u32)1e9) / var->pixclock) * (u32)(1e3), par);
657
658 /* Since we program the clocks ourselves, always use VCLK2. */
659 par->misc |= 0x0C;
660
661 /* Calculate the FIFO Watermark and Burst Length. */
662 par->lmi_fifo_watermark =
663 i740_calc_fifo(par, 1000000 / var->pixclock, bpp);
664
665 return 0;
666}
667
668static int i740fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
669{
670 switch (var->bits_per_pixel) {
671 case 8:
672 var->red.offset = var->green.offset = var->blue.offset = 0;
673 var->red.length = var->green.length = var->blue.length = 8;
674 break;
675 case 16:
676 switch (var->green.length) {
677 default:
678 case 5:
679 var->red.offset = 10;
680 var->green.offset = 5;
681 var->blue.offset = 0;
682 var->red.length = 5;
683 var->green.length = 5;
684 var->blue.length = 5;
685 break;
686 case 6:
687 var->red.offset = 11;
688 var->green.offset = 5;
689 var->blue.offset = 0;
690 var->red.length = var->blue.length = 5;
691 break;
692 }
693 break;
694 case 24:
695 var->red.offset = 16;
696 var->green.offset = 8;
697 var->blue.offset = 0;
698 var->red.length = var->green.length = var->blue.length = 8;
699 break;
700 case 32:
701 var->transp.offset = 24;
702 var->red.offset = 16;
703 var->green.offset = 8;
704 var->blue.offset = 0;
705 var->transp.length = 8;
706 var->red.length = var->green.length = var->blue.length = 8;
707 break;
708 default:
709 return -EINVAL;
710 }
711
712 if (var->xres > var->xres_virtual)
713 var->xres_virtual = var->xres;
714
715 if (var->yres > var->yres_virtual)
716 var->yres_virtual = var->yres;
717
718 if (info->monspecs.hfmax && info->monspecs.vfmax &&
719 info->monspecs.dclkmax && fb_validate_mode(var, info) < 0)
720 return -EINVAL;
721
722 return 0;
723}
724
725static void vga_protect(struct i740fb_par *par)
726{
727 /* disable the display */
728 i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0x20, 0x20);
729
730 i740inb(par, 0x3DA);
731 i740outb(par, VGA_ATT_W, 0x00); /* enable pallete access */
732}
733
734static void vga_unprotect(struct i740fb_par *par)
735{
736 /* reenable display */
737 i740outreg_mask(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE, 0, 0x20);
738
739 i740inb(par, 0x3DA);
740 i740outb(par, VGA_ATT_W, 0x20); /* disable pallete access */
741}
742
743static int i740fb_set_par(struct fb_info *info)
744{
745 struct i740fb_par *par = info->par;
746 u32 itemp;
747 int i;
748
749 i = i740fb_decode_var(&info->var, par, info);
750 if (i)
751 return i;
752
753 memset(info->screen_base, 0, info->screen_size);
754
755 vga_protect(par);
756
757 i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE);
758
759 mdelay(1);
760
761 i740outreg(par, XRX, VCLK2_VCO_M, par->video_clk2_m);
762 i740outreg(par, XRX, VCLK2_VCO_N, par->video_clk2_n);
763 i740outreg(par, XRX, VCLK2_VCO_MN_MSBS, par->video_clk2_mn_msbs);
764 i740outreg(par, XRX, VCLK2_VCO_DIV_SEL, par->video_clk2_div_sel);
765
766 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0,
767 par->pixelpipe_cfg0 & DAC_8_BIT, 0x80);
768
769 i740inb(par, 0x3DA);
770 i740outb(par, 0x3C0, 0x00);
771
772 /* update misc output register */
773 i740outb(par, VGA_MIS_W, par->misc | 0x01);
774
775 /* synchronous reset on */
776 i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x01);
777 /* write sequencer registers */
778 i740outreg(par, VGA_SEQ_I, VGA_SEQ_CLOCK_MODE,
779 par->seq[VGA_SEQ_CLOCK_MODE] | 0x20);
780 for (i = 2; i < VGA_SEQ_C; i++)
781 i740outreg(par, VGA_SEQ_I, i, par->seq[i]);
782
783 /* synchronous reset off */
784 i740outreg(par, VGA_SEQ_I, VGA_SEQ_RESET, 0x03);
785
786 /* deprotect CRT registers 0-7 */
787 i740outreg(par, VGA_CRT_IC, VGA_CRTC_V_SYNC_END,
788 par->crtc[VGA_CRTC_V_SYNC_END]);
789
790 /* write CRT registers */
791 for (i = 0; i < VGA_CRT_C; i++)
792 i740outreg(par, VGA_CRT_IC, i, par->crtc[i]);
793
794 /* write graphics controller registers */
795 for (i = 0; i < VGA_GFX_C; i++)
796 i740outreg(par, VGA_GFX_I, i, par->gdc[i]);
797
798 /* write attribute controller registers */
799 for (i = 0; i < VGA_ATT_C; i++) {
800 i740inb(par, VGA_IS1_RC); /* reset flip-flop */
801 i740outb(par, VGA_ATT_IW, i);
802 i740outb(par, VGA_ATT_IW, par->atc[i]);
803 }
804
805 i740inb(par, VGA_IS1_RC);
806 i740outb(par, VGA_ATT_IW, 0x20);
807
808 i740outreg(par, VGA_CRT_IC, EXT_VERT_TOTAL, par->ext_vert_total);
809 i740outreg(par, VGA_CRT_IC, EXT_VERT_DISPLAY, par->ext_vert_disp_end);
810 i740outreg(par, VGA_CRT_IC, EXT_VERT_SYNC_START,
811 par->ext_vert_sync_start);
812 i740outreg(par, VGA_CRT_IC, EXT_VERT_BLANK_START,
813 par->ext_vert_blank_start);
814 i740outreg(par, VGA_CRT_IC, EXT_HORIZ_TOTAL, par->ext_horiz_total);
815 i740outreg(par, VGA_CRT_IC, EXT_HORIZ_BLANK, par->ext_horiz_blank);
816 i740outreg(par, VGA_CRT_IC, EXT_OFFSET, par->ext_offset);
817 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI, par->ext_start_addr_hi);
818 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR, par->ext_start_addr);
819
820 i740outreg_mask(par, VGA_CRT_IC, INTERLACE_CNTL,
821 par->interlace_cntl, INTERLACE_ENABLE);
822 i740outreg_mask(par, XRX, ADDRESS_MAPPING, par->address_mapping, 0x1F);
823 i740outreg_mask(par, XRX, BITBLT_CNTL, par->bitblt_cntl, COLEXP_MODE);
824 i740outreg_mask(par, XRX, DISPLAY_CNTL,
825 par->display_cntl, VGA_WRAP_MODE | GUI_MODE);
826 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_0, par->pixelpipe_cfg0, 0x9B);
827 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_2, par->pixelpipe_cfg2, 0x0C);
828
829 i740outreg(par, XRX, PLL_CNTL, par->pll_cntl);
830
831 i740outreg_mask(par, XRX, PIXPIPE_CONFIG_1,
832 par->pixelpipe_cfg1, DISPLAY_COLOR_MODE);
833
834 itemp = readl(par->regs + FWATER_BLC);
835 itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK);
836 itemp |= par->lmi_fifo_watermark;
837 writel(itemp, par->regs + FWATER_BLC);
838
839 i740outreg(par, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ);
840
841 i740outreg_mask(par, MRX, COL_KEY_CNTL_1, 0, BLANK_DISP_OVERLAY);
842 i740outreg_mask(par, XRX, IO_CTNL,
843 par->io_cntl, EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
844
845 if (par->pixelpipe_cfg1 != DISPLAY_8BPP_MODE) {
846 i740outb(par, VGA_PEL_MSK, 0xFF);
847 i740outb(par, VGA_PEL_IW, 0x00);
848 for (i = 0; i < 256; i++) {
849 itemp = (par->pixelpipe_cfg0 & DAC_8_BIT) ? i : i >> 2;
850 i740outb(par, VGA_PEL_D, itemp);
851 i740outb(par, VGA_PEL_D, itemp);
852 i740outb(par, VGA_PEL_D, itemp);
853 }
854 }
855
856 /* Wait for screen to stabilize. */
857 mdelay(50);
858 vga_unprotect(par);
859
860 info->fix.line_length =
861 info->var.xres_virtual * info->var.bits_per_pixel / 8;
862 if (info->var.bits_per_pixel == 8)
863 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
864 else
865 info->fix.visual = FB_VISUAL_TRUECOLOR;
866
867 return 0;
868}
869
870static int i740fb_setcolreg(unsigned regno, unsigned red, unsigned green,
871 unsigned blue, unsigned transp,
872 struct fb_info *info)
873{
874 u32 r, g, b;
875
876 dev_dbg(info->device, "setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
877 regno, red, green, blue, transp, info->var.bits_per_pixel);
878
879 switch (info->fix.visual) {
880 case FB_VISUAL_PSEUDOCOLOR:
881 if (regno >= 256)
882 return -EINVAL;
883 i740outb(info->par, VGA_PEL_IW, regno);
884 i740outb(info->par, VGA_PEL_D, red >> 8);
885 i740outb(info->par, VGA_PEL_D, green >> 8);
886 i740outb(info->par, VGA_PEL_D, blue >> 8);
887 break;
888 case FB_VISUAL_TRUECOLOR:
889 if (regno >= 16)
890 return -EINVAL;
891 r = (red >> (16 - info->var.red.length))
892 << info->var.red.offset;
893 b = (blue >> (16 - info->var.blue.length))
894 << info->var.blue.offset;
895 g = (green >> (16 - info->var.green.length))
896 << info->var.green.offset;
897 ((u32 *) info->pseudo_palette)[regno] = r | g | b;
898 break;
899 default:
900 return -EINVAL;
901 }
902
903 return 0;
904}
905
906static int i740fb_pan_display(struct fb_var_screeninfo *var,
907 struct fb_info *info)
908{
909 struct i740fb_par *par = info->par;
910 u32 base = (var->yoffset * info->var.xres_virtual
911 + (var->xoffset & ~7)) >> 2;
912
913 dev_dbg(info->device, "pan_display: xoffset: %i yoffset: %i base: %i\n",
914 var->xoffset, var->yoffset, base);
915
916 switch (info->var.bits_per_pixel) {
917 case 8:
918 break;
919 case 15:
920 case 16:
921 base *= 2;
922 break;
923 case 24:
924 /*
925 * The last bit does not seem to have any effect on the start
926 * address register in 24bpp mode, so...
927 */
928 base &= 0xFFFFFFFE; /* ...ignore the last bit. */
929 base *= 3;
930 break;
931 case 32:
932 base *= 4;
933 break;
934 }
935
936 par->crtc[VGA_CRTC_START_LO] = base & 0x000000FF;
937 par->crtc[VGA_CRTC_START_HI] = (base & 0x0000FF00) >> 8;
938 par->ext_start_addr_hi = (base & 0x3FC00000) >> 22;
939 par->ext_start_addr =
940 ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE;
941
942 i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_LO, base & 0x000000FF);
943 i740outreg(par, VGA_CRT_IC, VGA_CRTC_START_HI,
944 (base & 0x0000FF00) >> 8);
945 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR_HI,
946 (base & 0x3FC00000) >> 22);
947 i740outreg(par, VGA_CRT_IC, EXT_START_ADDR,
948 ((base & 0x003F0000) >> 16) | EXT_START_ADDR_ENABLE);
949
950 return 0;
951}
952
953static int i740fb_blank(int blank_mode, struct fb_info *info)
954{
955 struct i740fb_par *par = info->par;
956
957 unsigned char SEQ01;
958 int DPMSSyncSelect;
959
960 switch (blank_mode) {
961 case FB_BLANK_UNBLANK:
962 case FB_BLANK_NORMAL:
963 SEQ01 = 0x00;
964 DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
965 break;
966 case FB_BLANK_VSYNC_SUSPEND:
967 SEQ01 = 0x20;
968 DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
969 break;
970 case FB_BLANK_HSYNC_SUSPEND:
971 SEQ01 = 0x20;
972 DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
973 break;
974 case FB_BLANK_POWERDOWN:
975 SEQ01 = 0x20;
976 DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
977 break;
978 default:
979 return -EINVAL;
980 }
981 /* Turn the screen on/off */
982 i740outb(par, SRX, 0x01);
983 SEQ01 |= i740inb(par, SRX + 1) & ~0x20;
984 i740outb(par, SRX, 0x01);
985 i740outb(par, SRX + 1, SEQ01);
986
987 /* Set the DPMS mode */
988 i740outreg(par, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect);
989
990 /* Let fbcon do a soft blank for us */
991 return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
992}
993
994static struct fb_ops i740fb_ops = {
995 .owner = THIS_MODULE,
996 .fb_open = i740fb_open,
997 .fb_release = i740fb_release,
998 .fb_check_var = i740fb_check_var,
999 .fb_set_par = i740fb_set_par,
1000 .fb_setcolreg = i740fb_setcolreg,
1001 .fb_blank = i740fb_blank,
1002 .fb_pan_display = i740fb_pan_display,
1003 .fb_fillrect = cfb_fillrect,
1004 .fb_copyarea = cfb_copyarea,
1005 .fb_imageblit = cfb_imageblit,
1006};
1007
1008/* ------------------------------------------------------------------------- */
1009
1010static int __devinit i740fb_probe(struct pci_dev *dev,
1011 const struct pci_device_id *ent)
1012{
1013 struct fb_info *info;
1014 struct i740fb_par *par;
1015 int ret, tmp;
1016 bool found = false;
1017 u8 *edid;
1018
1019 info = framebuffer_alloc(sizeof(struct i740fb_par), &(dev->dev));
1020 if (!info) {
1021 dev_err(&(dev->dev), "cannot allocate framebuffer\n");
1022 return -ENOMEM;
1023 }
1024
1025 par = info->par;
1026 mutex_init(&par->open_lock);
1027
1028 info->var.activate = FB_ACTIVATE_NOW;
1029 info->var.bits_per_pixel = 8;
1030 info->fbops = &i740fb_ops;
1031 info->pseudo_palette = par->pseudo_palette;
1032
1033 ret = pci_enable_device(dev);
1034 if (ret) {
1035 dev_err(info->device, "cannot enable PCI device\n");
1036 goto err_enable_device;
1037 }
1038
1039 ret = pci_request_regions(dev, info->fix.id);
1040 if (ret) {
1041 dev_err(info->device, "error requesting regions\n");
1042 goto err_request_regions;
1043 }
1044
1045 info->screen_base = pci_ioremap_bar(dev, 0);
1046 if (!info->screen_base) {
1047 dev_err(info->device, "error remapping base\n");
1048 ret = -ENOMEM;
1049 goto err_ioremap_1;
1050 }
1051
1052 par->regs = pci_ioremap_bar(dev, 1);
1053 if (!par->regs) {
1054 dev_err(info->device, "error remapping MMIO\n");
1055 ret = -ENOMEM;
1056 goto err_ioremap_2;
1057 }
1058
1059 /* detect memory size */
1060 if ((i740inreg(par, XRX, DRAM_ROW_TYPE) & DRAM_ROW_1)
1061 == DRAM_ROW_1_SDRAM)
1062 i740outb(par, XRX, DRAM_ROW_BNDRY_1);
1063 else
1064 i740outb(par, XRX, DRAM_ROW_BNDRY_0);
1065 info->screen_size = i740inb(par, XRX + 1) * 1024 * 1024;
1066 /* detect memory type */
1067 tmp = i740inreg(par, XRX, DRAM_ROW_CNTL_LO);
1068 par->has_sgram = !((tmp & DRAM_RAS_TIMING) ||
1069 (tmp & DRAM_RAS_PRECHARGE));
1070
1071 printk(KERN_INFO "fb%d: Intel740 on %s, %ld KB %s\n", info->node,
1072 pci_name(dev), info->screen_size >> 10,
1073 par->has_sgram ? "SGRAM" : "SDRAM");
1074
1075 info->fix = i740fb_fix;
1076 info->fix.mmio_start = pci_resource_start(dev, 1);
1077 info->fix.mmio_len = pci_resource_len(dev, 1);
1078 info->fix.smem_start = pci_resource_start(dev, 0);
1079 info->fix.smem_len = info->screen_size;
1080 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1081
1082 if (i740fb_setup_ddc_bus(info) == 0) {
1083 par->ddc_registered = true;
1084 edid = fb_ddc_read(&par->ddc_adapter);
1085 if (edid) {
1086 fb_edid_to_monspecs(edid, &info->monspecs);
1087 kfree(edid);
1088 if (!info->monspecs.modedb)
1089 dev_err(info->device,
1090 "error getting mode database\n");
1091 else {
1092 const struct fb_videomode *m;
1093
1094 fb_videomode_to_modelist(
1095 info->monspecs.modedb,
1096 info->monspecs.modedb_len,
1097 &info->modelist);
1098 m = fb_find_best_display(&info->monspecs,
1099 &info->modelist);
1100 if (m) {
1101 fb_videomode_to_var(&info->var, m);
1102 /* fill all other info->var's fields */
1103 if (!i740fb_check_var(&info->var, info))
1104 found = true;
1105 }
1106 }
1107 }
1108 }
1109
1110 if (!mode_option && !found)
1111 mode_option = "640x480-8@60";
1112
1113 if (mode_option) {
1114 ret = fb_find_mode(&info->var, info, mode_option,
1115 info->monspecs.modedb,
1116 info->monspecs.modedb_len,
1117 NULL, info->var.bits_per_pixel);
1118 if (!ret || ret == 4) {
1119 dev_err(info->device, "mode %s not found\n",
1120 mode_option);
1121 ret = -EINVAL;
1122 }
1123 }
1124
1125 fb_destroy_modedb(info->monspecs.modedb);
1126 info->monspecs.modedb = NULL;
1127
1128 /* maximize virtual vertical size for fast scrolling */
1129 info->var.yres_virtual = info->fix.smem_len * 8 /
1130 (info->var.bits_per_pixel * info->var.xres_virtual);
1131
1132 if (ret == -EINVAL)
1133 goto err_find_mode;
1134
1135 ret = fb_alloc_cmap(&info->cmap, 256, 0);
1136 if (ret) {
1137 dev_err(info->device, "cannot allocate colormap\n");
1138 goto err_alloc_cmap;
1139 }
1140
1141 ret = register_framebuffer(info);
1142 if (ret) {
1143 dev_err(info->device, "error registering framebuffer\n");
1144 goto err_reg_framebuffer;
1145 }
1146
1147 printk(KERN_INFO "fb%d: %s frame buffer device\n",
1148 info->node, info->fix.id);
1149 pci_set_drvdata(dev, info);
1150#ifdef CONFIG_MTRR
1151 if (mtrr) {
1152 par->mtrr_reg = -1;
1153 par->mtrr_reg = mtrr_add(info->fix.smem_start,
1154 info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
1155 }
1156#endif
1157 return 0;
1158
1159err_reg_framebuffer:
1160 fb_dealloc_cmap(&info->cmap);
1161err_alloc_cmap:
1162err_find_mode:
1163 if (par->ddc_registered)
1164 i2c_del_adapter(&par->ddc_adapter);
1165 pci_iounmap(dev, par->regs);
1166err_ioremap_2:
1167 pci_iounmap(dev, info->screen_base);
1168err_ioremap_1:
1169 pci_release_regions(dev);
1170err_request_regions:
1171/* pci_disable_device(dev); */
1172err_enable_device:
1173 framebuffer_release(info);
1174 return ret;
1175}
1176
1177static void __devexit i740fb_remove(struct pci_dev *dev)
1178{
1179 struct fb_info *info = pci_get_drvdata(dev);
1180
1181 if (info) {
1182 struct i740fb_par *par = info->par;
1183
1184#ifdef CONFIG_MTRR
1185 if (par->mtrr_reg >= 0) {
1186 mtrr_del(par->mtrr_reg, 0, 0);
1187 par->mtrr_reg = -1;
1188 }
1189#endif
1190 unregister_framebuffer(info);
1191 fb_dealloc_cmap(&info->cmap);
1192 if (par->ddc_registered)
1193 i2c_del_adapter(&par->ddc_adapter);
1194 pci_iounmap(dev, par->regs);
1195 pci_iounmap(dev, info->screen_base);
1196 pci_release_regions(dev);
1197/* pci_disable_device(dev); */
1198 pci_set_drvdata(dev, NULL);
1199 framebuffer_release(info);
1200 }
1201}
1202
1203#ifdef CONFIG_PM
1204static int i740fb_suspend(struct pci_dev *dev, pm_message_t state)
1205{
1206 struct fb_info *info = pci_get_drvdata(dev);
1207 struct i740fb_par *par = info->par;
1208
1209 /* don't disable console during hibernation and wakeup from it */
1210 if (state.event == PM_EVENT_FREEZE || state.event == PM_EVENT_PRETHAW)
1211 return 0;
1212
1213 console_lock();
1214 mutex_lock(&(par->open_lock));
1215
1216 /* do nothing if framebuffer is not active */
1217 if (par->ref_count == 0) {
1218 mutex_unlock(&(par->open_lock));
1219 console_unlock();
1220 return 0;
1221 }
1222
1223 fb_set_suspend(info, 1);
1224
1225 pci_save_state(dev);
1226 pci_disable_device(dev);
1227 pci_set_power_state(dev, pci_choose_state(dev, state));
1228
1229 mutex_unlock(&(par->open_lock));
1230 console_unlock();
1231
1232 return 0;
1233}
1234
1235static int i740fb_resume(struct pci_dev *dev)
1236{
1237 struct fb_info *info = pci_get_drvdata(dev);
1238 struct i740fb_par *par = info->par;
1239
1240 console_lock();
1241 mutex_lock(&(par->open_lock));
1242
1243 if (par->ref_count == 0)
1244 goto fail;
1245
1246 pci_set_power_state(dev, PCI_D0);
1247 pci_restore_state(dev);
1248 if (pci_enable_device(dev))
1249 goto fail;
1250
1251 i740fb_set_par(info);
1252 fb_set_suspend(info, 0);
1253
1254fail:
1255 mutex_unlock(&(par->open_lock));
1256 console_unlock();
1257 return 0;
1258}
1259#else
1260#define i740fb_suspend NULL
1261#define i740fb_resume NULL
1262#endif /* CONFIG_PM */
1263
1264#define I740_ID_PCI 0x00d1
1265#define I740_ID_AGP 0x7800
1266
1267static DEFINE_PCI_DEVICE_TABLE(i740fb_id_table) = {
1268 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_PCI) },
1269 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, I740_ID_AGP) },
1270 { 0 }
1271};
1272MODULE_DEVICE_TABLE(pci, i740fb_id_table);
1273
1274static struct pci_driver i740fb_driver = {
1275 .name = "i740fb",
1276 .id_table = i740fb_id_table,
1277 .probe = i740fb_probe,
1278 .remove = __devexit_p(i740fb_remove),
1279 .suspend = i740fb_suspend,
1280 .resume = i740fb_resume,
1281};
1282
1283#ifndef MODULE
1284static int __init i740fb_setup(char *options)
1285{
1286 char *opt;
1287
1288 if (!options || !*options)
1289 return 0;
1290
1291 while ((opt = strsep(&options, ",")) != NULL) {
1292 if (!*opt)
1293 continue;
1294#ifdef CONFIG_MTRR
1295 else if (!strncmp(opt, "mtrr:", 5))
1296 mtrr = simple_strtoul(opt + 5, NULL, 0);
1297#endif
1298 else
1299 mode_option = opt;
1300 }
1301
1302 return 0;
1303}
1304#endif
1305
1306int __init i740fb_init(void)
1307{
1308#ifndef MODULE
1309 char *option = NULL;
1310
1311 if (fb_get_options("i740fb", &option))
1312 return -ENODEV;
1313 i740fb_setup(option);
1314#endif
1315
1316 return pci_register_driver(&i740fb_driver);
1317}
1318
1319static void __exit i740fb_exit(void)
1320{
1321 pci_unregister_driver(&i740fb_driver);
1322}
1323
1324module_init(i740fb_init);
1325module_exit(i740fb_exit);
1326
1327MODULE_AUTHOR("(c) 2011 Ondrej Zary <linux@rainbow-software.org>");
1328MODULE_LICENSE("GPL");
1329MODULE_DESCRIPTION("fbdev driver for Intel740");
1330
1331module_param(mode_option, charp, 0444);
1332MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
1333
1334#ifdef CONFIG_MTRR
1335module_param(mtrr, int, 0444);
1336MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
1337#endif
diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/msm/mddi_client_nt35399.c
index f239f4a25e01..7fcd67e132bf 100644
--- a/drivers/video/msm/mddi_client_nt35399.c
+++ b/drivers/video/msm/mddi_client_nt35399.c
@@ -155,14 +155,10 @@ static int setup_vsync(struct panel_info *panel, int init)
155 ret = 0; 155 ret = 0;
156 goto uninit; 156 goto uninit;
157 } 157 }
158 ret = gpio_request(gpio, "vsync"); 158 ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
159 if (ret) 159 if (ret)
160 goto err_request_gpio_failed; 160 goto err_request_gpio_failed;
161 161
162 ret = gpio_direction_input(gpio);
163 if (ret)
164 goto err_gpio_direction_input_failed;
165
166 ret = irq = gpio_to_irq(gpio); 162 ret = irq = gpio_to_irq(gpio);
167 if (ret < 0) 163 if (ret < 0)
168 goto err_get_irq_num_failed; 164 goto err_get_irq_num_failed;
@@ -180,7 +176,6 @@ uninit:
180 free_irq(gpio_to_irq(gpio), panel->client_data); 176 free_irq(gpio_to_irq(gpio), panel->client_data);
181err_request_irq_failed: 177err_request_irq_failed:
182err_get_irq_num_failed: 178err_get_irq_num_failed:
183err_gpio_direction_input_failed:
184 gpio_free(gpio); 179 gpio_free(gpio);
185err_request_gpio_failed: 180err_request_gpio_failed:
186 return ret; 181 return ret;
diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/msm/mddi_client_toshiba.c
index f9bc932ac46b..053eb6877330 100644
--- a/drivers/video/msm/mddi_client_toshiba.c
+++ b/drivers/video/msm/mddi_client_toshiba.c
@@ -186,14 +186,10 @@ static int setup_vsync(struct panel_info *panel,
186 ret = 0; 186 ret = 0;
187 goto uninit; 187 goto uninit;
188 } 188 }
189 ret = gpio_request(gpio, "vsync"); 189 ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
190 if (ret) 190 if (ret)
191 goto err_request_gpio_failed; 191 goto err_request_gpio_failed;
192 192
193 ret = gpio_direction_input(gpio);
194 if (ret)
195 goto err_gpio_direction_input_failed;
196
197 ret = irq = gpio_to_irq(gpio); 193 ret = irq = gpio_to_irq(gpio);
198 if (ret < 0) 194 if (ret < 0)
199 goto err_get_irq_num_failed; 195 goto err_get_irq_num_failed;
@@ -210,7 +206,6 @@ uninit:
210 free_irq(gpio_to_irq(gpio), panel); 206 free_irq(gpio_to_irq(gpio), panel);
211err_request_irq_failed: 207err_request_irq_failed:
212err_get_irq_num_failed: 208err_get_irq_num_failed:
213err_gpio_direction_input_failed:
214 gpio_free(gpio); 209 gpio_free(gpio);
215err_request_gpio_failed: 210err_request_gpio_failed:
216 return ret; 211 return ret;
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 7e8bd8e08a98..e3d3d135aa48 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -22,7 +22,7 @@
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#include <asm/gpio.h> 25#include <linux/gpio.h>
26#include "omapfb.h" 26#include "omapfb.h"
27 27
28#define MODULE_NAME "omapfb-lcd_h3" 28#define MODULE_NAME "omapfb-lcd_h3"
@@ -32,20 +32,18 @@ static int innovator1610_panel_init(struct lcd_panel *panel,
32{ 32{
33 int r = 0; 33 int r = 0;
34 34
35 if (gpio_request(14, "lcd_en0")) { 35 /* configure GPIO(14, 15) as outputs */
36 if (gpio_request_one(14, GPIOF_OUT_INIT_LOW, "lcd_en0")) {
36 pr_err(MODULE_NAME ": can't request GPIO 14\n"); 37 pr_err(MODULE_NAME ": can't request GPIO 14\n");
37 r = -1; 38 r = -1;
38 goto exit; 39 goto exit;
39 } 40 }
40 if (gpio_request(15, "lcd_en1")) { 41 if (gpio_request_one(15, GPIOF_OUT_INIT_LOW, "lcd_en1")) {
41 pr_err(MODULE_NAME ": can't request GPIO 15\n"); 42 pr_err(MODULE_NAME ": can't request GPIO 15\n");
42 gpio_free(14); 43 gpio_free(14);
43 r = -1; 44 r = -1;
44 goto exit; 45 goto exit;
45 } 46 }
46 /* configure GPIO(14, 15) as outputs */
47 gpio_direction_output(14, 0);
48 gpio_direction_output(15, 0);
49exit: 47exit:
50 return r; 48 return r;
51} 49}
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index 8d546dd55e81..e3880c4a0bb1 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -609,19 +609,7 @@ static struct spi_driver mipid_spi_driver = {
609 .remove = __devexit_p(mipid_spi_remove), 609 .remove = __devexit_p(mipid_spi_remove),
610}; 610};
611 611
612static int __init mipid_drv_init(void) 612module_spi_driver(mipid_spi_driver);
613{
614 spi_register_driver(&mipid_spi_driver);
615
616 return 0;
617}
618module_init(mipid_drv_init);
619
620static void __exit mipid_drv_cleanup(void)
621{
622 spi_unregister_driver(&mipid_spi_driver);
623}
624module_exit(mipid_drv_cleanup);
625 613
626MODULE_DESCRIPTION("MIPI display driver"); 614MODULE_DESCRIPTION("MIPI display driver");
627MODULE_LICENSE("GPL"); 615MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 51a87e149e24..d26f37ac69d8 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -809,18 +809,7 @@ static struct spi_driver acx565akm_spi_driver = {
809 .remove = __devexit_p(acx565akm_spi_remove), 809 .remove = __devexit_p(acx565akm_spi_remove),
810}; 810};
811 811
812static int __init acx565akm_init(void) 812module_spi_driver(acx565akm_spi_driver);
813{
814 return spi_register_driver(&acx565akm_spi_driver);
815}
816
817static void __exit acx565akm_exit(void)
818{
819 spi_unregister_driver(&acx565akm_spi_driver);
820}
821
822module_init(acx565akm_init);
823module_exit(acx565akm_exit);
824 813
825MODULE_AUTHOR("Nokia Corporation"); 814MODULE_AUTHOR("Nokia Corporation");
826MODULE_DESCRIPTION("acx565akm LCD Driver"); 815MODULE_DESCRIPTION("acx565akm LCD Driver");
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index e0eb35be303e..0841cc2b3f77 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -264,16 +264,6 @@ static struct spi_driver lb035q02_spi_driver = {
264 .remove = __devexit_p(lb035q02_panel_spi_remove), 264 .remove = __devexit_p(lb035q02_panel_spi_remove),
265}; 265};
266 266
267static int __init lb035q02_panel_drv_init(void) 267module_spi_driver(lb035q02_spi_driver);
268{
269 return spi_register_driver(&lb035q02_spi_driver);
270}
271
272static void __exit lb035q02_panel_drv_exit(void)
273{
274 spi_unregister_driver(&lb035q02_spi_driver);
275}
276 268
277module_init(lb035q02_panel_drv_init);
278module_exit(lb035q02_panel_drv_exit);
279MODULE_LICENSE("GPL"); 269MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 0eb31caddca8..8b38b39213f4 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -350,18 +350,8 @@ static struct spi_driver nec_8048_spi_driver = {
350 }, 350 },
351}; 351};
352 352
353static int __init nec_8048_lcd_init(void) 353module_spi_driver(nec_8048_spi_driver);
354{
355 return spi_register_driver(&nec_8048_spi_driver);
356}
357
358static void __exit nec_8048_lcd_exit(void)
359{
360 return spi_unregister_driver(&nec_8048_spi_driver);
361}
362 354
363module_init(nec_8048_lcd_init);
364module_exit(nec_8048_lcd_exit);
365MODULE_AUTHOR("Erik Gilling <konkers@android.com>"); 355MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
366MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver"); 356MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
367MODULE_LICENSE("GPL"); 357MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 00c5c615585f..0f21fa5a16ae 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -1019,14 +1019,12 @@ static int taal_probe(struct omap_dss_device *dssdev)
1019 if (panel_data->use_ext_te) { 1019 if (panel_data->use_ext_te) {
1020 int gpio = panel_data->ext_te_gpio; 1020 int gpio = panel_data->ext_te_gpio;
1021 1021
1022 r = gpio_request(gpio, "taal irq"); 1022 r = gpio_request_one(gpio, GPIOF_IN, "taal irq");
1023 if (r) { 1023 if (r) {
1024 dev_err(&dssdev->dev, "GPIO request failed\n"); 1024 dev_err(&dssdev->dev, "GPIO request failed\n");
1025 goto err_gpio; 1025 goto err_gpio;
1026 } 1026 }
1027 1027
1028 gpio_direction_input(gpio);
1029
1030 r = request_irq(gpio_to_irq(gpio), taal_te_isr, 1028 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
1031 IRQF_TRIGGER_RISING, 1029 IRQF_TRIGGER_RISING,
1032 "taal vsync", dssdev); 1030 "taal vsync", dssdev);
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index d63e5e5dbbfa..32f3fcd7f0f0 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -436,17 +436,12 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
436 } 436 }
437 437
438 if (gpio_is_valid(nreset_gpio)) { 438 if (gpio_is_valid(nreset_gpio)) {
439 ret = gpio_request(nreset_gpio, "lcd reset"); 439 ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW,
440 "lcd reset");
440 if (ret < 0) { 441 if (ret < 0) {
441 dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); 442 dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
442 goto fail_gpio_req; 443 goto fail_gpio_req;
443 } 444 }
444
445 ret = gpio_direction_output(nreset_gpio, 0);
446 if (ret < 0) {
447 dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
448 goto fail_gpio_direction;
449 }
450 } 445 }
451 446
452 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group); 447 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
@@ -455,8 +450,6 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
455 450
456 return 0; 451 return 0;
457 452
458fail_gpio_direction:
459 gpio_free(nreset_gpio);
460fail_gpio_req: 453fail_gpio_req:
461 regulator_put(tpo_td043->vcc_reg); 454 regulator_put(tpo_td043->vcc_reg);
462fail_regulator: 455fail_regulator:
@@ -583,18 +576,7 @@ static struct spi_driver tpo_td043_spi_driver = {
583 .remove = __devexit_p(tpo_td043_spi_remove), 576 .remove = __devexit_p(tpo_td043_spi_remove),
584}; 577};
585 578
586static int __init tpo_td043_init(void) 579module_spi_driver(tpo_td043_spi_driver);
587{
588 return spi_register_driver(&tpo_td043_spi_driver);
589}
590
591static void __exit tpo_td043_exit(void)
592{
593 spi_unregister_driver(&tpo_td043_spi_driver);
594}
595
596module_init(tpo_td043_init);
597module_exit(tpo_td043_exit);
598 580
599MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>"); 581MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
600MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver"); 582MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index 3a3fdc62c75b..bcd44c32a2ed 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -895,7 +895,7 @@ static int __init pvr2fb_dc_init(void)
895 895
896#ifdef CONFIG_PVR2_DMA 896#ifdef CONFIG_PVR2_DMA
897 if (request_dma(pvr2dma, "pvr2") != 0) { 897 if (request_dma(pvr2dma, "pvr2") != 0) {
898 free_irq(HW_EVENT_VSYNC, 0); 898 free_irq(HW_EVENT_VSYNC, fb_info);
899 return -EBUSY; 899 return -EBUSY;
900 } 900 }
901#endif 901#endif
@@ -914,7 +914,7 @@ static void __exit pvr2fb_dc_exit(void)
914 currentpar->mmio_base = 0; 914 currentpar->mmio_base = 0;
915 } 915 }
916 916
917 free_irq(HW_EVENT_VSYNC, 0); 917 free_irq(HW_EVENT_VSYNC, fb_info);
918#ifdef CONFIG_PVR2_DMA 918#ifdef CONFIG_PVR2_DMA
919 free_dma(pvr2dma); 919 free_dma(pvr2dma);
920#endif 920#endif
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 8384b941f6ba..f146089261f4 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -21,6 +21,7 @@
21#include <linux/fb.h> 21#include <linux/fb.h>
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/io.h>
24#include <linux/ioport.h> 25#include <linux/ioport.h>
25#include <linux/platform_device.h> 26#include <linux/platform_device.h>
26#include <linux/dma-mapping.h> 27#include <linux/dma-mapping.h>
@@ -670,7 +671,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
670 /* 671 /*
671 * Map LCD controller registers. 672 * Map LCD controller registers.
672 */ 673 */
673 fbi->reg_base = ioremap_nocache(res->start, resource_size(res)); 674 fbi->reg_base = devm_ioremap_nocache(&pdev->dev, res->start,
675 resource_size(res));
674 if (fbi->reg_base == NULL) { 676 if (fbi->reg_base == NULL) {
675 ret = -ENOMEM; 677 ret = -ENOMEM;
676 goto failed_free_info; 678 goto failed_free_info;
@@ -739,8 +741,8 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
739 /* 741 /*
740 * Register irq handler. 742 * Register irq handler.
741 */ 743 */
742 ret = request_irq(irq, pxa168fb_handle_irq, IRQF_SHARED, 744 ret = devm_request_irq(&pdev->dev, irq, pxa168fb_handle_irq,
743 info->fix.id, fbi); 745 IRQF_SHARED, info->fix.id, fbi);
744 if (ret < 0) { 746 if (ret < 0) {
745 dev_err(&pdev->dev, "unable to request IRQ\n"); 747 dev_err(&pdev->dev, "unable to request IRQ\n");
746 ret = -ENXIO; 748 ret = -ENXIO;
@@ -759,14 +761,12 @@ static int __devinit pxa168fb_probe(struct platform_device *pdev)
759 if (ret < 0) { 761 if (ret < 0) {
760 dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret); 762 dev_err(&pdev->dev, "Failed to register pxa168-fb: %d\n", ret);
761 ret = -ENXIO; 763 ret = -ENXIO;
762 goto failed_free_irq; 764 goto failed_free_cmap;
763 } 765 }
764 766
765 platform_set_drvdata(pdev, fbi); 767 platform_set_drvdata(pdev, fbi);
766 return 0; 768 return 0;
767 769
768failed_free_irq:
769 free_irq(irq, fbi);
770failed_free_cmap: 770failed_free_cmap:
771 fb_dealloc_cmap(&info->cmap); 771 fb_dealloc_cmap(&info->cmap);
772failed_free_clk: 772failed_free_clk:
@@ -808,13 +808,10 @@ static int __devexit pxa168fb_remove(struct platform_device *pdev)
808 fb_dealloc_cmap(&info->cmap); 808 fb_dealloc_cmap(&info->cmap);
809 809
810 irq = platform_get_irq(pdev, 0); 810 irq = platform_get_irq(pdev, 0);
811 free_irq(irq, fbi);
812 811
813 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len), 812 dma_free_writecombine(fbi->dev, PAGE_ALIGN(info->fix.smem_len),
814 info->screen_base, info->fix.smem_start); 813 info->screen_base, info->fix.smem_start);
815 814
816 iounmap(fbi->reg_base);
817
818 clk_disable(fbi->clk); 815 clk_disable(fbi->clk);
819 clk_put(fbi->clk); 816 clk_put(fbi->clk);
820 817
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 1d1e4f175e78..c176561a2222 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -54,6 +54,7 @@
54#include <linux/mutex.h> 54#include <linux/mutex.h>
55#include <linux/kthread.h> 55#include <linux/kthread.h>
56#include <linux/freezer.h> 56#include <linux/freezer.h>
57#include <linux/console.h>
57 58
58#include <mach/hardware.h> 59#include <mach/hardware.h>
59#include <asm/io.h> 60#include <asm/io.h>
@@ -730,9 +731,12 @@ static int overlayfb_open(struct fb_info *info, int user)
730 if (user == 0) 731 if (user == 0)
731 return -ENODEV; 732 return -ENODEV;
732 733
733 if (ofb->usage++ == 0) 734 if (ofb->usage++ == 0) {
734 /* unblank the base framebuffer */ 735 /* unblank the base framebuffer */
736 console_lock();
735 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK); 737 fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
738 console_unlock();
739 }
736 740
737 return 0; 741 return 0;
738} 742}
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 2f58cf9c813b..90df1a60bd16 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1816,6 +1816,8 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
1816 specs->modedb, specs->modedb_len, 1816 specs->modedb, specs->modedb_len,
1817 NULL, 8); 1817 NULL, 8);
1818 } else if (specs->modedb != NULL) { 1818 } else if (specs->modedb != NULL) {
1819 /* get first mode in database as fallback */
1820 modedb = specs->modedb[0];
1819 /* get preferred timing */ 1821 /* get preferred timing */
1820 if (info->monspecs.misc & FB_MISC_1ST_DETAIL) { 1822 if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
1821 int i; 1823 int i;
@@ -1826,9 +1828,6 @@ static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
1826 break; 1828 break;
1827 } 1829 }
1828 } 1830 }
1829 } else {
1830 /* otherwise, get first mode in database */
1831 modedb = specs->modedb[0];
1832 } 1831 }
1833 var->bits_per_pixel = 8; 1832 var->bits_per_pixel = 8;
1834 riva_update_var(var, &modedb); 1833 riva_update_var(var, &modedb);
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 0c63b69b6340..f3105160bf98 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -48,7 +48,8 @@
48#undef writel 48#undef writel
49#define writel(v, r) do { \ 49#define writel(v, r) do { \
50 printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ 50 printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
51 __raw_writel(v, r); } while (0) 51 __raw_writel(v, r); \
52} while (0)
52#endif /* FB_S3C_DEBUG_REGWRITE */ 53#endif /* FB_S3C_DEBUG_REGWRITE */
53 54
54/* irq_flags bits */ 55/* irq_flags bits */
@@ -81,12 +82,14 @@ struct s3c_fb;
81 * @palette: Address of palette memory, or 0 if none. 82 * @palette: Address of palette memory, or 0 if none.
82 * @has_prtcon: Set if has PRTCON register. 83 * @has_prtcon: Set if has PRTCON register.
83 * @has_shadowcon: Set if has SHADOWCON register. 84 * @has_shadowcon: Set if has SHADOWCON register.
85 * @has_blendcon: Set if has BLENDCON register.
84 * @has_clksel: Set if VIDCON0 register has CLKSEL bit. 86 * @has_clksel: Set if VIDCON0 register has CLKSEL bit.
87 * @has_fixvclk: Set if VIDCON1 register has FIXVCLK bits.
85 */ 88 */
86struct s3c_fb_variant { 89struct s3c_fb_variant {
87 unsigned int is_2443:1; 90 unsigned int is_2443:1;
88 unsigned short nr_windows; 91 unsigned short nr_windows;
89 unsigned short vidtcon; 92 unsigned int vidtcon;
90 unsigned short wincon; 93 unsigned short wincon;
91 unsigned short winmap; 94 unsigned short winmap;
92 unsigned short keycon; 95 unsigned short keycon;
@@ -99,7 +102,9 @@ struct s3c_fb_variant {
99 102
100 unsigned int has_prtcon:1; 103 unsigned int has_prtcon:1;
101 unsigned int has_shadowcon:1; 104 unsigned int has_shadowcon:1;
105 unsigned int has_blendcon:1;
102 unsigned int has_clksel:1; 106 unsigned int has_clksel:1;
107 unsigned int has_fixvclk:1;
103}; 108};
104 109
105/** 110/**
@@ -186,7 +191,6 @@ struct s3c_fb_vsync {
186 * struct s3c_fb - overall hardware state of the hardware 191 * struct s3c_fb - overall hardware state of the hardware
187 * @slock: The spinlock protection for this data sturcture. 192 * @slock: The spinlock protection for this data sturcture.
188 * @dev: The device that we bound to, for printing, etc. 193 * @dev: The device that we bound to, for printing, etc.
189 * @regs_res: The resource we claimed for the IO registers.
190 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. 194 * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
191 * @lcd_clk: The clk (sclk) feeding pixclk. 195 * @lcd_clk: The clk (sclk) feeding pixclk.
192 * @regs: The mapped hardware registers. 196 * @regs: The mapped hardware registers.
@@ -202,7 +206,6 @@ struct s3c_fb_vsync {
202struct s3c_fb { 206struct s3c_fb {
203 spinlock_t slock; 207 spinlock_t slock;
204 struct device *dev; 208 struct device *dev;
205 struct resource *regs_res;
206 struct clk *bus_clk; 209 struct clk *bus_clk;
207 struct clk *lcd_clk; 210 struct clk *lcd_clk;
208 void __iomem *regs; 211 void __iomem *regs;
@@ -565,7 +568,9 @@ static int s3c_fb_set_par(struct fb_info *info)
565 writel(data, regs + sfb->variant.vidtcon + 4); 568 writel(data, regs + sfb->variant.vidtcon + 4);
566 569
567 data = VIDTCON2_LINEVAL(var->yres - 1) | 570 data = VIDTCON2_LINEVAL(var->yres - 1) |
568 VIDTCON2_HOZVAL(var->xres - 1); 571 VIDTCON2_HOZVAL(var->xres - 1) |
572 VIDTCON2_LINEVAL_E(var->yres - 1) |
573 VIDTCON2_HOZVAL_E(var->xres - 1);
569 writel(data, regs + sfb->variant.vidtcon + 8); 574 writel(data, regs + sfb->variant.vidtcon + 8);
570 } 575 }
571 576
@@ -581,17 +586,23 @@ static int s3c_fb_set_par(struct fb_info *info)
581 586
582 pagewidth = (var->xres * var->bits_per_pixel) >> 3; 587 pagewidth = (var->xres * var->bits_per_pixel) >> 3;
583 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | 588 data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
584 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); 589 VIDW_BUF_SIZE_PAGEWIDTH(pagewidth) |
590 VIDW_BUF_SIZE_OFFSET_E(info->fix.line_length - pagewidth) |
591 VIDW_BUF_SIZE_PAGEWIDTH_E(pagewidth);
585 writel(data, regs + sfb->variant.buf_size + (win_no * 4)); 592 writel(data, regs + sfb->variant.buf_size + (win_no * 4));
586 593
587 /* write 'OSD' registers to control position of framebuffer */ 594 /* write 'OSD' registers to control position of framebuffer */
588 595
589 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); 596 data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0) |
597 VIDOSDxA_TOPLEFT_X_E(0) | VIDOSDxA_TOPLEFT_Y_E(0);
590 writel(data, regs + VIDOSD_A(win_no, sfb->variant)); 598 writel(data, regs + VIDOSD_A(win_no, sfb->variant));
591 599
592 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, 600 data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
593 var->xres - 1)) | 601 var->xres - 1)) |
594 VIDOSDxB_BOTRIGHT_Y(var->yres - 1); 602 VIDOSDxB_BOTRIGHT_Y(var->yres - 1) |
603 VIDOSDxB_BOTRIGHT_X_E(s3c_fb_align_word(var->bits_per_pixel,
604 var->xres - 1)) |
605 VIDOSDxB_BOTRIGHT_Y_E(var->yres - 1);
595 606
596 writel(data, regs + VIDOSD_B(win_no, sfb->variant)); 607 writel(data, regs + VIDOSD_B(win_no, sfb->variant));
597 608
@@ -692,6 +703,17 @@ static int s3c_fb_set_par(struct fb_info *info)
692 writel(data, regs + sfb->variant.wincon + (win_no * 4)); 703 writel(data, regs + sfb->variant.wincon + (win_no * 4));
693 writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); 704 writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
694 705
706 /* Set alpha value width */
707 if (sfb->variant.has_blendcon) {
708 data = readl(sfb->regs + BLENDCON);
709 data &= ~BLENDCON_NEW_MASK;
710 if (var->transp.length > 4)
711 data |= BLENDCON_NEW_8BIT_ALPHA_VALUE;
712 else
713 data |= BLENDCON_NEW_4BIT_ALPHA_VALUE;
714 writel(data, sfb->regs + BLENDCON);
715 }
716
695 shadow_protect_win(win, 0); 717 shadow_protect_win(win, 0);
696 718
697 pm_runtime_put_sync(sfb->dev); 719 pm_runtime_put_sync(sfb->dev);
@@ -1346,6 +1368,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1346 struct resource *res; 1368 struct resource *res;
1347 int win; 1369 int win;
1348 int ret = 0; 1370 int ret = 0;
1371 u32 reg;
1349 1372
1350 platid = platform_get_device_id(pdev); 1373 platid = platform_get_device_id(pdev);
1351 fbdrv = (struct s3c_fb_driverdata *)platid->driver_data; 1374 fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
@@ -1361,7 +1384,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1361 return -EINVAL; 1384 return -EINVAL;
1362 } 1385 }
1363 1386
1364 sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL); 1387 sfb = devm_kzalloc(dev, sizeof(struct s3c_fb), GFP_KERNEL);
1365 if (!sfb) { 1388 if (!sfb) {
1366 dev_err(dev, "no memory for framebuffers\n"); 1389 dev_err(dev, "no memory for framebuffers\n");
1367 return -ENOMEM; 1390 return -ENOMEM;
@@ -1404,33 +1427,25 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1404 goto err_lcd_clk; 1427 goto err_lcd_clk;
1405 } 1428 }
1406 1429
1407 sfb->regs_res = request_mem_region(res->start, resource_size(res), 1430 sfb->regs = devm_request_and_ioremap(dev, res);
1408 dev_name(dev));
1409 if (!sfb->regs_res) {
1410 dev_err(dev, "failed to claim register region\n");
1411 ret = -ENOENT;
1412 goto err_lcd_clk;
1413 }
1414
1415 sfb->regs = ioremap(res->start, resource_size(res));
1416 if (!sfb->regs) { 1431 if (!sfb->regs) {
1417 dev_err(dev, "failed to map registers\n"); 1432 dev_err(dev, "failed to map registers\n");
1418 ret = -ENXIO; 1433 ret = -ENXIO;
1419 goto err_req_region; 1434 goto err_lcd_clk;
1420 } 1435 }
1421 1436
1422 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1437 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1423 if (!res) { 1438 if (!res) {
1424 dev_err(dev, "failed to acquire irq resource\n"); 1439 dev_err(dev, "failed to acquire irq resource\n");
1425 ret = -ENOENT; 1440 ret = -ENOENT;
1426 goto err_ioremap; 1441 goto err_lcd_clk;
1427 } 1442 }
1428 sfb->irq_no = res->start; 1443 sfb->irq_no = res->start;
1429 ret = request_irq(sfb->irq_no, s3c_fb_irq, 1444 ret = devm_request_irq(dev, sfb->irq_no, s3c_fb_irq,
1430 0, "s3c_fb", sfb); 1445 0, "s3c_fb", sfb);
1431 if (ret) { 1446 if (ret) {
1432 dev_err(dev, "irq request failed\n"); 1447 dev_err(dev, "irq request failed\n");
1433 goto err_ioremap; 1448 goto err_lcd_clk;
1434 } 1449 }
1435 1450
1436 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); 1451 dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
@@ -1444,6 +1459,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1444 1459
1445 writel(pd->vidcon1, sfb->regs + VIDCON1); 1460 writel(pd->vidcon1, sfb->regs + VIDCON1);
1446 1461
1462 /* set video clock running at under-run */
1463 if (sfb->variant.has_fixvclk) {
1464 reg = readl(sfb->regs + VIDCON1);
1465 reg &= ~VIDCON1_VCLK_MASK;
1466 reg |= VIDCON1_VCLK_RUN;
1467 writel(reg, sfb->regs + VIDCON1);
1468 }
1469
1447 /* zero all windows before we do anything */ 1470 /* zero all windows before we do anything */
1448 1471
1449 for (win = 0; win < fbdrv->variant.nr_windows; win++) 1472 for (win = 0; win < fbdrv->variant.nr_windows; win++)
@@ -1484,13 +1507,6 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1484 1507
1485err_pm_runtime: 1508err_pm_runtime:
1486 pm_runtime_put_sync(sfb->dev); 1509 pm_runtime_put_sync(sfb->dev);
1487 free_irq(sfb->irq_no, sfb);
1488
1489err_ioremap:
1490 iounmap(sfb->regs);
1491
1492err_req_region:
1493 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1494 1510
1495err_lcd_clk: 1511err_lcd_clk:
1496 pm_runtime_disable(sfb->dev); 1512 pm_runtime_disable(sfb->dev);
@@ -1505,7 +1521,6 @@ err_bus_clk:
1505 clk_put(sfb->bus_clk); 1521 clk_put(sfb->bus_clk);
1506 1522
1507err_sfb: 1523err_sfb:
1508 kfree(sfb);
1509 return ret; 1524 return ret;
1510} 1525}
1511 1526
@@ -1527,10 +1542,6 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1527 if (sfb->windows[win]) 1542 if (sfb->windows[win])
1528 s3c_fb_release_win(sfb, sfb->windows[win]); 1543 s3c_fb_release_win(sfb, sfb->windows[win]);
1529 1544
1530 free_irq(sfb->irq_no, sfb);
1531
1532 iounmap(sfb->regs);
1533
1534 if (!sfb->variant.has_clksel) { 1545 if (!sfb->variant.has_clksel) {
1535 clk_disable(sfb->lcd_clk); 1546 clk_disable(sfb->lcd_clk);
1536 clk_put(sfb->lcd_clk); 1547 clk_put(sfb->lcd_clk);
@@ -1539,12 +1550,9 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1539 clk_disable(sfb->bus_clk); 1550 clk_disable(sfb->bus_clk);
1540 clk_put(sfb->bus_clk); 1551 clk_put(sfb->bus_clk);
1541 1552
1542 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1543
1544 pm_runtime_put_sync(sfb->dev); 1553 pm_runtime_put_sync(sfb->dev);
1545 pm_runtime_disable(sfb->dev); 1554 pm_runtime_disable(sfb->dev);
1546 1555
1547 kfree(sfb);
1548 return 0; 1556 return 0;
1549} 1557}
1550 1558
@@ -1579,6 +1587,7 @@ static int s3c_fb_resume(struct device *dev)
1579 struct s3c_fb_platdata *pd = sfb->pdata; 1587 struct s3c_fb_platdata *pd = sfb->pdata;
1580 struct s3c_fb_win *win; 1588 struct s3c_fb_win *win;
1581 int win_no; 1589 int win_no;
1590 u32 reg;
1582 1591
1583 clk_enable(sfb->bus_clk); 1592 clk_enable(sfb->bus_clk);
1584 1593
@@ -1589,6 +1598,14 @@ static int s3c_fb_resume(struct device *dev)
1589 pd->setup_gpio(); 1598 pd->setup_gpio();
1590 writel(pd->vidcon1, sfb->regs + VIDCON1); 1599 writel(pd->vidcon1, sfb->regs + VIDCON1);
1591 1600
1601 /* set video clock running at under-run */
1602 if (sfb->variant.has_fixvclk) {
1603 reg = readl(sfb->regs + VIDCON1);
1604 reg &= ~VIDCON1_VCLK_MASK;
1605 reg |= VIDCON1_VCLK_RUN;
1606 writel(reg, sfb->regs + VIDCON1);
1607 }
1608
1592 /* zero all windows before we do anything */ 1609 /* zero all windows before we do anything */
1593 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) 1610 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1594 s3c_fb_clear_win(sfb, win_no); 1611 s3c_fb_clear_win(sfb, win_no);
@@ -1819,6 +1836,7 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pc100 = {
1819 }, 1836 },
1820 1837
1821 .has_prtcon = 1, 1838 .has_prtcon = 1,
1839 .has_blendcon = 1,
1822 .has_clksel = 1, 1840 .has_clksel = 1,
1823 }, 1841 },
1824 .win[0] = &s3c_fb_data_s5p_wins[0], 1842 .win[0] = &s3c_fb_data_s5p_wins[0],
@@ -1850,7 +1868,9 @@ static struct s3c_fb_driverdata s3c_fb_data_s5pv210 = {
1850 }, 1868 },
1851 1869
1852 .has_shadowcon = 1, 1870 .has_shadowcon = 1,
1871 .has_blendcon = 1,
1853 .has_clksel = 1, 1872 .has_clksel = 1,
1873 .has_fixvclk = 1,
1854 }, 1874 },
1855 .win[0] = &s3c_fb_data_s5p_wins[0], 1875 .win[0] = &s3c_fb_data_s5p_wins[0],
1856 .win[1] = &s3c_fb_data_s5p_wins[1], 1876 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1881,6 +1901,39 @@ static struct s3c_fb_driverdata s3c_fb_data_exynos4 = {
1881 }, 1901 },
1882 1902
1883 .has_shadowcon = 1, 1903 .has_shadowcon = 1,
1904 .has_blendcon = 1,
1905 .has_fixvclk = 1,
1906 },
1907 .win[0] = &s3c_fb_data_s5p_wins[0],
1908 .win[1] = &s3c_fb_data_s5p_wins[1],
1909 .win[2] = &s3c_fb_data_s5p_wins[2],
1910 .win[3] = &s3c_fb_data_s5p_wins[3],
1911 .win[4] = &s3c_fb_data_s5p_wins[4],
1912};
1913
1914static struct s3c_fb_driverdata s3c_fb_data_exynos5 = {
1915 .variant = {
1916 .nr_windows = 5,
1917 .vidtcon = VIDTCON0,
1918 .wincon = WINCON(0),
1919 .winmap = WINxMAP(0),
1920 .keycon = WKEYCON,
1921 .osd = VIDOSD_BASE,
1922 .osd_stride = 16,
1923 .buf_start = VIDW_BUF_START(0),
1924 .buf_size = VIDW_BUF_SIZE(0),
1925 .buf_end = VIDW_BUF_END(0),
1926
1927 .palette = {
1928 [0] = 0x2400,
1929 [1] = 0x2800,
1930 [2] = 0x2c00,
1931 [3] = 0x3000,
1932 [4] = 0x3400,
1933 },
1934 .has_shadowcon = 1,
1935 .has_blendcon = 1,
1936 .has_fixvclk = 1,
1884 }, 1937 },
1885 .win[0] = &s3c_fb_data_s5p_wins[0], 1938 .win[0] = &s3c_fb_data_s5p_wins[0],
1886 .win[1] = &s3c_fb_data_s5p_wins[1], 1939 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1944,6 +1997,9 @@ static struct s3c_fb_driverdata s3c_fb_data_s5p64x0 = {
1944 [1] = 0x2800, 1997 [1] = 0x2800,
1945 [2] = 0x2c00, 1998 [2] = 0x2c00,
1946 }, 1999 },
2000
2001 .has_blendcon = 1,
2002 .has_fixvclk = 1,
1947 }, 2003 },
1948 .win[0] = &s3c_fb_data_s5p_wins[0], 2004 .win[0] = &s3c_fb_data_s5p_wins[0],
1949 .win[1] = &s3c_fb_data_s5p_wins[1], 2005 .win[1] = &s3c_fb_data_s5p_wins[1],
@@ -1964,6 +2020,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1964 .name = "exynos4-fb", 2020 .name = "exynos4-fb",
1965 .driver_data = (unsigned long)&s3c_fb_data_exynos4, 2021 .driver_data = (unsigned long)&s3c_fb_data_exynos4,
1966 }, { 2022 }, {
2023 .name = "exynos5-fb",
2024 .driver_data = (unsigned long)&s3c_fb_data_exynos5,
2025 }, {
1967 .name = "s3c2443-fb", 2026 .name = "s3c2443-fb",
1968 .driver_data = (unsigned long)&s3c_fb_data_s3c2443, 2027 .driver_data = (unsigned long)&s3c_fb_data_s3c2443,
1969 }, { 2028 }, {
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 05151b82f40f..42ad0f707e88 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -24,6 +24,8 @@
24#include <video/sh_mipi_dsi.h> 24#include <video/sh_mipi_dsi.h>
25#include <video/sh_mobile_lcdc.h> 25#include <video/sh_mobile_lcdc.h>
26 26
27#include "sh_mobile_lcdcfb.h"
28
27#define SYSCTRL 0x0000 29#define SYSCTRL 0x0000
28#define SYSCONF 0x0004 30#define SYSCONF 0x0004
29#define TIMSET 0x0008 31#define TIMSET 0x0008
@@ -50,16 +52,16 @@
50#define MAX_SH_MIPI_DSI 2 52#define MAX_SH_MIPI_DSI 2
51 53
52struct sh_mipi { 54struct sh_mipi {
55 struct sh_mobile_lcdc_entity entity;
56
53 void __iomem *base; 57 void __iomem *base;
54 void __iomem *linkbase; 58 void __iomem *linkbase;
55 struct clk *dsit_clk; 59 struct clk *dsit_clk;
56 struct platform_device *pdev; 60 struct platform_device *pdev;
57
58 void *next_board_data;
59 void (*next_display_on)(void *board_data, struct fb_info *info);
60 void (*next_display_off)(void *board_data);
61}; 61};
62 62
63#define to_sh_mipi(e) container_of(e, struct sh_mipi, entity)
64
63static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; 65static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
64 66
65/* Protect the above array */ 67/* Protect the above array */
@@ -120,7 +122,7 @@ static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
120 122
121static void sh_mipi_shutdown(struct platform_device *pdev) 123static void sh_mipi_shutdown(struct platform_device *pdev)
122{ 124{
123 struct sh_mipi *mipi = platform_get_drvdata(pdev); 125 struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
124 126
125 sh_mipi_dsi_enable(mipi, false); 127 sh_mipi_dsi_enable(mipi, false);
126} 128}
@@ -145,77 +147,77 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
145 pctype = 0; 147 pctype = 0;
146 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 148 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
147 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 149 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
148 linelength = ch->lcd_cfg[0].xres * 3; 150 linelength = ch->lcd_modes[0].xres * 3;
149 yuv = false; 151 yuv = false;
150 break; 152 break;
151 case MIPI_RGB565: 153 case MIPI_RGB565:
152 pctype = 1; 154 pctype = 1;
153 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 155 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
154 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 156 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
155 linelength = ch->lcd_cfg[0].xres * 2; 157 linelength = ch->lcd_modes[0].xres * 2;
156 yuv = false; 158 yuv = false;
157 break; 159 break;
158 case MIPI_RGB666_LP: 160 case MIPI_RGB666_LP:
159 pctype = 2; 161 pctype = 2;
160 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 162 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
161 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 163 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
162 linelength = ch->lcd_cfg[0].xres * 3; 164 linelength = ch->lcd_modes[0].xres * 3;
163 yuv = false; 165 yuv = false;
164 break; 166 break;
165 case MIPI_RGB666: 167 case MIPI_RGB666:
166 pctype = 3; 168 pctype = 3;
167 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 169 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
168 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 170 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
169 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; 171 linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
170 yuv = false; 172 yuv = false;
171 break; 173 break;
172 case MIPI_BGR888: 174 case MIPI_BGR888:
173 pctype = 8; 175 pctype = 8;
174 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; 176 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
175 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 177 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
176 linelength = ch->lcd_cfg[0].xres * 3; 178 linelength = ch->lcd_modes[0].xres * 3;
177 yuv = false; 179 yuv = false;
178 break; 180 break;
179 case MIPI_BGR565: 181 case MIPI_BGR565:
180 pctype = 9; 182 pctype = 9;
181 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; 183 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
182 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 184 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
183 linelength = ch->lcd_cfg[0].xres * 2; 185 linelength = ch->lcd_modes[0].xres * 2;
184 yuv = false; 186 yuv = false;
185 break; 187 break;
186 case MIPI_BGR666_LP: 188 case MIPI_BGR666_LP:
187 pctype = 0xa; 189 pctype = 0xa;
188 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 190 datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
189 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; 191 pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
190 linelength = ch->lcd_cfg[0].xres * 3; 192 linelength = ch->lcd_modes[0].xres * 3;
191 yuv = false; 193 yuv = false;
192 break; 194 break;
193 case MIPI_BGR666: 195 case MIPI_BGR666:
194 pctype = 0xb; 196 pctype = 0xb;
195 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; 197 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
196 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; 198 pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
197 linelength = (ch->lcd_cfg[0].xres * 18 + 7) / 8; 199 linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
198 yuv = false; 200 yuv = false;
199 break; 201 break;
200 case MIPI_YUYV: 202 case MIPI_YUYV:
201 pctype = 4; 203 pctype = 4;
202 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 204 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
203 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 205 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
204 linelength = ch->lcd_cfg[0].xres * 2; 206 linelength = ch->lcd_modes[0].xres * 2;
205 yuv = true; 207 yuv = true;
206 break; 208 break;
207 case MIPI_UYVY: 209 case MIPI_UYVY:
208 pctype = 5; 210 pctype = 5;
209 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; 211 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
210 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; 212 pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
211 linelength = ch->lcd_cfg[0].xres * 2; 213 linelength = ch->lcd_modes[0].xres * 2;
212 yuv = true; 214 yuv = true;
213 break; 215 break;
214 case MIPI_YUV420_L: 216 case MIPI_YUV420_L:
215 pctype = 6; 217 pctype = 6;
216 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 218 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
217 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 219 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
218 linelength = (ch->lcd_cfg[0].xres * 12 + 7) / 8; 220 linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
219 yuv = true; 221 yuv = true;
220 break; 222 break;
221 case MIPI_YUV420: 223 case MIPI_YUV420:
@@ -223,7 +225,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
223 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; 225 datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
224 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; 226 pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
225 /* Length of U/V line */ 227 /* Length of U/V line */
226 linelength = (ch->lcd_cfg[0].xres + 1) / 2; 228 linelength = (ch->lcd_modes[0].xres + 1) / 2;
227 yuv = true; 229 yuv = true;
228 break; 230 break;
229 default: 231 default:
@@ -292,7 +294,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
292 */ 294 */
293 iowrite32(0x00000006, mipi->linkbase + DTCTR); 295 iowrite32(0x00000006, mipi->linkbase + DTCTR);
294 /* VSYNC width = 2 (<< 17) */ 296 /* VSYNC width = 2 (<< 17) */
295 iowrite32((ch->lcd_cfg[0].vsync_len << pdata->vsynw_offset) | 297 iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
296 (pdata->clksrc << 16) | (pctype << 12) | datatype, 298 (pdata->clksrc << 16) | (pctype << 12) | datatype,
297 mipi->linkbase + VMCTR1); 299 mipi->linkbase + VMCTR1);
298 300
@@ -326,7 +328,7 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
326 top = linelength << 16; /* RGBLEN */ 328 top = linelength << 16; /* RGBLEN */
327 bottom = 0x00000001; 329 bottom = 0x00000001;
328 if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ 330 if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
329 bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10; 331 bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
330 iowrite32(top | bottom , mipi->linkbase + VMLEN1); 332 iowrite32(top | bottom , mipi->linkbase + VMLEN1);
331 333
332 /* 334 /*
@@ -346,18 +348,18 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
346 div = 2; 348 div = 2;
347 349
348 if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ 350 if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
349 top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin; 351 top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
350 top = ((pdata->lane * top / div) - 10) << 16; 352 top = ((pdata->lane * top / div) - 10) << 16;
351 } 353 }
352 if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ 354 if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
353 bottom = ch->lcd_cfg[0].right_margin; 355 bottom = ch->lcd_modes[0].right_margin;
354 bottom = (pdata->lane * bottom / div) - 12; 356 bottom = (pdata->lane * bottom / div) - 12;
355 } 357 }
356 358
357 bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */ 359 bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
358 if ((pdata->lane / div) > bpp) { 360 if ((pdata->lane / div) > bpp) {
359 tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */ 361 tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
360 tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */ 362 tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
361 delay = (pdata->lane * tmp); 363 delay = (pdata->lane * tmp);
362 } 364 }
363 365
@@ -392,9 +394,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
392 return 0; 394 return 0;
393} 395}
394 396
395static void mipi_display_on(void *arg, struct fb_info *info) 397static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
396{ 398{
397 struct sh_mipi *mipi = arg; 399 struct sh_mipi *mipi = to_sh_mipi(entity);
398 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; 400 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
399 int ret; 401 int ret;
400 402
@@ -410,25 +412,21 @@ static void mipi_display_on(void *arg, struct fb_info *info)
410 412
411 sh_mipi_dsi_enable(mipi, true); 413 sh_mipi_dsi_enable(mipi, true);
412 414
413 if (mipi->next_display_on) 415 return SH_MOBILE_LCDC_DISPLAY_CONNECTED;
414 mipi->next_display_on(mipi->next_board_data, info);
415
416 return;
417 416
418mipi_display_on_fail1: 417mipi_display_on_fail1:
419 pm_runtime_put_sync(&mipi->pdev->dev); 418 pm_runtime_put_sync(&mipi->pdev->dev);
420mipi_display_on_fail2: 419mipi_display_on_fail2:
421 pdata->set_dot_clock(mipi->pdev, mipi->base, 0); 420 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
421
422 return ret;
422} 423}
423 424
424static void mipi_display_off(void *arg) 425static void mipi_display_off(struct sh_mobile_lcdc_entity *entity)
425{ 426{
426 struct sh_mipi *mipi = arg; 427 struct sh_mipi *mipi = to_sh_mipi(entity);
427 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; 428 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
428 429
429 if (mipi->next_display_off)
430 mipi->next_display_off(mipi->next_board_data);
431
432 sh_mipi_dsi_enable(mipi, false); 430 sh_mipi_dsi_enable(mipi, false);
433 431
434 pdata->set_dot_clock(mipi->pdev, mipi->base, 0); 432 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
@@ -436,6 +434,11 @@ static void mipi_display_off(void *arg)
436 pm_runtime_put_sync(&mipi->pdev->dev); 434 pm_runtime_put_sync(&mipi->pdev->dev);
437} 435}
438 436
437static const struct sh_mobile_lcdc_entity_ops mipi_ops = {
438 .display_on = mipi_display_on,
439 .display_off = mipi_display_off,
440};
441
439static int __init sh_mipi_probe(struct platform_device *pdev) 442static int __init sh_mipi_probe(struct platform_device *pdev)
440{ 443{
441 struct sh_mipi *mipi; 444 struct sh_mipi *mipi;
@@ -467,6 +470,9 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
467 goto ealloc; 470 goto ealloc;
468 } 471 }
469 472
473 mipi->entity.owner = THIS_MODULE;
474 mipi->entity.ops = &mipi_ops;
475
470 if (!request_mem_region(res->start, resource_size(res), pdev->name)) { 476 if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
471 dev_err(&pdev->dev, "MIPI register region already claimed\n"); 477 dev_err(&pdev->dev, "MIPI register region already claimed\n");
472 ret = -EBUSY; 478 ret = -EBUSY;
@@ -521,18 +527,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
521 pm_runtime_resume(&pdev->dev); 527 pm_runtime_resume(&pdev->dev);
522 528
523 mutex_unlock(&array_lock); 529 mutex_unlock(&array_lock);
524 platform_set_drvdata(pdev, mipi); 530 platform_set_drvdata(pdev, &mipi->entity);
525
526 /* Save original LCDC callbacks */
527 mipi->next_board_data = pdata->lcd_chan->board_cfg.board_data;
528 mipi->next_display_on = pdata->lcd_chan->board_cfg.display_on;
529 mipi->next_display_off = pdata->lcd_chan->board_cfg.display_off;
530
531 /* Set up LCDC callbacks */
532 pdata->lcd_chan->board_cfg.board_data = mipi;
533 pdata->lcd_chan->board_cfg.display_on = mipi_display_on;
534 pdata->lcd_chan->board_cfg.display_off = mipi_display_off;
535 pdata->lcd_chan->board_cfg.owner = THIS_MODULE;
536 531
537 return 0; 532 return 0;
538 533
@@ -558,10 +553,9 @@ efindslot:
558 553
559static int __exit sh_mipi_remove(struct platform_device *pdev) 554static int __exit sh_mipi_remove(struct platform_device *pdev)
560{ 555{
561 struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
562 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 556 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
563 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 557 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
564 struct sh_mipi *mipi = platform_get_drvdata(pdev); 558 struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
565 int i, ret; 559 int i, ret;
566 560
567 mutex_lock(&array_lock); 561 mutex_lock(&array_lock);
@@ -581,11 +575,6 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
581 if (ret < 0) 575 if (ret < 0)
582 return ret; 576 return ret;
583 577
584 pdata->lcd_chan->board_cfg.owner = NULL;
585 pdata->lcd_chan->board_cfg.display_on = NULL;
586 pdata->lcd_chan->board_cfg.display_off = NULL;
587 pdata->lcd_chan->board_cfg.board_data = NULL;
588
589 pm_runtime_disable(&pdev->dev); 578 pm_runtime_disable(&pdev->dev);
590 clk_disable(mipi->dsit_clk); 579 clk_disable(mipi->dsit_clk);
591 clk_put(mipi->dsit_clk); 580 clk_put(mipi->dsit_clk);
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 647ba984f00f..eafb19da2c07 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -208,6 +208,8 @@ enum hotplug_state {
208}; 208};
209 209
210struct sh_hdmi { 210struct sh_hdmi {
211 struct sh_mobile_lcdc_entity entity;
212
211 void __iomem *base; 213 void __iomem *base;
212 enum hotplug_state hp_state; /* hot-plug status */ 214 enum hotplug_state hp_state; /* hot-plug status */
213 u8 preprogrammed_vic; /* use a pre-programmed VIC or 215 u8 preprogrammed_vic; /* use a pre-programmed VIC or
@@ -217,14 +219,13 @@ struct sh_hdmi {
217 u8 edid_blocks; 219 u8 edid_blocks;
218 struct clk *hdmi_clk; 220 struct clk *hdmi_clk;
219 struct device *dev; 221 struct device *dev;
220 struct fb_info *info;
221 struct mutex mutex; /* Protect the info pointer */
222 struct delayed_work edid_work; 222 struct delayed_work edid_work;
223 struct fb_var_screeninfo var; 223 struct fb_videomode mode;
224 struct fb_monspecs monspec; 224 struct fb_monspecs monspec;
225 struct notifier_block notifier;
226}; 225};
227 226
227#define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity)
228
228static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 229static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
229{ 230{
230 iowrite8(data, hdmi->base + reg); 231 iowrite8(data, hdmi->base + reg);
@@ -290,24 +291,24 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
290/* External video parameter settings */ 291/* External video parameter settings */
291static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi) 292static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
292{ 293{
293 struct fb_var_screeninfo *var = &hdmi->var; 294 struct fb_videomode *mode = &hdmi->mode;
294 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 295 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
295 u8 sync = 0; 296 u8 sync = 0;
296 297
297 htotal = var->xres + var->right_margin + var->left_margin + var->hsync_len; 298 htotal = mode->xres + mode->right_margin + mode->left_margin
298 299 + mode->hsync_len;
299 hdelay = var->hsync_len + var->left_margin; 300 hdelay = mode->hsync_len + mode->left_margin;
300 hblank = var->right_margin + hdelay; 301 hblank = mode->right_margin + hdelay;
301 302
302 /* 303 /*
303 * Vertical timing looks a bit different in Figure 18, 304 * Vertical timing looks a bit different in Figure 18,
304 * but let's try the same first by setting offset = 0 305 * but let's try the same first by setting offset = 0
305 */ 306 */
306 vtotal = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; 307 vtotal = mode->yres + mode->upper_margin + mode->lower_margin
307 308 + mode->vsync_len;
308 vdelay = var->vsync_len + var->upper_margin; 309 vdelay = mode->vsync_len + mode->upper_margin;
309 vblank = var->lower_margin + vdelay; 310 vblank = mode->lower_margin + vdelay;
310 voffset = min(var->upper_margin / 2, 6U); 311 voffset = min(mode->upper_margin / 2, 6U);
311 312
312 /* 313 /*
313 * [3]: VSYNC polarity: Positive 314 * [3]: VSYNC polarity: Positive
@@ -315,14 +316,14 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
315 * [1]: Interlace/Progressive: Progressive 316 * [1]: Interlace/Progressive: Progressive
316 * [0]: External video settings enable: used. 317 * [0]: External video settings enable: used.
317 */ 318 */
318 if (var->sync & FB_SYNC_HOR_HIGH_ACT) 319 if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
319 sync |= 4; 320 sync |= 4;
320 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 321 if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
321 sync |= 8; 322 sync |= 8;
322 323
323 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 324 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
324 htotal, hblank, hdelay, var->hsync_len, 325 htotal, hblank, hdelay, mode->hsync_len,
325 vtotal, vblank, vdelay, var->vsync_len, sync); 326 vtotal, vblank, vdelay, mode->vsync_len, sync);
326 327
327 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 328 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
328 329
@@ -335,8 +336,8 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
335 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0); 336 hdmi_write(hdmi, hdelay, HDMI_EXTERNAL_H_DELAY_7_0);
336 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8); 337 hdmi_write(hdmi, hdelay >> 8, HDMI_EXTERNAL_H_DELAY_9_8);
337 338
338 hdmi_write(hdmi, var->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0); 339 hdmi_write(hdmi, mode->hsync_len, HDMI_EXTERNAL_H_DURATION_7_0);
339 hdmi_write(hdmi, var->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8); 340 hdmi_write(hdmi, mode->hsync_len >> 8, HDMI_EXTERNAL_H_DURATION_9_8);
340 341
341 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0); 342 hdmi_write(hdmi, vtotal, HDMI_EXTERNAL_V_TOTAL_7_0);
342 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8); 343 hdmi_write(hdmi, vtotal >> 8, HDMI_EXTERNAL_V_TOTAL_9_8);
@@ -345,7 +346,7 @@ static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
345 346
346 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY); 347 hdmi_write(hdmi, vdelay, HDMI_EXTERNAL_V_DELAY);
347 348
348 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 349 hdmi_write(hdmi, mode->vsync_len, HDMI_EXTERNAL_V_DURATION);
349 350
350 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */ 351 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
351 if (!hdmi->preprogrammed_vic) 352 if (!hdmi->preprogrammed_vic)
@@ -472,7 +473,7 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
472 */ 473 */
473static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 474static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
474{ 475{
475 if (hdmi->var.pixclock < 10000) { 476 if (hdmi->mode.pixclock < 10000) {
476 /* for 1080p8bit 148MHz */ 477 /* for 1080p8bit 148MHz */
477 hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 478 hdmi_write(hdmi, 0x1d, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
478 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 479 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
@@ -483,7 +484,7 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
483 hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 484 hdmi_write(hdmi, 0x0e, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
484 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 485 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
485 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 486 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
486 } else if (hdmi->var.pixclock < 30000) { 487 } else if (hdmi->mode.pixclock < 30000) {
487 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 488 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
488 /* 489 /*
489 * [1:0] Speed_A 490 * [1:0] Speed_A
@@ -732,14 +733,12 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
732static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, 733static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
733 unsigned long *parent_rate) 734 unsigned long *parent_rate)
734{ 735{
735 struct fb_var_screeninfo tmpvar; 736 struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
736 struct fb_var_screeninfo *var = &tmpvar;
737 const struct fb_videomode *mode, *found = NULL; 737 const struct fb_videomode *mode, *found = NULL;
738 struct fb_info *info = hdmi->info;
739 struct fb_modelist *modelist = NULL;
740 unsigned int f_width = 0, f_height = 0, f_refresh = 0; 738 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
741 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ 739 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
742 bool scanning = false, preferred_bad = false; 740 bool scanning = false, preferred_bad = false;
741 bool use_edid_mode = false;
743 u8 edid[128]; 742 u8 edid[128];
744 char *forced; 743 char *forced;
745 int i; 744 int i;
@@ -854,12 +853,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
854 } 853 }
855 854
856 /* Check if supported: sufficient fb memory, supported clock-rate */ 855 /* Check if supported: sufficient fb memory, supported clock-rate */
857 fb_videomode_to_var(var, mode); 856 if (ch && ch->notify &&
858 857 ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_MODE, mode,
859 var->bits_per_pixel = info->var.bits_per_pixel; 858 NULL)) {
860
861 if (info && info->fbops->fb_check_var &&
862 info->fbops->fb_check_var(var, info)) {
863 scanning = true; 859 scanning = true;
864 preferred_bad = true; 860 preferred_bad = true;
865 continue; 861 continue;
@@ -867,28 +863,19 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
867 863
868 found = mode; 864 found = mode;
869 found_rate_error = rate_error; 865 found_rate_error = rate_error;
866 use_edid_mode = true;
870 } 867 }
871 868
872 hdmi->var.width = hdmi->monspec.max_x * 10;
873 hdmi->var.height = hdmi->monspec.max_y * 10;
874
875 /* 869 /*
876 * TODO 1: if no ->info is present, postpone running the config until 870 * TODO 1: if no default mode is present, postpone running the config
877 * after ->info first gets registered. 871 * until after the LCDC channel is initialized.
878 * TODO 2: consider registering the HDMI platform device from the LCDC 872 * TODO 2: consider registering the HDMI platform device from the LCDC
879 * driver, and passing ->info with HDMI platform data. 873 * driver.
880 */ 874 */
881 if (info && !found) { 875 if (!found && hdmi->entity.def_mode.xres != 0) {
882 modelist = info->modelist.next && 876 found = &hdmi->entity.def_mode;
883 !list_empty(&info->modelist) ? 877 found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate,
884 list_entry(info->modelist.next, 878 parent_rate);
885 struct fb_modelist, list) :
886 NULL;
887
888 if (modelist) {
889 found = &modelist->mode;
890 found_rate_error = sh_hdmi_rate_error(hdmi, found, hdmi_rate, parent_rate);
891 }
892 } 879 }
893 880
894 /* No cookie today */ 881 /* No cookie today */
@@ -912,12 +899,13 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
912 else 899 else
913 hdmi->preprogrammed_vic = 0; 900 hdmi->preprogrammed_vic = 0;
914 901
915 dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), clock error %luHz\n", 902 dev_dbg(hdmi->dev, "Using %s %s mode %ux%u@%uHz (%luHz), "
916 modelist ? "default" : "EDID", hdmi->preprogrammed_vic ? "VIC" : "external", 903 "clock error %luHz\n", use_edid_mode ? "EDID" : "default",
917 found->xres, found->yres, found->refresh, 904 hdmi->preprogrammed_vic ? "VIC" : "external", found->xres,
918 PICOS2KHZ(found->pixclock) * 1000, found_rate_error); 905 found->yres, found->refresh, PICOS2KHZ(found->pixclock) * 1000,
906 found_rate_error);
919 907
920 fb_videomode_to_var(&hdmi->var, found); 908 hdmi->mode = *found;
921 sh_hdmi_external_video_param(hdmi); 909 sh_hdmi_external_video_param(hdmi);
922 910
923 return 0; 911 return 0;
@@ -998,22 +986,12 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
998 return IRQ_HANDLED; 986 return IRQ_HANDLED;
999} 987}
1000 988
1001/* locking: called with info->lock held, or before register_framebuffer() */ 989static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
1002static void sh_hdmi_display_on(void *arg, struct fb_info *info)
1003{ 990{
1004 /* 991 struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
1005 * info is guaranteed to be valid, when we are called, because our
1006 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
1007 */
1008 struct sh_hdmi *hdmi = arg;
1009 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1010 struct sh_mobile_lcdc_chan *ch = info->par;
1011 992
1012 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, 993 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__, hdmi,
1013 pdata->lcd_dev, info->state); 994 hdmi->hp_state);
1014
1015 /* No need to lock */
1016 hdmi->info = info;
1017 995
1018 /* 996 /*
1019 * hp_state can be set to 997 * hp_state can be set to
@@ -1021,56 +999,30 @@ static void sh_hdmi_display_on(void *arg, struct fb_info *info)
1021 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in 999 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
1022 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion 1000 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
1023 */ 1001 */
1024 switch (hdmi->hp_state) { 1002 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
1025 case HDMI_HOTPLUG_EDID_DONE:
1026 /* PS mode d->e. All functions are active */ 1003 /* PS mode d->e. All functions are active */
1027 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 1004 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
1028 dev_dbg(hdmi->dev, "HDMI running\n"); 1005 dev_dbg(hdmi->dev, "HDMI running\n");
1029 break;
1030 case HDMI_HOTPLUG_DISCONNECTED:
1031 info->state = FBINFO_STATE_SUSPENDED;
1032 default:
1033 hdmi->var = ch->display_var;
1034 } 1006 }
1007
1008 return hdmi->hp_state == HDMI_HOTPLUG_DISCONNECTED
1009 ? SH_MOBILE_LCDC_DISPLAY_DISCONNECTED
1010 : SH_MOBILE_LCDC_DISPLAY_CONNECTED;
1035} 1011}
1036 1012
1037/* locking: called with info->lock held */ 1013static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
1038static void sh_hdmi_display_off(void *arg)
1039{ 1014{
1040 struct sh_hdmi *hdmi = arg; 1015 struct sh_hdmi *hdmi = entity_to_sh_hdmi(entity);
1041 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1042 1016
1043 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev); 1017 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
1044 /* PS mode e->a */ 1018 /* PS mode e->a */
1045 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 1019 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
1046} 1020}
1047 1021
1048static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi) 1022static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
1049{ 1023 .display_on = sh_hdmi_display_on,
1050 struct fb_info *info = hdmi->info; 1024 .display_off = sh_hdmi_display_off,
1051 struct sh_mobile_lcdc_chan *ch = info->par; 1025};
1052 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
1053 struct fb_videomode mode1, mode2;
1054
1055 fb_var_to_videomode(&mode1, old_var);
1056 fb_var_to_videomode(&mode2, new_var);
1057
1058 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
1059 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
1060
1061 if (fb_mode_is_equal(&mode1, &mode2)) {
1062 /* It can be a different monitor with an equal video-mode */
1063 old_var->width = new_var->width;
1064 old_var->height = new_var->height;
1065 return false;
1066 }
1067
1068 dev_dbg(info->dev, "Switching %u -> %u lines\n",
1069 mode1.yres, mode2.yres);
1070 *old_var = *new_var;
1071
1072 return true;
1073}
1074 1026
1075/** 1027/**
1076 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock 1028 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
@@ -1111,20 +1063,11 @@ static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long hdmi_rate,
1111static void sh_hdmi_edid_work_fn(struct work_struct *work) 1063static void sh_hdmi_edid_work_fn(struct work_struct *work)
1112{ 1064{
1113 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1065 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
1114 struct fb_info *info; 1066 struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc;
1115 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1116 struct sh_mobile_lcdc_chan *ch;
1117 int ret; 1067 int ret;
1118 1068
1119 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, 1069 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi,
1120 pdata->lcd_dev, hdmi->hp_state); 1070 hdmi->hp_state);
1121
1122 if (!pdata->lcd_dev)
1123 return;
1124
1125 mutex_lock(&hdmi->mutex);
1126
1127 info = hdmi->info;
1128 1071
1129 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) { 1072 if (hdmi->hp_state == HDMI_HOTPLUG_CONNECTED) {
1130 unsigned long parent_rate = 0, hdmi_rate; 1073 unsigned long parent_rate = 0, hdmi_rate;
@@ -1145,103 +1088,32 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
1145 /* Switched to another (d) power-save mode */ 1088 /* Switched to another (d) power-save mode */
1146 msleep(10); 1089 msleep(10);
1147 1090
1148 if (!info) 1091 if (ch && ch->notify)
1149 goto out; 1092 ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
1150 1093 &hdmi->mode, &hdmi->monspec);
1151 ch = info->par;
1152
1153 if (lock_fb_info(info)) {
1154 console_lock();
1155
1156 /* HDMI plug in */
1157 if (!sh_hdmi_must_reconfigure(hdmi) &&
1158 info->state == FBINFO_STATE_RUNNING) {
1159 /*
1160 * First activation with the default monitor - just turn
1161 * on, if we run a resume here, the logo disappears
1162 */
1163 info->var.width = hdmi->var.width;
1164 info->var.height = hdmi->var.height;
1165 sh_hdmi_display_on(hdmi, info);
1166 } else {
1167 /* New monitor or have to wake up */
1168 fb_set_suspend(info, 0);
1169 }
1170
1171 console_unlock();
1172 unlock_fb_info(info);
1173 }
1174 } else { 1094 } else {
1175 ret = 0;
1176 if (!info)
1177 goto out;
1178
1179 hdmi->monspec.modedb_len = 0; 1095 hdmi->monspec.modedb_len = 0;
1180 fb_destroy_modedb(hdmi->monspec.modedb); 1096 fb_destroy_modedb(hdmi->monspec.modedb);
1181 hdmi->monspec.modedb = NULL; 1097 hdmi->monspec.modedb = NULL;
1182 1098
1183 if (lock_fb_info(info)) { 1099 if (ch && ch->notify)
1184 console_lock(); 1100 ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
1101 NULL, NULL);
1185 1102
1186 /* HDMI disconnect */ 1103 ret = 0;
1187 fb_set_suspend(info, 1);
1188
1189 console_unlock();
1190 unlock_fb_info(info);
1191 }
1192 } 1104 }
1193 1105
1194out: 1106out:
1195 if (ret < 0 && ret != -EAGAIN) 1107 if (ret < 0 && ret != -EAGAIN)
1196 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED; 1108 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1197 mutex_unlock(&hdmi->mutex);
1198 1109
1199 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev); 1110 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
1200}
1201
1202static int sh_hdmi_notify(struct notifier_block *nb,
1203 unsigned long action, void *data)
1204{
1205 struct fb_event *event = data;
1206 struct fb_info *info = event->info;
1207 struct sh_mobile_lcdc_chan *ch = info->par;
1208 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1209 struct sh_hdmi *hdmi = board_cfg->board_data;
1210
1211 if (!hdmi || nb != &hdmi->notifier || hdmi->info != info)
1212 return NOTIFY_DONE;
1213
1214 switch(action) {
1215 case FB_EVENT_FB_REGISTERED:
1216 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1217 break;
1218 case FB_EVENT_FB_UNREGISTERED:
1219 /*
1220 * We are called from unregister_framebuffer() with the
1221 * info->lock held. This is bad for us, because we can race with
1222 * the scheduled work, which has to call fb_set_suspend(), which
1223 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1224 * cannot take and hold info->lock for the whole function
1225 * duration. Using an additional lock creates a classical AB-BA
1226 * lock up. Therefore, we have to release the info->lock
1227 * temporarily, synchronise with the work queue and re-acquire
1228 * the info->lock.
1229 */
1230 unlock_fb_info(info);
1231 mutex_lock(&hdmi->mutex);
1232 hdmi->info = NULL;
1233 mutex_unlock(&hdmi->mutex);
1234 lock_fb_info(info);
1235 return NOTIFY_OK;
1236 }
1237 return NOTIFY_DONE;
1238} 1111}
1239 1112
1240static int __init sh_hdmi_probe(struct platform_device *pdev) 1113static int __init sh_hdmi_probe(struct platform_device *pdev)
1241{ 1114{
1242 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1115 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1243 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1116 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1244 struct sh_mobile_lcdc_board_cfg *board_cfg;
1245 int irq = platform_get_irq(pdev, 0), ret; 1117 int irq = platform_get_irq(pdev, 0), ret;
1246 struct sh_hdmi *hdmi; 1118 struct sh_hdmi *hdmi;
1247 long rate; 1119 long rate;
@@ -1255,9 +1127,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1255 return -ENOMEM; 1127 return -ENOMEM;
1256 } 1128 }
1257 1129
1258 mutex_init(&hdmi->mutex);
1259
1260 hdmi->dev = &pdev->dev; 1130 hdmi->dev = &pdev->dev;
1131 hdmi->entity.owner = THIS_MODULE;
1132 hdmi->entity.ops = &sh_hdmi_ops;
1261 1133
1262 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); 1134 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
1263 if (IS_ERR(hdmi->hdmi_clk)) { 1135 if (IS_ERR(hdmi->hdmi_clk)) {
@@ -1297,14 +1169,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1297 goto emap; 1169 goto emap;
1298 } 1170 }
1299 1171
1300 platform_set_drvdata(pdev, hdmi); 1172 platform_set_drvdata(pdev, &hdmi->entity);
1301
1302 /* Set up LCDC callbacks */
1303 board_cfg = &pdata->lcd_chan->board_cfg;
1304 board_cfg->owner = THIS_MODULE;
1305 board_cfg->board_data = hdmi;
1306 board_cfg->display_on = sh_hdmi_display_on;
1307 board_cfg->display_off = sh_hdmi_display_off;
1308 1173
1309 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn); 1174 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
1310 1175
@@ -1329,9 +1194,6 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1329 goto ecodec; 1194 goto ecodec;
1330 } 1195 }
1331 1196
1332 hdmi->notifier.notifier_call = sh_hdmi_notify;
1333 fb_register_client(&hdmi->notifier);
1334
1335 return 0; 1197 return 0;
1336 1198
1337ecodec: 1199ecodec:
@@ -1347,7 +1209,6 @@ ereqreg:
1347erate: 1209erate:
1348 clk_put(hdmi->hdmi_clk); 1210 clk_put(hdmi->hdmi_clk);
1349egetclk: 1211egetclk:
1350 mutex_destroy(&hdmi->mutex);
1351 kfree(hdmi); 1212 kfree(hdmi);
1352 1213
1353 return ret; 1214 return ret;
@@ -1355,21 +1216,12 @@ egetclk:
1355 1216
1356static int __exit sh_hdmi_remove(struct platform_device *pdev) 1217static int __exit sh_hdmi_remove(struct platform_device *pdev)
1357{ 1218{
1358 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1219 struct sh_hdmi *hdmi = entity_to_sh_hdmi(platform_get_drvdata(pdev));
1359 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1360 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1220 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1361 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
1362 int irq = platform_get_irq(pdev, 0); 1221 int irq = platform_get_irq(pdev, 0);
1363 1222
1364 snd_soc_unregister_codec(&pdev->dev); 1223 snd_soc_unregister_codec(&pdev->dev);
1365 1224
1366 fb_unregister_client(&hdmi->notifier);
1367
1368 board_cfg->display_on = NULL;
1369 board_cfg->display_off = NULL;
1370 board_cfg->board_data = NULL;
1371 board_cfg->owner = NULL;
1372
1373 /* No new work will be scheduled, wait for running ISR */ 1225 /* No new work will be scheduled, wait for running ISR */
1374 free_irq(irq, hdmi); 1226 free_irq(irq, hdmi);
1375 /* Wait for already scheduled work */ 1227 /* Wait for already scheduled work */
@@ -1380,7 +1232,6 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
1380 clk_put(hdmi->hdmi_clk); 1232 clk_put(hdmi->hdmi_clk);
1381 iounmap(hdmi->base); 1233 iounmap(hdmi->base);
1382 release_mem_region(res->start, resource_size(res)); 1234 release_mem_region(res->start, resource_size(res));
1383 mutex_destroy(&hdmi->mutex);
1384 kfree(hdmi); 1235 kfree(hdmi);
1385 1236
1386 return 0; 1237 return 0;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index aac5b369d73c..7a0b301587f6 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -8,26 +8,27 @@
8 * for more details. 8 * for more details.
9 */ 9 */
10 10
11#include <linux/kernel.h> 11#include <linux/atomic.h>
12#include <linux/init.h> 12#include <linux/backlight.h>
13#include <linux/delay.h>
14#include <linux/mm.h>
15#include <linux/clk.h> 13#include <linux/clk.h>
16#include <linux/pm_runtime.h> 14#include <linux/console.h>
17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 15#include <linux/dma-mapping.h>
16#include <linux/delay.h>
17#include <linux/gpio.h>
18#include <linux/init.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/videodev2.h>
21#include <linux/vmalloc.h>
22#include <linux/ioctl.h> 20#include <linux/ioctl.h>
23#include <linux/slab.h> 21#include <linux/kernel.h>
24#include <linux/console.h> 22#include <linux/mm.h>
25#include <linux/backlight.h>
26#include <linux/gpio.h>
27#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/platform_device.h>
25#include <linux/pm_runtime.h>
26#include <linux/slab.h>
27#include <linux/videodev2.h>
28#include <linux/vmalloc.h>
29
28#include <video/sh_mobile_lcdc.h> 30#include <video/sh_mobile_lcdc.h>
29#include <video/sh_mobile_meram.h> 31#include <video/sh_mobile_meram.h>
30#include <linux/atomic.h>
31 32
32#include "sh_mobile_lcdcfb.h" 33#include "sh_mobile_lcdcfb.h"
33 34
@@ -37,6 +38,24 @@
37#define MAX_XRES 1920 38#define MAX_XRES 1920
38#define MAX_YRES 1080 39#define MAX_YRES 1080
39 40
41struct sh_mobile_lcdc_priv {
42 void __iomem *base;
43 int irq;
44 atomic_t hw_usecnt;
45 struct device *dev;
46 struct clk *dot_clk;
47 unsigned long lddckr;
48 struct sh_mobile_lcdc_chan ch[2];
49 struct notifier_block notifier;
50 int started;
51 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
52 struct sh_mobile_meram_info *meram_dev;
53};
54
55/* -----------------------------------------------------------------------------
56 * Registers access
57 */
58
40static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 59static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
41 [LDDCKPAT1R] = 0x400, 60 [LDDCKPAT1R] = 0x400,
42 [LDDCKPAT2R] = 0x404, 61 [LDDCKPAT2R] = 0x404,
@@ -75,38 +94,6 @@ static unsigned long lcdc_offs_sublcd[NR_CH_REGS] = {
75 [LDPMR] = 0x63c, 94 [LDPMR] = 0x63c,
76}; 95};
77 96
78static const struct fb_videomode default_720p = {
79 .name = "HDMI 720p",
80 .xres = 1280,
81 .yres = 720,
82
83 .left_margin = 220,
84 .right_margin = 110,
85 .hsync_len = 40,
86
87 .upper_margin = 20,
88 .lower_margin = 5,
89 .vsync_len = 5,
90
91 .pixclock = 13468,
92 .refresh = 60,
93 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
94};
95
96struct sh_mobile_lcdc_priv {
97 void __iomem *base;
98 int irq;
99 atomic_t hw_usecnt;
100 struct device *dev;
101 struct clk *dot_clk;
102 unsigned long lddckr;
103 struct sh_mobile_lcdc_chan ch[2];
104 struct notifier_block notifier;
105 int started;
106 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
107 struct sh_mobile_meram_info *meram_dev;
108};
109
110static bool banked(int reg_nr) 97static bool banked(int reg_nr)
111{ 98{
112 switch (reg_nr) { 99 switch (reg_nr) {
@@ -127,6 +114,11 @@ static bool banked(int reg_nr)
127 return false; 114 return false;
128} 115}
129 116
117static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan)
118{
119 return chan->cfg->chan == LCDC_CHAN_SUBLCD;
120}
121
130static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, 122static void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan,
131 int reg_nr, unsigned long data) 123 int reg_nr, unsigned long data)
132{ 124{
@@ -169,11 +161,72 @@ static void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv,
169 cpu_relax(); 161 cpu_relax();
170} 162}
171 163
172static int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan) 164/* -----------------------------------------------------------------------------
165 * Clock management
166 */
167
168static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
169{
170 if (atomic_inc_and_test(&priv->hw_usecnt)) {
171 if (priv->dot_clk)
172 clk_enable(priv->dot_clk);
173 pm_runtime_get_sync(priv->dev);
174 if (priv->meram_dev && priv->meram_dev->pdev)
175 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
176 }
177}
178
179static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
173{ 180{
174 return chan->cfg.chan == LCDC_CHAN_SUBLCD; 181 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
182 if (priv->meram_dev && priv->meram_dev->pdev)
183 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
184 pm_runtime_put(priv->dev);
185 if (priv->dot_clk)
186 clk_disable(priv->dot_clk);
187 }
175} 188}
176 189
190static int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv,
191 int clock_source)
192{
193 struct clk *clk;
194 char *str;
195
196 switch (clock_source) {
197 case LCDC_CLK_BUS:
198 str = "bus_clk";
199 priv->lddckr = LDDCKR_ICKSEL_BUS;
200 break;
201 case LCDC_CLK_PERIPHERAL:
202 str = "peripheral_clk";
203 priv->lddckr = LDDCKR_ICKSEL_MIPI;
204 break;
205 case LCDC_CLK_EXTERNAL:
206 str = NULL;
207 priv->lddckr = LDDCKR_ICKSEL_HDMI;
208 break;
209 default:
210 return -EINVAL;
211 }
212
213 if (str == NULL)
214 return 0;
215
216 clk = clk_get(priv->dev, str);
217 if (IS_ERR(clk)) {
218 dev_err(priv->dev, "cannot get dot clock %s\n", str);
219 return PTR_ERR(clk);
220 }
221
222 priv->dot_clk = clk;
223 return 0;
224}
225
226/* -----------------------------------------------------------------------------
227 * Display, panel and deferred I/O
228 */
229
177static void lcdc_sys_write_index(void *handle, unsigned long data) 230static void lcdc_sys_write_index(void *handle, unsigned long data)
178{ 231{
179 struct sh_mobile_lcdc_chan *ch = handle; 232 struct sh_mobile_lcdc_chan *ch = handle;
@@ -216,74 +269,11 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
216 lcdc_sys_read_data, 269 lcdc_sys_read_data,
217}; 270};
218 271
219static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
220{
221 if (var->grayscale > 1)
222 return var->grayscale;
223
224 switch (var->bits_per_pixel) {
225 case 16:
226 return V4L2_PIX_FMT_RGB565;
227 case 24:
228 return V4L2_PIX_FMT_BGR24;
229 case 32:
230 return V4L2_PIX_FMT_BGR32;
231 default:
232 return 0;
233 }
234}
235
236static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
237{
238 return var->grayscale > 1;
239}
240
241static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
242{
243 if (var->grayscale <= 1)
244 return false;
245
246 switch (var->grayscale) {
247 case V4L2_PIX_FMT_NV12:
248 case V4L2_PIX_FMT_NV21:
249 case V4L2_PIX_FMT_NV16:
250 case V4L2_PIX_FMT_NV61:
251 case V4L2_PIX_FMT_NV24:
252 case V4L2_PIX_FMT_NV42:
253 return true;
254
255 default:
256 return false;
257 }
258}
259
260static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
261{
262 if (atomic_inc_and_test(&priv->hw_usecnt)) {
263 if (priv->dot_clk)
264 clk_enable(priv->dot_clk);
265 pm_runtime_get_sync(priv->dev);
266 if (priv->meram_dev && priv->meram_dev->pdev)
267 pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
268 }
269}
270
271static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
272{
273 if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
274 if (priv->meram_dev && priv->meram_dev->pdev)
275 pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
276 pm_runtime_put(priv->dev);
277 if (priv->dot_clk)
278 clk_disable(priv->dot_clk);
279 }
280}
281
282static int sh_mobile_lcdc_sginit(struct fb_info *info, 272static int sh_mobile_lcdc_sginit(struct fb_info *info,
283 struct list_head *pagelist) 273 struct list_head *pagelist)
284{ 274{
285 struct sh_mobile_lcdc_chan *ch = info->par; 275 struct sh_mobile_lcdc_chan *ch = info->par;
286 unsigned int nr_pages_max = info->fix.smem_len >> PAGE_SHIFT; 276 unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT;
287 struct page *page; 277 struct page *page;
288 int nr_pages = 0; 278 int nr_pages = 0;
289 279
@@ -299,7 +289,7 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
299 struct list_head *pagelist) 289 struct list_head *pagelist)
300{ 290{
301 struct sh_mobile_lcdc_chan *ch = info->par; 291 struct sh_mobile_lcdc_chan *ch = info->par;
302 struct sh_mobile_lcdc_board_cfg *bcfg = &ch->cfg.board_cfg; 292 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
303 293
304 /* enable clocks before accessing hardware */ 294 /* enable clocks before accessing hardware */
305 sh_mobile_lcdc_clk_on(ch->lcdc); 295 sh_mobile_lcdc_clk_on(ch->lcdc);
@@ -323,16 +313,15 @@ static void sh_mobile_lcdc_deferred_io(struct fb_info *info,
323 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist); 313 unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist);
324 314
325 /* trigger panel update */ 315 /* trigger panel update */
326 dma_map_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 316 dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE);
327 if (bcfg->start_transfer) 317 if (panel->start_transfer)
328 bcfg->start_transfer(bcfg->board_data, ch, 318 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
329 &sh_mobile_lcdc_sys_bus_ops);
330 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 319 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
331 dma_unmap_sg(info->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 320 dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages,
321 DMA_TO_DEVICE);
332 } else { 322 } else {
333 if (bcfg->start_transfer) 323 if (panel->start_transfer)
334 bcfg->start_transfer(bcfg->board_data, ch, 324 panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops);
335 &sh_mobile_lcdc_sys_bus_ops);
336 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 325 lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG);
337 } 326 }
338} 327}
@@ -345,6 +334,217 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info)
345 schedule_delayed_work(&info->deferred_work, fbdefio->delay); 334 schedule_delayed_work(&info->deferred_work, fbdefio->delay);
346} 335}
347 336
337static void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch)
338{
339 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
340
341 if (ch->tx_dev) {
342 int ret;
343
344 ret = ch->tx_dev->ops->display_on(ch->tx_dev);
345 if (ret < 0)
346 return;
347
348 if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED)
349 ch->info->state = FBINFO_STATE_SUSPENDED;
350 }
351
352 /* HDMI must be enabled before LCDC configuration */
353 if (panel->display_on)
354 panel->display_on();
355}
356
357static void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch)
358{
359 const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg;
360
361 if (panel->display_off)
362 panel->display_off();
363
364 if (ch->tx_dev)
365 ch->tx_dev->ops->display_off(ch->tx_dev);
366}
367
368static bool
369sh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch,
370 const struct fb_videomode *new_mode)
371{
372 dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n",
373 ch->display.mode.xres, ch->display.mode.yres,
374 new_mode->xres, new_mode->yres);
375
376 /* It can be a different monitor with an equal video-mode */
377 if (fb_mode_is_equal(&ch->display.mode, new_mode))
378 return false;
379
380 dev_dbg(ch->info->dev, "Switching %u -> %u lines\n",
381 ch->display.mode.yres, new_mode->yres);
382 ch->display.mode = *new_mode;
383
384 return true;
385}
386
387static int sh_mobile_check_var(struct fb_var_screeninfo *var,
388 struct fb_info *info);
389
390static int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch,
391 enum sh_mobile_lcdc_entity_event event,
392 const struct fb_videomode *mode,
393 const struct fb_monspecs *monspec)
394{
395 struct fb_info *info = ch->info;
396 struct fb_var_screeninfo var;
397 int ret = 0;
398
399 switch (event) {
400 case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT:
401 /* HDMI plug in */
402 if (lock_fb_info(info)) {
403 console_lock();
404
405 ch->display.width = monspec->max_x * 10;
406 ch->display.height = monspec->max_y * 10;
407
408 if (!sh_mobile_lcdc_must_reconfigure(ch, mode) &&
409 info->state == FBINFO_STATE_RUNNING) {
410 /* First activation with the default monitor.
411 * Just turn on, if we run a resume here, the
412 * logo disappears.
413 */
414 info->var.width = monspec->max_x * 10;
415 info->var.height = monspec->max_y * 10;
416 sh_mobile_lcdc_display_on(ch);
417 } else {
418 /* New monitor or have to wake up */
419 fb_set_suspend(info, 0);
420 }
421
422 console_unlock();
423 unlock_fb_info(info);
424 }
425 break;
426
427 case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT:
428 /* HDMI disconnect */
429 if (lock_fb_info(info)) {
430 console_lock();
431 fb_set_suspend(info, 1);
432 console_unlock();
433 unlock_fb_info(info);
434 }
435 break;
436
437 case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE:
438 /* Validate a proposed new mode */
439 fb_videomode_to_var(&var, mode);
440 var.bits_per_pixel = info->var.bits_per_pixel;
441 var.grayscale = info->var.grayscale;
442 ret = sh_mobile_check_var(&var, info);
443 break;
444 }
445
446 return ret;
447}
448
449/* -----------------------------------------------------------------------------
450 * Format helpers
451 */
452
453struct sh_mobile_lcdc_format_info {
454 u32 fourcc;
455 unsigned int bpp;
456 bool yuv;
457 u32 lddfr;
458};
459
460static const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = {
461 {
462 .fourcc = V4L2_PIX_FMT_RGB565,
463 .bpp = 16,
464 .yuv = false,
465 .lddfr = LDDFR_PKF_RGB16,
466 }, {
467 .fourcc = V4L2_PIX_FMT_BGR24,
468 .bpp = 24,
469 .yuv = false,
470 .lddfr = LDDFR_PKF_RGB24,
471 }, {
472 .fourcc = V4L2_PIX_FMT_BGR32,
473 .bpp = 32,
474 .yuv = false,
475 .lddfr = LDDFR_PKF_ARGB32,
476 }, {
477 .fourcc = V4L2_PIX_FMT_NV12,
478 .bpp = 12,
479 .yuv = true,
480 .lddfr = LDDFR_CC | LDDFR_YF_420,
481 }, {
482 .fourcc = V4L2_PIX_FMT_NV21,
483 .bpp = 12,
484 .yuv = true,
485 .lddfr = LDDFR_CC | LDDFR_YF_420,
486 }, {
487 .fourcc = V4L2_PIX_FMT_NV16,
488 .bpp = 16,
489 .yuv = true,
490 .lddfr = LDDFR_CC | LDDFR_YF_422,
491 }, {
492 .fourcc = V4L2_PIX_FMT_NV61,
493 .bpp = 16,
494 .yuv = true,
495 .lddfr = LDDFR_CC | LDDFR_YF_422,
496 }, {
497 .fourcc = V4L2_PIX_FMT_NV24,
498 .bpp = 24,
499 .yuv = true,
500 .lddfr = LDDFR_CC | LDDFR_YF_444,
501 }, {
502 .fourcc = V4L2_PIX_FMT_NV42,
503 .bpp = 24,
504 .yuv = true,
505 .lddfr = LDDFR_CC | LDDFR_YF_444,
506 },
507};
508
509static const struct sh_mobile_lcdc_format_info *
510sh_mobile_format_info(u32 fourcc)
511{
512 unsigned int i;
513
514 for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) {
515 if (sh_mobile_format_infos[i].fourcc == fourcc)
516 return &sh_mobile_format_infos[i];
517 }
518
519 return NULL;
520}
521
522static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
523{
524 if (var->grayscale > 1)
525 return var->grayscale;
526
527 switch (var->bits_per_pixel) {
528 case 16:
529 return V4L2_PIX_FMT_RGB565;
530 case 24:
531 return V4L2_PIX_FMT_BGR24;
532 case 32:
533 return V4L2_PIX_FMT_BGR32;
534 default:
535 return 0;
536 }
537}
538
539static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
540{
541 return var->grayscale > 1;
542}
543
544/* -----------------------------------------------------------------------------
545 * Start, stop and IRQ
546 */
547
348static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) 548static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
349{ 549{
350 struct sh_mobile_lcdc_priv *priv = data; 550 struct sh_mobile_lcdc_priv *priv = data;
@@ -385,6 +585,26 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data)
385 return IRQ_HANDLED; 585 return IRQ_HANDLED;
386} 586}
387 587
588static int sh_mobile_wait_for_vsync(struct sh_mobile_lcdc_chan *ch)
589{
590 unsigned long ldintr;
591 int ret;
592
593 /* Enable VSync End interrupt and be careful not to acknowledge any
594 * pending interrupt.
595 */
596 ldintr = lcdc_read(ch->lcdc, _LDINTR);
597 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
598 lcdc_write(ch->lcdc, _LDINTR, ldintr);
599
600 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
601 msecs_to_jiffies(100));
602 if (!ret)
603 return -ETIMEDOUT;
604
605 return 0;
606}
607
388static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, 608static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
389 int start) 609 int start)
390{ 610{
@@ -416,53 +636,52 @@ static void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv,
416 636
417static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 637static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
418{ 638{
419 struct fb_var_screeninfo *var = &ch->info->var, *display_var = &ch->display_var; 639 const struct fb_var_screeninfo *var = &ch->info->var;
640 const struct fb_videomode *mode = &ch->display.mode;
420 unsigned long h_total, hsync_pos, display_h_total; 641 unsigned long h_total, hsync_pos, display_h_total;
421 u32 tmp; 642 u32 tmp;
422 643
423 tmp = ch->ldmt1r_value; 644 tmp = ch->ldmt1r_value;
424 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; 645 tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL;
425 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; 646 tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL;
426 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; 647 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0;
427 tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; 648 tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0;
428 tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; 649 tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0;
429 tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; 650 tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0;
430 tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; 651 tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0;
431 lcdc_write_chan(ch, LDMT1R, tmp); 652 lcdc_write_chan(ch, LDMT1R, tmp);
432 653
433 /* setup SYS bus */ 654 /* setup SYS bus */
434 lcdc_write_chan(ch, LDMT2R, ch->cfg.sys_bus_cfg.ldmt2r); 655 lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r);
435 lcdc_write_chan(ch, LDMT3R, ch->cfg.sys_bus_cfg.ldmt3r); 656 lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r);
436 657
437 /* horizontal configuration */ 658 /* horizontal configuration */
438 h_total = display_var->xres + display_var->hsync_len + 659 h_total = mode->xres + mode->hsync_len + mode->left_margin
439 display_var->left_margin + display_var->right_margin; 660 + mode->right_margin;
440 tmp = h_total / 8; /* HTCN */ 661 tmp = h_total / 8; /* HTCN */
441 tmp |= (min(display_var->xres, var->xres) / 8) << 16; /* HDCN */ 662 tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */
442 lcdc_write_chan(ch, LDHCNR, tmp); 663 lcdc_write_chan(ch, LDHCNR, tmp);
443 664
444 hsync_pos = display_var->xres + display_var->right_margin; 665 hsync_pos = mode->xres + mode->right_margin;
445 tmp = hsync_pos / 8; /* HSYNP */ 666 tmp = hsync_pos / 8; /* HSYNP */
446 tmp |= (display_var->hsync_len / 8) << 16; /* HSYNW */ 667 tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */
447 lcdc_write_chan(ch, LDHSYNR, tmp); 668 lcdc_write_chan(ch, LDHSYNR, tmp);
448 669
449 /* vertical configuration */ 670 /* vertical configuration */
450 tmp = display_var->yres + display_var->vsync_len + 671 tmp = mode->yres + mode->vsync_len + mode->upper_margin
451 display_var->upper_margin + display_var->lower_margin; /* VTLN */ 672 + mode->lower_margin; /* VTLN */
452 tmp |= min(display_var->yres, var->yres) << 16; /* VDLN */ 673 tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */
453 lcdc_write_chan(ch, LDVLNR, tmp); 674 lcdc_write_chan(ch, LDVLNR, tmp);
454 675
455 tmp = display_var->yres + display_var->lower_margin; /* VSYNP */ 676 tmp = mode->yres + mode->lower_margin; /* VSYNP */
456 tmp |= display_var->vsync_len << 16; /* VSYNW */ 677 tmp |= mode->vsync_len << 16; /* VSYNW */
457 lcdc_write_chan(ch, LDVSYNR, tmp); 678 lcdc_write_chan(ch, LDVSYNR, tmp);
458 679
459 /* Adjust horizontal synchronisation for HDMI */ 680 /* Adjust horizontal synchronisation for HDMI */
460 display_h_total = display_var->xres + display_var->hsync_len + 681 display_h_total = mode->xres + mode->hsync_len + mode->left_margin
461 display_var->left_margin + display_var->right_margin; 682 + mode->right_margin;
462 tmp = ((display_var->xres & 7) << 24) | 683 tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
463 ((display_h_total & 7) << 16) | 684 | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
464 ((display_var->hsync_len & 7) << 8) |
465 (hsync_pos & 7);
466 lcdc_write_chan(ch, LDHAJR, tmp); 685 lcdc_write_chan(ch, LDHAJR, tmp);
467} 686}
468 687
@@ -498,7 +717,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
498 /* Power supply */ 717 /* Power supply */
499 lcdc_write_chan(ch, LDPMR, 0); 718 lcdc_write_chan(ch, LDPMR, 0);
500 719
501 m = ch->cfg.clock_divider; 720 m = ch->cfg->clock_divider;
502 if (!m) 721 if (!m)
503 continue; 722 continue;
504 723
@@ -525,32 +744,10 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
525 744
526 sh_mobile_lcdc_geometry(ch); 745 sh_mobile_lcdc_geometry(ch);
527 746
528 switch (sh_mobile_format_fourcc(&ch->info->var)) { 747 tmp = ch->format->lddfr;
529 case V4L2_PIX_FMT_RGB565:
530 tmp = LDDFR_PKF_RGB16;
531 break;
532 case V4L2_PIX_FMT_BGR24:
533 tmp = LDDFR_PKF_RGB24;
534 break;
535 case V4L2_PIX_FMT_BGR32:
536 tmp = LDDFR_PKF_ARGB32;
537 break;
538 case V4L2_PIX_FMT_NV12:
539 case V4L2_PIX_FMT_NV21:
540 tmp = LDDFR_CC | LDDFR_YF_420;
541 break;
542 case V4L2_PIX_FMT_NV16:
543 case V4L2_PIX_FMT_NV61:
544 tmp = LDDFR_CC | LDDFR_YF_422;
545 break;
546 case V4L2_PIX_FMT_NV24:
547 case V4L2_PIX_FMT_NV42:
548 tmp = LDDFR_CC | LDDFR_YF_444;
549 break;
550 }
551 748
552 if (sh_mobile_format_is_yuv(&ch->info->var)) { 749 if (ch->format->yuv) {
553 switch (ch->info->var.colorspace) { 750 switch (ch->colorspace) {
554 case V4L2_COLORSPACE_REC709: 751 case V4L2_COLORSPACE_REC709:
555 tmp |= LDDFR_CF1; 752 tmp |= LDDFR_CF1;
556 break; 753 break;
@@ -563,7 +760,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
563 lcdc_write_chan(ch, LDDFR, tmp); 760 lcdc_write_chan(ch, LDDFR, tmp);
564 lcdc_write_chan(ch, LDMLSR, ch->pitch); 761 lcdc_write_chan(ch, LDMLSR, ch->pitch);
565 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 762 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
566 if (sh_mobile_format_is_yuv(&ch->info->var)) 763 if (ch->format->yuv)
567 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 764 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
568 765
569 /* When using deferred I/O mode, configure the LCDC for one-shot 766 /* When using deferred I/O mode, configure the LCDC for one-shot
@@ -571,7 +768,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
571 * continuous read mode. 768 * continuous read mode.
572 */ 769 */
573 if (ch->ldmt1r_value & LDMT1R_IFM && 770 if (ch->ldmt1r_value & LDMT1R_IFM &&
574 ch->cfg.sys_bus_cfg.deferred_io_msec) { 771 ch->cfg->sys_bus_cfg.deferred_io_msec) {
575 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); 772 lcdc_write_chan(ch, LDSM1R, LDSM1R_OS);
576 lcdc_write(priv, _LDINTR, LDINTR_FE); 773 lcdc_write(priv, _LDINTR, LDINTR_FE);
577 } else { 774 } else {
@@ -580,7 +777,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
580 } 777 }
581 778
582 /* Word and long word swap. */ 779 /* Word and long word swap. */
583 switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) { 780 switch (priv->ch[0].format->fourcc) {
584 case V4L2_PIX_FMT_RGB565: 781 case V4L2_PIX_FMT_RGB565:
585 case V4L2_PIX_FMT_NV21: 782 case V4L2_PIX_FMT_NV21:
586 case V4L2_PIX_FMT_NV61: 783 case V4L2_PIX_FMT_NV61:
@@ -609,7 +806,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
609static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 806static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
610{ 807{
611 struct sh_mobile_meram_info *mdev = priv->meram_dev; 808 struct sh_mobile_meram_info *mdev = priv->meram_dev;
612 struct sh_mobile_lcdc_board_cfg *board_cfg;
613 struct sh_mobile_lcdc_chan *ch; 809 struct sh_mobile_lcdc_chan *ch;
614 unsigned long tmp; 810 unsigned long tmp;
615 int ret; 811 int ret;
@@ -626,15 +822,15 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
626 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); 822 lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0);
627 823
628 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 824 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
629 ch = &priv->ch[k]; 825 const struct sh_mobile_lcdc_panel_cfg *panel;
630 826
827 ch = &priv->ch[k];
631 if (!ch->enabled) 828 if (!ch->enabled)
632 continue; 829 continue;
633 830
634 board_cfg = &ch->cfg.board_cfg; 831 panel = &ch->cfg->panel_cfg;
635 if (board_cfg->setup_sys) { 832 if (panel->setup_sys) {
636 ret = board_cfg->setup_sys(board_cfg->board_data, ch, 833 ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops);
637 &sh_mobile_lcdc_sys_bus_ops);
638 if (ret) 834 if (ret)
639 return ret; 835 return ret;
640 } 836 }
@@ -642,33 +838,30 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
642 838
643 /* Compute frame buffer base address and pitch for each channel. */ 839 /* Compute frame buffer base address and pitch for each channel. */
644 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 840 for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
645 struct sh_mobile_meram_cfg *cfg;
646 int pixelformat; 841 int pixelformat;
842 void *meram;
647 843
648 ch = &priv->ch[k]; 844 ch = &priv->ch[k];
649 if (!ch->enabled) 845 if (!ch->enabled)
650 continue; 846 continue;
651 847
652 ch->base_addr_y = ch->info->fix.smem_start; 848 ch->base_addr_y = ch->dma_handle;
653 ch->base_addr_c = ch->base_addr_y 849 ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual;
654 + ch->info->var.xres
655 * ch->info->var.yres_virtual;
656 ch->pitch = ch->info->fix.line_length;
657 850
658 /* Enable MERAM if possible. */ 851 /* Enable MERAM if possible. */
659 cfg = ch->cfg.meram_cfg; 852 if (mdev == NULL || mdev->ops == NULL ||
660 if (mdev == NULL || mdev->ops == NULL || cfg == NULL) 853 ch->cfg->meram_cfg == NULL)
661 continue; 854 continue;
662 855
663 /* we need to de-init configured ICBs before we can 856 /* we need to de-init configured ICBs before we can
664 * re-initialize them. 857 * re-initialize them.
665 */ 858 */
666 if (ch->meram_enabled) { 859 if (ch->meram) {
667 mdev->ops->meram_unregister(mdev, cfg); 860 mdev->ops->meram_unregister(mdev, ch->meram);
668 ch->meram_enabled = 0; 861 ch->meram = NULL;
669 } 862 }
670 863
671 switch (sh_mobile_format_fourcc(&ch->info->var)) { 864 switch (ch->format->fourcc) {
672 case V4L2_PIX_FMT_NV12: 865 case V4L2_PIX_FMT_NV12:
673 case V4L2_PIX_FMT_NV21: 866 case V4L2_PIX_FMT_NV21:
674 case V4L2_PIX_FMT_NV16: 867 case V4L2_PIX_FMT_NV16:
@@ -687,13 +880,15 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
687 break; 880 break;
688 } 881 }
689 882
690 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, 883 meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg,
691 ch->info->var.yres, pixelformat, 884 ch->pitch, ch->yres, pixelformat,
692 ch->base_addr_y, ch->base_addr_c,
693 &ch->base_addr_y, &ch->base_addr_c,
694 &ch->pitch); 885 &ch->pitch);
695 if (!ret) 886 if (!IS_ERR(meram)) {
696 ch->meram_enabled = 1; 887 mdev->ops->meram_update(mdev, meram,
888 ch->base_addr_y, ch->base_addr_c,
889 &ch->base_addr_y, &ch->base_addr_c);
890 ch->meram = meram;
891 }
697 } 892 }
698 893
699 /* Start the LCDC. */ 894 /* Start the LCDC. */
@@ -707,7 +902,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
707 if (!ch->enabled) 902 if (!ch->enabled)
708 continue; 903 continue;
709 904
710 tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; 905 tmp = ch->cfg->sys_bus_cfg.deferred_io_msec;
711 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { 906 if (ch->ldmt1r_value & LDMT1R_IFM && tmp) {
712 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 907 ch->defio.deferred_io = sh_mobile_lcdc_deferred_io;
713 ch->defio.delay = msecs_to_jiffies(tmp); 908 ch->defio.delay = msecs_to_jiffies(tmp);
@@ -715,11 +910,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
715 fb_deferred_io_init(ch->info); 910 fb_deferred_io_init(ch->info);
716 } 911 }
717 912
718 board_cfg = &ch->cfg.board_cfg; 913 sh_mobile_lcdc_display_on(ch);
719 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
720 board_cfg->display_on(board_cfg->board_data, ch->info);
721 module_put(board_cfg->owner);
722 }
723 914
724 if (ch->bl) { 915 if (ch->bl) {
725 ch->bl->props.power = FB_BLANK_UNBLANK; 916 ch->bl->props.power = FB_BLANK_UNBLANK;
@@ -733,7 +924,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
733static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) 924static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
734{ 925{
735 struct sh_mobile_lcdc_chan *ch; 926 struct sh_mobile_lcdc_chan *ch;
736 struct sh_mobile_lcdc_board_cfg *board_cfg;
737 int k; 927 int k;
738 928
739 /* clean up deferred io and ask board code to disable panel */ 929 /* clean up deferred io and ask board code to disable panel */
@@ -760,20 +950,14 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
760 backlight_update_status(ch->bl); 950 backlight_update_status(ch->bl);
761 } 951 }
762 952
763 board_cfg = &ch->cfg.board_cfg; 953 sh_mobile_lcdc_display_off(ch);
764 if (board_cfg->display_off && try_module_get(board_cfg->owner)) {
765 board_cfg->display_off(board_cfg->board_data);
766 module_put(board_cfg->owner);
767 }
768 954
769 /* disable the meram */ 955 /* disable the meram */
770 if (ch->meram_enabled) { 956 if (ch->meram) {
771 struct sh_mobile_meram_cfg *cfg;
772 struct sh_mobile_meram_info *mdev; 957 struct sh_mobile_meram_info *mdev;
773 cfg = ch->cfg.meram_cfg;
774 mdev = priv->meram_dev; 958 mdev = priv->meram_dev;
775 mdev->ops->meram_unregister(mdev, cfg); 959 mdev->ops->meram_unregister(mdev, ch->meram);
776 ch->meram_enabled = 0; 960 ch->meram = 0;
777 } 961 }
778 962
779 } 963 }
@@ -790,86 +974,9 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
790 sh_mobile_lcdc_clk_off(priv); 974 sh_mobile_lcdc_clk_off(priv);
791} 975}
792 976
793static int sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 977/* -----------------------------------------------------------------------------
794{ 978 * Frame buffer operations
795 int interface_type = ch->cfg.interface_type; 979 */
796
797 switch (interface_type) {
798 case RGB8:
799 case RGB9:
800 case RGB12A:
801 case RGB12B:
802 case RGB16:
803 case RGB18:
804 case RGB24:
805 case SYS8A:
806 case SYS8B:
807 case SYS8C:
808 case SYS8D:
809 case SYS9:
810 case SYS12:
811 case SYS16A:
812 case SYS16B:
813 case SYS16C:
814 case SYS18:
815 case SYS24:
816 break;
817 default:
818 return -EINVAL;
819 }
820
821 /* SUBLCD only supports SYS interface */
822 if (lcdc_chan_is_sublcd(ch)) {
823 if (!(interface_type & LDMT1R_IFM))
824 return -EINVAL;
825
826 interface_type &= ~LDMT1R_IFM;
827 }
828
829 ch->ldmt1r_value = interface_type;
830 return 0;
831}
832
833static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev,
834 int clock_source,
835 struct sh_mobile_lcdc_priv *priv)
836{
837 char *str;
838
839 switch (clock_source) {
840 case LCDC_CLK_BUS:
841 str = "bus_clk";
842 priv->lddckr = LDDCKR_ICKSEL_BUS;
843 break;
844 case LCDC_CLK_PERIPHERAL:
845 str = "peripheral_clk";
846 priv->lddckr = LDDCKR_ICKSEL_MIPI;
847 break;
848 case LCDC_CLK_EXTERNAL:
849 str = NULL;
850 priv->lddckr = LDDCKR_ICKSEL_HDMI;
851 break;
852 default:
853 return -EINVAL;
854 }
855
856 if (str) {
857 priv->dot_clk = clk_get(&pdev->dev, str);
858 if (IS_ERR(priv->dot_clk)) {
859 dev_err(&pdev->dev, "cannot get dot clock %s\n", str);
860 return PTR_ERR(priv->dot_clk);
861 }
862 }
863
864 /* Runtime PM support involves two step for this driver:
865 * 1) Enable Runtime PM
866 * 2) Force Runtime PM Resume since hardware is accessed from probe()
867 */
868 priv->dev = &pdev->dev;
869 pm_runtime_enable(priv->dev);
870 pm_runtime_resume(priv->dev);
871 return 0;
872}
873 980
874static int sh_mobile_lcdc_setcolreg(u_int regno, 981static int sh_mobile_lcdc_setcolreg(u_int regno,
875 u_int red, u_int green, u_int blue, 982 u_int red, u_int green, u_int blue,
@@ -936,14 +1043,12 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
936 unsigned long new_pan_offset; 1043 unsigned long new_pan_offset;
937 unsigned long base_addr_y, base_addr_c; 1044 unsigned long base_addr_y, base_addr_c;
938 unsigned long c_offset; 1045 unsigned long c_offset;
939 bool yuv = sh_mobile_format_is_yuv(&info->var);
940 1046
941 if (!yuv) 1047 if (!ch->format->yuv)
942 new_pan_offset = var->yoffset * info->fix.line_length 1048 new_pan_offset = var->yoffset * ch->pitch
943 + var->xoffset * (info->var.bits_per_pixel / 8); 1049 + var->xoffset * (ch->format->bpp / 8);
944 else 1050 else
945 new_pan_offset = var->yoffset * info->fix.line_length 1051 new_pan_offset = var->yoffset * ch->pitch + var->xoffset;
946 + var->xoffset;
947 1052
948 if (new_pan_offset == ch->pan_offset) 1053 if (new_pan_offset == ch->pan_offset)
949 return 0; /* No change, do nothing */ 1054 return 0; /* No change, do nothing */
@@ -952,39 +1057,33 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
952 1057
953 /* Set the source address for the next refresh */ 1058 /* Set the source address for the next refresh */
954 base_addr_y = ch->dma_handle + new_pan_offset; 1059 base_addr_y = ch->dma_handle + new_pan_offset;
955 if (yuv) { 1060 if (ch->format->yuv) {
956 /* Set y offset */ 1061 /* Set y offset */
957 c_offset = var->yoffset * info->fix.line_length 1062 c_offset = var->yoffset * ch->pitch
958 * (info->var.bits_per_pixel - 8) / 8; 1063 * (ch->format->bpp - 8) / 8;
959 base_addr_c = ch->dma_handle 1064 base_addr_c = ch->dma_handle + ch->xres * ch->yres_virtual
960 + info->var.xres * info->var.yres_virtual
961 + c_offset; 1065 + c_offset;
962 /* Set x offset */ 1066 /* Set x offset */
963 if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24) 1067 if (ch->format->fourcc == V4L2_PIX_FMT_NV24)
964 base_addr_c += 2 * var->xoffset; 1068 base_addr_c += 2 * var->xoffset;
965 else 1069 else
966 base_addr_c += var->xoffset; 1070 base_addr_c += var->xoffset;
967 } 1071 }
968 1072
969 if (ch->meram_enabled) { 1073 if (ch->meram) {
970 struct sh_mobile_meram_cfg *cfg;
971 struct sh_mobile_meram_info *mdev; 1074 struct sh_mobile_meram_info *mdev;
972 int ret;
973 1075
974 cfg = ch->cfg.meram_cfg;
975 mdev = priv->meram_dev; 1076 mdev = priv->meram_dev;
976 ret = mdev->ops->meram_update(mdev, cfg, 1077 mdev->ops->meram_update(mdev, ch->meram,
977 base_addr_y, base_addr_c, 1078 base_addr_y, base_addr_c,
978 &base_addr_y, &base_addr_c); 1079 &base_addr_y, &base_addr_c);
979 if (ret)
980 return ret;
981 } 1080 }
982 1081
983 ch->base_addr_y = base_addr_y; 1082 ch->base_addr_y = base_addr_y;
984 ch->base_addr_c = base_addr_c; 1083 ch->base_addr_c = base_addr_c;
985 1084
986 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 1085 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
987 if (yuv) 1086 if (ch->format->yuv)
988 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 1087 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
989 1088
990 if (lcdc_chan_is_sublcd(ch)) 1089 if (lcdc_chan_is_sublcd(ch))
@@ -999,27 +1098,6 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
999 return 0; 1098 return 0;
1000} 1099}
1001 1100
1002static int sh_mobile_wait_for_vsync(struct fb_info *info)
1003{
1004 struct sh_mobile_lcdc_chan *ch = info->par;
1005 unsigned long ldintr;
1006 int ret;
1007
1008 /* Enable VSync End interrupt and be careful not to acknowledge any
1009 * pending interrupt.
1010 */
1011 ldintr = lcdc_read(ch->lcdc, _LDINTR);
1012 ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK;
1013 lcdc_write(ch->lcdc, _LDINTR, ldintr);
1014
1015 ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion,
1016 msecs_to_jiffies(100));
1017 if (!ret)
1018 return -ETIMEDOUT;
1019
1020 return 0;
1021}
1022
1023static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd, 1101static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
1024 unsigned long arg) 1102 unsigned long arg)
1025{ 1103{
@@ -1027,7 +1105,7 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
1027 1105
1028 switch (cmd) { 1106 switch (cmd) {
1029 case FBIO_WAITFORVSYNC: 1107 case FBIO_WAITFORVSYNC:
1030 retval = sh_mobile_wait_for_vsync(info); 1108 retval = sh_mobile_wait_for_vsync(info->par);
1031 break; 1109 break;
1032 1110
1033 default: 1111 default:
@@ -1040,7 +1118,8 @@ static int sh_mobile_ioctl(struct fb_info *info, unsigned int cmd,
1040static void sh_mobile_fb_reconfig(struct fb_info *info) 1118static void sh_mobile_fb_reconfig(struct fb_info *info)
1041{ 1119{
1042 struct sh_mobile_lcdc_chan *ch = info->par; 1120 struct sh_mobile_lcdc_chan *ch = info->par;
1043 struct fb_videomode mode1, mode2; 1121 struct fb_var_screeninfo var;
1122 struct fb_videomode mode;
1044 struct fb_event event; 1123 struct fb_event event;
1045 int evnt = FB_EVENT_MODE_CHANGE_ALL; 1124 int evnt = FB_EVENT_MODE_CHANGE_ALL;
1046 1125
@@ -1048,14 +1127,19 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
1048 /* More framebuffer users are active */ 1127 /* More framebuffer users are active */
1049 return; 1128 return;
1050 1129
1051 fb_var_to_videomode(&mode1, &ch->display_var); 1130 fb_var_to_videomode(&mode, &info->var);
1052 fb_var_to_videomode(&mode2, &info->var);
1053 1131
1054 if (fb_mode_is_equal(&mode1, &mode2)) 1132 if (fb_mode_is_equal(&ch->display.mode, &mode))
1055 return; 1133 return;
1056 1134
1057 /* Display has been re-plugged, framebuffer is free now, reconfigure */ 1135 /* Display has been re-plugged, framebuffer is free now, reconfigure */
1058 if (fb_set_var(info, &ch->display_var) < 0) 1136 var = info->var;
1137 fb_videomode_to_var(&var, &ch->display.mode);
1138 var.width = ch->display.width;
1139 var.height = ch->display.height;
1140 var.activate = FB_ACTIVATE_NOW;
1141
1142 if (fb_set_var(info, &var) < 0)
1059 /* Couldn't reconfigure, hopefully, can continue as before */ 1143 /* Couldn't reconfigure, hopefully, can continue as before */
1060 return; 1144 return;
1061 1145
@@ -1065,7 +1149,7 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
1065 * user event, we have to call the chain ourselves. 1149 * user event, we have to call the chain ourselves.
1066 */ 1150 */
1067 event.info = info; 1151 event.info = info;
1068 event.data = &mode1; 1152 event.data = &ch->display.mode;
1069 fb_notifier_call_chain(evnt, &event); 1153 fb_notifier_call_chain(evnt, &event);
1070} 1154}
1071 1155
@@ -1124,8 +1208,8 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1124 * distance between two modes is defined as the size of the 1208 * distance between two modes is defined as the size of the
1125 * non-overlapping parts of the two rectangles. 1209 * non-overlapping parts of the two rectangles.
1126 */ 1210 */
1127 for (i = 0; i < ch->cfg.num_cfg; ++i) { 1211 for (i = 0; i < ch->cfg->num_modes; ++i) {
1128 const struct fb_videomode *mode = &ch->cfg.lcd_cfg[i]; 1212 const struct fb_videomode *mode = &ch->cfg->lcd_modes[i];
1129 unsigned int dist; 1213 unsigned int dist;
1130 1214
1131 /* We can only round up. */ 1215 /* We can only round up. */
@@ -1144,7 +1228,7 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1144 } 1228 }
1145 1229
1146 /* If no available mode can be used, return an error. */ 1230 /* If no available mode can be used, return an error. */
1147 if (ch->cfg.num_cfg != 0) { 1231 if (ch->cfg->num_modes != 0) {
1148 if (best_dist == (unsigned int)-1) 1232 if (best_dist == (unsigned int)-1)
1149 return -EINVAL; 1233 return -EINVAL;
1150 1234
@@ -1161,32 +1245,17 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1161 var->yres_virtual = var->yres; 1245 var->yres_virtual = var->yres;
1162 1246
1163 if (sh_mobile_format_is_fourcc(var)) { 1247 if (sh_mobile_format_is_fourcc(var)) {
1164 switch (var->grayscale) { 1248 const struct sh_mobile_lcdc_format_info *format;
1165 case V4L2_PIX_FMT_NV12: 1249
1166 case V4L2_PIX_FMT_NV21: 1250 format = sh_mobile_format_info(var->grayscale);
1167 var->bits_per_pixel = 12; 1251 if (format == NULL)
1168 break;
1169 case V4L2_PIX_FMT_RGB565:
1170 case V4L2_PIX_FMT_NV16:
1171 case V4L2_PIX_FMT_NV61:
1172 var->bits_per_pixel = 16;
1173 break;
1174 case V4L2_PIX_FMT_BGR24:
1175 case V4L2_PIX_FMT_NV24:
1176 case V4L2_PIX_FMT_NV42:
1177 var->bits_per_pixel = 24;
1178 break;
1179 case V4L2_PIX_FMT_BGR32:
1180 var->bits_per_pixel = 32;
1181 break;
1182 default:
1183 return -EINVAL; 1252 return -EINVAL;
1184 } 1253 var->bits_per_pixel = format->bpp;
1185 1254
1186 /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1255 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1187 * respectively. 1256 * respectively.
1188 */ 1257 */
1189 if (!sh_mobile_format_is_yuv(var)) 1258 if (!format->yuv)
1190 var->colorspace = V4L2_COLORSPACE_SRGB; 1259 var->colorspace = V4L2_COLORSPACE_SRGB;
1191 else if (var->colorspace != V4L2_COLORSPACE_REC709) 1260 else if (var->colorspace != V4L2_COLORSPACE_REC709)
1192 var->colorspace = V4L2_COLORSPACE_JPEG; 1261 var->colorspace = V4L2_COLORSPACE_JPEG;
@@ -1246,22 +1315,28 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1246static int sh_mobile_set_par(struct fb_info *info) 1315static int sh_mobile_set_par(struct fb_info *info)
1247{ 1316{
1248 struct sh_mobile_lcdc_chan *ch = info->par; 1317 struct sh_mobile_lcdc_chan *ch = info->par;
1249 u32 line_length = info->fix.line_length;
1250 int ret; 1318 int ret;
1251 1319
1252 sh_mobile_lcdc_stop(ch->lcdc); 1320 sh_mobile_lcdc_stop(ch->lcdc);
1253 1321
1254 if (sh_mobile_format_is_yuv(&info->var)) 1322 ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var));
1255 info->fix.line_length = info->var.xres; 1323 ch->colorspace = info->var.colorspace;
1324
1325 ch->xres = info->var.xres;
1326 ch->xres_virtual = info->var.xres_virtual;
1327 ch->yres = info->var.yres;
1328 ch->yres_virtual = info->var.yres_virtual;
1329
1330 if (ch->format->yuv)
1331 ch->pitch = info->var.xres;
1256 else 1332 else
1257 info->fix.line_length = info->var.xres 1333 ch->pitch = info->var.xres * ch->format->bpp / 8;
1258 * info->var.bits_per_pixel / 8;
1259 1334
1260 ret = sh_mobile_lcdc_start(ch->lcdc); 1335 ret = sh_mobile_lcdc_start(ch->lcdc);
1261 if (ret < 0) { 1336 if (ret < 0)
1262 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 1337 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__);
1263 info->fix.line_length = line_length; 1338
1264 } 1339 info->fix.line_length = ch->pitch;
1265 1340
1266 if (sh_mobile_format_is_fourcc(&info->var)) { 1341 if (sh_mobile_format_is_fourcc(&info->var)) {
1267 info->fix.type = FB_TYPE_FOURCC; 1342 info->fix.type = FB_TYPE_FOURCC;
@@ -1290,8 +1365,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
1290 /* blank the screen? */ 1365 /* blank the screen? */
1291 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { 1366 if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) {
1292 struct fb_fillrect rect = { 1367 struct fb_fillrect rect = {
1293 .width = info->var.xres, 1368 .width = ch->xres,
1294 .height = info->var.yres, 1369 .height = ch->yres,
1295 }; 1370 };
1296 sh_mobile_lcdc_fillrect(info, &rect); 1371 sh_mobile_lcdc_fillrect(info, &rect);
1297 } 1372 }
@@ -1307,8 +1382,8 @@ static int sh_mobile_lcdc_blank(int blank, struct fb_info *info)
1307 * mode will reenable the clocks and update the screen in time, 1382 * mode will reenable the clocks and update the screen in time,
1308 * so it does not need this. */ 1383 * so it does not need this. */
1309 if (!info->fbdefio) { 1384 if (!info->fbdefio) {
1310 sh_mobile_wait_for_vsync(info); 1385 sh_mobile_wait_for_vsync(ch);
1311 sh_mobile_wait_for_vsync(info); 1386 sh_mobile_wait_for_vsync(ch);
1312 } 1387 }
1313 sh_mobile_lcdc_clk_off(p); 1388 sh_mobile_lcdc_clk_off(p);
1314 } 1389 }
@@ -1334,25 +1409,161 @@ static struct fb_ops sh_mobile_lcdc_ops = {
1334 .fb_set_par = sh_mobile_set_par, 1409 .fb_set_par = sh_mobile_set_par,
1335}; 1410};
1336 1411
1412static void
1413sh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch)
1414{
1415 if (ch->info && ch->info->dev)
1416 unregister_framebuffer(ch->info);
1417}
1418
1419static int __devinit
1420sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
1421{
1422 struct fb_info *info = ch->info;
1423 int ret;
1424
1425 if (info->fbdefio) {
1426 ch->sglist = vmalloc(sizeof(struct scatterlist) *
1427 ch->fb_size >> PAGE_SHIFT);
1428 if (!ch->sglist) {
1429 dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
1430 return -ENOMEM;
1431 }
1432 }
1433
1434 info->bl_dev = ch->bl;
1435
1436 ret = register_framebuffer(info);
1437 if (ret < 0)
1438 return ret;
1439
1440 dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n",
1441 dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ?
1442 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
1443 info->var.bits_per_pixel);
1444
1445 /* deferred io mode: disable clock to save power */
1446 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1447 sh_mobile_lcdc_clk_off(ch->lcdc);
1448
1449 return ret;
1450}
1451
1452static void
1453sh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch)
1454{
1455 struct fb_info *info = ch->info;
1456
1457 if (!info || !info->device)
1458 return;
1459
1460 if (ch->sglist)
1461 vfree(ch->sglist);
1462
1463 fb_dealloc_cmap(&info->cmap);
1464 framebuffer_release(info);
1465}
1466
1467static int __devinit
1468sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch,
1469 const struct fb_videomode *mode,
1470 unsigned int num_modes)
1471{
1472 struct sh_mobile_lcdc_priv *priv = ch->lcdc;
1473 struct fb_var_screeninfo *var;
1474 struct fb_info *info;
1475 int ret;
1476
1477 /* Allocate and initialize the frame buffer device. Create the modes
1478 * list and allocate the color map.
1479 */
1480 info = framebuffer_alloc(0, priv->dev);
1481 if (info == NULL) {
1482 dev_err(priv->dev, "unable to allocate fb_info\n");
1483 return -ENOMEM;
1484 }
1485
1486 ch->info = info;
1487
1488 info->flags = FBINFO_FLAG_DEFAULT;
1489 info->fbops = &sh_mobile_lcdc_ops;
1490 info->device = priv->dev;
1491 info->screen_base = ch->fb_mem;
1492 info->pseudo_palette = &ch->pseudo_palette;
1493 info->par = ch;
1494
1495 fb_videomode_to_modelist(mode, num_modes, &info->modelist);
1496
1497 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1498 if (ret < 0) {
1499 dev_err(priv->dev, "unable to allocate cmap\n");
1500 return ret;
1501 }
1502
1503 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1504 * for NV12 and NV21.
1505 */
1506 info->fix = sh_mobile_lcdc_fix;
1507 info->fix.smem_start = ch->dma_handle;
1508 info->fix.smem_len = ch->fb_size;
1509 info->fix.line_length = ch->pitch;
1510
1511 if (ch->format->yuv)
1512 info->fix.visual = FB_VISUAL_FOURCC;
1513 else
1514 info->fix.visual = FB_VISUAL_TRUECOLOR;
1515
1516 if (ch->format->fourcc == V4L2_PIX_FMT_NV12 ||
1517 ch->format->fourcc == V4L2_PIX_FMT_NV21)
1518 info->fix.ypanstep = 2;
1519
1520 /* Initialize variable screen information using the first mode as
1521 * default. The default Y virtual resolution is twice the panel size to
1522 * allow for double-buffering.
1523 */
1524 var = &info->var;
1525 fb_videomode_to_var(var, mode);
1526 var->width = ch->cfg->panel_cfg.width;
1527 var->height = ch->cfg->panel_cfg.height;
1528 var->yres_virtual = var->yres * 2;
1529 var->activate = FB_ACTIVATE_NOW;
1530
1531 /* Use the legacy API by default for RGB formats, and the FOURCC API
1532 * for YUV formats.
1533 */
1534 if (!ch->format->yuv)
1535 var->bits_per_pixel = ch->format->bpp;
1536 else
1537 var->grayscale = ch->format->fourcc;
1538
1539 ret = sh_mobile_check_var(var, info);
1540 if (ret)
1541 return ret;
1542
1543 return 0;
1544}
1545
1546/* -----------------------------------------------------------------------------
1547 * Backlight
1548 */
1549
1337static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) 1550static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
1338{ 1551{
1339 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 1552 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
1340 struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
1341 int brightness = bdev->props.brightness; 1553 int brightness = bdev->props.brightness;
1342 1554
1343 if (bdev->props.power != FB_BLANK_UNBLANK || 1555 if (bdev->props.power != FB_BLANK_UNBLANK ||
1344 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) 1556 bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
1345 brightness = 0; 1557 brightness = 0;
1346 1558
1347 return cfg->set_brightness(cfg->board_data, brightness); 1559 return ch->cfg->bl_info.set_brightness(brightness);
1348} 1560}
1349 1561
1350static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) 1562static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
1351{ 1563{
1352 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 1564 struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
1353 struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
1354 1565
1355 return cfg->get_brightness(cfg->board_data); 1566 return ch->cfg->bl_info.get_brightness();
1356} 1567}
1357 1568
1358static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, 1569static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
@@ -1373,7 +1584,7 @@ static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
1373{ 1584{
1374 struct backlight_device *bl; 1585 struct backlight_device *bl;
1375 1586
1376 bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch, 1587 bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch,
1377 &sh_mobile_lcdc_bl_ops, NULL); 1588 &sh_mobile_lcdc_bl_ops, NULL);
1378 if (IS_ERR(bl)) { 1589 if (IS_ERR(bl)) {
1379 dev_err(parent, "unable to register backlight device: %ld\n", 1590 dev_err(parent, "unable to register backlight device: %ld\n",
@@ -1381,7 +1592,7 @@ static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
1381 return NULL; 1592 return NULL;
1382 } 1593 }
1383 1594
1384 bl->props.max_brightness = ch->cfg.bl_info.max_brightness; 1595 bl->props.max_brightness = ch->cfg->bl_info.max_brightness;
1385 bl->props.brightness = bl->props.max_brightness; 1596 bl->props.brightness = bl->props.max_brightness;
1386 backlight_update_status(bl); 1597 backlight_update_status(bl);
1387 1598
@@ -1393,6 +1604,10 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
1393 backlight_device_unregister(bdev); 1604 backlight_device_unregister(bdev);
1394} 1605}
1395 1606
1607/* -----------------------------------------------------------------------------
1608 * Power management
1609 */
1610
1396static int sh_mobile_lcdc_suspend(struct device *dev) 1611static int sh_mobile_lcdc_suspend(struct device *dev)
1397{ 1612{
1398 struct platform_device *pdev = to_platform_device(dev); 1613 struct platform_device *pdev = to_platform_device(dev);
@@ -1436,6 +1651,10 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
1436 .runtime_resume = sh_mobile_lcdc_runtime_resume, 1651 .runtime_resume = sh_mobile_lcdc_runtime_resume,
1437}; 1652};
1438 1653
1654/* -----------------------------------------------------------------------------
1655 * Framebuffer notifier
1656 */
1657
1439/* locking: called with info->lock held */ 1658/* locking: called with info->lock held */
1440static int sh_mobile_lcdc_notify(struct notifier_block *nb, 1659static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1441 unsigned long action, void *data) 1660 unsigned long action, void *data)
@@ -1443,7 +1662,6 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1443 struct fb_event *event = data; 1662 struct fb_event *event = data;
1444 struct fb_info *info = event->info; 1663 struct fb_info *info = event->info;
1445 struct sh_mobile_lcdc_chan *ch = info->par; 1664 struct sh_mobile_lcdc_chan *ch = info->par;
1446 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1447 1665
1448 if (&ch->lcdc->notifier != nb) 1666 if (&ch->lcdc->notifier != nb)
1449 return NOTIFY_DONE; 1667 return NOTIFY_DONE;
@@ -1453,10 +1671,7 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1453 1671
1454 switch(action) { 1672 switch(action) {
1455 case FB_EVENT_SUSPEND: 1673 case FB_EVENT_SUSPEND:
1456 if (board_cfg->display_off && try_module_get(board_cfg->owner)) { 1674 sh_mobile_lcdc_display_off(ch);
1457 board_cfg->display_off(board_cfg->board_data);
1458 module_put(board_cfg->owner);
1459 }
1460 sh_mobile_lcdc_stop(ch->lcdc); 1675 sh_mobile_lcdc_stop(ch->lcdc);
1461 break; 1676 break;
1462 case FB_EVENT_RESUME: 1677 case FB_EVENT_RESUME:
@@ -1464,47 +1679,60 @@ static int sh_mobile_lcdc_notify(struct notifier_block *nb,
1464 sh_mobile_fb_reconfig(info); 1679 sh_mobile_fb_reconfig(info);
1465 mutex_unlock(&ch->open_lock); 1680 mutex_unlock(&ch->open_lock);
1466 1681
1467 /* HDMI must be enabled before LCDC configuration */ 1682 sh_mobile_lcdc_display_on(ch);
1468 if (board_cfg->display_on && try_module_get(board_cfg->owner)) {
1469 board_cfg->display_on(board_cfg->board_data, info);
1470 module_put(board_cfg->owner);
1471 }
1472
1473 sh_mobile_lcdc_start(ch->lcdc); 1683 sh_mobile_lcdc_start(ch->lcdc);
1474 } 1684 }
1475 1685
1476 return NOTIFY_OK; 1686 return NOTIFY_OK;
1477} 1687}
1478 1688
1689/* -----------------------------------------------------------------------------
1690 * Probe/remove and driver init/exit
1691 */
1692
1693static const struct fb_videomode default_720p __devinitconst = {
1694 .name = "HDMI 720p",
1695 .xres = 1280,
1696 .yres = 720,
1697
1698 .left_margin = 220,
1699 .right_margin = 110,
1700 .hsync_len = 40,
1701
1702 .upper_margin = 20,
1703 .lower_margin = 5,
1704 .vsync_len = 5,
1705
1706 .pixclock = 13468,
1707 .refresh = 60,
1708 .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT,
1709};
1710
1479static int sh_mobile_lcdc_remove(struct platform_device *pdev) 1711static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1480{ 1712{
1481 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 1713 struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
1482 struct fb_info *info;
1483 int i; 1714 int i;
1484 1715
1485 fb_unregister_client(&priv->notifier); 1716 fb_unregister_client(&priv->notifier);
1486 1717
1487 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 1718 for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
1488 if (priv->ch[i].info && priv->ch[i].info->dev) 1719 sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]);
1489 unregister_framebuffer(priv->ch[i].info);
1490 1720
1491 sh_mobile_lcdc_stop(priv); 1721 sh_mobile_lcdc_stop(priv);
1492 1722
1493 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 1723 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
1494 info = priv->ch[i].info; 1724 struct sh_mobile_lcdc_chan *ch = &priv->ch[i];
1495 1725
1496 if (!info || !info->device) 1726 if (ch->tx_dev) {
1497 continue; 1727 ch->tx_dev->lcdc = NULL;
1728 module_put(ch->cfg->tx_dev->dev.driver->owner);
1729 }
1498 1730
1499 if (priv->ch[i].sglist) 1731 sh_mobile_lcdc_channel_fb_cleanup(ch);
1500 vfree(priv->ch[i].sglist);
1501 1732
1502 if (info->screen_base) 1733 if (ch->fb_mem)
1503 dma_free_coherent(&pdev->dev, info->fix.smem_len, 1734 dma_free_coherent(&pdev->dev, ch->fb_size,
1504 info->screen_base, 1735 ch->fb_mem, ch->dma_handle);
1505 priv->ch[i].dma_handle);
1506 fb_dealloc_cmap(&info->cmap);
1507 framebuffer_release(info);
1508 } 1736 }
1509 1737
1510 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 1738 for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
@@ -1512,11 +1740,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1512 sh_mobile_lcdc_bl_remove(priv->ch[i].bl); 1740 sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
1513 } 1741 }
1514 1742
1515 if (priv->dot_clk) 1743 if (priv->dot_clk) {
1744 pm_runtime_disable(&pdev->dev);
1516 clk_put(priv->dot_clk); 1745 clk_put(priv->dot_clk);
1517 1746 }
1518 if (priv->dev)
1519 pm_runtime_disable(priv->dev);
1520 1747
1521 if (priv->base) 1748 if (priv->base)
1522 iounmap(priv->base); 1749 iounmap(priv->base);
@@ -1527,49 +1754,82 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
1527 return 0; 1754 return 0;
1528} 1755}
1529 1756
1530static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch, 1757static int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch)
1531 struct device *dev)
1532{ 1758{
1533 struct sh_mobile_lcdc_chan_cfg *cfg = &ch->cfg; 1759 int interface_type = ch->cfg->interface_type;
1760
1761 switch (interface_type) {
1762 case RGB8:
1763 case RGB9:
1764 case RGB12A:
1765 case RGB12B:
1766 case RGB16:
1767 case RGB18:
1768 case RGB24:
1769 case SYS8A:
1770 case SYS8B:
1771 case SYS8C:
1772 case SYS8D:
1773 case SYS9:
1774 case SYS12:
1775 case SYS16A:
1776 case SYS16B:
1777 case SYS16C:
1778 case SYS18:
1779 case SYS24:
1780 break;
1781 default:
1782 return -EINVAL;
1783 }
1784
1785 /* SUBLCD only supports SYS interface */
1786 if (lcdc_chan_is_sublcd(ch)) {
1787 if (!(interface_type & LDMT1R_IFM))
1788 return -EINVAL;
1789
1790 interface_type &= ~LDMT1R_IFM;
1791 }
1792
1793 ch->ldmt1r_value = interface_type;
1794 return 0;
1795}
1796
1797static int __devinit
1798sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_priv *priv,
1799 struct sh_mobile_lcdc_chan *ch)
1800{
1801 const struct sh_mobile_lcdc_format_info *format;
1802 const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg;
1534 const struct fb_videomode *max_mode; 1803 const struct fb_videomode *max_mode;
1535 const struct fb_videomode *mode; 1804 const struct fb_videomode *mode;
1536 struct fb_var_screeninfo *var; 1805 unsigned int num_modes;
1537 struct fb_info *info;
1538 unsigned int max_size; 1806 unsigned int max_size;
1539 int num_cfg; 1807 unsigned int i;
1540 void *buf;
1541 int ret;
1542 int i;
1543 1808
1544 mutex_init(&ch->open_lock); 1809 mutex_init(&ch->open_lock);
1810 ch->notify = sh_mobile_lcdc_display_notify;
1545 1811
1546 /* Allocate the frame buffer device. */ 1812 /* Validate the format. */
1547 ch->info = framebuffer_alloc(0, dev); 1813 format = sh_mobile_format_info(cfg->fourcc);
1548 if (!ch->info) { 1814 if (format == NULL) {
1549 dev_err(dev, "unable to allocate fb_info\n"); 1815 dev_err(priv->dev, "Invalid FOURCC %08x.\n", cfg->fourcc);
1550 return -ENOMEM; 1816 return -EINVAL;
1551 } 1817 }
1552 1818
1553 info = ch->info;
1554 info->fbops = &sh_mobile_lcdc_ops;
1555 info->par = ch;
1556 info->pseudo_palette = &ch->pseudo_palette;
1557 info->flags = FBINFO_FLAG_DEFAULT;
1558
1559 /* Iterate through the modes to validate them and find the highest 1819 /* Iterate through the modes to validate them and find the highest
1560 * resolution. 1820 * resolution.
1561 */ 1821 */
1562 max_mode = NULL; 1822 max_mode = NULL;
1563 max_size = 0; 1823 max_size = 0;
1564 1824
1565 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) { 1825 for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) {
1566 unsigned int size = mode->yres * mode->xres; 1826 unsigned int size = mode->yres * mode->xres;
1567 1827
1568 /* NV12/NV21 buffers must have even number of lines */ 1828 /* NV12/NV21 buffers must have even number of lines */
1569 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || 1829 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
1570 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { 1830 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
1571 dev_err(dev, "yres must be multiple of 2 for YCbCr420 " 1831 dev_err(priv->dev, "yres must be multiple of 2 for "
1572 "mode.\n"); 1832 "YCbCr420 mode.\n");
1573 return -EINVAL; 1833 return -EINVAL;
1574 } 1834 }
1575 1835
@@ -1582,93 +1842,59 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1582 if (!max_size) 1842 if (!max_size)
1583 max_size = MAX_XRES * MAX_YRES; 1843 max_size = MAX_XRES * MAX_YRES;
1584 else 1844 else
1585 dev_dbg(dev, "Found largest videomode %ux%u\n", 1845 dev_dbg(priv->dev, "Found largest videomode %ux%u\n",
1586 max_mode->xres, max_mode->yres); 1846 max_mode->xres, max_mode->yres);
1587 1847
1588 /* Create the mode list. */ 1848 if (cfg->lcd_modes == NULL) {
1589 if (cfg->lcd_cfg == NULL) {
1590 mode = &default_720p; 1849 mode = &default_720p;
1591 num_cfg = 1; 1850 num_modes = 1;
1592 } else { 1851 } else {
1593 mode = cfg->lcd_cfg; 1852 mode = cfg->lcd_modes;
1594 num_cfg = cfg->num_cfg; 1853 num_modes = cfg->num_modes;
1595 } 1854 }
1596 1855
1597 fb_videomode_to_modelist(mode, num_cfg, &info->modelist); 1856 /* Use the first mode as default. */
1857 ch->format = format;
1858 ch->xres = mode->xres;
1859 ch->xres_virtual = mode->xres;
1860 ch->yres = mode->yres;
1861 ch->yres_virtual = mode->yres * 2;
1598 1862
1599 /* Initialize variable screen information using the first mode as 1863 if (!format->yuv) {
1600 * default. The default Y virtual resolution is twice the panel size to 1864 ch->colorspace = V4L2_COLORSPACE_SRGB;
1601 * allow for double-buffering. 1865 ch->pitch = ch->xres * format->bpp / 8;
1602 */ 1866 } else {
1603 var = &info->var; 1867 ch->colorspace = V4L2_COLORSPACE_REC709;
1604 fb_videomode_to_var(var, mode); 1868 ch->pitch = ch->xres;
1605 var->width = cfg->lcd_size_cfg.width;
1606 var->height = cfg->lcd_size_cfg.height;
1607 var->yres_virtual = var->yres * 2;
1608 var->activate = FB_ACTIVATE_NOW;
1609
1610 switch (cfg->fourcc) {
1611 case V4L2_PIX_FMT_RGB565:
1612 var->bits_per_pixel = 16;
1613 break;
1614 case V4L2_PIX_FMT_BGR24:
1615 var->bits_per_pixel = 24;
1616 break;
1617 case V4L2_PIX_FMT_BGR32:
1618 var->bits_per_pixel = 32;
1619 break;
1620 default:
1621 var->grayscale = cfg->fourcc;
1622 break;
1623 } 1869 }
1624 1870
1625 /* Make sure the memory size check won't fail. smem_len is initialized 1871 ch->display.width = cfg->panel_cfg.width;
1626 * later based on var. 1872 ch->display.height = cfg->panel_cfg.height;
1627 */ 1873 ch->display.mode = *mode;
1628 info->fix.smem_len = UINT_MAX;
1629 ret = sh_mobile_check_var(var, info);
1630 if (ret)
1631 return ret;
1632
1633 max_size = max_size * var->bits_per_pixel / 8 * 2;
1634 1874
1635 /* Allocate frame buffer memory and color map. */ 1875 /* Allocate frame buffer memory. */
1636 buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL); 1876 ch->fb_size = max_size * format->bpp / 8 * 2;
1637 if (!buf) { 1877 ch->fb_mem = dma_alloc_coherent(priv->dev, ch->fb_size, &ch->dma_handle,
1638 dev_err(dev, "unable to allocate buffer\n"); 1878 GFP_KERNEL);
1879 if (ch->fb_mem == NULL) {
1880 dev_err(priv->dev, "unable to allocate buffer\n");
1639 return -ENOMEM; 1881 return -ENOMEM;
1640 } 1882 }
1641 1883
1642 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1884 /* Initialize the transmitter device if present. */
1643 if (ret < 0) { 1885 if (cfg->tx_dev) {
1644 dev_err(dev, "unable to allocate cmap\n"); 1886 if (!cfg->tx_dev->dev.driver ||
1645 dma_free_coherent(dev, max_size, buf, ch->dma_handle); 1887 !try_module_get(cfg->tx_dev->dev.driver->owner)) {
1646 return ret; 1888 dev_warn(priv->dev,
1647 } 1889 "unable to get transmitter device\n");
1648 1890 return -EINVAL;
1649 /* Initialize fixed screen information. Restrict pan to 2 lines steps 1891 }
1650 * for NV12 and NV21. 1892 ch->tx_dev = platform_get_drvdata(cfg->tx_dev);
1651 */ 1893 ch->tx_dev->lcdc = ch;
1652 info->fix = sh_mobile_lcdc_fix; 1894 ch->tx_dev->def_mode = *mode;
1653 info->fix.smem_start = ch->dma_handle;
1654 info->fix.smem_len = max_size;
1655 if (cfg->fourcc == V4L2_PIX_FMT_NV12 ||
1656 cfg->fourcc == V4L2_PIX_FMT_NV21)
1657 info->fix.ypanstep = 2;
1658
1659 if (sh_mobile_format_is_yuv(var)) {
1660 info->fix.line_length = var->xres;
1661 info->fix.visual = FB_VISUAL_FOURCC;
1662 } else {
1663 info->fix.line_length = var->xres * var->bits_per_pixel / 8;
1664 info->fix.visual = FB_VISUAL_TRUECOLOR;
1665 } 1895 }
1666 1896
1667 info->screen_base = buf; 1897 return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes);
1668 info->device = dev;
1669 ch->display_var = *var;
1670
1671 return 0;
1672} 1898}
1673 1899
1674static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 1900static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
@@ -1698,6 +1924,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1698 return -ENOMEM; 1924 return -ENOMEM;
1699 } 1925 }
1700 1926
1927 priv->dev = &pdev->dev;
1928 priv->meram_dev = pdata->meram_dev;
1701 platform_set_drvdata(pdev, priv); 1929 platform_set_drvdata(pdev, priv);
1702 1930
1703 error = request_irq(i, sh_mobile_lcdc_irq, 0, 1931 error = request_irq(i, sh_mobile_lcdc_irq, 0,
@@ -1714,7 +1942,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1714 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; 1942 struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels;
1715 1943
1716 ch->lcdc = priv; 1944 ch->lcdc = priv;
1717 memcpy(&ch->cfg, &pdata->ch[i], sizeof(pdata->ch[i])); 1945 ch->cfg = &pdata->ch[i];
1718 1946
1719 error = sh_mobile_lcdc_check_interface(ch); 1947 error = sh_mobile_lcdc_check_interface(ch);
1720 if (error) { 1948 if (error) {
@@ -1726,7 +1954,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1726 ch->pan_offset = 0; 1954 ch->pan_offset = 0;
1727 1955
1728 /* probe the backlight is there is one defined */ 1956 /* probe the backlight is there is one defined */
1729 if (ch->cfg.bl_info.max_brightness) 1957 if (ch->cfg->bl_info.max_brightness)
1730 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch); 1958 ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
1731 1959
1732 switch (pdata->ch[i].chan) { 1960 switch (pdata->ch[i].chan) {
@@ -1757,18 +1985,19 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1757 if (!priv->base) 1985 if (!priv->base)
1758 goto err1; 1986 goto err1;
1759 1987
1760 error = sh_mobile_lcdc_setup_clocks(pdev, pdata->clock_source, priv); 1988 error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source);
1761 if (error) { 1989 if (error) {
1762 dev_err(&pdev->dev, "unable to setup clocks\n"); 1990 dev_err(&pdev->dev, "unable to setup clocks\n");
1763 goto err1; 1991 goto err1;
1764 } 1992 }
1765 1993
1766 priv->meram_dev = pdata->meram_dev; 1994 /* Enable runtime PM. */
1995 pm_runtime_enable(&pdev->dev);
1767 1996
1768 for (i = 0; i < num_channels; i++) { 1997 for (i = 0; i < num_channels; i++) {
1769 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 1998 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1770 1999
1771 error = sh_mobile_lcdc_channel_init(ch, &pdev->dev); 2000 error = sh_mobile_lcdc_channel_init(priv, ch);
1772 if (error) 2001 if (error)
1773 goto err1; 2002 goto err1;
1774 } 2003 }
@@ -1781,31 +2010,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1781 2010
1782 for (i = 0; i < num_channels; i++) { 2011 for (i = 0; i < num_channels; i++) {
1783 struct sh_mobile_lcdc_chan *ch = priv->ch + i; 2012 struct sh_mobile_lcdc_chan *ch = priv->ch + i;
1784 struct fb_info *info = ch->info;
1785
1786 if (info->fbdefio) {
1787 ch->sglist = vmalloc(sizeof(struct scatterlist) *
1788 info->fix.smem_len >> PAGE_SHIFT);
1789 if (!ch->sglist) {
1790 dev_err(&pdev->dev, "cannot allocate sglist\n");
1791 goto err1;
1792 }
1793 }
1794
1795 info->bl_dev = ch->bl;
1796 2013
1797 error = register_framebuffer(info); 2014 error = sh_mobile_lcdc_channel_fb_register(ch);
1798 if (error < 0) 2015 if (error)
1799 goto err1; 2016 goto err1;
1800
1801 dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
1802 pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1803 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
1804 info->var.bits_per_pixel);
1805
1806 /* deferred io mode: disable clock to save power */
1807 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
1808 sh_mobile_lcdc_clk_off(priv);
1809 } 2017 }
1810 2018
1811 /* Failure ignored */ 2019 /* Failure ignored */
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index a58a0f38848b..da1c26e78a57 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -14,9 +14,35 @@ enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
14 14
15#define PALETTE_NR 16 15#define PALETTE_NR 16
16 16
17struct sh_mobile_lcdc_priv;
18struct fb_info;
19struct backlight_device; 17struct backlight_device;
18struct fb_info;
19struct module;
20struct sh_mobile_lcdc_chan;
21struct sh_mobile_lcdc_entity;
22struct sh_mobile_lcdc_format_info;
23struct sh_mobile_lcdc_priv;
24
25#define SH_MOBILE_LCDC_DISPLAY_DISCONNECTED 0
26#define SH_MOBILE_LCDC_DISPLAY_CONNECTED 1
27
28struct sh_mobile_lcdc_entity_ops {
29 /* Display */
30 int (*display_on)(struct sh_mobile_lcdc_entity *entity);
31 void (*display_off)(struct sh_mobile_lcdc_entity *entity);
32};
33
34enum sh_mobile_lcdc_entity_event {
35 SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT,
36 SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT,
37 SH_MOBILE_LCDC_EVENT_DISPLAY_MODE,
38};
39
40struct sh_mobile_lcdc_entity {
41 struct module *owner;
42 const struct sh_mobile_lcdc_entity_ops *ops;
43 struct sh_mobile_lcdc_chan *lcdc;
44 struct fb_videomode def_mode;
45};
20 46
21/* 47/*
22 * struct sh_mobile_lcdc_chan - LCDC display channel 48 * struct sh_mobile_lcdc_chan - LCDC display channel
@@ -27,29 +53,57 @@ struct backlight_device;
27 */ 53 */
28struct sh_mobile_lcdc_chan { 54struct sh_mobile_lcdc_chan {
29 struct sh_mobile_lcdc_priv *lcdc; 55 struct sh_mobile_lcdc_priv *lcdc;
56 struct sh_mobile_lcdc_entity *tx_dev;
57 const struct sh_mobile_lcdc_chan_cfg *cfg;
58
30 unsigned long *reg_offs; 59 unsigned long *reg_offs;
31 unsigned long ldmt1r_value; 60 unsigned long ldmt1r_value;
32 unsigned long enabled; /* ME and SE in LDCNT2R */ 61 unsigned long enabled; /* ME and SE in LDCNT2R */
33 struct sh_mobile_lcdc_chan_cfg cfg; 62 void *meram;
34 u32 pseudo_palette[PALETTE_NR]; 63
35 struct fb_info *info; 64 struct mutex open_lock; /* protects the use counter */
36 struct backlight_device *bl; 65 int use_count;
66
67 void *fb_mem;
68 unsigned long fb_size;
69
37 dma_addr_t dma_handle; 70 dma_addr_t dma_handle;
38 struct fb_deferred_io defio;
39 struct scatterlist *sglist;
40 unsigned long frame_end;
41 unsigned long pan_offset; 71 unsigned long pan_offset;
72
73 unsigned long frame_end;
42 wait_queue_head_t frame_end_wait; 74 wait_queue_head_t frame_end_wait;
43 struct completion vsync_completion; 75 struct completion vsync_completion;
44 struct fb_var_screeninfo display_var; 76
45 int use_count; 77 const struct sh_mobile_lcdc_format_info *format;
46 int blank_status; 78 u32 colorspace;
47 struct mutex open_lock; /* protects the use counter */ 79 unsigned int xres;
48 int meram_enabled; 80 unsigned int xres_virtual;
81 unsigned int yres;
82 unsigned int yres_virtual;
83 unsigned int pitch;
49 84
50 unsigned long base_addr_y; 85 unsigned long base_addr_y;
51 unsigned long base_addr_c; 86 unsigned long base_addr_c;
52 unsigned int pitch; 87
88 int (*notify)(struct sh_mobile_lcdc_chan *ch,
89 enum sh_mobile_lcdc_entity_event event,
90 const struct fb_videomode *mode,
91 const struct fb_monspecs *monspec);
92
93 /* Backlight */
94 struct backlight_device *bl;
95
96 /* FB */
97 struct fb_info *info;
98 u32 pseudo_palette[PALETTE_NR];
99 struct {
100 unsigned int width;
101 unsigned int height;
102 struct fb_videomode mode;
103 } display;
104 struct fb_deferred_io defio;
105 struct scatterlist *sglist;
106 int blank_status;
53}; 107};
54 108
55#endif 109#endif
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index f45d83ecfd21..82ba830bf95d 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -9,16 +9,22 @@
9 * for more details. 9 * for more details.
10 */ 10 */
11 11
12#include <linux/device.h>
13#include <linux/err.h>
14#include <linux/genalloc.h>
15#include <linux/io.h>
12#include <linux/kernel.h> 16#include <linux/kernel.h>
13#include <linux/module.h> 17#include <linux/module.h>
14#include <linux/device.h> 18#include <linux/platform_device.h>
15#include <linux/pm_runtime.h> 19#include <linux/pm_runtime.h>
16#include <linux/io.h>
17#include <linux/slab.h> 20#include <linux/slab.h>
18#include <linux/platform_device.h> 21
19#include <video/sh_mobile_meram.h> 22#include <video/sh_mobile_meram.h>
20 23
21/* meram registers */ 24/* -----------------------------------------------------------------------------
25 * MERAM registers
26 */
27
22#define MEVCR1 0x4 28#define MEVCR1 0x4
23#define MEVCR1_RST (1 << 31) 29#define MEVCR1_RST (1 << 31)
24#define MEVCR1_WD (1 << 30) 30#define MEVCR1_WD (1 << 30)
@@ -81,16 +87,14 @@
81 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \ 87 ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
82 ((xszm1) << MExxBSIZE_XSZM1_SHIFT)) 88 ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
83 89
84#define SH_MOBILE_MERAM_ICB_NUM 32 90static const unsigned long common_regs[] = {
85
86static unsigned long common_regs[] = {
87 MEVCR1, 91 MEVCR1,
88 MEQSEL1, 92 MEQSEL1,
89 MEQSEL2, 93 MEQSEL2,
90}; 94};
91#define CMN_REGS_SIZE ARRAY_SIZE(common_regs) 95#define MERAM_REGS_SIZE ARRAY_SIZE(common_regs)
92 96
93static unsigned long icb_regs[] = { 97static const unsigned long icb_regs[] = {
94 MExxCTL, 98 MExxCTL,
95 MExxBSIZE, 99 MExxBSIZE,
96 MExxMNCF, 100 MExxMNCF,
@@ -100,216 +104,269 @@ static unsigned long icb_regs[] = {
100}; 104};
101#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs) 105#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
102 106
107/*
108 * sh_mobile_meram_icb - MERAM ICB information
109 * @regs: Registers cache
110 * @index: ICB index
111 * @offset: MERAM block offset
112 * @size: MERAM block size in KiB
113 * @cache_unit: Bytes to cache per ICB
114 * @pixelformat: Video pixel format of the data stored in the ICB
115 * @current_reg: Which of Start Address Register A (0) or B (1) is in use
116 */
117struct sh_mobile_meram_icb {
118 unsigned long regs[ICB_REGS_SIZE];
119 unsigned int index;
120 unsigned long offset;
121 unsigned int size;
122
123 unsigned int cache_unit;
124 unsigned int pixelformat;
125 unsigned int current_reg;
126};
127
128#define MERAM_ICB_NUM 32
129
130struct sh_mobile_meram_fb_plane {
131 struct sh_mobile_meram_icb *marker;
132 struct sh_mobile_meram_icb *cache;
133};
134
135struct sh_mobile_meram_fb_cache {
136 unsigned int nplanes;
137 struct sh_mobile_meram_fb_plane planes[2];
138};
139
140/*
141 * sh_mobile_meram_priv - MERAM device
142 * @base: Registers base address
143 * @meram: MERAM physical address
144 * @regs: Registers cache
145 * @lock: Protects used_icb and icbs
146 * @used_icb: Bitmask of used ICBs
147 * @icbs: ICBs
148 * @pool: Allocation pool to manage the MERAM
149 */
103struct sh_mobile_meram_priv { 150struct sh_mobile_meram_priv {
104 void __iomem *base; 151 void __iomem *base;
105 struct mutex lock; 152 unsigned long meram;
106 unsigned long used_icb; 153 unsigned long regs[MERAM_REGS_SIZE];
107 int used_meram_cache_regions; 154
108 unsigned long used_meram_cache[SH_MOBILE_MERAM_ICB_NUM]; 155 struct mutex lock;
109 unsigned long cmn_saved_regs[CMN_REGS_SIZE]; 156 unsigned long used_icb;
110 unsigned long icb_saved_regs[ICB_REGS_SIZE * SH_MOBILE_MERAM_ICB_NUM]; 157 struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM];
158
159 struct gen_pool *pool;
111}; 160};
112 161
113/* settings */ 162/* settings */
114#define MERAM_SEC_LINE 15 163#define MERAM_GRANULARITY 1024
115#define MERAM_LINE_WIDTH 2048 164#define MERAM_SEC_LINE 15
165#define MERAM_LINE_WIDTH 2048
116 166
117/* 167/* -----------------------------------------------------------------------------
118 * MERAM/ICB access functions 168 * Registers access
119 */ 169 */
120 170
121#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20) 171#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
122 172
123static inline void meram_write_icb(void __iomem *base, int idx, int off, 173static inline void meram_write_icb(void __iomem *base, unsigned int idx,
124 unsigned long val) 174 unsigned int off, unsigned long val)
125{ 175{
126 iowrite32(val, MERAM_ICB_OFFSET(base, idx, off)); 176 iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
127} 177}
128 178
129static inline unsigned long meram_read_icb(void __iomem *base, int idx, int off) 179static inline unsigned long meram_read_icb(void __iomem *base, unsigned int idx,
180 unsigned int off)
130{ 181{
131 return ioread32(MERAM_ICB_OFFSET(base, idx, off)); 182 return ioread32(MERAM_ICB_OFFSET(base, idx, off));
132} 183}
133 184
134static inline void meram_write_reg(void __iomem *base, int off, 185static inline void meram_write_reg(void __iomem *base, unsigned int off,
135 unsigned long val) 186 unsigned long val)
136{ 187{
137 iowrite32(val, base + off); 188 iowrite32(val, base + off);
138} 189}
139 190
140static inline unsigned long meram_read_reg(void __iomem *base, int off) 191static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
141{ 192{
142 return ioread32(base + off); 193 return ioread32(base + off);
143} 194}
144 195
145/* 196/* -----------------------------------------------------------------------------
146 * register ICB 197 * Allocation
147 */
148
149#define MERAM_CACHE_START(p) ((p) >> 16)
150#define MERAM_CACHE_END(p) ((p) & 0xffff)
151#define MERAM_CACHE_SET(o, s) ((((o) & 0xffff) << 16) | \
152 (((o) + (s) - 1) & 0xffff))
153
154/*
155 * check if there's no overlaps in MERAM allocation.
156 */ 198 */
157 199
158static inline int meram_check_overlap(struct sh_mobile_meram_priv *priv, 200/* Allocate ICBs and MERAM for a plane. */
159 struct sh_mobile_meram_icb *new) 201static int __meram_alloc(struct sh_mobile_meram_priv *priv,
202 struct sh_mobile_meram_fb_plane *plane,
203 size_t size)
160{ 204{
161 int i; 205 unsigned long mem;
162 int used_start, used_end, meram_start, meram_end; 206 unsigned long idx;
163 207
164 /* valid ICB? */ 208 idx = find_first_zero_bit(&priv->used_icb, 28);
165 if (new->marker_icb & ~0x1f || new->cache_icb & ~0x1f) 209 if (idx == 28)
166 return 1; 210 return -ENOMEM;
211 plane->cache = &priv->icbs[idx];
167 212
168 if (test_bit(new->marker_icb, &priv->used_icb) || 213 idx = find_next_zero_bit(&priv->used_icb, 32, 28);
169 test_bit(new->cache_icb, &priv->used_icb)) 214 if (idx == 32)
170 return 1; 215 return -ENOMEM;
216 plane->marker = &priv->icbs[idx];
171 217
172 for (i = 0; i < priv->used_meram_cache_regions; i++) { 218 mem = gen_pool_alloc(priv->pool, size * 1024);
173 used_start = MERAM_CACHE_START(priv->used_meram_cache[i]); 219 if (mem == 0)
174 used_end = MERAM_CACHE_END(priv->used_meram_cache[i]); 220 return -ENOMEM;
175 meram_start = new->meram_offset;
176 meram_end = new->meram_offset + new->meram_size;
177 221
178 if ((meram_start >= used_start && meram_start < used_end) || 222 __set_bit(plane->marker->index, &priv->used_icb);
179 (meram_end > used_start && meram_end < used_end)) 223 __set_bit(plane->cache->index, &priv->used_icb);
180 return 1; 224
181 } 225 plane->marker->offset = mem - priv->meram;
226 plane->marker->size = size;
182 227
183 return 0; 228 return 0;
184} 229}
185 230
186/* 231/* Free ICBs and MERAM for a plane. */
187 * mark the specified ICB as used 232static void __meram_free(struct sh_mobile_meram_priv *priv,
188 */ 233 struct sh_mobile_meram_fb_plane *plane)
234{
235 gen_pool_free(priv->pool, priv->meram + plane->marker->offset,
236 plane->marker->size * 1024);
189 237
190static inline void meram_mark(struct sh_mobile_meram_priv *priv, 238 __clear_bit(plane->marker->index, &priv->used_icb);
191 struct sh_mobile_meram_icb *new) 239 __clear_bit(plane->cache->index, &priv->used_icb);
240}
241
242/* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */
243static int is_nvcolor(int cspace)
192{ 244{
193 int n; 245 if (cspace == SH_MOBILE_MERAM_PF_NV ||
246 cspace == SH_MOBILE_MERAM_PF_NV24)
247 return 1;
248 return 0;
249}
194 250
195 if (new->marker_icb < 0 || new->cache_icb < 0) 251/* Allocate memory for the ICBs and mark them as used. */
196 return; 252static struct sh_mobile_meram_fb_cache *
253meram_alloc(struct sh_mobile_meram_priv *priv,
254 const struct sh_mobile_meram_cfg *cfg,
255 int pixelformat)
256{
257 struct sh_mobile_meram_fb_cache *cache;
258 unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
259 int ret;
197 260
198 __set_bit(new->marker_icb, &priv->used_icb); 261 if (cfg->icb[0].meram_size == 0)
199 __set_bit(new->cache_icb, &priv->used_icb); 262 return ERR_PTR(-EINVAL);
200 263
201 n = priv->used_meram_cache_regions; 264 if (nplanes == 2 && cfg->icb[1].meram_size == 0)
265 return ERR_PTR(-EINVAL);
202 266
203 priv->used_meram_cache[n] = MERAM_CACHE_SET(new->meram_offset, 267 cache = kzalloc(sizeof(*cache), GFP_KERNEL);
204 new->meram_size); 268 if (cache == NULL)
269 return ERR_PTR(-ENOMEM);
205 270
206 priv->used_meram_cache_regions++; 271 cache->nplanes = nplanes;
207}
208 272
209/* 273 ret = __meram_alloc(priv, &cache->planes[0], cfg->icb[0].meram_size);
210 * unmark the specified ICB as used 274 if (ret < 0)
211 */ 275 goto error;
212 276
213static inline void meram_unmark(struct sh_mobile_meram_priv *priv, 277 cache->planes[0].marker->current_reg = 1;
214 struct sh_mobile_meram_icb *icb) 278 cache->planes[0].marker->pixelformat = pixelformat;
215{ 279
216 int i; 280 if (cache->nplanes == 1)
217 unsigned long pattern; 281 return cache;
218 282
219 if (icb->marker_icb < 0 || icb->cache_icb < 0) 283 ret = __meram_alloc(priv, &cache->planes[1], cfg->icb[1].meram_size);
220 return; 284 if (ret < 0) {
221 285 __meram_free(priv, &cache->planes[0]);
222 __clear_bit(icb->marker_icb, &priv->used_icb); 286 goto error;
223 __clear_bit(icb->cache_icb, &priv->used_icb);
224
225 pattern = MERAM_CACHE_SET(icb->meram_offset, icb->meram_size);
226 for (i = 0; i < priv->used_meram_cache_regions; i++) {
227 if (priv->used_meram_cache[i] == pattern) {
228 while (i < priv->used_meram_cache_regions - 1) {
229 priv->used_meram_cache[i] =
230 priv->used_meram_cache[i + 1] ;
231 i++;
232 }
233 priv->used_meram_cache[i] = 0;
234 priv->used_meram_cache_regions--;
235 break;
236 }
237 } 287 }
288
289 return cache;
290
291error:
292 kfree(cache);
293 return ERR_PTR(-ENOMEM);
238} 294}
239 295
240/* 296/* Unmark the specified ICB as used. */
241 * is this a YCbCr(NV12, NV16 or NV24) colorspace 297static void meram_free(struct sh_mobile_meram_priv *priv,
242 */ 298 struct sh_mobile_meram_fb_cache *cache)
243static inline int is_nvcolor(int cspace)
244{ 299{
245 if (cspace == SH_MOBILE_MERAM_PF_NV || 300 __meram_free(priv, &cache->planes[0]);
246 cspace == SH_MOBILE_MERAM_PF_NV24) 301 if (cache->nplanes == 2)
247 return 1; 302 __meram_free(priv, &cache->planes[1]);
248 return 0; 303
304 kfree(cache);
249} 305}
250 306
251/* 307/* Set the next address to fetch. */
252 * set the next address to fetch 308static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
253 */ 309 struct sh_mobile_meram_fb_cache *cache,
254static inline void meram_set_next_addr(struct sh_mobile_meram_priv *priv, 310 unsigned long base_addr_y,
255 struct sh_mobile_meram_cfg *cfg, 311 unsigned long base_addr_c)
256 unsigned long base_addr_y,
257 unsigned long base_addr_c)
258{ 312{
313 struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
259 unsigned long target; 314 unsigned long target;
260 315
261 target = (cfg->current_reg) ? MExxSARA : MExxSARB; 316 icb->current_reg ^= 1;
262 cfg->current_reg ^= 1; 317 target = icb->current_reg ? MExxSARB : MExxSARA;
263 318
264 /* set the next address to fetch */ 319 /* set the next address to fetch */
265 meram_write_icb(priv->base, cfg->icb[0].cache_icb, target, 320 meram_write_icb(priv->base, cache->planes[0].cache->index, target,
266 base_addr_y); 321 base_addr_y);
267 meram_write_icb(priv->base, cfg->icb[0].marker_icb, target, 322 meram_write_icb(priv->base, cache->planes[0].marker->index, target,
268 base_addr_y + cfg->icb[0].cache_unit); 323 base_addr_y + cache->planes[0].marker->cache_unit);
269 324
270 if (is_nvcolor(cfg->pixelformat)) { 325 if (cache->nplanes == 2) {
271 meram_write_icb(priv->base, cfg->icb[1].cache_icb, target, 326 meram_write_icb(priv->base, cache->planes[1].cache->index,
272 base_addr_c); 327 target, base_addr_c);
273 meram_write_icb(priv->base, cfg->icb[1].marker_icb, target, 328 meram_write_icb(priv->base, cache->planes[1].marker->index,
274 base_addr_c + cfg->icb[1].cache_unit); 329 target, base_addr_c +
330 cache->planes[1].marker->cache_unit);
275 } 331 }
276} 332}
277 333
278/* 334/* Get the next ICB address. */
279 * get the next ICB address 335static void
280 */ 336meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
281static inline void meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata, 337 struct sh_mobile_meram_fb_cache *cache,
282 struct sh_mobile_meram_cfg *cfg, 338 unsigned long *icb_addr_y, unsigned long *icb_addr_c)
283 unsigned long *icb_addr_y,
284 unsigned long *icb_addr_c)
285{ 339{
340 struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
286 unsigned long icb_offset; 341 unsigned long icb_offset;
287 342
288 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0) 343 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
289 icb_offset = 0x80000000 | (cfg->current_reg << 29); 344 icb_offset = 0x80000000 | (icb->current_reg << 29);
290 else 345 else
291 icb_offset = 0xc0000000 | (cfg->current_reg << 23); 346 icb_offset = 0xc0000000 | (icb->current_reg << 23);
292 347
293 *icb_addr_y = icb_offset | (cfg->icb[0].marker_icb << 24); 348 *icb_addr_y = icb_offset | (cache->planes[0].marker->index << 24);
294 if (is_nvcolor(cfg->pixelformat)) 349 if (cache->nplanes == 2)
295 *icb_addr_c = icb_offset | (cfg->icb[1].marker_icb << 24); 350 *icb_addr_c = icb_offset
351 | (cache->planes[1].marker->index << 24);
296} 352}
297 353
298#define MERAM_CALC_BYTECOUNT(x, y) \ 354#define MERAM_CALC_BYTECOUNT(x, y) \
299 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1)) 355 (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
300 356
301/* 357/* Initialize MERAM. */
302 * initialize MERAM
303 */
304
305static int meram_init(struct sh_mobile_meram_priv *priv, 358static int meram_init(struct sh_mobile_meram_priv *priv,
306 struct sh_mobile_meram_icb *icb, 359 struct sh_mobile_meram_fb_plane *plane,
307 int xres, int yres, int *out_pitch) 360 unsigned int xres, unsigned int yres,
361 unsigned int *out_pitch)
308{ 362{
363 struct sh_mobile_meram_icb *marker = plane->marker;
309 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres); 364 unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
310 unsigned long bnm; 365 unsigned long bnm;
311 int lcdc_pitch, xpitch, line_cnt; 366 unsigned int lcdc_pitch;
312 int save_lines; 367 unsigned int xpitch;
368 unsigned int line_cnt;
369 unsigned int save_lines;
313 370
314 /* adjust pitch to 1024, 2048, 4096 or 8192 */ 371 /* adjust pitch to 1024, 2048, 4096 or 8192 */
315 lcdc_pitch = (xres - 1) | 1023; 372 lcdc_pitch = (xres - 1) | 1023;
@@ -322,13 +379,13 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
322 lcdc_pitch = xpitch = MERAM_LINE_WIDTH; 379 lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
323 line_cnt = total_byte_count >> 11; 380 line_cnt = total_byte_count >> 11;
324 *out_pitch = xres; 381 *out_pitch = xres;
325 save_lines = (icb->meram_size / 16 / MERAM_SEC_LINE); 382 save_lines = plane->marker->size / 16 / MERAM_SEC_LINE;
326 save_lines *= MERAM_SEC_LINE; 383 save_lines *= MERAM_SEC_LINE;
327 } else { 384 } else {
328 xpitch = xres; 385 xpitch = xres;
329 line_cnt = yres; 386 line_cnt = yres;
330 *out_pitch = lcdc_pitch; 387 *out_pitch = lcdc_pitch;
331 save_lines = icb->meram_size / (lcdc_pitch >> 10) / 2; 388 save_lines = plane->marker->size / (lcdc_pitch >> 10) / 2;
332 save_lines &= 0xff; 389 save_lines &= 0xff;
333 } 390 }
334 bnm = (save_lines - 1) << 16; 391 bnm = (save_lines - 1) << 16;
@@ -336,19 +393,20 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
336 /* TODO: we better to check if we have enough MERAM buffer size */ 393 /* TODO: we better to check if we have enough MERAM buffer size */
337 394
338 /* set up ICB */ 395 /* set up ICB */
339 meram_write_icb(priv->base, icb->cache_icb, MExxBSIZE, 396 meram_write_icb(priv->base, plane->cache->index, MExxBSIZE,
340 MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1)); 397 MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
341 meram_write_icb(priv->base, icb->marker_icb, MExxBSIZE, 398 meram_write_icb(priv->base, plane->marker->index, MExxBSIZE,
342 MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1)); 399 MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
343 400
344 meram_write_icb(priv->base, icb->cache_icb, MExxMNCF, bnm); 401 meram_write_icb(priv->base, plane->cache->index, MExxMNCF, bnm);
345 meram_write_icb(priv->base, icb->marker_icb, MExxMNCF, bnm); 402 meram_write_icb(priv->base, plane->marker->index, MExxMNCF, bnm);
346 403
347 meram_write_icb(priv->base, icb->cache_icb, MExxSBSIZE, xpitch); 404 meram_write_icb(priv->base, plane->cache->index, MExxSBSIZE, xpitch);
348 meram_write_icb(priv->base, icb->marker_icb, MExxSBSIZE, xpitch); 405 meram_write_icb(priv->base, plane->marker->index, MExxSBSIZE, xpitch);
349 406
350 /* save a cache unit size */ 407 /* save a cache unit size */
351 icb->cache_unit = xres * save_lines; 408 plane->cache->cache_unit = xres * save_lines;
409 plane->marker->cache_unit = xres * save_lines;
352 410
353 /* 411 /*
354 * Set MERAM for framebuffer 412 * Set MERAM for framebuffer
@@ -356,13 +414,13 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
356 * we also chain the cache_icb and the marker_icb. 414 * we also chain the cache_icb and the marker_icb.
357 * we also split the allocated MERAM buffer between two ICBs. 415 * we also split the allocated MERAM buffer between two ICBs.
358 */ 416 */
359 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 417 meram_write_icb(priv->base, plane->cache->index, MExxCTL,
360 MERAM_MExxCTL_VAL(icb->marker_icb, icb->meram_offset) | 418 MERAM_MExxCTL_VAL(plane->marker->index, marker->offset)
361 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | 419 | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
362 MExxCTL_MD_FB); 420 MExxCTL_MD_FB);
363 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 421 meram_write_icb(priv->base, plane->marker->index, MExxCTL,
364 MERAM_MExxCTL_VAL(icb->cache_icb, icb->meram_offset + 422 MERAM_MExxCTL_VAL(plane->cache->index, marker->offset +
365 icb->meram_size / 2) | 423 plane->marker->size / 2) |
366 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM | 424 MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
367 MExxCTL_MD_FB); 425 MExxCTL_MD_FB);
368 426
@@ -370,239 +428,175 @@ static int meram_init(struct sh_mobile_meram_priv *priv,
370} 428}
371 429
372static void meram_deinit(struct sh_mobile_meram_priv *priv, 430static void meram_deinit(struct sh_mobile_meram_priv *priv,
373 struct sh_mobile_meram_icb *icb) 431 struct sh_mobile_meram_fb_plane *plane)
374{ 432{
375 /* disable ICB */ 433 /* disable ICB */
376 meram_write_icb(priv->base, icb->cache_icb, MExxCTL, 434 meram_write_icb(priv->base, plane->cache->index, MExxCTL,
377 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); 435 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
378 meram_write_icb(priv->base, icb->marker_icb, MExxCTL, 436 meram_write_icb(priv->base, plane->marker->index, MExxCTL,
379 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF); 437 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
380 icb->cache_unit = 0; 438
439 plane->cache->cache_unit = 0;
440 plane->marker->cache_unit = 0;
381} 441}
382 442
383/* 443/* -----------------------------------------------------------------------------
384 * register the ICB 444 * Registration/unregistration
385 */ 445 */
386 446
387static int sh_mobile_meram_register(struct sh_mobile_meram_info *pdata, 447static void *sh_mobile_meram_register(struct sh_mobile_meram_info *pdata,
388 struct sh_mobile_meram_cfg *cfg, 448 const struct sh_mobile_meram_cfg *cfg,
389 int xres, int yres, int pixelformat, 449 unsigned int xres, unsigned int yres,
390 unsigned long base_addr_y, 450 unsigned int pixelformat,
391 unsigned long base_addr_c, 451 unsigned int *pitch)
392 unsigned long *icb_addr_y,
393 unsigned long *icb_addr_c,
394 int *pitch)
395{ 452{
396 struct platform_device *pdev; 453 struct sh_mobile_meram_fb_cache *cache;
397 struct sh_mobile_meram_priv *priv; 454 struct sh_mobile_meram_priv *priv = pdata->priv;
398 int n, out_pitch; 455 struct platform_device *pdev = pdata->pdev;
399 int error = 0; 456 unsigned int out_pitch;
400
401 if (!pdata || !pdata->priv || !pdata->pdev || !cfg)
402 return -EINVAL;
403 457
404 if (pixelformat != SH_MOBILE_MERAM_PF_NV && 458 if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
405 pixelformat != SH_MOBILE_MERAM_PF_NV24 && 459 pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
406 pixelformat != SH_MOBILE_MERAM_PF_RGB) 460 pixelformat != SH_MOBILE_MERAM_PF_RGB)
407 return -EINVAL; 461 return ERR_PTR(-EINVAL);
408
409 priv = pdata->priv;
410 pdev = pdata->pdev;
411 462
412 dev_dbg(&pdev->dev, "registering %dx%d (%s) (y=%08lx, c=%08lx)", 463 dev_dbg(&pdev->dev, "registering %dx%d (%s)", xres, yres,
413 xres, yres, (!pixelformat) ? "yuv" : "rgb", 464 !pixelformat ? "yuv" : "rgb");
414 base_addr_y, base_addr_c);
415 465
416 /* we can't handle wider than 8192px */ 466 /* we can't handle wider than 8192px */
417 if (xres > 8192) { 467 if (xres > 8192) {
418 dev_err(&pdev->dev, "width exceeding the limit (> 8192)."); 468 dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
419 return -EINVAL; 469 return ERR_PTR(-EINVAL);
420 }
421
422 /* do we have at least one ICB config? */
423 if (cfg->icb[0].marker_icb < 0 || cfg->icb[0].cache_icb < 0) {
424 dev_err(&pdev->dev, "at least one ICB is required.");
425 return -EINVAL;
426 } 470 }
427 471
428 mutex_lock(&priv->lock); 472 mutex_lock(&priv->lock);
429 473
430 if (priv->used_meram_cache_regions + 2 > SH_MOBILE_MERAM_ICB_NUM) { 474 /* We now register the ICBs and allocate the MERAM regions. */
431 dev_err(&pdev->dev, "no more ICB available."); 475 cache = meram_alloc(priv, cfg, pixelformat);
432 error = -EINVAL; 476 if (IS_ERR(cache)) {
433 goto err; 477 dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
434 } 478 PTR_ERR(cache));
435
436 /* make sure that there's no overlaps */
437 if (meram_check_overlap(priv, &cfg->icb[0])) {
438 dev_err(&pdev->dev, "conflicting config detected.");
439 error = -EINVAL;
440 goto err; 479 goto err;
441 } 480 }
442 n = 1;
443
444 /* do the same if we have the second ICB set */
445 if (cfg->icb[1].marker_icb >= 0 && cfg->icb[1].cache_icb >= 0) {
446 if (meram_check_overlap(priv, &cfg->icb[1])) {
447 dev_err(&pdev->dev, "conflicting config detected.");
448 error = -EINVAL;
449 goto err;
450 }
451 n = 2;
452 }
453
454 if (is_nvcolor(pixelformat) && n != 2) {
455 dev_err(&pdev->dev, "requires two ICB sets for planar Y/C.");
456 error = -EINVAL;
457 goto err;
458 }
459
460 /* we now register the ICB */
461 cfg->pixelformat = pixelformat;
462 meram_mark(priv, &cfg->icb[0]);
463 if (is_nvcolor(pixelformat))
464 meram_mark(priv, &cfg->icb[1]);
465 481
466 /* initialize MERAM */ 482 /* initialize MERAM */
467 meram_init(priv, &cfg->icb[0], xres, yres, &out_pitch); 483 meram_init(priv, &cache->planes[0], xres, yres, &out_pitch);
468 *pitch = out_pitch; 484 *pitch = out_pitch;
469 if (pixelformat == SH_MOBILE_MERAM_PF_NV) 485 if (pixelformat == SH_MOBILE_MERAM_PF_NV)
470 meram_init(priv, &cfg->icb[1], xres, (yres + 1) / 2, 486 meram_init(priv, &cache->planes[1], xres, (yres + 1) / 2,
471 &out_pitch); 487 &out_pitch);
472 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24) 488 else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
473 meram_init(priv, &cfg->icb[1], 2 * xres, (yres + 1) / 2, 489 meram_init(priv, &cache->planes[1], 2 * xres, (yres + 1) / 2,
474 &out_pitch); 490 &out_pitch);
475 491
476 cfg->current_reg = 1;
477 meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c);
478 meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c);
479
480 dev_dbg(&pdev->dev, "registered - can access via y=%08lx, c=%08lx",
481 *icb_addr_y, *icb_addr_c);
482
483err: 492err:
484 mutex_unlock(&priv->lock); 493 mutex_unlock(&priv->lock);
485 return error; 494 return cache;
486} 495}
487 496
488static int sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, 497static void
489 struct sh_mobile_meram_cfg *cfg) 498sh_mobile_meram_unregister(struct sh_mobile_meram_info *pdata, void *data)
490{ 499{
491 struct sh_mobile_meram_priv *priv; 500 struct sh_mobile_meram_fb_cache *cache = data;
492 501 struct sh_mobile_meram_priv *priv = pdata->priv;
493 if (!pdata || !pdata->priv || !cfg)
494 return -EINVAL;
495
496 priv = pdata->priv;
497 502
498 mutex_lock(&priv->lock); 503 mutex_lock(&priv->lock);
499 504
500 /* deinit & unmark */ 505 /* deinit & free */
501 if (is_nvcolor(cfg->pixelformat)) { 506 meram_deinit(priv, &cache->planes[0]);
502 meram_deinit(priv, &cfg->icb[1]); 507 if (cache->nplanes == 2)
503 meram_unmark(priv, &cfg->icb[1]); 508 meram_deinit(priv, &cache->planes[1]);
504 }
505 meram_deinit(priv, &cfg->icb[0]);
506 meram_unmark(priv, &cfg->icb[0]);
507 509
508 mutex_unlock(&priv->lock); 510 meram_free(priv, cache);
509 511
510 return 0; 512 mutex_unlock(&priv->lock);
511} 513}
512 514
513static int sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, 515static void
514 struct sh_mobile_meram_cfg *cfg, 516sh_mobile_meram_update(struct sh_mobile_meram_info *pdata, void *data,
515 unsigned long base_addr_y, 517 unsigned long base_addr_y, unsigned long base_addr_c,
516 unsigned long base_addr_c, 518 unsigned long *icb_addr_y, unsigned long *icb_addr_c)
517 unsigned long *icb_addr_y,
518 unsigned long *icb_addr_c)
519{ 519{
520 struct sh_mobile_meram_priv *priv; 520 struct sh_mobile_meram_fb_cache *cache = data;
521 521 struct sh_mobile_meram_priv *priv = pdata->priv;
522 if (!pdata || !pdata->priv || !cfg)
523 return -EINVAL;
524
525 priv = pdata->priv;
526 522
527 mutex_lock(&priv->lock); 523 mutex_lock(&priv->lock);
528 524
529 meram_set_next_addr(priv, cfg, base_addr_y, base_addr_c); 525 meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
530 meram_get_next_icb_addr(pdata, cfg, icb_addr_y, icb_addr_c); 526 meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
531 527
532 mutex_unlock(&priv->lock); 528 mutex_unlock(&priv->lock);
533
534 return 0;
535} 529}
536 530
537static int sh_mobile_meram_runtime_suspend(struct device *dev) 531static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
532 .module = THIS_MODULE,
533 .meram_register = sh_mobile_meram_register,
534 .meram_unregister = sh_mobile_meram_unregister,
535 .meram_update = sh_mobile_meram_update,
536};
537
538/* -----------------------------------------------------------------------------
539 * Power management
540 */
541
542static int sh_mobile_meram_suspend(struct device *dev)
538{ 543{
539 struct platform_device *pdev = to_platform_device(dev); 544 struct platform_device *pdev = to_platform_device(dev);
540 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 545 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
541 int k, j; 546 unsigned int i, j;
542 547
543 for (k = 0; k < CMN_REGS_SIZE; k++) 548 for (i = 0; i < MERAM_REGS_SIZE; i++)
544 priv->cmn_saved_regs[k] = meram_read_reg(priv->base, 549 priv->regs[i] = meram_read_reg(priv->base, common_regs[i]);
545 common_regs[k]);
546 550
547 for (j = 0; j < 32; j++) { 551 for (i = 0; i < 32; i++) {
548 if (!test_bit(j, &priv->used_icb)) 552 if (!test_bit(i, &priv->used_icb))
549 continue; 553 continue;
550 for (k = 0; k < ICB_REGS_SIZE; k++) { 554 for (j = 0; j < ICB_REGS_SIZE; j++) {
551 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] = 555 priv->icbs[i].regs[j] =
552 meram_read_icb(priv->base, j, icb_regs[k]); 556 meram_read_icb(priv->base, i, icb_regs[j]);
553 /* Reset ICB on resume */ 557 /* Reset ICB on resume */
554 if (icb_regs[k] == MExxCTL) 558 if (icb_regs[j] == MExxCTL)
555 priv->icb_saved_regs[j * ICB_REGS_SIZE + k] |= 559 priv->icbs[i].regs[j] |=
556 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF; 560 MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
557 } 561 }
558 } 562 }
559 return 0; 563 return 0;
560} 564}
561 565
562static int sh_mobile_meram_runtime_resume(struct device *dev) 566static int sh_mobile_meram_resume(struct device *dev)
563{ 567{
564 struct platform_device *pdev = to_platform_device(dev); 568 struct platform_device *pdev = to_platform_device(dev);
565 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 569 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
566 int k, j; 570 unsigned int i, j;
567 571
568 for (j = 0; j < 32; j++) { 572 for (i = 0; i < 32; i++) {
569 if (!test_bit(j, &priv->used_icb)) 573 if (!test_bit(i, &priv->used_icb))
570 continue; 574 continue;
571 for (k = 0; k < ICB_REGS_SIZE; k++) { 575 for (j = 0; j < ICB_REGS_SIZE; j++)
572 meram_write_icb(priv->base, j, icb_regs[k], 576 meram_write_icb(priv->base, i, icb_regs[j],
573 priv->icb_saved_regs[j * ICB_REGS_SIZE + k]); 577 priv->icbs[i].regs[j]);
574 }
575 } 578 }
576 579
577 for (k = 0; k < CMN_REGS_SIZE; k++) 580 for (i = 0; i < MERAM_REGS_SIZE; i++)
578 meram_write_reg(priv->base, common_regs[k], 581 meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
579 priv->cmn_saved_regs[k]);
580 return 0; 582 return 0;
581} 583}
582 584
583static const struct dev_pm_ops sh_mobile_meram_dev_pm_ops = { 585static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
584 .runtime_suspend = sh_mobile_meram_runtime_suspend, 586 sh_mobile_meram_suspend,
585 .runtime_resume = sh_mobile_meram_runtime_resume, 587 sh_mobile_meram_resume, NULL);
586};
587
588static struct sh_mobile_meram_ops sh_mobile_meram_ops = {
589 .module = THIS_MODULE,
590 .meram_register = sh_mobile_meram_register,
591 .meram_unregister = sh_mobile_meram_unregister,
592 .meram_update = sh_mobile_meram_update,
593};
594 588
595/* 589/* -----------------------------------------------------------------------------
596 * initialize MERAM 590 * Probe/remove and driver init/exit
597 */ 591 */
598 592
599static int sh_mobile_meram_remove(struct platform_device *pdev);
600
601static int __devinit sh_mobile_meram_probe(struct platform_device *pdev) 593static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
602{ 594{
603 struct sh_mobile_meram_priv *priv; 595 struct sh_mobile_meram_priv *priv;
604 struct sh_mobile_meram_info *pdata = pdev->dev.platform_data; 596 struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
605 struct resource *res; 597 struct resource *regs;
598 struct resource *meram;
599 unsigned int i;
606 int error; 600 int error;
607 601
608 if (!pdata) { 602 if (!pdata) {
@@ -610,8 +604,9 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
610 return -EINVAL; 604 return -EINVAL;
611 } 605 }
612 606
613 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 607 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
614 if (!res) { 608 meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
609 if (regs == NULL || meram == NULL) {
615 dev_err(&pdev->dev, "cannot get platform resources\n"); 610 dev_err(&pdev->dev, "cannot get platform resources\n");
616 return -ENOENT; 611 return -ENOENT;
617 } 612 }
@@ -622,32 +617,74 @@ static int __devinit sh_mobile_meram_probe(struct platform_device *pdev)
622 return -ENOMEM; 617 return -ENOMEM;
623 } 618 }
624 619
625 platform_set_drvdata(pdev, priv); 620 /* Initialize private data. */
626
627 /* initialize private data */
628 mutex_init(&priv->lock); 621 mutex_init(&priv->lock);
629 priv->base = ioremap_nocache(res->start, resource_size(res)); 622 priv->used_icb = pdata->reserved_icbs;
623
624 for (i = 0; i < MERAM_ICB_NUM; ++i)
625 priv->icbs[i].index = i;
626
627 pdata->ops = &sh_mobile_meram_ops;
628 pdata->priv = priv;
629 pdata->pdev = pdev;
630
631 /* Request memory regions and remap the registers. */
632 if (!request_mem_region(regs->start, resource_size(regs), pdev->name)) {
633 dev_err(&pdev->dev, "MERAM registers region already claimed\n");
634 error = -EBUSY;
635 goto err_req_regs;
636 }
637
638 if (!request_mem_region(meram->start, resource_size(meram),
639 pdev->name)) {
640 dev_err(&pdev->dev, "MERAM memory region already claimed\n");
641 error = -EBUSY;
642 goto err_req_meram;
643 }
644
645 priv->base = ioremap_nocache(regs->start, resource_size(regs));
630 if (!priv->base) { 646 if (!priv->base) {
631 dev_err(&pdev->dev, "ioremap failed\n"); 647 dev_err(&pdev->dev, "ioremap failed\n");
632 error = -EFAULT; 648 error = -EFAULT;
633 goto err; 649 goto err_ioremap;
634 } 650 }
635 pdata->ops = &sh_mobile_meram_ops; 651
636 pdata->priv = priv; 652 priv->meram = meram->start;
637 pdata->pdev = pdev; 653
654 /* Create and initialize the MERAM memory pool. */
655 priv->pool = gen_pool_create(ilog2(MERAM_GRANULARITY), -1);
656 if (priv->pool == NULL) {
657 error = -ENOMEM;
658 goto err_genpool;
659 }
660
661 error = gen_pool_add(priv->pool, meram->start, resource_size(meram),
662 -1);
663 if (error < 0)
664 goto err_genpool;
638 665
639 /* initialize ICB addressing mode */ 666 /* initialize ICB addressing mode */
640 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1) 667 if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
641 meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1); 668 meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
642 669
670 platform_set_drvdata(pdev, priv);
643 pm_runtime_enable(&pdev->dev); 671 pm_runtime_enable(&pdev->dev);
644 672
645 dev_info(&pdev->dev, "sh_mobile_meram initialized."); 673 dev_info(&pdev->dev, "sh_mobile_meram initialized.");
646 674
647 return 0; 675 return 0;
648 676
649err: 677err_genpool:
650 sh_mobile_meram_remove(pdev); 678 if (priv->pool)
679 gen_pool_destroy(priv->pool);
680 iounmap(priv->base);
681err_ioremap:
682 release_mem_region(meram->start, resource_size(meram));
683err_req_meram:
684 release_mem_region(regs->start, resource_size(regs));
685err_req_regs:
686 mutex_destroy(&priv->lock);
687 kfree(priv);
651 688
652 return error; 689 return error;
653} 690}
@@ -656,11 +693,16 @@ err:
656static int sh_mobile_meram_remove(struct platform_device *pdev) 693static int sh_mobile_meram_remove(struct platform_device *pdev)
657{ 694{
658 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev); 695 struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
696 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
697 struct resource *meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
659 698
660 pm_runtime_disable(&pdev->dev); 699 pm_runtime_disable(&pdev->dev);
661 700
662 if (priv->base) 701 gen_pool_destroy(priv->pool);
663 iounmap(priv->base); 702
703 iounmap(priv->base);
704 release_mem_region(meram->start, resource_size(meram));
705 release_mem_region(regs->start, resource_size(regs));
664 706
665 mutex_destroy(&priv->lock); 707 mutex_destroy(&priv->lock);
666 708
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index a19773149bd7..157df78e5bfc 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -72,6 +72,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
72static bool console = 1; /* Allow fbcon to open framebuffer */ 72static bool console = 1; /* Allow fbcon to open framebuffer */
73static bool fb_defio = 1; /* Detect mmap writes using page faults */ 73static bool fb_defio = 1; /* Detect mmap writes using page faults */
74static bool shadow = 1; /* Optionally disable shadow framebuffer */ 74static bool shadow = 1; /* Optionally disable shadow framebuffer */
75static int pixel_limit; /* Optionally force a pixel resolution limit */
75 76
76/* dlfb keeps a list of urbs for efficient bulk transfers */ 77/* dlfb keeps a list of urbs for efficient bulk transfers */
77static void dlfb_urb_completion(struct urb *urb); 78static void dlfb_urb_completion(struct urb *urb);
@@ -918,10 +919,6 @@ static void dlfb_free(struct kref *kref)
918{ 919{
919 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref); 920 struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
920 921
921 /* this function will wait for all in-flight urbs to complete */
922 if (dev->urbs.count > 0)
923 dlfb_free_urb_list(dev);
924
925 if (dev->backing_buffer) 922 if (dev->backing_buffer)
926 vfree(dev->backing_buffer); 923 vfree(dev->backing_buffer);
927 924
@@ -940,35 +937,42 @@ static void dlfb_release_urb_work(struct work_struct *work)
940 up(&unode->dev->urbs.limit_sem); 937 up(&unode->dev->urbs.limit_sem);
941} 938}
942 939
943static void dlfb_free_framebuffer_work(struct work_struct *work) 940static void dlfb_free_framebuffer(struct dlfb_data *dev)
944{ 941{
945 struct dlfb_data *dev = container_of(work, struct dlfb_data,
946 free_framebuffer_work.work);
947 struct fb_info *info = dev->info; 942 struct fb_info *info = dev->info;
948 int node = info->node;
949 943
950 unregister_framebuffer(info); 944 if (info) {
945 int node = info->node;
951 946
952 if (info->cmap.len != 0) 947 unregister_framebuffer(info);
953 fb_dealloc_cmap(&info->cmap);
954 if (info->monspecs.modedb)
955 fb_destroy_modedb(info->monspecs.modedb);
956 if (info->screen_base)
957 vfree(info->screen_base);
958 948
959 fb_destroy_modelist(&info->modelist); 949 if (info->cmap.len != 0)
950 fb_dealloc_cmap(&info->cmap);
951 if (info->monspecs.modedb)
952 fb_destroy_modedb(info->monspecs.modedb);
953 if (info->screen_base)
954 vfree(info->screen_base);
960 955
961 dev->info = 0; 956 fb_destroy_modelist(&info->modelist);
962 957
963 /* Assume info structure is freed after this point */ 958 dev->info = NULL;
964 framebuffer_release(info);
965 959
966 pr_warn("fb_info for /dev/fb%d has been freed\n", node); 960 /* Assume info structure is freed after this point */
961 framebuffer_release(info);
962
963 pr_warn("fb_info for /dev/fb%d has been freed\n", node);
964 }
967 965
968 /* ref taken in probe() as part of registering framebfufer */ 966 /* ref taken in probe() as part of registering framebfufer */
969 kref_put(&dev->kref, dlfb_free); 967 kref_put(&dev->kref, dlfb_free);
970} 968}
971 969
970static void dlfb_free_framebuffer_work(struct work_struct *work)
971{
972 struct dlfb_data *dev = container_of(work, struct dlfb_data,
973 free_framebuffer_work.work);
974 dlfb_free_framebuffer(dev);
975}
972/* 976/*
973 * Assumes caller is holding info->lock mutex (for open and release at least) 977 * Assumes caller is holding info->lock mutex (for open and release at least)
974 */ 978 */
@@ -1012,7 +1016,8 @@ static int dlfb_is_valid_mode(struct fb_videomode *mode,
1012 return 0; 1016 return 0;
1013 } 1017 }
1014 1018
1015 pr_info("%dx%d valid mode\n", mode->xres, mode->yres); 1019 pr_info("%dx%d @ %d Hz valid mode\n", mode->xres, mode->yres,
1020 mode->refresh);
1016 1021
1017 return 1; 1022 return 1;
1018} 1023}
@@ -1427,19 +1432,22 @@ static ssize_t edid_store(
1427 struct device *fbdev = container_of(kobj, struct device, kobj); 1432 struct device *fbdev = container_of(kobj, struct device, kobj);
1428 struct fb_info *fb_info = dev_get_drvdata(fbdev); 1433 struct fb_info *fb_info = dev_get_drvdata(fbdev);
1429 struct dlfb_data *dev = fb_info->par; 1434 struct dlfb_data *dev = fb_info->par;
1435 int ret;
1430 1436
1431 /* We only support write of entire EDID at once, no offset*/ 1437 /* We only support write of entire EDID at once, no offset*/
1432 if ((src_size != EDID_LENGTH) || (src_off != 0)) 1438 if ((src_size != EDID_LENGTH) || (src_off != 0))
1433 return 0; 1439 return -EINVAL;
1434 1440
1435 dlfb_setup_modes(dev, fb_info, src, src_size); 1441 ret = dlfb_setup_modes(dev, fb_info, src, src_size);
1442 if (ret)
1443 return ret;
1436 1444
1437 if (dev->edid && (memcmp(src, dev->edid, src_size) == 0)) { 1445 if (!dev->edid || memcmp(src, dev->edid, src_size))
1438 pr_info("sysfs written EDID is new default\n"); 1446 return -EINVAL;
1439 dlfb_ops_set_par(fb_info); 1447
1440 return src_size; 1448 pr_info("sysfs written EDID is new default\n");
1441 } else 1449 dlfb_ops_set_par(fb_info);
1442 return 0; 1450 return src_size;
1443} 1451}
1444 1452
1445static ssize_t metrics_reset_store(struct device *fbdev, 1453static ssize_t metrics_reset_store(struct device *fbdev,
@@ -1537,7 +1545,7 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dev,
1537 u8 length; 1545 u8 length;
1538 u16 key; 1546 u16 key;
1539 1547
1540 key = *((u16 *) desc); 1548 key = le16_to_cpu(*((u16 *) desc));
1541 desc += sizeof(u16); 1549 desc += sizeof(u16);
1542 length = *desc; 1550 length = *desc;
1543 desc++; 1551 desc++;
@@ -1570,14 +1578,15 @@ success:
1570 kfree(buf); 1578 kfree(buf);
1571 return true; 1579 return true;
1572} 1580}
1581
1582static void dlfb_init_framebuffer_work(struct work_struct *work);
1583
1573static int dlfb_usb_probe(struct usb_interface *interface, 1584static int dlfb_usb_probe(struct usb_interface *interface,
1574 const struct usb_device_id *id) 1585 const struct usb_device_id *id)
1575{ 1586{
1576 struct usb_device *usbdev; 1587 struct usb_device *usbdev;
1577 struct dlfb_data *dev = 0; 1588 struct dlfb_data *dev = 0;
1578 struct fb_info *info = 0;
1579 int retval = -ENOMEM; 1589 int retval = -ENOMEM;
1580 int i;
1581 1590
1582 /* usb initialization */ 1591 /* usb initialization */
1583 1592
@@ -1589,9 +1598,7 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1589 goto error; 1598 goto error;
1590 } 1599 }
1591 1600
1592 /* we need to wait for both usb and fbdev to spin down on disconnect */
1593 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */ 1601 kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
1594 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1595 1602
1596 dev->udev = usbdev; 1603 dev->udev = usbdev;
1597 dev->gdev = &usbdev->dev; /* our generic struct device * */ 1604 dev->gdev = &usbdev->dev; /* our generic struct device * */
@@ -1613,16 +1620,53 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1613 goto error; 1620 goto error;
1614 } 1621 }
1615 1622
1623 if (pixel_limit) {
1624 pr_warn("DL chip limit of %d overriden"
1625 " by module param to %d\n",
1626 dev->sku_pixel_limit, pixel_limit);
1627 dev->sku_pixel_limit = pixel_limit;
1628 }
1629
1630
1616 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) { 1631 if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
1617 retval = -ENOMEM; 1632 retval = -ENOMEM;
1618 pr_err("dlfb_alloc_urb_list failed\n"); 1633 pr_err("dlfb_alloc_urb_list failed\n");
1619 goto error; 1634 goto error;
1620 } 1635 }
1621 1636
1637 kref_get(&dev->kref); /* matching kref_put in free_framebuffer_work */
1638
1622 /* We don't register a new USB class. Our client interface is fbdev */ 1639 /* We don't register a new USB class. Our client interface is fbdev */
1623 1640
1641 /* Workitem keep things fast & simple during USB enumeration */
1642 INIT_DELAYED_WORK(&dev->init_framebuffer_work,
1643 dlfb_init_framebuffer_work);
1644 schedule_delayed_work(&dev->init_framebuffer_work, 0);
1645
1646 return 0;
1647
1648error:
1649 if (dev) {
1650
1651 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1652 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1653
1654 /* dev has been deallocated. Do not dereference */
1655 }
1656
1657 return retval;
1658}
1659
1660static void dlfb_init_framebuffer_work(struct work_struct *work)
1661{
1662 struct dlfb_data *dev = container_of(work, struct dlfb_data,
1663 init_framebuffer_work.work);
1664 struct fb_info *info;
1665 int retval;
1666 int i;
1667
1624 /* allocates framebuffer driver structure, not framebuffer memory */ 1668 /* allocates framebuffer driver structure, not framebuffer memory */
1625 info = framebuffer_alloc(0, &interface->dev); 1669 info = framebuffer_alloc(0, dev->gdev);
1626 if (!info) { 1670 if (!info) {
1627 retval = -ENOMEM; 1671 retval = -ENOMEM;
1628 pr_err("framebuffer_alloc failed\n"); 1672 pr_err("framebuffer_alloc failed\n");
@@ -1668,15 +1712,13 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1668 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) { 1712 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) {
1669 retval = device_create_file(info->dev, &fb_device_attrs[i]); 1713 retval = device_create_file(info->dev, &fb_device_attrs[i]);
1670 if (retval) { 1714 if (retval) {
1671 pr_err("device_create_file failed %d\n", retval); 1715 pr_warn("device_create_file failed %d\n", retval);
1672 goto err_del_attrs;
1673 } 1716 }
1674 } 1717 }
1675 1718
1676 retval = device_create_bin_file(info->dev, &edid_attr); 1719 retval = device_create_bin_file(info->dev, &edid_attr);
1677 if (retval) { 1720 if (retval) {
1678 pr_err("device_create_bin_file failed %d\n", retval); 1721 pr_warn("device_create_bin_file failed %d\n", retval);
1679 goto err_del_attrs;
1680 } 1722 }
1681 1723
1682 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution." 1724 pr_info("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
@@ -1684,38 +1726,10 @@ static int dlfb_usb_probe(struct usb_interface *interface,
1684 info->var.xres, info->var.yres, 1726 info->var.xres, info->var.yres,
1685 ((dev->backing_buffer) ? 1727 ((dev->backing_buffer) ?
1686 info->fix.smem_len * 2 : info->fix.smem_len) >> 10); 1728 info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
1687 return 0; 1729 return;
1688
1689err_del_attrs:
1690 for (i -= 1; i >= 0; i--)
1691 device_remove_file(info->dev, &fb_device_attrs[i]);
1692 1730
1693error: 1731error:
1694 if (dev) { 1732 dlfb_free_framebuffer(dev);
1695
1696 if (info) {
1697 if (info->cmap.len != 0)
1698 fb_dealloc_cmap(&info->cmap);
1699 if (info->monspecs.modedb)
1700 fb_destroy_modedb(info->monspecs.modedb);
1701 if (info->screen_base)
1702 vfree(info->screen_base);
1703
1704 fb_destroy_modelist(&info->modelist);
1705
1706 framebuffer_release(info);
1707 }
1708
1709 if (dev->backing_buffer)
1710 vfree(dev->backing_buffer);
1711
1712 kref_put(&dev->kref, dlfb_free); /* ref for framebuffer */
1713 kref_put(&dev->kref, dlfb_free); /* last ref from kref_init */
1714
1715 /* dev has been deallocated. Do not dereference */
1716 }
1717
1718 return retval;
1719} 1733}
1720 1734
1721static void dlfb_usb_disconnect(struct usb_interface *interface) 1735static void dlfb_usb_disconnect(struct usb_interface *interface)
@@ -1735,12 +1749,24 @@ static void dlfb_usb_disconnect(struct usb_interface *interface)
1735 /* When non-active we'll update virtual framebuffer, but no new urbs */ 1749 /* When non-active we'll update virtual framebuffer, but no new urbs */
1736 atomic_set(&dev->usb_active, 0); 1750 atomic_set(&dev->usb_active, 0);
1737 1751
1738 /* remove udlfb's sysfs interfaces */ 1752 /* this function will wait for all in-flight urbs to complete */
1739 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) 1753 dlfb_free_urb_list(dev);
1740 device_remove_file(info->dev, &fb_device_attrs[i]); 1754
1741 device_remove_bin_file(info->dev, &edid_attr); 1755 if (info) {
1756
1757 /* remove udlfb's sysfs interfaces */
1758 for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
1759 device_remove_file(info->dev, &fb_device_attrs[i]);
1760 device_remove_bin_file(info->dev, &edid_attr);
1761
1762 /* it's safe to uncomment next line if your kernel
1763 doesn't yet have this function exported */
1764 unlink_framebuffer(info);
1765 }
1742 1766
1743 usb_set_intfdata(interface, NULL); 1767 usb_set_intfdata(interface, NULL);
1768 dev->udev = NULL;
1769 dev->gdev = NULL;
1744 1770
1745 /* if clients still have us open, will be freed on last close */ 1771 /* if clients still have us open, will be freed on last close */
1746 if (dev->fb_count == 0) 1772 if (dev->fb_count == 0)
@@ -1806,12 +1832,12 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
1806 int ret; 1832 int ret;
1807 unsigned long flags; 1833 unsigned long flags;
1808 1834
1809 pr_notice("Waiting for completes and freeing all render urbs\n"); 1835 pr_notice("Freeing all render urbs\n");
1810 1836
1811 /* keep waiting and freeing, until we've got 'em all */ 1837 /* keep waiting and freeing, until we've got 'em all */
1812 while (count--) { 1838 while (count--) {
1813 1839
1814 /* Getting interrupted means a leak, but ok at shutdown*/ 1840 /* Getting interrupted means a leak, but ok at disconnect */
1815 ret = down_interruptible(&dev->urbs.limit_sem); 1841 ret = down_interruptible(&dev->urbs.limit_sem);
1816 if (ret) 1842 if (ret)
1817 break; 1843 break;
@@ -1833,6 +1859,7 @@ static void dlfb_free_urb_list(struct dlfb_data *dev)
1833 kfree(node); 1859 kfree(node);
1834 } 1860 }
1835 1861
1862 dev->urbs.count = 0;
1836} 1863}
1837 1864
1838static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size) 1865static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
@@ -1948,6 +1975,9 @@ MODULE_PARM_DESC(fb_defio, "Page fault detection of mmap writes");
1948module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); 1975module_param(shadow, bool, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1949MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf"); 1976MODULE_PARM_DESC(shadow, "Shadow vid mem. Disable to save mem but lose perf");
1950 1977
1978module_param(pixel_limit, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP);
1979MODULE_PARM_DESC(pixel_limit, "Force limit on max mode (in x*y pixels)");
1980
1951MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, " 1981MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
1952 "Jaya Kumar <jayakumar.lkml@gmail.com>, " 1982 "Jaya Kumar <jayakumar.lkml@gmail.com>, "
1953 "Bernie Thompson <bernie@plugable.com>"); 1983 "Bernie Thompson <bernie@plugable.com>");
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index e7f69ef572dc..1f882ed6ba04 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -23,6 +23,7 @@
23#include <video/uvesafb.h> 23#include <video/uvesafb.h>
24#ifdef CONFIG_X86 24#ifdef CONFIG_X86
25#include <video/vga.h> 25#include <video/vga.h>
26#include <linux/pci.h>
26#endif 27#endif
27#ifdef CONFIG_MTRR 28#ifdef CONFIG_MTRR
28#include <asm/mtrr.h> 29#include <asm/mtrr.h>
@@ -362,7 +363,7 @@ static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
362 363
363 state = kmalloc(par->vbe_state_size, GFP_KERNEL); 364 state = kmalloc(par->vbe_state_size, GFP_KERNEL);
364 if (!state) 365 if (!state)
365 return NULL; 366 return ERR_PTR(-ENOMEM);
366 367
367 task = uvesafb_prep(); 368 task = uvesafb_prep();
368 if (!task) { 369 if (!task) {
@@ -815,8 +816,15 @@ static int __devinit uvesafb_vbe_init(struct fb_info *info)
815 par->pmi_setpal = pmi_setpal; 816 par->pmi_setpal = pmi_setpal;
816 par->ypan = ypan; 817 par->ypan = ypan;
817 818
818 if (par->pmi_setpal || par->ypan) 819 if (par->pmi_setpal || par->ypan) {
819 uvesafb_vbe_getpmi(task, par); 820 if (pcibios_enabled) {
821 uvesafb_vbe_getpmi(task, par);
822 } else {
823 par->pmi_setpal = par->ypan = 0;
824 printk(KERN_WARNING "uvesafb: PCI BIOS area is NX."
825 "Can't use protected mode interface\n");
826 }
827 }
820#else 828#else
821 /* The protected mode interface is not available on non-x86. */ 829 /* The protected mode interface is not available on non-x86. */
822 par->pmi_setpal = par->ypan = 0; 830 par->pmi_setpal = par->ypan = 0;
@@ -1172,9 +1180,17 @@ static int uvesafb_open(struct fb_info *info, int user)
1172{ 1180{
1173 struct uvesafb_par *par = info->par; 1181 struct uvesafb_par *par = info->par;
1174 int cnt = atomic_read(&par->ref_count); 1182 int cnt = atomic_read(&par->ref_count);
1183 u8 *buf = NULL;
1175 1184
1176 if (!cnt && par->vbe_state_size) 1185 if (!cnt && par->vbe_state_size) {
1177 par->vbe_state_orig = uvesafb_vbe_state_save(par); 1186 buf = uvesafb_vbe_state_save(par);
1187 if (IS_ERR(buf)) {
1188 printk(KERN_WARNING "uvesafb: save hardware state"
1189 "failed, error code is %ld!\n", PTR_ERR(buf));
1190 } else {
1191 par->vbe_state_orig = buf;
1192 }
1193 }
1178 1194
1179 atomic_inc(&par->ref_count); 1195 atomic_inc(&par->ref_count);
1180 return 0; 1196 return 0;
diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile
index 5108136e8776..159f26e6adb5 100644
--- a/drivers/video/via/Makefile
+++ b/drivers/video/via/Makefile
@@ -6,4 +6,7 @@ obj-$(CONFIG_FB_VIA) += viafb.o
6 6
7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \ 7viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \
8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \ 8 via_utility.o vt1636.o global.o tblDPASetting.o viamode.o \
9 via-core.o via-gpio.o via_modesetting.o via_clock.o 9 via-core.o via-gpio.o via_modesetting.o via_clock.o \
10 via_aux.o via_aux_edid.o via_aux_vt1636.o via_aux_vt1632.o \
11 via_aux_vt1631.o via_aux_vt1625.o via_aux_vt1622.o via_aux_vt1621.o \
12 via_aux_sii164.o via_aux_ch7301.o
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index 3ebf20c06eef..d32a5076c20f 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -146,9 +146,6 @@ struct tmds_setting_information {
146 146
147struct lvds_setting_information { 147struct lvds_setting_information {
148 int iga_path; 148 int iga_path;
149 int h_active;
150 int v_active;
151 int bpp;
152 int lcd_panel_hres; 149 int lcd_panel_hres;
153 int lcd_panel_vres; 150 int lcd_panel_vres;
154 int display_method; 151 int display_method;
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 9138e517267c..6be72f0ba21d 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -172,10 +172,11 @@ static int tmds_register_read_bytes(int index, u8 *buff, int buff_len)
172} 172}
173 173
174/* DVI Set Mode */ 174/* DVI Set Mode */
175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga) 175void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
176 u16 cxres, u16 cyres, int iga)
176{ 177{
177 struct fb_var_screeninfo dvi_var = *var; 178 struct fb_var_screeninfo dvi_var = *var;
178 struct crt_mode_table *rb_mode; 179 const struct fb_videomode *rb_mode;
179 int maxPixelClock; 180 int maxPixelClock;
180 181
181 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock; 182 maxPixelClock = viaparinfo->shared->tmds_setting_info.max_pixel_clock;
@@ -185,7 +186,7 @@ void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga)
185 viafb_fill_var_timing_info(&dvi_var, rb_mode); 186 viafb_fill_var_timing_info(&dvi_var, rb_mode);
186 } 187 }
187 188
188 viafb_fill_crtc_timing(&dvi_var, iga); 189 viafb_fill_crtc_timing(&dvi_var, cxres, cyres, iga);
189} 190}
190 191
191/* Sense DVI Connector */ 192/* Sense DVI Connector */
diff --git a/drivers/video/via/dvi.h b/drivers/video/via/dvi.h
index e2116aaf797a..db757850c216 100644
--- a/drivers/video/via/dvi.h
+++ b/drivers/video/via/dvi.h
@@ -59,6 +59,7 @@ void viafb_dvi_enable(void);
59bool __devinit viafb_tmds_trasmitter_identify(void); 59bool __devinit viafb_tmds_trasmitter_identify(void);
60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip, 60void __devinit viafb_init_dvi_size(struct tmds_chip_information *tmds_chip,
61 struct tmds_setting_information *tmds_setting); 61 struct tmds_setting_information *tmds_setting);
62void viafb_dvi_set_mode(const struct fb_var_screeninfo *var, int iga); 62void viafb_dvi_set_mode(const struct fb_var_screeninfo *var,
63 u16 cxres, u16 cyres, int iga);
63 64
64#endif /* __DVI_H__ */ 65#endif /* __DVI_H__ */
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 8497727d66de..898590db5e14 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1467,28 +1467,32 @@ void viafb_set_vclock(u32 clk, int set_iga)
1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */ 1467 via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
1468} 1468}
1469 1469
1470static struct display_timing var_to_timing(const struct fb_var_screeninfo *var) 1470struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
1471 u16 cxres, u16 cyres)
1471{ 1472{
1472 struct display_timing timing; 1473 struct display_timing timing;
1474 u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
1473 1475
1474 timing.hor_addr = var->xres; 1476 timing.hor_addr = cxres;
1475 timing.hor_sync_start = timing.hor_addr + var->right_margin; 1477 timing.hor_sync_start = timing.hor_addr + var->right_margin + dx;
1476 timing.hor_sync_end = timing.hor_sync_start + var->hsync_len; 1478 timing.hor_sync_end = timing.hor_sync_start + var->hsync_len;
1477 timing.hor_total = timing.hor_sync_end + var->left_margin; 1479 timing.hor_total = timing.hor_sync_end + var->left_margin + dx;
1478 timing.hor_blank_start = timing.hor_addr; 1480 timing.hor_blank_start = timing.hor_addr + dx;
1479 timing.hor_blank_end = timing.hor_total; 1481 timing.hor_blank_end = timing.hor_total - dx;
1480 timing.ver_addr = var->yres; 1482 timing.ver_addr = cyres;
1481 timing.ver_sync_start = timing.ver_addr + var->lower_margin; 1483 timing.ver_sync_start = timing.ver_addr + var->lower_margin + dy;
1482 timing.ver_sync_end = timing.ver_sync_start + var->vsync_len; 1484 timing.ver_sync_end = timing.ver_sync_start + var->vsync_len;
1483 timing.ver_total = timing.ver_sync_end + var->upper_margin; 1485 timing.ver_total = timing.ver_sync_end + var->upper_margin + dy;
1484 timing.ver_blank_start = timing.ver_addr; 1486 timing.ver_blank_start = timing.ver_addr + dy;
1485 timing.ver_blank_end = timing.ver_total; 1487 timing.ver_blank_end = timing.ver_total - dy;
1486 return timing; 1488 return timing;
1487} 1489}
1488 1490
1489void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga) 1491void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
1492 u16 cxres, u16 cyres, int iga)
1490{ 1493{
1491 struct display_timing crt_reg = var_to_timing(var); 1494 struct display_timing crt_reg = var_to_timing(var,
1495 cxres ? cxres : var->xres, cyres ? cyres : var->yres);
1492 1496
1493 if (iga == IGA1) 1497 if (iga == IGA1)
1494 via_set_primary_timing(&crt_reg); 1498 via_set_primary_timing(&crt_reg);
@@ -1526,13 +1530,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
1526 if (flag == 0) { 1530 if (flag == 0) {
1527 viaparinfo->tmds_setting_info->h_active = hres; 1531 viaparinfo->tmds_setting_info->h_active = hres;
1528 viaparinfo->tmds_setting_info->v_active = vres; 1532 viaparinfo->tmds_setting_info->v_active = vres;
1529
1530 viaparinfo->lvds_setting_info->h_active = hres;
1531 viaparinfo->lvds_setting_info->v_active = vres;
1532 viaparinfo->lvds_setting_info->bpp = bpp;
1533 viaparinfo->lvds_setting_info2->h_active = hres;
1534 viaparinfo->lvds_setting_info2->v_active = vres;
1535 viaparinfo->lvds_setting_info2->bpp = bpp;
1536 } else { 1533 } else {
1537 1534
1538 if (viaparinfo->tmds_setting_info->iga_path == IGA2) { 1535 if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
@@ -1540,16 +1537,6 @@ void viafb_update_device_setting(int hres, int vres, int bpp, int flag)
1540 viaparinfo->tmds_setting_info->v_active = vres; 1537 viaparinfo->tmds_setting_info->v_active = vres;
1541 } 1538 }
1542 1539
1543 if (viaparinfo->lvds_setting_info->iga_path == IGA2) {
1544 viaparinfo->lvds_setting_info->h_active = hres;
1545 viaparinfo->lvds_setting_info->v_active = vres;
1546 viaparinfo->lvds_setting_info->bpp = bpp;
1547 }
1548 if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
1549 viaparinfo->lvds_setting_info2->h_active = hres;
1550 viaparinfo->lvds_setting_info2->v_active = vres;
1551 viaparinfo->lvds_setting_info2->bpp = bpp;
1552 }
1553 } 1540 }
1554} 1541}
1555 1542
@@ -1758,13 +1745,13 @@ static void set_display_channel(void)
1758 } 1745 }
1759} 1746}
1760 1747
1761static u8 get_sync(struct fb_info *info) 1748static u8 get_sync(struct fb_var_screeninfo *var)
1762{ 1749{
1763 u8 polarity = 0; 1750 u8 polarity = 0;
1764 1751
1765 if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT)) 1752 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
1766 polarity |= VIA_HSYNC_NEGATIVE; 1753 polarity |= VIA_HSYNC_NEGATIVE;
1767 if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT)) 1754 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
1768 polarity |= VIA_VSYNC_NEGATIVE; 1755 polarity |= VIA_VSYNC_NEGATIVE;
1769 return polarity; 1756 return polarity;
1770} 1757}
@@ -1844,9 +1831,9 @@ static void hw_init(void)
1844 load_fix_bit_crtc_reg(); 1831 load_fix_bit_crtc_reg();
1845} 1832}
1846 1833
1847int viafb_setmode(int video_bpp, int video_bpp1) 1834int viafb_setmode(void)
1848{ 1835{
1849 int j; 1836 int j, cxres = 0, cyres = 0;
1850 int port; 1837 int port;
1851 u32 devices = viaparinfo->shared->iga1_devices 1838 u32 devices = viaparinfo->shared->iga1_devices
1852 | viaparinfo->shared->iga2_devices; 1839 | viaparinfo->shared->iga2_devices;
@@ -1895,6 +1882,8 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1895 } else if (viafb_SAMM_ON) { 1882 } else if (viafb_SAMM_ON) {
1896 viafb_fill_var_timing_info(&var2, viafb_get_best_mode( 1883 viafb_fill_var_timing_info(&var2, viafb_get_best_mode(
1897 viafb_second_xres, viafb_second_yres, viafb_refresh1)); 1884 viafb_second_xres, viafb_second_yres, viafb_refresh1));
1885 cxres = viafbinfo->var.xres;
1886 cyres = viafbinfo->var.yres;
1898 var2.bits_per_pixel = viafbinfo->var.bits_per_pixel; 1887 var2.bits_per_pixel = viafbinfo->var.bits_per_pixel;
1899 } 1888 }
1900 1889
@@ -1902,9 +1891,9 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1902 if (viafb_CRT_ON) { 1891 if (viafb_CRT_ON) {
1903 if (viaparinfo->shared->iga2_devices & VIA_CRT 1892 if (viaparinfo->shared->iga2_devices & VIA_CRT
1904 && viafb_SAMM_ON) 1893 && viafb_SAMM_ON)
1905 viafb_fill_crtc_timing(&var2, IGA2); 1894 viafb_fill_crtc_timing(&var2, cxres, cyres, IGA2);
1906 else 1895 else
1907 viafb_fill_crtc_timing(&viafbinfo->var, 1896 viafb_fill_crtc_timing(&viafbinfo->var, 0, 0,
1908 (viaparinfo->shared->iga1_devices & VIA_CRT) 1897 (viaparinfo->shared->iga1_devices & VIA_CRT)
1909 ? IGA1 : IGA2); 1898 ? IGA1 : IGA2);
1910 1899
@@ -1922,17 +1911,17 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1922 if (viafb_DVI_ON) { 1911 if (viafb_DVI_ON) {
1923 if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2 1912 if (viaparinfo->shared->tmds_setting_info.iga_path == IGA2
1924 && viafb_SAMM_ON) 1913 && viafb_SAMM_ON)
1925 viafb_dvi_set_mode(&var2, IGA2); 1914 viafb_dvi_set_mode(&var2, cxres, cyres, IGA2);
1926 else 1915 else
1927 viafb_dvi_set_mode(&viafbinfo->var, 1916 viafb_dvi_set_mode(&viafbinfo->var, 0, 0,
1928 viaparinfo->tmds_setting_info->iga_path); 1917 viaparinfo->tmds_setting_info->iga_path);
1929 } 1918 }
1930 1919
1931 if (viafb_LCD_ON) { 1920 if (viafb_LCD_ON) {
1932 if (viafb_SAMM_ON && 1921 if (viafb_SAMM_ON &&
1933 (viaparinfo->lvds_setting_info->iga_path == IGA2)) { 1922 (viaparinfo->lvds_setting_info->iga_path == IGA2)) {
1934 viaparinfo->lvds_setting_info->bpp = video_bpp1; 1923 viafb_lcd_set_mode(&var2, cxres, cyres,
1935 viafb_lcd_set_mode(viaparinfo->lvds_setting_info, 1924 viaparinfo->lvds_setting_info,
1936 &viaparinfo->chip_info->lvds_chip_info); 1925 &viaparinfo->chip_info->lvds_chip_info);
1937 } else { 1926 } else {
1938 /* IGA1 doesn't have LCD scaling, so set it center. */ 1927 /* IGA1 doesn't have LCD scaling, so set it center. */
@@ -1940,16 +1929,16 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1940 viaparinfo->lvds_setting_info->display_method = 1929 viaparinfo->lvds_setting_info->display_method =
1941 LCD_CENTERING; 1930 LCD_CENTERING;
1942 } 1931 }
1943 viaparinfo->lvds_setting_info->bpp = video_bpp; 1932 viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1944 viafb_lcd_set_mode(viaparinfo->lvds_setting_info, 1933 viaparinfo->lvds_setting_info,
1945 &viaparinfo->chip_info->lvds_chip_info); 1934 &viaparinfo->chip_info->lvds_chip_info);
1946 } 1935 }
1947 } 1936 }
1948 if (viafb_LCD2_ON) { 1937 if (viafb_LCD2_ON) {
1949 if (viafb_SAMM_ON && 1938 if (viafb_SAMM_ON &&
1950 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) { 1939 (viaparinfo->lvds_setting_info2->iga_path == IGA2)) {
1951 viaparinfo->lvds_setting_info2->bpp = video_bpp1; 1940 viafb_lcd_set_mode(&var2, cxres, cyres,
1952 viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, 1941 viaparinfo->lvds_setting_info2,
1953 &viaparinfo->chip_info->lvds_chip_info2); 1942 &viaparinfo->chip_info->lvds_chip_info2);
1954 } else { 1943 } else {
1955 /* IGA1 doesn't have LCD scaling, so set it center. */ 1944 /* IGA1 doesn't have LCD scaling, so set it center. */
@@ -1957,8 +1946,8 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1957 viaparinfo->lvds_setting_info2->display_method = 1946 viaparinfo->lvds_setting_info2->display_method =
1958 LCD_CENTERING; 1947 LCD_CENTERING;
1959 } 1948 }
1960 viaparinfo->lvds_setting_info2->bpp = video_bpp; 1949 viafb_lcd_set_mode(&viafbinfo->var, 0, 0,
1961 viafb_lcd_set_mode(viaparinfo->lvds_setting_info2, 1950 viaparinfo->lvds_setting_info2,
1962 &viaparinfo->chip_info->lvds_chip_info2); 1951 &viaparinfo->chip_info->lvds_chip_info2);
1963 } 1952 }
1964 } 1953 }
@@ -1971,7 +1960,7 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1971 if (!viafb_hotplug) { 1960 if (!viafb_hotplug) {
1972 viafb_hotplug_Xres = viafbinfo->var.xres; 1961 viafb_hotplug_Xres = viafbinfo->var.xres;
1973 viafb_hotplug_Yres = viafbinfo->var.yres; 1962 viafb_hotplug_Yres = viafbinfo->var.yres;
1974 viafb_hotplug_bpp = video_bpp; 1963 viafb_hotplug_bpp = viafbinfo->var.bits_per_pixel;
1975 viafb_hotplug_refresh = viafb_refresh; 1964 viafb_hotplug_refresh = viafb_refresh;
1976 1965
1977 if (viafb_DVI_ON) 1966 if (viafb_DVI_ON)
@@ -1980,13 +1969,13 @@ int viafb_setmode(int video_bpp, int video_bpp1)
1980 viafb_DeviceStatus = CRT_Device; 1969 viafb_DeviceStatus = CRT_Device;
1981 } 1970 }
1982 device_on(); 1971 device_on();
1983 if (!viafb_dual_fb) 1972 if (!viafb_SAMM_ON)
1984 via_set_sync_polarity(devices, get_sync(viafbinfo)); 1973 via_set_sync_polarity(devices, get_sync(&viafbinfo->var));
1985 else { 1974 else {
1986 via_set_sync_polarity(viaparinfo->shared->iga1_devices, 1975 via_set_sync_polarity(viaparinfo->shared->iga1_devices,
1987 get_sync(viafbinfo)); 1976 get_sync(&viafbinfo->var));
1988 via_set_sync_polarity(viaparinfo->shared->iga2_devices, 1977 via_set_sync_polarity(viaparinfo->shared->iga2_devices,
1989 get_sync(viafbinfo1)); 1978 get_sync(&var2));
1990 } 1979 }
1991 1980
1992 clock.set_engine_pll_state(VIA_STATE_ON); 1981 clock.set_engine_pll_state(VIA_STATE_ON);
@@ -2023,20 +2012,20 @@ int viafb_setmode(int video_bpp, int video_bpp1)
2023 2012
2024int viafb_get_refresh(int hres, int vres, u32 long_refresh) 2013int viafb_get_refresh(int hres, int vres, u32 long_refresh)
2025{ 2014{
2026 struct crt_mode_table *best; 2015 const struct fb_videomode *best;
2027 2016
2028 best = viafb_get_best_mode(hres, vres, long_refresh); 2017 best = viafb_get_best_mode(hres, vres, long_refresh);
2029 if (!best) 2018 if (!best)
2030 return 60; 2019 return 60;
2031 2020
2032 if (abs(best->refresh_rate - long_refresh) > 3) { 2021 if (abs(best->refresh - long_refresh) > 3) {
2033 if (hres == 1200 && vres == 900) 2022 if (hres == 1200 && vres == 900)
2034 return 49; /* OLPC DCON only supports 50 Hz */ 2023 return 49; /* OLPC DCON only supports 50 Hz */
2035 else 2024 else
2036 return 60; 2025 return 60;
2037 } 2026 }
2038 2027
2039 return best->refresh_rate; 2028 return best->refresh;
2040} 2029}
2041 2030
2042static void device_off(void) 2031static void device_off(void)
@@ -2129,26 +2118,17 @@ void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
2129 } 2118 }
2130} 2119}
2131 2120
2132/*According var's xres, yres fill var's other timing information*/
2133void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, 2121void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
2134 struct crt_mode_table *mode) 2122 const struct fb_videomode *mode)
2135{ 2123{
2136 struct display_timing crt_reg; 2124 var->pixclock = mode->pixclock;
2137 2125 var->xres = mode->xres;
2138 crt_reg = mode->crtc; 2126 var->yres = mode->yres;
2139 var->pixclock = 1000000000 / (crt_reg.hor_total * crt_reg.ver_total) 2127 var->left_margin = mode->left_margin;
2140 * 1000 / mode->refresh_rate; 2128 var->right_margin = mode->right_margin;
2141 var->left_margin = 2129 var->hsync_len = mode->hsync_len;
2142 crt_reg.hor_total - (crt_reg.hor_sync_start + crt_reg.hor_sync_end); 2130 var->upper_margin = mode->upper_margin;
2143 var->right_margin = crt_reg.hor_sync_start - crt_reg.hor_addr; 2131 var->lower_margin = mode->lower_margin;
2144 var->hsync_len = crt_reg.hor_sync_end; 2132 var->vsync_len = mode->vsync_len;
2145 var->upper_margin = 2133 var->sync = mode->sync;
2146 crt_reg.ver_total - (crt_reg.ver_sync_start + crt_reg.ver_sync_end);
2147 var->lower_margin = crt_reg.ver_sync_start - crt_reg.ver_addr;
2148 var->vsync_len = crt_reg.ver_sync_end;
2149 var->sync = 0;
2150 if (mode->h_sync_polarity == POSITIVE)
2151 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2152 if (mode->v_sync_polarity == POSITIVE)
2153 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2154} 2134}
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 4db5b6e8d8d0..6be243cfc823 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -637,7 +637,10 @@ extern int viafb_LCD_ON;
637extern int viafb_DVI_ON; 637extern int viafb_DVI_ON;
638extern int viafb_hotplug; 638extern int viafb_hotplug;
639 639
640void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var, int iga); 640struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
641 u16 cxres, u16 cyres);
642void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
643 u16 cxres, u16 cyres, int iga);
641void viafb_set_vclock(u32 CLK, int set_iga); 644void viafb_set_vclock(u32 CLK, int set_iga);
642void viafb_load_reg(int timing_value, int viafb_load_reg_num, 645void viafb_load_reg(int timing_value, int viafb_load_reg_num,
643 struct io_register *reg, 646 struct io_register *reg,
@@ -657,9 +660,9 @@ void viafb_load_FIFO_reg(int set_iga, int hor_active, int ver_active);
657void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\ 660void viafb_set_dpa_gfx(int output_interface, struct GFX_DPA_SETTING\
658 *p_gfx_dpa_setting); 661 *p_gfx_dpa_setting);
659 662
660int viafb_setmode(int video_bpp, int video_bpp1); 663int viafb_setmode(void);
661void viafb_fill_var_timing_info(struct fb_var_screeninfo *var, 664void viafb_fill_var_timing_info(struct fb_var_screeninfo *var,
662 struct crt_mode_table *mode); 665 const struct fb_videomode *mode);
663void __devinit viafb_init_chip_info(int chip_type); 666void __devinit viafb_init_chip_info(int chip_type);
664void __devinit viafb_init_dac(int set_iga); 667void __devinit viafb_init_dac(int set_iga);
665int viafb_get_refresh(int hres, int vres, u32 float_refresh); 668int viafb_get_refresh(int hres, int vres, u32 float_refresh);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 5f3b4e394e82..165037910536 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -53,10 +53,6 @@ static void __devinit fp_id_to_vindex(int panel_id);
53static int lvds_register_read(int index); 53static int lvds_register_read(int index);
54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres, 54static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
55 int panel_vres); 55 int panel_vres);
56static void via_pitch_alignment_patch_lcd(
57 struct lvds_setting_information *plvds_setting_info,
58 struct lvds_chip_information
59 *plvds_chip_info);
60static void lcd_patch_skew_dvp0(struct lvds_setting_information 56static void lcd_patch_skew_dvp0(struct lvds_setting_information
61 *plvds_setting_info, 57 *plvds_setting_info,
62 struct lvds_chip_information *plvds_chip_info); 58 struct lvds_chip_information *plvds_chip_info);
@@ -79,9 +75,6 @@ static void check_diport_of_integrated_lvds(
79 struct lvds_chip_information *plvds_chip_info, 75 struct lvds_chip_information *plvds_chip_info,
80 struct lvds_setting_information 76 struct lvds_setting_information
81 *plvds_setting_info); 77 *plvds_setting_info);
82static struct display_timing lcd_centering_timging(struct display_timing
83 mode_crt_reg,
84 struct display_timing panel_crt_reg);
85 78
86static inline bool check_lvds_chip(int device_id_subaddr, int device_id) 79static inline bool check_lvds_chip(int device_id_subaddr, int device_id)
87{ 80{
@@ -454,20 +447,17 @@ static void load_lcd_scaling(int set_hres, int set_vres, int panel_hres,
454 } 447 }
455} 448}
456 449
457static void via_pitch_alignment_patch_lcd( 450static void via_pitch_alignment_patch_lcd(int iga_path, int hres, int bpp)
458 struct lvds_setting_information *plvds_setting_info,
459 struct lvds_chip_information
460 *plvds_chip_info)
461{ 451{
462 unsigned char cr13, cr35, cr65, cr66, cr67; 452 unsigned char cr13, cr35, cr65, cr66, cr67;
463 unsigned long dwScreenPitch = 0; 453 unsigned long dwScreenPitch = 0;
464 unsigned long dwPitch; 454 unsigned long dwPitch;
465 455
466 dwPitch = plvds_setting_info->h_active * (plvds_setting_info->bpp >> 3); 456 dwPitch = hres * (bpp >> 3);
467 if (dwPitch & 0x1F) { 457 if (dwPitch & 0x1F) {
468 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3; 458 dwScreenPitch = ((dwPitch + 31) & ~31) >> 3;
469 if (plvds_setting_info->iga_path == IGA2) { 459 if (iga_path == IGA2) {
470 if (plvds_setting_info->bpp > 8) { 460 if (bpp > 8) {
471 cr66 = (unsigned char)(dwScreenPitch & 0xFF); 461 cr66 = (unsigned char)(dwScreenPitch & 0xFF);
472 viafb_write_reg(CR66, VIACR, cr66); 462 viafb_write_reg(CR66, VIACR, cr66);
473 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC; 463 cr67 = viafb_read_reg(VIACR, CR67) & 0xFC;
@@ -485,7 +475,7 @@ static void via_pitch_alignment_patch_lcd(
485 cr65 += 2; 475 cr65 += 2;
486 viafb_write_reg(CR65, VIACR, cr65); 476 viafb_write_reg(CR65, VIACR, cr65);
487 } else { 477 } else {
488 if (plvds_setting_info->bpp > 8) { 478 if (bpp > 8) {
489 cr13 = (unsigned char)(dwScreenPitch & 0xFF); 479 cr13 = (unsigned char)(dwScreenPitch & 0xFF);
490 viafb_write_reg(CR13, VIACR, cr13); 480 viafb_write_reg(CR13, VIACR, cr13);
491 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F; 481 cr35 = viafb_read_reg(VIACR, CR35) & 0x1F;
@@ -548,49 +538,45 @@ static void lcd_patch_skew(struct lvds_setting_information
548} 538}
549 539
550/* LCD Set Mode */ 540/* LCD Set Mode */
551void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, 541void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
542 u16 cyres, struct lvds_setting_information *plvds_setting_info,
552 struct lvds_chip_information *plvds_chip_info) 543 struct lvds_chip_information *plvds_chip_info)
553{ 544{
554 int set_iga = plvds_setting_info->iga_path; 545 int set_iga = plvds_setting_info->iga_path;
555 int mode_bpp = plvds_setting_info->bpp; 546 int mode_bpp = var->bits_per_pixel;
556 int set_hres = plvds_setting_info->h_active; 547 int set_hres = cxres ? cxres : var->xres;
557 int set_vres = plvds_setting_info->v_active; 548 int set_vres = cyres ? cyres : var->yres;
558 int panel_hres = plvds_setting_info->lcd_panel_hres; 549 int panel_hres = plvds_setting_info->lcd_panel_hres;
559 int panel_vres = plvds_setting_info->lcd_panel_vres; 550 int panel_vres = plvds_setting_info->lcd_panel_vres;
560 u32 clock; 551 u32 clock;
561 struct display_timing mode_crt_reg, panel_crt_reg, timing; 552 struct display_timing timing;
562 struct crt_mode_table *mode_crt_table, *panel_crt_table; 553 struct fb_var_screeninfo panel_var;
554 const struct fb_videomode *mode_crt_table, *panel_crt_table;
563 555
564 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n"); 556 DEBUG_MSG(KERN_INFO "viafb_lcd_set_mode!!\n");
565 /* Get mode table */ 557 /* Get mode table */
566 mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60); 558 mode_crt_table = viafb_get_best_mode(set_hres, set_vres, 60);
567 mode_crt_reg = mode_crt_table->crtc;
568 /* Get panel table Pointer */ 559 /* Get panel table Pointer */
569 panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60); 560 panel_crt_table = viafb_get_best_mode(panel_hres, panel_vres, 60);
570 panel_crt_reg = panel_crt_table->crtc; 561 viafb_fill_var_timing_info(&panel_var, panel_crt_table);
571 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n"); 562 DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
572 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name) 563 if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
573 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info); 564 viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
574 clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total 565 clock = PICOS2KHZ(panel_crt_table->pixclock) * 1000;
575 * panel_crt_table->refresh_rate;
576 plvds_setting_info->vclk = clock; 566 plvds_setting_info->vclk = clock;
577 567
578 if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres) 568 if (set_iga == IGA2 && (set_hres < panel_hres || set_vres < panel_vres)
579 && plvds_setting_info->display_method == LCD_EXPANDSION) { 569 && plvds_setting_info->display_method == LCD_EXPANDSION) {
580 timing = panel_crt_reg; 570 timing = var_to_timing(&panel_var, panel_hres, panel_vres);
581 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres); 571 load_lcd_scaling(set_hres, set_vres, panel_hres, panel_vres);
582 } else { 572 } else {
583 timing = lcd_centering_timging(mode_crt_reg, panel_crt_reg); 573 timing = var_to_timing(&panel_var, set_hres, set_vres);
584 if (set_iga == IGA2) 574 if (set_iga == IGA2)
585 /* disable scaling */ 575 /* disable scaling */
586 via_write_reg_mask(VIACR, 0x79, 0x00, 576 via_write_reg_mask(VIACR, 0x79, 0x00,
587 BIT0 + BIT1 + BIT2); 577 BIT0 + BIT1 + BIT2);
588 } 578 }
589 579
590 timing.hor_blank_end += timing.hor_blank_start;
591 timing.hor_sync_end += timing.hor_sync_start;
592 timing.ver_blank_end += timing.ver_blank_start;
593 timing.ver_sync_end += timing.ver_sync_start;
594 if (set_iga == IGA1) 580 if (set_iga == IGA1)
595 via_set_primary_timing(&timing); 581 via_set_primary_timing(&timing);
596 else if (set_iga == IGA2) 582 else if (set_iga == IGA2)
@@ -613,7 +599,8 @@ void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info,
613 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0); 599 viafb_write_reg_mask(CR6A, VIACR, 0x01, BIT0);
614 600
615 /* Patch for non 32bit alignment mode */ 601 /* Patch for non 32bit alignment mode */
616 via_pitch_alignment_patch_lcd(plvds_setting_info, plvds_chip_info); 602 via_pitch_alignment_patch_lcd(plvds_setting_info->iga_path, set_hres,
603 var->bits_per_pixel);
617} 604}
618 605
619static void integrated_lvds_disable(struct lvds_setting_information 606static void integrated_lvds_disable(struct lvds_setting_information
@@ -973,37 +960,6 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
973 } 960 }
974} 961}
975 962
976static struct display_timing lcd_centering_timging(struct display_timing
977 mode_crt_reg,
978 struct display_timing panel_crt_reg)
979{
980 struct display_timing crt_reg;
981
982 crt_reg.hor_total = panel_crt_reg.hor_total;
983 crt_reg.hor_addr = mode_crt_reg.hor_addr;
984 crt_reg.hor_blank_start =
985 (panel_crt_reg.hor_addr - mode_crt_reg.hor_addr) / 2 +
986 crt_reg.hor_addr;
987 crt_reg.hor_blank_end = panel_crt_reg.hor_blank_end;
988 crt_reg.hor_sync_start =
989 (panel_crt_reg.hor_sync_start -
990 panel_crt_reg.hor_blank_start) + crt_reg.hor_blank_start;
991 crt_reg.hor_sync_end = panel_crt_reg.hor_sync_end;
992
993 crt_reg.ver_total = panel_crt_reg.ver_total;
994 crt_reg.ver_addr = mode_crt_reg.ver_addr;
995 crt_reg.ver_blank_start =
996 (panel_crt_reg.ver_addr - mode_crt_reg.ver_addr) / 2 +
997 crt_reg.ver_addr;
998 crt_reg.ver_blank_end = panel_crt_reg.ver_blank_end;
999 crt_reg.ver_sync_start =
1000 (panel_crt_reg.ver_sync_start -
1001 panel_crt_reg.ver_blank_start) + crt_reg.ver_blank_start;
1002 crt_reg.ver_sync_end = panel_crt_reg.ver_sync_end;
1003
1004 return crt_reg;
1005}
1006
1007bool viafb_lcd_get_mobile_state(bool *mobile) 963bool viafb_lcd_get_mobile_state(bool *mobile)
1008{ 964{
1009 unsigned char __iomem *romptr, *tableptr, *biosptr; 965 unsigned char __iomem *romptr, *tableptr, *biosptr;
diff --git a/drivers/video/via/lcd.h b/drivers/video/via/lcd.h
index 77ca7b862e68..8f3e4e06156c 100644
--- a/drivers/video/via/lcd.h
+++ b/drivers/video/via/lcd.h
@@ -76,7 +76,8 @@ void __devinit viafb_init_lvds_output_interface(struct lvds_chip_information
76 *plvds_chip_info, 76 *plvds_chip_info,
77 struct lvds_setting_information 77 struct lvds_setting_information
78 *plvds_setting_info); 78 *plvds_setting_info);
79void viafb_lcd_set_mode(struct lvds_setting_information *plvds_setting_info, 79void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
80 u16 cyres, struct lvds_setting_information *plvds_setting_info,
80 struct lvds_chip_information *plvds_chip_info); 81 struct lvds_chip_information *plvds_chip_info);
81bool __devinit viafb_lvds_trasmitter_identify(void); 82bool __devinit viafb_lvds_trasmitter_identify(void);
82void viafb_init_lvds_output_interface(struct lvds_chip_information 83void viafb_init_lvds_output_interface(struct lvds_chip_information
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index c01c1c162726..3158dfc90bed 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -283,337 +283,6 @@
283#define HW_LAYOUT_LCD1_LCD2 0x04 283#define HW_LAYOUT_LCD1_LCD2 0x04
284#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10 284#define HW_LAYOUT_LCD_EXTERNAL_LCD2 0x10
285 285
286/* Definition Refresh Rate */
287#define REFRESH_49 49
288#define REFRESH_50 50
289#define REFRESH_60 60
290#define REFRESH_75 75
291#define REFRESH_85 85
292#define REFRESH_100 100
293#define REFRESH_120 120
294
295/* Definition Sync Polarity*/
296#define NEGATIVE 1
297#define POSITIVE 0
298
299/*480x640@60 Sync Polarity (GTF)
300*/
301#define M480X640_R60_HSP NEGATIVE
302#define M480X640_R60_VSP POSITIVE
303
304/*640x480@60 Sync Polarity (VESA Mode)
305*/
306#define M640X480_R60_HSP NEGATIVE
307#define M640X480_R60_VSP NEGATIVE
308
309/*640x480@75 Sync Polarity (VESA Mode)
310*/
311#define M640X480_R75_HSP NEGATIVE
312#define M640X480_R75_VSP NEGATIVE
313
314/*640x480@85 Sync Polarity (VESA Mode)
315*/
316#define M640X480_R85_HSP NEGATIVE
317#define M640X480_R85_VSP NEGATIVE
318
319/*640x480@100 Sync Polarity (GTF Mode)
320*/
321#define M640X480_R100_HSP NEGATIVE
322#define M640X480_R100_VSP POSITIVE
323
324/*640x480@120 Sync Polarity (GTF Mode)
325*/
326#define M640X480_R120_HSP NEGATIVE
327#define M640X480_R120_VSP POSITIVE
328
329/*720x480@60 Sync Polarity (GTF Mode)
330*/
331#define M720X480_R60_HSP NEGATIVE
332#define M720X480_R60_VSP POSITIVE
333
334/*720x576@60 Sync Polarity (GTF Mode)
335*/
336#define M720X576_R60_HSP NEGATIVE
337#define M720X576_R60_VSP POSITIVE
338
339/*800x600@60 Sync Polarity (VESA Mode)
340*/
341#define M800X600_R60_HSP POSITIVE
342#define M800X600_R60_VSP POSITIVE
343
344/*800x600@75 Sync Polarity (VESA Mode)
345*/
346#define M800X600_R75_HSP POSITIVE
347#define M800X600_R75_VSP POSITIVE
348
349/*800x600@85 Sync Polarity (VESA Mode)
350*/
351#define M800X600_R85_HSP POSITIVE
352#define M800X600_R85_VSP POSITIVE
353
354/*800x600@100 Sync Polarity (GTF Mode)
355*/
356#define M800X600_R100_HSP NEGATIVE
357#define M800X600_R100_VSP POSITIVE
358
359/*800x600@120 Sync Polarity (GTF Mode)
360*/
361#define M800X600_R120_HSP NEGATIVE
362#define M800X600_R120_VSP POSITIVE
363
364/*800x480@60 Sync Polarity (CVT Mode)
365*/
366#define M800X480_R60_HSP NEGATIVE
367#define M800X480_R60_VSP POSITIVE
368
369/*848x480@60 Sync Polarity (CVT Mode)
370*/
371#define M848X480_R60_HSP NEGATIVE
372#define M848X480_R60_VSP POSITIVE
373
374/*852x480@60 Sync Polarity (GTF Mode)
375*/
376#define M852X480_R60_HSP NEGATIVE
377#define M852X480_R60_VSP POSITIVE
378
379/*1024x512@60 Sync Polarity (GTF Mode)
380*/
381#define M1024X512_R60_HSP NEGATIVE
382#define M1024X512_R60_VSP POSITIVE
383
384/*1024x600@60 Sync Polarity (GTF Mode)
385*/
386#define M1024X600_R60_HSP NEGATIVE
387#define M1024X600_R60_VSP POSITIVE
388
389/*1024x768@60 Sync Polarity (VESA Mode)
390*/
391#define M1024X768_R60_HSP NEGATIVE
392#define M1024X768_R60_VSP NEGATIVE
393
394/*1024x768@75 Sync Polarity (VESA Mode)
395*/
396#define M1024X768_R75_HSP POSITIVE
397#define M1024X768_R75_VSP POSITIVE
398
399/*1024x768@85 Sync Polarity (VESA Mode)
400*/
401#define M1024X768_R85_HSP POSITIVE
402#define M1024X768_R85_VSP POSITIVE
403
404/*1024x768@100 Sync Polarity (GTF Mode)
405*/
406#define M1024X768_R100_HSP NEGATIVE
407#define M1024X768_R100_VSP POSITIVE
408
409/*1152x864@75 Sync Polarity (VESA Mode)
410*/
411#define M1152X864_R75_HSP POSITIVE
412#define M1152X864_R75_VSP POSITIVE
413
414/*1280x720@60 Sync Polarity (GTF Mode)
415*/
416#define M1280X720_R60_HSP NEGATIVE
417#define M1280X720_R60_VSP POSITIVE
418
419/* 1280x768@50 Sync Polarity (GTF Mode) */
420#define M1280X768_R50_HSP NEGATIVE
421#define M1280X768_R50_VSP POSITIVE
422
423/*1280x768@60 Sync Polarity (GTF Mode)
424*/
425#define M1280X768_R60_HSP NEGATIVE
426#define M1280X768_R60_VSP POSITIVE
427
428/*1280x800@60 Sync Polarity (CVT Mode)
429*/
430#define M1280X800_R60_HSP NEGATIVE
431#define M1280X800_R60_VSP POSITIVE
432
433/*1280x960@60 Sync Polarity (VESA Mode)
434*/
435#define M1280X960_R60_HSP POSITIVE
436#define M1280X960_R60_VSP POSITIVE
437
438/*1280x1024@60 Sync Polarity (VESA Mode)
439*/
440#define M1280X1024_R60_HSP POSITIVE
441#define M1280X1024_R60_VSP POSITIVE
442
443/* 1360x768@60 Sync Polarity (CVT Mode) */
444#define M1360X768_R60_HSP POSITIVE
445#define M1360X768_R60_VSP POSITIVE
446
447/* 1360x768@60 Sync Polarity (CVT Reduce Blanking Mode) */
448#define M1360X768_RB_R60_HSP POSITIVE
449#define M1360X768_RB_R60_VSP NEGATIVE
450
451/* 1368x768@50 Sync Polarity (GTF Mode) */
452#define M1368X768_R50_HSP NEGATIVE
453#define M1368X768_R50_VSP POSITIVE
454
455/* 1368x768@60 Sync Polarity (VESA Mode) */
456#define M1368X768_R60_HSP NEGATIVE
457#define M1368X768_R60_VSP POSITIVE
458
459/*1280x1024@75 Sync Polarity (VESA Mode)
460*/
461#define M1280X1024_R75_HSP POSITIVE
462#define M1280X1024_R75_VSP POSITIVE
463
464/*1280x1024@85 Sync Polarity (VESA Mode)
465*/
466#define M1280X1024_R85_HSP POSITIVE
467#define M1280X1024_R85_VSP POSITIVE
468
469/*1440x1050@60 Sync Polarity (GTF Mode)
470*/
471#define M1440X1050_R60_HSP NEGATIVE
472#define M1440X1050_R60_VSP POSITIVE
473
474/*1600x1200@60 Sync Polarity (VESA Mode)
475*/
476#define M1600X1200_R60_HSP POSITIVE
477#define M1600X1200_R60_VSP POSITIVE
478
479/*1600x1200@75 Sync Polarity (VESA Mode)
480*/
481#define M1600X1200_R75_HSP POSITIVE
482#define M1600X1200_R75_VSP POSITIVE
483
484/* 1680x1050@60 Sync Polarity (CVT Mode) */
485#define M1680x1050_R60_HSP NEGATIVE
486#define M1680x1050_R60_VSP NEGATIVE
487
488/* 1680x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
489#define M1680x1050_RB_R60_HSP POSITIVE
490#define M1680x1050_RB_R60_VSP NEGATIVE
491
492/* 1680x1050@75 Sync Polarity (CVT Mode) */
493#define M1680x1050_R75_HSP NEGATIVE
494#define M1680x1050_R75_VSP POSITIVE
495
496/*1920x1080@60 Sync Polarity (CVT Mode)
497*/
498#define M1920X1080_R60_HSP NEGATIVE
499#define M1920X1080_R60_VSP POSITIVE
500
501/* 1920x1080@60 Sync Polarity (CVT Reduce Blanking Mode) */
502#define M1920X1080_RB_R60_HSP POSITIVE
503#define M1920X1080_RB_R60_VSP NEGATIVE
504
505/*1920x1440@60 Sync Polarity (VESA Mode)
506*/
507#define M1920X1440_R60_HSP NEGATIVE
508#define M1920X1440_R60_VSP POSITIVE
509
510/*1920x1440@75 Sync Polarity (VESA Mode)
511*/
512#define M1920X1440_R75_HSP NEGATIVE
513#define M1920X1440_R75_VSP POSITIVE
514
515#if 0
516/* 1400x1050@60 Sync Polarity (VESA Mode) */
517#define M1400X1050_R60_HSP NEGATIVE
518#define M1400X1050_R60_VSP NEGATIVE
519#endif
520
521/* 1400x1050@60 Sync Polarity (CVT Mode) */
522#define M1400X1050_R60_HSP NEGATIVE
523#define M1400X1050_R60_VSP POSITIVE
524
525/* 1400x1050@60 Sync Polarity (CVT Reduce Blanking Mode) */
526#define M1400X1050_RB_R60_HSP POSITIVE
527#define M1400X1050_RB_R60_VSP NEGATIVE
528
529/* 1400x1050@75 Sync Polarity (CVT Mode) */
530#define M1400X1050_R75_HSP NEGATIVE
531#define M1400X1050_R75_VSP POSITIVE
532
533/* 960x600@60 Sync Polarity (CVT Mode) */
534#define M960X600_R60_HSP NEGATIVE
535#define M960X600_R60_VSP POSITIVE
536
537/* 1000x600@60 Sync Polarity (GTF Mode) */
538#define M1000X600_R60_HSP NEGATIVE
539#define M1000X600_R60_VSP POSITIVE
540
541/* 1024x576@60 Sync Polarity (GTF Mode) */
542#define M1024X576_R60_HSP NEGATIVE
543#define M1024X576_R60_VSP POSITIVE
544
545/*1024x600@60 Sync Polarity (GTF Mode)*/
546#define M1024X600_R60_HSP NEGATIVE
547#define M1024X600_R60_VSP POSITIVE
548
549/* 1088x612@60 Sync Polarity (CVT Mode) */
550#define M1088X612_R60_HSP NEGATIVE
551#define M1088X612_R60_VSP POSITIVE
552
553/* 1152x720@60 Sync Polarity (CVT Mode) */
554#define M1152X720_R60_HSP NEGATIVE
555#define M1152X720_R60_VSP POSITIVE
556
557/* 1200x720@60 Sync Polarity (GTF Mode) */
558#define M1200X720_R60_HSP NEGATIVE
559#define M1200X720_R60_VSP POSITIVE
560
561/* 1200x900@60 Sync Polarity (DCON) */
562#define M1200X900_R60_HSP POSITIVE
563#define M1200X900_R60_VSP POSITIVE
564
565/* 1280x600@60 Sync Polarity (GTF Mode) */
566#define M1280x600_R60_HSP NEGATIVE
567#define M1280x600_R60_VSP POSITIVE
568
569/* 1280x720@50 Sync Polarity (GTF Mode) */
570#define M1280X720_R50_HSP NEGATIVE
571#define M1280X720_R50_VSP POSITIVE
572
573/* 1440x900@60 Sync Polarity (CVT Mode) */
574#define M1440X900_R60_HSP NEGATIVE
575#define M1440X900_R60_VSP POSITIVE
576
577/* 1440x900@75 Sync Polarity (CVT Mode) */
578#define M1440X900_R75_HSP NEGATIVE
579#define M1440X900_R75_VSP POSITIVE
580
581/* 1440x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
582#define M1440X900_RB_R60_HSP POSITIVE
583#define M1440X900_RB_R60_VSP NEGATIVE
584
585/* 1600x900@60 Sync Polarity (CVT Mode) */
586#define M1600X900_R60_HSP NEGATIVE
587#define M1600X900_R60_VSP POSITIVE
588
589/* 1600x900@60 Sync Polarity (CVT Reduce Blanking Mode) */
590#define M1600X900_RB_R60_HSP POSITIVE
591#define M1600X900_RB_R60_VSP NEGATIVE
592
593/* 1600x1024@60 Sync Polarity (GTF Mode) */
594#define M1600X1024_R60_HSP NEGATIVE
595#define M1600X1024_R60_VSP POSITIVE
596
597/* 1792x1344@60 Sync Polarity (DMT Mode) */
598#define M1792x1344_R60_HSP NEGATIVE
599#define M1792x1344_R60_VSP POSITIVE
600
601/* 1856x1392@60 Sync Polarity (DMT Mode) */
602#define M1856x1392_R60_HSP NEGATIVE
603#define M1856x1392_R60_VSP POSITIVE
604
605/* 1920x1200@60 Sync Polarity (CVT Mode) */
606#define M1920X1200_R60_HSP NEGATIVE
607#define M1920X1200_R60_VSP POSITIVE
608
609/* 1920x1200@60 Sync Polarity (CVT Reduce Blanking Mode) */
610#define M1920X1200_RB_R60_HSP POSITIVE
611#define M1920X1200_RB_R60_VSP NEGATIVE
612
613/* 2048x1536@60 Sync Polarity (CVT Mode) */
614#define M2048x1536_R60_HSP NEGATIVE
615#define M2048x1536_R60_VSP POSITIVE
616
617/* Definition CRTC Timing Index */ 286/* Definition CRTC Timing Index */
618#define H_TOTAL_INDEX 0 287#define H_TOTAL_INDEX 0
619#define H_ADDR_INDEX 1 288#define H_ADDR_INDEX 1
diff --git a/drivers/video/via/via_aux.c b/drivers/video/via/via_aux.c
new file mode 100644
index 000000000000..4a0a55cdac3d
--- /dev/null
+++ b/drivers/video/via/via_aux.c
@@ -0,0 +1,88 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * infrastructure for devices connected via I2C
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap)
29{
30 struct via_aux_bus *bus;
31
32 if (!adap)
33 return NULL;
34
35 bus = kmalloc(sizeof(*bus), GFP_KERNEL);
36 if (!bus)
37 return NULL;
38
39 bus->adap = adap;
40 INIT_LIST_HEAD(&bus->drivers);
41
42 via_aux_edid_probe(bus);
43 via_aux_vt1636_probe(bus);
44 via_aux_vt1632_probe(bus);
45 via_aux_vt1631_probe(bus);
46 via_aux_vt1625_probe(bus);
47 via_aux_vt1622_probe(bus);
48 via_aux_vt1621_probe(bus);
49 via_aux_sii164_probe(bus);
50 via_aux_ch7301_probe(bus);
51
52 return bus;
53}
54
55void via_aux_free(struct via_aux_bus *bus)
56{
57 struct via_aux_drv *pos, *n;
58
59 if (!bus)
60 return;
61
62 list_for_each_entry_safe(pos, n, &bus->drivers, chain) {
63 if (pos->cleanup)
64 pos->cleanup(pos);
65
66 list_del(&pos->chain);
67 kfree(pos->data);
68 kfree(pos);
69 }
70
71 kfree(bus);
72}
73
74const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus)
75{
76 struct via_aux_drv *pos;
77 const struct fb_videomode *mode = NULL;
78
79 if (!bus)
80 return NULL;
81
82 list_for_each_entry(pos, &bus->drivers, chain) {
83 if (pos->get_preferred_mode)
84 mode = pos->get_preferred_mode(pos);
85 }
86
87 return mode;
88}
diff --git a/drivers/video/via/via_aux.h b/drivers/video/via/via_aux.h
new file mode 100644
index 000000000000..a8de3f038cea
--- /dev/null
+++ b/drivers/video/via/via_aux.h
@@ -0,0 +1,93 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * infrastructure for devices connected via I2C
22 */
23
24#ifndef __VIA_AUX_H__
25#define __VIA_AUX_H__
26
27
28#include <linux/list.h>
29#include <linux/i2c.h>
30#include <linux/fb.h>
31
32
33struct via_aux_bus {
34 struct i2c_adapter *adap; /* the I2C device to access the bus */
35 struct list_head drivers; /* drivers for devices on this bus */
36};
37
38struct via_aux_drv {
39 struct list_head chain; /* chain to support multiple drivers */
40
41 struct via_aux_bus *bus; /* the I2C bus used */
42 u8 addr; /* the I2C slave address */
43
44 const char *name; /* human readable name of the driver */
45 void *data; /* private data of this driver */
46
47 void (*cleanup)(struct via_aux_drv *drv);
48 const struct fb_videomode* (*get_preferred_mode)
49 (struct via_aux_drv *drv);
50};
51
52
53struct via_aux_bus *via_aux_probe(struct i2c_adapter *adap);
54void via_aux_free(struct via_aux_bus *bus);
55const struct fb_videomode *via_aux_get_preferred_mode(struct via_aux_bus *bus);
56
57
58static inline bool via_aux_add(struct via_aux_drv *drv)
59{
60 struct via_aux_drv *data = kmalloc(sizeof(*data), GFP_KERNEL);
61
62 if (!data)
63 return false;
64
65 *data = *drv;
66 list_add_tail(&data->chain, &data->bus->drivers);
67 return true;
68}
69
70static inline bool via_aux_read(struct via_aux_drv *drv, u8 start, u8 *buf,
71 u8 len)
72{
73 struct i2c_msg msg[2] = {
74 {.addr = drv->addr, .flags = 0, .len = 1, .buf = &start},
75 {.addr = drv->addr, .flags = I2C_M_RD, .len = len, .buf = buf} };
76
77 return i2c_transfer(drv->bus->adap, msg, 2) == 2;
78}
79
80
81/* probe functions of existing drivers - should only be called in via_aux.c */
82void via_aux_ch7301_probe(struct via_aux_bus *bus);
83void via_aux_edid_probe(struct via_aux_bus *bus);
84void via_aux_sii164_probe(struct via_aux_bus *bus);
85void via_aux_vt1636_probe(struct via_aux_bus *bus);
86void via_aux_vt1632_probe(struct via_aux_bus *bus);
87void via_aux_vt1631_probe(struct via_aux_bus *bus);
88void via_aux_vt1625_probe(struct via_aux_bus *bus);
89void via_aux_vt1622_probe(struct via_aux_bus *bus);
90void via_aux_vt1621_probe(struct via_aux_bus *bus);
91
92
93#endif /* __VIA_AUX_H__ */
diff --git a/drivers/video/via/via_aux_ch7301.c b/drivers/video/via/via_aux_ch7301.c
new file mode 100644
index 000000000000..1cbe5037a6b0
--- /dev/null
+++ b/drivers/video/via/via_aux_ch7301.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for Chrontel CH7301 DVI Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "CH7301 DVI Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x4B, &tmp, 1) || tmp != 0x17)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_ch7301_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x75);
49 probe(bus, 0x76);
50}
diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/via/via_aux_edid.c
new file mode 100644
index 000000000000..754d4509033f
--- /dev/null
+++ b/drivers/video/via/via_aux_edid.c
@@ -0,0 +1,100 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * generic EDID driver
22 */
23
24#include <linux/slab.h>
25#include <linux/fb.h>
26#include "via_aux.h"
27#include "../edid.h"
28
29
30static const char *name = "EDID";
31
32
33static void query_edid(struct via_aux_drv *drv)
34{
35 struct fb_monspecs *spec = drv->data;
36 unsigned char edid[EDID_LENGTH];
37 bool valid = false;
38
39 if (spec) {
40 fb_destroy_modedb(spec->modedb);
41 } else {
42 spec = kmalloc(sizeof(*spec), GFP_KERNEL);
43 if (!spec)
44 return;
45 }
46
47 spec->version = spec->revision = 0;
48 if (via_aux_read(drv, 0x00, edid, EDID_LENGTH)) {
49 fb_edid_to_monspecs(edid, spec);
50 valid = spec->version || spec->revision;
51 }
52
53 if (!valid) {
54 kfree(spec);
55 spec = NULL;
56 } else
57 printk(KERN_DEBUG "EDID: %s %s\n", spec->manufacturer, spec->monitor);
58
59 drv->data = spec;
60}
61
62static const struct fb_videomode *get_preferred_mode(struct via_aux_drv *drv)
63{
64 struct fb_monspecs *spec = drv->data;
65 int i;
66
67 if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
68 return NULL;
69
70 for (i = 0; i < spec->modedb_len; i++) {
71 if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
72 spec->modedb[i].flag & FB_MODE_IS_DETAILED)
73 return &spec->modedb[i];
74 }
75
76 return NULL;
77}
78
79static void cleanup(struct via_aux_drv *drv)
80{
81 struct fb_monspecs *spec = drv->data;
82
83 if (spec)
84 fb_destroy_modedb(spec->modedb);
85}
86
87void via_aux_edid_probe(struct via_aux_bus *bus)
88{
89 struct via_aux_drv drv = {
90 .bus = bus,
91 .addr = 0x50,
92 .name = name,
93 .cleanup = cleanup,
94 .get_preferred_mode = get_preferred_mode};
95
96 query_edid(&drv);
97
98 /* as EDID devices can be connected/disconnected just add the driver */
99 via_aux_add(&drv);
100}
diff --git a/drivers/video/via/via_aux_sii164.c b/drivers/video/via/via_aux_sii164.c
new file mode 100644
index 000000000000..ca1b35f033b1
--- /dev/null
+++ b/drivers/video/via/via_aux_sii164.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for Silicon Image SiI 164 PanelLink Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "SiI 164 PanelLink Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x01, 0x00, 0x06, 0x00}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
45 via_aux_add(&drv);
46}
47
48void via_aux_sii164_probe(struct via_aux_bus *bus)
49{
50 u8 i;
51
52 for (i = 0x38; i <= 0x3F; i++)
53 probe(bus, i);
54}
diff --git a/drivers/video/via/via_aux_vt1621.c b/drivers/video/via/via_aux_vt1621.c
new file mode 100644
index 000000000000..38eca8479898
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1621.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1621(M) TV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1621(M) TV Encoder";
29
30
31void via_aux_vt1621_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x20,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x02)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s\n", name);
43 via_aux_add(&drv);
44}
diff --git a/drivers/video/via/via_aux_vt1622.c b/drivers/video/via/via_aux_vt1622.c
new file mode 100644
index 000000000000..8c79c68ba683
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1622.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1622(M) Digital TV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1622(M) Digital TV Encoder";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x03)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_vt1622_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x20);
49 probe(bus, 0x21);
50}
diff --git a/drivers/video/via/via_aux_vt1625.c b/drivers/video/via/via_aux_vt1625.c
new file mode 100644
index 000000000000..03eb30165d36
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1625.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1625(M) HDTV Encoder
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1625(M) HDTV Encoder";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 u8 tmp;
38
39 if (!via_aux_read(&drv, 0x1B, &tmp, 1) || tmp != 0x50)
40 return;
41
42 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
43 via_aux_add(&drv);
44}
45
46void via_aux_vt1625_probe(struct via_aux_bus *bus)
47{
48 probe(bus, 0x20);
49 probe(bus, 0x21);
50}
diff --git a/drivers/video/via/via_aux_vt1631.c b/drivers/video/via/via_aux_vt1631.c
new file mode 100644
index 000000000000..06e742f1f723
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1631.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1631 LVDS Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1631 LVDS Transmitter";
29
30
31void via_aux_vt1631_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x38,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x91, 0x31}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s\n", name);
45 via_aux_add(&drv);
46}
diff --git a/drivers/video/via/via_aux_vt1632.c b/drivers/video/via/via_aux_vt1632.c
new file mode 100644
index 000000000000..d24f4cd97401
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1632.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1632 DVI Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1632 DVI Transmitter";
29
30
31static void probe(struct via_aux_bus *bus, u8 addr)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = addr,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x92, 0x31}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s at address 0x%x\n", name, addr);
45 via_aux_add(&drv);
46}
47
48void via_aux_vt1632_probe(struct via_aux_bus *bus)
49{
50 u8 i;
51
52 for (i = 0x08; i <= 0x0F; i++)
53 probe(bus, i);
54}
diff --git a/drivers/video/via/via_aux_vt1636.c b/drivers/video/via/via_aux_vt1636.c
new file mode 100644
index 000000000000..9e015c101d4d
--- /dev/null
+++ b/drivers/video/via/via_aux_vt1636.c
@@ -0,0 +1,46 @@
1/*
2 * Copyright 2011 Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation;
7 * either version 2, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even
11 * the implied warranty of MERCHANTABILITY or FITNESS FOR
12 * A PARTICULAR PURPOSE.See the GNU General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20/*
21 * driver for VIA VT1636 LVDS Transmitter
22 */
23
24#include <linux/slab.h>
25#include "via_aux.h"
26
27
28static const char *name = "VT1636 LVDS Transmitter";
29
30
31void via_aux_vt1636_probe(struct via_aux_bus *bus)
32{
33 struct via_aux_drv drv = {
34 .bus = bus,
35 .addr = 0x40,
36 .name = name};
37 /* check vendor id and device id */
38 const u8 id[] = {0x06, 0x11, 0x45, 0x33}, len = ARRAY_SIZE(id);
39 u8 tmp[len];
40
41 if (!via_aux_read(&drv, 0x00, tmp, len) || memcmp(id, tmp, len))
42 return;
43
44 printk(KERN_INFO "viafb: Found %s\n", name);
45 via_aux_add(&drv);
46}
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 78f1405dbab7..dd53058bbbb7 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -51,7 +51,7 @@ static void via_i2c_setscl(void *data, int state)
51 val |= 0x01; 51 val |= 0x01;
52 break; 52 break;
53 case VIA_PORT_GPIO: 53 case VIA_PORT_GPIO:
54 val |= 0x80; 54 val |= 0x82;
55 break; 55 break;
56 default: 56 default:
57 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); 57 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
@@ -67,6 +67,9 @@ static int via_i2c_getscl(void *data)
67 int ret = 0; 67 int ret = 0;
68 68
69 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 69 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
70 if (adap_data->type == VIA_PORT_GPIO)
71 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
72 0, 0x80);
70 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08) 73 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x08)
71 ret = 1; 74 ret = 1;
72 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 75 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
@@ -80,6 +83,9 @@ static int via_i2c_getsda(void *data)
80 int ret = 0; 83 int ret = 0;
81 84
82 spin_lock_irqsave(&i2c_vdev->reg_lock, flags); 85 spin_lock_irqsave(&i2c_vdev->reg_lock, flags);
86 if (adap_data->type == VIA_PORT_GPIO)
87 via_write_reg_mask(adap_data->io_port, adap_data->ioport_index,
88 0, 0x40);
83 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04) 89 if (via_read_reg(adap_data->io_port, adap_data->ioport_index) & 0x04)
84 ret = 1; 90 ret = 1;
85 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); 91 spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags);
@@ -103,7 +109,7 @@ static void via_i2c_setsda(void *data, int state)
103 val |= 0x01; 109 val |= 0x01;
104 break; 110 break;
105 case VIA_PORT_GPIO: 111 case VIA_PORT_GPIO:
106 val |= 0x40; 112 val |= 0x42;
107 break; 113 break;
108 default: 114 default:
109 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n"); 115 printk(KERN_ERR "viafb_i2c: specify wrong i2c type.\n");
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index a13c258bd32f..0c8837565bc7 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/stat.h> 25#include <linux/stat.h>
26#include <linux/via-core.h> 26#include <linux/via-core.h>
27#include <linux/via_i2c.h>
27#include <asm/olpc.h> 28#include <asm/olpc.h>
28 29
29#define _MASTER_FILE 30#define _MASTER_FILE
@@ -286,26 +287,22 @@ static int viafb_set_par(struct fb_info *info)
286 viafb_second_yres, viafb_bpp1, 1); 287 viafb_second_yres, viafb_bpp1, 1);
287 } 288 }
288 289
289 refresh = viafb_get_refresh(info->var.xres, info->var.yres, 290 refresh = get_var_refresh(&info->var);
290 get_var_refresh(&info->var)); 291 if (viafb_dual_fb && viapar->iga_path == IGA2) {
291 if (viafb_get_best_mode(viafbinfo->var.xres, viafbinfo->var.yres, 292 viafb_bpp1 = info->var.bits_per_pixel;
292 refresh)) { 293 viafb_refresh1 = refresh;
293 if (viafb_dual_fb && viapar->iga_path == IGA2) { 294 } else {
294 viafb_bpp1 = info->var.bits_per_pixel; 295 viafb_bpp = info->var.bits_per_pixel;
295 viafb_refresh1 = refresh; 296 viafb_refresh = refresh;
296 } else {
297 viafb_bpp = info->var.bits_per_pixel;
298 viafb_refresh = refresh;
299 }
300
301 if (info->var.accel_flags & FB_ACCELF_TEXT)
302 info->flags &= ~FBINFO_HWACCEL_DISABLED;
303 else
304 info->flags |= FBINFO_HWACCEL_DISABLED;
305 viafb_setmode(info->var.bits_per_pixel, viafb_bpp1);
306 viafb_pan_display(&info->var, info);
307 } 297 }
308 298
299 if (info->var.accel_flags & FB_ACCELF_TEXT)
300 info->flags &= ~FBINFO_HWACCEL_DISABLED;
301 else
302 info->flags |= FBINFO_HWACCEL_DISABLED;
303 viafb_setmode();
304 viafb_pan_display(&info->var, info);
305
309 return 0; 306 return 0;
310} 307}
311 308
@@ -1670,12 +1667,23 @@ static void viafb_remove_proc(struct viafb_shared *shared)
1670} 1667}
1671#undef IS_VT1636 1668#undef IS_VT1636
1672 1669
1673static int parse_mode(const char *str, u32 *xres, u32 *yres) 1670static int parse_mode(const char *str, u32 devices, u32 *xres, u32 *yres)
1674{ 1671{
1672 const struct fb_videomode *mode = NULL;
1675 char *ptr; 1673 char *ptr;
1676 1674
1677 if (!str) { 1675 if (!str) {
1678 if (machine_is_olpc()) { 1676 if (devices == VIA_CRT)
1677 mode = via_aux_get_preferred_mode(
1678 viaparinfo->shared->i2c_26);
1679 else if (devices == VIA_DVP1)
1680 mode = via_aux_get_preferred_mode(
1681 viaparinfo->shared->i2c_31);
1682
1683 if (mode) {
1684 *xres = mode->xres;
1685 *yres = mode->yres;
1686 } else if (machine_is_olpc()) {
1679 *xres = 1200; 1687 *xres = 1200;
1680 *yres = 900; 1688 *yres = 900;
1681 } else { 1689 } else {
@@ -1729,6 +1737,31 @@ static struct viafb_pm_hooks viafb_fb_pm_hooks = {
1729 1737
1730#endif 1738#endif
1731 1739
1740static void __devinit i2c_bus_probe(struct viafb_shared *shared)
1741{
1742 /* should be always CRT */
1743 printk(KERN_INFO "viafb: Probing I2C bus 0x26\n");
1744 shared->i2c_26 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_26));
1745
1746 /* seems to be usually DVP1 */
1747 printk(KERN_INFO "viafb: Probing I2C bus 0x31\n");
1748 shared->i2c_31 = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_31));
1749
1750 /* FIXME: what is this? */
1751 if (!machine_is_olpc()) {
1752 printk(KERN_INFO "viafb: Probing I2C bus 0x2C\n");
1753 shared->i2c_2C = via_aux_probe(viafb_find_i2c_adapter(VIA_PORT_2C));
1754 }
1755
1756 printk(KERN_INFO "viafb: Finished I2C bus probing");
1757}
1758
1759static void i2c_bus_free(struct viafb_shared *shared)
1760{
1761 via_aux_free(shared->i2c_26);
1762 via_aux_free(shared->i2c_31);
1763 via_aux_free(shared->i2c_2C);
1764}
1732 1765
1733int __devinit via_fb_pci_probe(struct viafb_dev *vdev) 1766int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1734{ 1767{
@@ -1762,6 +1795,7 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1762 &viaparinfo->shared->lvds_setting_info2; 1795 &viaparinfo->shared->lvds_setting_info2;
1763 viaparinfo->chip_info = &viaparinfo->shared->chip_info; 1796 viaparinfo->chip_info = &viaparinfo->shared->chip_info;
1764 1797
1798 i2c_bus_probe(viaparinfo->shared);
1765 if (viafb_dual_fb) 1799 if (viafb_dual_fb)
1766 viafb_SAMM_ON = 1; 1800 viafb_SAMM_ON = 1;
1767 parse_lcd_port(); 1801 parse_lcd_port();
@@ -1804,10 +1838,11 @@ int __devinit via_fb_pci_probe(struct viafb_dev *vdev)
1804 viafb_second_size * 1024 * 1024; 1838 viafb_second_size * 1024 * 1024;
1805 } 1839 }
1806 1840
1807 parse_mode(viafb_mode, &default_xres, &default_yres); 1841 parse_mode(viafb_mode, viaparinfo->shared->iga1_devices,
1842 &default_xres, &default_yres);
1808 if (viafb_SAMM_ON == 1) 1843 if (viafb_SAMM_ON == 1)
1809 parse_mode(viafb_mode1, &viafb_second_xres, 1844 parse_mode(viafb_mode1, viaparinfo->shared->iga2_devices,
1810 &viafb_second_yres); 1845 &viafb_second_xres, &viafb_second_yres);
1811 1846
1812 default_var.xres = default_xres; 1847 default_var.xres = default_xres;
1813 default_var.yres = default_yres; 1848 default_var.yres = default_yres;
@@ -1915,6 +1950,7 @@ out_fb1_release:
1915 if (viafbinfo1) 1950 if (viafbinfo1)
1916 framebuffer_release(viafbinfo1); 1951 framebuffer_release(viafbinfo1);
1917out_fb_release: 1952out_fb_release:
1953 i2c_bus_free(viaparinfo->shared);
1918 framebuffer_release(viafbinfo); 1954 framebuffer_release(viafbinfo);
1919 return rc; 1955 return rc;
1920} 1956}
@@ -1927,6 +1963,7 @@ void __devexit via_fb_pci_remove(struct pci_dev *pdev)
1927 if (viafb_dual_fb) 1963 if (viafb_dual_fb)
1928 unregister_framebuffer(viafbinfo1); 1964 unregister_framebuffer(viafbinfo1);
1929 viafb_remove_proc(viaparinfo->shared); 1965 viafb_remove_proc(viaparinfo->shared);
1966 i2c_bus_free(viaparinfo->shared);
1930 framebuffer_release(viafbinfo); 1967 framebuffer_release(viafbinfo);
1931 if (viafb_dual_fb) 1968 if (viafb_dual_fb)
1932 framebuffer_release(viafbinfo1); 1969 framebuffer_release(viafbinfo1);
@@ -2033,9 +2070,9 @@ int __init viafb_init(void)
2033 if (r < 0) 2070 if (r < 0)
2034 return r; 2071 return r;
2035#endif 2072#endif
2036 if (parse_mode(viafb_mode, &dummy_x, &dummy_y) 2073 if (parse_mode(viafb_mode, 0, &dummy_x, &dummy_y)
2037 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh) 2074 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh)
2038 || parse_mode(viafb_mode1, &dummy_x, &dummy_y) 2075 || parse_mode(viafb_mode1, 0, &dummy_x, &dummy_y)
2039 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1) 2076 || !viafb_get_best_mode(dummy_x, dummy_y, viafb_refresh1)
2040 || viafb_bpp < 0 || viafb_bpp > 32 2077 || viafb_bpp < 0 || viafb_bpp > 32
2041 || viafb_bpp1 < 0 || viafb_bpp1 > 32 2078 || viafb_bpp1 < 0 || viafb_bpp1 > 32
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index d9440635d1d4..f6b2ddf56e94 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -26,6 +26,7 @@
26#include <linux/fb.h> 26#include <linux/fb.h>
27#include <linux/spinlock.h> 27#include <linux/spinlock.h>
28 28
29#include "via_aux.h"
29#include "ioctl.h" 30#include "ioctl.h"
30#include "share.h" 31#include "share.h"
31#include "chip.h" 32#include "chip.h"
@@ -48,6 +49,11 @@ struct viafb_shared {
48 struct proc_dir_entry *iga2_proc_entry; 49 struct proc_dir_entry *iga2_proc_entry;
49 struct viafb_dev *vdev; /* Global dev info */ 50 struct viafb_dev *vdev; /* Global dev info */
50 51
52 /* I2C busses that may have auxiliary devices */
53 struct via_aux_bus *i2c_26;
54 struct via_aux_bus *i2c_31;
55 struct via_aux_bus *i2c_2C;
56
51 /* All the information will be needed to set engine */ 57 /* All the information will be needed to set engine */
52 struct tmds_setting_information tmds_setting_info; 58 struct tmds_setting_information tmds_setting_info;
53 struct lvds_setting_information lvds_setting_info; 59 struct lvds_setting_information lvds_setting_info;
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 0911cac1b2ff..0666ab01cf4a 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -268,591 +268,78 @@ struct VPITTable VPIT = {
268/* Mode Table */ 268/* Mode Table */
269/********************/ 269/********************/
270 270
271/* 480x640 */ 271static const struct fb_videomode viafb_modes[] = {
272static struct crt_mode_table CRTM480x640[] = { 272 {NULL, 60, 480, 640, 40285, 72, 24, 19, 1, 48, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
273 /* r_rate, hsp, vsp */ 273 {NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, 0, 0, 0},
274 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 274 {NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, 0, 0, 0},
275 {REFRESH_60, M480X640_R60_HSP, M480X640_R60_VSP, 275 {NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, 0, 0, 0},
276 {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} } /* GTF*/ 276 {NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
277}; 277 {NULL, 120, 640, 480, 19081, 104, 40, 31, 1, 64, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
278 278 {NULL, 60, 720, 480, 37426, 88, 16, 13, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
279/* 640x480*/ 279 {NULL, 60, 720, 576, 30611, 96, 24, 17, 1, 72, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
280static struct crt_mode_table CRTM640x480[] = { 280 {NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
281 /*r_rate,hsp,vsp */ 281 {NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
282 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 282 {NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
283 {REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP, 283 {NULL, 100, 800, 600, 14667, 136, 48, 32, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
284 {800, 640, 640, 160, 656, 96, 525, 480, 480, 45, 490, 2} }, 284 {NULL, 120, 800, 600, 11911, 144, 56, 39, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
285 {REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP, 285 {NULL, 60, 800, 480, 33602, 96, 24, 10, 3, 72, 7, FB_SYNC_VERT_HIGH_ACT, 0, 0},
286 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} }, 286 {NULL, 60, 848, 480, 31565, 104, 24, 12, 3, 80, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
287 {REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP, 287 {NULL, 60, 856, 480, 31517, 104, 16, 13, 1, 88, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
288 {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} }, 288 {NULL, 60, 1024, 512, 24218, 136, 32, 15, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
289 {REFRESH_100, M640X480_R100_HSP, M640X480_R100_VSP, 289 {NULL, 60, 1024, 600, 20423, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
290 {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/ 290 {NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, 0, 0, 0},
291 {REFRESH_120, M640X480_R120_HSP, M640X480_R120_VSP, 291 {NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
292 {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481, 3} } /*GTF*/ 292 {NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
293}; 293 {NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
294 294 {NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
295/*720x480 (GTF)*/ 295 {NULL, 60, 1280, 768, 12478, 200, 64, 23, 1, 136, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
296static struct crt_mode_table CRTM720x480[] = { 296 {NULL, 50, 1280, 768, 15342, 184, 56, 19, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
297 /*r_rate,hsp,vsp */ 297 {NULL, 60, 960, 600, 21964, 128, 32, 15, 3, 96, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
298 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 298 {NULL, 60, 1000, 600, 20803, 144, 40, 18, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
299 {REFRESH_60, M720X480_R60_HSP, M720X480_R60_VSP, 299 {NULL, 60, 1024, 576, 21278, 144, 40, 17, 1, 104, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
300 {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} } 300 {NULL, 60, 1088, 612, 18825, 152, 48, 16, 3, 104, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
301 301 {NULL, 60, 1152, 720, 14974, 168, 56, 19, 3, 112, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
302}; 302 {NULL, 60, 1200, 720, 14248, 184, 56, 22, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
303 303 {NULL, 49, 1200, 900, 17703, 21, 11, 1, 1, 32, 10, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
304/*720x576 (GTF)*/ 304 {NULL, 60, 1280, 600, 16259, 184, 56, 18, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
305static struct crt_mode_table CRTM720x576[] = { 305 {NULL, 60, 1280, 800, 11938, 200, 72, 22, 3, 128, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
306 /*r_rate,hsp,vsp */ 306 {NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
307 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 307 {NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
308 {REFRESH_60, M720X576_R60_HSP, M720X576_R60_VSP, 308 {NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
309 {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} } 309 {NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
310}; 310 {NULL, 60, 1360, 768, 11759, 208, 72, 22, 3, 136, 5, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
311 311 {NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
312/* 800x480 (CVT) */ 312 {NULL, 50, 1368, 768, 14301, 200, 56, 19, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
313static struct crt_mode_table CRTM800x480[] = { 313 {NULL, 60, 1368, 768, 11646, 216, 72, 23, 1, 144, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
314 /* r_rate, hsp, vsp */ 314 {NULL, 60, 1440, 900, 9372, 232, 80, 25, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
315 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 315 {NULL, 75, 1440, 900, 7311, 248, 96, 33, 3, 152, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
316 {REFRESH_60, M800X480_R60_HSP, M800X480_R60_VSP, 316 {NULL, 60, 1440, 1040, 7993, 248, 96, 33, 1, 152, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
317 {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} } 317 {NULL, 60, 1600, 900, 8449, 256, 88, 26, 3, 168, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
318}; 318 {NULL, 60, 1600, 1024, 7333, 272, 104, 32, 1, 168, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
319 319 {NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
320/* 800x600*/ 320 {NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 0, 0},
321static struct crt_mode_table CRTM800x600[] = { 321 {NULL, 60, 1680, 1050, 6832, 280, 104, 30, 3, 176, 6, 0, 0, 0},
322 /*r_rate,hsp,vsp */ 322 {NULL, 75, 1680, 1050, 5339, 296, 120, 40, 3, 176, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
323 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 323 {NULL, 60, 1792, 1344, 4883, 328, 128, 46, 1, 200, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
324 {REFRESH_60, M800X600_R60_HSP, M800X600_R60_VSP, 324 {NULL, 60, 1856, 1392, 4581, 352, 96, 43, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
325 {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} }, 325 {NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
326 {REFRESH_75, M800X600_R75_HSP, M800X600_R75_VSP, 326 {NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
327 {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} }, 327 {NULL, 60, 2048, 1536, 3738, 376, 152, 49, 3, 224, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
328 {REFRESH_85, M800X600_R85_HSP, M800X600_R85_VSP, 328 {NULL, 60, 1280, 720, 13484, 216, 112, 20, 5, 40, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
329 {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} }, 329 {NULL, 50, 1280, 720, 16538, 176, 48, 17, 1, 128, 3, FB_SYNC_VERT_HIGH_ACT, 0, 0},
330 {REFRESH_100, M800X600_R100_HSP, M800X600_R100_VSP, 330 {NULL, 60, 1920, 1080, 5776, 328, 128, 32, 3, 200, 5, FB_SYNC_VERT_HIGH_ACT, 0, 0},
331 {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} }, 331 {NULL, 60, 1920, 1200, 5164, 336, 136, 36, 3, 200, 6, FB_SYNC_VERT_HIGH_ACT, 0, 0},
332 {REFRESH_120, M800X600_R120_HSP, M800X600_R120_VSP, 332 {NULL, 60, 1400, 1050, 8210, 232, 88, 32, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0},
333 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601, 3} } 333 {NULL, 75, 1400, 1050, 6398, 248, 104, 42, 3, 144, 4, FB_SYNC_VERT_HIGH_ACT, 0, 0} };
334}; 334
335 335static const struct fb_videomode viafb_rb_modes[] = {
336/* 848x480 (CVT) */ 336 {NULL, 60, 1360, 768, 13879, 80, 48, 14, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
337static struct crt_mode_table CRTM848x480[] = { 337 {NULL, 60, 1440, 900, 11249, 80, 48, 17, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
338 /* r_rate, hsp, vsp */ 338 {NULL, 60, 1400, 1050, 9892, 80, 48, 23, 3, 32, 4, FB_SYNC_HOR_HIGH_ACT, 0, 0},
339 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */ 339 {NULL, 60, 1600, 900, 10226, 80, 48, 18, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
340 {REFRESH_60, M848X480_R60_HSP, M848X480_R60_VSP, 340 {NULL, 60, 1680, 1050, 8387, 80, 48, 21, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0},
341 {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} } 341 {NULL, 60, 1920, 1080, 7212, 80, 48, 23, 3, 32, 5, FB_SYNC_HOR_HIGH_ACT, 0, 0},
342}; 342 {NULL, 60, 1920, 1200, 6488, 80, 48, 26, 3, 32, 6, FB_SYNC_HOR_HIGH_ACT, 0, 0} };
343
344/*856x480 (GTF) convert to 852x480*/
345static struct crt_mode_table CRTM852x480[] = {
346 /*r_rate,hsp,vsp */
347 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
348 {REFRESH_60, M852X480_R60_HSP, M852X480_R60_VSP,
349 {1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
350};
351
352/*1024x512 (GTF)*/
353static struct crt_mode_table CRTM1024x512[] = {
354 /*r_rate,hsp,vsp */
355 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
356 {REFRESH_60, M1024X512_R60_HSP, M1024X512_R60_VSP,
357 {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
358
359};
360
361/* 1024x600*/
362static struct crt_mode_table CRTM1024x600[] = {
363 /*r_rate,hsp,vsp */
364 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
365 {REFRESH_60, M1024X600_R60_HSP, M1024X600_R60_VSP,
366 {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
367};
368
369/* 1024x768*/
370static struct crt_mode_table CRTM1024x768[] = {
371 /*r_rate,hsp,vsp */
372 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
373 {REFRESH_60, M1024X768_R60_HSP, M1024X768_R60_VSP,
374 {1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
375 {REFRESH_75, M1024X768_R75_HSP, M1024X768_R75_VSP,
376 {1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
377 {REFRESH_85, M1024X768_R85_HSP, M1024X768_R85_VSP,
378 {1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
379 {REFRESH_100, M1024X768_R100_HSP, M1024X768_R100_VSP,
380 {1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
381};
382
383/* 1152x864*/
384static struct crt_mode_table CRTM1152x864[] = {
385 /*r_rate,hsp,vsp */
386 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
387 {REFRESH_75, M1152X864_R75_HSP, M1152X864_R75_VSP,
388 {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
389
390};
391
392/* 1280x720 (HDMI 720P)*/
393static struct crt_mode_table CRTM1280x720[] = {
394 /*r_rate,hsp,vsp */
395 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
396 {REFRESH_60, M1280X720_R60_HSP, M1280X720_R60_VSP,
397 {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
398 {REFRESH_50, M1280X720_R50_HSP, M1280X720_R50_VSP,
399 {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
400};
401
402/*1280x768 (GTF)*/
403static struct crt_mode_table CRTM1280x768[] = {
404 /*r_rate,hsp,vsp */
405 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
406 {REFRESH_60, M1280X768_R60_HSP, M1280X768_R60_VSP,
407 {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
408 {REFRESH_50, M1280X768_R50_HSP, M1280X768_R50_VSP,
409 {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
410};
411
412/* 1280x800 (CVT) */
413static struct crt_mode_table CRTM1280x800[] = {
414 /* r_rate, hsp, vsp */
415 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
416 {REFRESH_60, M1280X800_R60_HSP, M1280X800_R60_VSP,
417 {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
418};
419
420/*1280x960*/
421static struct crt_mode_table CRTM1280x960[] = {
422 /*r_rate,hsp,vsp */
423 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
424 {REFRESH_60, M1280X960_R60_HSP, M1280X960_R60_VSP,
425 {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
426};
427
428/* 1280x1024*/
429static struct crt_mode_table CRTM1280x1024[] = {
430 /*r_rate,hsp,vsp */
431 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
432 {REFRESH_60, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
433 {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
434 3} },
435 {REFRESH_75, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
436 {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
437 3} },
438 {REFRESH_85, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
439 {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
440};
441
442/* 1368x768 (GTF) */
443static struct crt_mode_table CRTM1368x768[] = {
444 /* r_rate, hsp, vsp */
445 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
446 {REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
447 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
448};
449
450/*1440x1050 (GTF)*/
451static struct crt_mode_table CRTM1440x1050[] = {
452 /*r_rate,hsp,vsp */
453 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
454 {REFRESH_60, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
455 {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
456};
457
458/* 1600x1200*/
459static struct crt_mode_table CRTM1600x1200[] = {
460 /*r_rate,hsp,vsp */
461 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
462 {REFRESH_60, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
463 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
464 3} },
465 {REFRESH_75, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
466 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
467
468};
469
470/* 1680x1050 (CVT) */
471static struct crt_mode_table CRTM1680x1050[] = {
472 /* r_rate, hsp, vsp */
473 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
474 {REFRESH_60, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
475 {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
476 6} },
477 {REFRESH_75, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
478 {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
479};
480
481/* 1680x1050 (CVT Reduce Blanking) */
482static struct crt_mode_table CRTM1680x1050_RB[] = {
483 /* r_rate, hsp, vsp */
484 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
485 {REFRESH_60, M1680x1050_RB_R60_HSP, M1680x1050_RB_R60_VSP,
486 {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
487};
488
489/* 1920x1080 (CVT)*/
490static struct crt_mode_table CRTM1920x1080[] = {
491 /*r_rate,hsp,vsp */
492 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
493 {REFRESH_60, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
494 {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
495};
496
497/* 1920x1080 (CVT with Reduce Blanking) */
498static struct crt_mode_table CRTM1920x1080_RB[] = {
499 /* r_rate, hsp, vsp */
500 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
501 {REFRESH_60, M1920X1080_RB_R60_HSP, M1920X1080_RB_R60_VSP,
502 {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
503};
504
505/* 1920x1440*/
506static struct crt_mode_table CRTM1920x1440[] = {
507 /*r_rate,hsp,vsp */
508 /*HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
509 {REFRESH_60, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
510 {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
511 3} },
512 {REFRESH_75, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
513 {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
514};
515
516/* 1400x1050 (CVT) */
517static struct crt_mode_table CRTM1400x1050[] = {
518 /* r_rate, hsp, vsp */
519 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
520 {REFRESH_60, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
521 {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
522 4} },
523 {REFRESH_75, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
524 {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
525};
526
527/* 1400x1050 (CVT Reduce Blanking) */
528static struct crt_mode_table CRTM1400x1050_RB[] = {
529 /* r_rate, hsp, vsp */
530 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
531 {REFRESH_60, M1400X1050_RB_R60_HSP, M1400X1050_RB_R60_VSP,
532 {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
533};
534
535/* 960x600 (CVT) */
536static struct crt_mode_table CRTM960x600[] = {
537 /* r_rate, hsp, vsp */
538 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
539 {REFRESH_60, M960X600_R60_HSP, M960X600_R60_VSP,
540 {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
541};
542
543/* 1000x600 (GTF) */
544static struct crt_mode_table CRTM1000x600[] = {
545 /* r_rate, hsp, vsp */
546 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
547 {REFRESH_60, M1000X600_R60_HSP, M1000X600_R60_VSP,
548 {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
549};
550
551/* 1024x576 (GTF) */
552static struct crt_mode_table CRTM1024x576[] = {
553 /* r_rate, hsp, vsp */
554 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
555 {REFRESH_60, M1024X576_R60_HSP, M1024X576_R60_VSP,
556 {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
557};
558
559/* 1088x612 (CVT) */
560static struct crt_mode_table CRTM1088x612[] = {
561 /* r_rate, hsp, vsp */
562 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
563 {REFRESH_60, M1088X612_R60_HSP, M1088X612_R60_VSP,
564 {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
565};
566
567/* 1152x720 (CVT) */
568static struct crt_mode_table CRTM1152x720[] = {
569 /* r_rate, hsp, vsp */
570 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
571 {REFRESH_60, M1152X720_R60_HSP, M1152X720_R60_VSP,
572 {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
573};
574
575/* 1200x720 (GTF) */
576static struct crt_mode_table CRTM1200x720[] = {
577 /* r_rate, hsp, vsp */
578 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
579 {REFRESH_60, M1200X720_R60_HSP, M1200X720_R60_VSP,
580 {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
581};
582
583/* 1200x900 (DCON) */
584static struct crt_mode_table DCON1200x900[] = {
585 /* r_rate, hsp, vsp */
586 {REFRESH_49, M1200X900_R60_HSP, M1200X900_R60_VSP,
587 /* The correct htotal is 1240, but this doesn't raster on VX855. */
588 /* Via suggested changing to a multiple of 16, hence 1264. */
589 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
590 {1264, 1200, 1200, 64, 1211, 32, 912, 900, 900, 12, 901, 10} }
591};
592
593/* 1280x600 (GTF) */
594static struct crt_mode_table CRTM1280x600[] = {
595 /* r_rate, hsp, vsp */
596 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
597 {REFRESH_60, M1280x600_R60_HSP, M1280x600_R60_VSP,
598 {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
599};
600
601/* 1360x768 (CVT) */
602static struct crt_mode_table CRTM1360x768[] = {
603 /* r_rate, hsp, vsp */
604 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
605 {REFRESH_60, M1360X768_R60_HSP, M1360X768_R60_VSP,
606 {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
607};
608
609/* 1360x768 (CVT Reduce Blanking) */
610static struct crt_mode_table CRTM1360x768_RB[] = {
611 /* r_rate, hsp, vsp */
612 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
613 {REFRESH_60, M1360X768_RB_R60_HSP, M1360X768_RB_R60_VSP,
614 {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
615};
616
617/* 1366x768 (GTF) */
618static struct crt_mode_table CRTM1366x768[] = {
619 /* r_rate, hsp, vsp */
620 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
621 {REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
622 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
623 {REFRESH_50, M1368X768_R50_HSP, M1368X768_R50_VSP,
624 {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
625};
626
627/* 1440x900 (CVT) */
628static struct crt_mode_table CRTM1440x900[] = {
629 /* r_rate, hsp, vsp */
630 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
631 {REFRESH_60, M1440X900_R60_HSP, M1440X900_R60_VSP,
632 {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
633 {REFRESH_75, M1440X900_R75_HSP, M1440X900_R75_VSP,
634 {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
635};
636
637/* 1440x900 (CVT Reduce Blanking) */
638static struct crt_mode_table CRTM1440x900_RB[] = {
639 /* r_rate, hsp, vsp */
640 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
641 {REFRESH_60, M1440X900_RB_R60_HSP, M1440X900_RB_R60_VSP,
642 {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
643};
644
645/* 1600x900 (CVT) */
646static struct crt_mode_table CRTM1600x900[] = {
647 /* r_rate, hsp, vsp */
648 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
649 {REFRESH_60, M1600X900_R60_HSP, M1600X900_R60_VSP,
650 {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
651};
652
653/* 1600x900 (CVT Reduce Blanking) */
654static struct crt_mode_table CRTM1600x900_RB[] = {
655 /* r_rate, hsp, vsp */
656 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
657 {REFRESH_60, M1600X900_RB_R60_HSP, M1600X900_RB_R60_VSP,
658 {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
659};
660
661/* 1600x1024 (GTF) */
662static struct crt_mode_table CRTM1600x1024[] = {
663 /* r_rate, hsp, vsp */
664 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
665 {REFRESH_60, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
666 {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
667};
668
669/* 1792x1344 (DMT) */
670static struct crt_mode_table CRTM1792x1344[] = {
671 /* r_rate, hsp, vsp */
672 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
673 {REFRESH_60, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
674 {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
675};
676
677/* 1856x1392 (DMT) */
678static struct crt_mode_table CRTM1856x1392[] = {
679 /* r_rate, hsp, vsp */
680 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
681 {REFRESH_60, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
682 {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
683};
684
685/* 1920x1200 (CVT) */
686static struct crt_mode_table CRTM1920x1200[] = {
687 /* r_rate, hsp, vsp */
688 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
689 {REFRESH_60, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
690 {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
691};
692
693/* 1920x1200 (CVT with Reduce Blanking) */
694static struct crt_mode_table CRTM1920x1200_RB[] = {
695 /* r_rate, hsp, vsp */
696 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
697 {REFRESH_60, M1920X1200_RB_R60_HSP, M1920X1200_RB_R60_VSP,
698 {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
699};
700
701/* 2048x1536 (CVT) */
702static struct crt_mode_table CRTM2048x1536[] = {
703 /* r_rate, hsp, vsp */
704 /* HT, HA, HBS, HBE, HSS, HSE, VT, VA, VBS, VBE, VSS, VSE */
705 {REFRESH_60, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
706 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
707};
708
709static struct VideoModeTable viafb_modes[] = {
710 /* Display : 480x640 (GTF) */
711 {CRTM480x640, ARRAY_SIZE(CRTM480x640)},
712
713 /* Display : 640x480 */
714 {CRTM640x480, ARRAY_SIZE(CRTM640x480)},
715
716 /* Display : 720x480 (GTF) */
717 {CRTM720x480, ARRAY_SIZE(CRTM720x480)},
718
719 /* Display : 720x576 (GTF) */
720 {CRTM720x576, ARRAY_SIZE(CRTM720x576)},
721
722 /* Display : 800x600 */
723 {CRTM800x600, ARRAY_SIZE(CRTM800x600)},
724
725 /* Display : 800x480 (CVT) */
726 {CRTM800x480, ARRAY_SIZE(CRTM800x480)},
727
728 /* Display : 848x480 (CVT) */
729 {CRTM848x480, ARRAY_SIZE(CRTM848x480)},
730
731 /* Display : 852x480 (GTF) */
732 {CRTM852x480, ARRAY_SIZE(CRTM852x480)},
733
734 /* Display : 1024x512 (GTF) */
735 {CRTM1024x512, ARRAY_SIZE(CRTM1024x512)},
736
737 /* Display : 1024x600 */
738 {CRTM1024x600, ARRAY_SIZE(CRTM1024x600)},
739
740 /* Display : 1024x768 */
741 {CRTM1024x768, ARRAY_SIZE(CRTM1024x768)},
742
743 /* Display : 1152x864 */
744 {CRTM1152x864, ARRAY_SIZE(CRTM1152x864)},
745
746 /* Display : 1280x768 (GTF) */
747 {CRTM1280x768, ARRAY_SIZE(CRTM1280x768)},
748
749 /* Display : 960x600 (CVT) */
750 {CRTM960x600, ARRAY_SIZE(CRTM960x600)},
751
752 /* Display : 1000x600 (GTF) */
753 {CRTM1000x600, ARRAY_SIZE(CRTM1000x600)},
754
755 /* Display : 1024x576 (GTF) */
756 {CRTM1024x576, ARRAY_SIZE(CRTM1024x576)},
757
758 /* Display : 1088x612 (GTF) */
759 {CRTM1088x612, ARRAY_SIZE(CRTM1088x612)},
760
761 /* Display : 1152x720 (CVT) */
762 {CRTM1152x720, ARRAY_SIZE(CRTM1152x720)},
763
764 /* Display : 1200x720 (GTF) */
765 {CRTM1200x720, ARRAY_SIZE(CRTM1200x720)},
766
767 /* Display : 1200x900 (DCON) */
768 {DCON1200x900, ARRAY_SIZE(DCON1200x900)},
769
770 /* Display : 1280x600 (GTF) */
771 {CRTM1280x600, ARRAY_SIZE(CRTM1280x600)},
772
773 /* Display : 1280x800 (CVT) */
774 {CRTM1280x800, ARRAY_SIZE(CRTM1280x800)},
775
776 /* Display : 1280x960 */
777 {CRTM1280x960, ARRAY_SIZE(CRTM1280x960)},
778
779 /* Display : 1280x1024 */
780 {CRTM1280x1024, ARRAY_SIZE(CRTM1280x1024)},
781
782 /* Display : 1360x768 (CVT) */
783 {CRTM1360x768, ARRAY_SIZE(CRTM1360x768)},
784
785 /* Display : 1366x768 */
786 {CRTM1366x768, ARRAY_SIZE(CRTM1366x768)},
787
788 /* Display : 1368x768 (GTF) */
789 {CRTM1368x768, ARRAY_SIZE(CRTM1368x768)},
790
791 /* Display : 1440x900 (CVT) */
792 {CRTM1440x900, ARRAY_SIZE(CRTM1440x900)},
793
794 /* Display : 1440x1050 (GTF) */
795 {CRTM1440x1050, ARRAY_SIZE(CRTM1440x1050)},
796
797 /* Display : 1600x900 (CVT) */
798 {CRTM1600x900, ARRAY_SIZE(CRTM1600x900)},
799
800 /* Display : 1600x1024 (GTF) */
801 {CRTM1600x1024, ARRAY_SIZE(CRTM1600x1024)},
802
803 /* Display : 1600x1200 */
804 {CRTM1600x1200, ARRAY_SIZE(CRTM1600x1200)},
805
806 /* Display : 1680x1050 (CVT) */
807 {CRTM1680x1050, ARRAY_SIZE(CRTM1680x1050)},
808
809 /* Display : 1792x1344 (DMT) */
810 {CRTM1792x1344, ARRAY_SIZE(CRTM1792x1344)},
811
812 /* Display : 1856x1392 (DMT) */
813 {CRTM1856x1392, ARRAY_SIZE(CRTM1856x1392)},
814
815 /* Display : 1920x1440 */
816 {CRTM1920x1440, ARRAY_SIZE(CRTM1920x1440)},
817
818 /* Display : 2048x1536 */
819 {CRTM2048x1536, ARRAY_SIZE(CRTM2048x1536)},
820
821 /* Display : 1280x720 */
822 {CRTM1280x720, ARRAY_SIZE(CRTM1280x720)},
823
824 /* Display : 1920x1080 (CVT) */
825 {CRTM1920x1080, ARRAY_SIZE(CRTM1920x1080)},
826
827 /* Display : 1920x1200 (CVT) */
828 {CRTM1920x1200, ARRAY_SIZE(CRTM1920x1200)},
829
830 /* Display : 1400x1050 (CVT) */
831 {CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
832};
833
834static struct VideoModeTable viafb_rb_modes[] = {
835 /* Display : 1360x768 (CVT Reduce Blanking) */
836 {CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)},
837
838 /* Display : 1440x900 (CVT Reduce Blanking) */
839 {CRTM1440x900_RB, ARRAY_SIZE(CRTM1440x900_RB)},
840
841 /* Display : 1400x1050 (CVT Reduce Blanking) */
842 {CRTM1400x1050_RB, ARRAY_SIZE(CRTM1400x1050_RB)},
843
844 /* Display : 1600x900 (CVT Reduce Blanking) */
845 {CRTM1600x900_RB, ARRAY_SIZE(CRTM1600x900_RB)},
846
847 /* Display : 1680x1050 (CVT Reduce Blanking) */
848 {CRTM1680x1050_RB, ARRAY_SIZE(CRTM1680x1050_RB)},
849
850 /* Display : 1920x1080 (CVT Reduce Blanking) */
851 {CRTM1920x1080_RB, ARRAY_SIZE(CRTM1920x1080_RB)},
852
853 /* Display : 1920x1200 (CVT Reduce Blanking) */
854 {CRTM1920x1200_RB, ARRAY_SIZE(CRTM1920x1200_RB)}
855};
856 343
857int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs); 344int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
858int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs); 345int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
@@ -863,56 +350,34 @@ int NUM_TOTAL_CLE266_ModeXregs = ARRAY_SIZE(CLE266_ModeXregs);
863int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table); 350int NUM_TOTAL_PATCH_MODE = ARRAY_SIZE(res_patch_table);
864 351
865 352
866static struct VideoModeTable *get_modes(struct VideoModeTable *vmt, int n, 353static const struct fb_videomode *get_best_mode(
867 int hres, int vres) 354 const struct fb_videomode *modes, int n,
868{ 355 int hres, int vres, int refresh)
869 int i;
870
871 for (i = 0; i < n; i++)
872 if (vmt[i].mode_array &&
873 vmt[i].crtc[0].crtc.hor_addr == hres &&
874 vmt[i].crtc[0].crtc.ver_addr == vres)
875 return &viafb_modes[i];
876
877 return NULL;
878}
879
880static struct crt_mode_table *get_best_mode(struct VideoModeTable *vmt,
881 int refresh)
882{ 356{
883 struct crt_mode_table *best; 357 const struct fb_videomode *best = NULL;
884 int i; 358 int i;
885 359
886 if (!vmt) 360 for (i = 0; i < n; i++) {
887 return NULL; 361 if (modes[i].xres != hres || modes[i].yres != vres)
362 continue;
888 363
889 best = &vmt->crtc[0]; 364 if (!best || abs(modes[i].refresh - refresh) <
890 for (i = 1; i < vmt->mode_array; i++) { 365 abs(best->refresh - refresh))
891 if (abs(vmt->crtc[i].refresh_rate - refresh) 366 best = &modes[i];
892 < abs(best->refresh_rate - refresh))
893 best = &vmt->crtc[i];
894 } 367 }
895 368
896 return best; 369 return best;
897} 370}
898 371
899static struct VideoModeTable *viafb_get_mode(int hres, int vres) 372const struct fb_videomode *viafb_get_best_mode(int hres, int vres, int refresh)
900{
901 return get_modes(viafb_modes, ARRAY_SIZE(viafb_modes), hres, vres);
902}
903
904struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh)
905{ 373{
906 return get_best_mode(viafb_get_mode(hres, vres), refresh); 374 return get_best_mode(viafb_modes, ARRAY_SIZE(viafb_modes),
375 hres, vres, refresh);
907} 376}
908 377
909static struct VideoModeTable *viafb_get_rb_mode(int hres, int vres) 378const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
910{ 379 int refresh)
911 return get_modes(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes), hres,
912 vres);
913}
914
915struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh)
916{ 380{
917 return get_best_mode(viafb_get_rb_mode(hres, vres), refresh); 381 return get_best_mode(viafb_rb_modes, ARRAY_SIZE(viafb_rb_modes),
382 hres, vres, refresh);
918} 383}
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 5917a2b00e1b..dd19106698e7 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -31,11 +31,6 @@ struct VPITTable {
31 unsigned char AR[StdAR]; 31 unsigned char AR[StdAR];
32}; 32};
33 33
34struct VideoModeTable {
35 struct crt_mode_table *crtc;
36 int mode_array;
37};
38
39struct patch_table { 34struct patch_table {
40 int table_length; 35 int table_length;
41 struct io_reg *io_reg_table; 36 struct io_reg *io_reg_table;
@@ -60,7 +55,9 @@ extern struct io_reg PM1024x768[];
60extern struct patch_table res_patch_table[]; 55extern struct patch_table res_patch_table[];
61extern struct VPITTable VPIT; 56extern struct VPITTable VPIT;
62 57
63struct crt_mode_table *viafb_get_best_mode(int hres, int vres, int refresh); 58const struct fb_videomode *viafb_get_best_mode(int hres, int vres,
64struct crt_mode_table *viafb_get_best_rb_mode(int hres, int vres, int refresh); 59 int refresh);
60const struct fb_videomode *viafb_get_best_rb_mode(int hres, int vres,
61 int refresh);
65 62
66#endif /* __VIAMODE_H__ */ 63#endif /* __VIAMODE_H__ */
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c18122f40543..a395b8c76992 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1003,6 +1003,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
1003/* drivers/video/fbmem.c */ 1003/* drivers/video/fbmem.c */
1004extern int register_framebuffer(struct fb_info *fb_info); 1004extern int register_framebuffer(struct fb_info *fb_info);
1005extern int unregister_framebuffer(struct fb_info *fb_info); 1005extern int unregister_framebuffer(struct fb_info *fb_info);
1006extern int unlink_framebuffer(struct fb_info *fb_info);
1006extern void remove_conflicting_framebuffers(struct apertures_struct *a, 1007extern void remove_conflicting_framebuffers(struct apertures_struct *a,
1007 const char *name, bool primary); 1008 const char *name, bool primary);
1008extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); 1009extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h
new file mode 100644
index 000000000000..8847a9d6dd42
--- /dev/null
+++ b/include/video/exynos_dp.h
@@ -0,0 +1,131 @@
1/*
2 * Samsung SoC DP device support
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_DP_H
13#define _EXYNOS_DP_H
14
15#define DP_TIMEOUT_LOOP_COUNT 100
16#define MAX_CR_LOOP 5
17#define MAX_EQ_LOOP 4
18
19enum link_rate_type {
20 LINK_RATE_1_62GBPS = 0x06,
21 LINK_RATE_2_70GBPS = 0x0a
22};
23
24enum link_lane_count_type {
25 LANE_COUNT1 = 1,
26 LANE_COUNT2 = 2,
27 LANE_COUNT4 = 4
28};
29
30enum link_training_state {
31 START,
32 CLOCK_RECOVERY,
33 EQUALIZER_TRAINING,
34 FINISHED,
35 FAILED
36};
37
38enum voltage_swing_level {
39 VOLTAGE_LEVEL_0,
40 VOLTAGE_LEVEL_1,
41 VOLTAGE_LEVEL_2,
42 VOLTAGE_LEVEL_3,
43};
44
45enum pre_emphasis_level {
46 PRE_EMPHASIS_LEVEL_0,
47 PRE_EMPHASIS_LEVEL_1,
48 PRE_EMPHASIS_LEVEL_2,
49 PRE_EMPHASIS_LEVEL_3,
50};
51
52enum pattern_set {
53 PRBS7,
54 D10_2,
55 TRAINING_PTN1,
56 TRAINING_PTN2,
57 DP_NONE
58};
59
60enum color_space {
61 COLOR_RGB,
62 COLOR_YCBCR422,
63 COLOR_YCBCR444
64};
65
66enum color_depth {
67 COLOR_6,
68 COLOR_8,
69 COLOR_10,
70 COLOR_12
71};
72
73enum color_coefficient {
74 COLOR_YCBCR601,
75 COLOR_YCBCR709
76};
77
78enum dynamic_range {
79 VESA,
80 CEA
81};
82
83enum pll_status {
84 PLL_UNLOCKED,
85 PLL_LOCKED
86};
87
88enum clock_recovery_m_value_type {
89 CALCULATED_M,
90 REGISTER_M
91};
92
93enum video_timing_recognition_type {
94 VIDEO_TIMING_FROM_CAPTURE,
95 VIDEO_TIMING_FROM_REGISTER
96};
97
98enum analog_power_block {
99 AUX_BLOCK,
100 CH0_BLOCK,
101 CH1_BLOCK,
102 CH2_BLOCK,
103 CH3_BLOCK,
104 ANALOG_TOTAL,
105 POWER_ALL
106};
107
108struct video_info {
109 char *name;
110
111 bool h_sync_polarity;
112 bool v_sync_polarity;
113 bool interlaced;
114
115 enum color_space color_space;
116 enum dynamic_range dynamic_range;
117 enum color_coefficient ycbcr_coeff;
118 enum color_depth color_depth;
119
120 enum link_rate_type link_rate;
121 enum link_lane_count_type lane_count;
122};
123
124struct exynos_dp_platdata {
125 struct video_info *video_info;
126
127 void (*phy_init)(void);
128 void (*phy_exit)(void);
129};
130
131#endif /* _EXYNOS_DP_H */
diff --git a/include/video/exynos_mipi_dsim.h b/include/video/exynos_mipi_dsim.h
new file mode 100644
index 000000000000..772c770535f1
--- /dev/null
+++ b/include/video/exynos_mipi_dsim.h
@@ -0,0 +1,359 @@
1/* include/video/exynos_mipi_dsim.h
2 *
3 * Platform data header for Samsung SoC MIPI-DSIM.
4 *
5 * Copyright (c) 2012 Samsung Electronics Co., Ltd
6 *
7 * InKi Dae <inki.dae@samsung.com>
8 * Donghwa Lee <dh09.lee@samsung.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#ifndef _EXYNOS_MIPI_DSIM_H
16#define _EXYNOS_MIPI_DSIM_H
17
18#include <linux/device.h>
19#include <linux/fb.h>
20
21#define PANEL_NAME_SIZE (32)
22
23/*
24 * Enumerate display interface type.
25 *
26 * DSIM_COMMAND means cpu interface and rgb interface for DSIM_VIDEO.
27 *
28 * P.S. MIPI DSI Master has two display controller intefaces, RGB Interface
29 * for main display and CPU Interface(same as I80 Interface) for main
30 * and sub display.
31 */
32enum mipi_dsim_interface_type {
33 DSIM_COMMAND,
34 DSIM_VIDEO
35};
36
37enum mipi_dsim_virtual_ch_no {
38 DSIM_VIRTUAL_CH_0,
39 DSIM_VIRTUAL_CH_1,
40 DSIM_VIRTUAL_CH_2,
41 DSIM_VIRTUAL_CH_3
42};
43
44enum mipi_dsim_burst_mode_type {
45 DSIM_NON_BURST_SYNC_EVENT,
46 DSIM_BURST_SYNC_EVENT,
47 DSIM_NON_BURST_SYNC_PULSE,
48 DSIM_BURST,
49 DSIM_NON_VIDEO_MODE
50};
51
52enum mipi_dsim_no_of_data_lane {
53 DSIM_DATA_LANE_1,
54 DSIM_DATA_LANE_2,
55 DSIM_DATA_LANE_3,
56 DSIM_DATA_LANE_4
57};
58
59enum mipi_dsim_byte_clk_src {
60 DSIM_PLL_OUT_DIV8,
61 DSIM_EXT_CLK_DIV8,
62 DSIM_EXT_CLK_BYPASS
63};
64
65enum mipi_dsim_pixel_format {
66 DSIM_CMD_3BPP,
67 DSIM_CMD_8BPP,
68 DSIM_CMD_12BPP,
69 DSIM_CMD_16BPP,
70 DSIM_VID_16BPP_565,
71 DSIM_VID_18BPP_666PACKED,
72 DSIM_18BPP_666LOOSELYPACKED,
73 DSIM_24BPP_888
74};
75
76/*
77 * struct mipi_dsim_config - interface for configuring mipi-dsi controller.
78 *
79 * @auto_flush: enable or disable Auto flush of MD FIFO using VSYNC pulse.
80 * @eot_disable: enable or disable EoT packet in HS mode.
81 * @auto_vertical_cnt: specifies auto vertical count mode.
82 * in Video mode, the vertical line transition uses line counter
83 * configured by VSA, VBP, and Vertical resolution.
84 * If this bit is set to '1', the line counter does not use VSA and VBP
85 * registers.(in command mode, this variable is ignored)
86 * @hse: set horizontal sync event mode.
87 * In VSYNC pulse and Vporch area, MIPI DSI master transfers only HSYNC
88 * start packet to MIPI DSI slave at MIPI DSI spec1.1r02.
89 * this bit transfers HSYNC end packet in VSYNC pulse and Vporch area
90 * (in mommand mode, this variable is ignored)
91 * @hfp: specifies HFP disable mode.
92 * if this variable is set, DSI master ignores HFP area in VIDEO mode.
93 * (in command mode, this variable is ignored)
94 * @hbp: specifies HBP disable mode.
95 * if this variable is set, DSI master ignores HBP area in VIDEO mode.
96 * (in command mode, this variable is ignored)
97 * @hsa: specifies HSA disable mode.
98 * if this variable is set, DSI master ignores HSA area in VIDEO mode.
99 * (in command mode, this variable is ignored)
100 * @cma_allow: specifies the number of horizontal lines, where command packet
101 * transmission is allowed after Stable VFP period.
102 * @e_interface: specifies interface to be used.(CPU or RGB interface)
103 * @e_virtual_ch: specifies virtual channel number that main or
104 * sub diaplsy uses.
105 * @e_pixel_format: specifies pixel stream format for main or sub display.
106 * @e_burst_mode: selects Burst mode in Video mode.
107 * in Non-burst mode, RGB data area is filled with RGB data and NULL
108 * packets, according to input bandwidth of RGB interface.
109 * In Burst mode, RGB data area is filled with RGB data only.
110 * @e_no_data_lane: specifies data lane count to be used by Master.
111 * @e_byte_clk: select byte clock source. (it must be DSIM_PLL_OUT_DIV8)
112 * DSIM_EXT_CLK_DIV8 and DSIM_EXT_CLK_BYPASSS are not supported.
113 * @pll_stable_time: specifies the PLL Timer for stability of the ganerated
114 * clock(System clock cycle base)
115 * if the timer value goes to 0x00000000, the clock stable bit of status
116 * and interrupt register is set.
117 * @esc_clk: specifies escape clock frequency for getting the escape clock
118 * prescaler value.
119 * @stop_holding_cnt: specifies the interval value between transmitting
120 * read packet(or write "set_tear_on" command) and BTA request.
121 * after transmitting read packet or write "set_tear_on" command,
122 * BTA requests to D-PHY automatically. this counter value specifies
123 * the interval between them.
124 * @bta_timeout: specifies the timer for BTA.
125 * this register specifies time out from BTA request to change
126 * the direction with respect to Tx escape clock.
127 * @rx_timeout: specifies the timer for LP Rx mode timeout.
128 * this register specifies time out on how long RxValid deasserts,
129 * after RxLpdt asserts with respect to Tx escape clock.
130 * - RxValid specifies Rx data valid indicator.
131 * - RxLpdt specifies an indicator that D-PHY is under RxLpdt mode.
132 * - RxValid and RxLpdt specifies signal from D-PHY.
133 */
134struct mipi_dsim_config {
135 unsigned char auto_flush;
136 unsigned char eot_disable;
137
138 unsigned char auto_vertical_cnt;
139 unsigned char hse;
140 unsigned char hfp;
141 unsigned char hbp;
142 unsigned char hsa;
143 unsigned char cmd_allow;
144
145 enum mipi_dsim_interface_type e_interface;
146 enum mipi_dsim_virtual_ch_no e_virtual_ch;
147 enum mipi_dsim_pixel_format e_pixel_format;
148 enum mipi_dsim_burst_mode_type e_burst_mode;
149 enum mipi_dsim_no_of_data_lane e_no_data_lane;
150 enum mipi_dsim_byte_clk_src e_byte_clk;
151
152 /*
153 * ===========================================
154 * | P | M | S | MHz |
155 * -------------------------------------------
156 * | 3 | 100 | 3 | 100 |
157 * | 3 | 100 | 2 | 200 |
158 * | 3 | 63 | 1 | 252 |
159 * | 4 | 100 | 1 | 300 |
160 * | 4 | 110 | 1 | 330 |
161 * | 12 | 350 | 1 | 350 |
162 * | 3 | 100 | 1 | 400 |
163 * | 4 | 150 | 1 | 450 |
164 * | 6 | 118 | 1 | 472 |
165 * | 3 | 120 | 1 | 480 |
166 * | 12 | 250 | 0 | 500 |
167 * | 4 | 100 | 0 | 600 |
168 * | 3 | 81 | 0 | 648 |
169 * | 3 | 88 | 0 | 704 |
170 * | 3 | 90 | 0 | 720 |
171 * | 3 | 100 | 0 | 800 |
172 * | 12 | 425 | 0 | 850 |
173 * | 4 | 150 | 0 | 900 |
174 * | 12 | 475 | 0 | 950 |
175 * | 6 | 250 | 0 | 1000 |
176 * -------------------------------------------
177 */
178
179 /*
180 * pms could be calculated as the following.
181 * M * 24 / P * 2 ^ S = MHz
182 */
183 unsigned char p;
184 unsigned short m;
185 unsigned char s;
186
187 unsigned int pll_stable_time;
188 unsigned long esc_clk;
189
190 unsigned short stop_holding_cnt;
191 unsigned char bta_timeout;
192 unsigned short rx_timeout;
193};
194
195/*
196 * struct mipi_dsim_device - global interface for mipi-dsi driver.
197 *
198 * @dev: driver model representation of the device.
199 * @id: unique device id.
200 * @clock: pointer to MIPI-DSI clock of clock framework.
201 * @irq: interrupt number to MIPI-DSI controller.
202 * @reg_base: base address to memory mapped SRF of MIPI-DSI controller.
203 * (virtual address)
204 * @lock: the mutex protecting this data structure.
205 * @dsim_info: infomation for configuring mipi-dsi controller.
206 * @master_ops: callbacks to mipi-dsi operations.
207 * @dsim_lcd_dev: pointer to activated ddi device.
208 * (it would be registered by mipi-dsi driver.)
209 * @dsim_lcd_drv: pointer to activated_ddi driver.
210 * (it would be registered by mipi-dsi driver.)
211 * @lcd_info: pointer to mipi_lcd_info structure.
212 * @state: specifies status of MIPI-DSI controller.
213 * the status could be RESET, INIT, STOP, HSCLKEN and ULPS.
214 * @data_lane: specifiec enabled data lane number.
215 * this variable would be set by driver according to e_no_data_lane
216 * automatically.
217 * @e_clk_src: select byte clock source.
218 * @pd: pointer to MIPI-DSI driver platform data.
219 */
220struct mipi_dsim_device {
221 struct device *dev;
222 int id;
223 struct resource *res;
224 struct clk *clock;
225 unsigned int irq;
226 void __iomem *reg_base;
227 struct mutex lock;
228
229 struct mipi_dsim_config *dsim_config;
230 struct mipi_dsim_master_ops *master_ops;
231 struct mipi_dsim_lcd_device *dsim_lcd_dev;
232 struct mipi_dsim_lcd_driver *dsim_lcd_drv;
233
234 unsigned int state;
235 unsigned int data_lane;
236 unsigned int e_clk_src;
237 bool suspended;
238
239 struct mipi_dsim_platform_data *pd;
240};
241
242/*
243 * struct mipi_dsim_platform_data - interface to platform data
244 * for mipi-dsi driver.
245 *
246 * @lcd_panel_name: specifies lcd panel name registered to mipi-dsi driver.
247 * lcd panel driver searched would be actived.
248 * @dsim_config: pointer of structure for configuring mipi-dsi controller.
249 * @enabled: indicate whether mipi controller got enabled or not.
250 * @lcd_panel_info: pointer for lcd panel specific structure.
251 * this structure specifies width, height, timing and polarity and so on.
252 * @phy_enable: pointer to a callback controlling D-PHY enable/reset
253 */
254struct mipi_dsim_platform_data {
255 char lcd_panel_name[PANEL_NAME_SIZE];
256
257 struct mipi_dsim_config *dsim_config;
258 unsigned int enabled;
259 void *lcd_panel_info;
260
261 int (*phy_enable)(struct platform_device *pdev, bool on);
262};
263
264/*
265 * struct mipi_dsim_master_ops - callbacks to mipi-dsi operations.
266 *
267 * @cmd_write: transfer command to lcd panel at LP mode.
268 * @cmd_read: read command from rx register.
269 * @get_dsim_frame_done: get the status that all screen data have been
270 * transferred to mipi-dsi.
271 * @clear_dsim_frame_done: clear frame done status.
272 * @get_fb_frame_done: get frame done status of display controller.
273 * @trigger: trigger display controller.
274 * - this one would be used only in case of CPU mode.
275 * @set_early_blank_mode: set framebuffer blank mode.
276 * - this callback should be called prior to fb_blank() by a client driver
277 * only if needing.
278 * @set_blank_mode: set framebuffer blank mode.
279 * - this callback should be called after fb_blank() by a client driver
280 * only if needing.
281 */
282
283struct mipi_dsim_master_ops {
284 int (*cmd_write)(struct mipi_dsim_device *dsim, unsigned int data_id,
285 const unsigned char *data0, unsigned int data1);
286 int (*cmd_read)(struct mipi_dsim_device *dsim, unsigned int data_id,
287 unsigned int data0, unsigned int req_size, u8 *rx_buf);
288 int (*get_dsim_frame_done)(struct mipi_dsim_device *dsim);
289 int (*clear_dsim_frame_done)(struct mipi_dsim_device *dsim);
290
291 int (*get_fb_frame_done)(struct fb_info *info);
292 void (*trigger)(struct fb_info *info);
293 int (*set_early_blank_mode)(struct mipi_dsim_device *dsim, int power);
294 int (*set_blank_mode)(struct mipi_dsim_device *dsim, int power);
295};
296
297/*
298 * device structure for mipi-dsi based lcd panel.
299 *
300 * @name: name of the device to use with this device, or an
301 * alias for that name.
302 * @dev: driver model representation of the device.
303 * @id: id of device to be registered.
304 * @bus_id: bus id for identifing connected bus
305 * and this bus id should be same as id of mipi_dsim_device.
306 * @irq: irq number for signaling when framebuffer transfer of
307 * lcd panel module is completed.
308 * this irq would be used only for MIPI-DSI based CPU mode lcd panel.
309 * @master: pointer to mipi-dsi master device object.
310 * @platform_data: lcd panel specific platform data.
311 */
312struct mipi_dsim_lcd_device {
313 char *name;
314 struct device dev;
315 int id;
316 int bus_id;
317 int irq;
318
319 struct mipi_dsim_device *master;
320 void *platform_data;
321};
322
323/*
324 * driver structure for mipi-dsi based lcd panel.
325 *
326 * this structure should be registered by lcd panel driver.
327 * mipi-dsi driver seeks lcd panel registered through name field
328 * and calls these callback functions in appropriate time.
329 *
330 * @name: name of the driver to use with this device, or an
331 * alias for that name.
332 * @id: id of driver to be registered.
333 * this id would be used for finding device object registered.
334 */
335struct mipi_dsim_lcd_driver {
336 char *name;
337 int id;
338
339 void (*power_on)(struct mipi_dsim_lcd_device *dsim_dev, int enable);
340 void (*set_sequence)(struct mipi_dsim_lcd_device *dsim_dev);
341 int (*probe)(struct mipi_dsim_lcd_device *dsim_dev);
342 int (*remove)(struct mipi_dsim_lcd_device *dsim_dev);
343 void (*shutdown)(struct mipi_dsim_lcd_device *dsim_dev);
344 int (*suspend)(struct mipi_dsim_lcd_device *dsim_dev);
345 int (*resume)(struct mipi_dsim_lcd_device *dsim_dev);
346};
347
348/*
349 * register mipi_dsim_lcd_device to mipi-dsi master.
350 */
351int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device
352 *lcd_dev);
353/**
354 * register mipi_dsim_lcd_driver object defined by lcd panel driver
355 * to mipi-dsi driver.
356 */
357int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver
358 *lcd_drv);
359#endif /* _EXYNOS_MIPI_DSIM_H */
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
index b56932927d0a..728f9de9c258 100644
--- a/include/video/sh_mobile_hdmi.h
+++ b/include/video/sh_mobile_hdmi.h
@@ -31,8 +31,6 @@ struct clk;
31#define HDMI_SND_SRC_HBR (3 << 0) 31#define HDMI_SND_SRC_HBR (3 << 0)
32 32
33struct sh_mobile_hdmi_info { 33struct sh_mobile_hdmi_info {
34 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
35 struct device *lcd_dev;
36 unsigned int flags; 34 unsigned int flags;
37 long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq, 35 long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
38 unsigned long *parent_freq); 36 unsigned long *parent_freq);
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index fe30b759c51e..7571b27a0ba1 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -147,29 +147,23 @@ struct sh_mobile_lcdc_sys_bus_ops {
147 unsigned long (*read_data)(void *handle); 147 unsigned long (*read_data)(void *handle);
148}; 148};
149 149
150struct module; 150struct sh_mobile_lcdc_panel_cfg {
151struct sh_mobile_lcdc_board_cfg { 151 unsigned long width; /* Panel width in mm */
152 struct module *owner; 152 unsigned long height; /* Panel height in mm */
153 void *board_data; 153 int (*setup_sys)(void *sys_ops_handle,
154 int (*setup_sys)(void *board_data, void *sys_ops_handle,
155 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 154 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
156 void (*start_transfer)(void *board_data, void *sys_ops_handle, 155 void (*start_transfer)(void *sys_ops_handle,
157 struct sh_mobile_lcdc_sys_bus_ops *sys_ops); 156 struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
158 void (*display_on)(void *board_data, struct fb_info *info); 157 void (*display_on)(void);
159 void (*display_off)(void *board_data); 158 void (*display_off)(void);
160 int (*set_brightness)(void *board_data, int brightness);
161 int (*get_brightness)(void *board_data);
162};
163
164struct sh_mobile_lcdc_lcd_size_cfg { /* width and height of panel in mm */
165 unsigned long width;
166 unsigned long height;
167}; 159};
168 160
169/* backlight info */ 161/* backlight info */
170struct sh_mobile_lcdc_bl_info { 162struct sh_mobile_lcdc_bl_info {
171 const char *name; 163 const char *name;
172 int max_brightness; 164 int max_brightness;
165 int (*set_brightness)(int brightness);
166 int (*get_brightness)(void);
173}; 167};
174 168
175struct sh_mobile_lcdc_chan_cfg { 169struct sh_mobile_lcdc_chan_cfg {
@@ -179,13 +173,14 @@ struct sh_mobile_lcdc_chan_cfg {
179 int interface_type; /* selects RGBn or SYSn I/F, see above */ 173 int interface_type; /* selects RGBn or SYSn I/F, see above */
180 int clock_divider; 174 int clock_divider;
181 unsigned long flags; /* LCDC_FLAGS_... */ 175 unsigned long flags; /* LCDC_FLAGS_... */
182 const struct fb_videomode *lcd_cfg; 176 const struct fb_videomode *lcd_modes;
183 int num_cfg; 177 int num_modes;
184 struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg; 178 struct sh_mobile_lcdc_panel_cfg panel_cfg;
185 struct sh_mobile_lcdc_board_cfg board_cfg;
186 struct sh_mobile_lcdc_bl_info bl_info; 179 struct sh_mobile_lcdc_bl_info bl_info;
187 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ 180 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
188 struct sh_mobile_meram_cfg *meram_cfg; 181 const struct sh_mobile_meram_cfg *meram_cfg;
182
183 struct platform_device *tx_dev; /* HDMI/DSI transmitter device */
189}; 184};
190 185
191struct sh_mobile_lcdc_info { 186struct sh_mobile_lcdc_info {
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
index af602d602b28..29b2fd3b147e 100644
--- a/include/video/sh_mobile_meram.h
+++ b/include/video/sh_mobile_meram.h
@@ -17,52 +17,47 @@ enum {
17struct sh_mobile_meram_priv; 17struct sh_mobile_meram_priv;
18struct sh_mobile_meram_ops; 18struct sh_mobile_meram_ops;
19 19
20/*
21 * struct sh_mobile_meram_info - MERAM platform data
22 * @reserved_icbs: Bitmask of reserved ICBs (for instance used through UIO)
23 */
20struct sh_mobile_meram_info { 24struct sh_mobile_meram_info {
21 int addr_mode; 25 int addr_mode;
26 u32 reserved_icbs;
22 struct sh_mobile_meram_ops *ops; 27 struct sh_mobile_meram_ops *ops;
23 struct sh_mobile_meram_priv *priv; 28 struct sh_mobile_meram_priv *priv;
24 struct platform_device *pdev; 29 struct platform_device *pdev;
25}; 30};
26 31
27/* icb config */ 32/* icb config */
28struct sh_mobile_meram_icb { 33struct sh_mobile_meram_icb_cfg {
29 int marker_icb; /* ICB # for Marker ICB */ 34 unsigned int meram_size; /* MERAM Buffer Size to use */
30 int cache_icb; /* ICB # for Cache ICB */
31 int meram_offset; /* MERAM Buffer Offset to use */
32 int meram_size; /* MERAM Buffer Size to use */
33
34 int cache_unit; /* bytes to cache per ICB */
35}; 35};
36 36
37struct sh_mobile_meram_cfg { 37struct sh_mobile_meram_cfg {
38 struct sh_mobile_meram_icb icb[2]; 38 struct sh_mobile_meram_icb_cfg icb[2];
39 int pixelformat;
40 int current_reg;
41}; 39};
42 40
43struct module; 41struct module;
44struct sh_mobile_meram_ops { 42struct sh_mobile_meram_ops {
45 struct module *module; 43 struct module *module;
46 /* register usage of meram */ 44 /* register usage of meram */
47 int (*meram_register)(struct sh_mobile_meram_info *meram_dev, 45 void *(*meram_register)(struct sh_mobile_meram_info *meram_dev,
48 struct sh_mobile_meram_cfg *cfg, 46 const struct sh_mobile_meram_cfg *cfg,
49 int xres, int yres, int pixelformat, 47 unsigned int xres, unsigned int yres,
50 unsigned long base_addr_y, 48 unsigned int pixelformat,
51 unsigned long base_addr_c, 49 unsigned int *pitch);
52 unsigned long *icb_addr_y,
53 unsigned long *icb_addr_c, int *pitch);
54 50
55 /* unregister usage of meram */ 51 /* unregister usage of meram */
56 int (*meram_unregister)(struct sh_mobile_meram_info *meram_dev, 52 void (*meram_unregister)(struct sh_mobile_meram_info *meram_dev,
57 struct sh_mobile_meram_cfg *cfg); 53 void *data);
58 54
59 /* update meram settings */ 55 /* update meram settings */
60 int (*meram_update)(struct sh_mobile_meram_info *meram_dev, 56 void (*meram_update)(struct sh_mobile_meram_info *meram_dev, void *data,
61 struct sh_mobile_meram_cfg *cfg, 57 unsigned long base_addr_y,
62 unsigned long base_addr_y, 58 unsigned long base_addr_c,
63 unsigned long base_addr_c, 59 unsigned long *icb_addr_y,
64 unsigned long *icb_addr_y, 60 unsigned long *icb_addr_c);
65 unsigned long *icb_addr_c);
66}; 61};
67 62
68#endif /* __VIDEO_SH_MOBILE_MERAM_H__ */ 63#endif /* __VIDEO_SH_MOBILE_MERAM_H__ */
diff --git a/include/video/udlfb.h b/include/video/udlfb.h
index c41f308c9636..f9466fa54ba4 100644
--- a/include/video/udlfb.h
+++ b/include/video/udlfb.h
@@ -41,6 +41,7 @@ struct dlfb_data {
41 char *backing_buffer; 41 char *backing_buffer;
42 int fb_count; 42 int fb_count;
43 bool virtualized; /* true when physical usb device not present */ 43 bool virtualized; /* true when physical usb device not present */
44 struct delayed_work init_framebuffer_work;
44 struct delayed_work free_framebuffer_work; 45 struct delayed_work free_framebuffer_work;
45 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */ 46 atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
46 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */ 47 atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */