aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/video/omap2
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r--drivers/video/omap2/Kconfig7
-rw-r--r--drivers/video/omap2/Makefile1
-rw-r--r--drivers/video/omap2/displays/Kconfig28
-rw-r--r--drivers/video/omap2/displays/Makefile3
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c71
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c486
-rw-r--r--drivers/video/omap2/displays/panel-lgphilips-lb035q02.c63
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c687
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c72
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.c558
-rw-r--r--drivers/video/omap2/displays/panel-picodlp.h288
-rw-r--r--drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c29
-rw-r--r--drivers/video/omap2/displays/panel-taal.c547
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c353
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c211
-rw-r--r--drivers/video/omap2/dss/Kconfig52
-rw-r--r--drivers/video/omap2/dss/Makefile12
-rw-r--r--drivers/video/omap2/dss/apply.c1671
-rw-r--r--drivers/video/omap2/dss/core.c435
-rw-r--r--drivers/video/omap2/dss/dispc-compat.c667
-rw-r--r--drivers/video/omap2/dss/dispc-compat.h30
-rw-r--r--drivers/video/omap2/dss/dispc.c4093
-rw-r--r--drivers/video/omap2/dss/dispc.h205
-rw-r--r--drivers/video/omap2/dss/dispc_coefs.c325
-rw-r--r--drivers/video/omap2/dss/display-sysfs.c321
-rw-r--r--drivers/video/omap2/dss/display.c388
-rw-r--r--drivers/video/omap2/dss/dpi.c405
-rw-r--r--drivers/video/omap2/dss/dsi.c2547
-rw-r--r--drivers/video/omap2/dss/dss.c450
-rw-r--r--drivers/video/omap2/dss/dss.h414
-rw-r--r--drivers/video/omap2/dss/dss_features.c617
-rw-r--r--drivers/video/omap2/dss/dss_features.h89
-rw-r--r--drivers/video/omap2/dss/hdmi.c2204
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c414
-rw-r--r--drivers/video/omap2/dss/manager-sysfs.c512
-rw-r--r--drivers/video/omap2/dss/manager.c1678
-rw-r--r--drivers/video/omap2/dss/output.c180
-rw-r--r--drivers/video/omap2/dss/overlay-sysfs.c456
-rw-r--r--drivers/video/omap2/dss/overlay.c745
-rw-r--r--drivers/video/omap2/dss/rfbi.c348
-rw-r--r--drivers/video/omap2/dss/sdi.c228
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h190
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c1430
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h436
-rw-r--r--drivers/video/omap2/dss/venc.c396
-rw-r--r--drivers/video/omap2/dss/venc_panel.c232
-rw-r--r--drivers/video/omap2/omapfb/Kconfig5
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c117
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c521
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c16
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h35
-rw-r--r--drivers/video/omap2/vrfb.c147
52 files changed, 9087 insertions, 17328 deletions
diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig
index b07b2b042e7..d877c361abd 100644
--- a/drivers/video/omap2/Kconfig
+++ b/drivers/video/omap2/Kconfig
@@ -1,10 +1,9 @@
1config OMAP2_VRFB 1config OMAP2_VRAM
2 bool 2 bool
3 3
4if ARCH_OMAP2PLUS 4config OMAP2_VRFB
5 bool
5 6
6source "drivers/video/omap2/dss/Kconfig" 7source "drivers/video/omap2/dss/Kconfig"
7source "drivers/video/omap2/omapfb/Kconfig" 8source "drivers/video/omap2/omapfb/Kconfig"
8source "drivers/video/omap2/displays/Kconfig" 9source "drivers/video/omap2/displays/Kconfig"
9
10endif
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 5ea7cb9aed1..5ddef129f79 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_OMAP2_VRAM) += vram.o
1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 2obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2 3
3obj-$(CONFIG_OMAP2_DSS) += dss/ 4obj-$(CONFIG_OMAP2_DSS) += dss/
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index c3853c92279..609a2807317 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,13 +10,6 @@ config PANEL_GENERIC_DPI
10 Supports LCD Panel used in TI SDP3430 and EVM boards, 10 Supports LCD Panel used in TI SDP3430 and EVM boards,
11 OMAP3517 EVM boards and CM-T35. 11 OMAP3517 EVM boards and CM-T35.
12 12
13config PANEL_TFP410
14 tristate "TFP410 DPI-to-DVI chip"
15 depends on OMAP2_DSS_DPI && I2C
16 help
17 Driver for TFP410 DPI-to-DVI chip. The driver uses i2c to read EDID
18 information from the monitor.
19
20config PANEL_LGPHILIPS_LB035Q02 13config PANEL_LGPHILIPS_LB035Q02
21 tristate "LG.Philips LB035Q02 LCD Panel" 14 tristate "LG.Philips LB035Q02 LCD Panel"
22 depends on OMAP2_DSS_DPI && SPI 15 depends on OMAP2_DSS_DPI && SPI
@@ -26,30 +19,20 @@ config PANEL_LGPHILIPS_LB035Q02
26config PANEL_SHARP_LS037V7DW01 19config PANEL_SHARP_LS037V7DW01
27 tristate "Sharp LS037V7DW01 LCD Panel" 20 tristate "Sharp LS037V7DW01 LCD Panel"
28 depends on OMAP2_DSS_DPI 21 depends on OMAP2_DSS_DPI
29 depends on BACKLIGHT_CLASS_DEVICE 22 select BACKLIGHT_CLASS_DEVICE
30 help 23 help
31 LCD Panel used in TI's SDP3430 and EVM boards 24 LCD Panel used in TI's SDP3430 and EVM boards
32 25
33config PANEL_NEC_NL8048HL11_01B 26config PANEL_NEC_NL8048HL11_01B
34 tristate "NEC NL8048HL11-01B Panel" 27 tristate "NEC NL8048HL11-01B Panel"
35 depends on OMAP2_DSS_DPI 28 depends on OMAP2_DSS_DPI
36 depends on SPI
37 depends on BACKLIGHT_CLASS_DEVICE
38 help 29 help
39 This NEC NL8048HL11-01B panel is TFT LCD 30 This NEC NL8048HL11-01B panel is TFT LCD
40 used in the Zoom2/3/3630 sdp boards. 31 used in the Zoom2/3/3630 sdp boards.
41 32
42config PANEL_PICODLP
43 tristate "TI PICO DLP mini-projector"
44 depends on OMAP2_DSS_DPI && I2C
45 help
46 A mini-projector used in TI's SDP4430 and EVM boards
47 For more info please visit http://www.dlp.com/projector/
48
49config PANEL_TAAL 33config PANEL_TAAL
50 tristate "Taal DSI Panel" 34 tristate "Taal DSI Panel"
51 depends on OMAP2_DSS_DSI 35 depends on OMAP2_DSS_DSI
52 depends on BACKLIGHT_CLASS_DEVICE
53 help 36 help
54 Taal DSI command mode panel from TPO. 37 Taal DSI command mode panel from TPO.
55 38
@@ -62,14 +45,7 @@ config PANEL_TPO_TD043MTEA1
62config PANEL_ACX565AKM 45config PANEL_ACX565AKM
63 tristate "ACX565AKM Panel" 46 tristate "ACX565AKM Panel"
64 depends on OMAP2_DSS_SDI && SPI 47 depends on OMAP2_DSS_SDI && SPI
65 depends on BACKLIGHT_CLASS_DEVICE 48 select BACKLIGHT_CLASS_DEVICE
66 help 49 help
67 This is the LCD panel used on Nokia N900 50 This is the LCD panel used on Nokia N900
68
69config PANEL_N8X0
70 tristate "N8X0 Panel"
71 depends on OMAP2_DSS_RFBI && SPI
72 depends on BACKLIGHT_CLASS_DEVICE
73 help
74 This is the LCD panel used on Nokia N8x0
75endmenu 51endmenu
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index 58a5176b07b..0f601ab3abf 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,11 +1,8 @@
1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o 1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
2obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
3obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o 2obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
4obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o 3obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
5obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o 4obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
6 5
7obj-$(CONFIG_PANEL_TAAL) += panel-taal.o 6obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
8obj-$(CONFIG_PANEL_PICODLP) += panel-picodlp.o
9obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o 7obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
10obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o 8obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
11obj-$(CONFIG_PANEL_N8X0) += panel-n8x0.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index 72699f88c00..dbd59b8e5b3 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -487,13 +487,6 @@ static struct omap_video_timings acx_panel_timings = {
487 .vfp = 3, 487 .vfp = 3,
488 .vsw = 3, 488 .vsw = 3,
489 .vbp = 4, 489 .vbp = 4,
490
491 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
492 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
493
494 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
495 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
496 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
497}; 490};
498 491
499static int acx_panel_probe(struct omap_dss_device *dssdev) 492static int acx_panel_probe(struct omap_dss_device *dssdev)
@@ -505,7 +498,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
505 struct backlight_properties props; 498 struct backlight_properties props;
506 499
507 dev_dbg(&dssdev->dev, "%s\n", __func__); 500 dev_dbg(&dssdev->dev, "%s\n", __func__);
508 501 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
502 OMAP_DSS_LCD_IHS;
509 /* FIXME AC bias ? */ 503 /* FIXME AC bias ? */
510 dssdev->panel.timings = acx_panel_timings; 504 dssdev->panel.timings = acx_panel_timings;
511 505
@@ -538,7 +532,6 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
538 532
539 /*------- Backlight control --------*/ 533 /*------- Backlight control --------*/
540 534
541 memset(&props, 0, sizeof(props));
542 props.fb_blank = FB_BLANK_UNBLANK; 535 props.fb_blank = FB_BLANK_UNBLANK;
543 props.power = FB_BLANK_UNBLANK; 536 props.power = FB_BLANK_UNBLANK;
544 props.type = BACKLIGHT_RAW; 537 props.type = BACKLIGHT_RAW;
@@ -600,9 +593,6 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
600 593
601 mutex_lock(&md->mutex); 594 mutex_lock(&md->mutex);
602 595
603 omapdss_sdi_set_timings(dssdev, &dssdev->panel.timings);
604 omapdss_sdi_set_datapairs(dssdev, dssdev->phy.sdi.datapairs);
605
606 r = omapdss_sdi_display_enable(dssdev); 596 r = omapdss_sdi_display_enable(dssdev);
607 if (r) { 597 if (r) {
608 pr_err("%s sdi enable failed\n", __func__); 598 pr_err("%s sdi enable failed\n", __func__);
@@ -710,12 +700,48 @@ static void acx_panel_disable(struct omap_dss_device *dssdev)
710 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 700 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
711} 701}
712 702
703static int acx_panel_suspend(struct omap_dss_device *dssdev)
704{
705 dev_dbg(&dssdev->dev, "%s\n", __func__);
706 acx_panel_power_off(dssdev);
707 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
708 return 0;
709}
710
711static int acx_panel_resume(struct omap_dss_device *dssdev)
712{
713 int r;
714
715 dev_dbg(&dssdev->dev, "%s\n", __func__);
716 r = acx_panel_power_on(dssdev);
717 if (r)
718 return r;
719
720 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
721 return 0;
722}
723
713static void acx_panel_set_timings(struct omap_dss_device *dssdev, 724static void acx_panel_set_timings(struct omap_dss_device *dssdev,
714 struct omap_video_timings *timings) 725 struct omap_video_timings *timings)
715{ 726{
716 omapdss_sdi_set_timings(dssdev, timings); 727 int r;
728
729 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
730 omapdss_sdi_display_disable(dssdev);
717 731
718 dssdev->panel.timings = *timings; 732 dssdev->panel.timings = *timings;
733
734 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
735 r = omapdss_sdi_display_enable(dssdev);
736 if (r)
737 dev_err(&dssdev->dev, "%s enable failed\n", __func__);
738 }
739}
740
741static void acx_panel_get_timings(struct omap_dss_device *dssdev,
742 struct omap_video_timings *timings)
743{
744 *timings = dssdev->panel.timings;
719} 745}
720 746
721static int acx_panel_check_timings(struct omap_dss_device *dssdev, 747static int acx_panel_check_timings(struct omap_dss_device *dssdev,
@@ -731,8 +757,11 @@ static struct omap_dss_driver acx_panel_driver = {
731 757
732 .enable = acx_panel_enable, 758 .enable = acx_panel_enable,
733 .disable = acx_panel_disable, 759 .disable = acx_panel_disable,
760 .suspend = acx_panel_suspend,
761 .resume = acx_panel_resume,
734 762
735 .set_timings = acx_panel_set_timings, 763 .set_timings = acx_panel_set_timings,
764 .get_timings = acx_panel_get_timings,
736 .check_timings = acx_panel_check_timings, 765 .check_timings = acx_panel_check_timings,
737 766
738 .get_recommended_bpp = acx_get_recommended_bpp, 767 .get_recommended_bpp = acx_get_recommended_bpp,
@@ -774,13 +803,25 @@ static int acx565akm_spi_remove(struct spi_device *spi)
774static struct spi_driver acx565akm_spi_driver = { 803static struct spi_driver acx565akm_spi_driver = {
775 .driver = { 804 .driver = {
776 .name = "acx565akm", 805 .name = "acx565akm",
806 .bus = &spi_bus_type,
777 .owner = THIS_MODULE, 807 .owner = THIS_MODULE,
778 }, 808 },
779 .probe = acx565akm_spi_probe, 809 .probe = acx565akm_spi_probe,
780 .remove = acx565akm_spi_remove, 810 .remove = __devexit_p(acx565akm_spi_remove),
781}; 811};
782 812
783module_spi_driver(acx565akm_spi_driver); 813static int __init acx565akm_init(void)
814{
815 return spi_register_driver(&acx565akm_spi_driver);
816}
817
818static void __exit acx565akm_exit(void)
819{
820 spi_unregister_driver(&acx565akm_spi_driver);
821}
822
823module_init(acx565akm_init);
824module_exit(acx565akm_exit);
784 825
785MODULE_AUTHOR("Nokia Corporation"); 826MODULE_AUTHOR("Nokia Corporation");
786MODULE_DESCRIPTION("acx565akm LCD Driver"); 827MODULE_DESCRIPTION("acx565akm LCD Driver");
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 54ca8ae2107..9c90f75653f 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -40,6 +40,12 @@
40struct panel_config { 40struct panel_config {
41 struct omap_video_timings timings; 41 struct omap_video_timings timings;
42 42
43 int acbi; /* ac-bias pin transitions per interrupt */
44 /* Unit: line clocks */
45 int acb; /* ac-bias pin frequency */
46
47 enum omap_panel_config config;
48
43 int power_on_delay; 49 int power_on_delay;
44 int power_off_delay; 50 int power_off_delay;
45 51
@@ -52,6 +58,30 @@ struct panel_config {
52 58
53/* Panel configurations */ 59/* Panel configurations */
54static struct panel_config generic_dpi_panels[] = { 60static struct panel_config generic_dpi_panels[] = {
61 /* Generic Panel */
62 {
63 {
64 .x_res = 640,
65 .y_res = 480,
66
67 .pixel_clock = 23500,
68
69 .hfp = 48,
70 .hsw = 32,
71 .hbp = 80,
72
73 .vfp = 3,
74 .vsw = 4,
75 .vbp = 7,
76 },
77 .acbi = 0x0,
78 .acb = 0x0,
79 .config = OMAP_DSS_LCD_TFT,
80 .power_on_delay = 0,
81 .power_off_delay = 0,
82 .name = "generic",
83 },
84
55 /* Sharp LQ043T1DG01 */ 85 /* Sharp LQ043T1DG01 */
56 { 86 {
57 { 87 {
@@ -67,13 +97,11 @@ static struct panel_config generic_dpi_panels[] = {
67 .vsw = 11, 97 .vsw = 11,
68 .vfp = 3, 98 .vfp = 3,
69 .vbp = 2, 99 .vbp = 2,
70
71 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
72 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
73 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
74 .de_level = OMAPDSS_SIG_ACTIVE_LOW,
75 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
76 }, 100 },
101 .acbi = 0x0,
102 .acb = 0x0,
103 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
104 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
77 .power_on_delay = 50, 105 .power_on_delay = 50,
78 .power_off_delay = 100, 106 .power_off_delay = 100,
79 .name = "sharp_lq", 107 .name = "sharp_lq",
@@ -94,13 +122,11 @@ static struct panel_config generic_dpi_panels[] = {
94 .vsw = 1, 122 .vsw = 1,
95 .vfp = 1, 123 .vfp = 1,
96 .vbp = 1, 124 .vbp = 1,
97
98 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
99 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
100 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
101 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
102 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
103 }, 125 },
126 .acbi = 0x0,
127 .acb = 0x28,
128 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
129 OMAP_DSS_LCD_IHS,
104 .power_on_delay = 50, 130 .power_on_delay = 50,
105 .power_off_delay = 100, 131 .power_off_delay = 100,
106 .name = "sharp_ls", 132 .name = "sharp_ls",
@@ -121,13 +147,12 @@ static struct panel_config generic_dpi_panels[] = {
121 .vfp = 4, 147 .vfp = 4,
122 .vsw = 2, 148 .vsw = 2,
123 .vbp = 2, 149 .vbp = 2,
124
125 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
126 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
127 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
128 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
129 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
130 }, 150 },
151 .acbi = 0x0,
152 .acb = 0x0,
153 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
154 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC |
155 OMAP_DSS_LCD_ONOFF,
131 .power_on_delay = 0, 156 .power_on_delay = 0,
132 .power_off_delay = 0, 157 .power_off_delay = 0,
133 .name = "toppoly_tdo35s", 158 .name = "toppoly_tdo35s",
@@ -148,13 +173,11 @@ static struct panel_config generic_dpi_panels[] = {
148 .vfp = 4, 173 .vfp = 4,
149 .vsw = 10, 174 .vsw = 10,
150 .vbp = 12 - 10, 175 .vbp = 12 - 10,
151
152 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
153 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
154 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
155 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
156 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
157 }, 176 },
177 .acbi = 0x0,
178 .acb = 0x0,
179 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
180 OMAP_DSS_LCD_IHS,
158 .power_on_delay = 0, 181 .power_on_delay = 0,
159 .power_off_delay = 0, 182 .power_off_delay = 0,
160 .name = "samsung_lte430wq_f0c", 183 .name = "samsung_lte430wq_f0c",
@@ -175,13 +198,11 @@ static struct panel_config generic_dpi_panels[] = {
175 .vsw = 2, 198 .vsw = 2,
176 .vfp = 4, 199 .vfp = 4,
177 .vbp = 11, 200 .vbp = 11,
178
179 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
180 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
181 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
182 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
183 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
184 }, 201 },
202 .acbi = 0x0,
203 .acb = 0x0,
204 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
205 OMAP_DSS_LCD_IHS,
185 .power_on_delay = 0, 206 .power_on_delay = 0,
186 .power_off_delay = 0, 207 .power_off_delay = 0,
187 .name = "seiko_70wvw1tz3", 208 .name = "seiko_70wvw1tz3",
@@ -202,342 +223,15 @@ static struct panel_config generic_dpi_panels[] = {
202 .vsw = 10, 223 .vsw = 10,
203 .vfp = 2, 224 .vfp = 2,
204 .vbp = 2, 225 .vbp = 2,
205
206 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
207 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
208 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
209 .de_level = OMAPDSS_SIG_ACTIVE_LOW,
210 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
211 }, 226 },
227 .acbi = 0x0,
228 .acb = 0x0,
229 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
230 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
212 .power_on_delay = 0, 231 .power_on_delay = 0,
213 .power_off_delay = 0, 232 .power_off_delay = 0,
214 .name = "powertip_ph480272t", 233 .name = "powertip_ph480272t",
215 }, 234 },
216
217 /* Innolux AT070TN83 */
218 {
219 {
220 .x_res = 800,
221 .y_res = 480,
222
223 .pixel_clock = 40000,
224
225 .hsw = 48,
226 .hfp = 1,
227 .hbp = 1,
228
229 .vsw = 3,
230 .vfp = 12,
231 .vbp = 25,
232
233 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
234 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
235 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
236 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
237 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
238 },
239 .power_on_delay = 0,
240 .power_off_delay = 0,
241 .name = "innolux_at070tn83",
242 },
243
244 /* NEC NL2432DR22-11B */
245 {
246 {
247 .x_res = 240,
248 .y_res = 320,
249
250 .pixel_clock = 5400,
251
252 .hsw = 3,
253 .hfp = 3,
254 .hbp = 39,
255
256 .vsw = 1,
257 .vfp = 2,
258 .vbp = 7,
259
260 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
261 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
262 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
263 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
264 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
265 },
266 .name = "nec_nl2432dr22-11b",
267 },
268
269 /* Unknown panel used in OMAP H4 */
270 {
271 {
272 .x_res = 240,
273 .y_res = 320,
274
275 .pixel_clock = 6250,
276
277 .hsw = 15,
278 .hfp = 15,
279 .hbp = 60,
280
281 .vsw = 1,
282 .vfp = 1,
283 .vbp = 1,
284
285 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
286 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
287 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
288 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
289 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
290 },
291 .name = "h4",
292 },
293
294 /* Unknown panel used in Samsung OMAP2 Apollon */
295 {
296 {
297 .x_res = 480,
298 .y_res = 272,
299
300 .pixel_clock = 6250,
301
302 .hsw = 41,
303 .hfp = 2,
304 .hbp = 2,
305
306 .vsw = 10,
307 .vfp = 2,
308 .vbp = 2,
309
310 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
311 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
312 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
313 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
314 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
315 },
316 .name = "apollon",
317 },
318 /* FocalTech ETM070003DH6 */
319 {
320 {
321 .x_res = 800,
322 .y_res = 480,
323
324 .pixel_clock = 28000,
325
326 .hsw = 48,
327 .hfp = 40,
328 .hbp = 40,
329
330 .vsw = 3,
331 .vfp = 13,
332 .vbp = 29,
333
334 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
335 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
336 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
337 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
338 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
339 },
340 .name = "focaltech_etm070003dh6",
341 },
342
343 /* Microtips Technologies - UMSH-8173MD */
344 {
345 {
346 .x_res = 800,
347 .y_res = 480,
348
349 .pixel_clock = 34560,
350
351 .hsw = 13,
352 .hfp = 101,
353 .hbp = 101,
354
355 .vsw = 23,
356 .vfp = 1,
357 .vbp = 1,
358
359 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
360 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
361 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
362 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
363 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
364 },
365 .power_on_delay = 0,
366 .power_off_delay = 0,
367 .name = "microtips_umsh_8173md",
368 },
369
370 /* OrtusTech COM43H4M10XTC */
371 {
372 {
373 .x_res = 480,
374 .y_res = 272,
375
376 .pixel_clock = 8000,
377
378 .hsw = 41,
379 .hfp = 8,
380 .hbp = 4,
381
382 .vsw = 10,
383 .vfp = 4,
384 .vbp = 2,
385
386 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
387 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
388 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
389 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
390 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
391 },
392 .name = "ortustech_com43h4m10xtc",
393 },
394
395 /* Innolux AT080TN52 */
396 {
397 {
398 .x_res = 800,
399 .y_res = 600,
400
401 .pixel_clock = 41142,
402
403 .hsw = 20,
404 .hfp = 210,
405 .hbp = 46,
406
407 .vsw = 10,
408 .vfp = 12,
409 .vbp = 23,
410
411 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
412 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
413 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
414 .de_level = OMAPDSS_SIG_ACTIVE_LOW,
415 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
416 },
417 .name = "innolux_at080tn52",
418 },
419
420 /* Mitsubishi AA084SB01 */
421 {
422 {
423 .x_res = 800,
424 .y_res = 600,
425 .pixel_clock = 40000,
426
427 .hsw = 1,
428 .hfp = 254,
429 .hbp = 1,
430
431 .vsw = 1,
432 .vfp = 26,
433 .vbp = 1,
434
435 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
436 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
437 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
438 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
439 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
440 },
441 .name = "mitsubishi_aa084sb01",
442 },
443 /* EDT ET0500G0DH6 */
444 {
445 {
446 .x_res = 800,
447 .y_res = 480,
448 .pixel_clock = 33260,
449
450 .hsw = 128,
451 .hfp = 216,
452 .hbp = 40,
453
454 .vsw = 2,
455 .vfp = 35,
456 .vbp = 10,
457
458 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
459 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
460 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
461 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
462 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
463 },
464 .name = "edt_et0500g0dh6",
465 },
466
467 /* Prime-View PD050VL1 */
468 {
469 {
470 .x_res = 640,
471 .y_res = 480,
472
473 .pixel_clock = 25000,
474
475 .hsw = 96,
476 .hfp = 18,
477 .hbp = 46,
478
479 .vsw = 2,
480 .vfp = 10,
481 .vbp = 33,
482
483 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
484 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
485 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
486 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
487 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
488 },
489 .name = "primeview_pd050vl1",
490 },
491
492 /* Prime-View PM070WL4 */
493 {
494 {
495 .x_res = 800,
496 .y_res = 480,
497
498 .pixel_clock = 32000,
499
500 .hsw = 128,
501 .hfp = 42,
502 .hbp = 86,
503
504 .vsw = 2,
505 .vfp = 10,
506 .vbp = 33,
507
508 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
509 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
510 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
511 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
512 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
513 },
514 .name = "primeview_pm070wl4",
515 },
516
517 /* Prime-View PD104SLF */
518 {
519 {
520 .x_res = 800,
521 .y_res = 600,
522
523 .pixel_clock = 40000,
524
525 .hsw = 128,
526 .hfp = 42,
527 .hbp = 86,
528
529 .vsw = 4,
530 .vfp = 1,
531 .vbp = 23,
532
533 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
534 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
535 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
536 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
537 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
538 },
539 .name = "primeview_pd104slf",
540 },
541}; 235};
542 236
543struct panel_drv_data { 237struct panel_drv_data {
@@ -545,8 +239,6 @@ struct panel_drv_data {
545 struct omap_dss_device *dssdev; 239 struct omap_dss_device *dssdev;
546 240
547 struct panel_config *panel_config; 241 struct panel_config *panel_config;
548
549 struct mutex lock;
550}; 242};
551 243
552static inline struct panel_generic_dpi_data 244static inline struct panel_generic_dpi_data
@@ -565,9 +257,6 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev)
565 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 257 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
566 return 0; 258 return 0;
567 259
568 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
569 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
570
571 r = omapdss_dpi_display_enable(dssdev); 260 r = omapdss_dpi_display_enable(dssdev);
572 if (r) 261 if (r)
573 goto err0; 262 goto err0;
@@ -630,7 +319,10 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
630 if (!panel_config) 319 if (!panel_config)
631 return -EINVAL; 320 return -EINVAL;
632 321
322 dssdev->panel.config = panel_config->config;
633 dssdev->panel.timings = panel_config->timings; 323 dssdev->panel.timings = panel_config->timings;
324 dssdev->panel.acb = panel_config->acb;
325 dssdev->panel.acbi = panel_config->acbi;
634 326
635 drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); 327 drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
636 if (!drv_data) 328 if (!drv_data)
@@ -639,8 +331,6 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
639 drv_data->dssdev = dssdev; 331 drv_data->dssdev = dssdev;
640 drv_data->panel_config = panel_config; 332 drv_data->panel_config = panel_config;
641 333
642 mutex_init(&drv_data->lock);
643
644 dev_set_drvdata(&dssdev->dev, drv_data); 334 dev_set_drvdata(&dssdev->dev, drv_data);
645 335
646 return 0; 336 return 0;
@@ -659,74 +349,62 @@ static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
659 349
660static int generic_dpi_panel_enable(struct omap_dss_device *dssdev) 350static int generic_dpi_panel_enable(struct omap_dss_device *dssdev)
661{ 351{
662 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); 352 int r = 0;
663 int r;
664
665 mutex_lock(&drv_data->lock);
666 353
667 r = generic_dpi_panel_power_on(dssdev); 354 r = generic_dpi_panel_power_on(dssdev);
668 if (r) 355 if (r)
669 goto err; 356 return r;
670 357
671 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 358 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
672err:
673 mutex_unlock(&drv_data->lock);
674 359
675 return r; 360 return 0;
676} 361}
677 362
678static void generic_dpi_panel_disable(struct omap_dss_device *dssdev) 363static void generic_dpi_panel_disable(struct omap_dss_device *dssdev)
679{ 364{
680 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); 365 generic_dpi_panel_power_off(dssdev);
681 366
682 mutex_lock(&drv_data->lock); 367 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
368}
683 369
370static int generic_dpi_panel_suspend(struct omap_dss_device *dssdev)
371{
684 generic_dpi_panel_power_off(dssdev); 372 generic_dpi_panel_power_off(dssdev);
685 373
686 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 374 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
687 375
688 mutex_unlock(&drv_data->lock); 376 return 0;
689} 377}
690 378
691static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev, 379static int generic_dpi_panel_resume(struct omap_dss_device *dssdev)
692 struct omap_video_timings *timings)
693{ 380{
694 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); 381 int r = 0;
695 382
696 mutex_lock(&drv_data->lock); 383 r = generic_dpi_panel_power_on(dssdev);
384 if (r)
385 return r;
697 386
698 omapdss_dpi_set_timings(dssdev, timings); 387 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
699 388
700 dssdev->panel.timings = *timings; 389 return 0;
390}
701 391
702 mutex_unlock(&drv_data->lock); 392static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
393 struct omap_video_timings *timings)
394{
395 dpi_set_timings(dssdev, timings);
703} 396}
704 397
705static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev, 398static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
706 struct omap_video_timings *timings) 399 struct omap_video_timings *timings)
707{ 400{
708 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
709
710 mutex_lock(&drv_data->lock);
711
712 *timings = dssdev->panel.timings; 401 *timings = dssdev->panel.timings;
713
714 mutex_unlock(&drv_data->lock);
715} 402}
716 403
717static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, 404static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
718 struct omap_video_timings *timings) 405 struct omap_video_timings *timings)
719{ 406{
720 struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); 407 return dpi_check_timings(dssdev, timings);
721 int r;
722
723 mutex_lock(&drv_data->lock);
724
725 r = dpi_check_timings(dssdev, timings);
726
727 mutex_unlock(&drv_data->lock);
728
729 return r;
730} 408}
731 409
732static struct omap_dss_driver dpi_driver = { 410static struct omap_dss_driver dpi_driver = {
@@ -735,6 +413,8 @@ static struct omap_dss_driver dpi_driver = {
735 413
736 .enable = generic_dpi_panel_enable, 414 .enable = generic_dpi_panel_enable,
737 .disable = generic_dpi_panel_disable, 415 .disable = generic_dpi_panel_disable,
416 .suspend = generic_dpi_panel_suspend,
417 .resume = generic_dpi_panel_resume,
738 418
739 .set_timings = generic_dpi_panel_set_timings, 419 .set_timings = generic_dpi_panel_set_timings,
740 .get_timings = generic_dpi_panel_get_timings, 420 .get_timings = generic_dpi_panel_get_timings,
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
index 6e5abe8fd2d..e0eb35be303 100644
--- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -40,12 +40,6 @@ static struct omap_video_timings lb035q02_timings = {
40 .vsw = 2, 40 .vsw = 2,
41 .vfp = 4, 41 .vfp = 4,
42 .vbp = 18, 42 .vbp = 18,
43
44 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
45 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
46 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
47 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
48 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
49}; 43};
50 44
51static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) 45static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
@@ -55,9 +49,6 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
55 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 49 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
56 return 0; 50 return 0;
57 51
58 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
59 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
60
61 r = omapdss_dpi_display_enable(dssdev); 52 r = omapdss_dpi_display_enable(dssdev);
62 if (r) 53 if (r)
63 goto err0; 54 goto err0;
@@ -91,6 +82,8 @@ static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
91 struct lb035q02_data *ld; 82 struct lb035q02_data *ld;
92 int r; 83 int r;
93 84
85 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
86 OMAP_DSS_LCD_IHS;
94 dssdev->panel.timings = lb035q02_timings; 87 dssdev->panel.timings = lb035q02_timings;
95 88
96 ld = kzalloc(sizeof(*ld), GFP_KERNEL); 89 ld = kzalloc(sizeof(*ld), GFP_KERNEL);
@@ -143,12 +136,46 @@ static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
143 mutex_unlock(&ld->lock); 136 mutex_unlock(&ld->lock);
144} 137}
145 138
139static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
140{
141 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
142
143 mutex_lock(&ld->lock);
144
145 lb035q02_panel_power_off(dssdev);
146 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
147
148 mutex_unlock(&ld->lock);
149 return 0;
150}
151
152static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
153{
154 struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev);
155 int r;
156
157 mutex_lock(&ld->lock);
158
159 r = lb035q02_panel_power_on(dssdev);
160 if (r)
161 goto err;
162 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
163
164 mutex_unlock(&ld->lock);
165 return 0;
166err:
167 mutex_unlock(&ld->lock);
168 return r;
169}
170
146static struct omap_dss_driver lb035q02_driver = { 171static struct omap_dss_driver lb035q02_driver = {
147 .probe = lb035q02_panel_probe, 172 .probe = lb035q02_panel_probe,
148 .remove = lb035q02_panel_remove, 173 .remove = lb035q02_panel_remove,
149 174
150 .enable = lb035q02_panel_enable, 175 .enable = lb035q02_panel_enable,
151 .disable = lb035q02_panel_disable, 176 .disable = lb035q02_panel_disable,
177 .suspend = lb035q02_panel_suspend,
178 .resume = lb035q02_panel_resume,
152 179
153 .driver = { 180 .driver = {
154 .name = "lgphilips_lb035q02_panel", 181 .name = "lgphilips_lb035q02_panel",
@@ -216,13 +243,13 @@ static void init_lb035q02_panel(struct spi_device *spi)
216 lb035q02_write_reg(spi, 0x3b, 0x0806); 243 lb035q02_write_reg(spi, 0x3b, 0x0806);
217} 244}
218 245
219static int lb035q02_panel_spi_probe(struct spi_device *spi) 246static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi)
220{ 247{
221 init_lb035q02_panel(spi); 248 init_lb035q02_panel(spi);
222 return omap_dss_register_driver(&lb035q02_driver); 249 return omap_dss_register_driver(&lb035q02_driver);
223} 250}
224 251
225static int lb035q02_panel_spi_remove(struct spi_device *spi) 252static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi)
226{ 253{
227 omap_dss_unregister_driver(&lb035q02_driver); 254 omap_dss_unregister_driver(&lb035q02_driver);
228 return 0; 255 return 0;
@@ -234,9 +261,19 @@ static struct spi_driver lb035q02_spi_driver = {
234 .owner = THIS_MODULE, 261 .owner = THIS_MODULE,
235 }, 262 },
236 .probe = lb035q02_panel_spi_probe, 263 .probe = lb035q02_panel_spi_probe,
237 .remove = lb035q02_panel_spi_remove, 264 .remove = __devexit_p(lb035q02_panel_spi_remove),
238}; 265};
239 266
240module_spi_driver(lb035q02_spi_driver); 267static int __init lb035q02_panel_drv_init(void)
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}
241 276
277module_init(lb035q02_panel_drv_init);
278module_exit(lb035q02_panel_drv_exit);
242MODULE_LICENSE("GPL"); 279MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
deleted file mode 100644
index dd129475080..00000000000
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ /dev/null
@@ -1,687 +0,0 @@
1/* #define DEBUG */
2
3#include <linux/module.h>
4#include <linux/delay.h>
5#include <linux/slab.h>
6#include <linux/gpio.h>
7#include <linux/spi/spi.h>
8#include <linux/backlight.h>
9#include <linux/fb.h>
10
11#include <video/omapdss.h>
12#include <video/omap-panel-n8x0.h>
13
14#define BLIZZARD_REV_CODE 0x00
15#define BLIZZARD_CONFIG 0x02
16#define BLIZZARD_PLL_DIV 0x04
17#define BLIZZARD_PLL_LOCK_RANGE 0x06
18#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
19#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
20#define BLIZZARD_PLL_MODE 0x0c
21#define BLIZZARD_CLK_SRC 0x0e
22#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
23#define BLIZZARD_MEM_BANK0_STATUS 0x14
24#define BLIZZARD_PANEL_CONFIGURATION 0x28
25#define BLIZZARD_HDISP 0x2a
26#define BLIZZARD_HNDP 0x2c
27#define BLIZZARD_VDISP0 0x2e
28#define BLIZZARD_VDISP1 0x30
29#define BLIZZARD_VNDP 0x32
30#define BLIZZARD_HSW 0x34
31#define BLIZZARD_VSW 0x38
32#define BLIZZARD_DISPLAY_MODE 0x68
33#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
34#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
35#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
36#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
37#define BLIZZARD_POWER_SAVE 0xE6
38#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
39
40/* Data source select */
41/* For S1D13745 */
42#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
43#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
44#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
45#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
46/* For S1D13744 */
47#define BLIZZARD_SRC_WRITE_LCD 0x00
48#define BLIZZARD_SRC_BLT_LCD 0x06
49
50#define BLIZZARD_COLOR_RGB565 0x01
51#define BLIZZARD_COLOR_YUV420 0x09
52
53#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
54#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
55
56#define MIPID_CMD_READ_DISP_ID 0x04
57#define MIPID_CMD_READ_RED 0x06
58#define MIPID_CMD_READ_GREEN 0x07
59#define MIPID_CMD_READ_BLUE 0x08
60#define MIPID_CMD_READ_DISP_STATUS 0x09
61#define MIPID_CMD_RDDSDR 0x0F
62#define MIPID_CMD_SLEEP_IN 0x10
63#define MIPID_CMD_SLEEP_OUT 0x11
64#define MIPID_CMD_DISP_OFF 0x28
65#define MIPID_CMD_DISP_ON 0x29
66
67static struct panel_drv_data {
68 struct mutex lock;
69
70 struct omap_dss_device *dssdev;
71 struct spi_device *spidev;
72 struct backlight_device *bldev;
73
74 int blizzard_ver;
75} s_drv_data;
76
77
78static inline
79struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
80{
81 return dssdev->data;
82}
83
84static inline
85struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
86{
87 return &s_drv_data;
88}
89
90
91static inline void blizzard_cmd(u8 cmd)
92{
93 omap_rfbi_write_command(&cmd, 1);
94}
95
96static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
97{
98 omap_rfbi_write_command(&cmd, 1);
99 omap_rfbi_write_data(buf, len);
100}
101
102static inline void blizzard_read(u8 cmd, u8 *buf, int len)
103{
104 omap_rfbi_write_command(&cmd, 1);
105 omap_rfbi_read_data(buf, len);
106}
107
108static u8 blizzard_read_reg(u8 cmd)
109{
110 u8 data;
111 blizzard_read(cmd, &data, 1);
112 return data;
113}
114
115static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
116 int x, int y, int w, int h)
117{
118 struct panel_drv_data *ddata = get_drv_data(dssdev);
119 u8 tmp[18];
120 int x_end, y_end;
121
122 x_end = x + w - 1;
123 y_end = y + h - 1;
124
125 tmp[0] = x;
126 tmp[1] = x >> 8;
127 tmp[2] = y;
128 tmp[3] = y >> 8;
129 tmp[4] = x_end;
130 tmp[5] = x_end >> 8;
131 tmp[6] = y_end;
132 tmp[7] = y_end >> 8;
133
134 /* scaling? */
135 tmp[8] = x;
136 tmp[9] = x >> 8;
137 tmp[10] = y;
138 tmp[11] = y >> 8;
139 tmp[12] = x_end;
140 tmp[13] = x_end >> 8;
141 tmp[14] = y_end;
142 tmp[15] = y_end >> 8;
143
144 tmp[16] = BLIZZARD_COLOR_RGB565;
145
146 if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
147 tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
148 else
149 tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
150 BLIZZARD_SRC_WRITE_LCD :
151 BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
152
153 omapdss_rfbi_set_pixel_size(dssdev, 16);
154 omapdss_rfbi_set_data_lines(dssdev, 8);
155
156 omap_rfbi_configure(dssdev);
157
158 blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
159
160 omapdss_rfbi_set_pixel_size(dssdev, 16);
161 omapdss_rfbi_set_data_lines(dssdev, 16);
162
163 omap_rfbi_configure(dssdev);
164}
165
166static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
167 int wlen, u8 *rbuf, int rlen)
168{
169 struct spi_message m;
170 struct spi_transfer *x, xfer[4];
171 u16 w;
172 int r;
173
174 spi_message_init(&m);
175
176 memset(xfer, 0, sizeof(xfer));
177 x = &xfer[0];
178
179 cmd &= 0xff;
180 x->tx_buf = &cmd;
181 x->bits_per_word = 9;
182 x->len = 2;
183 spi_message_add_tail(x, &m);
184
185 if (wlen) {
186 x++;
187 x->tx_buf = wbuf;
188 x->len = wlen;
189 x->bits_per_word = 9;
190 spi_message_add_tail(x, &m);
191 }
192
193 if (rlen) {
194 x++;
195 x->rx_buf = &w;
196 x->len = 1;
197 spi_message_add_tail(x, &m);
198
199 if (rlen > 1) {
200 /* Arrange for the extra clock before the first
201 * data bit.
202 */
203 x->bits_per_word = 9;
204 x->len = 2;
205
206 x++;
207 x->rx_buf = &rbuf[1];
208 x->len = rlen - 1;
209 spi_message_add_tail(x, &m);
210 }
211 }
212
213 r = spi_sync(spi, &m);
214 if (r < 0)
215 dev_dbg(&spi->dev, "spi_sync %d\n", r);
216
217 if (rlen)
218 rbuf[0] = w & 0xff;
219}
220
221static inline void mipid_cmd(struct spi_device *spi, int cmd)
222{
223 mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
224}
225
226static inline void mipid_write(struct spi_device *spi,
227 int reg, const u8 *buf, int len)
228{
229 mipid_transfer(spi, reg, buf, len, NULL, 0);
230}
231
232static inline void mipid_read(struct spi_device *spi,
233 int reg, u8 *buf, int len)
234{
235 mipid_transfer(spi, reg, NULL, 0, buf, len);
236}
237
238static void set_data_lines(struct spi_device *spi, int data_lines)
239{
240 u16 par;
241
242 switch (data_lines) {
243 case 16:
244 par = 0x150;
245 break;
246 case 18:
247 par = 0x160;
248 break;
249 case 24:
250 par = 0x170;
251 break;
252 }
253
254 mipid_write(spi, 0x3a, (u8 *)&par, 2);
255}
256
257static void send_init_string(struct spi_device *spi)
258{
259 u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
260 mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
261}
262
263static void send_display_on(struct spi_device *spi)
264{
265 mipid_cmd(spi, MIPID_CMD_DISP_ON);
266}
267
268static void send_display_off(struct spi_device *spi)
269{
270 mipid_cmd(spi, MIPID_CMD_DISP_OFF);
271}
272
273static void send_sleep_out(struct spi_device *spi)
274{
275 mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
276 msleep(120);
277}
278
279static void send_sleep_in(struct spi_device *spi)
280{
281 mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
282 msleep(50);
283}
284
285static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
286{
287 int r;
288 struct panel_n8x0_data *bdata = get_board_data(dssdev);
289 struct panel_drv_data *ddata = get_drv_data(dssdev);
290 struct spi_device *spi = ddata->spidev;
291 u8 rev, conf;
292 u8 display_id[3];
293 const char *panel_name;
294
295 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
296 return 0;
297
298 gpio_direction_output(bdata->ctrl_pwrdown, 1);
299
300 if (bdata->platform_enable) {
301 r = bdata->platform_enable(dssdev);
302 if (r)
303 goto err_plat_en;
304 }
305
306 omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
307 dssdev->panel.timings.y_res);
308 omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
309 omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
310 omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
311
312 r = omapdss_rfbi_display_enable(dssdev);
313 if (r)
314 goto err_rfbi_en;
315
316 rev = blizzard_read_reg(BLIZZARD_REV_CODE);
317 conf = blizzard_read_reg(BLIZZARD_CONFIG);
318
319 switch (rev & 0xfc) {
320 case 0x9c:
321 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
322 dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
323 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
324 break;
325 case 0xa4:
326 ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
327 dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
328 "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
329 break;
330 default:
331 dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
332 r = -ENODEV;
333 goto err_inv_chip;
334 }
335
336 /* panel */
337
338 gpio_direction_output(bdata->panel_reset, 1);
339
340 mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
341 dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
342 display_id[0], display_id[1], display_id[2]);
343
344 switch (display_id[0]) {
345 case 0x45:
346 panel_name = "lph8923";
347 break;
348 case 0x83:
349 panel_name = "ls041y3";
350 break;
351 default:
352 dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
353 display_id[0]);
354 r = -ENODEV;
355 goto err_inv_panel;
356 }
357
358 dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
359 panel_name, display_id[1]);
360
361 send_sleep_out(spi);
362 send_init_string(spi);
363 set_data_lines(spi, 24);
364 send_display_on(spi);
365
366 return 0;
367
368err_inv_panel:
369 /*
370 * HACK: we should turn off the panel here, but there is some problem
371 * with the initialization sequence, and we fail to init the panel if we
372 * have turned it off
373 */
374 /* gpio_direction_output(bdata->panel_reset, 0); */
375err_inv_chip:
376 omapdss_rfbi_display_disable(dssdev);
377err_rfbi_en:
378 if (bdata->platform_disable)
379 bdata->platform_disable(dssdev);
380err_plat_en:
381 gpio_direction_output(bdata->ctrl_pwrdown, 0);
382 return r;
383}
384
385static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
386{
387 struct panel_n8x0_data *bdata = get_board_data(dssdev);
388 struct panel_drv_data *ddata = get_drv_data(dssdev);
389 struct spi_device *spi = ddata->spidev;
390
391 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
392 return;
393
394 send_display_off(spi);
395 send_sleep_in(spi);
396
397 if (bdata->platform_disable)
398 bdata->platform_disable(dssdev);
399
400 /*
401 * HACK: we should turn off the panel here, but there is some problem
402 * with the initialization sequence, and we fail to init the panel if we
403 * have turned it off
404 */
405 /* gpio_direction_output(bdata->panel_reset, 0); */
406 gpio_direction_output(bdata->ctrl_pwrdown, 0);
407 omapdss_rfbi_display_disable(dssdev);
408}
409
410static const struct rfbi_timings n8x0_panel_timings = {
411 .cs_on_time = 0,
412
413 .we_on_time = 9000,
414 .we_off_time = 18000,
415 .we_cycle_time = 36000,
416
417 .re_on_time = 9000,
418 .re_off_time = 27000,
419 .re_cycle_time = 36000,
420
421 .access_time = 27000,
422 .cs_off_time = 36000,
423
424 .cs_pulse_width = 0,
425};
426
427static int n8x0_bl_update_status(struct backlight_device *dev)
428{
429 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
430 struct panel_n8x0_data *bdata = get_board_data(dssdev);
431 struct panel_drv_data *ddata = get_drv_data(dssdev);
432 int r;
433 int level;
434
435 mutex_lock(&ddata->lock);
436
437 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
438 dev->props.power == FB_BLANK_UNBLANK)
439 level = dev->props.brightness;
440 else
441 level = 0;
442
443 dev_dbg(&dssdev->dev, "update brightness to %d\n", level);
444
445 if (!bdata->set_backlight)
446 r = -EINVAL;
447 else
448 r = bdata->set_backlight(dssdev, level);
449
450 mutex_unlock(&ddata->lock);
451
452 return r;
453}
454
455static int n8x0_bl_get_intensity(struct backlight_device *dev)
456{
457 if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
458 dev->props.power == FB_BLANK_UNBLANK)
459 return dev->props.brightness;
460
461 return 0;
462}
463
464static const struct backlight_ops n8x0_bl_ops = {
465 .get_brightness = n8x0_bl_get_intensity,
466 .update_status = n8x0_bl_update_status,
467};
468
469static int n8x0_panel_probe(struct omap_dss_device *dssdev)
470{
471 struct panel_n8x0_data *bdata = get_board_data(dssdev);
472 struct panel_drv_data *ddata;
473 struct backlight_device *bldev;
474 struct backlight_properties props;
475 int r;
476
477 dev_dbg(&dssdev->dev, "probe\n");
478
479 if (!bdata)
480 return -EINVAL;
481
482 s_drv_data.dssdev = dssdev;
483
484 ddata = &s_drv_data;
485
486 mutex_init(&ddata->lock);
487
488 dssdev->panel.timings.x_res = 800;
489 dssdev->panel.timings.y_res = 480;
490 dssdev->ctrl.pixel_size = 16;
491 dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
492 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
493
494 memset(&props, 0, sizeof(props));
495 props.max_brightness = 127;
496 props.type = BACKLIGHT_PLATFORM;
497 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
498 dssdev, &n8x0_bl_ops, &props);
499 if (IS_ERR(bldev)) {
500 r = PTR_ERR(bldev);
501 dev_err(&dssdev->dev, "register backlight failed\n");
502 return r;
503 }
504
505 ddata->bldev = bldev;
506
507 bldev->props.fb_blank = FB_BLANK_UNBLANK;
508 bldev->props.power = FB_BLANK_UNBLANK;
509 bldev->props.brightness = 127;
510
511 n8x0_bl_update_status(bldev);
512
513 return 0;
514}
515
516static void n8x0_panel_remove(struct omap_dss_device *dssdev)
517{
518 struct panel_drv_data *ddata = get_drv_data(dssdev);
519 struct backlight_device *bldev;
520
521 dev_dbg(&dssdev->dev, "remove\n");
522
523 bldev = ddata->bldev;
524 bldev->props.power = FB_BLANK_POWERDOWN;
525 n8x0_bl_update_status(bldev);
526 backlight_device_unregister(bldev);
527
528 dev_set_drvdata(&dssdev->dev, NULL);
529}
530
531static int n8x0_panel_enable(struct omap_dss_device *dssdev)
532{
533 struct panel_drv_data *ddata = get_drv_data(dssdev);
534 int r;
535
536 dev_dbg(&dssdev->dev, "enable\n");
537
538 mutex_lock(&ddata->lock);
539
540 rfbi_bus_lock();
541
542 r = n8x0_panel_power_on(dssdev);
543
544 rfbi_bus_unlock();
545
546 if (r) {
547 mutex_unlock(&ddata->lock);
548 return r;
549 }
550
551 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
552
553 mutex_unlock(&ddata->lock);
554
555 return 0;
556}
557
558static void n8x0_panel_disable(struct omap_dss_device *dssdev)
559{
560 struct panel_drv_data *ddata = get_drv_data(dssdev);
561
562 dev_dbg(&dssdev->dev, "disable\n");
563
564 mutex_lock(&ddata->lock);
565
566 rfbi_bus_lock();
567
568 n8x0_panel_power_off(dssdev);
569
570 rfbi_bus_unlock();
571
572 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
573
574 mutex_unlock(&ddata->lock);
575}
576
577static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
578 u16 *xres, u16 *yres)
579{
580 *xres = dssdev->panel.timings.x_res;
581 *yres = dssdev->panel.timings.y_res;
582}
583
584static void update_done(void *data)
585{
586 rfbi_bus_unlock();
587}
588
589static int n8x0_panel_update(struct omap_dss_device *dssdev,
590 u16 x, u16 y, u16 w, u16 h)
591{
592 struct panel_drv_data *ddata = get_drv_data(dssdev);
593 u16 dw, dh;
594
595 dev_dbg(&dssdev->dev, "update\n");
596
597 dw = dssdev->panel.timings.x_res;
598 dh = dssdev->panel.timings.y_res;
599
600 if (x != 0 || y != 0 || w != dw || h != dh) {
601 dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
602 x, y, w, h);
603 return -EINVAL;
604 }
605
606 mutex_lock(&ddata->lock);
607 rfbi_bus_lock();
608
609 blizzard_ctrl_setup_update(dssdev, x, y, w, h);
610
611 omap_rfbi_update(dssdev, update_done, NULL);
612
613 mutex_unlock(&ddata->lock);
614
615 return 0;
616}
617
618static int n8x0_panel_sync(struct omap_dss_device *dssdev)
619{
620 struct panel_drv_data *ddata = get_drv_data(dssdev);
621
622 dev_dbg(&dssdev->dev, "sync\n");
623
624 mutex_lock(&ddata->lock);
625 rfbi_bus_lock();
626 rfbi_bus_unlock();
627 mutex_unlock(&ddata->lock);
628
629 return 0;
630}
631
632static struct omap_dss_driver n8x0_panel_driver = {
633 .probe = n8x0_panel_probe,
634 .remove = n8x0_panel_remove,
635
636 .enable = n8x0_panel_enable,
637 .disable = n8x0_panel_disable,
638
639 .update = n8x0_panel_update,
640 .sync = n8x0_panel_sync,
641
642 .get_resolution = n8x0_panel_get_resolution,
643 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
644
645 .driver = {
646 .name = "n8x0_panel",
647 .owner = THIS_MODULE,
648 },
649};
650
651/* PANEL */
652
653static int mipid_spi_probe(struct spi_device *spi)
654{
655 int r;
656
657 dev_dbg(&spi->dev, "mipid_spi_probe\n");
658
659 spi->mode = SPI_MODE_0;
660
661 s_drv_data.spidev = spi;
662
663 r = omap_dss_register_driver(&n8x0_panel_driver);
664 if (r)
665 pr_err("n8x0_panel: dss driver registration failed\n");
666
667 return r;
668}
669
670static int mipid_spi_remove(struct spi_device *spi)
671{
672 dev_dbg(&spi->dev, "mipid_spi_remove\n");
673 omap_dss_unregister_driver(&n8x0_panel_driver);
674 return 0;
675}
676
677static struct spi_driver mipid_spi_driver = {
678 .driver = {
679 .name = "lcd_mipid",
680 .owner = THIS_MODULE,
681 },
682 .probe = mipid_spi_probe,
683 .remove = mipid_spi_remove,
684};
685module_spi_driver(mipid_spi_driver);
686
687MODULE_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 c4e9c2b1b46..2ba9d0ca187 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -76,12 +76,6 @@ static struct omap_video_timings nec_8048_panel_timings = {
76 .vfp = 3, 76 .vfp = 3,
77 .vsw = 1, 77 .vsw = 1,
78 .vbp = 4, 78 .vbp = 4,
79
80 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
81 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
82 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
83 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
84 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
85}; 79};
86 80
87static int nec_8048_bl_update_status(struct backlight_device *bl) 81static int nec_8048_bl_update_status(struct backlight_device *bl)
@@ -122,6 +116,9 @@ static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
122 struct backlight_properties props; 116 struct backlight_properties props;
123 int r; 117 int r;
124 118
119 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
120 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_RF |
121 OMAP_DSS_LCD_ONOFF;
125 dssdev->panel.timings = nec_8048_panel_timings; 122 dssdev->panel.timings = nec_8048_panel_timings;
126 123
127 necd = kzalloc(sizeof(*necd), GFP_KERNEL); 124 necd = kzalloc(sizeof(*necd), GFP_KERNEL);
@@ -166,74 +163,50 @@ static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
166 kfree(necd); 163 kfree(necd);
167} 164}
168 165
169static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) 166static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
170{ 167{
171 int r; 168 int r = 0;
172 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 169 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
173 struct backlight_device *bl = necd->bl; 170 struct backlight_device *bl = necd->bl;
174 171
175 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
176 return 0;
177
178 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
179 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
180
181 r = omapdss_dpi_display_enable(dssdev);
182 if (r)
183 goto err0;
184
185 if (dssdev->platform_enable) { 172 if (dssdev->platform_enable) {
186 r = dssdev->platform_enable(dssdev); 173 r = dssdev->platform_enable(dssdev);
187 if (r) 174 if (r)
188 goto err1; 175 return r;
189 } 176 }
190 177
191 r = nec_8048_bl_update_status(bl); 178 r = nec_8048_bl_update_status(bl);
192 if (r < 0) 179 if (r < 0)
193 dev_err(&dssdev->dev, "failed to set lcd brightness\n"); 180 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
194 181
195 return 0; 182 r = omapdss_dpi_display_enable(dssdev);
196err1: 183
197 omapdss_dpi_display_disable(dssdev);
198err0:
199 return r; 184 return r;
200} 185}
201 186
202static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) 187static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
203{ 188{
204 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 189 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
205 struct backlight_device *bl = necd->bl; 190 struct backlight_device *bl = necd->bl;
206 191
207 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 192 omapdss_dpi_display_disable(dssdev);
208 return;
209 193
210 bl->props.brightness = 0; 194 bl->props.brightness = 0;
211 nec_8048_bl_update_status(bl); 195 nec_8048_bl_update_status(bl);
212 196
213 if (dssdev->platform_disable) 197 if (dssdev->platform_disable)
214 dssdev->platform_disable(dssdev); 198 dssdev->platform_disable(dssdev);
215
216 omapdss_dpi_display_disable(dssdev);
217} 199}
218 200
219static int nec_8048_panel_enable(struct omap_dss_device *dssdev) 201static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
220{ 202{
221 int r; 203 nec_8048_panel_disable(dssdev);
222
223 r = nec_8048_panel_power_on(dssdev);
224 if (r)
225 return r;
226
227 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
228
229 return 0; 204 return 0;
230} 205}
231 206
232static void nec_8048_panel_disable(struct omap_dss_device *dssdev) 207static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
233{ 208{
234 nec_8048_panel_power_off(dssdev); 209 return nec_8048_panel_enable(dssdev);
235
236 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
237} 210}
238 211
239static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev) 212static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
@@ -246,6 +219,8 @@ static struct omap_dss_driver nec_8048_driver = {
246 .remove = nec_8048_panel_remove, 219 .remove = nec_8048_panel_remove,
247 .enable = nec_8048_panel_enable, 220 .enable = nec_8048_panel_enable,
248 .disable = nec_8048_panel_disable, 221 .disable = nec_8048_panel_disable,
222 .suspend = nec_8048_panel_suspend,
223 .resume = nec_8048_panel_resume,
249 .get_recommended_bpp = nec_8048_recommended_bpp, 224 .get_recommended_bpp = nec_8048_recommended_bpp,
250 225
251 .driver = { 226 .driver = {
@@ -323,17 +298,28 @@ static int nec_8048_spi_resume(struct spi_device *spi)
323 298
324static struct spi_driver nec_8048_spi_driver = { 299static struct spi_driver nec_8048_spi_driver = {
325 .probe = nec_8048_spi_probe, 300 .probe = nec_8048_spi_probe,
326 .remove = nec_8048_spi_remove, 301 .remove = __devexit_p(nec_8048_spi_remove),
327 .suspend = nec_8048_spi_suspend, 302 .suspend = nec_8048_spi_suspend,
328 .resume = nec_8048_spi_resume, 303 .resume = nec_8048_spi_resume,
329 .driver = { 304 .driver = {
330 .name = "nec_8048_spi", 305 .name = "nec_8048_spi",
306 .bus = &spi_bus_type,
331 .owner = THIS_MODULE, 307 .owner = THIS_MODULE,
332 }, 308 },
333}; 309};
334 310
335module_spi_driver(nec_8048_spi_driver); 311static int __init nec_8048_lcd_init(void)
312{
313 return spi_register_driver(&nec_8048_spi_driver);
314}
315
316static void __exit nec_8048_lcd_exit(void)
317{
318 return spi_unregister_driver(&nec_8048_spi_driver);
319}
336 320
321module_init(nec_8048_lcd_init);
322module_exit(nec_8048_lcd_exit);
337MODULE_AUTHOR("Erik Gilling <konkers@android.com>"); 323MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
338MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver"); 324MODULE_DESCRIPTION("NEC-nl8048hl11-01b Driver");
339MODULE_LICENSE("GPL"); 325MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c
deleted file mode 100644
index 1b94018aac3..00000000000
--- a/drivers/video/omap2/displays/panel-picodlp.c
+++ /dev/null
@@ -1,558 +0,0 @@
1/*
2 * picodlp panel driver
3 * picodlp_i2c_driver: i2c_client driver
4 *
5 * Copyright (C) 2009-2011 Texas Instruments
6 * Author: Mythri P K <mythripk@ti.com>
7 * Mayuresh Janorkar <mayur@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/module.h>
23#include <linux/input.h>
24#include <linux/platform_device.h>
25#include <linux/interrupt.h>
26#include <linux/firmware.h>
27#include <linux/slab.h>
28#include <linux/mutex.h>
29#include <linux/i2c.h>
30#include <linux/delay.h>
31#include <linux/gpio.h>
32
33#include <video/omapdss.h>
34#include <video/omap-panel-picodlp.h>
35
36#include "panel-picodlp.h"
37
38struct picodlp_data {
39 struct mutex lock;
40 struct i2c_client *picodlp_i2c_client;
41};
42
43static struct i2c_board_info picodlp_i2c_board_info = {
44 I2C_BOARD_INFO("picodlp_i2c_driver", 0x1b),
45};
46
47struct picodlp_i2c_data {
48 struct mutex xfer_lock;
49};
50
51static struct i2c_device_id picodlp_i2c_id[] = {
52 { "picodlp_i2c_driver", 0 },
53 { }
54};
55
56struct picodlp_i2c_command {
57 u8 reg;
58 u32 value;
59};
60
61static struct omap_video_timings pico_ls_timings = {
62 .x_res = 864,
63 .y_res = 480,
64 .hsw = 7,
65 .hfp = 11,
66 .hbp = 7,
67
68 .pixel_clock = 19200,
69
70 .vsw = 2,
71 .vfp = 3,
72 .vbp = 14,
73
74 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
75 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
76 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
77 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
78 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
79};
80
81static inline struct picodlp_panel_data
82 *get_panel_data(const struct omap_dss_device *dssdev)
83{
84 return (struct picodlp_panel_data *) dssdev->data;
85}
86
87static u32 picodlp_i2c_read(struct i2c_client *client, u8 reg)
88{
89 u8 read_cmd[] = {READ_REG_SELECT, reg}, data[4];
90 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
91 struct i2c_msg msg[2];
92
93 mutex_lock(&picodlp_i2c_data->xfer_lock);
94
95 msg[0].addr = client->addr;
96 msg[0].flags = 0;
97 msg[0].len = 2;
98 msg[0].buf = read_cmd;
99
100 msg[1].addr = client->addr;
101 msg[1].flags = I2C_M_RD;
102 msg[1].len = 4;
103 msg[1].buf = data;
104
105 i2c_transfer(client->adapter, msg, 2);
106 mutex_unlock(&picodlp_i2c_data->xfer_lock);
107 return (data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24));
108}
109
110static int picodlp_i2c_write_block(struct i2c_client *client,
111 u8 *data, int len)
112{
113 struct i2c_msg msg;
114 int i, r, msg_count = 1;
115
116 struct picodlp_i2c_data *picodlp_i2c_data = i2c_get_clientdata(client);
117
118 if (len < 1 || len > 32) {
119 dev_err(&client->dev,
120 "too long syn_write_block len %d\n", len);
121 return -EIO;
122 }
123 mutex_lock(&picodlp_i2c_data->xfer_lock);
124
125 msg.addr = client->addr;
126 msg.flags = 0;
127 msg.len = len;
128 msg.buf = data;
129 r = i2c_transfer(client->adapter, &msg, msg_count);
130 mutex_unlock(&picodlp_i2c_data->xfer_lock);
131
132 /*
133 * i2c_transfer returns:
134 * number of messages sent in case of success
135 * a negative error number in case of failure
136 */
137 if (r != msg_count)
138 goto err;
139
140 /* In case of success */
141 for (i = 0; i < len; i++)
142 dev_dbg(&client->dev,
143 "addr %x bw 0x%02x[%d]: 0x%02x\n",
144 client->addr, data[0] + i, i, data[i]);
145
146 return 0;
147err:
148 dev_err(&client->dev, "picodlp_i2c_write error\n");
149 return r;
150}
151
152static int picodlp_i2c_write(struct i2c_client *client, u8 reg, u32 value)
153{
154 u8 data[5];
155 int i;
156
157 data[0] = reg;
158 for (i = 1; i < 5; i++)
159 data[i] = (value >> (32 - (i) * 8)) & 0xFF;
160
161 return picodlp_i2c_write_block(client, data, 5);
162}
163
164static int picodlp_i2c_write_array(struct i2c_client *client,
165 const struct picodlp_i2c_command commands[],
166 int count)
167{
168 int i, r = 0;
169 for (i = 0; i < count; i++) {
170 r = picodlp_i2c_write(client, commands[i].reg,
171 commands[i].value);
172 if (r)
173 return r;
174 }
175 return r;
176}
177
178static int picodlp_wait_for_dma_done(struct i2c_client *client)
179{
180 u8 trial = 100;
181
182 do {
183 msleep(1);
184 if (!trial--)
185 return -ETIMEDOUT;
186 } while (picodlp_i2c_read(client, MAIN_STATUS) & DMA_STATUS);
187
188 return 0;
189}
190
191/**
192 * picodlp_i2c_init: i2c_initialization routine
193 * client: i2c_client for communication
194 *
195 * return
196 * 0 : Success, no error
197 * error code : Failure
198 */
199static int picodlp_i2c_init(struct i2c_client *client)
200{
201 int r;
202 static const struct picodlp_i2c_command init_cmd_set1[] = {
203 {SOFT_RESET, 1},
204 {DMD_PARK_TRIGGER, 1},
205 {MISC_REG, 5},
206 {SEQ_CONTROL, 0},
207 {SEQ_VECTOR, 0x100},
208 {DMD_BLOCK_COUNT, 7},
209 {DMD_VCC_CONTROL, 0x109},
210 {DMD_PARK_PULSE_COUNT, 0xA},
211 {DMD_PARK_PULSE_WIDTH, 0xB},
212 {DMD_PARK_DELAY, 0x2ED},
213 {DMD_SHADOW_ENABLE, 0},
214 {FLASH_OPCODE, 0xB},
215 {FLASH_DUMMY_BYTES, 1},
216 {FLASH_ADDR_BYTES, 3},
217 {PBC_CONTROL, 0},
218 {FLASH_START_ADDR, CMT_LUT_0_START_ADDR},
219 {FLASH_READ_BYTES, CMT_LUT_0_SIZE},
220 {CMT_SPLASH_LUT_START_ADDR, 0},
221 {CMT_SPLASH_LUT_DEST_SELECT, CMT_LUT_ALL},
222 {PBC_CONTROL, 1},
223 };
224
225 static const struct picodlp_i2c_command init_cmd_set2[] = {
226 {PBC_CONTROL, 0},
227 {CMT_SPLASH_LUT_DEST_SELECT, 0},
228 {PBC_CONTROL, 0},
229 {FLASH_START_ADDR, SEQUENCE_0_START_ADDR},
230 {FLASH_READ_BYTES, SEQUENCE_0_SIZE},
231 {SEQ_RESET_LUT_START_ADDR, 0},
232 {SEQ_RESET_LUT_DEST_SELECT, SEQ_SEQ_LUT},
233 {PBC_CONTROL, 1},
234 };
235
236 static const struct picodlp_i2c_command init_cmd_set3[] = {
237 {PBC_CONTROL, 0},
238 {SEQ_RESET_LUT_DEST_SELECT, 0},
239 {PBC_CONTROL, 0},
240 {FLASH_START_ADDR, DRC_TABLE_0_START_ADDR},
241 {FLASH_READ_BYTES, DRC_TABLE_0_SIZE},
242 {SEQ_RESET_LUT_START_ADDR, 0},
243 {SEQ_RESET_LUT_DEST_SELECT, SEQ_DRC_LUT_ALL},
244 {PBC_CONTROL, 1},
245 };
246
247 static const struct picodlp_i2c_command init_cmd_set4[] = {
248 {PBC_CONTROL, 0},
249 {SEQ_RESET_LUT_DEST_SELECT, 0},
250 {SDC_ENABLE, 1},
251 {AGC_CTRL, 7},
252 {CCA_C1A, 0x100},
253 {CCA_C1B, 0x0},
254 {CCA_C1C, 0x0},
255 {CCA_C2A, 0x0},
256 {CCA_C2B, 0x100},
257 {CCA_C2C, 0x0},
258 {CCA_C3A, 0x0},
259 {CCA_C3B, 0x0},
260 {CCA_C3C, 0x100},
261 {CCA_C7A, 0x100},
262 {CCA_C7B, 0x100},
263 {CCA_C7C, 0x100},
264 {CCA_ENABLE, 1},
265 {CPU_IF_MODE, 1},
266 {SHORT_FLIP, 1},
267 {CURTAIN_CONTROL, 0},
268 {DMD_PARK_TRIGGER, 0},
269 {R_DRIVE_CURRENT, 0x298},
270 {G_DRIVE_CURRENT, 0x298},
271 {B_DRIVE_CURRENT, 0x298},
272 {RGB_DRIVER_ENABLE, 7},
273 {SEQ_CONTROL, 0},
274 {ACTGEN_CONTROL, 0x10},
275 {SEQUENCE_MODE, SEQ_LOCK},
276 {DATA_FORMAT, RGB888},
277 {INPUT_RESOLUTION, WVGA_864_LANDSCAPE},
278 {INPUT_SOURCE, PARALLEL_RGB},
279 {CPU_IF_SYNC_METHOD, 1},
280 {SEQ_CONTROL, 1}
281 };
282
283 r = picodlp_i2c_write_array(client, init_cmd_set1,
284 ARRAY_SIZE(init_cmd_set1));
285 if (r)
286 return r;
287
288 r = picodlp_wait_for_dma_done(client);
289 if (r)
290 return r;
291
292 r = picodlp_i2c_write_array(client, init_cmd_set2,
293 ARRAY_SIZE(init_cmd_set2));
294 if (r)
295 return r;
296
297 r = picodlp_wait_for_dma_done(client);
298 if (r)
299 return r;
300
301 r = picodlp_i2c_write_array(client, init_cmd_set3,
302 ARRAY_SIZE(init_cmd_set3));
303 if (r)
304 return r;
305
306 r = picodlp_wait_for_dma_done(client);
307 if (r)
308 return r;
309
310 r = picodlp_i2c_write_array(client, init_cmd_set4,
311 ARRAY_SIZE(init_cmd_set4));
312 if (r)
313 return r;
314
315 return 0;
316}
317
318static int picodlp_i2c_probe(struct i2c_client *client,
319 const struct i2c_device_id *id)
320{
321 struct picodlp_i2c_data *picodlp_i2c_data;
322
323 picodlp_i2c_data = kzalloc(sizeof(struct picodlp_i2c_data), GFP_KERNEL);
324
325 if (!picodlp_i2c_data)
326 return -ENOMEM;
327
328 mutex_init(&picodlp_i2c_data->xfer_lock);
329 i2c_set_clientdata(client, picodlp_i2c_data);
330
331 return 0;
332}
333
334static int picodlp_i2c_remove(struct i2c_client *client)
335{
336 struct picodlp_i2c_data *picodlp_i2c_data =
337 i2c_get_clientdata(client);
338 kfree(picodlp_i2c_data);
339 return 0;
340}
341
342static struct i2c_driver picodlp_i2c_driver = {
343 .driver = {
344 .name = "picodlp_i2c_driver",
345 },
346 .probe = picodlp_i2c_probe,
347 .remove = picodlp_i2c_remove,
348 .id_table = picodlp_i2c_id,
349};
350
351static int picodlp_panel_power_on(struct omap_dss_device *dssdev)
352{
353 int r, trial = 100;
354 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
355 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
356
357 if (dssdev->platform_enable) {
358 r = dssdev->platform_enable(dssdev);
359 if (r)
360 return r;
361 }
362
363 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
364 msleep(1);
365 gpio_set_value(picodlp_pdata->pwrgood_gpio, 1);
366
367 while (!gpio_get_value(picodlp_pdata->emu_done_gpio)) {
368 if (!trial--) {
369 dev_err(&dssdev->dev, "emu_done signal not"
370 " going high\n");
371 return -ETIMEDOUT;
372 }
373 msleep(5);
374 }
375 /*
376 * As per dpp2600 programming guide,
377 * it is required to sleep for 1000ms after emu_done signal goes high
378 * then only i2c commands can be successfully sent to dpp2600
379 */
380 msleep(1000);
381
382 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
383 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
384
385 r = omapdss_dpi_display_enable(dssdev);
386 if (r) {
387 dev_err(&dssdev->dev, "failed to enable DPI\n");
388 goto err1;
389 }
390
391 r = picodlp_i2c_init(picod->picodlp_i2c_client);
392 if (r)
393 goto err;
394
395 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
396
397 return r;
398err:
399 omapdss_dpi_display_disable(dssdev);
400err1:
401 if (dssdev->platform_disable)
402 dssdev->platform_disable(dssdev);
403
404 return r;
405}
406
407static void picodlp_panel_power_off(struct omap_dss_device *dssdev)
408{
409 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
410
411 omapdss_dpi_display_disable(dssdev);
412
413 gpio_set_value(picodlp_pdata->emu_done_gpio, 0);
414 gpio_set_value(picodlp_pdata->pwrgood_gpio, 0);
415
416 if (dssdev->platform_disable)
417 dssdev->platform_disable(dssdev);
418}
419
420static int picodlp_panel_probe(struct omap_dss_device *dssdev)
421{
422 struct picodlp_data *picod;
423 struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev);
424 struct i2c_adapter *adapter;
425 struct i2c_client *picodlp_i2c_client;
426 int r = 0, picodlp_adapter_id;
427
428 dssdev->panel.timings = pico_ls_timings;
429
430 picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL);
431 if (!picod)
432 return -ENOMEM;
433
434 mutex_init(&picod->lock);
435
436 picodlp_adapter_id = picodlp_pdata->picodlp_adapter_id;
437
438 adapter = i2c_get_adapter(picodlp_adapter_id);
439 if (!adapter) {
440 dev_err(&dssdev->dev, "can't get i2c adapter\n");
441 r = -ENODEV;
442 goto err;
443 }
444
445 picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info);
446 if (!picodlp_i2c_client) {
447 dev_err(&dssdev->dev, "can't add i2c device::"
448 " picodlp_i2c_client is NULL\n");
449 r = -ENODEV;
450 goto err;
451 }
452
453 picod->picodlp_i2c_client = picodlp_i2c_client;
454
455 dev_set_drvdata(&dssdev->dev, picod);
456 return r;
457err:
458 kfree(picod);
459 return r;
460}
461
462static void picodlp_panel_remove(struct omap_dss_device *dssdev)
463{
464 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
465
466 i2c_unregister_device(picod->picodlp_i2c_client);
467 dev_set_drvdata(&dssdev->dev, NULL);
468 dev_dbg(&dssdev->dev, "removing picodlp panel\n");
469
470 kfree(picod);
471}
472
473static int picodlp_panel_enable(struct omap_dss_device *dssdev)
474{
475 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
476 int r;
477
478 dev_dbg(&dssdev->dev, "enabling picodlp panel\n");
479
480 mutex_lock(&picod->lock);
481 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
482 mutex_unlock(&picod->lock);
483 return -EINVAL;
484 }
485
486 r = picodlp_panel_power_on(dssdev);
487 mutex_unlock(&picod->lock);
488
489 return r;
490}
491
492static void picodlp_panel_disable(struct omap_dss_device *dssdev)
493{
494 struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev);
495
496 mutex_lock(&picod->lock);
497 /* Turn off DLP Power */
498 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
499 picodlp_panel_power_off(dssdev);
500
501 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
502 mutex_unlock(&picod->lock);
503
504 dev_dbg(&dssdev->dev, "disabling picodlp panel\n");
505}
506
507static void picodlp_get_resolution(struct omap_dss_device *dssdev,
508 u16 *xres, u16 *yres)
509{
510 *xres = dssdev->panel.timings.x_res;
511 *yres = dssdev->panel.timings.y_res;
512}
513
514static struct omap_dss_driver picodlp_driver = {
515 .probe = picodlp_panel_probe,
516 .remove = picodlp_panel_remove,
517
518 .enable = picodlp_panel_enable,
519 .disable = picodlp_panel_disable,
520
521 .get_resolution = picodlp_get_resolution,
522
523 .driver = {
524 .name = "picodlp_panel",
525 .owner = THIS_MODULE,
526 },
527};
528
529static int __init picodlp_init(void)
530{
531 int r = 0;
532
533 r = i2c_add_driver(&picodlp_i2c_driver);
534 if (r) {
535 printk(KERN_WARNING "picodlp_i2c_driver" \
536 " registration failed\n");
537 return r;
538 }
539
540 r = omap_dss_register_driver(&picodlp_driver);
541 if (r)
542 i2c_del_driver(&picodlp_i2c_driver);
543
544 return r;
545}
546
547static void __exit picodlp_exit(void)
548{
549 i2c_del_driver(&picodlp_i2c_driver);
550 omap_dss_unregister_driver(&picodlp_driver);
551}
552
553module_init(picodlp_init);
554module_exit(picodlp_exit);
555
556MODULE_AUTHOR("Mythri P K <mythripk@ti.com>");
557MODULE_DESCRIPTION("picodlp driver");
558MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-picodlp.h b/drivers/video/omap2/displays/panel-picodlp.h
deleted file mode 100644
index a34b431a726..00000000000
--- a/drivers/video/omap2/displays/panel-picodlp.h
+++ /dev/null
@@ -1,288 +0,0 @@
1/*
2 * Header file required by picodlp panel driver
3 *
4 * Copyright (C) 2009-2011 Texas Instruments
5 * Author: Mythri P K <mythripk@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#ifndef __OMAP2_DISPLAY_PANEL_PICODLP_H
21#define __OMAP2_DISPLAY_PANEL_PICODLP_H
22
23/* Commands used for configuring picodlp panel */
24
25#define MAIN_STATUS 0x03
26#define PBC_CONTROL 0x08
27#define INPUT_SOURCE 0x0B
28#define INPUT_RESOLUTION 0x0C
29#define DATA_FORMAT 0x0D
30#define IMG_ROTATION 0x0E
31#define LONG_FLIP 0x0F
32#define SHORT_FLIP 0x10
33#define TEST_PAT_SELECT 0x11
34#define R_DRIVE_CURRENT 0x12
35#define G_DRIVE_CURRENT 0x13
36#define B_DRIVE_CURRENT 0x14
37#define READ_REG_SELECT 0x15
38#define RGB_DRIVER_ENABLE 0x16
39
40#define CPU_IF_MODE 0x18
41#define FRAME_RATE 0x19
42#define CPU_IF_SYNC_METHOD 0x1A
43#define CPU_IF_SOF 0x1B
44#define CPU_IF_EOF 0x1C
45#define CPU_IF_SLEEP 0x1D
46
47#define SEQUENCE_MODE 0x1E
48#define SOFT_RESET 0x1F
49#define FRONT_END_RESET 0x21
50#define AUTO_PWR_ENABLE 0x22
51
52#define VSYNC_LINE_DELAY 0x23
53#define CPU_PI_HORIZ_START 0x24
54#define CPU_PI_VERT_START 0x25
55#define CPU_PI_HORIZ_WIDTH 0x26
56#define CPU_PI_VERT_HEIGHT 0x27
57
58#define PIXEL_MASK_CROP 0x28
59#define CROP_FIRST_LINE 0x29
60#define CROP_LAST_LINE 0x2A
61#define CROP_FIRST_PIXEL 0x2B
62#define CROP_LAST_PIXEL 0x2C
63#define DMD_PARK_TRIGGER 0x2D
64
65#define MISC_REG 0x30
66
67/* AGC registers */
68#define AGC_CTRL 0x50
69#define AGC_CLIPPED_PIXS 0x55
70#define AGC_BRIGHT_PIXS 0x56
71#define AGC_BG_PIXS 0x57
72#define AGC_SAFETY_MARGIN 0x17
73
74/* Color Coordinate Adjustment registers */
75#define CCA_ENABLE 0x5E
76#define CCA_C1A 0x5F
77#define CCA_C1B 0x60
78#define CCA_C1C 0x61
79#define CCA_C2A 0x62
80#define CCA_C2B 0x63
81#define CCA_C2C 0x64
82#define CCA_C3A 0x65
83#define CCA_C3B 0x66
84#define CCA_C3C 0x67
85#define CCA_C7A 0x71
86#define CCA_C7B 0x72
87#define CCA_C7C 0x73
88
89/**
90 * DLP Pico Processor 2600 comes with flash
91 * We can do DMA operations from flash for accessing Look Up Tables
92 */
93#define DMA_STATUS 0x100
94#define FLASH_ADDR_BYTES 0x74
95#define FLASH_DUMMY_BYTES 0x75
96#define FLASH_WRITE_BYTES 0x76
97#define FLASH_READ_BYTES 0x77
98#define FLASH_OPCODE 0x78
99#define FLASH_START_ADDR 0x79
100#define FLASH_DUMMY2 0x7A
101#define FLASH_WRITE_DATA 0x7B
102
103#define TEMPORAL_DITH_DISABLE 0x7E
104#define SEQ_CONTROL 0x82
105#define SEQ_VECTOR 0x83
106
107/* DMD is Digital Micromirror Device */
108#define DMD_BLOCK_COUNT 0x84
109#define DMD_VCC_CONTROL 0x86
110#define DMD_PARK_PULSE_COUNT 0x87
111#define DMD_PARK_PULSE_WIDTH 0x88
112#define DMD_PARK_DELAY 0x89
113#define DMD_SHADOW_ENABLE 0x8E
114#define SEQ_STATUS 0x8F
115#define FLASH_CLOCK_CONTROL 0x98
116#define DMD_PARK 0x2D
117
118#define SDRAM_BIST_ENABLE 0x46
119#define DDR_DRIVER_STRENGTH 0x9A
120#define SDC_ENABLE 0x9D
121#define SDC_BUFF_SWAP_DISABLE 0xA3
122#define CURTAIN_CONTROL 0xA6
123#define DDR_BUS_SWAP_ENABLE 0xA7
124#define DMD_TRC_ENABLE 0xA8
125#define DMD_BUS_SWAP_ENABLE 0xA9
126
127#define ACTGEN_ENABLE 0xAE
128#define ACTGEN_CONTROL 0xAF
129#define ACTGEN_HORIZ_BP 0xB0
130#define ACTGEN_VERT_BP 0xB1
131
132/* Look Up Table access */
133#define CMT_SPLASH_LUT_START_ADDR 0xFA
134#define CMT_SPLASH_LUT_DEST_SELECT 0xFB
135#define CMT_SPLASH_LUT_DATA 0xFC
136#define SEQ_RESET_LUT_START_ADDR 0xFD
137#define SEQ_RESET_LUT_DEST_SELECT 0xFE
138#define SEQ_RESET_LUT_DATA 0xFF
139
140/* Input source definitions */
141#define PARALLEL_RGB 0
142#define INT_TEST_PATTERN 1
143#define SPLASH_SCREEN 2
144#define CPU_INTF 3
145#define BT656 4
146
147/* Standard input resolution definitions */
148#define QWVGA_LANDSCAPE 3 /* (427h*240v) */
149#define WVGA_864_LANDSCAPE 21 /* (864h*480v) */
150#define WVGA_DMD_OPTICAL_TEST 35 /* (608h*684v) */
151
152/* Standard data format definitions */
153#define RGB565 0
154#define RGB666 1
155#define RGB888 2
156
157/* Test Pattern definitions */
158#define TPG_CHECKERBOARD 0
159#define TPG_BLACK 1
160#define TPG_WHITE 2
161#define TPG_RED 3
162#define TPG_BLUE 4
163#define TPG_GREEN 5
164#define TPG_VLINES_BLACK 6
165#define TPG_HLINES_BLACK 7
166#define TPG_VLINES_ALT 8
167#define TPG_HLINES_ALT 9
168#define TPG_DIAG_LINES 10
169#define TPG_GREYRAMP_VERT 11
170#define TPG_GREYRAMP_HORIZ 12
171#define TPG_ANSI_CHECKERBOARD 13
172
173/* sequence mode definitions */
174#define SEQ_FREE_RUN 0
175#define SEQ_LOCK 1
176
177/* curtain color definitions */
178#define CURTAIN_BLACK 0
179#define CURTAIN_RED 1
180#define CURTAIN_GREEN 2
181#define CURTAIN_BLUE 3
182#define CURTAIN_YELLOW 4
183#define CURTAIN_MAGENTA 5
184#define CURTAIN_CYAN 6
185#define CURTAIN_WHITE 7
186
187/* LUT definitions */
188#define CMT_LUT_NONE 0
189#define CMT_LUT_GREEN 1
190#define CMT_LUT_RED 2
191#define CMT_LUT_BLUE 3
192#define CMT_LUT_ALL 4
193#define SPLASH_LUT 5
194
195#define SEQ_LUT_NONE 0
196#define SEQ_DRC_LUT_0 1
197#define SEQ_DRC_LUT_1 2
198#define SEQ_DRC_LUT_2 3
199#define SEQ_DRC_LUT_3 4
200#define SEQ_SEQ_LUT 5
201#define SEQ_DRC_LUT_ALL 6
202#define WPC_PROGRAM_LUT 7
203
204#define BITSTREAM_START_ADDR 0x00000000
205#define BITSTREAM_SIZE 0x00040000
206
207#define WPC_FW_0_START_ADDR 0x00040000
208#define WPC_FW_0_SIZE 0x00000ce8
209
210#define SEQUENCE_0_START_ADDR 0x00044000
211#define SEQUENCE_0_SIZE 0x00001000
212
213#define SEQUENCE_1_START_ADDR 0x00045000
214#define SEQUENCE_1_SIZE 0x00000d10
215
216#define SEQUENCE_2_START_ADDR 0x00046000
217#define SEQUENCE_2_SIZE 0x00000d10
218
219#define SEQUENCE_3_START_ADDR 0x00047000
220#define SEQUENCE_3_SIZE 0x00000d10
221
222#define SEQUENCE_4_START_ADDR 0x00048000
223#define SEQUENCE_4_SIZE 0x00000d10
224
225#define SEQUENCE_5_START_ADDR 0x00049000
226#define SEQUENCE_5_SIZE 0x00000d10
227
228#define SEQUENCE_6_START_ADDR 0x0004a000
229#define SEQUENCE_6_SIZE 0x00000d10
230
231#define CMT_LUT_0_START_ADDR 0x0004b200
232#define CMT_LUT_0_SIZE 0x00000600
233
234#define CMT_LUT_1_START_ADDR 0x0004b800
235#define CMT_LUT_1_SIZE 0x00000600
236
237#define CMT_LUT_2_START_ADDR 0x0004be00
238#define CMT_LUT_2_SIZE 0x00000600
239
240#define CMT_LUT_3_START_ADDR 0x0004c400
241#define CMT_LUT_3_SIZE 0x00000600
242
243#define CMT_LUT_4_START_ADDR 0x0004ca00
244#define CMT_LUT_4_SIZE 0x00000600
245
246#define CMT_LUT_5_START_ADDR 0x0004d000
247#define CMT_LUT_5_SIZE 0x00000600
248
249#define CMT_LUT_6_START_ADDR 0x0004d600
250#define CMT_LUT_6_SIZE 0x00000600
251
252#define DRC_TABLE_0_START_ADDR 0x0004dc00
253#define DRC_TABLE_0_SIZE 0x00000100
254
255#define SPLASH_0_START_ADDR 0x0004dd00
256#define SPLASH_0_SIZE 0x00032280
257
258#define SEQUENCE_7_START_ADDR 0x00080000
259#define SEQUENCE_7_SIZE 0x00000d10
260
261#define SEQUENCE_8_START_ADDR 0x00081800
262#define SEQUENCE_8_SIZE 0x00000d10
263
264#define SEQUENCE_9_START_ADDR 0x00083000
265#define SEQUENCE_9_SIZE 0x00000d10
266
267#define CMT_LUT_7_START_ADDR 0x0008e000
268#define CMT_LUT_7_SIZE 0x00000600
269
270#define CMT_LUT_8_START_ADDR 0x0008e800
271#define CMT_LUT_8_SIZE 0x00000600
272
273#define CMT_LUT_9_START_ADDR 0x0008f000
274#define CMT_LUT_9_SIZE 0x00000600
275
276#define SPLASH_1_START_ADDR 0x0009a000
277#define SPLASH_1_SIZE 0x00032280
278
279#define SPLASH_2_START_ADDR 0x000cd000
280#define SPLASH_2_SIZE 0x00032280
281
282#define SPLASH_3_START_ADDR 0x00100000
283#define SPLASH_3_SIZE 0x00032280
284
285#define OPT_SPLASH_0_START_ADDR 0x00134000
286#define OPT_SPLASH_0_SIZE 0x000cb100
287
288#endif
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index cada8c621e0..ba38b3ad17d 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -44,12 +44,6 @@ static struct omap_video_timings sharp_ls_timings = {
44 .vsw = 1, 44 .vsw = 1,
45 .vfp = 1, 45 .vfp = 1,
46 .vbp = 1, 46 .vbp = 1,
47
48 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
49 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
50 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
51 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
52 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
53}; 47};
54 48
55static int sharp_ls_bl_update_status(struct backlight_device *bl) 49static int sharp_ls_bl_update_status(struct backlight_device *bl)
@@ -92,6 +86,9 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
92 struct sharp_data *sd; 86 struct sharp_data *sd;
93 int r; 87 int r;
94 88
89 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
90 OMAP_DSS_LCD_IHS;
91 dssdev->panel.acb = 0x28;
95 dssdev->panel.timings = sharp_ls_timings; 92 dssdev->panel.timings = sharp_ls_timings;
96 93
97 sd = kzalloc(sizeof(*sd), GFP_KERNEL); 94 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
@@ -142,9 +139,6 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
142 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 139 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
143 return 0; 140 return 0;
144 141
145 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
146 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
147
148 r = omapdss_dpi_display_enable(dssdev); 142 r = omapdss_dpi_display_enable(dssdev);
149 if (r) 143 if (r)
150 goto err0; 144 goto err0;
@@ -194,12 +188,29 @@ static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
194 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 188 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
195} 189}
196 190
191static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
192{
193 sharp_ls_power_off(dssdev);
194 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
195 return 0;
196}
197
198static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
199{
200 int r;
201 r = sharp_ls_power_on(dssdev);
202 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
203 return r;
204}
205
197static struct omap_dss_driver sharp_ls_driver = { 206static struct omap_dss_driver sharp_ls_driver = {
198 .probe = sharp_ls_panel_probe, 207 .probe = sharp_ls_panel_probe,
199 .remove = __exit_p(sharp_ls_panel_remove), 208 .remove = __exit_p(sharp_ls_panel_remove),
200 209
201 .enable = sharp_ls_panel_enable, 210 .enable = sharp_ls_panel_enable,
202 .disable = sharp_ls_panel_disable, 211 .disable = sharp_ls_panel_disable,
212 .suspend = sharp_ls_panel_suspend,
213 .resume = sharp_ls_panel_resume,
203 214
204 .driver = { 215 .driver = {
205 .name = "sharp_ls_panel", 216 .name = "sharp_ls_panel",
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index a32407a5735..4e888ac09b3 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -30,16 +30,31 @@
30#include <linux/gpio.h> 30#include <linux/gpio.h>
31#include <linux/workqueue.h> 31#include <linux/workqueue.h>
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/regulator/consumer.h>
33#include <linux/mutex.h> 34#include <linux/mutex.h>
34 35
35#include <video/omapdss.h> 36#include <video/omapdss.h>
36#include <video/omap-panel-nokia-dsi.h> 37#include <video/omap-panel-nokia-dsi.h>
37#include <video/mipi_display.h>
38 38
39/* DSI Virtual channel. Hardcoded for now. */ 39/* DSI Virtual channel. Hardcoded for now. */
40#define TCH 0 40#define TCH 0
41 41
42#define DCS_READ_NUM_ERRORS 0x05 42#define DCS_READ_NUM_ERRORS 0x05
43#define DCS_READ_POWER_MODE 0x0a
44#define DCS_READ_MADCTL 0x0b
45#define DCS_READ_PIXEL_FORMAT 0x0c
46#define DCS_RDDSDR 0x0f
47#define DCS_SLEEP_IN 0x10
48#define DCS_SLEEP_OUT 0x11
49#define DCS_DISPLAY_OFF 0x28
50#define DCS_DISPLAY_ON 0x29
51#define DCS_COLUMN_ADDR 0x2a
52#define DCS_PAGE_ADDR 0x2b
53#define DCS_MEMORY_WRITE 0x2c
54#define DCS_TEAR_OFF 0x34
55#define DCS_TEAR_ON 0x35
56#define DCS_MEM_ACC_CTRL 0x36
57#define DCS_PIXEL_FORMAT 0x3a
43#define DCS_BRIGHTNESS 0x51 58#define DCS_BRIGHTNESS 0x51
44#define DCS_CTRL_DISPLAY 0x53 59#define DCS_CTRL_DISPLAY 0x53
45#define DCS_WRITE_CABC 0x55 60#define DCS_WRITE_CABC 0x55
@@ -54,6 +69,73 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
54 69
55static int taal_panel_reset(struct omap_dss_device *dssdev); 70static int taal_panel_reset(struct omap_dss_device *dssdev);
56 71
72struct panel_regulator {
73 struct regulator *regulator;
74 const char *name;
75 int min_uV;
76 int max_uV;
77};
78
79static void free_regulators(struct panel_regulator *regulators, int n)
80{
81 int i;
82
83 for (i = 0; i < n; i++) {
84 /* disable/put in reverse order */
85 regulator_disable(regulators[n - i - 1].regulator);
86 regulator_put(regulators[n - i - 1].regulator);
87 }
88}
89
90static int init_regulators(struct omap_dss_device *dssdev,
91 struct panel_regulator *regulators, int n)
92{
93 int r, i, v;
94
95 for (i = 0; i < n; i++) {
96 struct regulator *reg;
97
98 reg = regulator_get(&dssdev->dev, regulators[i].name);
99 if (IS_ERR(reg)) {
100 dev_err(&dssdev->dev, "failed to get regulator %s\n",
101 regulators[i].name);
102 r = PTR_ERR(reg);
103 goto err;
104 }
105
106 /* FIXME: better handling of fixed vs. variable regulators */
107 v = regulator_get_voltage(reg);
108 if (v < regulators[i].min_uV || v > regulators[i].max_uV) {
109 r = regulator_set_voltage(reg, regulators[i].min_uV,
110 regulators[i].max_uV);
111 if (r) {
112 dev_err(&dssdev->dev,
113 "failed to set regulator %s voltage\n",
114 regulators[i].name);
115 regulator_put(reg);
116 goto err;
117 }
118 }
119
120 r = regulator_enable(reg);
121 if (r) {
122 dev_err(&dssdev->dev, "failed to enable regulator %s\n",
123 regulators[i].name);
124 regulator_put(reg);
125 goto err;
126 }
127
128 regulators[i].regulator = reg;
129 }
130
131 return 0;
132
133err:
134 free_regulators(regulators, i);
135
136 return r;
137}
138
57/** 139/**
58 * struct panel_config - panel configuration 140 * struct panel_config - panel configuration
59 * @name: panel name 141 * @name: panel name
@@ -82,6 +164,8 @@ struct panel_config {
82 unsigned int low; 164 unsigned int low;
83 } reset_sequence; 165 } reset_sequence;
84 166
167 struct panel_regulator *regulators;
168 int num_regulators;
85}; 169};
86 170
87enum { 171enum {
@@ -121,18 +205,6 @@ struct taal_data {
121 205
122 struct omap_dss_device *dssdev; 206 struct omap_dss_device *dssdev;
123 207
124 /* panel specific HW info */
125 struct panel_config *panel_config;
126
127 /* panel HW configuration from DT or platform data */
128 int reset_gpio;
129 int ext_te_gpio;
130
131 bool use_dsi_backlight;
132
133 struct omap_dsi_pin_config pin_config;
134
135 /* runtime variables */
136 bool enabled; 208 bool enabled;
137 u8 rotate; 209 u8 rotate;
138 bool mirror; 210 bool mirror;
@@ -140,10 +212,18 @@ struct taal_data {
140 bool te_enabled; 212 bool te_enabled;
141 213
142 atomic_t do_update; 214 atomic_t do_update;
215 struct {
216 u16 x;
217 u16 y;
218 u16 w;
219 u16 h;
220 } update_region;
143 int channel; 221 int channel;
144 222
145 struct delayed_work te_timeout_work; 223 struct delayed_work te_timeout_work;
146 224
225 bool use_dsi_bl;
226
147 bool cabc_broken; 227 bool cabc_broken;
148 unsigned cabc_mode; 228 unsigned cabc_mode;
149 229
@@ -157,8 +237,16 @@ struct taal_data {
157 bool ulps_enabled; 237 bool ulps_enabled;
158 unsigned ulps_timeout; 238 unsigned ulps_timeout;
159 struct delayed_work ulps_work; 239 struct delayed_work ulps_work;
240
241 struct panel_config *panel_config;
160}; 242};
161 243
244static inline struct nokia_dsi_panel_data
245*get_panel_data(const struct omap_dss_device *dssdev)
246{
247 return (struct nokia_dsi_panel_data *) dssdev->data;
248}
249
162static void taal_esd_work(struct work_struct *work); 250static void taal_esd_work(struct work_struct *work);
163static void taal_ulps_work(struct work_struct *work); 251static void taal_ulps_work(struct work_struct *work);
164 252
@@ -214,7 +302,7 @@ static int taal_sleep_in(struct taal_data *td)
214 302
215 hw_guard_wait(td); 303 hw_guard_wait(td);
216 304
217 cmd = MIPI_DCS_ENTER_SLEEP_MODE; 305 cmd = DCS_SLEEP_IN;
218 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1); 306 r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
219 if (r) 307 if (r)
220 return r; 308 return r;
@@ -233,7 +321,7 @@ static int taal_sleep_out(struct taal_data *td)
233 321
234 hw_guard_wait(td); 322 hw_guard_wait(td);
235 323
236 r = taal_dcs_write_0(td, MIPI_DCS_EXIT_SLEEP_MODE); 324 r = taal_dcs_write_0(td, DCS_SLEEP_OUT);
237 if (r) 325 if (r)
238 return r; 326 return r;
239 327
@@ -268,7 +356,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
268 u8 mode; 356 u8 mode;
269 int b5, b6, b7; 357 int b5, b6, b7;
270 358
271 r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode); 359 r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode);
272 if (r) 360 if (r)
273 return r; 361 return r;
274 362
@@ -302,7 +390,7 @@ static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror)
302 mode &= ~((1<<7) | (1<<6) | (1<<5)); 390 mode &= ~((1<<7) | (1<<6) | (1<<5));
303 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); 391 mode |= (b7 << 7) | (b6 << 6) | (b5 << 5);
304 392
305 return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode); 393 return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode);
306} 394}
307 395
308static int taal_set_update_window(struct taal_data *td, 396static int taal_set_update_window(struct taal_data *td,
@@ -315,7 +403,7 @@ static int taal_set_update_window(struct taal_data *td,
315 u16 y2 = y + h - 1; 403 u16 y2 = y + h - 1;
316 404
317 u8 buf[5]; 405 u8 buf[5];
318 buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS; 406 buf[0] = DCS_COLUMN_ADDR;
319 buf[1] = (x1 >> 8) & 0xff; 407 buf[1] = (x1 >> 8) & 0xff;
320 buf[2] = (x1 >> 0) & 0xff; 408 buf[2] = (x1 >> 0) & 0xff;
321 buf[3] = (x2 >> 8) & 0xff; 409 buf[3] = (x2 >> 8) & 0xff;
@@ -325,7 +413,7 @@ static int taal_set_update_window(struct taal_data *td,
325 if (r) 413 if (r)
326 return r; 414 return r;
327 415
328 buf[0] = MIPI_DCS_SET_PAGE_ADDRESS; 416 buf[0] = DCS_PAGE_ADDR;
329 buf[1] = (y1 >> 8) & 0xff; 417 buf[1] = (y1 >> 8) & 0xff;
330 buf[2] = (y1 >> 0) & 0xff; 418 buf[2] = (y1 >> 0) & 0xff;
331 buf[3] = (y2 >> 8) & 0xff; 419 buf[3] = (y2 >> 8) & 0xff;
@@ -375,6 +463,7 @@ static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
375static int taal_enter_ulps(struct omap_dss_device *dssdev) 463static int taal_enter_ulps(struct omap_dss_device *dssdev)
376{ 464{
377 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 465 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
466 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
378 int r; 467 int r;
379 468
380 if (td->ulps_enabled) 469 if (td->ulps_enabled)
@@ -386,8 +475,7 @@ static int taal_enter_ulps(struct omap_dss_device *dssdev)
386 if (r) 475 if (r)
387 goto err; 476 goto err;
388 477
389 if (gpio_is_valid(td->ext_te_gpio)) 478 disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
390 disable_irq(gpio_to_irq(td->ext_te_gpio));
391 479
392 omapdss_dsi_display_disable(dssdev, false, true); 480 omapdss_dsi_display_disable(dssdev, false, true);
393 481
@@ -409,6 +497,7 @@ err:
409static int taal_exit_ulps(struct omap_dss_device *dssdev) 497static int taal_exit_ulps(struct omap_dss_device *dssdev)
410{ 498{
411 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 499 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
500 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
412 int r; 501 int r;
413 502
414 if (!td->ulps_enabled) 503 if (!td->ulps_enabled)
@@ -428,8 +517,7 @@ static int taal_exit_ulps(struct omap_dss_device *dssdev)
428 goto err2; 517 goto err2;
429 } 518 }
430 519
431 if (gpio_is_valid(td->ext_te_gpio)) 520 enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
432 enable_irq(gpio_to_irq(td->ext_te_gpio));
433 521
434 taal_queue_ulps_work(dssdev); 522 taal_queue_ulps_work(dssdev);
435 523
@@ -442,8 +530,7 @@ err2:
442 530
443 r = taal_panel_reset(dssdev); 531 r = taal_panel_reset(dssdev);
444 if (!r) { 532 if (!r) {
445 if (gpio_is_valid(td->ext_te_gpio)) 533 enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
446 enable_irq(gpio_to_irq(td->ext_te_gpio));
447 td->ulps_enabled = false; 534 td->ulps_enabled = false;
448 } 535 }
449err1: 536err1:
@@ -468,6 +555,7 @@ static int taal_bl_update_status(struct backlight_device *dev)
468{ 555{
469 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); 556 struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
470 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 557 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
558 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
471 int r; 559 int r;
472 int level; 560 int level;
473 561
@@ -481,16 +569,23 @@ static int taal_bl_update_status(struct backlight_device *dev)
481 569
482 mutex_lock(&td->lock); 570 mutex_lock(&td->lock);
483 571
484 if (td->enabled) { 572 if (td->use_dsi_bl) {
485 dsi_bus_lock(dssdev); 573 if (td->enabled) {
574 dsi_bus_lock(dssdev);
486 575
487 r = taal_wake_up(dssdev); 576 r = taal_wake_up(dssdev);
488 if (!r) 577 if (!r)
489 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); 578 r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
490 579
491 dsi_bus_unlock(dssdev); 580 dsi_bus_unlock(dssdev);
581 } else {
582 r = 0;
583 }
492 } else { 584 } else {
493 r = 0; 585 if (!panel_data->set_backlight)
586 r = -EINVAL;
587 else
588 r = panel_data->set_backlight(dssdev, level);
494 } 589 }
495 590
496 mutex_unlock(&td->lock); 591 mutex_unlock(&td->lock);
@@ -512,6 +607,12 @@ static const struct backlight_ops taal_bl_ops = {
512 .update_status = taal_bl_update_status, 607 .update_status = taal_bl_update_status,
513}; 608};
514 609
610static void taal_get_timings(struct omap_dss_device *dssdev,
611 struct omap_video_timings *timings)
612{
613 *timings = dssdev->panel.timings;
614}
615
515static void taal_get_resolution(struct omap_dss_device *dssdev, 616static void taal_get_resolution(struct omap_dss_device *dssdev,
516 u16 *xres, u16 *yres) 617 u16 *xres, u16 *yres)
517{ 618{
@@ -531,7 +632,7 @@ static ssize_t taal_num_errors_show(struct device *dev,
531{ 632{
532 struct omap_dss_device *dssdev = to_dss_device(dev); 633 struct omap_dss_device *dssdev = to_dss_device(dev);
533 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 634 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
534 u8 errors = 0; 635 u8 errors;
535 int r; 636 int r;
536 637
537 mutex_lock(&td->lock); 638 mutex_lock(&td->lock);
@@ -840,153 +941,145 @@ static struct attribute_group taal_attr_group = {
840static void taal_hw_reset(struct omap_dss_device *dssdev) 941static void taal_hw_reset(struct omap_dss_device *dssdev)
841{ 942{
842 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 943 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
944 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
843 945
844 if (!gpio_is_valid(td->reset_gpio)) 946 if (panel_data->reset_gpio == -1)
845 return; 947 return;
846 948
847 gpio_set_value(td->reset_gpio, 1); 949 gpio_set_value(panel_data->reset_gpio, 1);
848 if (td->panel_config->reset_sequence.high) 950 if (td->panel_config->reset_sequence.high)
849 udelay(td->panel_config->reset_sequence.high); 951 udelay(td->panel_config->reset_sequence.high);
850 /* reset the panel */ 952 /* reset the panel */
851 gpio_set_value(td->reset_gpio, 0); 953 gpio_set_value(panel_data->reset_gpio, 0);
852 /* assert reset */ 954 /* assert reset */
853 if (td->panel_config->reset_sequence.low) 955 if (td->panel_config->reset_sequence.low)
854 udelay(td->panel_config->reset_sequence.low); 956 udelay(td->panel_config->reset_sequence.low);
855 gpio_set_value(td->reset_gpio, 1); 957 gpio_set_value(panel_data->reset_gpio, 1);
856 /* wait after releasing reset */ 958 /* wait after releasing reset */
857 if (td->panel_config->sleep.hw_reset) 959 if (td->panel_config->sleep.hw_reset)
858 msleep(td->panel_config->sleep.hw_reset); 960 msleep(td->panel_config->sleep.hw_reset);
859} 961}
860 962
861static void taal_probe_pdata(struct taal_data *td,
862 const struct nokia_dsi_panel_data *pdata)
863{
864 td->reset_gpio = pdata->reset_gpio;
865
866 if (pdata->use_ext_te)
867 td->ext_te_gpio = pdata->ext_te_gpio;
868 else
869 td->ext_te_gpio = -1;
870
871 td->esd_interval = pdata->esd_interval;
872 td->ulps_timeout = pdata->ulps_timeout;
873
874 td->use_dsi_backlight = pdata->use_dsi_backlight;
875
876 td->pin_config = pdata->pin_config;
877}
878
879static int taal_probe(struct omap_dss_device *dssdev) 963static int taal_probe(struct omap_dss_device *dssdev)
880{ 964{
881 struct backlight_properties props; 965 struct backlight_properties props;
882 struct taal_data *td; 966 struct taal_data *td;
883 struct backlight_device *bldev = NULL; 967 struct backlight_device *bldev;
968 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
969 struct panel_config *panel_config = NULL;
884 int r, i; 970 int r, i;
885 const char *panel_name;
886 971
887 dev_dbg(&dssdev->dev, "probe\n"); 972 dev_dbg(&dssdev->dev, "probe\n");
888 973
889 td = devm_kzalloc(&dssdev->dev, sizeof(*td), GFP_KERNEL); 974 if (!panel_data || !panel_data->name) {
890 if (!td) 975 r = -EINVAL;
891 return -ENOMEM; 976 goto err;
892
893 dev_set_drvdata(&dssdev->dev, td);
894 td->dssdev = dssdev;
895
896 if (dssdev->data) {
897 const struct nokia_dsi_panel_data *pdata = dssdev->data;
898
899 taal_probe_pdata(td, pdata);
900
901 panel_name = pdata->name;
902 } else {
903 return -ENODEV;
904 } 977 }
905 978
906 if (panel_name == NULL)
907 return -EINVAL;
908
909 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { 979 for (i = 0; i < ARRAY_SIZE(panel_configs); i++) {
910 if (strcmp(panel_name, panel_configs[i].name) == 0) { 980 if (strcmp(panel_data->name, panel_configs[i].name) == 0) {
911 td->panel_config = &panel_configs[i]; 981 panel_config = &panel_configs[i];
912 break; 982 break;
913 } 983 }
914 } 984 }
915 985
916 if (!td->panel_config) 986 if (!panel_config) {
917 return -EINVAL; 987 r = -EINVAL;
918 988 goto err;
919 dssdev->panel.timings = td->panel_config->timings;
920 dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
921 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
922 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
923
924 mutex_init(&td->lock);
925
926 atomic_set(&td->do_update, 0);
927
928 if (gpio_is_valid(td->reset_gpio)) {
929 r = devm_gpio_request_one(&dssdev->dev, td->reset_gpio,
930 GPIOF_OUT_INIT_LOW, "taal rst");
931 if (r) {
932 dev_err(&dssdev->dev, "failed to request reset gpio\n");
933 return r;
934 }
935 } 989 }
936 990
937 if (gpio_is_valid(td->ext_te_gpio)) { 991 dssdev->panel.config = OMAP_DSS_LCD_TFT;
938 r = devm_gpio_request_one(&dssdev->dev, td->ext_te_gpio, 992 dssdev->panel.timings = panel_config->timings;
939 GPIOF_IN, "taal irq"); 993 dssdev->ctrl.pixel_size = 24;
940 if (r) {
941 dev_err(&dssdev->dev, "GPIO request failed\n");
942 return r;
943 }
944 994
945 r = devm_request_irq(&dssdev->dev, gpio_to_irq(td->ext_te_gpio), 995 td = kzalloc(sizeof(*td), GFP_KERNEL);
946 taal_te_isr, 996 if (!td) {
947 IRQF_TRIGGER_RISING, 997 r = -ENOMEM;
948 "taal vsync", dssdev); 998 goto err;
999 }
1000 td->dssdev = dssdev;
1001 td->panel_config = panel_config;
1002 td->esd_interval = panel_data->esd_interval;
1003 td->ulps_enabled = false;
1004 td->ulps_timeout = panel_data->ulps_timeout;
949 1005
950 if (r) { 1006 mutex_init(&td->lock);
951 dev_err(&dssdev->dev, "IRQ request failed\n");
952 return r;
953 }
954 1007
955 INIT_DEFERRABLE_WORK(&td->te_timeout_work, 1008 atomic_set(&td->do_update, 0);
956 taal_te_timeout_work_callback);
957 1009
958 dev_dbg(&dssdev->dev, "Using GPIO TE\n"); 1010 r = init_regulators(dssdev, panel_config->regulators,
959 } 1011 panel_config->num_regulators);
1012 if (r)
1013 goto err_reg;
960 1014
961 td->workqueue = create_singlethread_workqueue("taal_esd"); 1015 td->workqueue = create_singlethread_workqueue("taal_esd");
962 if (td->workqueue == NULL) { 1016 if (td->workqueue == NULL) {
963 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 1017 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
964 return -ENOMEM; 1018 r = -ENOMEM;
1019 goto err_wq;
965 } 1020 }
966 INIT_DEFERRABLE_WORK(&td->esd_work, taal_esd_work); 1021 INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
967 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work); 1022 INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
968 1023
1024 dev_set_drvdata(&dssdev->dev, td);
1025
969 taal_hw_reset(dssdev); 1026 taal_hw_reset(dssdev);
970 1027
971 if (td->use_dsi_backlight) { 1028 /* if no platform set_backlight() defined, presume DSI backlight
972 memset(&props, 0, sizeof(struct backlight_properties)); 1029 * control */
1030 memset(&props, 0, sizeof(struct backlight_properties));
1031 if (!panel_data->set_backlight)
1032 td->use_dsi_bl = true;
1033
1034 if (td->use_dsi_bl)
973 props.max_brightness = 255; 1035 props.max_brightness = 255;
1036 else
1037 props.max_brightness = 127;
1038
1039 props.type = BACKLIGHT_RAW;
1040 bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
1041 dssdev, &taal_bl_ops, &props);
1042 if (IS_ERR(bldev)) {
1043 r = PTR_ERR(bldev);
1044 goto err_bl;
1045 }
1046
1047 td->bldev = bldev;
1048
1049 bldev->props.fb_blank = FB_BLANK_UNBLANK;
1050 bldev->props.power = FB_BLANK_UNBLANK;
1051 if (td->use_dsi_bl)
1052 bldev->props.brightness = 255;
1053 else
1054 bldev->props.brightness = 127;
974 1055
975 props.type = BACKLIGHT_RAW; 1056 taal_bl_update_status(bldev);
976 bldev = backlight_device_register(dev_name(&dssdev->dev), 1057
977 &dssdev->dev, dssdev, &taal_bl_ops, &props); 1058 if (panel_data->use_ext_te) {
978 if (IS_ERR(bldev)) { 1059 int gpio = panel_data->ext_te_gpio;
979 r = PTR_ERR(bldev); 1060
980 goto err_bl; 1061 r = gpio_request(gpio, "taal irq");
1062 if (r) {
1063 dev_err(&dssdev->dev, "GPIO request failed\n");
1064 goto err_gpio;
981 } 1065 }
982 1066
983 td->bldev = bldev; 1067 gpio_direction_input(gpio);
984 1068
985 bldev->props.fb_blank = FB_BLANK_UNBLANK; 1069 r = request_irq(gpio_to_irq(gpio), taal_te_isr,
986 bldev->props.power = FB_BLANK_UNBLANK; 1070 IRQF_DISABLED | IRQF_TRIGGER_RISING,
987 bldev->props.brightness = 255; 1071 "taal vsync", dssdev);
988 1072
989 taal_bl_update_status(bldev); 1073 if (r) {
1074 dev_err(&dssdev->dev, "IRQ request failed\n");
1075 gpio_free(gpio);
1076 goto err_irq;
1077 }
1078
1079 INIT_DELAYED_WORK_DEFERRABLE(&td->te_timeout_work,
1080 taal_te_timeout_work_callback);
1081
1082 dev_dbg(&dssdev->dev, "Using GPIO TE\n");
990 } 1083 }
991 1084
992 r = omap_dsi_request_vc(dssdev, &td->channel); 1085 r = omap_dsi_request_vc(dssdev, &td->channel);
@@ -1012,16 +1105,27 @@ static int taal_probe(struct omap_dss_device *dssdev)
1012err_vc_id: 1105err_vc_id:
1013 omap_dsi_release_vc(dssdev, td->channel); 1106 omap_dsi_release_vc(dssdev, td->channel);
1014err_req_vc: 1107err_req_vc:
1015 if (bldev != NULL) 1108 if (panel_data->use_ext_te)
1016 backlight_device_unregister(bldev); 1109 free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev);
1110err_irq:
1111 if (panel_data->use_ext_te)
1112 gpio_free(panel_data->ext_te_gpio);
1113err_gpio:
1114 backlight_device_unregister(bldev);
1017err_bl: 1115err_bl:
1018 destroy_workqueue(td->workqueue); 1116 destroy_workqueue(td->workqueue);
1117err_wq:
1118 free_regulators(panel_config->regulators, panel_config->num_regulators);
1119err_reg:
1120 kfree(td);
1121err:
1019 return r; 1122 return r;
1020} 1123}
1021 1124
1022static void __exit taal_remove(struct omap_dss_device *dssdev) 1125static void __exit taal_remove(struct omap_dss_device *dssdev)
1023{ 1126{
1024 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1127 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1128 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1025 struct backlight_device *bldev; 1129 struct backlight_device *bldev;
1026 1130
1027 dev_dbg(&dssdev->dev, "remove\n"); 1131 dev_dbg(&dssdev->dev, "remove\n");
@@ -1029,19 +1133,28 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1029 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); 1133 sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group);
1030 omap_dsi_release_vc(dssdev, td->channel); 1134 omap_dsi_release_vc(dssdev, td->channel);
1031 1135
1032 bldev = td->bldev; 1136 if (panel_data->use_ext_te) {
1033 if (bldev != NULL) { 1137 int gpio = panel_data->ext_te_gpio;
1034 bldev->props.power = FB_BLANK_POWERDOWN; 1138 free_irq(gpio_to_irq(gpio), dssdev);
1035 taal_bl_update_status(bldev); 1139 gpio_free(gpio);
1036 backlight_device_unregister(bldev);
1037 } 1140 }
1038 1141
1142 bldev = td->bldev;
1143 bldev->props.power = FB_BLANK_POWERDOWN;
1144 taal_bl_update_status(bldev);
1145 backlight_device_unregister(bldev);
1146
1039 taal_cancel_ulps_work(dssdev); 1147 taal_cancel_ulps_work(dssdev);
1040 taal_cancel_esd_work(dssdev); 1148 taal_cancel_esd_work(dssdev);
1041 destroy_workqueue(td->workqueue); 1149 destroy_workqueue(td->workqueue);
1042 1150
1043 /* reset, to be sure that the panel is in a valid state */ 1151 /* reset, to be sure that the panel is in a valid state */
1044 taal_hw_reset(dssdev); 1152 taal_hw_reset(dssdev);
1153
1154 free_regulators(td->panel_config->regulators,
1155 td->panel_config->num_regulators);
1156
1157 kfree(td);
1045} 1158}
1046 1159
1047static int taal_power_on(struct omap_dss_device *dssdev) 1160static int taal_power_on(struct omap_dss_device *dssdev)
@@ -1050,23 +1163,6 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1050 u8 id1, id2, id3; 1163 u8 id1, id2, id3;
1051 int r; 1164 int r;
1052 1165
1053 r = omapdss_dsi_configure_pins(dssdev, &td->pin_config);
1054 if (r) {
1055 dev_err(&dssdev->dev, "failed to configure DSI pins\n");
1056 goto err0;
1057 };
1058
1059 omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res,
1060 dssdev->panel.timings.y_res);
1061 omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888);
1062 omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE);
1063
1064 r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000);
1065 if (r) {
1066 dev_err(&dssdev->dev, "failed to set HS and LP clocks\n");
1067 goto err0;
1068 }
1069
1070 r = omapdss_dsi_display_enable(dssdev); 1166 r = omapdss_dsi_display_enable(dssdev);
1071 if (r) { 1167 if (r) {
1072 dev_err(&dssdev->dev, "failed to enable DSI\n"); 1168 dev_err(&dssdev->dev, "failed to enable DSI\n");
@@ -1099,8 +1195,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1099 if (r) 1195 if (r)
1100 goto err; 1196 goto err;
1101 1197
1102 r = taal_dcs_write_1(td, MIPI_DCS_SET_PIXEL_FORMAT, 1198 r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */
1103 MIPI_DCS_PIXEL_FMT_24BIT);
1104 if (r) 1199 if (r)
1105 goto err; 1200 goto err;
1106 1201
@@ -1114,7 +1209,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1114 goto err; 1209 goto err;
1115 } 1210 }
1116 1211
1117 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_ON); 1212 r = taal_dcs_write_0(td, DCS_DISPLAY_ON);
1118 if (r) 1213 if (r)
1119 goto err; 1214 goto err;
1120 1215
@@ -1122,10 +1217,6 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1122 if (r) 1217 if (r)
1123 goto err; 1218 goto err;
1124 1219
1125 r = dsi_enable_video_output(dssdev, td->channel);
1126 if (r)
1127 goto err;
1128
1129 td->enabled = 1; 1220 td->enabled = 1;
1130 1221
1131 if (!td->intro_printed) { 1222 if (!td->intro_printed) {
@@ -1155,9 +1246,7 @@ static void taal_power_off(struct omap_dss_device *dssdev)
1155 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1246 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1156 int r; 1247 int r;
1157 1248
1158 dsi_disable_video_output(dssdev, td->channel); 1249 r = taal_dcs_write_0(td, DCS_DISPLAY_OFF);
1159
1160 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
1161 if (!r) 1250 if (!r)
1162 r = taal_sleep_in(td); 1251 r = taal_sleep_in(td);
1163 1252
@@ -1245,6 +1334,76 @@ static void taal_disable(struct omap_dss_device *dssdev)
1245 mutex_unlock(&td->lock); 1334 mutex_unlock(&td->lock);
1246} 1335}
1247 1336
1337static int taal_suspend(struct omap_dss_device *dssdev)
1338{
1339 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1340 int r;
1341
1342 dev_dbg(&dssdev->dev, "suspend\n");
1343
1344 mutex_lock(&td->lock);
1345
1346 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
1347 r = -EINVAL;
1348 goto err;
1349 }
1350
1351 taal_cancel_ulps_work(dssdev);
1352 taal_cancel_esd_work(dssdev);
1353
1354 dsi_bus_lock(dssdev);
1355
1356 r = taal_wake_up(dssdev);
1357 if (!r)
1358 taal_power_off(dssdev);
1359
1360 dsi_bus_unlock(dssdev);
1361
1362 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
1363
1364 mutex_unlock(&td->lock);
1365
1366 return 0;
1367err:
1368 mutex_unlock(&td->lock);
1369 return r;
1370}
1371
1372static int taal_resume(struct omap_dss_device *dssdev)
1373{
1374 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1375 int r;
1376
1377 dev_dbg(&dssdev->dev, "resume\n");
1378
1379 mutex_lock(&td->lock);
1380
1381 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
1382 r = -EINVAL;
1383 goto err;
1384 }
1385
1386 dsi_bus_lock(dssdev);
1387
1388 r = taal_power_on(dssdev);
1389
1390 dsi_bus_unlock(dssdev);
1391
1392 if (r) {
1393 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
1394 } else {
1395 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
1396 taal_queue_esd_work(dssdev);
1397 }
1398
1399 mutex_unlock(&td->lock);
1400
1401 return r;
1402err:
1403 mutex_unlock(&td->lock);
1404 return r;
1405}
1406
1248static void taal_framedone_cb(int err, void *data) 1407static void taal_framedone_cb(int err, void *data)
1249{ 1408{
1250 struct omap_dss_device *dssdev = data; 1409 struct omap_dss_device *dssdev = data;
@@ -1264,8 +1423,12 @@ static irqreturn_t taal_te_isr(int irq, void *data)
1264 if (old) { 1423 if (old) {
1265 cancel_delayed_work(&td->te_timeout_work); 1424 cancel_delayed_work(&td->te_timeout_work);
1266 1425
1267 r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb, 1426 r = omap_dsi_update(dssdev, td->channel,
1268 dssdev); 1427 td->update_region.x,
1428 td->update_region.y,
1429 td->update_region.w,
1430 td->update_region.h,
1431 taal_framedone_cb, dssdev);
1269 if (r) 1432 if (r)
1270 goto err; 1433 goto err;
1271 } 1434 }
@@ -1293,6 +1456,7 @@ static int taal_update(struct omap_dss_device *dssdev,
1293 u16 x, u16 y, u16 w, u16 h) 1456 u16 x, u16 y, u16 w, u16 h)
1294{ 1457{
1295 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1458 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1459 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1296 int r; 1460 int r;
1297 1461
1298 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); 1462 dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
@@ -1309,20 +1473,26 @@ static int taal_update(struct omap_dss_device *dssdev,
1309 goto err; 1473 goto err;
1310 } 1474 }
1311 1475
1312 /* XXX no need to send this every frame, but dsi break if not done */ 1476 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true);
1313 r = taal_set_update_window(td, 0, 0,
1314 td->panel_config->timings.x_res,
1315 td->panel_config->timings.y_res);
1316 if (r) 1477 if (r)
1317 goto err; 1478 goto err;
1318 1479
1319 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) { 1480 r = taal_set_update_window(td, x, y, w, h);
1481 if (r)
1482 goto err;
1483
1484 if (td->te_enabled && panel_data->use_ext_te) {
1485 td->update_region.x = x;
1486 td->update_region.y = y;
1487 td->update_region.w = w;
1488 td->update_region.h = h;
1489 barrier();
1320 schedule_delayed_work(&td->te_timeout_work, 1490 schedule_delayed_work(&td->te_timeout_work,
1321 msecs_to_jiffies(250)); 1491 msecs_to_jiffies(250));
1322 atomic_set(&td->do_update, 1); 1492 atomic_set(&td->do_update, 1);
1323 } else { 1493 } else {
1324 r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb, 1494 r = omap_dsi_update(dssdev, td->channel, x, y, w, h,
1325 dssdev); 1495 taal_framedone_cb, dssdev);
1326 if (r) 1496 if (r)
1327 goto err; 1497 goto err;
1328 } 1498 }
@@ -1355,14 +1525,15 @@ static int taal_sync(struct omap_dss_device *dssdev)
1355static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) 1525static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
1356{ 1526{
1357 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1527 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1528 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1358 int r; 1529 int r;
1359 1530
1360 if (enable) 1531 if (enable)
1361 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); 1532 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
1362 else 1533 else
1363 r = taal_dcs_write_0(td, MIPI_DCS_SET_TEAR_OFF); 1534 r = taal_dcs_write_0(td, DCS_TEAR_OFF);
1364 1535
1365 if (!gpio_is_valid(td->ext_te_gpio)) 1536 if (!panel_data->use_ext_te)
1366 omapdss_dsi_enable_te(dssdev, enable); 1537 omapdss_dsi_enable_te(dssdev, enable);
1367 1538
1368 if (td->panel_config->sleep.enable_te) 1539 if (td->panel_config->sleep.enable_te)
@@ -1422,7 +1593,6 @@ static int taal_get_te(struct omap_dss_device *dssdev)
1422static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) 1593static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1423{ 1594{
1424 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1595 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1425 u16 dw, dh;
1426 int r; 1596 int r;
1427 1597
1428 dev_dbg(&dssdev->dev, "rotate %d\n", rotate); 1598 dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
@@ -1444,16 +1614,6 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
1444 goto err; 1614 goto err;
1445 } 1615 }
1446 1616
1447 if (rotate == 0 || rotate == 2) {
1448 dw = dssdev->panel.timings.x_res;
1449 dh = dssdev->panel.timings.y_res;
1450 } else {
1451 dw = dssdev->panel.timings.y_res;
1452 dh = dssdev->panel.timings.x_res;
1453 }
1454
1455 omapdss_dsi_set_size(dssdev, dw, dh);
1456
1457 td->rotate = rotate; 1617 td->rotate = rotate;
1458 1618
1459 dsi_bus_unlock(dssdev); 1619 dsi_bus_unlock(dssdev);
@@ -1672,6 +1832,7 @@ static void taal_esd_work(struct work_struct *work)
1672 struct taal_data *td = container_of(work, struct taal_data, 1832 struct taal_data *td = container_of(work, struct taal_data,
1673 esd_work.work); 1833 esd_work.work);
1674 struct omap_dss_device *dssdev = td->dssdev; 1834 struct omap_dss_device *dssdev = td->dssdev;
1835 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1675 u8 state1, state2; 1836 u8 state1, state2;
1676 int r; 1837 int r;
1677 1838
@@ -1690,7 +1851,7 @@ static void taal_esd_work(struct work_struct *work)
1690 goto err; 1851 goto err;
1691 } 1852 }
1692 1853
1693 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state1); 1854 r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
1694 if (r) { 1855 if (r) {
1695 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1856 dev_err(&dssdev->dev, "failed to read Taal status\n");
1696 goto err; 1857 goto err;
@@ -1703,7 +1864,7 @@ static void taal_esd_work(struct work_struct *work)
1703 goto err; 1864 goto err;
1704 } 1865 }
1705 1866
1706 r = taal_dcs_read_1(td, MIPI_DCS_GET_DIAGNOSTIC_RESULT, &state2); 1867 r = taal_dcs_read_1(td, DCS_RDDSDR, &state2);
1707 if (r) { 1868 if (r) {
1708 dev_err(&dssdev->dev, "failed to read Taal status\n"); 1869 dev_err(&dssdev->dev, "failed to read Taal status\n");
1709 goto err; 1870 goto err;
@@ -1718,8 +1879,8 @@ static void taal_esd_work(struct work_struct *work)
1718 } 1879 }
1719 /* Self-diagnostics result is also shown on TE GPIO line. We need 1880 /* Self-diagnostics result is also shown on TE GPIO line. We need
1720 * to re-enable TE after self diagnostics */ 1881 * to re-enable TE after self diagnostics */
1721 if (td->te_enabled && gpio_is_valid(td->ext_te_gpio)) { 1882 if (td->te_enabled && panel_data->use_ext_te) {
1722 r = taal_dcs_write_1(td, MIPI_DCS_SET_TEAR_ON, 0); 1883 r = taal_dcs_write_1(td, DCS_TEAR_ON, 0);
1723 if (r) 1884 if (r)
1724 goto err; 1885 goto err;
1725 } 1886 }
@@ -1748,6 +1909,8 @@ static struct omap_dss_driver taal_driver = {
1748 1909
1749 .enable = taal_enable, 1910 .enable = taal_enable,
1750 .disable = taal_disable, 1911 .disable = taal_disable,
1912 .suspend = taal_suspend,
1913 .resume = taal_resume,
1751 1914
1752 .update = taal_update, 1915 .update = taal_update,
1753 .sync = taal_sync, 1916 .sync = taal_sync,
@@ -1765,6 +1928,8 @@ static struct omap_dss_driver taal_driver = {
1765 .run_test = taal_run_test, 1928 .run_test = taal_run_test,
1766 .memory_read = taal_memory_read, 1929 .memory_read = taal_memory_read,
1767 1930
1931 .get_timings = taal_get_timings,
1932
1768 .driver = { 1933 .driver = {
1769 .name = "taal", 1934 .name = "taal",
1770 .owner = THIS_MODULE, 1935 .owner = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
deleted file mode 100644
index 8281baafe1e..00000000000
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ /dev/null
@@ -1,353 +0,0 @@
1/*
2 * TFP410 DPI-to-DVI chip
3 *
4 * Copyright (C) 2011 Texas Instruments Inc
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <video/omapdss.h>
23#include <linux/i2c.h>
24#include <linux/gpio.h>
25#include <drm/drm_edid.h>
26
27#include <video/omap-panel-tfp410.h>
28
29static const struct omap_video_timings tfp410_default_timings = {
30 .x_res = 640,
31 .y_res = 480,
32
33 .pixel_clock = 23500,
34
35 .hfp = 48,
36 .hsw = 32,
37 .hbp = 80,
38
39 .vfp = 3,
40 .vsw = 4,
41 .vbp = 7,
42
43 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
44 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
45 .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
46 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
47 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
48};
49
50struct panel_drv_data {
51 struct omap_dss_device *dssdev;
52
53 struct mutex lock;
54
55 int pd_gpio;
56
57 struct i2c_adapter *i2c_adapter;
58};
59
60static int tfp410_power_on(struct omap_dss_device *dssdev)
61{
62 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
63 int r;
64
65 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
66 return 0;
67
68 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
69 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
70
71 r = omapdss_dpi_display_enable(dssdev);
72 if (r)
73 goto err0;
74
75 if (gpio_is_valid(ddata->pd_gpio))
76 gpio_set_value_cansleep(ddata->pd_gpio, 1);
77
78 return 0;
79err0:
80 return r;
81}
82
83static void tfp410_power_off(struct omap_dss_device *dssdev)
84{
85 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
86
87 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
88 return;
89
90 if (gpio_is_valid(ddata->pd_gpio))
91 gpio_set_value_cansleep(ddata->pd_gpio, 0);
92
93 omapdss_dpi_display_disable(dssdev);
94}
95
96static int tfp410_probe(struct omap_dss_device *dssdev)
97{
98 struct panel_drv_data *ddata;
99 int r;
100 int i2c_bus_num;
101
102 ddata = devm_kzalloc(&dssdev->dev, sizeof(*ddata), GFP_KERNEL);
103 if (!ddata)
104 return -ENOMEM;
105
106 dssdev->panel.timings = tfp410_default_timings;
107
108 ddata->dssdev = dssdev;
109 mutex_init(&ddata->lock);
110
111 if (dssdev->data) {
112 struct tfp410_platform_data *pdata = dssdev->data;
113
114 ddata->pd_gpio = pdata->power_down_gpio;
115 i2c_bus_num = pdata->i2c_bus_num;
116 } else {
117 ddata->pd_gpio = -1;
118 i2c_bus_num = -1;
119 }
120
121 if (gpio_is_valid(ddata->pd_gpio)) {
122 r = devm_gpio_request_one(&dssdev->dev, ddata->pd_gpio,
123 GPIOF_OUT_INIT_LOW, "tfp410 pd");
124 if (r) {
125 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
126 ddata->pd_gpio);
127 return r;
128 }
129 }
130
131 if (i2c_bus_num != -1) {
132 struct i2c_adapter *adapter;
133
134 adapter = i2c_get_adapter(i2c_bus_num);
135 if (!adapter) {
136 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
137 i2c_bus_num);
138 return -EINVAL;
139 }
140
141 ddata->i2c_adapter = adapter;
142 }
143
144 dev_set_drvdata(&dssdev->dev, ddata);
145
146 return 0;
147}
148
149static void __exit tfp410_remove(struct omap_dss_device *dssdev)
150{
151 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
152
153 mutex_lock(&ddata->lock);
154
155 if (ddata->i2c_adapter)
156 i2c_put_adapter(ddata->i2c_adapter);
157
158 dev_set_drvdata(&dssdev->dev, NULL);
159
160 mutex_unlock(&ddata->lock);
161}
162
163static int tfp410_enable(struct omap_dss_device *dssdev)
164{
165 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
166 int r;
167
168 mutex_lock(&ddata->lock);
169
170 r = tfp410_power_on(dssdev);
171 if (r == 0)
172 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
173
174 mutex_unlock(&ddata->lock);
175
176 return r;
177}
178
179static void tfp410_disable(struct omap_dss_device *dssdev)
180{
181 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
182
183 mutex_lock(&ddata->lock);
184
185 tfp410_power_off(dssdev);
186
187 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
188
189 mutex_unlock(&ddata->lock);
190}
191
192static void tfp410_set_timings(struct omap_dss_device *dssdev,
193 struct omap_video_timings *timings)
194{
195 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
196
197 mutex_lock(&ddata->lock);
198 omapdss_dpi_set_timings(dssdev, timings);
199 dssdev->panel.timings = *timings;
200 mutex_unlock(&ddata->lock);
201}
202
203static void tfp410_get_timings(struct omap_dss_device *dssdev,
204 struct omap_video_timings *timings)
205{
206 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
207
208 mutex_lock(&ddata->lock);
209 *timings = dssdev->panel.timings;
210 mutex_unlock(&ddata->lock);
211}
212
213static int tfp410_check_timings(struct omap_dss_device *dssdev,
214 struct omap_video_timings *timings)
215{
216 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
217 int r;
218
219 mutex_lock(&ddata->lock);
220 r = dpi_check_timings(dssdev, timings);
221 mutex_unlock(&ddata->lock);
222
223 return r;
224}
225
226
227static int tfp410_ddc_read(struct i2c_adapter *adapter,
228 unsigned char *buf, u16 count, u8 offset)
229{
230 int r, retries;
231
232 for (retries = 3; retries > 0; retries--) {
233 struct i2c_msg msgs[] = {
234 {
235 .addr = DDC_ADDR,
236 .flags = 0,
237 .len = 1,
238 .buf = &offset,
239 }, {
240 .addr = DDC_ADDR,
241 .flags = I2C_M_RD,
242 .len = count,
243 .buf = buf,
244 }
245 };
246
247 r = i2c_transfer(adapter, msgs, 2);
248 if (r == 2)
249 return 0;
250
251 if (r != -EAGAIN)
252 break;
253 }
254
255 return r < 0 ? r : -EIO;
256}
257
258static int tfp410_read_edid(struct omap_dss_device *dssdev,
259 u8 *edid, int len)
260{
261 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
262 int r, l, bytes_read;
263
264 mutex_lock(&ddata->lock);
265
266 if (!ddata->i2c_adapter) {
267 r = -ENODEV;
268 goto err;
269 }
270
271 l = min(EDID_LENGTH, len);
272 r = tfp410_ddc_read(ddata->i2c_adapter, edid, l, 0);
273 if (r)
274 goto err;
275
276 bytes_read = l;
277
278 /* if there are extensions, read second block */
279 if (len > EDID_LENGTH && edid[0x7e] > 0) {
280 l = min(EDID_LENGTH, len - EDID_LENGTH);
281
282 r = tfp410_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
283 l, EDID_LENGTH);
284 if (r)
285 goto err;
286
287 bytes_read += l;
288 }
289
290 mutex_unlock(&ddata->lock);
291
292 return bytes_read;
293
294err:
295 mutex_unlock(&ddata->lock);
296 return r;
297}
298
299static bool tfp410_detect(struct omap_dss_device *dssdev)
300{
301 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
302 unsigned char out;
303 int r;
304
305 mutex_lock(&ddata->lock);
306
307 if (!ddata->i2c_adapter)
308 goto out;
309
310 r = tfp410_ddc_read(ddata->i2c_adapter, &out, 1, 0);
311
312 mutex_unlock(&ddata->lock);
313
314 return r == 0;
315
316out:
317 mutex_unlock(&ddata->lock);
318 return true;
319}
320
321static struct omap_dss_driver tfp410_driver = {
322 .probe = tfp410_probe,
323 .remove = __exit_p(tfp410_remove),
324
325 .enable = tfp410_enable,
326 .disable = tfp410_disable,
327
328 .set_timings = tfp410_set_timings,
329 .get_timings = tfp410_get_timings,
330 .check_timings = tfp410_check_timings,
331
332 .read_edid = tfp410_read_edid,
333 .detect = tfp410_detect,
334
335 .driver = {
336 .name = "tfp410",
337 .owner = THIS_MODULE,
338 },
339};
340
341static int __init tfp410_init(void)
342{
343 return omap_dss_register_driver(&tfp410_driver);
344}
345
346static void __exit tfp410_exit(void)
347{
348 omap_dss_unregister_driver(&tfp410_driver);
349}
350
351module_init(tfp410_init);
352module_exit(tfp410_exit);
353MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 6b6643911d2..2462b9ec666 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -47,20 +47,16 @@
47 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL) 47 TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
48 48
49static const u16 tpo_td043_def_gamma[12] = { 49static const u16 tpo_td043_def_gamma[12] = {
50 105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023 50 106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020
51}; 51};
52 52
53struct tpo_td043_device { 53struct tpo_td043_device {
54 struct spi_device *spi; 54 struct spi_device *spi;
55 struct regulator *vcc_reg; 55 struct regulator *vcc_reg;
56 int nreset_gpio;
57 u16 gamma[12]; 56 u16 gamma[12];
58 u32 mode; 57 u32 mode;
59 u32 hmirror:1; 58 u32 hmirror:1;
60 u32 vmirror:1; 59 u32 vmirror:1;
61 u32 powered_on:1;
62 u32 spi_suspended:1;
63 u32 power_on_resume:1;
64}; 60};
65 61
66static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data) 62static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
@@ -267,27 +263,30 @@ static const struct omap_video_timings tpo_td043_timings = {
267 .vsw = 1, 263 .vsw = 1,
268 .vfp = 39, 264 .vfp = 39,
269 .vbp = 34, 265 .vbp = 34,
270
271 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
272 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
273 .data_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
274 .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
275 .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES,
276}; 266};
277 267
278static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) 268static int tpo_td043_power_on(struct omap_dss_device *dssdev)
279{ 269{
280 int nreset_gpio = tpo_td043->nreset_gpio; 270 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
271 int nreset_gpio = dssdev->reset_gpio;
281 int r; 272 int r;
282 273
283 if (tpo_td043->powered_on) 274 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
284 return 0; 275 return 0;
285 276
286 r = regulator_enable(tpo_td043->vcc_reg); 277 r = omapdss_dpi_display_enable(dssdev);
287 if (r != 0) 278 if (r)
288 return r; 279 goto err0;
280
281 if (dssdev->platform_enable) {
282 r = dssdev->platform_enable(dssdev);
283 if (r)
284 goto err1;
285 }
286
287 regulator_enable(tpo_td043->vcc_reg);
289 288
290 /* wait for panel to stabilize */ 289 /* wait for power up */
291 msleep(160); 290 msleep(160);
292 291
293 if (gpio_is_valid(nreset_gpio)) 292 if (gpio_is_valid(nreset_gpio))
@@ -302,15 +301,19 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
302 tpo_td043->vmirror); 301 tpo_td043->vmirror);
303 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma); 302 tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
304 303
305 tpo_td043->powered_on = 1;
306 return 0; 304 return 0;
305err1:
306 omapdss_dpi_display_disable(dssdev);
307err0:
308 return r;
307} 309}
308 310
309static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043) 311static void tpo_td043_power_off(struct omap_dss_device *dssdev)
310{ 312{
311 int nreset_gpio = tpo_td043->nreset_gpio; 313 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
314 int nreset_gpio = dssdev->reset_gpio;
312 315
313 if (!tpo_td043->powered_on) 316 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
314 return; 317 return;
315 318
316 tpo_td043_write(tpo_td043->spi, 3, 319 tpo_td043_write(tpo_td043->spi, 3,
@@ -326,79 +329,54 @@ static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043)
326 329
327 regulator_disable(tpo_td043->vcc_reg); 330 regulator_disable(tpo_td043->vcc_reg);
328 331
329 tpo_td043->powered_on = 0; 332 if (dssdev->platform_disable)
333 dssdev->platform_disable(dssdev);
334
335 omapdss_dpi_display_disable(dssdev);
330} 336}
331 337
332static int tpo_td043_enable_dss(struct omap_dss_device *dssdev) 338static int tpo_td043_enable(struct omap_dss_device *dssdev)
333{ 339{
334 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 340 int ret;
335 int r;
336
337 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
338 return 0;
339
340 omapdss_dpi_set_timings(dssdev, &dssdev->panel.timings);
341 omapdss_dpi_set_data_lines(dssdev, dssdev->phy.dpi.data_lines);
342
343 r = omapdss_dpi_display_enable(dssdev);
344 if (r)
345 goto err0;
346 341
347 if (dssdev->platform_enable) { 342 dev_dbg(&dssdev->dev, "enable\n");
348 r = dssdev->platform_enable(dssdev);
349 if (r)
350 goto err1;
351 }
352 343
353 /* 344 ret = tpo_td043_power_on(dssdev);
354 * If we are resuming from system suspend, SPI clocks might not be 345 if (ret)
355 * enabled yet, so we'll program the LCD from SPI PM resume callback. 346 return ret;
356 */
357 if (!tpo_td043->spi_suspended) {
358 r = tpo_td043_power_on(tpo_td043);
359 if (r)
360 goto err1;
361 }
362 347
363 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 348 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
364 349
365 return 0; 350 return 0;
366err1:
367 omapdss_dpi_display_disable(dssdev);
368err0:
369 return r;
370} 351}
371 352
372static void tpo_td043_disable_dss(struct omap_dss_device *dssdev) 353static void tpo_td043_disable(struct omap_dss_device *dssdev)
373{ 354{
374 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); 355 dev_dbg(&dssdev->dev, "disable\n");
375
376 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
377 return;
378
379 if (dssdev->platform_disable)
380 dssdev->platform_disable(dssdev);
381 356
382 omapdss_dpi_display_disable(dssdev); 357 tpo_td043_power_off(dssdev);
383 358
384 if (!tpo_td043->spi_suspended) 359 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
385 tpo_td043_power_off(tpo_td043);
386} 360}
387 361
388static int tpo_td043_enable(struct omap_dss_device *dssdev) 362static int tpo_td043_suspend(struct omap_dss_device *dssdev)
389{ 363{
390 dev_dbg(&dssdev->dev, "enable\n"); 364 tpo_td043_power_off(dssdev);
391 365 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
392 return tpo_td043_enable_dss(dssdev); 366 return 0;
393} 367}
394 368
395static void tpo_td043_disable(struct omap_dss_device *dssdev) 369static int tpo_td043_resume(struct omap_dss_device *dssdev)
396{ 370{
397 dev_dbg(&dssdev->dev, "disable\n"); 371 int r = 0;
372
373 r = tpo_td043_power_on(dssdev);
374 if (r)
375 return r;
398 376
399 tpo_td043_disable_dss(dssdev); 377 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
400 378
401 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 379 return 0;
402} 380}
403 381
404static int tpo_td043_probe(struct omap_dss_device *dssdev) 382static int tpo_td043_probe(struct omap_dss_device *dssdev)
@@ -414,6 +392,8 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
414 return -ENODEV; 392 return -ENODEV;
415 } 393 }
416 394
395 dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS |
396 OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IPC;
417 dssdev->panel.timings = tpo_td043_timings; 397 dssdev->panel.timings = tpo_td043_timings;
418 dssdev->ctrl.pixel_size = 24; 398 dssdev->ctrl.pixel_size = 24;
419 399
@@ -428,12 +408,17 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
428 } 408 }
429 409
430 if (gpio_is_valid(nreset_gpio)) { 410 if (gpio_is_valid(nreset_gpio)) {
431 ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW, 411 ret = gpio_request(nreset_gpio, "lcd reset");
432 "lcd reset");
433 if (ret < 0) { 412 if (ret < 0) {
434 dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); 413 dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
435 goto fail_gpio_req; 414 goto fail_gpio_req;
436 } 415 }
416
417 ret = gpio_direction_output(nreset_gpio, 0);
418 if (ret < 0) {
419 dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
420 goto fail_gpio_direction;
421 }
437 } 422 }
438 423
439 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group); 424 ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
@@ -442,6 +427,8 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
442 427
443 return 0; 428 return 0;
444 429
430fail_gpio_direction:
431 gpio_free(nreset_gpio);
445fail_gpio_req: 432fail_gpio_req:
446 regulator_put(tpo_td043->vcc_reg); 433 regulator_put(tpo_td043->vcc_reg);
447fail_regulator: 434fail_regulator:
@@ -462,32 +449,17 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
462 gpio_free(nreset_gpio); 449 gpio_free(nreset_gpio);
463} 450}
464 451
465static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
466 struct omap_video_timings *timings)
467{
468 omapdss_dpi_set_timings(dssdev, timings);
469
470 dssdev->panel.timings = *timings;
471}
472
473static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
474 struct omap_video_timings *timings)
475{
476 return dpi_check_timings(dssdev, timings);
477}
478
479static struct omap_dss_driver tpo_td043_driver = { 452static struct omap_dss_driver tpo_td043_driver = {
480 .probe = tpo_td043_probe, 453 .probe = tpo_td043_probe,
481 .remove = tpo_td043_remove, 454 .remove = tpo_td043_remove,
482 455
483 .enable = tpo_td043_enable, 456 .enable = tpo_td043_enable,
484 .disable = tpo_td043_disable, 457 .disable = tpo_td043_disable,
458 .suspend = tpo_td043_suspend,
459 .resume = tpo_td043_resume,
485 .set_mirror = tpo_td043_set_hmirror, 460 .set_mirror = tpo_td043_set_hmirror,
486 .get_mirror = tpo_td043_get_hmirror, 461 .get_mirror = tpo_td043_get_hmirror,
487 462
488 .set_timings = tpo_td043_set_timings,
489 .check_timings = tpo_td043_check_timings,
490
491 .driver = { 463 .driver = {
492 .name = "tpo_td043mtea1_panel", 464 .name = "tpo_td043mtea1_panel",
493 .owner = THIS_MODULE, 465 .owner = THIS_MODULE,
@@ -519,7 +491,6 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
519 return -ENOMEM; 491 return -ENOMEM;
520 492
521 tpo_td043->spi = spi; 493 tpo_td043->spi = spi;
522 tpo_td043->nreset_gpio = dssdev->reset_gpio;
523 dev_set_drvdata(&spi->dev, tpo_td043); 494 dev_set_drvdata(&spi->dev, tpo_td043);
524 dev_set_drvdata(&dssdev->dev, tpo_td043); 495 dev_set_drvdata(&dssdev->dev, tpo_td043);
525 496
@@ -528,7 +499,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
528 return 0; 499 return 0;
529} 500}
530 501
531static int tpo_td043_spi_remove(struct spi_device *spi) 502static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
532{ 503{
533 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev); 504 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
534 505
@@ -538,52 +509,28 @@ static int tpo_td043_spi_remove(struct spi_device *spi)
538 return 0; 509 return 0;
539} 510}
540 511
541#ifdef CONFIG_PM_SLEEP
542static int tpo_td043_spi_suspend(struct device *dev)
543{
544 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
545
546 dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", tpo_td043);
547
548 tpo_td043->power_on_resume = tpo_td043->powered_on;
549 tpo_td043_power_off(tpo_td043);
550 tpo_td043->spi_suspended = 1;
551
552 return 0;
553}
554
555static int tpo_td043_spi_resume(struct device *dev)
556{
557 struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
558 int ret;
559
560 dev_dbg(dev, "tpo_td043_spi_resume\n");
561
562 if (tpo_td043->power_on_resume) {
563 ret = tpo_td043_power_on(tpo_td043);
564 if (ret)
565 return ret;
566 }
567 tpo_td043->spi_suspended = 0;
568
569 return 0;
570}
571#endif
572
573static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
574 tpo_td043_spi_suspend, tpo_td043_spi_resume);
575
576static struct spi_driver tpo_td043_spi_driver = { 512static struct spi_driver tpo_td043_spi_driver = {
577 .driver = { 513 .driver = {
578 .name = "tpo_td043mtea1_panel_spi", 514 .name = "tpo_td043mtea1_panel_spi",
515 .bus = &spi_bus_type,
579 .owner = THIS_MODULE, 516 .owner = THIS_MODULE,
580 .pm = &tpo_td043_spi_pm,
581 }, 517 },
582 .probe = tpo_td043_spi_probe, 518 .probe = tpo_td043_spi_probe,
583 .remove = tpo_td043_spi_remove, 519 .remove = __devexit_p(tpo_td043_spi_remove),
584}; 520};
585 521
586module_spi_driver(tpo_td043_spi_driver); 522static int __init tpo_td043_init(void)
523{
524 return spi_register_driver(&tpo_td043_spi_driver);
525}
526
527static void __exit tpo_td043_exit(void)
528{
529 spi_unregister_driver(&tpo_td043_spi_driver);
530}
531
532module_init(tpo_td043_init);
533module_exit(tpo_td043_exit);
587 534
588MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>"); 535MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
589MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver"); 536MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index cb0f145c707..0d12524db14 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -1,30 +1,33 @@
1menuconfig OMAP2_DSS 1menuconfig OMAP2_DSS
2 tristate "OMAP2+ Display Subsystem support" 2 tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)"
3 depends on ARCH_OMAP2PLUS
3 help 4 help
4 OMAP2+ Display Subsystem support. 5 OMAP2+ Display Subsystem support.
5 6
6if OMAP2_DSS 7if OMAP2_DSS
7 8
8config OMAP2_DSS_DEBUG 9config OMAP2_VRAM_SIZE
9 bool "Debug support" 10 int "VRAM size (MB)"
10 default n 11 range 0 32
12 default 0
11 help 13 help
12 This enables printing of debug messages. Alternatively, debug messages 14 The amount of SDRAM to reserve at boot time for video RAM use.
13 can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting 15 This VRAM will be used by omapfb and other drivers that need
14 appropriate flags in <debugfs>/dynamic_debug/control. 16 large continuous RAM area for video use.
15 17
16config OMAP2_DSS_DEBUGFS 18 You can also set this with "vram=<bytes>" kernel argument, or
17 bool "Debugfs filesystem support" 19 in the board file.
18 depends on DEBUG_FS 20
19 default n 21config OMAP2_DSS_DEBUG_SUPPORT
22 bool "Debug support"
23 default y
20 help 24 help
21 This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables 25 This enables debug messages. You need to enable printing
22 querying about clock configuration and register configuration of dss, 26 with 'debug' module parameter.
23 dispc, dsi, hdmi and rfbi.
24 27
25config OMAP2_DSS_COLLECT_IRQ_STATS 28config OMAP2_DSS_COLLECT_IRQ_STATS
26 bool "Collect DSS IRQ statistics" 29 bool "Collect DSS IRQ statistics"
27 depends on OMAP2_DSS_DEBUGFS 30 depends on OMAP2_DSS_DEBUG_SUPPORT
28 default n 31 default n
29 help 32 help
30 Collect DSS IRQ statistics, printable via debugfs. 33 Collect DSS IRQ statistics, printable via debugfs.
@@ -49,7 +52,7 @@ config OMAP2_DSS_RFBI
49 DBI is a bus between the host processor and a peripheral, 52 DBI is a bus between the host processor and a peripheral,
50 such as a display or a framebuffer chip. 53 such as a display or a framebuffer chip.
51 54
52 See http://www.mipi.org/ for DBI specifications. 55 See http://www.mipi.org/ for DBI spesifications.
53 56
54config OMAP2_DSS_VENC 57config OMAP2_DSS_VENC
55 bool "VENC support" 58 bool "VENC support"
@@ -59,16 +62,15 @@ config OMAP2_DSS_VENC
59 62
60config OMAP4_DSS_HDMI 63config OMAP4_DSS_HDMI
61 bool "HDMI support" 64 bool "HDMI support"
65 depends on ARCH_OMAP4
62 default y 66 default y
63 help 67 help
64 HDMI Interface. This adds the High Definition Multimedia Interface. 68 HDMI Interface. This adds the High Definition Multimedia Interface.
65 See http://www.hdmi.org/ for HDMI specification. 69 See http://www.hdmi.org/ for HDMI specification.
66 70
67config OMAP4_DSS_HDMI_AUDIO
68 bool
69
70config OMAP2_DSS_SDI 71config OMAP2_DSS_SDI
71 bool "SDI support" 72 bool "SDI support"
73 depends on ARCH_OMAP3
72 default n 74 default n
73 help 75 help
74 SDI (Serial Display Interface) support. 76 SDI (Serial Display Interface) support.
@@ -78,6 +80,7 @@ config OMAP2_DSS_SDI
78 80
79config OMAP2_DSS_DSI 81config OMAP2_DSS_DSI
80 bool "DSI support" 82 bool "DSI support"
83 depends on ARCH_OMAP3 || ARCH_OMAP4
81 default n 84 default n
82 help 85 help
83 MIPI DSI (Display Serial Interface) support. 86 MIPI DSI (Display Serial Interface) support.
@@ -85,7 +88,16 @@ config OMAP2_DSS_DSI
85 DSI is a high speed half-duplex serial interface between the host 88 DSI is a high speed half-duplex serial interface between the host
86 processor and a peripheral, such as a display or a framebuffer chip. 89 processor and a peripheral, such as a display or a framebuffer chip.
87 90
88 See http://www.mipi.org/ for DSI specifications. 91 See http://www.mipi.org/ for DSI spesifications.
92
93config OMAP2_DSS_FAKE_VSYNC
94 bool "Fake VSYNC irq from manual update displays"
95 default n
96 help
97 If this is selected, DSI will generate a fake DISPC VSYNC interrupt
98 when DSI has sent a frame. This is only needed with DSI or RFBI
99 displays using manual mode, and you want VSYNC to, for example,
100 time animation.
89 101
90config OMAP2_DSS_MIN_FCK_PER_PCK 102config OMAP2_DSS_MIN_FCK_PER_PCK
91 int "Minimum FCK/PCK ratio (for scaling)" 103 int "Minimum FCK/PCK ratio (for scaling)"
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index 61949ff7940..10d9d3bb3e2 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,15 +1,9 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2# Core DSS files 2omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
3omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
4 output.o
5# DSS compat layer files
6omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \
7 dispc-compat.o display-sysfs.o
8omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
9omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o venc_panel.o 5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 6omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 7omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ 8omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \
14 hdmi_panel.o ti_hdmi_4xxx_ip.o 9 hdmi_omap4_panel.o
15ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
deleted file mode 100644
index d446bdfc4c8..00000000000
--- a/drivers/video/omap2/dss/apply.c
+++ /dev/null
@@ -1,1671 +0,0 @@
1/*
2 * Copyright (C) 2011 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define DSS_SUBSYS_NAME "APPLY"
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/jiffies.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29#include "dss_features.h"
30#include "dispc-compat.h"
31
32/*
33 * We have 4 levels of cache for the dispc settings. First two are in SW and
34 * the latter two in HW.
35 *
36 * set_info()
37 * v
38 * +--------------------+
39 * | user_info |
40 * +--------------------+
41 * v
42 * apply()
43 * v
44 * +--------------------+
45 * | info |
46 * +--------------------+
47 * v
48 * write_regs()
49 * v
50 * +--------------------+
51 * | shadow registers |
52 * +--------------------+
53 * v
54 * VFP or lcd/digit_enable
55 * v
56 * +--------------------+
57 * | registers |
58 * +--------------------+
59 */
60
61struct ovl_priv_data {
62
63 bool user_info_dirty;
64 struct omap_overlay_info user_info;
65
66 bool info_dirty;
67 struct omap_overlay_info info;
68
69 bool shadow_info_dirty;
70
71 bool extra_info_dirty;
72 bool shadow_extra_info_dirty;
73
74 bool enabled;
75 u32 fifo_low, fifo_high;
76
77 /*
78 * True if overlay is to be enabled. Used to check and calculate configs
79 * for the overlay before it is enabled in the HW.
80 */
81 bool enabling;
82};
83
84struct mgr_priv_data {
85
86 bool user_info_dirty;
87 struct omap_overlay_manager_info user_info;
88
89 bool info_dirty;
90 struct omap_overlay_manager_info info;
91
92 bool shadow_info_dirty;
93
94 /* If true, GO bit is up and shadow registers cannot be written.
95 * Never true for manual update displays */
96 bool busy;
97
98 /* If true, dispc output is enabled */
99 bool updating;
100
101 /* If true, a display is enabled using this manager */
102 bool enabled;
103
104 bool extra_info_dirty;
105 bool shadow_extra_info_dirty;
106
107 struct omap_video_timings timings;
108 struct dss_lcd_mgr_config lcd_config;
109
110 void (*framedone_handler)(void *);
111 void *framedone_handler_data;
112};
113
114static struct {
115 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
116 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
117
118 bool irq_enabled;
119} dss_data;
120
121/* protects dss_data */
122static spinlock_t data_lock;
123/* lock for blocking functions */
124static DEFINE_MUTEX(apply_lock);
125static DECLARE_COMPLETION(extra_updated_completion);
126
127static void dss_register_vsync_isr(void);
128
129static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
130{
131 return &dss_data.ovl_priv_data_array[ovl->id];
132}
133
134static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
135{
136 return &dss_data.mgr_priv_data_array[mgr->id];
137}
138
139static void apply_init_priv(void)
140{
141 const int num_ovls = dss_feat_get_num_ovls();
142 struct mgr_priv_data *mp;
143 int i;
144
145 spin_lock_init(&data_lock);
146
147 for (i = 0; i < num_ovls; ++i) {
148 struct ovl_priv_data *op;
149
150 op = &dss_data.ovl_priv_data_array[i];
151
152 op->info.global_alpha = 255;
153
154 switch (i) {
155 case 0:
156 op->info.zorder = 0;
157 break;
158 case 1:
159 op->info.zorder =
160 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
161 break;
162 case 2:
163 op->info.zorder =
164 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
165 break;
166 case 3:
167 op->info.zorder =
168 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
169 break;
170 }
171
172 op->user_info = op->info;
173 }
174
175 /*
176 * Initialize some of the lcd_config fields for TV manager, this lets
177 * us prevent checking if the manager is LCD or TV at some places
178 */
179 mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
180
181 mp->lcd_config.video_port_width = 24;
182 mp->lcd_config.clock_info.lck_div = 1;
183 mp->lcd_config.clock_info.pck_div = 1;
184}
185
186/*
187 * A LCD manager's stallmode decides whether it is in manual or auto update. TV
188 * manager is always auto update, stallmode field for TV manager is false by
189 * default
190 */
191static bool ovl_manual_update(struct omap_overlay *ovl)
192{
193 struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
194
195 return mp->lcd_config.stallmode;
196}
197
198static bool mgr_manual_update(struct omap_overlay_manager *mgr)
199{
200 struct mgr_priv_data *mp = get_mgr_priv(mgr);
201
202 return mp->lcd_config.stallmode;
203}
204
205static int dss_check_settings_low(struct omap_overlay_manager *mgr,
206 bool applying)
207{
208 struct omap_overlay_info *oi;
209 struct omap_overlay_manager_info *mi;
210 struct omap_overlay *ovl;
211 struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
212 struct ovl_priv_data *op;
213 struct mgr_priv_data *mp;
214
215 mp = get_mgr_priv(mgr);
216
217 if (!mp->enabled)
218 return 0;
219
220 if (applying && mp->user_info_dirty)
221 mi = &mp->user_info;
222 else
223 mi = &mp->info;
224
225 /* collect the infos to be tested into the array */
226 list_for_each_entry(ovl, &mgr->overlays, list) {
227 op = get_ovl_priv(ovl);
228
229 if (!op->enabled && !op->enabling)
230 oi = NULL;
231 else if (applying && op->user_info_dirty)
232 oi = &op->user_info;
233 else
234 oi = &op->info;
235
236 ois[ovl->id] = oi;
237 }
238
239 return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
240}
241
242/*
243 * check manager and overlay settings using overlay_info from data->info
244 */
245static int dss_check_settings(struct omap_overlay_manager *mgr)
246{
247 return dss_check_settings_low(mgr, false);
248}
249
250/*
251 * check manager and overlay settings using overlay_info from ovl->info if
252 * dirty and from data->info otherwise
253 */
254static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
255{
256 return dss_check_settings_low(mgr, true);
257}
258
259static bool need_isr(void)
260{
261 const int num_mgrs = dss_feat_get_num_mgrs();
262 int i;
263
264 for (i = 0; i < num_mgrs; ++i) {
265 struct omap_overlay_manager *mgr;
266 struct mgr_priv_data *mp;
267 struct omap_overlay *ovl;
268
269 mgr = omap_dss_get_overlay_manager(i);
270 mp = get_mgr_priv(mgr);
271
272 if (!mp->enabled)
273 continue;
274
275 if (mgr_manual_update(mgr)) {
276 /* to catch FRAMEDONE */
277 if (mp->updating)
278 return true;
279 } else {
280 /* to catch GO bit going down */
281 if (mp->busy)
282 return true;
283
284 /* to write new values to registers */
285 if (mp->info_dirty)
286 return true;
287
288 /* to set GO bit */
289 if (mp->shadow_info_dirty)
290 return true;
291
292 /*
293 * NOTE: we don't check extra_info flags for disabled
294 * managers, once the manager is enabled, the extra_info
295 * related manager changes will be taken in by HW.
296 */
297
298 /* to write new values to registers */
299 if (mp->extra_info_dirty)
300 return true;
301
302 /* to set GO bit */
303 if (mp->shadow_extra_info_dirty)
304 return true;
305
306 list_for_each_entry(ovl, &mgr->overlays, list) {
307 struct ovl_priv_data *op;
308
309 op = get_ovl_priv(ovl);
310
311 /*
312 * NOTE: we check extra_info flags even for
313 * disabled overlays, as extra_infos need to be
314 * always written.
315 */
316
317 /* to write new values to registers */
318 if (op->extra_info_dirty)
319 return true;
320
321 /* to set GO bit */
322 if (op->shadow_extra_info_dirty)
323 return true;
324
325 if (!op->enabled)
326 continue;
327
328 /* to write new values to registers */
329 if (op->info_dirty)
330 return true;
331
332 /* to set GO bit */
333 if (op->shadow_info_dirty)
334 return true;
335 }
336 }
337 }
338
339 return false;
340}
341
342static bool need_go(struct omap_overlay_manager *mgr)
343{
344 struct omap_overlay *ovl;
345 struct mgr_priv_data *mp;
346 struct ovl_priv_data *op;
347
348 mp = get_mgr_priv(mgr);
349
350 if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
351 return true;
352
353 list_for_each_entry(ovl, &mgr->overlays, list) {
354 op = get_ovl_priv(ovl);
355 if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
356 return true;
357 }
358
359 return false;
360}
361
362/* returns true if an extra_info field is currently being updated */
363static bool extra_info_update_ongoing(void)
364{
365 const int num_mgrs = dss_feat_get_num_mgrs();
366 int i;
367
368 for (i = 0; i < num_mgrs; ++i) {
369 struct omap_overlay_manager *mgr;
370 struct omap_overlay *ovl;
371 struct mgr_priv_data *mp;
372
373 mgr = omap_dss_get_overlay_manager(i);
374 mp = get_mgr_priv(mgr);
375
376 if (!mp->enabled)
377 continue;
378
379 if (!mp->updating)
380 continue;
381
382 if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
383 return true;
384
385 list_for_each_entry(ovl, &mgr->overlays, list) {
386 struct ovl_priv_data *op = get_ovl_priv(ovl);
387
388 if (op->extra_info_dirty || op->shadow_extra_info_dirty)
389 return true;
390 }
391 }
392
393 return false;
394}
395
396/* wait until no extra_info updates are pending */
397static void wait_pending_extra_info_updates(void)
398{
399 bool updating;
400 unsigned long flags;
401 unsigned long t;
402 int r;
403
404 spin_lock_irqsave(&data_lock, flags);
405
406 updating = extra_info_update_ongoing();
407
408 if (!updating) {
409 spin_unlock_irqrestore(&data_lock, flags);
410 return;
411 }
412
413 init_completion(&extra_updated_completion);
414
415 spin_unlock_irqrestore(&data_lock, flags);
416
417 t = msecs_to_jiffies(500);
418 r = wait_for_completion_timeout(&extra_updated_completion, t);
419 if (r == 0)
420 DSSWARN("timeout in wait_pending_extra_info_updates\n");
421}
422
423static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
424{
425 return ovl->manager ?
426 (ovl->manager->output ? ovl->manager->output->device : NULL) :
427 NULL;
428}
429
430static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
431{
432 return mgr->output ? mgr->output->device : NULL;
433}
434
435static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
436{
437 unsigned long timeout = msecs_to_jiffies(500);
438 struct omap_dss_device *dssdev = mgr->get_device(mgr);
439 u32 irq;
440 int r;
441
442 r = dispc_runtime_get();
443 if (r)
444 return r;
445
446 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
447 irq = DISPC_IRQ_EVSYNC_ODD;
448 else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
449 irq = DISPC_IRQ_EVSYNC_EVEN;
450 else
451 irq = dispc_mgr_get_vsync_irq(mgr->id);
452
453 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
454
455 dispc_runtime_put();
456
457 return r;
458}
459
460static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
461{
462 unsigned long timeout = msecs_to_jiffies(500);
463 struct mgr_priv_data *mp = get_mgr_priv(mgr);
464 u32 irq;
465 unsigned long flags;
466 int r;
467 int i;
468
469 spin_lock_irqsave(&data_lock, flags);
470
471 if (mgr_manual_update(mgr)) {
472 spin_unlock_irqrestore(&data_lock, flags);
473 return 0;
474 }
475
476 if (!mp->enabled) {
477 spin_unlock_irqrestore(&data_lock, flags);
478 return 0;
479 }
480
481 spin_unlock_irqrestore(&data_lock, flags);
482
483 r = dispc_runtime_get();
484 if (r)
485 return r;
486
487 irq = dispc_mgr_get_vsync_irq(mgr->id);
488
489 i = 0;
490 while (1) {
491 bool shadow_dirty, dirty;
492
493 spin_lock_irqsave(&data_lock, flags);
494 dirty = mp->info_dirty;
495 shadow_dirty = mp->shadow_info_dirty;
496 spin_unlock_irqrestore(&data_lock, flags);
497
498 if (!dirty && !shadow_dirty) {
499 r = 0;
500 break;
501 }
502
503 /* 4 iterations is the worst case:
504 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
505 * 2 - first VSYNC, dirty = true
506 * 3 - dirty = false, shadow_dirty = true
507 * 4 - shadow_dirty = false */
508 if (i++ == 3) {
509 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
510 mgr->id);
511 r = 0;
512 break;
513 }
514
515 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
516 if (r == -ERESTARTSYS)
517 break;
518
519 if (r) {
520 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
521 break;
522 }
523 }
524
525 dispc_runtime_put();
526
527 return r;
528}
529
530static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
531{
532 unsigned long timeout = msecs_to_jiffies(500);
533 struct ovl_priv_data *op;
534 struct mgr_priv_data *mp;
535 u32 irq;
536 unsigned long flags;
537 int r;
538 int i;
539
540 if (!ovl->manager)
541 return 0;
542
543 mp = get_mgr_priv(ovl->manager);
544
545 spin_lock_irqsave(&data_lock, flags);
546
547 if (ovl_manual_update(ovl)) {
548 spin_unlock_irqrestore(&data_lock, flags);
549 return 0;
550 }
551
552 if (!mp->enabled) {
553 spin_unlock_irqrestore(&data_lock, flags);
554 return 0;
555 }
556
557 spin_unlock_irqrestore(&data_lock, flags);
558
559 r = dispc_runtime_get();
560 if (r)
561 return r;
562
563 irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
564
565 op = get_ovl_priv(ovl);
566 i = 0;
567 while (1) {
568 bool shadow_dirty, dirty;
569
570 spin_lock_irqsave(&data_lock, flags);
571 dirty = op->info_dirty;
572 shadow_dirty = op->shadow_info_dirty;
573 spin_unlock_irqrestore(&data_lock, flags);
574
575 if (!dirty && !shadow_dirty) {
576 r = 0;
577 break;
578 }
579
580 /* 4 iterations is the worst case:
581 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
582 * 2 - first VSYNC, dirty = true
583 * 3 - dirty = false, shadow_dirty = true
584 * 4 - shadow_dirty = false */
585 if (i++ == 3) {
586 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
587 ovl->id);
588 r = 0;
589 break;
590 }
591
592 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
593 if (r == -ERESTARTSYS)
594 break;
595
596 if (r) {
597 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
598 break;
599 }
600 }
601
602 dispc_runtime_put();
603
604 return r;
605}
606
607static void dss_ovl_write_regs(struct omap_overlay *ovl)
608{
609 struct ovl_priv_data *op = get_ovl_priv(ovl);
610 struct omap_overlay_info *oi;
611 bool replication;
612 struct mgr_priv_data *mp;
613 int r;
614
615 DSSDBG("writing ovl %d regs", ovl->id);
616
617 if (!op->enabled || !op->info_dirty)
618 return;
619
620 oi = &op->info;
621
622 mp = get_mgr_priv(ovl->manager);
623
624 replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
625
626 r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
627 if (r) {
628 /*
629 * We can't do much here, as this function can be called from
630 * vsync interrupt.
631 */
632 DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
633
634 /* This will leave fifo configurations in a nonoptimal state */
635 op->enabled = false;
636 dispc_ovl_enable(ovl->id, false);
637 return;
638 }
639
640 op->info_dirty = false;
641 if (mp->updating)
642 op->shadow_info_dirty = true;
643}
644
645static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
646{
647 struct ovl_priv_data *op = get_ovl_priv(ovl);
648 struct mgr_priv_data *mp;
649
650 DSSDBG("writing ovl %d regs extra", ovl->id);
651
652 if (!op->extra_info_dirty)
653 return;
654
655 /* note: write also when op->enabled == false, so that the ovl gets
656 * disabled */
657
658 dispc_ovl_enable(ovl->id, op->enabled);
659 dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
660
661 mp = get_mgr_priv(ovl->manager);
662
663 op->extra_info_dirty = false;
664 if (mp->updating)
665 op->shadow_extra_info_dirty = true;
666}
667
668static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
669{
670 struct mgr_priv_data *mp = get_mgr_priv(mgr);
671 struct omap_overlay *ovl;
672
673 DSSDBG("writing mgr %d regs", mgr->id);
674
675 if (!mp->enabled)
676 return;
677
678 WARN_ON(mp->busy);
679
680 /* Commit overlay settings */
681 list_for_each_entry(ovl, &mgr->overlays, list) {
682 dss_ovl_write_regs(ovl);
683 dss_ovl_write_regs_extra(ovl);
684 }
685
686 if (mp->info_dirty) {
687 dispc_mgr_setup(mgr->id, &mp->info);
688
689 mp->info_dirty = false;
690 if (mp->updating)
691 mp->shadow_info_dirty = true;
692 }
693}
694
695static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
696{
697 struct mgr_priv_data *mp = get_mgr_priv(mgr);
698
699 DSSDBG("writing mgr %d regs extra", mgr->id);
700
701 if (!mp->extra_info_dirty)
702 return;
703
704 dispc_mgr_set_timings(mgr->id, &mp->timings);
705
706 /* lcd_config parameters */
707 if (dss_mgr_is_lcd(mgr->id))
708 dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
709
710 mp->extra_info_dirty = false;
711 if (mp->updating)
712 mp->shadow_extra_info_dirty = true;
713}
714
715static void dss_write_regs(void)
716{
717 const int num_mgrs = omap_dss_get_num_overlay_managers();
718 int i;
719
720 for (i = 0; i < num_mgrs; ++i) {
721 struct omap_overlay_manager *mgr;
722 struct mgr_priv_data *mp;
723 int r;
724
725 mgr = omap_dss_get_overlay_manager(i);
726 mp = get_mgr_priv(mgr);
727
728 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
729 continue;
730
731 r = dss_check_settings(mgr);
732 if (r) {
733 DSSERR("cannot write registers for manager %s: "
734 "illegal configuration\n", mgr->name);
735 continue;
736 }
737
738 dss_mgr_write_regs(mgr);
739 dss_mgr_write_regs_extra(mgr);
740 }
741}
742
743static void dss_set_go_bits(void)
744{
745 const int num_mgrs = omap_dss_get_num_overlay_managers();
746 int i;
747
748 for (i = 0; i < num_mgrs; ++i) {
749 struct omap_overlay_manager *mgr;
750 struct mgr_priv_data *mp;
751
752 mgr = omap_dss_get_overlay_manager(i);
753 mp = get_mgr_priv(mgr);
754
755 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
756 continue;
757
758 if (!need_go(mgr))
759 continue;
760
761 mp->busy = true;
762
763 if (!dss_data.irq_enabled && need_isr())
764 dss_register_vsync_isr();
765
766 dispc_mgr_go(mgr->id);
767 }
768
769}
770
771static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
772{
773 struct omap_overlay *ovl;
774 struct mgr_priv_data *mp;
775 struct ovl_priv_data *op;
776
777 mp = get_mgr_priv(mgr);
778 mp->shadow_info_dirty = false;
779 mp->shadow_extra_info_dirty = false;
780
781 list_for_each_entry(ovl, &mgr->overlays, list) {
782 op = get_ovl_priv(ovl);
783 op->shadow_info_dirty = false;
784 op->shadow_extra_info_dirty = false;
785 }
786}
787
788static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
789{
790 struct mgr_priv_data *mp = get_mgr_priv(mgr);
791 unsigned long flags;
792 int r;
793
794 spin_lock_irqsave(&data_lock, flags);
795
796 WARN_ON(mp->updating);
797
798 r = dss_check_settings(mgr);
799 if (r) {
800 DSSERR("cannot start manual update: illegal configuration\n");
801 spin_unlock_irqrestore(&data_lock, flags);
802 return;
803 }
804
805 dss_mgr_write_regs(mgr);
806 dss_mgr_write_regs_extra(mgr);
807
808 mp->updating = true;
809
810 if (!dss_data.irq_enabled && need_isr())
811 dss_register_vsync_isr();
812
813 dispc_mgr_enable_sync(mgr->id);
814
815 spin_unlock_irqrestore(&data_lock, flags);
816}
817
818static void dss_apply_irq_handler(void *data, u32 mask);
819
820static void dss_register_vsync_isr(void)
821{
822 const int num_mgrs = dss_feat_get_num_mgrs();
823 u32 mask;
824 int r, i;
825
826 mask = 0;
827 for (i = 0; i < num_mgrs; ++i)
828 mask |= dispc_mgr_get_vsync_irq(i);
829
830 for (i = 0; i < num_mgrs; ++i)
831 mask |= dispc_mgr_get_framedone_irq(i);
832
833 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
834 WARN_ON(r);
835
836 dss_data.irq_enabled = true;
837}
838
839static void dss_unregister_vsync_isr(void)
840{
841 const int num_mgrs = dss_feat_get_num_mgrs();
842 u32 mask;
843 int r, i;
844
845 mask = 0;
846 for (i = 0; i < num_mgrs; ++i)
847 mask |= dispc_mgr_get_vsync_irq(i);
848
849 for (i = 0; i < num_mgrs; ++i)
850 mask |= dispc_mgr_get_framedone_irq(i);
851
852 r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
853 WARN_ON(r);
854
855 dss_data.irq_enabled = false;
856}
857
858static void dss_apply_irq_handler(void *data, u32 mask)
859{
860 const int num_mgrs = dss_feat_get_num_mgrs();
861 int i;
862 bool extra_updating;
863
864 spin_lock(&data_lock);
865
866 /* clear busy, updating flags, shadow_dirty flags */
867 for (i = 0; i < num_mgrs; i++) {
868 struct omap_overlay_manager *mgr;
869 struct mgr_priv_data *mp;
870
871 mgr = omap_dss_get_overlay_manager(i);
872 mp = get_mgr_priv(mgr);
873
874 if (!mp->enabled)
875 continue;
876
877 mp->updating = dispc_mgr_is_enabled(i);
878
879 if (!mgr_manual_update(mgr)) {
880 bool was_busy = mp->busy;
881 mp->busy = dispc_mgr_go_busy(i);
882
883 if (was_busy && !mp->busy)
884 mgr_clear_shadow_dirty(mgr);
885 }
886 }
887
888 dss_write_regs();
889 dss_set_go_bits();
890
891 extra_updating = extra_info_update_ongoing();
892 if (!extra_updating)
893 complete_all(&extra_updated_completion);
894
895 /* call framedone handlers for manual update displays */
896 for (i = 0; i < num_mgrs; i++) {
897 struct omap_overlay_manager *mgr;
898 struct mgr_priv_data *mp;
899
900 mgr = omap_dss_get_overlay_manager(i);
901 mp = get_mgr_priv(mgr);
902
903 if (!mgr_manual_update(mgr) || !mp->framedone_handler)
904 continue;
905
906 if (mask & dispc_mgr_get_framedone_irq(i))
907 mp->framedone_handler(mp->framedone_handler_data);
908 }
909
910 if (!need_isr())
911 dss_unregister_vsync_isr();
912
913 spin_unlock(&data_lock);
914}
915
916static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
917{
918 struct ovl_priv_data *op;
919
920 op = get_ovl_priv(ovl);
921
922 if (!op->user_info_dirty)
923 return;
924
925 op->user_info_dirty = false;
926 op->info_dirty = true;
927 op->info = op->user_info;
928}
929
930static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
931{
932 struct mgr_priv_data *mp;
933
934 mp = get_mgr_priv(mgr);
935
936 if (!mp->user_info_dirty)
937 return;
938
939 mp->user_info_dirty = false;
940 mp->info_dirty = true;
941 mp->info = mp->user_info;
942}
943
944static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
945{
946 unsigned long flags;
947 struct omap_overlay *ovl;
948 int r;
949
950 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
951
952 spin_lock_irqsave(&data_lock, flags);
953
954 r = dss_check_settings_apply(mgr);
955 if (r) {
956 spin_unlock_irqrestore(&data_lock, flags);
957 DSSERR("failed to apply settings: illegal configuration.\n");
958 return r;
959 }
960
961 /* Configure overlays */
962 list_for_each_entry(ovl, &mgr->overlays, list)
963 omap_dss_mgr_apply_ovl(ovl);
964
965 /* Configure manager */
966 omap_dss_mgr_apply_mgr(mgr);
967
968 dss_write_regs();
969 dss_set_go_bits();
970
971 spin_unlock_irqrestore(&data_lock, flags);
972
973 return 0;
974}
975
976static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
977{
978 struct ovl_priv_data *op;
979
980 op = get_ovl_priv(ovl);
981
982 if (op->enabled == enable)
983 return;
984
985 op->enabled = enable;
986 op->extra_info_dirty = true;
987}
988
989static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
990 u32 fifo_low, u32 fifo_high)
991{
992 struct ovl_priv_data *op = get_ovl_priv(ovl);
993
994 if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
995 return;
996
997 op->fifo_low = fifo_low;
998 op->fifo_high = fifo_high;
999 op->extra_info_dirty = true;
1000}
1001
1002static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
1003{
1004 struct ovl_priv_data *op = get_ovl_priv(ovl);
1005 u32 fifo_low, fifo_high;
1006 bool use_fifo_merge = false;
1007
1008 if (!op->enabled && !op->enabling)
1009 return;
1010
1011 dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
1012 use_fifo_merge, ovl_manual_update(ovl));
1013
1014 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
1015}
1016
1017static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
1018{
1019 struct omap_overlay *ovl;
1020 struct mgr_priv_data *mp;
1021
1022 mp = get_mgr_priv(mgr);
1023
1024 if (!mp->enabled)
1025 return;
1026
1027 list_for_each_entry(ovl, &mgr->overlays, list)
1028 dss_ovl_setup_fifo(ovl);
1029}
1030
1031static void dss_setup_fifos(void)
1032{
1033 const int num_mgrs = omap_dss_get_num_overlay_managers();
1034 struct omap_overlay_manager *mgr;
1035 int i;
1036
1037 for (i = 0; i < num_mgrs; ++i) {
1038 mgr = omap_dss_get_overlay_manager(i);
1039 dss_mgr_setup_fifos(mgr);
1040 }
1041}
1042
1043static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
1044{
1045 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1046 unsigned long flags;
1047 int r;
1048
1049 mutex_lock(&apply_lock);
1050
1051 if (mp->enabled)
1052 goto out;
1053
1054 spin_lock_irqsave(&data_lock, flags);
1055
1056 mp->enabled = true;
1057
1058 r = dss_check_settings(mgr);
1059 if (r) {
1060 DSSERR("failed to enable manager %d: check_settings failed\n",
1061 mgr->id);
1062 goto err;
1063 }
1064
1065 dss_setup_fifos();
1066
1067 dss_write_regs();
1068 dss_set_go_bits();
1069
1070 if (!mgr_manual_update(mgr))
1071 mp->updating = true;
1072
1073 if (!dss_data.irq_enabled && need_isr())
1074 dss_register_vsync_isr();
1075
1076 spin_unlock_irqrestore(&data_lock, flags);
1077
1078 if (!mgr_manual_update(mgr))
1079 dispc_mgr_enable_sync(mgr->id);
1080
1081out:
1082 mutex_unlock(&apply_lock);
1083
1084 return 0;
1085
1086err:
1087 mp->enabled = false;
1088 spin_unlock_irqrestore(&data_lock, flags);
1089 mutex_unlock(&apply_lock);
1090 return r;
1091}
1092
1093static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
1094{
1095 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1096 unsigned long flags;
1097
1098 mutex_lock(&apply_lock);
1099
1100 if (!mp->enabled)
1101 goto out;
1102
1103 if (!mgr_manual_update(mgr))
1104 dispc_mgr_disable_sync(mgr->id);
1105
1106 spin_lock_irqsave(&data_lock, flags);
1107
1108 mp->updating = false;
1109 mp->enabled = false;
1110
1111 spin_unlock_irqrestore(&data_lock, flags);
1112
1113out:
1114 mutex_unlock(&apply_lock);
1115}
1116
1117static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
1118 struct omap_overlay_manager_info *info)
1119{
1120 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1121 unsigned long flags;
1122 int r;
1123
1124 r = dss_mgr_simple_check(mgr, info);
1125 if (r)
1126 return r;
1127
1128 spin_lock_irqsave(&data_lock, flags);
1129
1130 mp->user_info = *info;
1131 mp->user_info_dirty = true;
1132
1133 spin_unlock_irqrestore(&data_lock, flags);
1134
1135 return 0;
1136}
1137
1138static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1139 struct omap_overlay_manager_info *info)
1140{
1141 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1142 unsigned long flags;
1143
1144 spin_lock_irqsave(&data_lock, flags);
1145
1146 *info = mp->user_info;
1147
1148 spin_unlock_irqrestore(&data_lock, flags);
1149}
1150
1151static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
1152 struct omap_dss_output *output)
1153{
1154 int r;
1155
1156 mutex_lock(&apply_lock);
1157
1158 if (mgr->output) {
1159 DSSERR("manager %s is already connected to an output\n",
1160 mgr->name);
1161 r = -EINVAL;
1162 goto err;
1163 }
1164
1165 if ((mgr->supported_outputs & output->id) == 0) {
1166 DSSERR("output does not support manager %s\n",
1167 mgr->name);
1168 r = -EINVAL;
1169 goto err;
1170 }
1171
1172 output->manager = mgr;
1173 mgr->output = output;
1174
1175 mutex_unlock(&apply_lock);
1176
1177 return 0;
1178err:
1179 mutex_unlock(&apply_lock);
1180 return r;
1181}
1182
1183static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
1184{
1185 int r;
1186 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1187 unsigned long flags;
1188
1189 mutex_lock(&apply_lock);
1190
1191 if (!mgr->output) {
1192 DSSERR("failed to unset output, output not set\n");
1193 r = -EINVAL;
1194 goto err;
1195 }
1196
1197 spin_lock_irqsave(&data_lock, flags);
1198
1199 if (mp->enabled) {
1200 DSSERR("output can't be unset when manager is enabled\n");
1201 r = -EINVAL;
1202 goto err1;
1203 }
1204
1205 spin_unlock_irqrestore(&data_lock, flags);
1206
1207 mgr->output->manager = NULL;
1208 mgr->output = NULL;
1209
1210 mutex_unlock(&apply_lock);
1211
1212 return 0;
1213err1:
1214 spin_unlock_irqrestore(&data_lock, flags);
1215err:
1216 mutex_unlock(&apply_lock);
1217
1218 return r;
1219}
1220
1221static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1222 const struct omap_video_timings *timings)
1223{
1224 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1225
1226 mp->timings = *timings;
1227 mp->extra_info_dirty = true;
1228}
1229
1230static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
1231 const struct omap_video_timings *timings)
1232{
1233 unsigned long flags;
1234 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1235
1236 spin_lock_irqsave(&data_lock, flags);
1237
1238 if (mp->updating) {
1239 DSSERR("cannot set timings for %s: manager needs to be disabled\n",
1240 mgr->name);
1241 goto out;
1242 }
1243
1244 dss_apply_mgr_timings(mgr, timings);
1245out:
1246 spin_unlock_irqrestore(&data_lock, flags);
1247}
1248
1249static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
1250 const struct dss_lcd_mgr_config *config)
1251{
1252 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1253
1254 mp->lcd_config = *config;
1255 mp->extra_info_dirty = true;
1256}
1257
1258static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
1259 const struct dss_lcd_mgr_config *config)
1260{
1261 unsigned long flags;
1262 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1263
1264 spin_lock_irqsave(&data_lock, flags);
1265
1266 if (mp->enabled) {
1267 DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
1268 mgr->name);
1269 goto out;
1270 }
1271
1272 dss_apply_mgr_lcd_config(mgr, config);
1273out:
1274 spin_unlock_irqrestore(&data_lock, flags);
1275}
1276
1277static int dss_ovl_set_info(struct omap_overlay *ovl,
1278 struct omap_overlay_info *info)
1279{
1280 struct ovl_priv_data *op = get_ovl_priv(ovl);
1281 unsigned long flags;
1282 int r;
1283
1284 r = dss_ovl_simple_check(ovl, info);
1285 if (r)
1286 return r;
1287
1288 spin_lock_irqsave(&data_lock, flags);
1289
1290 op->user_info = *info;
1291 op->user_info_dirty = true;
1292
1293 spin_unlock_irqrestore(&data_lock, flags);
1294
1295 return 0;
1296}
1297
1298static void dss_ovl_get_info(struct omap_overlay *ovl,
1299 struct omap_overlay_info *info)
1300{
1301 struct ovl_priv_data *op = get_ovl_priv(ovl);
1302 unsigned long flags;
1303
1304 spin_lock_irqsave(&data_lock, flags);
1305
1306 *info = op->user_info;
1307
1308 spin_unlock_irqrestore(&data_lock, flags);
1309}
1310
1311static int dss_ovl_set_manager(struct omap_overlay *ovl,
1312 struct omap_overlay_manager *mgr)
1313{
1314 struct ovl_priv_data *op = get_ovl_priv(ovl);
1315 unsigned long flags;
1316 int r;
1317
1318 if (!mgr)
1319 return -EINVAL;
1320
1321 mutex_lock(&apply_lock);
1322
1323 if (ovl->manager) {
1324 DSSERR("overlay '%s' already has a manager '%s'\n",
1325 ovl->name, ovl->manager->name);
1326 r = -EINVAL;
1327 goto err;
1328 }
1329
1330 r = dispc_runtime_get();
1331 if (r)
1332 goto err;
1333
1334 spin_lock_irqsave(&data_lock, flags);
1335
1336 if (op->enabled) {
1337 spin_unlock_irqrestore(&data_lock, flags);
1338 DSSERR("overlay has to be disabled to change the manager\n");
1339 r = -EINVAL;
1340 goto err1;
1341 }
1342
1343 dispc_ovl_set_channel_out(ovl->id, mgr->id);
1344
1345 ovl->manager = mgr;
1346 list_add_tail(&ovl->list, &mgr->overlays);
1347
1348 spin_unlock_irqrestore(&data_lock, flags);
1349
1350 dispc_runtime_put();
1351
1352 mutex_unlock(&apply_lock);
1353
1354 return 0;
1355
1356err1:
1357 dispc_runtime_put();
1358err:
1359 mutex_unlock(&apply_lock);
1360 return r;
1361}
1362
1363static int dss_ovl_unset_manager(struct omap_overlay *ovl)
1364{
1365 struct ovl_priv_data *op = get_ovl_priv(ovl);
1366 unsigned long flags;
1367 int r;
1368
1369 mutex_lock(&apply_lock);
1370
1371 if (!ovl->manager) {
1372 DSSERR("failed to detach overlay: manager not set\n");
1373 r = -EINVAL;
1374 goto err;
1375 }
1376
1377 spin_lock_irqsave(&data_lock, flags);
1378
1379 if (op->enabled) {
1380 spin_unlock_irqrestore(&data_lock, flags);
1381 DSSERR("overlay has to be disabled to unset the manager\n");
1382 r = -EINVAL;
1383 goto err;
1384 }
1385
1386 spin_unlock_irqrestore(&data_lock, flags);
1387
1388 /* wait for pending extra_info updates to ensure the ovl is disabled */
1389 wait_pending_extra_info_updates();
1390
1391 /*
1392 * For a manual update display, there is no guarantee that the overlay
1393 * is really disabled in HW, we may need an extra update from this
1394 * manager before the configurations can go in. Return an error if the
1395 * overlay needed an update from the manager.
1396 *
1397 * TODO: Instead of returning an error, try to do a dummy manager update
1398 * here to disable the overlay in hardware. Use the *GATED fields in
1399 * the DISPC_CONFIG registers to do a dummy update.
1400 */
1401 spin_lock_irqsave(&data_lock, flags);
1402
1403 if (ovl_manual_update(ovl) && op->extra_info_dirty) {
1404 spin_unlock_irqrestore(&data_lock, flags);
1405 DSSERR("need an update to change the manager\n");
1406 r = -EINVAL;
1407 goto err;
1408 }
1409
1410 ovl->manager = NULL;
1411 list_del(&ovl->list);
1412
1413 spin_unlock_irqrestore(&data_lock, flags);
1414
1415 mutex_unlock(&apply_lock);
1416
1417 return 0;
1418err:
1419 mutex_unlock(&apply_lock);
1420 return r;
1421}
1422
1423static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1424{
1425 struct ovl_priv_data *op = get_ovl_priv(ovl);
1426 unsigned long flags;
1427 bool e;
1428
1429 spin_lock_irqsave(&data_lock, flags);
1430
1431 e = op->enabled;
1432
1433 spin_unlock_irqrestore(&data_lock, flags);
1434
1435 return e;
1436}
1437
1438static int dss_ovl_enable(struct omap_overlay *ovl)
1439{
1440 struct ovl_priv_data *op = get_ovl_priv(ovl);
1441 unsigned long flags;
1442 int r;
1443
1444 mutex_lock(&apply_lock);
1445
1446 if (op->enabled) {
1447 r = 0;
1448 goto err1;
1449 }
1450
1451 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1452 r = -EINVAL;
1453 goto err1;
1454 }
1455
1456 spin_lock_irqsave(&data_lock, flags);
1457
1458 op->enabling = true;
1459
1460 r = dss_check_settings(ovl->manager);
1461 if (r) {
1462 DSSERR("failed to enable overlay %d: check_settings failed\n",
1463 ovl->id);
1464 goto err2;
1465 }
1466
1467 dss_setup_fifos();
1468
1469 op->enabling = false;
1470 dss_apply_ovl_enable(ovl, true);
1471
1472 dss_write_regs();
1473 dss_set_go_bits();
1474
1475 spin_unlock_irqrestore(&data_lock, flags);
1476
1477 mutex_unlock(&apply_lock);
1478
1479 return 0;
1480err2:
1481 op->enabling = false;
1482 spin_unlock_irqrestore(&data_lock, flags);
1483err1:
1484 mutex_unlock(&apply_lock);
1485 return r;
1486}
1487
1488static int dss_ovl_disable(struct omap_overlay *ovl)
1489{
1490 struct ovl_priv_data *op = get_ovl_priv(ovl);
1491 unsigned long flags;
1492 int r;
1493
1494 mutex_lock(&apply_lock);
1495
1496 if (!op->enabled) {
1497 r = 0;
1498 goto err;
1499 }
1500
1501 if (ovl->manager == NULL || ovl->manager->output == NULL) {
1502 r = -EINVAL;
1503 goto err;
1504 }
1505
1506 spin_lock_irqsave(&data_lock, flags);
1507
1508 dss_apply_ovl_enable(ovl, false);
1509 dss_write_regs();
1510 dss_set_go_bits();
1511
1512 spin_unlock_irqrestore(&data_lock, flags);
1513
1514 mutex_unlock(&apply_lock);
1515
1516 return 0;
1517
1518err:
1519 mutex_unlock(&apply_lock);
1520 return r;
1521}
1522
1523static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
1524 void (*handler)(void *), void *data)
1525{
1526 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1527
1528 if (mp->framedone_handler)
1529 return -EBUSY;
1530
1531 mp->framedone_handler = handler;
1532 mp->framedone_handler_data = data;
1533
1534 return 0;
1535}
1536
1537static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
1538 void (*handler)(void *), void *data)
1539{
1540 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1541
1542 WARN_ON(mp->framedone_handler != handler ||
1543 mp->framedone_handler_data != data);
1544
1545 mp->framedone_handler = NULL;
1546 mp->framedone_handler_data = NULL;
1547}
1548
1549static const struct dss_mgr_ops apply_mgr_ops = {
1550 .start_update = dss_mgr_start_update_compat,
1551 .enable = dss_mgr_enable_compat,
1552 .disable = dss_mgr_disable_compat,
1553 .set_timings = dss_mgr_set_timings_compat,
1554 .set_lcd_config = dss_mgr_set_lcd_config_compat,
1555 .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
1556 .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
1557};
1558
1559static int compat_refcnt;
1560static DEFINE_MUTEX(compat_init_lock);
1561
1562int omapdss_compat_init(void)
1563{
1564 struct platform_device *pdev = dss_get_core_pdev();
1565 struct omap_dss_device *dssdev = NULL;
1566 int i, r;
1567
1568 mutex_lock(&compat_init_lock);
1569
1570 if (compat_refcnt++ > 0)
1571 goto out;
1572
1573 apply_init_priv();
1574
1575 dss_init_overlay_managers(pdev);
1576 dss_init_overlays(pdev);
1577
1578 for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
1579 struct omap_overlay_manager *mgr;
1580
1581 mgr = omap_dss_get_overlay_manager(i);
1582
1583 mgr->set_output = &dss_mgr_set_output;
1584 mgr->unset_output = &dss_mgr_unset_output;
1585 mgr->apply = &omap_dss_mgr_apply;
1586 mgr->set_manager_info = &dss_mgr_set_info;
1587 mgr->get_manager_info = &dss_mgr_get_info;
1588 mgr->wait_for_go = &dss_mgr_wait_for_go;
1589 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1590 mgr->get_device = &dss_mgr_get_device;
1591 }
1592
1593 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
1594 struct omap_overlay *ovl = omap_dss_get_overlay(i);
1595
1596 ovl->is_enabled = &dss_ovl_is_enabled;
1597 ovl->enable = &dss_ovl_enable;
1598 ovl->disable = &dss_ovl_disable;
1599 ovl->set_manager = &dss_ovl_set_manager;
1600 ovl->unset_manager = &dss_ovl_unset_manager;
1601 ovl->set_overlay_info = &dss_ovl_set_info;
1602 ovl->get_overlay_info = &dss_ovl_get_info;
1603 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
1604 ovl->get_device = &dss_ovl_get_device;
1605 }
1606
1607 r = dss_install_mgr_ops(&apply_mgr_ops);
1608 if (r)
1609 goto err_mgr_ops;
1610
1611 for_each_dss_dev(dssdev) {
1612 r = display_init_sysfs(pdev, dssdev);
1613 /* XXX uninit sysfs files on error */
1614 if (r)
1615 goto err_disp_sysfs;
1616 }
1617
1618 dispc_runtime_get();
1619
1620 r = dss_dispc_initialize_irq();
1621 if (r)
1622 goto err_init_irq;
1623
1624 dispc_runtime_put();
1625
1626out:
1627 mutex_unlock(&compat_init_lock);
1628
1629 return 0;
1630
1631err_init_irq:
1632 dispc_runtime_put();
1633
1634err_disp_sysfs:
1635 dss_uninstall_mgr_ops();
1636
1637err_mgr_ops:
1638 dss_uninit_overlay_managers(pdev);
1639 dss_uninit_overlays(pdev);
1640
1641 compat_refcnt--;
1642
1643 mutex_unlock(&compat_init_lock);
1644
1645 return r;
1646}
1647EXPORT_SYMBOL(omapdss_compat_init);
1648
1649void omapdss_compat_uninit(void)
1650{
1651 struct platform_device *pdev = dss_get_core_pdev();
1652 struct omap_dss_device *dssdev = NULL;
1653
1654 mutex_lock(&compat_init_lock);
1655
1656 if (--compat_refcnt > 0)
1657 goto out;
1658
1659 dss_dispc_uninitialize_irq();
1660
1661 for_each_dss_dev(dssdev)
1662 display_uninit_sysfs(pdev, dssdev);
1663
1664 dss_uninstall_mgr_ops();
1665
1666 dss_uninit_overlay_managers(pdev);
1667 dss_uninit_overlays(pdev);
1668out:
1669 mutex_unlock(&compat_init_lock);
1670}
1671EXPORT_SYMBOL(omapdss_compat_uninit);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index f8779d4750b..76821fefce9 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -32,8 +32,6 @@
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/device.h> 33#include <linux/device.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/suspend.h>
36#include <linux/slab.h>
37 35
38#include <video/omapdss.h> 36#include <video/omapdss.h>
39 37
@@ -45,31 +43,19 @@ static struct {
45 43
46 struct regulator *vdds_dsi_reg; 44 struct regulator *vdds_dsi_reg;
47 struct regulator *vdds_sdi_reg; 45 struct regulator *vdds_sdi_reg;
48
49 const char *default_display_name;
50} core; 46} core;
51 47
52static char *def_disp_name; 48static char *def_disp_name;
53module_param_named(def_disp, def_disp_name, charp, 0); 49module_param_named(def_disp, def_disp_name, charp, 0);
54MODULE_PARM_DESC(def_disp, "default display name"); 50MODULE_PARM_DESC(def_disp, "default display name");
55 51
56const char *omapdss_get_default_display_name(void) 52#ifdef DEBUG
57{ 53unsigned int dss_debug;
58 return core.default_display_name; 54module_param_named(debug, dss_debug, bool, 0644);
59} 55#endif
60EXPORT_SYMBOL(omapdss_get_default_display_name);
61
62enum omapdss_version omapdss_get_version(void)
63{
64 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
65 return pdata->version;
66}
67EXPORT_SYMBOL(omapdss_get_version);
68 56
69struct platform_device *dss_get_core_pdev(void) 57static int omap_dss_register_device(struct omap_dss_device *);
70{ 58static void omap_dss_unregister_device(struct omap_dss_device *);
71 return core.pdev;
72}
73 59
74/* REGULATORS */ 60/* REGULATORS */
75 61
@@ -101,37 +87,7 @@ struct regulator *dss_get_vdds_sdi(void)
101 return reg; 87 return reg;
102} 88}
103 89
104int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask) 90#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
105{
106 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
107
108 if (!board_data->dsi_enable_pads)
109 return -ENOENT;
110
111 return board_data->dsi_enable_pads(dsi_id, lane_mask);
112}
113
114void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
115{
116 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
117
118 if (!board_data->dsi_disable_pads)
119 return;
120
121 return board_data->dsi_disable_pads(dsi_id, lane_mask);
122}
123
124int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
125{
126 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
127
128 if (pdata->set_min_bus_tput)
129 return pdata->set_min_bus_tput(dev, tput);
130 else
131 return 0;
132}
133
134#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
135static int dss_debug_show(struct seq_file *s, void *unused) 91static int dss_debug_show(struct seq_file *s, void *unused)
136{ 92{
137 void (*func)(struct seq_file *) = s->private; 93 void (*func)(struct seq_file *) = s->private;
@@ -165,6 +121,30 @@ static int dss_initialize_debugfs(void)
165 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 121 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
166 &dss_debug_dump_clocks, &dss_debug_fops); 122 &dss_debug_dump_clocks, &dss_debug_fops);
167 123
124#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
125 debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
126 &dispc_dump_irqs, &dss_debug_fops);
127#endif
128
129#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
130 dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops);
131#endif
132
133 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
134 &dss_dump_regs, &dss_debug_fops);
135 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
136 &dispc_dump_regs, &dss_debug_fops);
137#ifdef CONFIG_OMAP2_DSS_RFBI
138 debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
139 &rfbi_dump_regs, &dss_debug_fops);
140#endif
141#ifdef CONFIG_OMAP2_DSS_DSI
142 dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops);
143#endif
144#ifdef CONFIG_OMAP2_DSS_VENC
145 debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
146 &venc_dump_regs, &dss_debug_fops);
147#endif
168 return 0; 148 return 0;
169} 149}
170 150
@@ -173,20 +153,7 @@ static void dss_uninitialize_debugfs(void)
173 if (dss_debugfs_dir) 153 if (dss_debugfs_dir)
174 debugfs_remove_recursive(dss_debugfs_dir); 154 debugfs_remove_recursive(dss_debugfs_dir);
175} 155}
176 156#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
177int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
178{
179 struct dentry *d;
180
181 d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
182 write, &dss_debug_fops);
183
184 if (IS_ERR(d))
185 return PTR_ERR(d);
186
187 return 0;
188}
189#else /* CONFIG_OMAP2_DSS_DEBUGFS */
190static inline int dss_initialize_debugfs(void) 157static inline int dss_initialize_debugfs(void)
191{ 158{
192 return 0; 159 return 0;
@@ -194,68 +161,121 @@ static inline int dss_initialize_debugfs(void)
194static inline void dss_uninitialize_debugfs(void) 161static inline void dss_uninitialize_debugfs(void)
195{ 162{
196} 163}
197int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) 164#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
198{
199 return 0;
200}
201#endif /* CONFIG_OMAP2_DSS_DEBUGFS */
202 165
203/* PLATFORM DEVICE */ 166/* PLATFORM DEVICE */
204static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d) 167static int omap_dss_probe(struct platform_device *pdev)
205{ 168{
206 DSSDBG("pm notif %lu\n", v); 169 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
170 int r;
171 int i;
207 172
208 switch (v) { 173 core.pdev = pdev;
209 case PM_SUSPEND_PREPARE: 174
210 DSSDBG("suspending displays\n"); 175 dss_features_init();
211 return dss_suspend_all_devices();
212 176
213 case PM_POST_SUSPEND: 177 dss_init_overlay_managers(pdev);
214 DSSDBG("resuming displays\n"); 178 dss_init_overlays(pdev);
215 return dss_resume_all_devices();
216 179
217 default: 180 r = dss_init_platform_driver();
218 return 0; 181 if (r) {
182 DSSERR("Failed to initialize DSS platform driver\n");
183 goto err_dss;
219 } 184 }
220}
221 185
222static struct notifier_block omap_dss_pm_notif_block = { 186 r = dispc_init_platform_driver();
223 .notifier_call = omap_dss_pm_notif, 187 if (r) {
224}; 188 DSSERR("Failed to initialize dispc platform driver\n");
189 goto err_dispc;
190 }
225 191
226static int __init omap_dss_probe(struct platform_device *pdev) 192 r = rfbi_init_platform_driver();
227{ 193 if (r) {
228 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 194 DSSERR("Failed to initialize rfbi platform driver\n");
229 int r; 195 goto err_rfbi;
196 }
230 197
231 core.pdev = pdev; 198 r = venc_init_platform_driver();
199 if (r) {
200 DSSERR("Failed to initialize venc platform driver\n");
201 goto err_venc;
202 }
203
204 r = dsi_init_platform_driver();
205 if (r) {
206 DSSERR("Failed to initialize DSI platform driver\n");
207 goto err_dsi;
208 }
232 209
233 dss_features_init(omapdss_get_version()); 210 r = hdmi_init_platform_driver();
211 if (r) {
212 DSSERR("Failed to initialize hdmi\n");
213 goto err_hdmi;
214 }
234 215
235 r = dss_initialize_debugfs(); 216 r = dss_initialize_debugfs();
236 if (r) 217 if (r)
237 goto err_debugfs; 218 goto err_debugfs;
238 219
239 if (def_disp_name) 220 for (i = 0; i < pdata->num_devices; ++i) {
240 core.default_display_name = def_disp_name; 221 struct omap_dss_device *dssdev = pdata->devices[i];
241 else if (pdata->default_device) 222
242 core.default_display_name = pdata->default_device->name; 223 r = omap_dss_register_device(dssdev);
224 if (r) {
225 DSSERR("device %d %s register failed %d\n", i,
226 dssdev->name ?: "unnamed", r);
243 227
244 register_pm_notifier(&omap_dss_pm_notif_block); 228 while (--i >= 0)
229 omap_dss_unregister_device(pdata->devices[i]);
230
231 goto err_register;
232 }
233
234 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
235 pdata->default_device = dssdev;
236 }
245 237
246 return 0; 238 return 0;
247 239
240err_register:
241 dss_uninitialize_debugfs();
248err_debugfs: 242err_debugfs:
243 hdmi_uninit_platform_driver();
244err_hdmi:
245 dsi_uninit_platform_driver();
246err_dsi:
247 venc_uninit_platform_driver();
248err_venc:
249 dispc_uninit_platform_driver();
250err_dispc:
251 rfbi_uninit_platform_driver();
252err_rfbi:
253 dss_uninit_platform_driver();
254err_dss:
249 255
250 return r; 256 return r;
251} 257}
252 258
253static int omap_dss_remove(struct platform_device *pdev) 259static int omap_dss_remove(struct platform_device *pdev)
254{ 260{
255 unregister_pm_notifier(&omap_dss_pm_notif_block); 261 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
262 int i;
256 263
257 dss_uninitialize_debugfs(); 264 dss_uninitialize_debugfs();
258 265
266 hdmi_uninit_platform_driver();
267 dsi_uninit_platform_driver();
268 venc_uninit_platform_driver();
269 rfbi_uninit_platform_driver();
270 dispc_uninit_platform_driver();
271 dss_uninit_platform_driver();
272
273 dss_uninit_overlays(pdev);
274 dss_uninit_overlay_managers(pdev);
275
276 for (i = 0; i < pdata->num_devices; ++i)
277 omap_dss_unregister_device(pdata->devices[i]);
278
259 return 0; 279 return 0;
260} 280}
261 281
@@ -265,9 +285,26 @@ static void omap_dss_shutdown(struct platform_device *pdev)
265 dss_disable_all_devices(); 285 dss_disable_all_devices();
266} 286}
267 287
288static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
289{
290 DSSDBG("suspend %d\n", state.event);
291
292 return dss_suspend_all_devices();
293}
294
295static int omap_dss_resume(struct platform_device *pdev)
296{
297 DSSDBG("resume\n");
298
299 return dss_resume_all_devices();
300}
301
268static struct platform_driver omap_dss_driver = { 302static struct platform_driver omap_dss_driver = {
303 .probe = omap_dss_probe,
269 .remove = omap_dss_remove, 304 .remove = omap_dss_remove,
270 .shutdown = omap_dss_shutdown, 305 .shutdown = omap_dss_shutdown,
306 .suspend = omap_dss_suspend,
307 .resume = omap_dss_resume,
271 .driver = { 308 .driver = {
272 .name = "omapdss", 309 .name = "omapdss",
273 .owner = THIS_MODULE, 310 .owner = THIS_MODULE,
@@ -338,15 +375,23 @@ static int dss_driver_probe(struct device *dev)
338 int r; 375 int r;
339 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 376 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
340 struct omap_dss_device *dssdev = to_dss_device(dev); 377 struct omap_dss_device *dssdev = to_dss_device(dev);
378 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
379 bool force;
341 380
342 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 381 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
343 dev_name(dev), dssdev->driver_name, 382 dev_name(dev), dssdev->driver_name,
344 dssdrv->driver.name); 383 dssdrv->driver.name);
345 384
385 dss_init_device(core.pdev, dssdev);
386
387 force = pdata->default_device == dssdev;
388 dss_recheck_connections(dssdev, force);
389
346 r = dssdrv->probe(dssdev); 390 r = dssdrv->probe(dssdev);
347 391
348 if (r) { 392 if (r) {
349 DSSERR("driver probe failed: %d\n", r); 393 DSSERR("driver probe failed: %d\n", r);
394 dss_uninit_device(core.pdev, dssdev);
350 return r; 395 return r;
351 } 396 }
352 397
@@ -367,6 +412,8 @@ static int dss_driver_remove(struct device *dev)
367 412
368 dssdrv->remove(dssdev); 413 dssdrv->remove(dssdev);
369 414
415 dss_uninit_device(core.pdev, dssdev);
416
370 dssdev->driver = NULL; 417 dssdev->driver = NULL;
371 418
372 return 0; 419 return 0;
@@ -383,8 +430,6 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
383 if (dssdriver->get_recommended_bpp == NULL) 430 if (dssdriver->get_recommended_bpp == NULL)
384 dssdriver->get_recommended_bpp = 431 dssdriver->get_recommended_bpp =
385 omapdss_default_get_recommended_bpp; 432 omapdss_default_get_recommended_bpp;
386 if (dssdriver->get_timings == NULL)
387 dssdriver->get_timings = omapdss_default_get_timings;
388 433
389 return driver_register(&dssdriver->driver); 434 return driver_register(&dssdriver->driver);
390} 435}
@@ -397,72 +442,61 @@ void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
397EXPORT_SYMBOL(omap_dss_unregister_driver); 442EXPORT_SYMBOL(omap_dss_unregister_driver);
398 443
399/* DEVICE */ 444/* DEVICE */
445static void reset_device(struct device *dev, int check)
446{
447 u8 *dev_p = (u8 *)dev;
448 u8 *dev_end = dev_p + sizeof(*dev);
449 void *saved_pdata;
450
451 saved_pdata = dev->platform_data;
452 if (check) {
453 /*
454 * Check if there is any other setting than platform_data
455 * in struct device; warn that these will be reset by our
456 * init.
457 */
458 dev->platform_data = NULL;
459 while (dev_p < dev_end) {
460 if (*dev_p) {
461 WARN("%s: struct device fields will be "
462 "discarded\n",
463 __func__);
464 break;
465 }
466 dev_p++;
467 }
468 }
469 memset(dev, 0, sizeof(*dev));
470 dev->platform_data = saved_pdata;
471}
472
400 473
401static void omap_dss_dev_release(struct device *dev) 474static void omap_dss_dev_release(struct device *dev)
402{ 475{
403 struct omap_dss_device *dssdev = to_dss_device(dev); 476 reset_device(dev, 0);
404 kfree(dssdev);
405} 477}
406 478
407static int disp_num_counter; 479static int omap_dss_register_device(struct omap_dss_device *dssdev)
408
409struct omap_dss_device *dss_alloc_and_init_device(struct device *parent)
410{ 480{
411 struct omap_dss_device *dssdev; 481 static int dev_num;
412 482
413 dssdev = kzalloc(sizeof(*dssdev), GFP_KERNEL); 483 WARN_ON(!dssdev->driver_name);
414 if (!dssdev)
415 return NULL;
416 484
485 reset_device(&dssdev->dev, 1);
417 dssdev->dev.bus = &dss_bus_type; 486 dssdev->dev.bus = &dss_bus_type;
418 dssdev->dev.parent = parent; 487 dssdev->dev.parent = &dss_bus;
419 dssdev->dev.release = omap_dss_dev_release; 488 dssdev->dev.release = omap_dss_dev_release;
420 dev_set_name(&dssdev->dev, "display%d", disp_num_counter++); 489 dev_set_name(&dssdev->dev, "display%d", dev_num++);
421 490 return device_register(&dssdev->dev);
422 device_initialize(&dssdev->dev);
423
424 return dssdev;
425}
426
427int dss_add_device(struct omap_dss_device *dssdev)
428{
429 return device_add(&dssdev->dev);
430}
431
432void dss_put_device(struct omap_dss_device *dssdev)
433{
434 put_device(&dssdev->dev);
435} 491}
436 492
437void dss_unregister_device(struct omap_dss_device *dssdev) 493static void omap_dss_unregister_device(struct omap_dss_device *dssdev)
438{ 494{
439 device_unregister(&dssdev->dev); 495 device_unregister(&dssdev->dev);
440} 496}
441 497
442static int dss_unregister_dss_dev(struct device *dev, void *data)
443{
444 struct omap_dss_device *dssdev = to_dss_device(dev);
445 dss_unregister_device(dssdev);
446 return 0;
447}
448
449void dss_unregister_child_devices(struct device *parent)
450{
451 device_for_each_child(parent, NULL, dss_unregister_dss_dev);
452}
453
454void dss_copy_device_pdata(struct omap_dss_device *dst,
455 const struct omap_dss_device *src)
456{
457 u8 *d = (u8 *)dst;
458 u8 *s = (u8 *)src;
459 size_t dsize = sizeof(struct device);
460
461 memcpy(d + dsize, s + dsize, sizeof(struct omap_dss_device) - dsize);
462}
463
464/* BUS */ 498/* BUS */
465static int __init omap_dss_bus_register(void) 499static int omap_dss_bus_register(void)
466{ 500{
467 int r; 501 int r;
468 502
@@ -484,105 +518,6 @@ static int __init omap_dss_bus_register(void)
484} 518}
485 519
486/* INIT */ 520/* INIT */
487static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
488#ifdef CONFIG_OMAP2_DSS_DSI
489 dsi_init_platform_driver,
490#endif
491#ifdef CONFIG_OMAP2_DSS_DPI
492 dpi_init_platform_driver,
493#endif
494#ifdef CONFIG_OMAP2_DSS_SDI
495 sdi_init_platform_driver,
496#endif
497#ifdef CONFIG_OMAP2_DSS_RFBI
498 rfbi_init_platform_driver,
499#endif
500#ifdef CONFIG_OMAP2_DSS_VENC
501 venc_init_platform_driver,
502#endif
503#ifdef CONFIG_OMAP4_DSS_HDMI
504 hdmi_init_platform_driver,
505#endif
506};
507
508static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
509#ifdef CONFIG_OMAP2_DSS_DSI
510 dsi_uninit_platform_driver,
511#endif
512#ifdef CONFIG_OMAP2_DSS_DPI
513 dpi_uninit_platform_driver,
514#endif
515#ifdef CONFIG_OMAP2_DSS_SDI
516 sdi_uninit_platform_driver,
517#endif
518#ifdef CONFIG_OMAP2_DSS_RFBI
519 rfbi_uninit_platform_driver,
520#endif
521#ifdef CONFIG_OMAP2_DSS_VENC
522 venc_uninit_platform_driver,
523#endif
524#ifdef CONFIG_OMAP4_DSS_HDMI
525 hdmi_uninit_platform_driver,
526#endif
527};
528
529static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
530
531static int __init omap_dss_register_drivers(void)
532{
533 int r;
534 int i;
535
536 r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
537 if (r)
538 return r;
539
540 r = dss_init_platform_driver();
541 if (r) {
542 DSSERR("Failed to initialize DSS platform driver\n");
543 goto err_dss;
544 }
545
546 r = dispc_init_platform_driver();
547 if (r) {
548 DSSERR("Failed to initialize dispc platform driver\n");
549 goto err_dispc;
550 }
551
552 /*
553 * It's ok if the output-driver register fails. It happens, for example,
554 * when there is no output-device (e.g. SDI for OMAP4).
555 */
556 for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
557 r = dss_output_drv_reg_funcs[i]();
558 if (r == 0)
559 dss_output_drv_loaded[i] = true;
560 }
561
562 return 0;
563
564err_dispc:
565 dss_uninit_platform_driver();
566err_dss:
567 platform_driver_unregister(&omap_dss_driver);
568
569 return r;
570}
571
572static void __exit omap_dss_unregister_drivers(void)
573{
574 int i;
575
576 for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
577 if (dss_output_drv_loaded[i])
578 dss_output_drv_unreg_funcs[i]();
579 }
580
581 dispc_uninit_platform_driver();
582 dss_uninit_platform_driver();
583
584 platform_driver_unregister(&omap_dss_driver);
585}
586 521
587#ifdef CONFIG_OMAP2_DSS_MODULE 522#ifdef CONFIG_OMAP2_DSS_MODULE
588static void omap_dss_bus_unregister(void) 523static void omap_dss_bus_unregister(void)
@@ -600,7 +535,7 @@ static int __init omap_dss_init(void)
600 if (r) 535 if (r)
601 return r; 536 return r;
602 537
603 r = omap_dss_register_drivers(); 538 r = platform_driver_register(&omap_dss_driver);
604 if (r) { 539 if (r) {
605 omap_dss_bus_unregister(); 540 omap_dss_bus_unregister();
606 return r; 541 return r;
@@ -621,7 +556,7 @@ static void __exit omap_dss_exit(void)
621 core.vdds_sdi_reg = NULL; 556 core.vdds_sdi_reg = NULL;
622 } 557 }
623 558
624 omap_dss_unregister_drivers(); 559 platform_driver_unregister(&omap_dss_driver);
625 560
626 omap_dss_bus_unregister(); 561 omap_dss_bus_unregister();
627} 562}
@@ -636,7 +571,7 @@ static int __init omap_dss_init(void)
636 571
637static int __init omap_dss_init2(void) 572static int __init omap_dss_init2(void)
638{ 573{
639 return omap_dss_register_drivers(); 574 return platform_driver_register(&omap_dss_driver);
640} 575}
641 576
642core_initcall(omap_dss_init); 577core_initcall(omap_dss_init);
diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/omap2/dss/dispc-compat.c
deleted file mode 100644
index 928884c9a0a..00000000000
--- a/drivers/video/omap2/dss/dispc-compat.c
+++ /dev/null
@@ -1,667 +0,0 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define DSS_SUBSYS_NAME "APPLY"
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/spinlock.h>
24#include <linux/jiffies.h>
25#include <linux/delay.h>
26#include <linux/interrupt.h>
27#include <linux/seq_file.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33#include "dispc-compat.h"
34
35#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
36 DISPC_IRQ_OCP_ERR | \
37 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
38 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
39 DISPC_IRQ_SYNC_LOST | \
40 DISPC_IRQ_SYNC_LOST_DIGIT)
41
42#define DISPC_MAX_NR_ISRS 8
43
44struct omap_dispc_isr_data {
45 omap_dispc_isr_t isr;
46 void *arg;
47 u32 mask;
48};
49
50struct dispc_irq_stats {
51 unsigned long last_reset;
52 unsigned irq_count;
53 unsigned irqs[32];
54};
55
56static struct {
57 spinlock_t irq_lock;
58 u32 irq_error_mask;
59 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
60 u32 error_irqs;
61 struct work_struct error_work;
62
63#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
64 spinlock_t irq_stats_lock;
65 struct dispc_irq_stats irq_stats;
66#endif
67} dispc_compat;
68
69
70#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
71static void dispc_dump_irqs(struct seq_file *s)
72{
73 unsigned long flags;
74 struct dispc_irq_stats stats;
75
76 spin_lock_irqsave(&dispc_compat.irq_stats_lock, flags);
77
78 stats = dispc_compat.irq_stats;
79 memset(&dispc_compat.irq_stats, 0, sizeof(dispc_compat.irq_stats));
80 dispc_compat.irq_stats.last_reset = jiffies;
81
82 spin_unlock_irqrestore(&dispc_compat.irq_stats_lock, flags);
83
84 seq_printf(s, "period %u ms\n",
85 jiffies_to_msecs(jiffies - stats.last_reset));
86
87 seq_printf(s, "irqs %d\n", stats.irq_count);
88#define PIS(x) \
89 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
90
91 PIS(FRAMEDONE);
92 PIS(VSYNC);
93 PIS(EVSYNC_EVEN);
94 PIS(EVSYNC_ODD);
95 PIS(ACBIAS_COUNT_STAT);
96 PIS(PROG_LINE_NUM);
97 PIS(GFX_FIFO_UNDERFLOW);
98 PIS(GFX_END_WIN);
99 PIS(PAL_GAMMA_MASK);
100 PIS(OCP_ERR);
101 PIS(VID1_FIFO_UNDERFLOW);
102 PIS(VID1_END_WIN);
103 PIS(VID2_FIFO_UNDERFLOW);
104 PIS(VID2_END_WIN);
105 if (dss_feat_get_num_ovls() > 3) {
106 PIS(VID3_FIFO_UNDERFLOW);
107 PIS(VID3_END_WIN);
108 }
109 PIS(SYNC_LOST);
110 PIS(SYNC_LOST_DIGIT);
111 PIS(WAKEUP);
112 if (dss_has_feature(FEAT_MGR_LCD2)) {
113 PIS(FRAMEDONE2);
114 PIS(VSYNC2);
115 PIS(ACBIAS_COUNT_STAT2);
116 PIS(SYNC_LOST2);
117 }
118 if (dss_has_feature(FEAT_MGR_LCD3)) {
119 PIS(FRAMEDONE3);
120 PIS(VSYNC3);
121 PIS(ACBIAS_COUNT_STAT3);
122 PIS(SYNC_LOST3);
123 }
124#undef PIS
125}
126#endif
127
128/* dispc.irq_lock has to be locked by the caller */
129static void _omap_dispc_set_irqs(void)
130{
131 u32 mask;
132 int i;
133 struct omap_dispc_isr_data *isr_data;
134
135 mask = dispc_compat.irq_error_mask;
136
137 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
138 isr_data = &dispc_compat.registered_isr[i];
139
140 if (isr_data->isr == NULL)
141 continue;
142
143 mask |= isr_data->mask;
144 }
145
146 dispc_write_irqenable(mask);
147}
148
149int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
150{
151 int i;
152 int ret;
153 unsigned long flags;
154 struct omap_dispc_isr_data *isr_data;
155
156 if (isr == NULL)
157 return -EINVAL;
158
159 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
160
161 /* check for duplicate entry */
162 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
163 isr_data = &dispc_compat.registered_isr[i];
164 if (isr_data->isr == isr && isr_data->arg == arg &&
165 isr_data->mask == mask) {
166 ret = -EINVAL;
167 goto err;
168 }
169 }
170
171 isr_data = NULL;
172 ret = -EBUSY;
173
174 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
175 isr_data = &dispc_compat.registered_isr[i];
176
177 if (isr_data->isr != NULL)
178 continue;
179
180 isr_data->isr = isr;
181 isr_data->arg = arg;
182 isr_data->mask = mask;
183 ret = 0;
184
185 break;
186 }
187
188 if (ret)
189 goto err;
190
191 _omap_dispc_set_irqs();
192
193 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
194
195 return 0;
196err:
197 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
198
199 return ret;
200}
201EXPORT_SYMBOL(omap_dispc_register_isr);
202
203int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
204{
205 int i;
206 unsigned long flags;
207 int ret = -EINVAL;
208 struct omap_dispc_isr_data *isr_data;
209
210 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
211
212 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
213 isr_data = &dispc_compat.registered_isr[i];
214 if (isr_data->isr != isr || isr_data->arg != arg ||
215 isr_data->mask != mask)
216 continue;
217
218 /* found the correct isr */
219
220 isr_data->isr = NULL;
221 isr_data->arg = NULL;
222 isr_data->mask = 0;
223
224 ret = 0;
225 break;
226 }
227
228 if (ret == 0)
229 _omap_dispc_set_irqs();
230
231 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
232
233 return ret;
234}
235EXPORT_SYMBOL(omap_dispc_unregister_isr);
236
237static void print_irq_status(u32 status)
238{
239 if ((status & dispc_compat.irq_error_mask) == 0)
240 return;
241
242#define PIS(x) (status & DISPC_IRQ_##x) ? (#x " ") : ""
243
244 pr_debug("DISPC IRQ: 0x%x: %s%s%s%s%s%s%s%s%s\n",
245 status,
246 PIS(OCP_ERR),
247 PIS(GFX_FIFO_UNDERFLOW),
248 PIS(VID1_FIFO_UNDERFLOW),
249 PIS(VID2_FIFO_UNDERFLOW),
250 dss_feat_get_num_ovls() > 3 ? PIS(VID3_FIFO_UNDERFLOW) : "",
251 PIS(SYNC_LOST),
252 PIS(SYNC_LOST_DIGIT),
253 dss_has_feature(FEAT_MGR_LCD2) ? PIS(SYNC_LOST2) : "",
254 dss_has_feature(FEAT_MGR_LCD3) ? PIS(SYNC_LOST3) : "");
255#undef PIS
256}
257
258/* Called from dss.c. Note that we don't touch clocks here,
259 * but we presume they are on because we got an IRQ. However,
260 * an irq handler may turn the clocks off, so we may not have
261 * clock later in the function. */
262static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
263{
264 int i;
265 u32 irqstatus, irqenable;
266 u32 handledirqs = 0;
267 u32 unhandled_errors;
268 struct omap_dispc_isr_data *isr_data;
269 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
270
271 spin_lock(&dispc_compat.irq_lock);
272
273 irqstatus = dispc_read_irqstatus();
274 irqenable = dispc_read_irqenable();
275
276 /* IRQ is not for us */
277 if (!(irqstatus & irqenable)) {
278 spin_unlock(&dispc_compat.irq_lock);
279 return IRQ_NONE;
280 }
281
282#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
283 spin_lock(&dispc_compat.irq_stats_lock);
284 dispc_compat.irq_stats.irq_count++;
285 dss_collect_irq_stats(irqstatus, dispc_compat.irq_stats.irqs);
286 spin_unlock(&dispc_compat.irq_stats_lock);
287#endif
288
289 print_irq_status(irqstatus);
290
291 /* Ack the interrupt. Do it here before clocks are possibly turned
292 * off */
293 dispc_clear_irqstatus(irqstatus);
294 /* flush posted write */
295 dispc_read_irqstatus();
296
297 /* make a copy and unlock, so that isrs can unregister
298 * themselves */
299 memcpy(registered_isr, dispc_compat.registered_isr,
300 sizeof(registered_isr));
301
302 spin_unlock(&dispc_compat.irq_lock);
303
304 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
305 isr_data = &registered_isr[i];
306
307 if (!isr_data->isr)
308 continue;
309
310 if (isr_data->mask & irqstatus) {
311 isr_data->isr(isr_data->arg, irqstatus);
312 handledirqs |= isr_data->mask;
313 }
314 }
315
316 spin_lock(&dispc_compat.irq_lock);
317
318 unhandled_errors = irqstatus & ~handledirqs & dispc_compat.irq_error_mask;
319
320 if (unhandled_errors) {
321 dispc_compat.error_irqs |= unhandled_errors;
322
323 dispc_compat.irq_error_mask &= ~unhandled_errors;
324 _omap_dispc_set_irqs();
325
326 schedule_work(&dispc_compat.error_work);
327 }
328
329 spin_unlock(&dispc_compat.irq_lock);
330
331 return IRQ_HANDLED;
332}
333
334static void dispc_error_worker(struct work_struct *work)
335{
336 int i;
337 u32 errors;
338 unsigned long flags;
339 static const unsigned fifo_underflow_bits[] = {
340 DISPC_IRQ_GFX_FIFO_UNDERFLOW,
341 DISPC_IRQ_VID1_FIFO_UNDERFLOW,
342 DISPC_IRQ_VID2_FIFO_UNDERFLOW,
343 DISPC_IRQ_VID3_FIFO_UNDERFLOW,
344 };
345
346 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
347 errors = dispc_compat.error_irqs;
348 dispc_compat.error_irqs = 0;
349 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
350
351 dispc_runtime_get();
352
353 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
354 struct omap_overlay *ovl;
355 unsigned bit;
356
357 ovl = omap_dss_get_overlay(i);
358 bit = fifo_underflow_bits[i];
359
360 if (bit & errors) {
361 DSSERR("FIFO UNDERFLOW on %s, disabling the overlay\n",
362 ovl->name);
363 dispc_ovl_enable(ovl->id, false);
364 dispc_mgr_go(ovl->manager->id);
365 msleep(50);
366 }
367 }
368
369 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
370 struct omap_overlay_manager *mgr;
371 unsigned bit;
372
373 mgr = omap_dss_get_overlay_manager(i);
374 bit = dispc_mgr_get_sync_lost_irq(i);
375
376 if (bit & errors) {
377 int j;
378
379 DSSERR("SYNC_LOST on channel %s, restarting the output "
380 "with video overlays disabled\n",
381 mgr->name);
382
383 dss_mgr_disable(mgr);
384
385 for (j = 0; j < omap_dss_get_num_overlays(); ++j) {
386 struct omap_overlay *ovl;
387 ovl = omap_dss_get_overlay(j);
388
389 if (ovl->id != OMAP_DSS_GFX &&
390 ovl->manager == mgr)
391 ovl->disable(ovl);
392 }
393
394 dss_mgr_enable(mgr);
395 }
396 }
397
398 if (errors & DISPC_IRQ_OCP_ERR) {
399 DSSERR("OCP_ERR\n");
400 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
401 struct omap_overlay_manager *mgr;
402
403 mgr = omap_dss_get_overlay_manager(i);
404 dss_mgr_disable(mgr);
405 }
406 }
407
408 spin_lock_irqsave(&dispc_compat.irq_lock, flags);
409 dispc_compat.irq_error_mask |= errors;
410 _omap_dispc_set_irqs();
411 spin_unlock_irqrestore(&dispc_compat.irq_lock, flags);
412
413 dispc_runtime_put();
414}
415
416int dss_dispc_initialize_irq(void)
417{
418 int r;
419
420#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
421 spin_lock_init(&dispc_compat.irq_stats_lock);
422 dispc_compat.irq_stats.last_reset = jiffies;
423 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
424#endif
425
426 spin_lock_init(&dispc_compat.irq_lock);
427
428 memset(dispc_compat.registered_isr, 0,
429 sizeof(dispc_compat.registered_isr));
430
431 dispc_compat.irq_error_mask = DISPC_IRQ_MASK_ERROR;
432 if (dss_has_feature(FEAT_MGR_LCD2))
433 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
434 if (dss_has_feature(FEAT_MGR_LCD3))
435 dispc_compat.irq_error_mask |= DISPC_IRQ_SYNC_LOST3;
436 if (dss_feat_get_num_ovls() > 3)
437 dispc_compat.irq_error_mask |= DISPC_IRQ_VID3_FIFO_UNDERFLOW;
438
439 /*
440 * there's SYNC_LOST_DIGIT waiting after enabling the DSS,
441 * so clear it
442 */
443 dispc_clear_irqstatus(dispc_read_irqstatus());
444
445 INIT_WORK(&dispc_compat.error_work, dispc_error_worker);
446
447 _omap_dispc_set_irqs();
448
449 r = dispc_request_irq(omap_dispc_irq_handler, &dispc_compat);
450 if (r) {
451 DSSERR("dispc_request_irq failed\n");
452 return r;
453 }
454
455 return 0;
456}
457
458void dss_dispc_uninitialize_irq(void)
459{
460 dispc_free_irq(&dispc_compat);
461}
462
463static void dispc_mgr_disable_isr(void *data, u32 mask)
464{
465 struct completion *compl = data;
466 complete(compl);
467}
468
469static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
470{
471 dispc_mgr_enable(channel, true);
472}
473
474static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
475{
476 DECLARE_COMPLETION_ONSTACK(framedone_compl);
477 int r;
478 u32 irq;
479
480 if (dispc_mgr_is_enabled(channel) == false)
481 return;
482
483 /*
484 * When we disable LCD output, we need to wait for FRAMEDONE to know
485 * that DISPC has finished with the LCD output.
486 */
487
488 irq = dispc_mgr_get_framedone_irq(channel);
489
490 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
491 irq);
492 if (r)
493 DSSERR("failed to register FRAMEDONE isr\n");
494
495 dispc_mgr_enable(channel, false);
496
497 /* if we couldn't register for framedone, just sleep and exit */
498 if (r) {
499 msleep(100);
500 return;
501 }
502
503 if (!wait_for_completion_timeout(&framedone_compl,
504 msecs_to_jiffies(100)))
505 DSSERR("timeout waiting for FRAME DONE\n");
506
507 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
508 irq);
509 if (r)
510 DSSERR("failed to unregister FRAMEDONE isr\n");
511}
512
513static void dispc_digit_out_enable_isr(void *data, u32 mask)
514{
515 struct completion *compl = data;
516
517 /* ignore any sync lost interrupts */
518 if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
519 complete(compl);
520}
521
522static void dispc_mgr_enable_digit_out(void)
523{
524 DECLARE_COMPLETION_ONSTACK(vsync_compl);
525 int r;
526 u32 irq_mask;
527
528 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
529 return;
530
531 /*
532 * Digit output produces some sync lost interrupts during the first
533 * frame when enabling. Those need to be ignored, so we register for the
534 * sync lost irq to prevent the error handler from triggering.
535 */
536
537 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
538 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
539
540 r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
541 irq_mask);
542 if (r) {
543 DSSERR("failed to register %x isr\n", irq_mask);
544 return;
545 }
546
547 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, true);
548
549 /* wait for the first evsync */
550 if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
551 DSSERR("timeout waiting for digit out to start\n");
552
553 r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
554 irq_mask);
555 if (r)
556 DSSERR("failed to unregister %x isr\n", irq_mask);
557}
558
559static void dispc_mgr_disable_digit_out(void)
560{
561 DECLARE_COMPLETION_ONSTACK(framedone_compl);
562 int r, i;
563 u32 irq_mask;
564 int num_irqs;
565
566 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
567 return;
568
569 /*
570 * When we disable the digit output, we need to wait for FRAMEDONE to
571 * know that DISPC has finished with the output.
572 */
573
574 irq_mask = dispc_mgr_get_framedone_irq(OMAP_DSS_CHANNEL_DIGIT);
575 num_irqs = 1;
576
577 if (!irq_mask) {
578 /*
579 * omap 2/3 don't have framedone irq for TV, so we need to use
580 * vsyncs for this.
581 */
582
583 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
584 /*
585 * We need to wait for both even and odd vsyncs. Note that this
586 * is not totally reliable, as we could get a vsync interrupt
587 * before we disable the output, which leads to timeout in the
588 * wait_for_completion.
589 */
590 num_irqs = 2;
591 }
592
593 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
594 irq_mask);
595 if (r)
596 DSSERR("failed to register %x isr\n", irq_mask);
597
598 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, false);
599
600 /* if we couldn't register the irq, just sleep and exit */
601 if (r) {
602 msleep(100);
603 return;
604 }
605
606 for (i = 0; i < num_irqs; ++i) {
607 if (!wait_for_completion_timeout(&framedone_compl,
608 msecs_to_jiffies(100)))
609 DSSERR("timeout waiting for digit out to stop\n");
610 }
611
612 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
613 irq_mask);
614 if (r)
615 DSSERR("failed to unregister %x isr\n", irq_mask);
616}
617
618void dispc_mgr_enable_sync(enum omap_channel channel)
619{
620 if (dss_mgr_is_lcd(channel))
621 dispc_mgr_enable_lcd_out(channel);
622 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
623 dispc_mgr_enable_digit_out();
624 else
625 WARN_ON(1);
626}
627
628void dispc_mgr_disable_sync(enum omap_channel channel)
629{
630 if (dss_mgr_is_lcd(channel))
631 dispc_mgr_disable_lcd_out(channel);
632 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
633 dispc_mgr_disable_digit_out();
634 else
635 WARN_ON(1);
636}
637
638int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
639 unsigned long timeout)
640{
641 void dispc_irq_wait_handler(void *data, u32 mask)
642 {
643 complete((struct completion *)data);
644 }
645
646 int r;
647 DECLARE_COMPLETION_ONSTACK(completion);
648
649 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
650 irqmask);
651
652 if (r)
653 return r;
654
655 timeout = wait_for_completion_interruptible_timeout(&completion,
656 timeout);
657
658 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
659
660 if (timeout == 0)
661 return -ETIMEDOUT;
662
663 if (timeout == -ERESTARTSYS)
664 return -ERESTARTSYS;
665
666 return 0;
667}
diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/omap2/dss/dispc-compat.h
deleted file mode 100644
index 14a69b3d4fb..00000000000
--- a/drivers/video/omap2/dss/dispc-compat.h
+++ /dev/null
@@ -1,30 +0,0 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef __OMAP2_DSS_DISPC_COMPAT_H
19#define __OMAP2_DSS_DISPC_COMPAT_H
20
21void dispc_mgr_enable_sync(enum omap_channel channel);
22void dispc_mgr_disable_sync(enum omap_channel channel);
23
24int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
25 unsigned long timeout);
26
27int dss_dispc_initialize_irq(void);
28void dss_dispc_uninitialize_irq(void);
29
30#endif
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 05ff2b91d9e..0f3961a1ce2 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -25,7 +25,6 @@
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
27#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
28#include <linux/export.h>
29#include <linux/clk.h> 28#include <linux/clk.h>
30#include <linux/io.h> 29#include <linux/io.h>
31#include <linux/jiffies.h> 30#include <linux/jiffies.h>
@@ -33,9 +32,12 @@
33#include <linux/delay.h> 32#include <linux/delay.h>
34#include <linux/workqueue.h> 33#include <linux/workqueue.h>
35#include <linux/hardirq.h> 34#include <linux/hardirq.h>
35#include <linux/interrupt.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/pm_runtime.h> 37#include <linux/pm_runtime.h>
38#include <linux/sizes.h> 38
39#include <plat/sram.h>
40#include <plat/clock.h>
39 41
40#include <video/omapdss.h> 42#include <video/omapdss.h>
41 43
@@ -46,6 +48,37 @@
46/* DISPC */ 48/* DISPC */
47#define DISPC_SZ_REGS SZ_4K 49#define DISPC_SZ_REGS SZ_4K
48 50
51#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \
52 DISPC_IRQ_OCP_ERR | \
53 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \
54 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \
55 DISPC_IRQ_SYNC_LOST | \
56 DISPC_IRQ_SYNC_LOST_DIGIT)
57
58#define DISPC_MAX_NR_ISRS 8
59
60struct omap_dispc_isr_data {
61 omap_dispc_isr_t isr;
62 void *arg;
63 u32 mask;
64};
65
66struct dispc_h_coef {
67 s8 hc4;
68 s8 hc3;
69 u8 hc2;
70 s8 hc1;
71 s8 hc0;
72};
73
74struct dispc_v_coef {
75 s8 vc22;
76 s8 vc2;
77 u8 vc1;
78 s8 vc0;
79 s8 vc00;
80};
81
49enum omap_burst_size { 82enum omap_burst_size {
50 BURST_SIZE_X2 = 0, 83 BURST_SIZE_X2 = 0,
51 BURST_SIZE_X4 = 1, 84 BURST_SIZE_X4 = 1,
@@ -58,37 +91,12 @@ enum omap_burst_size {
58#define REG_FLD_MOD(idx, val, start, end) \ 91#define REG_FLD_MOD(idx, val, start, end) \
59 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) 92 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end))
60 93
61struct dispc_features { 94struct dispc_irq_stats {
62 u8 sw_start; 95 unsigned long last_reset;
63 u8 fp_start; 96 unsigned irq_count;
64 u8 bp_start; 97 unsigned irqs[32];
65 u16 sw_max;
66 u16 vp_max;
67 u16 hp_max;
68 u8 mgr_width_start;
69 u8 mgr_height_start;
70 u16 mgr_width_max;
71 u16 mgr_height_max;
72 int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
73 const struct omap_video_timings *mgr_timings,
74 u16 width, u16 height, u16 out_width, u16 out_height,
75 enum omap_color_mode color_mode, bool *five_taps,
76 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
77 u16 pos_x, unsigned long *core_clk, bool mem_to_mem);
78 unsigned long (*calc_core_clk) (unsigned long pclk,
79 u16 width, u16 height, u16 out_width, u16 out_height,
80 bool mem_to_mem);
81 u8 num_fifos;
82
83 /* swap GFX & WB fifos */
84 bool gfx_fifo_workaround:1;
85
86 /* no DISPC_IRQ_FRAMEDONETV on this SoC */
87 bool no_framedone_tv:1;
88}; 98};
89 99
90#define DISPC_MAX_NR_FIFOS 5
91
92static struct { 100static struct {
93 struct platform_device *pdev; 101 struct platform_device *pdev;
94 void __iomem *base; 102 void __iomem *base;
@@ -96,15 +104,23 @@ static struct {
96 int ctx_loss_cnt; 104 int ctx_loss_cnt;
97 105
98 int irq; 106 int irq;
107 struct clk *dss_clk;
99 108
100 u32 fifo_size[DISPC_MAX_NR_FIFOS]; 109 u32 fifo_size[3];
101 /* maps which plane is using a fifo. fifo-id -> plane-id */ 110
102 int fifo_assignment[DISPC_MAX_NR_FIFOS]; 111 spinlock_t irq_lock;
112 u32 irq_error_mask;
113 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
114 u32 error_irqs;
115 struct work_struct error_work;
103 116
104 bool ctx_valid; 117 bool ctx_valid;
105 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 118 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
106 119
107 const struct dispc_features *feat; 120#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
121 spinlock_t irq_stats_lock;
122 struct dispc_irq_stats irq_stats;
123#endif
108} dispc; 124} dispc;
109 125
110enum omap_color_component { 126enum omap_color_component {
@@ -119,104 +135,7 @@ enum omap_color_component {
119 DISPC_COLOR_COMPONENT_UV = 1 << 1, 135 DISPC_COLOR_COMPONENT_UV = 1 << 1,
120}; 136};
121 137
122enum mgr_reg_fields { 138static void _omap_dispc_set_irqs(void);
123 DISPC_MGR_FLD_ENABLE,
124 DISPC_MGR_FLD_STNTFT,
125 DISPC_MGR_FLD_GO,
126 DISPC_MGR_FLD_TFTDATALINES,
127 DISPC_MGR_FLD_STALLMODE,
128 DISPC_MGR_FLD_TCKENABLE,
129 DISPC_MGR_FLD_TCKSELECTION,
130 DISPC_MGR_FLD_CPR,
131 DISPC_MGR_FLD_FIFOHANDCHECK,
132 /* used to maintain a count of the above fields */
133 DISPC_MGR_FLD_NUM,
134};
135
136static const struct {
137 const char *name;
138 u32 vsync_irq;
139 u32 framedone_irq;
140 u32 sync_lost_irq;
141 struct reg_field reg_desc[DISPC_MGR_FLD_NUM];
142} mgr_desc[] = {
143 [OMAP_DSS_CHANNEL_LCD] = {
144 .name = "LCD",
145 .vsync_irq = DISPC_IRQ_VSYNC,
146 .framedone_irq = DISPC_IRQ_FRAMEDONE,
147 .sync_lost_irq = DISPC_IRQ_SYNC_LOST,
148 .reg_desc = {
149 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 0, 0 },
150 [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL, 3, 3 },
151 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL, 5, 5 },
152 [DISPC_MGR_FLD_TFTDATALINES] = { DISPC_CONTROL, 9, 8 },
153 [DISPC_MGR_FLD_STALLMODE] = { DISPC_CONTROL, 11, 11 },
154 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG, 10, 10 },
155 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG, 11, 11 },
156 [DISPC_MGR_FLD_CPR] = { DISPC_CONFIG, 15, 15 },
157 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG, 16, 16 },
158 },
159 },
160 [OMAP_DSS_CHANNEL_DIGIT] = {
161 .name = "DIGIT",
162 .vsync_irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN,
163 .framedone_irq = DISPC_IRQ_FRAMEDONETV,
164 .sync_lost_irq = DISPC_IRQ_SYNC_LOST_DIGIT,
165 .reg_desc = {
166 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL, 1, 1 },
167 [DISPC_MGR_FLD_STNTFT] = { },
168 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL, 6, 6 },
169 [DISPC_MGR_FLD_TFTDATALINES] = { },
170 [DISPC_MGR_FLD_STALLMODE] = { },
171 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG, 12, 12 },
172 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG, 13, 13 },
173 [DISPC_MGR_FLD_CPR] = { },
174 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG, 16, 16 },
175 },
176 },
177 [OMAP_DSS_CHANNEL_LCD2] = {
178 .name = "LCD2",
179 .vsync_irq = DISPC_IRQ_VSYNC2,
180 .framedone_irq = DISPC_IRQ_FRAMEDONE2,
181 .sync_lost_irq = DISPC_IRQ_SYNC_LOST2,
182 .reg_desc = {
183 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL2, 0, 0 },
184 [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL2, 3, 3 },
185 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL2, 5, 5 },
186 [DISPC_MGR_FLD_TFTDATALINES] = { DISPC_CONTROL2, 9, 8 },
187 [DISPC_MGR_FLD_STALLMODE] = { DISPC_CONTROL2, 11, 11 },
188 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG2, 10, 10 },
189 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG2, 11, 11 },
190 [DISPC_MGR_FLD_CPR] = { DISPC_CONFIG2, 15, 15 },
191 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG2, 16, 16 },
192 },
193 },
194 [OMAP_DSS_CHANNEL_LCD3] = {
195 .name = "LCD3",
196 .vsync_irq = DISPC_IRQ_VSYNC3,
197 .framedone_irq = DISPC_IRQ_FRAMEDONE3,
198 .sync_lost_irq = DISPC_IRQ_SYNC_LOST3,
199 .reg_desc = {
200 [DISPC_MGR_FLD_ENABLE] = { DISPC_CONTROL3, 0, 0 },
201 [DISPC_MGR_FLD_STNTFT] = { DISPC_CONTROL3, 3, 3 },
202 [DISPC_MGR_FLD_GO] = { DISPC_CONTROL3, 5, 5 },
203 [DISPC_MGR_FLD_TFTDATALINES] = { DISPC_CONTROL3, 9, 8 },
204 [DISPC_MGR_FLD_STALLMODE] = { DISPC_CONTROL3, 11, 11 },
205 [DISPC_MGR_FLD_TCKENABLE] = { DISPC_CONFIG3, 10, 10 },
206 [DISPC_MGR_FLD_TCKSELECTION] = { DISPC_CONFIG3, 11, 11 },
207 [DISPC_MGR_FLD_CPR] = { DISPC_CONFIG3, 15, 15 },
208 [DISPC_MGR_FLD_FIFOHANDCHECK] = { DISPC_CONFIG3, 16, 16 },
209 },
210 },
211};
212
213struct color_conv_coef {
214 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
215 int full_range;
216};
217
218static unsigned long dispc_plane_pclk_rate(enum omap_plane plane);
219static unsigned long dispc_plane_lclk_rate(enum omap_plane plane);
220 139
221static inline void dispc_write_reg(const u16 idx, u32 val) 140static inline void dispc_write_reg(const u16 idx, u32 val)
222{ 141{
@@ -228,16 +147,21 @@ static inline u32 dispc_read_reg(const u16 idx)
228 return __raw_readl(dispc.base + idx); 147 return __raw_readl(dispc.base + idx);
229} 148}
230 149
231static u32 mgr_fld_read(enum omap_channel channel, enum mgr_reg_fields regfld) 150static int dispc_get_ctx_loss_count(void)
232{ 151{
233 const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld]; 152 struct device *dev = &dispc.pdev->dev;
234 return REG_GET(rfld.reg, rfld.high, rfld.low); 153 struct omap_display_platform_data *pdata = dev->platform_data;
235} 154 struct omap_dss_board_info *board_data = pdata->board_data;
155 int cnt;
156
157 if (!board_data->get_context_loss_count)
158 return -ENOENT;
159
160 cnt = board_data->get_context_loss_count(dev);
236 161
237static void mgr_fld_write(enum omap_channel channel, 162 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
238 enum mgr_reg_fields regfld, int val) { 163
239 const struct reg_field rfld = mgr_desc[channel].reg_desc[regfld]; 164 return cnt;
240 REG_FLD_MOD(rfld.reg, val, rfld.high, rfld.low);
241} 165}
242 166
243#define SR(reg) \ 167#define SR(reg) \
@@ -247,107 +171,177 @@ static void mgr_fld_write(enum omap_channel channel,
247 171
248static void dispc_save_context(void) 172static void dispc_save_context(void)
249{ 173{
250 int i, j; 174 int i;
251 175
252 DSSDBG("dispc_save_context\n"); 176 DSSDBG("dispc_save_context\n");
253 177
254 SR(IRQENABLE); 178 SR(IRQENABLE);
255 SR(CONTROL); 179 SR(CONTROL);
256 SR(CONFIG); 180 SR(CONFIG);
181 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
182 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
183 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
184 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
257 SR(LINE_NUMBER); 185 SR(LINE_NUMBER);
258 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || 186 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
259 dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) 187 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
188 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
189 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
190 if (dss_has_feature(FEAT_GLOBAL_ALPHA))
260 SR(GLOBAL_ALPHA); 191 SR(GLOBAL_ALPHA);
192 SR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
193 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
261 if (dss_has_feature(FEAT_MGR_LCD2)) { 194 if (dss_has_feature(FEAT_MGR_LCD2)) {
262 SR(CONTROL2); 195 SR(CONTROL2);
196 SR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
197 SR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
198 SR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
199 SR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
200 SR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
201 SR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
202 SR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
263 SR(CONFIG2); 203 SR(CONFIG2);
264 } 204 }
265 if (dss_has_feature(FEAT_MGR_LCD3)) {
266 SR(CONTROL3);
267 SR(CONFIG3);
268 }
269 205
270 for (i = 0; i < dss_feat_get_num_mgrs(); i++) { 206 SR(OVL_BA0(OMAP_DSS_GFX));
271 SR(DEFAULT_COLOR(i)); 207 SR(OVL_BA1(OMAP_DSS_GFX));
272 SR(TRANS_COLOR(i)); 208 SR(OVL_POSITION(OMAP_DSS_GFX));
273 SR(SIZE_MGR(i)); 209 SR(OVL_SIZE(OMAP_DSS_GFX));
274 if (i == OMAP_DSS_CHANNEL_DIGIT) 210 SR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
275 continue; 211 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
276 SR(TIMING_H(i)); 212 SR(OVL_ROW_INC(OMAP_DSS_GFX));
277 SR(TIMING_V(i)); 213 SR(OVL_PIXEL_INC(OMAP_DSS_GFX));
278 SR(POL_FREQ(i)); 214 SR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
279 SR(DIVISORo(i)); 215 SR(OVL_TABLE_BA(OMAP_DSS_GFX));
280 216
281 SR(DATA_CYCLE1(i)); 217 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
282 SR(DATA_CYCLE2(i)); 218 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
283 SR(DATA_CYCLE3(i)); 219 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
284 220
221 if (dss_has_feature(FEAT_CPR)) {
222 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
223 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
224 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
225 }
226 if (dss_has_feature(FEAT_MGR_LCD2)) {
285 if (dss_has_feature(FEAT_CPR)) { 227 if (dss_has_feature(FEAT_CPR)) {
286 SR(CPR_COEF_R(i)); 228 SR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
287 SR(CPR_COEF_G(i)); 229 SR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
288 SR(CPR_COEF_B(i)); 230 SR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
289 } 231 }
232
233 SR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
234 SR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
235 SR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
290 } 236 }
291 237
292 for (i = 0; i < dss_feat_get_num_ovls(); i++) { 238 if (dss_has_feature(FEAT_PRELOAD))
293 SR(OVL_BA0(i)); 239 SR(OVL_PRELOAD(OMAP_DSS_GFX));
294 SR(OVL_BA1(i));
295 SR(OVL_POSITION(i));
296 SR(OVL_SIZE(i));
297 SR(OVL_ATTRIBUTES(i));
298 SR(OVL_FIFO_THRESHOLD(i));
299 SR(OVL_ROW_INC(i));
300 SR(OVL_PIXEL_INC(i));
301 if (dss_has_feature(FEAT_PRELOAD))
302 SR(OVL_PRELOAD(i));
303 if (i == OMAP_DSS_GFX) {
304 SR(OVL_WINDOW_SKIP(i));
305 SR(OVL_TABLE_BA(i));
306 continue;
307 }
308 SR(OVL_FIR(i));
309 SR(OVL_PICTURE_SIZE(i));
310 SR(OVL_ACCU0(i));
311 SR(OVL_ACCU1(i));
312 240
313 for (j = 0; j < 8; j++) 241 /* VID1 */
314 SR(OVL_FIR_COEF_H(i, j)); 242 SR(OVL_BA0(OMAP_DSS_VIDEO1));
243 SR(OVL_BA1(OMAP_DSS_VIDEO1));
244 SR(OVL_POSITION(OMAP_DSS_VIDEO1));
245 SR(OVL_SIZE(OMAP_DSS_VIDEO1));
246 SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
247 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
248 SR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
249 SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
250 SR(OVL_FIR(OMAP_DSS_VIDEO1));
251 SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
252 SR(OVL_ACCU0(OMAP_DSS_VIDEO1));
253 SR(OVL_ACCU1(OMAP_DSS_VIDEO1));
315 254
316 for (j = 0; j < 8; j++) 255 for (i = 0; i < 8; i++)
317 SR(OVL_FIR_COEF_HV(i, j)); 256 SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
318 257
319 for (j = 0; j < 5; j++) 258 for (i = 0; i < 8; i++)
320 SR(OVL_CONV_COEF(i, j)); 259 SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
321 260
322 if (dss_has_feature(FEAT_FIR_COEF_V)) { 261 for (i = 0; i < 5; i++)
323 for (j = 0; j < 8; j++) 262 SR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
324 SR(OVL_FIR_COEF_V(i, j)); 263
325 } 264 if (dss_has_feature(FEAT_FIR_COEF_V)) {
265 for (i = 0; i < 8; i++)
266 SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
267 }
326 268
327 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { 269 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
328 SR(OVL_BA0_UV(i)); 270 SR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
329 SR(OVL_BA1_UV(i)); 271 SR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
330 SR(OVL_FIR2(i)); 272 SR(OVL_FIR2(OMAP_DSS_VIDEO1));
331 SR(OVL_ACCU2_0(i)); 273 SR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
332 SR(OVL_ACCU2_1(i)); 274 SR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
333 275
334 for (j = 0; j < 8; j++) 276 for (i = 0; i < 8; i++)
335 SR(OVL_FIR_COEF_H2(i, j)); 277 SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
336 278
337 for (j = 0; j < 8; j++) 279 for (i = 0; i < 8; i++)
338 SR(OVL_FIR_COEF_HV2(i, j)); 280 SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
339 281
340 for (j = 0; j < 8; j++) 282 for (i = 0; i < 8; i++)
341 SR(OVL_FIR_COEF_V2(i, j)); 283 SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
342 } 284 }
343 if (dss_has_feature(FEAT_ATTR2)) 285 if (dss_has_feature(FEAT_ATTR2))
344 SR(OVL_ATTRIBUTES2(i)); 286 SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
287
288 if (dss_has_feature(FEAT_PRELOAD))
289 SR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
290
291 /* VID2 */
292 SR(OVL_BA0(OMAP_DSS_VIDEO2));
293 SR(OVL_BA1(OMAP_DSS_VIDEO2));
294 SR(OVL_POSITION(OMAP_DSS_VIDEO2));
295 SR(OVL_SIZE(OMAP_DSS_VIDEO2));
296 SR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
297 SR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
298 SR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
299 SR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
300 SR(OVL_FIR(OMAP_DSS_VIDEO2));
301 SR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
302 SR(OVL_ACCU0(OMAP_DSS_VIDEO2));
303 SR(OVL_ACCU1(OMAP_DSS_VIDEO2));
304
305 for (i = 0; i < 8; i++)
306 SR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
307
308 for (i = 0; i < 8; i++)
309 SR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
310
311 for (i = 0; i < 5; i++)
312 SR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
313
314 if (dss_has_feature(FEAT_FIR_COEF_V)) {
315 for (i = 0; i < 8; i++)
316 SR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
317 }
318
319 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
320 SR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
321 SR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
322 SR(OVL_FIR2(OMAP_DSS_VIDEO2));
323 SR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
324 SR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
325
326 for (i = 0; i < 8; i++)
327 SR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
328
329 for (i = 0; i < 8; i++)
330 SR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
331
332 for (i = 0; i < 8; i++)
333 SR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
345 } 334 }
335 if (dss_has_feature(FEAT_ATTR2))
336 SR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
337
338 if (dss_has_feature(FEAT_PRELOAD))
339 SR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
346 340
347 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 341 if (dss_has_feature(FEAT_CORE_CLK_DIV))
348 SR(DIVISOR); 342 SR(DIVISOR);
349 343
350 dispc.ctx_loss_cnt = dss_get_ctx_loss_count(); 344 dispc.ctx_loss_cnt = dispc_get_ctx_loss_count();
351 dispc.ctx_valid = true; 345 dispc.ctx_valid = true;
352 346
353 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); 347 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
@@ -355,14 +349,14 @@ static void dispc_save_context(void)
355 349
356static void dispc_restore_context(void) 350static void dispc_restore_context(void)
357{ 351{
358 int i, j, ctx; 352 int i, ctx;
359 353
360 DSSDBG("dispc_restore_context\n"); 354 DSSDBG("dispc_restore_context\n");
361 355
362 if (!dispc.ctx_valid) 356 if (!dispc.ctx_valid)
363 return; 357 return;
364 358
365 ctx = dss_get_ctx_loss_count(); 359 ctx = dispc_get_ctx_loss_count();
366 360
367 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) 361 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
368 return; 362 return;
@@ -373,91 +367,165 @@ static void dispc_restore_context(void)
373 /*RR(IRQENABLE);*/ 367 /*RR(IRQENABLE);*/
374 /*RR(CONTROL);*/ 368 /*RR(CONTROL);*/
375 RR(CONFIG); 369 RR(CONFIG);
370 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
371 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
372 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
373 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
376 RR(LINE_NUMBER); 374 RR(LINE_NUMBER);
377 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || 375 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD));
378 dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) 376 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD));
377 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD));
378 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD));
379 if (dss_has_feature(FEAT_GLOBAL_ALPHA))
379 RR(GLOBAL_ALPHA); 380 RR(GLOBAL_ALPHA);
380 if (dss_has_feature(FEAT_MGR_LCD2)) 381 RR(SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
382 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
383 if (dss_has_feature(FEAT_MGR_LCD2)) {
384 RR(DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
385 RR(TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
386 RR(SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
387 RR(TIMING_H(OMAP_DSS_CHANNEL_LCD2));
388 RR(TIMING_V(OMAP_DSS_CHANNEL_LCD2));
389 RR(POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
390 RR(DIVISORo(OMAP_DSS_CHANNEL_LCD2));
381 RR(CONFIG2); 391 RR(CONFIG2);
382 if (dss_has_feature(FEAT_MGR_LCD3)) 392 }
383 RR(CONFIG3); 393
384 394 RR(OVL_BA0(OMAP_DSS_GFX));
385 for (i = 0; i < dss_feat_get_num_mgrs(); i++) { 395 RR(OVL_BA1(OMAP_DSS_GFX));
386 RR(DEFAULT_COLOR(i)); 396 RR(OVL_POSITION(OMAP_DSS_GFX));
387 RR(TRANS_COLOR(i)); 397 RR(OVL_SIZE(OMAP_DSS_GFX));
388 RR(SIZE_MGR(i)); 398 RR(OVL_ATTRIBUTES(OMAP_DSS_GFX));
389 if (i == OMAP_DSS_CHANNEL_DIGIT) 399 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
390 continue; 400 RR(OVL_ROW_INC(OMAP_DSS_GFX));
391 RR(TIMING_H(i)); 401 RR(OVL_PIXEL_INC(OMAP_DSS_GFX));
392 RR(TIMING_V(i)); 402 RR(OVL_WINDOW_SKIP(OMAP_DSS_GFX));
393 RR(POL_FREQ(i)); 403 RR(OVL_TABLE_BA(OMAP_DSS_GFX));
394 RR(DIVISORo(i));
395 404
396 RR(DATA_CYCLE1(i)); 405
397 RR(DATA_CYCLE2(i)); 406 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
398 RR(DATA_CYCLE3(i)); 407 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
408 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
409
410 if (dss_has_feature(FEAT_CPR)) {
411 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
412 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
413 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
414 }
415 if (dss_has_feature(FEAT_MGR_LCD2)) {
416 RR(DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
417 RR(DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
418 RR(DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
399 419
400 if (dss_has_feature(FEAT_CPR)) { 420 if (dss_has_feature(FEAT_CPR)) {
401 RR(CPR_COEF_R(i)); 421 RR(CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
402 RR(CPR_COEF_G(i)); 422 RR(CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
403 RR(CPR_COEF_B(i)); 423 RR(CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
404 } 424 }
405 } 425 }
406 426
407 for (i = 0; i < dss_feat_get_num_ovls(); i++) { 427 if (dss_has_feature(FEAT_PRELOAD))
408 RR(OVL_BA0(i)); 428 RR(OVL_PRELOAD(OMAP_DSS_GFX));
409 RR(OVL_BA1(i));
410 RR(OVL_POSITION(i));
411 RR(OVL_SIZE(i));
412 RR(OVL_ATTRIBUTES(i));
413 RR(OVL_FIFO_THRESHOLD(i));
414 RR(OVL_ROW_INC(i));
415 RR(OVL_PIXEL_INC(i));
416 if (dss_has_feature(FEAT_PRELOAD))
417 RR(OVL_PRELOAD(i));
418 if (i == OMAP_DSS_GFX) {
419 RR(OVL_WINDOW_SKIP(i));
420 RR(OVL_TABLE_BA(i));
421 continue;
422 }
423 RR(OVL_FIR(i));
424 RR(OVL_PICTURE_SIZE(i));
425 RR(OVL_ACCU0(i));
426 RR(OVL_ACCU1(i));
427 429
428 for (j = 0; j < 8; j++) 430 /* VID1 */
429 RR(OVL_FIR_COEF_H(i, j)); 431 RR(OVL_BA0(OMAP_DSS_VIDEO1));
432 RR(OVL_BA1(OMAP_DSS_VIDEO1));
433 RR(OVL_POSITION(OMAP_DSS_VIDEO1));
434 RR(OVL_SIZE(OMAP_DSS_VIDEO1));
435 RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
436 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
437 RR(OVL_ROW_INC(OMAP_DSS_VIDEO1));
438 RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
439 RR(OVL_FIR(OMAP_DSS_VIDEO1));
440 RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
441 RR(OVL_ACCU0(OMAP_DSS_VIDEO1));
442 RR(OVL_ACCU1(OMAP_DSS_VIDEO1));
430 443
431 for (j = 0; j < 8; j++) 444 for (i = 0; i < 8; i++)
432 RR(OVL_FIR_COEF_HV(i, j)); 445 RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, i));
433 446
434 for (j = 0; j < 5; j++) 447 for (i = 0; i < 8; i++)
435 RR(OVL_CONV_COEF(i, j)); 448 RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, i));
436 449
437 if (dss_has_feature(FEAT_FIR_COEF_V)) { 450 for (i = 0; i < 5; i++)
438 for (j = 0; j < 8; j++) 451 RR(OVL_CONV_COEF(OMAP_DSS_VIDEO1, i));
439 RR(OVL_FIR_COEF_V(i, j));
440 }
441 452
442 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { 453 if (dss_has_feature(FEAT_FIR_COEF_V)) {
443 RR(OVL_BA0_UV(i)); 454 for (i = 0; i < 8; i++)
444 RR(OVL_BA1_UV(i)); 455 RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, i));
445 RR(OVL_FIR2(i)); 456 }
446 RR(OVL_ACCU2_0(i));
447 RR(OVL_ACCU2_1(i));
448 457
449 for (j = 0; j < 8; j++) 458 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
450 RR(OVL_FIR_COEF_H2(i, j)); 459 RR(OVL_BA0_UV(OMAP_DSS_VIDEO1));
460 RR(OVL_BA1_UV(OMAP_DSS_VIDEO1));
461 RR(OVL_FIR2(OMAP_DSS_VIDEO1));
462 RR(OVL_ACCU2_0(OMAP_DSS_VIDEO1));
463 RR(OVL_ACCU2_1(OMAP_DSS_VIDEO1));
451 464
452 for (j = 0; j < 8; j++) 465 for (i = 0; i < 8; i++)
453 RR(OVL_FIR_COEF_HV2(i, j)); 466 RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, i));
454 467
455 for (j = 0; j < 8; j++) 468 for (i = 0; i < 8; i++)
456 RR(OVL_FIR_COEF_V2(i, j)); 469 RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, i));
457 } 470
458 if (dss_has_feature(FEAT_ATTR2)) 471 for (i = 0; i < 8; i++)
459 RR(OVL_ATTRIBUTES2(i)); 472 RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, i));
473 }
474 if (dss_has_feature(FEAT_ATTR2))
475 RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
476
477 if (dss_has_feature(FEAT_PRELOAD))
478 RR(OVL_PRELOAD(OMAP_DSS_VIDEO1));
479
480 /* VID2 */
481 RR(OVL_BA0(OMAP_DSS_VIDEO2));
482 RR(OVL_BA1(OMAP_DSS_VIDEO2));
483 RR(OVL_POSITION(OMAP_DSS_VIDEO2));
484 RR(OVL_SIZE(OMAP_DSS_VIDEO2));
485 RR(OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
486 RR(OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
487 RR(OVL_ROW_INC(OMAP_DSS_VIDEO2));
488 RR(OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
489 RR(OVL_FIR(OMAP_DSS_VIDEO2));
490 RR(OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
491 RR(OVL_ACCU0(OMAP_DSS_VIDEO2));
492 RR(OVL_ACCU1(OMAP_DSS_VIDEO2));
493
494 for (i = 0; i < 8; i++)
495 RR(OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, i));
496
497 for (i = 0; i < 8; i++)
498 RR(OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, i));
499
500 for (i = 0; i < 5; i++)
501 RR(OVL_CONV_COEF(OMAP_DSS_VIDEO2, i));
502
503 if (dss_has_feature(FEAT_FIR_COEF_V)) {
504 for (i = 0; i < 8; i++)
505 RR(OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, i));
506 }
507
508 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
509 RR(OVL_BA0_UV(OMAP_DSS_VIDEO2));
510 RR(OVL_BA1_UV(OMAP_DSS_VIDEO2));
511 RR(OVL_FIR2(OMAP_DSS_VIDEO2));
512 RR(OVL_ACCU2_0(OMAP_DSS_VIDEO2));
513 RR(OVL_ACCU2_1(OMAP_DSS_VIDEO2));
514
515 for (i = 0; i < 8; i++)
516 RR(OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, i));
517
518 for (i = 0; i < 8; i++)
519 RR(OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, i));
520
521 for (i = 0; i < 8; i++)
522 RR(OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, i));
460 } 523 }
524 if (dss_has_feature(FEAT_ATTR2))
525 RR(OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
526
527 if (dss_has_feature(FEAT_PRELOAD))
528 RR(OVL_PRELOAD(OMAP_DSS_VIDEO2));
461 529
462 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 530 if (dss_has_feature(FEAT_CORE_CLK_DIV))
463 RR(DIVISOR); 531 RR(DIVISOR);
@@ -466,10 +534,8 @@ static void dispc_restore_context(void)
466 RR(CONTROL); 534 RR(CONTROL);
467 if (dss_has_feature(FEAT_MGR_LCD2)) 535 if (dss_has_feature(FEAT_MGR_LCD2))
468 RR(CONTROL2); 536 RR(CONTROL2);
469 if (dss_has_feature(FEAT_MGR_LCD3))
470 RR(CONTROL3);
471 /* clear spurious SYNC_LOST_DIGIT interrupts */ 537 /* clear spurious SYNC_LOST_DIGIT interrupts */
472 dispc_clear_irqstatus(DISPC_IRQ_SYNC_LOST_DIGIT); 538 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
473 539
474 /* 540 /*
475 * enable last so IRQs won't trigger before 541 * enable last so IRQs won't trigger before
@@ -493,7 +559,6 @@ int dispc_runtime_get(void)
493 WARN_ON(r < 0); 559 WARN_ON(r < 0);
494 return r < 0 ? r : 0; 560 return r < 0 ? r : 0;
495} 561}
496EXPORT_SYMBOL(dispc_runtime_get);
497 562
498void dispc_runtime_put(void) 563void dispc_runtime_put(void)
499{ 564{
@@ -501,143 +566,214 @@ void dispc_runtime_put(void)
501 566
502 DSSDBG("dispc_runtime_put\n"); 567 DSSDBG("dispc_runtime_put\n");
503 568
504 r = pm_runtime_put_sync(&dispc.pdev->dev); 569 r = pm_runtime_put(&dispc.pdev->dev);
505 WARN_ON(r < 0 && r != -ENOSYS); 570 WARN_ON(r < 0);
506}
507EXPORT_SYMBOL(dispc_runtime_put);
508
509u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
510{
511 return mgr_desc[channel].vsync_irq;
512} 571}
513EXPORT_SYMBOL(dispc_mgr_get_vsync_irq);
514 572
515u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
516{
517 if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv)
518 return 0;
519
520 return mgr_desc[channel].framedone_irq;
521}
522EXPORT_SYMBOL(dispc_mgr_get_framedone_irq);
523 573
524u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel) 574bool dispc_go_busy(enum omap_channel channel)
525{ 575{
526 return mgr_desc[channel].sync_lost_irq; 576 int bit;
527}
528EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq);
529 577
530u32 dispc_wb_get_framedone_irq(void) 578 if (channel == OMAP_DSS_CHANNEL_LCD ||
531{ 579 channel == OMAP_DSS_CHANNEL_LCD2)
532 return DISPC_IRQ_FRAMEDONEWB; 580 bit = 5; /* GOLCD */
533} 581 else
582 bit = 6; /* GODIGIT */
534 583
535bool dispc_mgr_go_busy(enum omap_channel channel) 584 if (channel == OMAP_DSS_CHANNEL_LCD2)
536{ 585 return REG_GET(DISPC_CONTROL2, bit, bit) == 1;
537 return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; 586 else
587 return REG_GET(DISPC_CONTROL, bit, bit) == 1;
538} 588}
539EXPORT_SYMBOL(dispc_mgr_go_busy);
540 589
541void dispc_mgr_go(enum omap_channel channel) 590void dispc_go(enum omap_channel channel)
542{ 591{
543 WARN_ON(dispc_mgr_is_enabled(channel) == false); 592 int bit;
544 WARN_ON(dispc_mgr_go_busy(channel)); 593 bool enable_bit, go_bit;
545
546 DSSDBG("GO %s\n", mgr_desc[channel].name);
547 594
548 mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); 595 if (channel == OMAP_DSS_CHANNEL_LCD ||
549} 596 channel == OMAP_DSS_CHANNEL_LCD2)
550EXPORT_SYMBOL(dispc_mgr_go); 597 bit = 0; /* LCDENABLE */
598 else
599 bit = 1; /* DIGITALENABLE */
551 600
552bool dispc_wb_go_busy(void) 601 /* if the channel is not enabled, we don't need GO */
553{ 602 if (channel == OMAP_DSS_CHANNEL_LCD2)
554 return REG_GET(DISPC_CONTROL2, 6, 6) == 1; 603 enable_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
555} 604 else
605 enable_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
556 606
557void dispc_wb_go(void) 607 if (!enable_bit)
558{ 608 return;
559 enum omap_plane plane = OMAP_DSS_WB;
560 bool enable, go;
561 609
562 enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1; 610 if (channel == OMAP_DSS_CHANNEL_LCD ||
611 channel == OMAP_DSS_CHANNEL_LCD2)
612 bit = 5; /* GOLCD */
613 else
614 bit = 6; /* GODIGIT */
563 615
564 if (!enable) 616 if (channel == OMAP_DSS_CHANNEL_LCD2)
565 return; 617 go_bit = REG_GET(DISPC_CONTROL2, bit, bit) == 1;
618 else
619 go_bit = REG_GET(DISPC_CONTROL, bit, bit) == 1;
566 620
567 go = REG_GET(DISPC_CONTROL2, 6, 6) == 1; 621 if (go_bit) {
568 if (go) { 622 DSSERR("GO bit not down for channel %d\n", channel);
569 DSSERR("GO bit not down for WB\n");
570 return; 623 return;
571 } 624 }
572 625
573 REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6); 626 DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" :
627 (channel == OMAP_DSS_CHANNEL_LCD2 ? "LCD2" : "DIGIT"));
628
629 if (channel == OMAP_DSS_CHANNEL_LCD2)
630 REG_FLD_MOD(DISPC_CONTROL2, 1, bit, bit);
631 else
632 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit);
574} 633}
575 634
576static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) 635static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value)
577{ 636{
578 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); 637 dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value);
579} 638}
580 639
581static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value) 640static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value)
582{ 641{
583 dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); 642 dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value);
584} 643}
585 644
586static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value) 645static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value)
587{ 646{
588 dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); 647 dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value);
589} 648}
590 649
591static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value) 650static void _dispc_write_firh2_reg(enum omap_plane plane, int reg, u32 value)
592{ 651{
593 BUG_ON(plane == OMAP_DSS_GFX); 652 BUG_ON(plane == OMAP_DSS_GFX);
594 653
595 dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); 654 dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value);
596} 655}
597 656
598static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg, 657static void _dispc_write_firhv2_reg(enum omap_plane plane, int reg, u32 value)
599 u32 value)
600{ 658{
601 BUG_ON(plane == OMAP_DSS_GFX); 659 BUG_ON(plane == OMAP_DSS_GFX);
602 660
603 dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); 661 dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value);
604} 662}
605 663
606static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value) 664static void _dispc_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
607{ 665{
608 BUG_ON(plane == OMAP_DSS_GFX); 666 BUG_ON(plane == OMAP_DSS_GFX);
609 667
610 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); 668 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
611} 669}
612 670
613static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc, 671static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
614 int fir_vinc, int five_taps, 672 int vscaleup, int five_taps,
615 enum omap_color_component color_comp) 673 enum omap_color_component color_comp)
616{ 674{
617 const struct dispc_coef *h_coef, *v_coef; 675 /* Coefficients for horizontal up-sampling */
676 static const struct dispc_h_coef coef_hup[8] = {
677 { 0, 0, 128, 0, 0 },
678 { -1, 13, 124, -8, 0 },
679 { -2, 30, 112, -11, -1 },
680 { -5, 51, 95, -11, -2 },
681 { 0, -9, 73, 73, -9 },
682 { -2, -11, 95, 51, -5 },
683 { -1, -11, 112, 30, -2 },
684 { 0, -8, 124, 13, -1 },
685 };
686
687 /* Coefficients for vertical up-sampling */
688 static const struct dispc_v_coef coef_vup_3tap[8] = {
689 { 0, 0, 128, 0, 0 },
690 { 0, 3, 123, 2, 0 },
691 { 0, 12, 111, 5, 0 },
692 { 0, 32, 89, 7, 0 },
693 { 0, 0, 64, 64, 0 },
694 { 0, 7, 89, 32, 0 },
695 { 0, 5, 111, 12, 0 },
696 { 0, 2, 123, 3, 0 },
697 };
698
699 static const struct dispc_v_coef coef_vup_5tap[8] = {
700 { 0, 0, 128, 0, 0 },
701 { -1, 13, 124, -8, 0 },
702 { -2, 30, 112, -11, -1 },
703 { -5, 51, 95, -11, -2 },
704 { 0, -9, 73, 73, -9 },
705 { -2, -11, 95, 51, -5 },
706 { -1, -11, 112, 30, -2 },
707 { 0, -8, 124, 13, -1 },
708 };
709
710 /* Coefficients for horizontal down-sampling */
711 static const struct dispc_h_coef coef_hdown[8] = {
712 { 0, 36, 56, 36, 0 },
713 { 4, 40, 55, 31, -2 },
714 { 8, 44, 54, 27, -5 },
715 { 12, 48, 53, 22, -7 },
716 { -9, 17, 52, 51, 17 },
717 { -7, 22, 53, 48, 12 },
718 { -5, 27, 54, 44, 8 },
719 { -2, 31, 55, 40, 4 },
720 };
721
722 /* Coefficients for vertical down-sampling */
723 static const struct dispc_v_coef coef_vdown_3tap[8] = {
724 { 0, 36, 56, 36, 0 },
725 { 0, 40, 57, 31, 0 },
726 { 0, 45, 56, 27, 0 },
727 { 0, 50, 55, 23, 0 },
728 { 0, 18, 55, 55, 0 },
729 { 0, 23, 55, 50, 0 },
730 { 0, 27, 56, 45, 0 },
731 { 0, 31, 57, 40, 0 },
732 };
733
734 static const struct dispc_v_coef coef_vdown_5tap[8] = {
735 { 0, 36, 56, 36, 0 },
736 { 4, 40, 55, 31, -2 },
737 { 8, 44, 54, 27, -5 },
738 { 12, 48, 53, 22, -7 },
739 { -9, 17, 52, 51, 17 },
740 { -7, 22, 53, 48, 12 },
741 { -5, 27, 54, 44, 8 },
742 { -2, 31, 55, 40, 4 },
743 };
744
745 const struct dispc_h_coef *h_coef;
746 const struct dispc_v_coef *v_coef;
618 int i; 747 int i;
619 748
620 h_coef = dispc_ovl_get_scale_coef(fir_hinc, true); 749 if (hscaleup)
621 v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps); 750 h_coef = coef_hup;
751 else
752 h_coef = coef_hdown;
753
754 if (vscaleup)
755 v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
756 else
757 v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
622 758
623 for (i = 0; i < 8; i++) { 759 for (i = 0; i < 8; i++) {
624 u32 h, hv; 760 u32 h, hv;
625 761
626 h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0) 762 h = FLD_VAL(h_coef[i].hc0, 7, 0)
627 | FLD_VAL(h_coef[i].hc1_vc0, 15, 8) 763 | FLD_VAL(h_coef[i].hc1, 15, 8)
628 | FLD_VAL(h_coef[i].hc2_vc1, 23, 16) 764 | FLD_VAL(h_coef[i].hc2, 23, 16)
629 | FLD_VAL(h_coef[i].hc3_vc2, 31, 24); 765 | FLD_VAL(h_coef[i].hc3, 31, 24);
630 hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0) 766 hv = FLD_VAL(h_coef[i].hc4, 7, 0)
631 | FLD_VAL(v_coef[i].hc1_vc0, 15, 8) 767 | FLD_VAL(v_coef[i].vc0, 15, 8)
632 | FLD_VAL(v_coef[i].hc2_vc1, 23, 16) 768 | FLD_VAL(v_coef[i].vc1, 23, 16)
633 | FLD_VAL(v_coef[i].hc3_vc2, 31, 24); 769 | FLD_VAL(v_coef[i].vc2, 31, 24);
634 770
635 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { 771 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
636 dispc_ovl_write_firh_reg(plane, i, h); 772 _dispc_write_firh_reg(plane, i, h);
637 dispc_ovl_write_firhv_reg(plane, i, hv); 773 _dispc_write_firhv_reg(plane, i, hv);
638 } else { 774 } else {
639 dispc_ovl_write_firh2_reg(plane, i, h); 775 _dispc_write_firh2_reg(plane, i, h);
640 dispc_ovl_write_firhv2_reg(plane, i, hv); 776 _dispc_write_firhv2_reg(plane, i, hv);
641 } 777 }
642 778
643 } 779 }
@@ -645,98 +781,100 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
645 if (five_taps) { 781 if (five_taps) {
646 for (i = 0; i < 8; i++) { 782 for (i = 0; i < 8; i++) {
647 u32 v; 783 u32 v;
648 v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0) 784 v = FLD_VAL(v_coef[i].vc00, 7, 0)
649 | FLD_VAL(v_coef[i].hc4_vc22, 15, 8); 785 | FLD_VAL(v_coef[i].vc22, 15, 8);
650 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) 786 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
651 dispc_ovl_write_firv_reg(plane, i, v); 787 _dispc_write_firv_reg(plane, i, v);
652 else 788 else
653 dispc_ovl_write_firv2_reg(plane, i, v); 789 _dispc_write_firv2_reg(plane, i, v);
654 } 790 }
655 } 791 }
656} 792}
657 793
658 794static void _dispc_setup_color_conv_coef(void)
659static void dispc_ovl_write_color_conv_coef(enum omap_plane plane,
660 const struct color_conv_coef *ct)
661{ 795{
662#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) 796 const struct color_conv_coef {
663 797 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
664 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->rcr, ct->ry)); 798 int full_range;
665 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->gy, ct->rcb)); 799 } ctbl_bt601_5 = {
666 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->gcb, ct->gcr)); 800 298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
667 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->bcr, ct->by)); 801 };
668 dispc_write_reg(DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->bcb));
669 802
670 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11); 803 const struct color_conv_coef *ct;
671 804
672#undef CVAL 805#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
673}
674 806
675static void dispc_setup_color_conv_coef(void) 807 ct = &ctbl_bt601_5;
676{ 808
677 int i; 809 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0),
678 int num_ovl = dss_feat_get_num_ovls(); 810 CVAL(ct->rcr, ct->ry));
679 int num_wb = dss_feat_get_num_wbs(); 811 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1),
680 const struct color_conv_coef ctbl_bt601_5_ovl = { 812 CVAL(ct->gy, ct->rcb));
681 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, 813 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2),
682 }; 814 CVAL(ct->gcb, ct->gcr));
683 const struct color_conv_coef ctbl_bt601_5_wb = { 815 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3),
684 66, 112, -38, 129, -94, -74, 25, -18, 112, 0, 816 CVAL(ct->bcr, ct->by));
685 }; 817 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4),
818 CVAL(0, ct->bcb));
819
820 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0),
821 CVAL(ct->rcr, ct->ry));
822 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1),
823 CVAL(ct->gy, ct->rcb));
824 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2),
825 CVAL(ct->gcb, ct->gcr));
826 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3),
827 CVAL(ct->bcr, ct->by));
828 dispc_write_reg(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4),
829 CVAL(0, ct->bcb));
686 830
687 for (i = 1; i < num_ovl; i++) 831#undef CVAL
688 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_ovl);
689 832
690 for (; i < num_wb; i++) 833 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1),
691 dispc_ovl_write_color_conv_coef(i, &ctbl_bt601_5_wb); 834 ct->full_range, 11, 11);
835 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2),
836 ct->full_range, 11, 11);
692} 837}
693 838
694static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) 839
840static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr)
695{ 841{
696 dispc_write_reg(DISPC_OVL_BA0(plane), paddr); 842 dispc_write_reg(DISPC_OVL_BA0(plane), paddr);
697} 843}
698 844
699static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr) 845static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr)
700{ 846{
701 dispc_write_reg(DISPC_OVL_BA1(plane), paddr); 847 dispc_write_reg(DISPC_OVL_BA1(plane), paddr);
702} 848}
703 849
704static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr) 850static void _dispc_set_plane_ba0_uv(enum omap_plane plane, u32 paddr)
705{ 851{
706 dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); 852 dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr);
707} 853}
708 854
709static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr) 855static void _dispc_set_plane_ba1_uv(enum omap_plane plane, u32 paddr)
710{ 856{
711 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); 857 dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr);
712} 858}
713 859
714static void dispc_ovl_set_pos(enum omap_plane plane, 860static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y)
715 enum omap_overlay_caps caps, int x, int y)
716{ 861{
717 u32 val; 862 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
718
719 if ((caps & OMAP_DSS_OVL_CAP_POS) == 0)
720 return;
721
722 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0);
723 863
724 dispc_write_reg(DISPC_OVL_POSITION(plane), val); 864 dispc_write_reg(DISPC_OVL_POSITION(plane), val);
725} 865}
726 866
727static void dispc_ovl_set_input_size(enum omap_plane plane, int width, 867static void _dispc_set_pic_size(enum omap_plane plane, int width, int height)
728 int height)
729{ 868{
730 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 869 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
731 870
732 if (plane == OMAP_DSS_GFX || plane == OMAP_DSS_WB) 871 if (plane == OMAP_DSS_GFX)
733 dispc_write_reg(DISPC_OVL_SIZE(plane), val); 872 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
734 else 873 else
735 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); 874 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
736} 875}
737 876
738static void dispc_ovl_set_output_size(enum omap_plane plane, int width, 877static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
739 int height)
740{ 878{
741 u32 val; 879 u32 val;
742 880
@@ -744,65 +882,47 @@ static void dispc_ovl_set_output_size(enum omap_plane plane, int width,
744 882
745 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 883 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
746 884
747 if (plane == OMAP_DSS_WB) 885 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
748 dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val);
749 else
750 dispc_write_reg(DISPC_OVL_SIZE(plane), val);
751}
752
753static void dispc_ovl_set_zorder(enum omap_plane plane,
754 enum omap_overlay_caps caps, u8 zorder)
755{
756 if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
757 return;
758
759 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), zorder, 27, 26);
760} 886}
761 887
762static void dispc_ovl_enable_zorder_planes(void) 888static void _dispc_set_pre_mult_alpha(enum omap_plane plane, bool enable)
763{ 889{
764 int i; 890 if (!dss_has_feature(FEAT_PRE_MULT_ALPHA))
765
766 if (!dss_has_feature(FEAT_ALPHA_FREE_ZORDER))
767 return; 891 return;
768 892
769 for (i = 0; i < dss_feat_get_num_ovls(); i++) 893 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
770 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); 894 plane == OMAP_DSS_VIDEO1)
771}
772
773static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane,
774 enum omap_overlay_caps caps, bool enable)
775{
776 if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
777 return; 895 return;
778 896
779 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); 897 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28);
780} 898}
781 899
782static void dispc_ovl_setup_global_alpha(enum omap_plane plane, 900static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
783 enum omap_overlay_caps caps, u8 global_alpha)
784{ 901{
785 static const unsigned shifts[] = { 0, 8, 16, 24, }; 902 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
786 int shift; 903 return;
787 904
788 if ((caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) 905 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
906 plane == OMAP_DSS_VIDEO1)
789 return; 907 return;
790 908
791 shift = shifts[plane]; 909 if (plane == OMAP_DSS_GFX)
792 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift); 910 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
911 else if (plane == OMAP_DSS_VIDEO2)
912 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16);
793} 913}
794 914
795static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc) 915static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc)
796{ 916{
797 dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); 917 dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc);
798} 918}
799 919
800static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc) 920static void _dispc_set_row_inc(enum omap_plane plane, s32 inc)
801{ 921{
802 dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); 922 dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc);
803} 923}
804 924
805static void dispc_ovl_set_color_mode(enum omap_plane plane, 925static void _dispc_set_color_mode(enum omap_plane plane,
806 enum omap_color_mode color_mode) 926 enum omap_color_mode color_mode)
807{ 927{
808 u32 m = 0; 928 u32 m = 0;
@@ -810,11 +930,11 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
810 switch (color_mode) { 930 switch (color_mode) {
811 case OMAP_DSS_COLOR_NV12: 931 case OMAP_DSS_COLOR_NV12:
812 m = 0x0; break; 932 m = 0x0; break;
813 case OMAP_DSS_COLOR_RGBX16: 933 case OMAP_DSS_COLOR_RGB12U:
814 m = 0x1; break; 934 m = 0x1; break;
815 case OMAP_DSS_COLOR_RGBA16: 935 case OMAP_DSS_COLOR_RGBA16:
816 m = 0x2; break; 936 m = 0x2; break;
817 case OMAP_DSS_COLOR_RGB12U: 937 case OMAP_DSS_COLOR_RGBX16:
818 m = 0x4; break; 938 m = 0x4; break;
819 case OMAP_DSS_COLOR_ARGB16: 939 case OMAP_DSS_COLOR_ARGB16:
820 m = 0x5; break; 940 m = 0x5; break;
@@ -839,7 +959,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
839 case OMAP_DSS_COLOR_XRGB16_1555: 959 case OMAP_DSS_COLOR_XRGB16_1555:
840 m = 0xf; break; 960 m = 0xf; break;
841 default: 961 default:
842 BUG(); return; 962 BUG(); break;
843 } 963 }
844 } else { 964 } else {
845 switch (color_mode) { 965 switch (color_mode) {
@@ -863,9 +983,9 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
863 m = 0x8; break; 983 m = 0x8; break;
864 case OMAP_DSS_COLOR_RGB24P: 984 case OMAP_DSS_COLOR_RGB24P:
865 m = 0x9; break; 985 m = 0x9; break;
866 case OMAP_DSS_COLOR_RGBX16: 986 case OMAP_DSS_COLOR_YUV2:
867 m = 0xa; break; 987 m = 0xa; break;
868 case OMAP_DSS_COLOR_RGBA16: 988 case OMAP_DSS_COLOR_UYVY:
869 m = 0xb; break; 989 m = 0xb; break;
870 case OMAP_DSS_COLOR_ARGB32: 990 case OMAP_DSS_COLOR_ARGB32:
871 m = 0xc; break; 991 m = 0xc; break;
@@ -876,26 +996,15 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
876 case OMAP_DSS_COLOR_XRGB16_1555: 996 case OMAP_DSS_COLOR_XRGB16_1555:
877 m = 0xf; break; 997 m = 0xf; break;
878 default: 998 default:
879 BUG(); return; 999 BUG(); break;
880 } 1000 }
881 } 1001 }
882 1002
883 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); 1003 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
884} 1004}
885 1005
886static void dispc_ovl_configure_burst_type(enum omap_plane plane, 1006void dispc_set_channel_out(enum omap_plane plane,
887 enum omap_dss_rotation_type rotation_type) 1007 enum omap_channel channel)
888{
889 if (dss_has_feature(FEAT_BURST_2D) == 0)
890 return;
891
892 if (rotation_type == OMAP_DSS_ROT_TILER)
893 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
894 else
895 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
896}
897
898void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
899{ 1008{
900 int shift; 1009 int shift;
901 u32 val; 1010 u32 val;
@@ -907,7 +1016,6 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
907 break; 1016 break;
908 case OMAP_DSS_VIDEO1: 1017 case OMAP_DSS_VIDEO1:
909 case OMAP_DSS_VIDEO2: 1018 case OMAP_DSS_VIDEO2:
910 case OMAP_DSS_VIDEO3:
911 shift = 16; 1019 shift = 16;
912 break; 1020 break;
913 default: 1021 default:
@@ -930,18 +1038,8 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
930 chan = 0; 1038 chan = 0;
931 chan2 = 1; 1039 chan2 = 1;
932 break; 1040 break;
933 case OMAP_DSS_CHANNEL_LCD3:
934 if (dss_has_feature(FEAT_MGR_LCD3)) {
935 chan = 0;
936 chan2 = 2;
937 } else {
938 BUG();
939 return;
940 }
941 break;
942 default: 1041 default:
943 BUG(); 1042 BUG();
944 return;
945 } 1043 }
946 1044
947 val = FLD_MOD(val, chan, shift, shift); 1045 val = FLD_MOD(val, chan, shift, shift);
@@ -951,63 +1049,25 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
951 } 1049 }
952 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1050 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
953} 1051}
954EXPORT_SYMBOL(dispc_ovl_set_channel_out);
955 1052
956static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) 1053static void dispc_set_burst_size(enum omap_plane plane,
1054 enum omap_burst_size burst_size)
957{ 1055{
958 int shift; 1056 int shift;
959 u32 val;
960 enum omap_channel channel;
961 1057
962 switch (plane) { 1058 switch (plane) {
963 case OMAP_DSS_GFX: 1059 case OMAP_DSS_GFX:
964 shift = 8; 1060 shift = 6;
965 break; 1061 break;
966 case OMAP_DSS_VIDEO1: 1062 case OMAP_DSS_VIDEO1:
967 case OMAP_DSS_VIDEO2: 1063 case OMAP_DSS_VIDEO2:
968 case OMAP_DSS_VIDEO3: 1064 shift = 14;
969 shift = 16;
970 break; 1065 break;
971 default: 1066 default:
972 BUG(); 1067 BUG();
973 return 0; 1068 return;
974 }
975
976 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
977
978 if (dss_has_feature(FEAT_MGR_LCD3)) {
979 if (FLD_GET(val, 31, 30) == 0)
980 channel = FLD_GET(val, shift, shift);
981 else if (FLD_GET(val, 31, 30) == 1)
982 channel = OMAP_DSS_CHANNEL_LCD2;
983 else
984 channel = OMAP_DSS_CHANNEL_LCD3;
985 } else if (dss_has_feature(FEAT_MGR_LCD2)) {
986 if (FLD_GET(val, 31, 30) == 0)
987 channel = FLD_GET(val, shift, shift);
988 else
989 channel = OMAP_DSS_CHANNEL_LCD2;
990 } else {
991 channel = FLD_GET(val, shift, shift);
992 } 1069 }
993 1070
994 return channel;
995}
996
997void dispc_wb_set_channel_in(enum dss_writeback_channel channel)
998{
999 enum omap_plane plane = OMAP_DSS_WB;
1000
1001 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16);
1002}
1003
1004static void dispc_ovl_set_burst_size(enum omap_plane plane,
1005 enum omap_burst_size burst_size)
1006{
1007 static const unsigned shifts[] = { 6, 14, 14, 14, 14, };
1008 int shift;
1009
1010 shift = shifts[plane];
1011 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift); 1071 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), burst_size, shift + 1, shift);
1012} 1072}
1013 1073
@@ -1017,11 +1077,11 @@ static void dispc_configure_burst_sizes(void)
1017 const int burst_size = BURST_SIZE_X8; 1077 const int burst_size = BURST_SIZE_X8;
1018 1078
1019 /* Configure burst size always to maximum size */ 1079 /* Configure burst size always to maximum size */
1020 for (i = 0; i < dss_feat_get_num_ovls(); ++i) 1080 for (i = 0; i < omap_dss_get_num_overlays(); ++i)
1021 dispc_ovl_set_burst_size(i, burst_size); 1081 dispc_set_burst_size(i, burst_size);
1022} 1082}
1023 1083
1024static u32 dispc_ovl_get_burst_size(enum omap_plane plane) 1084u32 dispc_get_burst_size(enum omap_plane plane)
1025{ 1085{
1026 unsigned unit = dss_feat_get_burst_size_unit(); 1086 unsigned unit = dss_feat_get_burst_size_unit();
1027 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ 1087 /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */
@@ -1042,20 +1102,26 @@ void dispc_enable_gamma_table(bool enable)
1042 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); 1102 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
1043} 1103}
1044 1104
1045static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) 1105void dispc_enable_cpr(enum omap_channel channel, bool enable)
1046{ 1106{
1047 if (channel == OMAP_DSS_CHANNEL_DIGIT) 1107 u16 reg;
1108
1109 if (channel == OMAP_DSS_CHANNEL_LCD)
1110 reg = DISPC_CONFIG;
1111 else if (channel == OMAP_DSS_CHANNEL_LCD2)
1112 reg = DISPC_CONFIG2;
1113 else
1048 return; 1114 return;
1049 1115
1050 mgr_fld_write(channel, DISPC_MGR_FLD_CPR, enable); 1116 REG_FLD_MOD(reg, enable, 15, 15);
1051} 1117}
1052 1118
1053static void dispc_mgr_set_cpr_coef(enum omap_channel channel, 1119void dispc_set_cpr_coef(enum omap_channel channel,
1054 const struct omap_dss_cpr_coefs *coefs) 1120 struct omap_dss_cpr_coefs *coefs)
1055{ 1121{
1056 u32 coef_r, coef_g, coef_b; 1122 u32 coef_r, coef_g, coef_b;
1057 1123
1058 if (!dss_mgr_is_lcd(channel)) 1124 if (channel != OMAP_DSS_CHANNEL_LCD && channel != OMAP_DSS_CHANNEL_LCD2)
1059 return; 1125 return;
1060 1126
1061 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) | 1127 coef_r = FLD_VAL(coefs->rr, 31, 22) | FLD_VAL(coefs->rg, 20, 11) |
@@ -1070,7 +1136,7 @@ static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
1070 dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); 1136 dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b);
1071} 1137}
1072 1138
1073static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable) 1139static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable)
1074{ 1140{
1075 u32 val; 1141 u32 val;
1076 1142
@@ -1081,34 +1147,38 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable)
1081 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 1147 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
1082} 1148}
1083 1149
1084static void dispc_ovl_enable_replication(enum omap_plane plane, 1150void dispc_enable_replication(enum omap_plane plane, bool enable)
1085 enum omap_overlay_caps caps, bool enable)
1086{ 1151{
1087 static const unsigned shifts[] = { 5, 10, 10, 10 }; 1152 int bit;
1088 int shift;
1089 1153
1090 if ((caps & OMAP_DSS_OVL_CAP_REPLICATION) == 0) 1154 if (plane == OMAP_DSS_GFX)
1091 return; 1155 bit = 5;
1156 else
1157 bit = 10;
1092 1158
1093 shift = shifts[plane]; 1159 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit);
1094 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
1095} 1160}
1096 1161
1097static void dispc_mgr_set_size(enum omap_channel channel, u16 width, 1162void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height)
1098 u16 height)
1099{ 1163{
1100 u32 val; 1164 u32 val;
1101 1165 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
1102 val = FLD_VAL(height - 1, dispc.feat->mgr_height_start, 16) | 1166 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
1103 FLD_VAL(width - 1, dispc.feat->mgr_width_start, 0);
1104
1105 dispc_write_reg(DISPC_SIZE_MGR(channel), val); 1167 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1106} 1168}
1107 1169
1108static void dispc_init_fifos(void) 1170void dispc_set_digit_size(u16 width, u16 height)
1171{
1172 u32 val;
1173 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
1174 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
1175 dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val);
1176}
1177
1178static void dispc_read_plane_fifo_sizes(void)
1109{ 1179{
1110 u32 size; 1180 u32 size;
1111 int fifo; 1181 int plane;
1112 u8 start, end; 1182 u8 start, end;
1113 u32 unit; 1183 u32 unit;
1114 1184
@@ -1116,56 +1186,19 @@ static void dispc_init_fifos(void)
1116 1186
1117 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end); 1187 dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
1118 1188
1119 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) { 1189 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
1120 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(fifo), start, end); 1190 size = REG_GET(DISPC_OVL_FIFO_SIZE_STATUS(plane), start, end);
1121 size *= unit; 1191 size *= unit;
1122 dispc.fifo_size[fifo] = size; 1192 dispc.fifo_size[plane] = size;
1123
1124 /*
1125 * By default fifos are mapped directly to overlays, fifo 0 to
1126 * ovl 0, fifo 1 to ovl 1, etc.
1127 */
1128 dispc.fifo_assignment[fifo] = fifo;
1129 }
1130
1131 /*
1132 * The GFX fifo on OMAP4 is smaller than the other fifos. The small fifo
1133 * causes problems with certain use cases, like using the tiler in 2D
1134 * mode. The below hack swaps the fifos of GFX and WB planes, thus
1135 * giving GFX plane a larger fifo. WB but should work fine with a
1136 * smaller fifo.
1137 */
1138 if (dispc.feat->gfx_fifo_workaround) {
1139 u32 v;
1140
1141 v = dispc_read_reg(DISPC_GLOBAL_BUFFER);
1142
1143 v = FLD_MOD(v, 4, 2, 0); /* GFX BUF top to WB */
1144 v = FLD_MOD(v, 4, 5, 3); /* GFX BUF bottom to WB */
1145 v = FLD_MOD(v, 0, 26, 24); /* WB BUF top to GFX */
1146 v = FLD_MOD(v, 0, 29, 27); /* WB BUF bottom to GFX */
1147
1148 dispc_write_reg(DISPC_GLOBAL_BUFFER, v);
1149
1150 dispc.fifo_assignment[OMAP_DSS_GFX] = OMAP_DSS_WB;
1151 dispc.fifo_assignment[OMAP_DSS_WB] = OMAP_DSS_GFX;
1152 } 1193 }
1153} 1194}
1154 1195
1155static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) 1196u32 dispc_get_plane_fifo_size(enum omap_plane plane)
1156{ 1197{
1157 int fifo; 1198 return dispc.fifo_size[plane];
1158 u32 size = 0;
1159
1160 for (fifo = 0; fifo < dispc.feat->num_fifos; ++fifo) {
1161 if (dispc.fifo_assignment[fifo] == plane)
1162 size += dispc.fifo_size[fifo];
1163 }
1164
1165 return size;
1166} 1199}
1167 1200
1168void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) 1201void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1169{ 1202{
1170 u8 hi_start, hi_end, lo_start, lo_end; 1203 u8 hi_start, hi_end, lo_start, lo_end;
1171 u32 unit; 1204 u32 unit;
@@ -1181,13 +1214,13 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1181 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end); 1214 dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
1182 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end); 1215 dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
1183 1216
1184 DSSDBG("fifo(%d) threshold (bytes), old %u/%u, new %u/%u\n", 1217 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
1185 plane, 1218 plane,
1186 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), 1219 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1187 lo_start, lo_end) * unit, 1220 lo_start, lo_end),
1188 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane), 1221 REG_GET(DISPC_OVL_FIFO_THRESHOLD(plane),
1189 hi_start, hi_end) * unit, 1222 hi_start, hi_end),
1190 low * unit, high * unit); 1223 low, high);
1191 1224
1192 dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane), 1225 dispc_write_reg(DISPC_OVL_FIFO_THRESHOLD(plane),
1193 FLD_VAL(high, hi_start, hi_end) | 1226 FLD_VAL(high, hi_start, hi_end) |
@@ -1196,63 +1229,11 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1196 1229
1197void dispc_enable_fifomerge(bool enable) 1230void dispc_enable_fifomerge(bool enable)
1198{ 1231{
1199 if (!dss_has_feature(FEAT_FIFO_MERGE)) {
1200 WARN_ON(enable);
1201 return;
1202 }
1203
1204 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); 1232 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled");
1205 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); 1233 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14);
1206} 1234}
1207 1235
1208void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 1236static void _dispc_set_fir(enum omap_plane plane,
1209 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
1210 bool manual_update)
1211{
1212 /*
1213 * All sizes are in bytes. Both the buffer and burst are made of
1214 * buffer_units, and the fifo thresholds must be buffer_unit aligned.
1215 */
1216
1217 unsigned buf_unit = dss_feat_get_buffer_size_unit();
1218 unsigned ovl_fifo_size, total_fifo_size, burst_size;
1219 int i;
1220
1221 burst_size = dispc_ovl_get_burst_size(plane);
1222 ovl_fifo_size = dispc_ovl_get_fifo_size(plane);
1223
1224 if (use_fifomerge) {
1225 total_fifo_size = 0;
1226 for (i = 0; i < dss_feat_get_num_ovls(); ++i)
1227 total_fifo_size += dispc_ovl_get_fifo_size(i);
1228 } else {
1229 total_fifo_size = ovl_fifo_size;
1230 }
1231
1232 /*
1233 * We use the same low threshold for both fifomerge and non-fifomerge
1234 * cases, but for fifomerge we calculate the high threshold using the
1235 * combined fifo size
1236 */
1237
1238 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1239 *fifo_low = ovl_fifo_size - burst_size * 2;
1240 *fifo_high = total_fifo_size - burst_size;
1241 } else if (plane == OMAP_DSS_WB) {
1242 /*
1243 * Most optimal configuration for writeback is to push out data
1244 * to the interconnect the moment writeback pushes enough pixels
1245 * in the FIFO to form a burst
1246 */
1247 *fifo_low = 0;
1248 *fifo_high = burst_size;
1249 } else {
1250 *fifo_low = ovl_fifo_size - burst_size;
1251 *fifo_high = total_fifo_size - buf_unit;
1252 }
1253}
1254
1255static void dispc_ovl_set_fir(enum omap_plane plane,
1256 int hinc, int vinc, 1237 int hinc, int vinc,
1257 enum omap_color_component color_comp) 1238 enum omap_color_component color_comp)
1258{ 1239{
@@ -1275,7 +1256,7 @@ static void dispc_ovl_set_fir(enum omap_plane plane,
1275 } 1256 }
1276} 1257}
1277 1258
1278static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) 1259static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1279{ 1260{
1280 u32 val; 1261 u32 val;
1281 u8 hor_start, hor_end, vert_start, vert_end; 1262 u8 hor_start, hor_end, vert_start, vert_end;
@@ -1289,7 +1270,7 @@ static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu)
1289 dispc_write_reg(DISPC_OVL_ACCU0(plane), val); 1270 dispc_write_reg(DISPC_OVL_ACCU0(plane), val);
1290} 1271}
1291 1272
1292static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) 1273static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1293{ 1274{
1294 u32 val; 1275 u32 val;
1295 u8 hor_start, hor_end, vert_start, vert_end; 1276 u8 hor_start, hor_end, vert_start, vert_end;
@@ -1303,8 +1284,7 @@ static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu)
1303 dispc_write_reg(DISPC_OVL_ACCU1(plane), val); 1284 dispc_write_reg(DISPC_OVL_ACCU1(plane), val);
1304} 1285}
1305 1286
1306static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu, 1287static void _dispc_set_vid_accu2_0(enum omap_plane plane, int haccu, int vaccu)
1307 int vaccu)
1308{ 1288{
1309 u32 val; 1289 u32 val;
1310 1290
@@ -1312,8 +1292,7 @@ static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu,
1312 dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); 1292 dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val);
1313} 1293}
1314 1294
1315static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu, 1295static void _dispc_set_vid_accu2_1(enum omap_plane plane, int haccu, int vaccu)
1316 int vaccu)
1317{ 1296{
1318 u32 val; 1297 u32 val;
1319 1298
@@ -1321,111 +1300,27 @@ static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu,
1321 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); 1300 dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val);
1322} 1301}
1323 1302
1324static void dispc_ovl_set_scale_param(enum omap_plane plane, 1303static void _dispc_set_scale_param(enum omap_plane plane,
1325 u16 orig_width, u16 orig_height, 1304 u16 orig_width, u16 orig_height,
1326 u16 out_width, u16 out_height, 1305 u16 out_width, u16 out_height,
1327 bool five_taps, u8 rotation, 1306 bool five_taps, u8 rotation,
1328 enum omap_color_component color_comp) 1307 enum omap_color_component color_comp)
1329{ 1308{
1330 int fir_hinc, fir_vinc; 1309 int fir_hinc, fir_vinc;
1310 int hscaleup, vscaleup;
1331 1311
1332 fir_hinc = 1024 * orig_width / out_width; 1312 hscaleup = orig_width <= out_width;
1333 fir_vinc = 1024 * orig_height / out_height; 1313 vscaleup = orig_height <= out_height;
1334
1335 dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
1336 color_comp);
1337 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1338}
1339
1340static void dispc_ovl_set_accu_uv(enum omap_plane plane,
1341 u16 orig_width, u16 orig_height, u16 out_width, u16 out_height,
1342 bool ilace, enum omap_color_mode color_mode, u8 rotation)
1343{
1344 int h_accu2_0, h_accu2_1;
1345 int v_accu2_0, v_accu2_1;
1346 int chroma_hinc, chroma_vinc;
1347 int idx;
1348
1349 struct accu {
1350 s8 h0_m, h0_n;
1351 s8 h1_m, h1_n;
1352 s8 v0_m, v0_n;
1353 s8 v1_m, v1_n;
1354 };
1355
1356 const struct accu *accu_table;
1357 const struct accu *accu_val;
1358
1359 static const struct accu accu_nv12[4] = {
1360 { 0, 1, 0, 1 , -1, 2, 0, 1 },
1361 { 1, 2, -3, 4 , 0, 1, 0, 1 },
1362 { -1, 1, 0, 1 , -1, 2, 0, 1 },
1363 { -1, 2, -1, 2 , -1, 1, 0, 1 },
1364 };
1365
1366 static const struct accu accu_nv12_ilace[4] = {
1367 { 0, 1, 0, 1 , -3, 4, -1, 4 },
1368 { -1, 4, -3, 4 , 0, 1, 0, 1 },
1369 { -1, 1, 0, 1 , -1, 4, -3, 4 },
1370 { -3, 4, -3, 4 , -1, 1, 0, 1 },
1371 };
1372
1373 static const struct accu accu_yuv[4] = {
1374 { 0, 1, 0, 1, 0, 1, 0, 1 },
1375 { 0, 1, 0, 1, 0, 1, 0, 1 },
1376 { -1, 1, 0, 1, 0, 1, 0, 1 },
1377 { 0, 1, 0, 1, -1, 1, 0, 1 },
1378 };
1379
1380 switch (rotation) {
1381 case OMAP_DSS_ROT_0:
1382 idx = 0;
1383 break;
1384 case OMAP_DSS_ROT_90:
1385 idx = 1;
1386 break;
1387 case OMAP_DSS_ROT_180:
1388 idx = 2;
1389 break;
1390 case OMAP_DSS_ROT_270:
1391 idx = 3;
1392 break;
1393 default:
1394 BUG();
1395 return;
1396 }
1397
1398 switch (color_mode) {
1399 case OMAP_DSS_COLOR_NV12:
1400 if (ilace)
1401 accu_table = accu_nv12_ilace;
1402 else
1403 accu_table = accu_nv12;
1404 break;
1405 case OMAP_DSS_COLOR_YUV2:
1406 case OMAP_DSS_COLOR_UYVY:
1407 accu_table = accu_yuv;
1408 break;
1409 default:
1410 BUG();
1411 return;
1412 }
1413
1414 accu_val = &accu_table[idx];
1415 1314
1416 chroma_hinc = 1024 * orig_width / out_width; 1315 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps, color_comp);
1417 chroma_vinc = 1024 * orig_height / out_height;
1418 1316
1419 h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024; 1317 fir_hinc = 1024 * orig_width / out_width;
1420 h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024; 1318 fir_vinc = 1024 * orig_height / out_height;
1421 v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024;
1422 v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024;
1423 1319
1424 dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0); 1320 _dispc_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1425 dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1);
1426} 1321}
1427 1322
1428static void dispc_ovl_set_scaling_common(enum omap_plane plane, 1323static void _dispc_set_scaling_common(enum omap_plane plane,
1429 u16 orig_width, u16 orig_height, 1324 u16 orig_width, u16 orig_height,
1430 u16 out_width, u16 out_height, 1325 u16 out_width, u16 out_height,
1431 bool ilace, bool five_taps, 1326 bool ilace, bool five_taps,
@@ -1436,7 +1331,7 @@ static void dispc_ovl_set_scaling_common(enum omap_plane plane,
1436 int accu1 = 0; 1331 int accu1 = 0;
1437 u32 l; 1332 u32 l;
1438 1333
1439 dispc_ovl_set_scale_param(plane, orig_width, orig_height, 1334 _dispc_set_scale_param(plane, orig_width, orig_height,
1440 out_width, out_height, five_taps, 1335 out_width, out_height, five_taps,
1441 rotation, DISPC_COLOR_COMPONENT_RGB_Y); 1336 rotation, DISPC_COLOR_COMPONENT_RGB_Y);
1442 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); 1337 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
@@ -1475,11 +1370,11 @@ static void dispc_ovl_set_scaling_common(enum omap_plane plane,
1475 } 1370 }
1476 } 1371 }
1477 1372
1478 dispc_ovl_set_vid_accu0(plane, 0, accu0); 1373 _dispc_set_vid_accu0(plane, 0, accu0);
1479 dispc_ovl_set_vid_accu1(plane, 0, accu1); 1374 _dispc_set_vid_accu1(plane, 0, accu1);
1480} 1375}
1481 1376
1482static void dispc_ovl_set_scaling_uv(enum omap_plane plane, 1377static void _dispc_set_scaling_uv(enum omap_plane plane,
1483 u16 orig_width, u16 orig_height, 1378 u16 orig_width, u16 orig_height,
1484 u16 out_width, u16 out_height, 1379 u16 out_width, u16 out_height,
1485 bool ilace, bool five_taps, 1380 bool ilace, bool five_taps,
@@ -1488,7 +1383,6 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1488{ 1383{
1489 int scale_x = out_width != orig_width; 1384 int scale_x = out_width != orig_width;
1490 int scale_y = out_height != orig_height; 1385 int scale_y = out_height != orig_height;
1491 bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
1492 1386
1493 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) 1387 if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
1494 return; 1388 return;
@@ -1496,48 +1390,31 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1496 color_mode != OMAP_DSS_COLOR_UYVY && 1390 color_mode != OMAP_DSS_COLOR_UYVY &&
1497 color_mode != OMAP_DSS_COLOR_NV12)) { 1391 color_mode != OMAP_DSS_COLOR_NV12)) {
1498 /* reset chroma resampling for RGB formats */ 1392 /* reset chroma resampling for RGB formats */
1499 if (plane != OMAP_DSS_WB) 1393 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1500 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1501 return; 1394 return;
1502 } 1395 }
1503
1504 dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width,
1505 out_height, ilace, color_mode, rotation);
1506
1507 switch (color_mode) { 1396 switch (color_mode) {
1508 case OMAP_DSS_COLOR_NV12: 1397 case OMAP_DSS_COLOR_NV12:
1509 if (chroma_upscale) { 1398 /* UV is subsampled by 2 vertically*/
1510 /* UV is subsampled by 2 horizontally and vertically */ 1399 orig_height >>= 1;
1511 orig_height >>= 1; 1400 /* UV is subsampled by 2 horz.*/
1512 orig_width >>= 1; 1401 orig_width >>= 1;
1513 } else {
1514 /* UV is downsampled by 2 horizontally and vertically */
1515 orig_height <<= 1;
1516 orig_width <<= 1;
1517 }
1518
1519 break; 1402 break;
1520 case OMAP_DSS_COLOR_YUV2: 1403 case OMAP_DSS_COLOR_YUV2:
1521 case OMAP_DSS_COLOR_UYVY: 1404 case OMAP_DSS_COLOR_UYVY:
1522 /* For YUV422 with 90/270 rotation, we don't upsample chroma */ 1405 /*For YUV422 with 90/270 rotation,
1406 *we don't upsample chroma
1407 */
1523 if (rotation == OMAP_DSS_ROT_0 || 1408 if (rotation == OMAP_DSS_ROT_0 ||
1524 rotation == OMAP_DSS_ROT_180) { 1409 rotation == OMAP_DSS_ROT_180)
1525 if (chroma_upscale) 1410 /* UV is subsampled by 2 hrz*/
1526 /* UV is subsampled by 2 horizontally */ 1411 orig_width >>= 1;
1527 orig_width >>= 1;
1528 else
1529 /* UV is downsampled by 2 horizontally */
1530 orig_width <<= 1;
1531 }
1532
1533 /* must use FIR for YUV422 if rotated */ 1412 /* must use FIR for YUV422 if rotated */
1534 if (rotation != OMAP_DSS_ROT_0) 1413 if (rotation != OMAP_DSS_ROT_0)
1535 scale_x = scale_y = true; 1414 scale_x = scale_y = true;
1536
1537 break; 1415 break;
1538 default: 1416 default:
1539 BUG(); 1417 BUG();
1540 return;
1541 } 1418 }
1542 1419
1543 if (out_width != orig_width) 1420 if (out_width != orig_width)
@@ -1545,21 +1422,22 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1545 if (out_height != orig_height) 1422 if (out_height != orig_height)
1546 scale_y = true; 1423 scale_y = true;
1547 1424
1548 dispc_ovl_set_scale_param(plane, orig_width, orig_height, 1425 _dispc_set_scale_param(plane, orig_width, orig_height,
1549 out_width, out_height, five_taps, 1426 out_width, out_height, five_taps,
1550 rotation, DISPC_COLOR_COMPONENT_UV); 1427 rotation, DISPC_COLOR_COMPONENT_UV);
1551 1428
1552 if (plane != OMAP_DSS_WB) 1429 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane),
1553 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 1430 (scale_x || scale_y) ? 1 : 0, 8, 8);
1554 (scale_x || scale_y) ? 1 : 0, 8, 8);
1555
1556 /* set H scaling */ 1431 /* set H scaling */
1557 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); 1432 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1558 /* set V scaling */ 1433 /* set V scaling */
1559 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); 1434 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1435
1436 _dispc_set_vid_accu2_0(plane, 0x80, 0);
1437 _dispc_set_vid_accu2_1(plane, 0x80, 0);
1560} 1438}
1561 1439
1562static void dispc_ovl_set_scaling(enum omap_plane plane, 1440static void _dispc_set_scaling(enum omap_plane plane,
1563 u16 orig_width, u16 orig_height, 1441 u16 orig_width, u16 orig_height,
1564 u16 out_width, u16 out_height, 1442 u16 out_width, u16 out_height,
1565 bool ilace, bool five_taps, 1443 bool ilace, bool five_taps,
@@ -1568,14 +1446,14 @@ static void dispc_ovl_set_scaling(enum omap_plane plane,
1568{ 1446{
1569 BUG_ON(plane == OMAP_DSS_GFX); 1447 BUG_ON(plane == OMAP_DSS_GFX);
1570 1448
1571 dispc_ovl_set_scaling_common(plane, 1449 _dispc_set_scaling_common(plane,
1572 orig_width, orig_height, 1450 orig_width, orig_height,
1573 out_width, out_height, 1451 out_width, out_height,
1574 ilace, five_taps, 1452 ilace, five_taps,
1575 fieldmode, color_mode, 1453 fieldmode, color_mode,
1576 rotation); 1454 rotation);
1577 1455
1578 dispc_ovl_set_scaling_uv(plane, 1456 _dispc_set_scaling_uv(plane,
1579 orig_width, orig_height, 1457 orig_width, orig_height,
1580 out_width, out_height, 1458 out_width, out_height,
1581 ilace, five_taps, 1459 ilace, five_taps,
@@ -1583,7 +1461,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane,
1583 rotation); 1461 rotation);
1584} 1462}
1585 1463
1586static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, 1464static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation,
1587 bool mirroring, enum omap_color_mode color_mode) 1465 bool mirroring, enum omap_color_mode color_mode)
1588{ 1466{
1589 bool row_repeat = false; 1467 bool row_repeat = false;
@@ -1667,7 +1545,6 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode)
1667 return 32; 1545 return 32;
1668 default: 1546 default:
1669 BUG(); 1547 BUG();
1670 return 0;
1671 } 1548 }
1672} 1549}
1673 1550
@@ -1681,7 +1558,6 @@ static s32 pixinc(int pixels, u8 ps)
1681 return 1 - (-pixels + 1) * ps; 1558 return 1 - (-pixels + 1) * ps;
1682 else 1559 else
1683 BUG(); 1560 BUG();
1684 return 0;
1685} 1561}
1686 1562
1687static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, 1563static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
@@ -1690,7 +1566,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1690 enum omap_color_mode color_mode, bool fieldmode, 1566 enum omap_color_mode color_mode, bool fieldmode,
1691 unsigned int field_offset, 1567 unsigned int field_offset,
1692 unsigned *offset0, unsigned *offset1, 1568 unsigned *offset0, unsigned *offset1,
1693 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) 1569 s32 *row_inc, s32 *pix_inc)
1694{ 1570{
1695 u8 ps; 1571 u8 ps;
1696 1572
@@ -1736,10 +1612,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1736 else 1612 else
1737 *offset0 = 0; 1613 *offset0 = 0;
1738 1614
1739 *row_inc = pixinc(1 + 1615 *row_inc = pixinc(1 + (screen_width - width) +
1740 (y_predecim * screen_width - x_predecim * width) + 1616 (fieldmode ? screen_width : 0),
1741 (fieldmode ? screen_width : 0), ps); 1617 ps);
1742 *pix_inc = pixinc(x_predecim, ps); 1618 *pix_inc = pixinc(1, ps);
1743 break; 1619 break;
1744 1620
1745 case OMAP_DSS_ROT_0 + 4: 1621 case OMAP_DSS_ROT_0 + 4:
@@ -1757,15 +1633,14 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1757 *offset0 = field_offset * screen_width * ps; 1633 *offset0 = field_offset * screen_width * ps;
1758 else 1634 else
1759 *offset0 = 0; 1635 *offset0 = 0;
1760 *row_inc = pixinc(1 - 1636 *row_inc = pixinc(1 - (screen_width + width) -
1761 (y_predecim * screen_width + x_predecim * width) - 1637 (fieldmode ? screen_width : 0),
1762 (fieldmode ? screen_width : 0), ps); 1638 ps);
1763 *pix_inc = pixinc(x_predecim, ps); 1639 *pix_inc = pixinc(1, ps);
1764 break; 1640 break;
1765 1641
1766 default: 1642 default:
1767 BUG(); 1643 BUG();
1768 return;
1769 } 1644 }
1770} 1645}
1771 1646
@@ -1775,7 +1650,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1775 enum omap_color_mode color_mode, bool fieldmode, 1650 enum omap_color_mode color_mode, bool fieldmode,
1776 unsigned int field_offset, 1651 unsigned int field_offset,
1777 unsigned *offset0, unsigned *offset1, 1652 unsigned *offset0, unsigned *offset1,
1778 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim) 1653 s32 *row_inc, s32 *pix_inc)
1779{ 1654{
1780 u8 ps; 1655 u8 ps;
1781 u16 fbw, fbh; 1656 u16 fbw, fbh;
@@ -1817,14 +1692,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1817 *offset0 = *offset1 + field_offset * screen_width * ps; 1692 *offset0 = *offset1 + field_offset * screen_width * ps;
1818 else 1693 else
1819 *offset0 = *offset1; 1694 *offset0 = *offset1;
1820 *row_inc = pixinc(1 + 1695 *row_inc = pixinc(1 + (screen_width - fbw) +
1821 (y_predecim * screen_width - fbw * x_predecim) + 1696 (fieldmode ? screen_width : 0),
1822 (fieldmode ? screen_width : 0), ps); 1697 ps);
1823 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1698 *pix_inc = pixinc(1, ps);
1824 color_mode == OMAP_DSS_COLOR_UYVY)
1825 *pix_inc = pixinc(x_predecim, 2 * ps);
1826 else
1827 *pix_inc = pixinc(x_predecim, ps);
1828 break; 1699 break;
1829 case OMAP_DSS_ROT_90: 1700 case OMAP_DSS_ROT_90:
1830 *offset1 = screen_width * (fbh - 1) * ps; 1701 *offset1 = screen_width * (fbh - 1) * ps;
@@ -1832,9 +1703,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1832 *offset0 = *offset1 + field_offset * ps; 1703 *offset0 = *offset1 + field_offset * ps;
1833 else 1704 else
1834 *offset0 = *offset1; 1705 *offset0 = *offset1;
1835 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) + 1706 *row_inc = pixinc(screen_width * (fbh - 1) + 1 +
1836 y_predecim + (fieldmode ? 1 : 0), ps); 1707 (fieldmode ? 1 : 0), ps);
1837 *pix_inc = pixinc(-x_predecim * screen_width, ps); 1708 *pix_inc = pixinc(-screen_width, ps);
1838 break; 1709 break;
1839 case OMAP_DSS_ROT_180: 1710 case OMAP_DSS_ROT_180:
1840 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; 1711 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
@@ -1843,13 +1714,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1843 else 1714 else
1844 *offset0 = *offset1; 1715 *offset0 = *offset1;
1845 *row_inc = pixinc(-1 - 1716 *row_inc = pixinc(-1 -
1846 (y_predecim * screen_width - fbw * x_predecim) - 1717 (screen_width - fbw) -
1847 (fieldmode ? screen_width : 0), ps); 1718 (fieldmode ? screen_width : 0),
1848 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1719 ps);
1849 color_mode == OMAP_DSS_COLOR_UYVY) 1720 *pix_inc = pixinc(-1, ps);
1850 *pix_inc = pixinc(-x_predecim, 2 * ps);
1851 else
1852 *pix_inc = pixinc(-x_predecim, ps);
1853 break; 1721 break;
1854 case OMAP_DSS_ROT_270: 1722 case OMAP_DSS_ROT_270:
1855 *offset1 = (fbw - 1) * ps; 1723 *offset1 = (fbw - 1) * ps;
@@ -1857,9 +1725,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1857 *offset0 = *offset1 - field_offset * ps; 1725 *offset0 = *offset1 - field_offset * ps;
1858 else 1726 else
1859 *offset0 = *offset1; 1727 *offset0 = *offset1;
1860 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) - 1728 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 -
1861 y_predecim - (fieldmode ? 1 : 0), ps); 1729 (fieldmode ? 1 : 0), ps);
1862 *pix_inc = pixinc(x_predecim * screen_width, ps); 1730 *pix_inc = pixinc(screen_width, ps);
1863 break; 1731 break;
1864 1732
1865 /* mirroring */ 1733 /* mirroring */
@@ -1869,14 +1737,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1869 *offset0 = *offset1 + field_offset * screen_width * ps; 1737 *offset0 = *offset1 + field_offset * screen_width * ps;
1870 else 1738 else
1871 *offset0 = *offset1; 1739 *offset0 = *offset1;
1872 *row_inc = pixinc(y_predecim * screen_width * 2 - 1 + 1740 *row_inc = pixinc(screen_width * 2 - 1 +
1873 (fieldmode ? screen_width : 0), 1741 (fieldmode ? screen_width : 0),
1874 ps); 1742 ps);
1875 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1743 *pix_inc = pixinc(-1, ps);
1876 color_mode == OMAP_DSS_COLOR_UYVY)
1877 *pix_inc = pixinc(-x_predecim, 2 * ps);
1878 else
1879 *pix_inc = pixinc(-x_predecim, ps);
1880 break; 1744 break;
1881 1745
1882 case OMAP_DSS_ROT_90 + 4: 1746 case OMAP_DSS_ROT_90 + 4:
@@ -1885,10 +1749,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1885 *offset0 = *offset1 + field_offset * ps; 1749 *offset0 = *offset1 + field_offset * ps;
1886 else 1750 else
1887 *offset0 = *offset1; 1751 *offset0 = *offset1;
1888 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) + 1752 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 +
1889 y_predecim + (fieldmode ? 1 : 0), 1753 (fieldmode ? 1 : 0),
1890 ps); 1754 ps);
1891 *pix_inc = pixinc(x_predecim * screen_width, ps); 1755 *pix_inc = pixinc(screen_width, ps);
1892 break; 1756 break;
1893 1757
1894 case OMAP_DSS_ROT_180 + 4: 1758 case OMAP_DSS_ROT_180 + 4:
@@ -1897,14 +1761,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1897 *offset0 = *offset1 - field_offset * screen_width * ps; 1761 *offset0 = *offset1 - field_offset * screen_width * ps;
1898 else 1762 else
1899 *offset0 = *offset1; 1763 *offset0 = *offset1;
1900 *row_inc = pixinc(1 - y_predecim * screen_width * 2 - 1764 *row_inc = pixinc(1 - screen_width * 2 -
1901 (fieldmode ? screen_width : 0), 1765 (fieldmode ? screen_width : 0),
1902 ps); 1766 ps);
1903 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1767 *pix_inc = pixinc(1, ps);
1904 color_mode == OMAP_DSS_COLOR_UYVY)
1905 *pix_inc = pixinc(x_predecim, 2 * ps);
1906 else
1907 *pix_inc = pixinc(x_predecim, ps);
1908 break; 1768 break;
1909 1769
1910 case OMAP_DSS_ROT_270 + 4: 1770 case OMAP_DSS_ROT_270 + 4:
@@ -1913,125 +1773,32 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1913 *offset0 = *offset1 - field_offset * ps; 1773 *offset0 = *offset1 - field_offset * ps;
1914 else 1774 else
1915 *offset0 = *offset1; 1775 *offset0 = *offset1;
1916 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) - 1776 *row_inc = pixinc(screen_width * (fbh - 1) - 1 -
1917 y_predecim - (fieldmode ? 1 : 0), 1777 (fieldmode ? 1 : 0),
1918 ps); 1778 ps);
1919 *pix_inc = pixinc(-x_predecim * screen_width, ps); 1779 *pix_inc = pixinc(-screen_width, ps);
1920 break; 1780 break;
1921 1781
1922 default: 1782 default:
1923 BUG(); 1783 BUG();
1924 return;
1925 }
1926}
1927
1928static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1929 enum omap_color_mode color_mode, bool fieldmode,
1930 unsigned int field_offset, unsigned *offset0, unsigned *offset1,
1931 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1932{
1933 u8 ps;
1934
1935 switch (color_mode) {
1936 case OMAP_DSS_COLOR_CLUT1:
1937 case OMAP_DSS_COLOR_CLUT2:
1938 case OMAP_DSS_COLOR_CLUT4:
1939 case OMAP_DSS_COLOR_CLUT8:
1940 BUG();
1941 return;
1942 default:
1943 ps = color_mode_to_bpp(color_mode) / 8;
1944 break;
1945 } 1784 }
1946
1947 DSSDBG("scrw %d, width %d\n", screen_width, width);
1948
1949 /*
1950 * field 0 = even field = bottom field
1951 * field 1 = odd field = top field
1952 */
1953 *offset1 = 0;
1954 if (field_offset)
1955 *offset0 = *offset1 + field_offset * screen_width * ps;
1956 else
1957 *offset0 = *offset1;
1958 *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) +
1959 (fieldmode ? screen_width : 0), ps);
1960 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1961 color_mode == OMAP_DSS_COLOR_UYVY)
1962 *pix_inc = pixinc(x_predecim, 2 * ps);
1963 else
1964 *pix_inc = pixinc(x_predecim, ps);
1965}
1966
1967/*
1968 * This function is used to avoid synclosts in OMAP3, because of some
1969 * undocumented horizontal position and timing related limitations.
1970 */
1971static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
1972 const struct omap_video_timings *t, u16 pos_x,
1973 u16 width, u16 height, u16 out_width, u16 out_height)
1974{
1975 const int ds = DIV_ROUND_UP(height, out_height);
1976 unsigned long nonactive;
1977 static const u8 limits[3] = { 8, 10, 20 };
1978 u64 val, blank;
1979 int i;
1980
1981 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1982
1983 i = 0;
1984 if (out_height < height)
1985 i++;
1986 if (out_width < width)
1987 i++;
1988 blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
1989 DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
1990 if (blank <= limits[i])
1991 return -EINVAL;
1992
1993 /*
1994 * Pixel data should be prepared before visible display point starts.
1995 * So, atleast DS-2 lines must have already been fetched by DISPC
1996 * during nonactive - pos_x period.
1997 */
1998 val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
1999 DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
2000 val, max(0, ds - 2) * width);
2001 if (val < max(0, ds - 2) * width)
2002 return -EINVAL;
2003
2004 /*
2005 * All lines need to be refilled during the nonactive period of which
2006 * only one line can be loaded during the active period. So, atleast
2007 * DS - 1 lines should be loaded during nonactive period.
2008 */
2009 val = div_u64((u64)nonactive * lclk, pclk);
2010 DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
2011 val, max(0, ds - 1) * width);
2012 if (val < max(0, ds - 1) * width)
2013 return -EINVAL;
2014
2015 return 0;
2016} 1785}
2017 1786
2018static unsigned long calc_core_clk_five_taps(unsigned long pclk, 1787static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
2019 const struct omap_video_timings *mgr_timings, u16 width,
2020 u16 height, u16 out_width, u16 out_height, 1788 u16 height, u16 out_width, u16 out_height,
2021 enum omap_color_mode color_mode) 1789 enum omap_color_mode color_mode)
2022{ 1790{
2023 u32 core_clk = 0; 1791 u32 fclk = 0;
2024 u64 tmp; 1792 /* FIXME venc pclk? */
2025 1793 u64 tmp, pclk = dispc_pclk_rate(channel);
2026 if (height <= out_height && width <= out_width)
2027 return (unsigned long) pclk;
2028 1794
2029 if (height > out_height) { 1795 if (height > out_height) {
2030 unsigned int ppl = mgr_timings->x_res; 1796 /* FIXME get real display PPL */
1797 unsigned int ppl = 800;
2031 1798
2032 tmp = pclk * height * out_width; 1799 tmp = pclk * height * out_width;
2033 do_div(tmp, 2 * out_height * ppl); 1800 do_div(tmp, 2 * out_height * ppl);
2034 core_clk = tmp; 1801 fclk = tmp;
2035 1802
2036 if (height > 2 * out_height) { 1803 if (height > 2 * out_height) {
2037 if (ppl == out_width) 1804 if (ppl == out_width)
@@ -2039,33 +1806,24 @@ static unsigned long calc_core_clk_five_taps(unsigned long pclk,
2039 1806
2040 tmp = pclk * (height - 2 * out_height) * out_width; 1807 tmp = pclk * (height - 2 * out_height) * out_width;
2041 do_div(tmp, 2 * out_height * (ppl - out_width)); 1808 do_div(tmp, 2 * out_height * (ppl - out_width));
2042 core_clk = max_t(u32, core_clk, tmp); 1809 fclk = max(fclk, (u32) tmp);
2043 } 1810 }
2044 } 1811 }
2045 1812
2046 if (width > out_width) { 1813 if (width > out_width) {
2047 tmp = pclk * width; 1814 tmp = pclk * width;
2048 do_div(tmp, out_width); 1815 do_div(tmp, out_width);
2049 core_clk = max_t(u32, core_clk, tmp); 1816 fclk = max(fclk, (u32) tmp);
2050 1817
2051 if (color_mode == OMAP_DSS_COLOR_RGB24U) 1818 if (color_mode == OMAP_DSS_COLOR_RGB24U)
2052 core_clk <<= 1; 1819 fclk <<= 1;
2053 } 1820 }
2054 1821
2055 return core_clk; 1822 return fclk;
2056} 1823}
2057 1824
2058static unsigned long calc_core_clk_24xx(unsigned long pclk, u16 width, 1825static unsigned long calc_fclk(enum omap_channel channel, u16 width,
2059 u16 height, u16 out_width, u16 out_height, bool mem_to_mem) 1826 u16 height, u16 out_width, u16 out_height)
2060{
2061 if (height > out_height && width > out_width)
2062 return pclk * 4;
2063 else
2064 return pclk * 2;
2065}
2066
2067static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
2068 u16 height, u16 out_width, u16 out_height, bool mem_to_mem)
2069{ 1827{
2070 unsigned int hf, vf; 1828 unsigned int hf, vf;
2071 1829
@@ -2082,353 +1840,120 @@ static unsigned long calc_core_clk_34xx(unsigned long pclk, u16 width,
2082 hf = 2; 1840 hf = 2;
2083 else 1841 else
2084 hf = 1; 1842 hf = 1;
1843
2085 if (height > out_height) 1844 if (height > out_height)
2086 vf = 2; 1845 vf = 2;
2087 else 1846 else
2088 vf = 1; 1847 vf = 1;
2089 1848
2090 return pclk * vf * hf; 1849 /* FIXME venc pclk? */
1850 return dispc_pclk_rate(channel) * vf * hf;
2091} 1851}
2092 1852
2093static unsigned long calc_core_clk_44xx(unsigned long pclk, u16 width, 1853int dispc_setup_plane(enum omap_plane plane,
2094 u16 height, u16 out_width, u16 out_height, bool mem_to_mem) 1854 u32 paddr, u16 screen_width,
2095{ 1855 u16 pos_x, u16 pos_y,
2096 /* 1856 u16 width, u16 height,
2097 * If the overlay/writeback is in mem to mem mode, there are no 1857 u16 out_width, u16 out_height,
2098 * downscaling limitations with respect to pixel clock, return 1 as 1858 enum omap_color_mode color_mode,
2099 * required core clock to represent that we have sufficient enough 1859 bool ilace,
2100 * core clock to do maximum downscaling 1860 enum omap_dss_rotation_type rotation_type,
2101 */ 1861 u8 rotation, bool mirror,
2102 if (mem_to_mem) 1862 u8 global_alpha, u8 pre_mult_alpha,
2103 return 1; 1863 enum omap_channel channel, u32 puv_addr)
2104 1864{
2105 if (width > out_width) 1865 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2;
2106 return DIV_ROUND_UP(pclk, out_width) * width; 1866 bool five_taps = 0;
2107 else
2108 return pclk;
2109}
2110
2111static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
2112 const struct omap_video_timings *mgr_timings,
2113 u16 width, u16 height, u16 out_width, u16 out_height,
2114 enum omap_color_mode color_mode, bool *five_taps,
2115 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2116 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2117{
2118 int error;
2119 u16 in_width, in_height;
2120 int min_factor = min(*decim_x, *decim_y);
2121 const int maxsinglelinewidth =
2122 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2123
2124 *five_taps = false;
2125
2126 do {
2127 in_height = DIV_ROUND_UP(height, *decim_y);
2128 in_width = DIV_ROUND_UP(width, *decim_x);
2129 *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
2130 in_height, out_width, out_height, mem_to_mem);
2131 error = (in_width > maxsinglelinewidth || !*core_clk ||
2132 *core_clk > dispc_core_clk_rate());
2133 if (error) {
2134 if (*decim_x == *decim_y) {
2135 *decim_x = min_factor;
2136 ++*decim_y;
2137 } else {
2138 swap(*decim_x, *decim_y);
2139 if (*decim_x < *decim_y)
2140 ++*decim_x;
2141 }
2142 }
2143 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2144
2145 if (in_width > maxsinglelinewidth) {
2146 DSSERR("Cannot scale max input width exceeded");
2147 return -EINVAL;
2148 }
2149 return 0;
2150}
2151
2152static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
2153 const struct omap_video_timings *mgr_timings,
2154 u16 width, u16 height, u16 out_width, u16 out_height,
2155 enum omap_color_mode color_mode, bool *five_taps,
2156 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2157 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2158{
2159 int error;
2160 u16 in_width, in_height;
2161 int min_factor = min(*decim_x, *decim_y);
2162 const int maxsinglelinewidth =
2163 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2164
2165 do {
2166 in_height = DIV_ROUND_UP(height, *decim_y);
2167 in_width = DIV_ROUND_UP(width, *decim_x);
2168 *core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
2169 in_width, in_height, out_width, out_height, color_mode);
2170
2171 error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
2172 pos_x, in_width, in_height, out_width,
2173 out_height);
2174
2175 if (in_width > maxsinglelinewidth)
2176 if (in_height > out_height &&
2177 in_height < out_height * 2)
2178 *five_taps = false;
2179 if (!*five_taps)
2180 *core_clk = dispc.feat->calc_core_clk(pclk, in_width,
2181 in_height, out_width, out_height,
2182 mem_to_mem);
2183
2184 error = (error || in_width > maxsinglelinewidth * 2 ||
2185 (in_width > maxsinglelinewidth && *five_taps) ||
2186 !*core_clk || *core_clk > dispc_core_clk_rate());
2187 if (error) {
2188 if (*decim_x == *decim_y) {
2189 *decim_x = min_factor;
2190 ++*decim_y;
2191 } else {
2192 swap(*decim_x, *decim_y);
2193 if (*decim_x < *decim_y)
2194 ++*decim_x;
2195 }
2196 }
2197 } while (*decim_x <= *x_predecim && *decim_y <= *y_predecim && error);
2198
2199 if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, width,
2200 height, out_width, out_height)){
2201 DSSERR("horizontal timing too tight\n");
2202 return -EINVAL;
2203 }
2204
2205 if (in_width > (maxsinglelinewidth * 2)) {
2206 DSSERR("Cannot setup scaling");
2207 DSSERR("width exceeds maximum width possible");
2208 return -EINVAL;
2209 }
2210
2211 if (in_width > maxsinglelinewidth && *five_taps) {
2212 DSSERR("cannot setup scaling with five taps");
2213 return -EINVAL;
2214 }
2215 return 0;
2216}
2217
2218static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
2219 const struct omap_video_timings *mgr_timings,
2220 u16 width, u16 height, u16 out_width, u16 out_height,
2221 enum omap_color_mode color_mode, bool *five_taps,
2222 int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
2223 u16 pos_x, unsigned long *core_clk, bool mem_to_mem)
2224{
2225 u16 in_width, in_width_max;
2226 int decim_x_min = *decim_x;
2227 u16 in_height = DIV_ROUND_UP(height, *decim_y);
2228 const int maxsinglelinewidth =
2229 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
2230 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2231
2232 if (mem_to_mem) {
2233 in_width_max = out_width * maxdownscale;
2234 } else {
2235 in_width_max = dispc_core_clk_rate() /
2236 DIV_ROUND_UP(pclk, out_width);
2237 }
2238
2239 *decim_x = DIV_ROUND_UP(width, in_width_max);
2240
2241 *decim_x = *decim_x > decim_x_min ? *decim_x : decim_x_min;
2242 if (*decim_x > *x_predecim)
2243 return -EINVAL;
2244
2245 do {
2246 in_width = DIV_ROUND_UP(width, *decim_x);
2247 } while (*decim_x <= *x_predecim &&
2248 in_width > maxsinglelinewidth && ++*decim_x);
2249
2250 if (in_width > maxsinglelinewidth) {
2251 DSSERR("Cannot scale width exceeds max line width");
2252 return -EINVAL;
2253 }
2254
2255 *core_clk = dispc.feat->calc_core_clk(pclk, in_width, in_height,
2256 out_width, out_height, mem_to_mem);
2257 return 0;
2258}
2259
2260static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
2261 enum omap_overlay_caps caps,
2262 const struct omap_video_timings *mgr_timings,
2263 u16 width, u16 height, u16 out_width, u16 out_height,
2264 enum omap_color_mode color_mode, bool *five_taps,
2265 int *x_predecim, int *y_predecim, u16 pos_x,
2266 enum omap_dss_rotation_type rotation_type, bool mem_to_mem)
2267{
2268 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
2269 const int max_decim_limit = 16;
2270 unsigned long core_clk = 0;
2271 int decim_x, decim_y, ret;
2272
2273 if (width == out_width && height == out_height)
2274 return 0;
2275
2276 if ((caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
2277 return -EINVAL;
2278
2279 if (mem_to_mem) {
2280 *x_predecim = *y_predecim = 1;
2281 } else {
2282 *x_predecim = max_decim_limit;
2283 *y_predecim = (rotation_type == OMAP_DSS_ROT_TILER &&
2284 dss_has_feature(FEAT_BURST_2D)) ?
2285 2 : max_decim_limit;
2286 }
2287
2288 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
2289 color_mode == OMAP_DSS_COLOR_CLUT2 ||
2290 color_mode == OMAP_DSS_COLOR_CLUT4 ||
2291 color_mode == OMAP_DSS_COLOR_CLUT8) {
2292 *x_predecim = 1;
2293 *y_predecim = 1;
2294 *five_taps = false;
2295 return 0;
2296 }
2297
2298 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
2299 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
2300
2301 if (decim_x > *x_predecim || out_width > width * 8)
2302 return -EINVAL;
2303
2304 if (decim_y > *y_predecim || out_height > height * 8)
2305 return -EINVAL;
2306
2307 ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
2308 out_width, out_height, color_mode, five_taps,
2309 x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
2310 mem_to_mem);
2311 if (ret)
2312 return ret;
2313
2314 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
2315 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
2316
2317 if (!core_clk || core_clk > dispc_core_clk_rate()) {
2318 DSSERR("failed to set up scaling, "
2319 "required core clk rate = %lu Hz, "
2320 "current core clk rate = %lu Hz\n",
2321 core_clk, dispc_core_clk_rate());
2322 return -EINVAL;
2323 }
2324
2325 *x_predecim = decim_x;
2326 *y_predecim = decim_y;
2327 return 0;
2328}
2329
2330int dispc_ovl_check(enum omap_plane plane, enum omap_channel channel,
2331 const struct omap_overlay_info *oi,
2332 const struct omap_video_timings *timings,
2333 int *x_predecim, int *y_predecim)
2334{
2335 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2336 bool five_taps = true;
2337 bool fieldmode = 0;
2338 u16 in_height = oi->height;
2339 u16 in_width = oi->width;
2340 bool ilace = timings->interlace;
2341 u16 out_width, out_height;
2342 int pos_x = oi->pos_x;
2343 unsigned long pclk = dispc_mgr_pclk_rate(channel);
2344 unsigned long lclk = dispc_mgr_lclk_rate(channel);
2345
2346 out_width = oi->out_width == 0 ? oi->width : oi->out_width;
2347 out_height = oi->out_height == 0 ? oi->height : oi->out_height;
2348
2349 if (ilace && oi->height == out_height)
2350 fieldmode = 1;
2351
2352 if (ilace) {
2353 if (fieldmode)
2354 in_height /= 2;
2355 out_height /= 2;
2356
2357 DSSDBG("adjusting for ilace: height %d, out_height %d\n",
2358 in_height, out_height);
2359 }
2360
2361 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
2362 return -EINVAL;
2363
2364 return dispc_ovl_calc_scaling(pclk, lclk, caps, timings, in_width,
2365 in_height, out_width, out_height, oi->color_mode,
2366 &five_taps, x_predecim, y_predecim, pos_x,
2367 oi->rotation_type, false);
2368}
2369EXPORT_SYMBOL(dispc_ovl_check);
2370
2371static int dispc_ovl_setup_common(enum omap_plane plane,
2372 enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr,
2373 u16 screen_width, int pos_x, int pos_y, u16 width, u16 height,
2374 u16 out_width, u16 out_height, enum omap_color_mode color_mode,
2375 u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
2376 u8 global_alpha, enum omap_dss_rotation_type rotation_type,
2377 bool replication, const struct omap_video_timings *mgr_timings,
2378 bool mem_to_mem)
2379{
2380 bool five_taps = true;
2381 bool fieldmode = 0; 1867 bool fieldmode = 0;
2382 int r, cconv = 0; 1868 int cconv = 0;
2383 unsigned offset0, offset1; 1869 unsigned offset0, offset1;
2384 s32 row_inc; 1870 s32 row_inc;
2385 s32 pix_inc; 1871 s32 pix_inc;
2386 u16 frame_width, frame_height; 1872 u16 frame_height = height;
2387 unsigned int field_offset = 0; 1873 unsigned int field_offset = 0;
2388 u16 in_height = height; 1874
2389 u16 in_width = width; 1875 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> "
2390 int x_predecim = 1, y_predecim = 1; 1876 "%dx%d, ilace %d, cmode %x, rot %d, mir %d chan %d\n",
2391 bool ilace = mgr_timings->interlace; 1877 plane, paddr, screen_width, pos_x, pos_y,
2392 unsigned long pclk = dispc_plane_pclk_rate(plane); 1878 width, height,
2393 unsigned long lclk = dispc_plane_lclk_rate(plane); 1879 out_width, out_height,
1880 ilace, color_mode,
1881 rotation, mirror, channel);
2394 1882
2395 if (paddr == 0) 1883 if (paddr == 0)
2396 return -EINVAL; 1884 return -EINVAL;
2397 1885
2398 out_width = out_width == 0 ? width : out_width;
2399 out_height = out_height == 0 ? height : out_height;
2400
2401 if (ilace && height == out_height) 1886 if (ilace && height == out_height)
2402 fieldmode = 1; 1887 fieldmode = 1;
2403 1888
2404 if (ilace) { 1889 if (ilace) {
2405 if (fieldmode) 1890 if (fieldmode)
2406 in_height /= 2; 1891 height /= 2;
2407 pos_y /= 2; 1892 pos_y /= 2;
2408 out_height /= 2; 1893 out_height /= 2;
2409 1894
2410 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 1895 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
2411 "out_height %d\n", in_height, pos_y, 1896 "out_height %d\n",
2412 out_height); 1897 height, pos_y, out_height);
2413 } 1898 }
2414 1899
2415 if (!dss_feat_color_mode_supported(plane, color_mode)) 1900 if (!dss_feat_color_mode_supported(plane, color_mode))
2416 return -EINVAL; 1901 return -EINVAL;
2417 1902
2418 r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width, 1903 if (plane == OMAP_DSS_GFX) {
2419 in_height, out_width, out_height, color_mode, 1904 if (width != out_width || height != out_height)
2420 &five_taps, &x_predecim, &y_predecim, pos_x, 1905 return -EINVAL;
2421 rotation_type, mem_to_mem); 1906 } else {
2422 if (r) 1907 /* video plane */
2423 return r;
2424 1908
2425 in_width = DIV_ROUND_UP(in_width, x_predecim); 1909 unsigned long fclk = 0;
2426 in_height = DIV_ROUND_UP(in_height, y_predecim);
2427 1910
2428 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1911 if (out_width < width / maxdownscale ||
1912 out_width > width * 8)
1913 return -EINVAL;
1914
1915 if (out_height < height / maxdownscale ||
1916 out_height > height * 8)
1917 return -EINVAL;
1918
1919 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
2429 color_mode == OMAP_DSS_COLOR_UYVY || 1920 color_mode == OMAP_DSS_COLOR_UYVY ||
2430 color_mode == OMAP_DSS_COLOR_NV12) 1921 color_mode == OMAP_DSS_COLOR_NV12)
2431 cconv = 1; 1922 cconv = 1;
1923
1924 /* Must use 5-tap filter? */
1925 five_taps = height > out_height * 2;
1926
1927 if (!five_taps) {
1928 fclk = calc_fclk(channel, width, height, out_width,
1929 out_height);
1930
1931 /* Try 5-tap filter if 3-tap fclk is too high */
1932 if (cpu_is_omap34xx() && height > out_height &&
1933 fclk > dispc_fclk_rate())
1934 five_taps = true;
1935 }
1936
1937 if (width > (2048 >> five_taps)) {
1938 DSSERR("failed to set up scaling, fclk too low\n");
1939 return -EINVAL;
1940 }
1941
1942 if (five_taps)
1943 fclk = calc_fclk_five_taps(channel, width, height,
1944 out_width, out_height, color_mode);
1945
1946 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1947 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1948
1949 if (!fclk || fclk > dispc_fclk_rate()) {
1950 DSSERR("failed to set up scaling, "
1951 "required fclk rate = %lu Hz, "
1952 "current fclk rate = %lu Hz\n",
1953 fclk, dispc_fclk_rate());
1954 return -EINVAL;
1955 }
1956 }
2432 1957
2433 if (ilace && !fieldmode) { 1958 if (ilace && !fieldmode) {
2434 /* 1959 /*
@@ -2438,209 +1963,222 @@ static int dispc_ovl_setup_common(enum omap_plane plane,
2438 * so the integer part must be added to the base address of the 1963 * so the integer part must be added to the base address of the
2439 * bottom field. 1964 * bottom field.
2440 */ 1965 */
2441 if (!in_height || in_height == out_height) 1966 if (!height || height == out_height)
2442 field_offset = 0; 1967 field_offset = 0;
2443 else 1968 else
2444 field_offset = in_height / out_height / 2; 1969 field_offset = height / out_height / 2;
2445 } 1970 }
2446 1971
2447 /* Fields are independent but interleaved in memory. */ 1972 /* Fields are independent but interleaved in memory. */
2448 if (fieldmode) 1973 if (fieldmode)
2449 field_offset = 1; 1974 field_offset = 1;
2450 1975
2451 offset0 = 0; 1976 if (rotation_type == OMAP_DSS_ROT_DMA)
2452 offset1 = 0; 1977 calc_dma_rotation_offset(rotation, mirror,
2453 row_inc = 0; 1978 screen_width, width, frame_height, color_mode,
2454 pix_inc = 0; 1979 fieldmode, field_offset,
2455 1980 &offset0, &offset1, &row_inc, &pix_inc);
2456 if (plane == OMAP_DSS_WB) {
2457 frame_width = out_width;
2458 frame_height = out_height;
2459 } else {
2460 frame_width = in_width;
2461 frame_height = height;
2462 }
2463
2464 if (rotation_type == OMAP_DSS_ROT_TILER)
2465 calc_tiler_rotation_offset(screen_width, frame_width,
2466 color_mode, fieldmode, field_offset,
2467 &offset0, &offset1, &row_inc, &pix_inc,
2468 x_predecim, y_predecim);
2469 else if (rotation_type == OMAP_DSS_ROT_DMA)
2470 calc_dma_rotation_offset(rotation, mirror, screen_width,
2471 frame_width, frame_height,
2472 color_mode, fieldmode, field_offset,
2473 &offset0, &offset1, &row_inc, &pix_inc,
2474 x_predecim, y_predecim);
2475 else 1981 else
2476 calc_vrfb_rotation_offset(rotation, mirror, 1982 calc_vrfb_rotation_offset(rotation, mirror,
2477 screen_width, frame_width, frame_height, 1983 screen_width, width, frame_height, color_mode,
2478 color_mode, fieldmode, field_offset, 1984 fieldmode, field_offset,
2479 &offset0, &offset1, &row_inc, &pix_inc, 1985 &offset0, &offset1, &row_inc, &pix_inc);
2480 x_predecim, y_predecim);
2481 1986
2482 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 1987 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
2483 offset0, offset1, row_inc, pix_inc); 1988 offset0, offset1, row_inc, pix_inc);
2484 1989
2485 dispc_ovl_set_color_mode(plane, color_mode); 1990 _dispc_set_color_mode(plane, color_mode);
2486 1991
2487 dispc_ovl_configure_burst_type(plane, rotation_type); 1992 _dispc_set_plane_ba0(plane, paddr + offset0);
2488 1993 _dispc_set_plane_ba1(plane, paddr + offset1);
2489 dispc_ovl_set_ba0(plane, paddr + offset0);
2490 dispc_ovl_set_ba1(plane, paddr + offset1);
2491 1994
2492 if (OMAP_DSS_COLOR_NV12 == color_mode) { 1995 if (OMAP_DSS_COLOR_NV12 == color_mode) {
2493 dispc_ovl_set_ba0_uv(plane, p_uv_addr + offset0); 1996 _dispc_set_plane_ba0_uv(plane, puv_addr + offset0);
2494 dispc_ovl_set_ba1_uv(plane, p_uv_addr + offset1); 1997 _dispc_set_plane_ba1_uv(plane, puv_addr + offset1);
2495 } 1998 }
2496 1999
2497 dispc_ovl_set_row_inc(plane, row_inc);
2498 dispc_ovl_set_pix_inc(plane, pix_inc);
2499 2000
2500 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, in_width, 2001 _dispc_set_row_inc(plane, row_inc);
2501 in_height, out_width, out_height); 2002 _dispc_set_pix_inc(plane, pix_inc);
2003
2004 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height,
2005 out_width, out_height);
2502 2006
2503 dispc_ovl_set_pos(plane, caps, pos_x, pos_y); 2007 _dispc_set_plane_pos(plane, pos_x, pos_y);
2504 2008
2505 dispc_ovl_set_input_size(plane, in_width, in_height); 2009 _dispc_set_pic_size(plane, width, height);
2506 2010
2507 if (caps & OMAP_DSS_OVL_CAP_SCALE) { 2011 if (plane != OMAP_DSS_GFX) {
2508 dispc_ovl_set_scaling(plane, in_width, in_height, out_width, 2012 _dispc_set_scaling(plane, width, height,
2509 out_height, ilace, five_taps, fieldmode, 2013 out_width, out_height,
2014 ilace, five_taps, fieldmode,
2510 color_mode, rotation); 2015 color_mode, rotation);
2511 dispc_ovl_set_output_size(plane, out_width, out_height); 2016 _dispc_set_vid_size(plane, out_width, out_height);
2512 dispc_ovl_set_vid_color_conv(plane, cconv); 2017 _dispc_set_vid_color_conv(plane, cconv);
2513 } 2018 }
2514 2019
2515 dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode); 2020 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode);
2516
2517 dispc_ovl_set_zorder(plane, caps, zorder);
2518 dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha);
2519 dispc_ovl_setup_global_alpha(plane, caps, global_alpha);
2520 2021
2521 dispc_ovl_enable_replication(plane, caps, replication); 2022 _dispc_set_pre_mult_alpha(plane, pre_mult_alpha);
2023 _dispc_setup_global_alpha(plane, global_alpha);
2522 2024
2523 return 0; 2025 return 0;
2524} 2026}
2525 2027
2526int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, 2028int dispc_enable_plane(enum omap_plane plane, bool enable)
2527 bool replication, const struct omap_video_timings *mgr_timings,
2528 bool mem_to_mem)
2529{ 2029{
2530 int r; 2030 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
2531 enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane);
2532 enum omap_channel channel;
2533 2031
2534 channel = dispc_ovl_get_channel_out(plane); 2032 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0);
2535 2033
2536 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " 2034 return 0;
2537 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n", 2035}
2538 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x,
2539 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2540 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2541 2036
2542 r = dispc_ovl_setup_common(plane, caps, oi->paddr, oi->p_uv_addr, 2037static void dispc_disable_isr(void *data, u32 mask)
2543 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, 2038{
2544 oi->out_width, oi->out_height, oi->color_mode, oi->rotation, 2039 struct completion *compl = data;
2545 oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha, 2040 complete(compl);
2546 oi->rotation_type, replication, mgr_timings, mem_to_mem); 2041}
2547 2042
2548 return r; 2043static void _enable_lcd_out(enum omap_channel channel, bool enable)
2044{
2045 if (channel == OMAP_DSS_CHANNEL_LCD2)
2046 REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
2047 else
2048 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
2549} 2049}
2550EXPORT_SYMBOL(dispc_ovl_setup);
2551 2050
2552int dispc_wb_setup(const struct omap_dss_writeback_info *wi, 2051static void dispc_enable_lcd_out(enum omap_channel channel, bool enable)
2553 bool mem_to_mem, const struct omap_video_timings *mgr_timings)
2554{ 2052{
2053 struct completion frame_done_completion;
2054 bool is_on;
2555 int r; 2055 int r;
2556 u32 l; 2056 u32 irq;
2557 enum omap_plane plane = OMAP_DSS_WB;
2558 const int pos_x = 0, pos_y = 0;
2559 const u8 zorder = 0, global_alpha = 0;
2560 const bool replication = false;
2561 bool truncation;
2562 int in_width = mgr_timings->x_res;
2563 int in_height = mgr_timings->y_res;
2564 enum omap_overlay_caps caps =
2565 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
2566
2567 DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, "
2568 "rot %d, mir %d\n", wi->paddr, wi->p_uv_addr, in_width,
2569 in_height, wi->width, wi->height, wi->color_mode, wi->rotation,
2570 wi->mirror);
2571
2572 r = dispc_ovl_setup_common(plane, caps, wi->paddr, wi->p_uv_addr,
2573 wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
2574 wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
2575 wi->pre_mult_alpha, global_alpha, wi->rotation_type,
2576 replication, mgr_timings, mem_to_mem);
2577
2578 switch (wi->color_mode) {
2579 case OMAP_DSS_COLOR_RGB16:
2580 case OMAP_DSS_COLOR_RGB24P:
2581 case OMAP_DSS_COLOR_ARGB16:
2582 case OMAP_DSS_COLOR_RGBA16:
2583 case OMAP_DSS_COLOR_RGB12U:
2584 case OMAP_DSS_COLOR_ARGB16_1555:
2585 case OMAP_DSS_COLOR_XRGB16_1555:
2586 case OMAP_DSS_COLOR_RGBX16:
2587 truncation = true;
2588 break;
2589 default:
2590 truncation = false;
2591 break;
2592 }
2593 2057
2594 /* setup extra DISPC_WB_ATTRIBUTES */ 2058 /* When we disable LCD output, we need to wait until frame is done.
2595 l = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); 2059 * Otherwise the DSS is still working, and turning off the clocks
2596 l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */ 2060 * prevents DSS from going to OFF mode */
2597 l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */ 2061 is_on = channel == OMAP_DSS_CHANNEL_LCD2 ?
2598 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), l); 2062 REG_GET(DISPC_CONTROL2, 0, 0) :
2063 REG_GET(DISPC_CONTROL, 0, 0);
2599 2064
2600 return r; 2065 irq = channel == OMAP_DSS_CHANNEL_LCD2 ? DISPC_IRQ_FRAMEDONE2 :
2601} 2066 DISPC_IRQ_FRAMEDONE;
2602 2067
2603int dispc_ovl_enable(enum omap_plane plane, bool enable) 2068 if (!enable && is_on) {
2604{ 2069 init_completion(&frame_done_completion);
2605 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
2606 2070
2607 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 0, 0); 2071 r = omap_dispc_register_isr(dispc_disable_isr,
2072 &frame_done_completion, irq);
2608 2073
2609 return 0; 2074 if (r)
2610} 2075 DSSERR("failed to register FRAMEDONE isr\n");
2611EXPORT_SYMBOL(dispc_ovl_enable); 2076 }
2612 2077
2613bool dispc_ovl_enabled(enum omap_plane plane) 2078 _enable_lcd_out(channel, enable);
2614{ 2079
2615 return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); 2080 if (!enable && is_on) {
2081 if (!wait_for_completion_timeout(&frame_done_completion,
2082 msecs_to_jiffies(100)))
2083 DSSERR("timeout waiting for FRAME DONE\n");
2084
2085 r = omap_dispc_unregister_isr(dispc_disable_isr,
2086 &frame_done_completion, irq);
2087
2088 if (r)
2089 DSSERR("failed to unregister FRAMEDONE isr\n");
2090 }
2616} 2091}
2617EXPORT_SYMBOL(dispc_ovl_enabled);
2618 2092
2619void dispc_mgr_enable(enum omap_channel channel, bool enable) 2093static void _enable_digit_out(bool enable)
2620{ 2094{
2621 mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); 2095 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
2622 /* flush posted write */
2623 mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2624} 2096}
2625EXPORT_SYMBOL(dispc_mgr_enable);
2626 2097
2627bool dispc_mgr_is_enabled(enum omap_channel channel) 2098static void dispc_enable_digit_out(bool enable)
2628{ 2099{
2629 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); 2100 struct completion frame_done_completion;
2101 int r;
2102
2103 if (REG_GET(DISPC_CONTROL, 1, 1) == enable)
2104 return;
2105
2106 if (enable) {
2107 unsigned long flags;
2108 /* When we enable digit output, we'll get an extra digit
2109 * sync lost interrupt, that we need to ignore */
2110 spin_lock_irqsave(&dispc.irq_lock, flags);
2111 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
2112 _omap_dispc_set_irqs();
2113 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2114 }
2115
2116 /* When we disable digit output, we need to wait until fields are done.
2117 * Otherwise the DSS is still working, and turning off the clocks
2118 * prevents DSS from going to OFF mode. And when enabling, we need to
2119 * wait for the extra sync losts */
2120 init_completion(&frame_done_completion);
2121
2122 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion,
2123 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
2124 if (r)
2125 DSSERR("failed to register EVSYNC isr\n");
2126
2127 _enable_digit_out(enable);
2128
2129 /* XXX I understand from TRM that we should only wait for the
2130 * current field to complete. But it seems we have to wait
2131 * for both fields */
2132 if (!wait_for_completion_timeout(&frame_done_completion,
2133 msecs_to_jiffies(100)))
2134 DSSERR("timeout waiting for EVSYNC\n");
2135
2136 if (!wait_for_completion_timeout(&frame_done_completion,
2137 msecs_to_jiffies(100)))
2138 DSSERR("timeout waiting for EVSYNC\n");
2139
2140 r = omap_dispc_unregister_isr(dispc_disable_isr,
2141 &frame_done_completion,
2142 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD);
2143 if (r)
2144 DSSERR("failed to unregister EVSYNC isr\n");
2145
2146 if (enable) {
2147 unsigned long flags;
2148 spin_lock_irqsave(&dispc.irq_lock, flags);
2149 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
2150 if (dss_has_feature(FEAT_MGR_LCD2))
2151 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
2152 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT);
2153 _omap_dispc_set_irqs();
2154 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2155 }
2630} 2156}
2631EXPORT_SYMBOL(dispc_mgr_is_enabled);
2632 2157
2633void dispc_wb_enable(bool enable) 2158bool dispc_is_channel_enabled(enum omap_channel channel)
2634{ 2159{
2635 dispc_ovl_enable(OMAP_DSS_WB, enable); 2160 if (channel == OMAP_DSS_CHANNEL_LCD)
2161 return !!REG_GET(DISPC_CONTROL, 0, 0);
2162 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2163 return !!REG_GET(DISPC_CONTROL, 1, 1);
2164 else if (channel == OMAP_DSS_CHANNEL_LCD2)
2165 return !!REG_GET(DISPC_CONTROL2, 0, 0);
2166 else
2167 BUG();
2636} 2168}
2637 2169
2638bool dispc_wb_is_enabled(void) 2170void dispc_enable_channel(enum omap_channel channel, bool enable)
2639{ 2171{
2640 return dispc_ovl_enabled(OMAP_DSS_WB); 2172 if (channel == OMAP_DSS_CHANNEL_LCD ||
2173 channel == OMAP_DSS_CHANNEL_LCD2)
2174 dispc_enable_lcd_out(channel, enable);
2175 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2176 dispc_enable_digit_out(enable);
2177 else
2178 BUG();
2641} 2179}
2642 2180
2643static void dispc_lcd_enable_signal_polarity(bool act_high) 2181void dispc_lcd_enable_signal_polarity(bool act_high)
2644{ 2182{
2645 if (!dss_has_feature(FEAT_LCDENABLEPOL)) 2183 if (!dss_has_feature(FEAT_LCDENABLEPOL))
2646 return; 2184 return;
@@ -2664,15 +2202,38 @@ void dispc_pck_free_enable(bool enable)
2664 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); 2202 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27);
2665} 2203}
2666 2204
2667static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) 2205void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable)
2668{ 2206{
2669 mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); 2207 if (channel == OMAP_DSS_CHANNEL_LCD2)
2208 REG_FLD_MOD(DISPC_CONFIG2, enable ? 1 : 0, 16, 16);
2209 else
2210 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16);
2670} 2211}
2671 2212
2672 2213
2673static void dispc_mgr_set_lcd_type_tft(enum omap_channel channel) 2214void dispc_set_lcd_display_type(enum omap_channel channel,
2215 enum omap_lcd_display_type type)
2674{ 2216{
2675 mgr_fld_write(channel, DISPC_MGR_FLD_STNTFT, 1); 2217 int mode;
2218
2219 switch (type) {
2220 case OMAP_DSS_LCD_DISPLAY_STN:
2221 mode = 0;
2222 break;
2223
2224 case OMAP_DSS_LCD_DISPLAY_TFT:
2225 mode = 1;
2226 break;
2227
2228 default:
2229 BUG();
2230 return;
2231 }
2232
2233 if (channel == OMAP_DSS_CHANNEL_LCD2)
2234 REG_FLD_MOD(DISPC_CONTROL2, mode, 3, 3);
2235 else
2236 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3);
2676} 2237}
2677 2238
2678void dispc_set_loadmode(enum omap_dss_load_mode mode) 2239void dispc_set_loadmode(enum omap_dss_load_mode mode)
@@ -2681,53 +2242,116 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
2681} 2242}
2682 2243
2683 2244
2684static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) 2245void dispc_set_default_color(enum omap_channel channel, u32 color)
2685{ 2246{
2686 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); 2247 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
2687} 2248}
2688 2249
2689static void dispc_mgr_set_trans_key(enum omap_channel ch, 2250u32 dispc_get_default_color(enum omap_channel channel)
2251{
2252 u32 l;
2253
2254 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
2255 channel != OMAP_DSS_CHANNEL_LCD &&
2256 channel != OMAP_DSS_CHANNEL_LCD2);
2257
2258 l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
2259
2260 return l;
2261}
2262
2263void dispc_set_trans_key(enum omap_channel ch,
2690 enum omap_dss_trans_key_type type, 2264 enum omap_dss_trans_key_type type,
2691 u32 trans_key) 2265 u32 trans_key)
2692{ 2266{
2693 mgr_fld_write(ch, DISPC_MGR_FLD_TCKSELECTION, type); 2267 if (ch == OMAP_DSS_CHANNEL_LCD)
2268 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11);
2269 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2270 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13);
2271 else /* OMAP_DSS_CHANNEL_LCD2 */
2272 REG_FLD_MOD(DISPC_CONFIG2, type, 11, 11);
2694 2273
2695 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); 2274 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
2696} 2275}
2697 2276
2698static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) 2277void dispc_get_trans_key(enum omap_channel ch,
2278 enum omap_dss_trans_key_type *type,
2279 u32 *trans_key)
2699{ 2280{
2700 mgr_fld_write(ch, DISPC_MGR_FLD_TCKENABLE, enable); 2281 if (type) {
2282 if (ch == OMAP_DSS_CHANNEL_LCD)
2283 *type = REG_GET(DISPC_CONFIG, 11, 11);
2284 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2285 *type = REG_GET(DISPC_CONFIG, 13, 13);
2286 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2287 *type = REG_GET(DISPC_CONFIG2, 11, 11);
2288 else
2289 BUG();
2290 }
2291
2292 if (trans_key)
2293 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
2701} 2294}
2702 2295
2703static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, 2296void dispc_enable_trans_key(enum omap_channel ch, bool enable)
2704 bool enable) 2297{
2298 if (ch == OMAP_DSS_CHANNEL_LCD)
2299 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
2300 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2301 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12);
2302 else /* OMAP_DSS_CHANNEL_LCD2 */
2303 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
2304}
2305void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
2705{ 2306{
2706 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 2307 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2707 return; 2308 return;
2708 2309
2709 if (ch == OMAP_DSS_CHANNEL_LCD) 2310 if (ch == OMAP_DSS_CHANNEL_LCD)
2710 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); 2311 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18);
2711 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2312 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2712 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2313 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2314 else /* OMAP_DSS_CHANNEL_LCD2 */
2315 REG_FLD_MOD(DISPC_CONFIG2, enable, 18, 18);
2316}
2317bool dispc_alpha_blending_enabled(enum omap_channel ch)
2318{
2319 bool enabled;
2320
2321 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
2322 return false;
2323
2324 if (ch == OMAP_DSS_CHANNEL_LCD)
2325 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2326 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2327 enabled = REG_GET(DISPC_CONFIG, 19, 19);
2328 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2329 enabled = REG_GET(DISPC_CONFIG2, 18, 18);
2330 else
2331 BUG();
2332
2333 return enabled;
2713} 2334}
2714 2335
2715void dispc_mgr_setup(enum omap_channel channel, 2336
2716 const struct omap_overlay_manager_info *info) 2337bool dispc_trans_key_enabled(enum omap_channel ch)
2717{ 2338{
2718 dispc_mgr_set_default_color(channel, info->default_color); 2339 bool enabled;
2719 dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key); 2340
2720 dispc_mgr_enable_trans_key(channel, info->trans_enabled); 2341 if (ch == OMAP_DSS_CHANNEL_LCD)
2721 dispc_mgr_enable_alpha_fixed_zorder(channel, 2342 enabled = REG_GET(DISPC_CONFIG, 10, 10);
2722 info->partial_alpha_enabled); 2343 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2723 if (dss_has_feature(FEAT_CPR)) { 2344 enabled = REG_GET(DISPC_CONFIG, 12, 12);
2724 dispc_mgr_enable_cpr(channel, info->cpr_enable); 2345 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2725 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); 2346 enabled = REG_GET(DISPC_CONFIG2, 10, 10);
2726 } 2347 else
2348 BUG();
2349
2350 return enabled;
2727} 2351}
2728EXPORT_SYMBOL(dispc_mgr_setup);
2729 2352
2730static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) 2353
2354void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2731{ 2355{
2732 int code; 2356 int code;
2733 2357
@@ -2749,211 +2373,153 @@ static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_line
2749 return; 2373 return;
2750 } 2374 }
2751 2375
2752 mgr_fld_write(channel, DISPC_MGR_FLD_TFTDATALINES, code); 2376 if (channel == OMAP_DSS_CHANNEL_LCD2)
2377 REG_FLD_MOD(DISPC_CONTROL2, code, 9, 8);
2378 else
2379 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8);
2753} 2380}
2754 2381
2755static void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode) 2382void dispc_set_parallel_interface_mode(enum omap_channel channel,
2383 enum omap_parallel_interface_mode mode)
2756{ 2384{
2757 u32 l; 2385 u32 l;
2758 int gpout0, gpout1; 2386 int stallmode;
2387 int gpout0 = 1;
2388 int gpout1;
2759 2389
2760 switch (mode) { 2390 switch (mode) {
2761 case DSS_IO_PAD_MODE_RESET: 2391 case OMAP_DSS_PARALLELMODE_BYPASS:
2762 gpout0 = 0; 2392 stallmode = 0;
2763 gpout1 = 0; 2393 gpout1 = 1;
2764 break; 2394 break;
2765 case DSS_IO_PAD_MODE_RFBI: 2395
2766 gpout0 = 1; 2396 case OMAP_DSS_PARALLELMODE_RFBI:
2397 stallmode = 1;
2767 gpout1 = 0; 2398 gpout1 = 0;
2768 break; 2399 break;
2769 case DSS_IO_PAD_MODE_BYPASS: 2400
2770 gpout0 = 1; 2401 case OMAP_DSS_PARALLELMODE_DSI:
2402 stallmode = 1;
2771 gpout1 = 1; 2403 gpout1 = 1;
2772 break; 2404 break;
2405
2773 default: 2406 default:
2774 BUG(); 2407 BUG();
2775 return; 2408 return;
2776 } 2409 }
2777 2410
2778 l = dispc_read_reg(DISPC_CONTROL); 2411 if (channel == OMAP_DSS_CHANNEL_LCD2) {
2779 l = FLD_MOD(l, gpout0, 15, 15); 2412 l = dispc_read_reg(DISPC_CONTROL2);
2780 l = FLD_MOD(l, gpout1, 16, 16); 2413 l = FLD_MOD(l, stallmode, 11, 11);
2781 dispc_write_reg(DISPC_CONTROL, l); 2414 dispc_write_reg(DISPC_CONTROL2, l);
2782} 2415 } else {
2783 2416 l = dispc_read_reg(DISPC_CONTROL);
2784static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) 2417 l = FLD_MOD(l, stallmode, 11, 11);
2785{ 2418 l = FLD_MOD(l, gpout0, 15, 15);
2786 mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable); 2419 l = FLD_MOD(l, gpout1, 16, 16);
2787} 2420 dispc_write_reg(DISPC_CONTROL, l);
2788 2421 }
2789void dispc_mgr_set_lcd_config(enum omap_channel channel,
2790 const struct dss_lcd_mgr_config *config)
2791{
2792 dispc_mgr_set_io_pad_mode(config->io_pad_mode);
2793
2794 dispc_mgr_enable_stallmode(channel, config->stallmode);
2795 dispc_mgr_enable_fifohandcheck(channel, config->fifohandcheck);
2796
2797 dispc_mgr_set_clock_div(channel, &config->clock_info);
2798
2799 dispc_mgr_set_tft_data_lines(channel, config->video_port_width);
2800
2801 dispc_lcd_enable_signal_polarity(config->lcden_sig_polarity);
2802
2803 dispc_mgr_set_lcd_type_tft(channel);
2804}
2805EXPORT_SYMBOL(dispc_mgr_set_lcd_config);
2806
2807static bool _dispc_mgr_size_ok(u16 width, u16 height)
2808{
2809 return width <= dispc.feat->mgr_width_max &&
2810 height <= dispc.feat->mgr_height_max;
2811} 2422}
2812 2423
2813static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2424static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2814 int vsw, int vfp, int vbp) 2425 int vsw, int vfp, int vbp)
2815{ 2426{
2816 if (hsw < 1 || hsw > dispc.feat->sw_max || 2427 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2817 hfp < 1 || hfp > dispc.feat->hp_max || 2428 if (hsw < 1 || hsw > 64 ||
2818 hbp < 1 || hbp > dispc.feat->hp_max || 2429 hfp < 1 || hfp > 256 ||
2819 vsw < 1 || vsw > dispc.feat->sw_max || 2430 hbp < 1 || hbp > 256 ||
2820 vfp < 0 || vfp > dispc.feat->vp_max || 2431 vsw < 1 || vsw > 64 ||
2821 vbp < 0 || vbp > dispc.feat->vp_max) 2432 vfp < 0 || vfp > 255 ||
2822 return false; 2433 vbp < 0 || vbp > 255)
2434 return false;
2435 } else {
2436 if (hsw < 1 || hsw > 256 ||
2437 hfp < 1 || hfp > 4096 ||
2438 hbp < 1 || hbp > 4096 ||
2439 vsw < 1 || vsw > 256 ||
2440 vfp < 0 || vfp > 4095 ||
2441 vbp < 0 || vbp > 4095)
2442 return false;
2443 }
2444
2823 return true; 2445 return true;
2824} 2446}
2825 2447
2826bool dispc_mgr_timings_ok(enum omap_channel channel, 2448bool dispc_lcd_timings_ok(struct omap_video_timings *timings)
2827 const struct omap_video_timings *timings)
2828{ 2449{
2829 bool timings_ok; 2450 return _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2830 2451 timings->hbp, timings->vsw,
2831 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); 2452 timings->vfp, timings->vbp);
2832
2833 if (dss_mgr_is_lcd(channel))
2834 timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw,
2835 timings->hfp, timings->hbp,
2836 timings->vsw, timings->vfp,
2837 timings->vbp);
2838
2839 return timings_ok;
2840} 2453}
2841 2454
2842static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, 2455static void _dispc_set_lcd_timings(enum omap_channel channel, int hsw,
2843 int hfp, int hbp, int vsw, int vfp, int vbp, 2456 int hfp, int hbp, int vsw, int vfp, int vbp)
2844 enum omap_dss_signal_level vsync_level,
2845 enum omap_dss_signal_level hsync_level,
2846 enum omap_dss_signal_edge data_pclk_edge,
2847 enum omap_dss_signal_level de_level,
2848 enum omap_dss_signal_edge sync_pclk_edge)
2849
2850{ 2457{
2851 u32 timing_h, timing_v, l; 2458 u32 timing_h, timing_v;
2852 bool onoff, rf, ipc;
2853 2459
2854 timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) | 2460 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
2855 FLD_VAL(hfp-1, dispc.feat->fp_start, 8) | 2461 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
2856 FLD_VAL(hbp-1, dispc.feat->bp_start, 20); 2462 FLD_VAL(hbp-1, 27, 20);
2857 timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
2858 FLD_VAL(vfp, dispc.feat->fp_start, 8) |
2859 FLD_VAL(vbp, dispc.feat->bp_start, 20);
2860 2463
2861 dispc_write_reg(DISPC_TIMING_H(channel), timing_h); 2464 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) |
2862 dispc_write_reg(DISPC_TIMING_V(channel), timing_v); 2465 FLD_VAL(vbp, 27, 20);
2466 } else {
2467 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) |
2468 FLD_VAL(hbp-1, 31, 20);
2863 2469
2864 switch (data_pclk_edge) { 2470 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) |
2865 case OMAPDSS_DRIVE_SIG_RISING_EDGE: 2471 FLD_VAL(vbp, 31, 20);
2866 ipc = false;
2867 break;
2868 case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
2869 ipc = true;
2870 break;
2871 case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES:
2872 default:
2873 BUG();
2874 } 2472 }
2875 2473
2876 switch (sync_pclk_edge) { 2474 dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
2877 case OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES: 2475 dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
2878 onoff = false;
2879 rf = false;
2880 break;
2881 case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
2882 onoff = true;
2883 rf = false;
2884 break;
2885 case OMAPDSS_DRIVE_SIG_RISING_EDGE:
2886 onoff = true;
2887 rf = true;
2888 break;
2889 default:
2890 BUG();
2891 };
2892
2893 l = dispc_read_reg(DISPC_POL_FREQ(channel));
2894 l |= FLD_VAL(onoff, 17, 17);
2895 l |= FLD_VAL(rf, 16, 16);
2896 l |= FLD_VAL(de_level, 15, 15);
2897 l |= FLD_VAL(ipc, 14, 14);
2898 l |= FLD_VAL(hsync_level, 13, 13);
2899 l |= FLD_VAL(vsync_level, 12, 12);
2900 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2901} 2476}
2902 2477
2903/* change name to mode? */ 2478/* change name to mode? */
2904void dispc_mgr_set_timings(enum omap_channel channel, 2479void dispc_set_lcd_timings(enum omap_channel channel,
2905 const struct omap_video_timings *timings) 2480 struct omap_video_timings *timings)
2906{ 2481{
2907 unsigned xtot, ytot; 2482 unsigned xtot, ytot;
2908 unsigned long ht, vt; 2483 unsigned long ht, vt;
2909 struct omap_video_timings t = *timings;
2910
2911 DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
2912 2484
2913 if (!dispc_mgr_timings_ok(channel, &t)) { 2485 if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
2486 timings->hbp, timings->vsw,
2487 timings->vfp, timings->vbp))
2914 BUG(); 2488 BUG();
2915 return;
2916 }
2917 2489
2918 if (dss_mgr_is_lcd(channel)) { 2490 _dispc_set_lcd_timings(channel, timings->hsw, timings->hfp,
2919 _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw, 2491 timings->hbp, timings->vsw, timings->vfp,
2920 t.vfp, t.vbp, t.vsync_level, t.hsync_level, 2492 timings->vbp);
2921 t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
2922 2493
2923 xtot = t.x_res + t.hfp + t.hsw + t.hbp; 2494 dispc_set_lcd_size(channel, timings->x_res, timings->y_res);
2924 ytot = t.y_res + t.vfp + t.vsw + t.vbp;
2925 2495
2926 ht = (timings->pixel_clock * 1000) / xtot; 2496 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp;
2927 vt = (timings->pixel_clock * 1000) / xtot / ytot; 2497 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp;
2928 2498
2929 DSSDBG("pck %u\n", timings->pixel_clock); 2499 ht = (timings->pixel_clock * 1000) / xtot;
2930 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", 2500 vt = (timings->pixel_clock * 1000) / xtot / ytot;
2931 t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
2932 DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n",
2933 t.vsync_level, t.hsync_level, t.data_pclk_edge,
2934 t.de_level, t.sync_pclk_edge);
2935 2501
2936 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); 2502 DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res,
2937 } else { 2503 timings->y_res);
2938 if (t.interlace == true) 2504 DSSDBG("pck %u\n", timings->pixel_clock);
2939 t.y_res /= 2; 2505 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2940 } 2506 timings->hsw, timings->hfp, timings->hbp,
2507 timings->vsw, timings->vfp, timings->vbp);
2941 2508
2942 dispc_mgr_set_size(channel, t.x_res, t.y_res); 2509 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2943} 2510}
2944EXPORT_SYMBOL(dispc_mgr_set_timings);
2945 2511
2946static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, 2512static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
2947 u16 pck_div) 2513 u16 pck_div)
2948{ 2514{
2949 BUG_ON(lck_div < 1); 2515 BUG_ON(lck_div < 1);
2950 BUG_ON(pck_div < 1); 2516 BUG_ON(pck_div < 2);
2951 2517
2952 dispc_write_reg(DISPC_DIVISORo(channel), 2518 dispc_write_reg(DISPC_DIVISORo(channel),
2953 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); 2519 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0));
2954} 2520}
2955 2521
2956static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, 2522static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div,
2957 int *pck_div) 2523 int *pck_div)
2958{ 2524{
2959 u32 l; 2525 u32 l;
@@ -2969,7 +2535,7 @@ unsigned long dispc_fclk_rate(void)
2969 2535
2970 switch (dss_get_dispc_clk_source()) { 2536 switch (dss_get_dispc_clk_source()) {
2971 case OMAP_DSS_CLK_SRC_FCK: 2537 case OMAP_DSS_CLK_SRC_FCK:
2972 r = dss_get_dispc_clk_rate(); 2538 r = clk_get_rate(dispc.dss_clk);
2973 break; 2539 break;
2974 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 2540 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
2975 dsidev = dsi_get_dsidev_from_id(0); 2541 dsidev = dsi_get_dsidev_from_id(0);
@@ -2981,142 +2547,62 @@ unsigned long dispc_fclk_rate(void)
2981 break; 2547 break;
2982 default: 2548 default:
2983 BUG(); 2549 BUG();
2984 return 0;
2985 } 2550 }
2986 2551
2987 return r; 2552 return r;
2988} 2553}
2989 2554
2990unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) 2555unsigned long dispc_lclk_rate(enum omap_channel channel)
2991{ 2556{
2992 struct platform_device *dsidev; 2557 struct platform_device *dsidev;
2993 int lcd; 2558 int lcd;
2994 unsigned long r; 2559 unsigned long r;
2995 u32 l; 2560 u32 l;
2996 2561
2997 if (dss_mgr_is_lcd(channel)) { 2562 l = dispc_read_reg(DISPC_DIVISORo(channel));
2998 l = dispc_read_reg(DISPC_DIVISORo(channel));
2999
3000 lcd = FLD_GET(l, 23, 16);
3001
3002 switch (dss_get_lcd_clk_source(channel)) {
3003 case OMAP_DSS_CLK_SRC_FCK:
3004 r = dss_get_dispc_clk_rate();
3005 break;
3006 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3007 dsidev = dsi_get_dsidev_from_id(0);
3008 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3009 break;
3010 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3011 dsidev = dsi_get_dsidev_from_id(1);
3012 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3013 break;
3014 default:
3015 BUG();
3016 return 0;
3017 }
3018
3019 return r / lcd;
3020 } else {
3021 return dispc_fclk_rate();
3022 }
3023}
3024
3025unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
3026{
3027 unsigned long r;
3028
3029 if (dss_mgr_is_lcd(channel)) {
3030 int pcd;
3031 u32 l;
3032
3033 l = dispc_read_reg(DISPC_DIVISORo(channel));
3034
3035 pcd = FLD_GET(l, 7, 0);
3036
3037 r = dispc_mgr_lclk_rate(channel);
3038
3039 return r / pcd;
3040 } else {
3041 enum dss_hdmi_venc_clk_source_select source;
3042 2563
3043 source = dss_get_hdmi_venc_clk_source(); 2564 lcd = FLD_GET(l, 23, 16);
3044 2565
3045 switch (source) { 2566 switch (dss_get_lcd_clk_source(channel)) {
3046 case DSS_VENC_TV_CLK: 2567 case OMAP_DSS_CLK_SRC_FCK:
3047 return venc_get_pixel_clock(); 2568 r = clk_get_rate(dispc.dss_clk);
3048 case DSS_HDMI_M_PCLK: 2569 break;
3049 return hdmi_get_pixel_clock(); 2570 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3050 default: 2571 dsidev = dsi_get_dsidev_from_id(0);
3051 BUG(); 2572 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
3052 return 0; 2573 break;
3053 } 2574 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
2575 dsidev = dsi_get_dsidev_from_id(1);
2576 r = dsi_get_pll_hsdiv_dispc_rate(dsidev);
2577 break;
2578 default:
2579 BUG();
3054 } 2580 }
3055}
3056
3057unsigned long dispc_core_clk_rate(void)
3058{
3059 int lcd;
3060 unsigned long fclk = dispc_fclk_rate();
3061
3062 if (dss_has_feature(FEAT_CORE_CLK_DIV))
3063 lcd = REG_GET(DISPC_DIVISOR, 23, 16);
3064 else
3065 lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
3066
3067 return fclk / lcd;
3068}
3069
3070static unsigned long dispc_plane_pclk_rate(enum omap_plane plane)
3071{
3072 enum omap_channel channel;
3073
3074 if (plane == OMAP_DSS_WB)
3075 return 0;
3076 2581
3077 channel = dispc_ovl_get_channel_out(plane); 2582 return r / lcd;
3078
3079 return dispc_mgr_pclk_rate(channel);
3080} 2583}
3081 2584
3082static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) 2585unsigned long dispc_pclk_rate(enum omap_channel channel)
3083{ 2586{
3084 enum omap_channel channel; 2587 int pcd;
3085 2588 unsigned long r;
3086 if (plane == OMAP_DSS_WB) 2589 u32 l;
3087 return 0;
3088
3089 channel = dispc_ovl_get_channel_out(plane);
3090
3091 return dispc_mgr_lclk_rate(channel);
3092}
3093
3094static void dispc_dump_clocks_channel(struct seq_file *s, enum omap_channel channel)
3095{
3096 int lcd, pcd;
3097 enum omap_dss_clk_source lcd_clk_src;
3098
3099 seq_printf(s, "- %s -\n", mgr_desc[channel].name);
3100 2590
3101 lcd_clk_src = dss_get_lcd_clk_source(channel); 2591 l = dispc_read_reg(DISPC_DIVISORo(channel));
3102 2592
3103 seq_printf(s, "%s clk source = %s (%s)\n", mgr_desc[channel].name, 2593 pcd = FLD_GET(l, 7, 0);
3104 dss_get_generic_clk_source_name(lcd_clk_src),
3105 dss_feat_get_clk_source_name(lcd_clk_src));
3106 2594
3107 dispc_mgr_get_lcd_divisor(channel, &lcd, &pcd); 2595 r = dispc_lclk_rate(channel);
3108 2596
3109 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", 2597 return r / pcd;
3110 dispc_mgr_lclk_rate(channel), lcd);
3111 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
3112 dispc_mgr_pclk_rate(channel), pcd);
3113} 2598}
3114 2599
3115void dispc_dump_clocks(struct seq_file *s) 2600void dispc_dump_clocks(struct seq_file *s)
3116{ 2601{
3117 int lcd; 2602 int lcd, pcd;
3118 u32 l; 2603 u32 l;
3119 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); 2604 enum omap_dss_clk_source dispc_clk_src = dss_get_dispc_clk_source();
2605 enum omap_dss_clk_source lcd_clk_src;
3120 2606
3121 if (dispc_runtime_get()) 2607 if (dispc_runtime_get())
3122 return; 2608 return;
@@ -3137,40 +2623,95 @@ void dispc_dump_clocks(struct seq_file *s)
3137 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", 2623 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
3138 (dispc_fclk_rate()/lcd), lcd); 2624 (dispc_fclk_rate()/lcd), lcd);
3139 } 2625 }
2626 seq_printf(s, "- LCD1 -\n");
3140 2627
3141 dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD); 2628 lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD);
3142 2629
3143 if (dss_has_feature(FEAT_MGR_LCD2)) 2630 seq_printf(s, "lcd1_clk source = %s (%s)\n",
3144 dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD2); 2631 dss_get_generic_clk_source_name(lcd_clk_src),
3145 if (dss_has_feature(FEAT_MGR_LCD3)) 2632 dss_feat_get_clk_source_name(lcd_clk_src));
3146 dispc_dump_clocks_channel(s, OMAP_DSS_CHANNEL_LCD3); 2633
2634 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd);
2635
2636 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2637 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD), lcd);
2638 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2639 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD), pcd);
2640 if (dss_has_feature(FEAT_MGR_LCD2)) {
2641 seq_printf(s, "- LCD2 -\n");
2642
2643 lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2);
2644
2645 seq_printf(s, "lcd2_clk source = %s (%s)\n",
2646 dss_get_generic_clk_source_name(lcd_clk_src),
2647 dss_feat_get_clk_source_name(lcd_clk_src));
2648
2649 dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd);
2650
2651 seq_printf(s, "lck\t\t%-16lulck div\t%u\n",
2652 dispc_lclk_rate(OMAP_DSS_CHANNEL_LCD2), lcd);
2653 seq_printf(s, "pck\t\t%-16lupck div\t%u\n",
2654 dispc_pclk_rate(OMAP_DSS_CHANNEL_LCD2), pcd);
2655 }
3147 2656
3148 dispc_runtime_put(); 2657 dispc_runtime_put();
3149} 2658}
3150 2659
3151static void dispc_dump_regs(struct seq_file *s) 2660#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3152{ 2661void dispc_dump_irqs(struct seq_file *s)
3153 int i, j; 2662{
3154 const char *mgr_names[] = { 2663 unsigned long flags;
3155 [OMAP_DSS_CHANNEL_LCD] = "LCD", 2664 struct dispc_irq_stats stats;
3156 [OMAP_DSS_CHANNEL_DIGIT] = "TV", 2665
3157 [OMAP_DSS_CHANNEL_LCD2] = "LCD2", 2666 spin_lock_irqsave(&dispc.irq_stats_lock, flags);
3158 [OMAP_DSS_CHANNEL_LCD3] = "LCD3", 2667
3159 }; 2668 stats = dispc.irq_stats;
3160 const char *ovl_names[] = { 2669 memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
3161 [OMAP_DSS_GFX] = "GFX", 2670 dispc.irq_stats.last_reset = jiffies;
3162 [OMAP_DSS_VIDEO1] = "VID1", 2671
3163 [OMAP_DSS_VIDEO2] = "VID2", 2672 spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
3164 [OMAP_DSS_VIDEO3] = "VID3", 2673
3165 }; 2674 seq_printf(s, "period %u ms\n",
3166 const char **p_names; 2675 jiffies_to_msecs(jiffies - stats.last_reset));
2676
2677 seq_printf(s, "irqs %d\n", stats.irq_count);
2678#define PIS(x) \
2679 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
2680
2681 PIS(FRAMEDONE);
2682 PIS(VSYNC);
2683 PIS(EVSYNC_EVEN);
2684 PIS(EVSYNC_ODD);
2685 PIS(ACBIAS_COUNT_STAT);
2686 PIS(PROG_LINE_NUM);
2687 PIS(GFX_FIFO_UNDERFLOW);
2688 PIS(GFX_END_WIN);
2689 PIS(PAL_GAMMA_MASK);
2690 PIS(OCP_ERR);
2691 PIS(VID1_FIFO_UNDERFLOW);
2692 PIS(VID1_END_WIN);
2693 PIS(VID2_FIFO_UNDERFLOW);
2694 PIS(VID2_END_WIN);
2695 PIS(SYNC_LOST);
2696 PIS(SYNC_LOST_DIGIT);
2697 PIS(WAKEUP);
2698 if (dss_has_feature(FEAT_MGR_LCD2)) {
2699 PIS(FRAMEDONE2);
2700 PIS(VSYNC2);
2701 PIS(ACBIAS_COUNT_STAT2);
2702 PIS(SYNC_LOST2);
2703 }
2704#undef PIS
2705}
2706#endif
3167 2707
2708void dispc_dump_regs(struct seq_file *s)
2709{
3168#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r)) 2710#define DUMPREG(r) seq_printf(s, "%-50s %08x\n", #r, dispc_read_reg(r))
3169 2711
3170 if (dispc_runtime_get()) 2712 if (dispc_runtime_get())
3171 return; 2713 return;
3172 2714
3173 /* DISPC common registers */
3174 DUMPREG(DISPC_REVISION); 2715 DUMPREG(DISPC_REVISION);
3175 DUMPREG(DISPC_SYSCONFIG); 2716 DUMPREG(DISPC_SYSCONFIG);
3176 DUMPREG(DISPC_SYSSTATUS); 2717 DUMPREG(DISPC_SYSSTATUS);
@@ -3179,152 +2720,286 @@ static void dispc_dump_regs(struct seq_file *s)
3179 DUMPREG(DISPC_CONTROL); 2720 DUMPREG(DISPC_CONTROL);
3180 DUMPREG(DISPC_CONFIG); 2721 DUMPREG(DISPC_CONFIG);
3181 DUMPREG(DISPC_CAPABLE); 2722 DUMPREG(DISPC_CAPABLE);
2723 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD));
2724 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_DIGIT));
2725 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD));
2726 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_DIGIT));
3182 DUMPREG(DISPC_LINE_STATUS); 2727 DUMPREG(DISPC_LINE_STATUS);
3183 DUMPREG(DISPC_LINE_NUMBER); 2728 DUMPREG(DISPC_LINE_NUMBER);
3184 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER) || 2729 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD));
3185 dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) 2730 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD));
2731 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD));
2732 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD));
2733 if (dss_has_feature(FEAT_GLOBAL_ALPHA))
3186 DUMPREG(DISPC_GLOBAL_ALPHA); 2734 DUMPREG(DISPC_GLOBAL_ALPHA);
2735 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT));
2736 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD));
3187 if (dss_has_feature(FEAT_MGR_LCD2)) { 2737 if (dss_has_feature(FEAT_MGR_LCD2)) {
3188 DUMPREG(DISPC_CONTROL2); 2738 DUMPREG(DISPC_CONTROL2);
3189 DUMPREG(DISPC_CONFIG2); 2739 DUMPREG(DISPC_CONFIG2);
3190 } 2740 DUMPREG(DISPC_DEFAULT_COLOR(OMAP_DSS_CHANNEL_LCD2));
3191 if (dss_has_feature(FEAT_MGR_LCD3)) { 2741 DUMPREG(DISPC_TRANS_COLOR(OMAP_DSS_CHANNEL_LCD2));
3192 DUMPREG(DISPC_CONTROL3); 2742 DUMPREG(DISPC_TIMING_H(OMAP_DSS_CHANNEL_LCD2));
3193 DUMPREG(DISPC_CONFIG3); 2743 DUMPREG(DISPC_TIMING_V(OMAP_DSS_CHANNEL_LCD2));
3194 } 2744 DUMPREG(DISPC_POL_FREQ(OMAP_DSS_CHANNEL_LCD2));
3195 2745 DUMPREG(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD2));
3196#undef DUMPREG 2746 DUMPREG(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_LCD2));
3197 2747 }
3198#define DISPC_REG(i, name) name(i) 2748
3199#define DUMPREG(i, r) seq_printf(s, "%s(%s)%*s %08x\n", #r, p_names[i], \ 2749 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_GFX));
3200 (int)(48 - strlen(#r) - strlen(p_names[i])), " ", \ 2750 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_GFX));
3201 dispc_read_reg(DISPC_REG(i, r))) 2751 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_GFX));
3202 2752 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_GFX));
3203 p_names = mgr_names; 2753 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_GFX));
3204 2754 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_GFX));
3205 /* DISPC channel specific registers */ 2755 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_GFX));
3206 for (i = 0; i < dss_feat_get_num_mgrs(); i++) { 2756 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_GFX));
3207 DUMPREG(i, DISPC_DEFAULT_COLOR); 2757 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_GFX));
3208 DUMPREG(i, DISPC_TRANS_COLOR); 2758 DUMPREG(DISPC_OVL_WINDOW_SKIP(OMAP_DSS_GFX));
3209 DUMPREG(i, DISPC_SIZE_MGR); 2759 DUMPREG(DISPC_OVL_TABLE_BA(OMAP_DSS_GFX));
2760
2761 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD));
2762 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD));
2763 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD));
3210 2764
3211 if (i == OMAP_DSS_CHANNEL_DIGIT) 2765 if (dss_has_feature(FEAT_CPR)) {
3212 continue; 2766 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD));
3213 2767 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD));
3214 DUMPREG(i, DISPC_DEFAULT_COLOR); 2768 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD));
3215 DUMPREG(i, DISPC_TRANS_COLOR); 2769 }
3216 DUMPREG(i, DISPC_TIMING_H); 2770 if (dss_has_feature(FEAT_MGR_LCD2)) {
3217 DUMPREG(i, DISPC_TIMING_V); 2771 DUMPREG(DISPC_DATA_CYCLE1(OMAP_DSS_CHANNEL_LCD2));
3218 DUMPREG(i, DISPC_POL_FREQ); 2772 DUMPREG(DISPC_DATA_CYCLE2(OMAP_DSS_CHANNEL_LCD2));
3219 DUMPREG(i, DISPC_DIVISORo); 2773 DUMPREG(DISPC_DATA_CYCLE3(OMAP_DSS_CHANNEL_LCD2));
3220 DUMPREG(i, DISPC_SIZE_MGR);
3221
3222 DUMPREG(i, DISPC_DATA_CYCLE1);
3223 DUMPREG(i, DISPC_DATA_CYCLE2);
3224 DUMPREG(i, DISPC_DATA_CYCLE3);
3225 2774
3226 if (dss_has_feature(FEAT_CPR)) { 2775 if (dss_has_feature(FEAT_CPR)) {
3227 DUMPREG(i, DISPC_CPR_COEF_R); 2776 DUMPREG(DISPC_CPR_COEF_R(OMAP_DSS_CHANNEL_LCD2));
3228 DUMPREG(i, DISPC_CPR_COEF_G); 2777 DUMPREG(DISPC_CPR_COEF_G(OMAP_DSS_CHANNEL_LCD2));
3229 DUMPREG(i, DISPC_CPR_COEF_B); 2778 DUMPREG(DISPC_CPR_COEF_B(OMAP_DSS_CHANNEL_LCD2));
3230 } 2779 }
3231 } 2780 }
3232 2781
3233 p_names = ovl_names; 2782 if (dss_has_feature(FEAT_PRELOAD))
3234 2783 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_GFX));
3235 for (i = 0; i < dss_feat_get_num_ovls(); i++) { 2784
3236 DUMPREG(i, DISPC_OVL_BA0); 2785 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO1));
3237 DUMPREG(i, DISPC_OVL_BA1); 2786 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO1));
3238 DUMPREG(i, DISPC_OVL_POSITION); 2787 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO1));
3239 DUMPREG(i, DISPC_OVL_SIZE); 2788 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO1));
3240 DUMPREG(i, DISPC_OVL_ATTRIBUTES); 2789 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO1));
3241 DUMPREG(i, DISPC_OVL_FIFO_THRESHOLD); 2790 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO1));
3242 DUMPREG(i, DISPC_OVL_FIFO_SIZE_STATUS); 2791 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO1));
3243 DUMPREG(i, DISPC_OVL_ROW_INC); 2792 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO1));
3244 DUMPREG(i, DISPC_OVL_PIXEL_INC); 2793 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO1));
3245 if (dss_has_feature(FEAT_PRELOAD)) 2794 DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO1));
3246 DUMPREG(i, DISPC_OVL_PRELOAD); 2795 DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO1));
3247 2796 DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO1));
3248 if (i == OMAP_DSS_GFX) { 2797 DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO1));
3249 DUMPREG(i, DISPC_OVL_WINDOW_SKIP); 2798
3250 DUMPREG(i, DISPC_OVL_TABLE_BA); 2799 DUMPREG(DISPC_OVL_BA0(OMAP_DSS_VIDEO2));
3251 continue; 2800 DUMPREG(DISPC_OVL_BA1(OMAP_DSS_VIDEO2));
3252 } 2801 DUMPREG(DISPC_OVL_POSITION(OMAP_DSS_VIDEO2));
3253 2802 DUMPREG(DISPC_OVL_SIZE(OMAP_DSS_VIDEO2));
3254 DUMPREG(i, DISPC_OVL_FIR); 2803 DUMPREG(DISPC_OVL_ATTRIBUTES(OMAP_DSS_VIDEO2));
3255 DUMPREG(i, DISPC_OVL_PICTURE_SIZE); 2804 DUMPREG(DISPC_OVL_FIFO_THRESHOLD(OMAP_DSS_VIDEO2));
3256 DUMPREG(i, DISPC_OVL_ACCU0); 2805 DUMPREG(DISPC_OVL_FIFO_SIZE_STATUS(OMAP_DSS_VIDEO2));
3257 DUMPREG(i, DISPC_OVL_ACCU1); 2806 DUMPREG(DISPC_OVL_ROW_INC(OMAP_DSS_VIDEO2));
3258 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) { 2807 DUMPREG(DISPC_OVL_PIXEL_INC(OMAP_DSS_VIDEO2));
3259 DUMPREG(i, DISPC_OVL_BA0_UV); 2808 DUMPREG(DISPC_OVL_FIR(OMAP_DSS_VIDEO2));
3260 DUMPREG(i, DISPC_OVL_BA1_UV); 2809 DUMPREG(DISPC_OVL_PICTURE_SIZE(OMAP_DSS_VIDEO2));
3261 DUMPREG(i, DISPC_OVL_FIR2); 2810 DUMPREG(DISPC_OVL_ACCU0(OMAP_DSS_VIDEO2));
3262 DUMPREG(i, DISPC_OVL_ACCU2_0); 2811 DUMPREG(DISPC_OVL_ACCU1(OMAP_DSS_VIDEO2));
3263 DUMPREG(i, DISPC_OVL_ACCU2_1); 2812
3264 } 2813 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 0));
3265 if (dss_has_feature(FEAT_ATTR2)) 2814 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 1));
3266 DUMPREG(i, DISPC_OVL_ATTRIBUTES2); 2815 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 2));
3267 if (dss_has_feature(FEAT_PRELOAD)) 2816 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 3));
3268 DUMPREG(i, DISPC_OVL_PRELOAD); 2817 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 4));
2818 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 5));
2819 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 6));
2820 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO1, 7));
2821 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 0));
2822 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 1));
2823 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 2));
2824 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 3));
2825 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 4));
2826 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 5));
2827 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 6));
2828 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO1, 7));
2829 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 0));
2830 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 1));
2831 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 2));
2832 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 3));
2833 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO1, 4));
2834 if (dss_has_feature(FEAT_FIR_COEF_V)) {
2835 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 0));
2836 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 1));
2837 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 2));
2838 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 3));
2839 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 4));
2840 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 5));
2841 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 6));
2842 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO1, 7));
2843 }
2844
2845 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2846 DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO1));
2847 DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO1));
2848 DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO1));
2849 DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO1));
2850 DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO1));
2851
2852 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 0));
2853 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 1));
2854 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 2));
2855 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 3));
2856 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 4));
2857 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 5));
2858 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 6));
2859 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO1, 7));
2860
2861 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 0));
2862 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 1));
2863 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 2));
2864 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 3));
2865 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 4));
2866 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 5));
2867 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 6));
2868 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO1, 7));
2869
2870 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 0));
2871 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 1));
2872 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 2));
2873 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 3));
2874 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 4));
2875 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 5));
2876 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 6));
2877 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO1, 7));
2878 }
2879 if (dss_has_feature(FEAT_ATTR2))
2880 DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO1));
2881
2882
2883 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 0));
2884 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 1));
2885 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 2));
2886 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 3));
2887 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 4));
2888 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 5));
2889 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 6));
2890 DUMPREG(DISPC_OVL_FIR_COEF_H(OMAP_DSS_VIDEO2, 7));
2891 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 0));
2892 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 1));
2893 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 2));
2894 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 3));
2895 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 4));
2896 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 5));
2897 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 6));
2898 DUMPREG(DISPC_OVL_FIR_COEF_HV(OMAP_DSS_VIDEO2, 7));
2899 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 0));
2900 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 1));
2901 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 2));
2902 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 3));
2903 DUMPREG(DISPC_OVL_CONV_COEF(OMAP_DSS_VIDEO2, 4));
2904
2905 if (dss_has_feature(FEAT_FIR_COEF_V)) {
2906 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 0));
2907 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 1));
2908 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 2));
2909 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 3));
2910 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 4));
2911 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 5));
2912 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 6));
2913 DUMPREG(DISPC_OVL_FIR_COEF_V(OMAP_DSS_VIDEO2, 7));
2914 }
2915
2916 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
2917 DUMPREG(DISPC_OVL_BA0_UV(OMAP_DSS_VIDEO2));
2918 DUMPREG(DISPC_OVL_BA1_UV(OMAP_DSS_VIDEO2));
2919 DUMPREG(DISPC_OVL_FIR2(OMAP_DSS_VIDEO2));
2920 DUMPREG(DISPC_OVL_ACCU2_0(OMAP_DSS_VIDEO2));
2921 DUMPREG(DISPC_OVL_ACCU2_1(OMAP_DSS_VIDEO2));
2922
2923 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 0));
2924 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 1));
2925 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 2));
2926 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 3));
2927 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 4));
2928 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 5));
2929 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 6));
2930 DUMPREG(DISPC_OVL_FIR_COEF_H2(OMAP_DSS_VIDEO2, 7));
2931
2932 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 0));
2933 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 1));
2934 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 2));
2935 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 3));
2936 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 4));
2937 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 5));
2938 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 6));
2939 DUMPREG(DISPC_OVL_FIR_COEF_HV2(OMAP_DSS_VIDEO2, 7));
2940
2941 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 0));
2942 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 1));
2943 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 2));
2944 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 3));
2945 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 4));
2946 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 5));
2947 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 6));
2948 DUMPREG(DISPC_OVL_FIR_COEF_V2(OMAP_DSS_VIDEO2, 7));
2949 }
2950 if (dss_has_feature(FEAT_ATTR2))
2951 DUMPREG(DISPC_OVL_ATTRIBUTES2(OMAP_DSS_VIDEO2));
2952
2953 if (dss_has_feature(FEAT_PRELOAD)) {
2954 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO1));
2955 DUMPREG(DISPC_OVL_PRELOAD(OMAP_DSS_VIDEO2));
3269 } 2956 }
3270 2957
3271#undef DISPC_REG 2958 dispc_runtime_put();
3272#undef DUMPREG 2959#undef DUMPREG
2960}
3273 2961
3274#define DISPC_REG(plane, name, i) name(plane, i) 2962static void _dispc_set_pol_freq(enum omap_channel channel, bool onoff, bool rf,
3275#define DUMPREG(plane, name, i) \ 2963 bool ieo, bool ipc, bool ihs, bool ivs, u8 acbi, u8 acb)
3276 seq_printf(s, "%s_%d(%s)%*s %08x\n", #name, i, p_names[plane], \ 2964{
3277 (int)(46 - strlen(#name) - strlen(p_names[plane])), " ", \ 2965 u32 l = 0;
3278 dispc_read_reg(DISPC_REG(plane, name, i)))
3279
3280 /* Video pipeline coefficient registers */
3281
3282 /* start from OMAP_DSS_VIDEO1 */
3283 for (i = 1; i < dss_feat_get_num_ovls(); i++) {
3284 for (j = 0; j < 8; j++)
3285 DUMPREG(i, DISPC_OVL_FIR_COEF_H, j);
3286
3287 for (j = 0; j < 8; j++)
3288 DUMPREG(i, DISPC_OVL_FIR_COEF_HV, j);
3289
3290 for (j = 0; j < 5; j++)
3291 DUMPREG(i, DISPC_OVL_CONV_COEF, j);
3292
3293 if (dss_has_feature(FEAT_FIR_COEF_V)) {
3294 for (j = 0; j < 8; j++)
3295 DUMPREG(i, DISPC_OVL_FIR_COEF_V, j);
3296 }
3297
3298 if (dss_has_feature(FEAT_HANDLE_UV_SEPARATE)) {
3299 for (j = 0; j < 8; j++)
3300 DUMPREG(i, DISPC_OVL_FIR_COEF_H2, j);
3301 2966
3302 for (j = 0; j < 8; j++) 2967 DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n",
3303 DUMPREG(i, DISPC_OVL_FIR_COEF_HV2, j); 2968 onoff, rf, ieo, ipc, ihs, ivs, acbi, acb);
3304 2969
3305 for (j = 0; j < 8; j++) 2970 l |= FLD_VAL(onoff, 17, 17);
3306 DUMPREG(i, DISPC_OVL_FIR_COEF_V2, j); 2971 l |= FLD_VAL(rf, 16, 16);
3307 } 2972 l |= FLD_VAL(ieo, 15, 15);
3308 } 2973 l |= FLD_VAL(ipc, 14, 14);
2974 l |= FLD_VAL(ihs, 13, 13);
2975 l |= FLD_VAL(ivs, 12, 12);
2976 l |= FLD_VAL(acbi, 11, 8);
2977 l |= FLD_VAL(acb, 7, 0);
3309 2978
3310 dispc_runtime_put(); 2979 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2980}
3311 2981
3312#undef DISPC_REG 2982void dispc_set_pol_freq(enum omap_channel channel,
3313#undef DUMPREG 2983 enum omap_panel_config config, u8 acbi, u8 acb)
2984{
2985 _dispc_set_pol_freq(channel, (config & OMAP_DSS_LCD_ONOFF) != 0,
2986 (config & OMAP_DSS_LCD_RF) != 0,
2987 (config & OMAP_DSS_LCD_IEO) != 0,
2988 (config & OMAP_DSS_LCD_IPC) != 0,
2989 (config & OMAP_DSS_LCD_IHS) != 0,
2990 (config & OMAP_DSS_LCD_IVS) != 0,
2991 acbi, acb);
3314} 2992}
3315 2993
3316/* with fck as input clock rate, find dispc dividers that produce req_pck */ 2994/* with fck as input clock rate, find dispc dividers that produce req_pck */
3317void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, 2995void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
3318 struct dispc_clock_info *cinfo) 2996 struct dispc_clock_info *cinfo)
3319{ 2997{
3320 u16 pcd_min, pcd_max; 2998 u16 pcd_min = is_tft ? 2 : 3;
3321 unsigned long best_pck; 2999 unsigned long best_pck;
3322 u16 best_ld, cur_ld; 3000 u16 best_ld, cur_ld;
3323 u16 best_pd, cur_pd; 3001 u16 best_pd, cur_pd;
3324 3002
3325 pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD);
3326 pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD);
3327
3328 best_pck = 0; 3003 best_pck = 0;
3329 best_ld = 0; 3004 best_ld = 0;
3330 best_pd = 0; 3005 best_pd = 0;
@@ -3332,7 +3007,7 @@ void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck,
3332 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { 3007 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) {
3333 unsigned long lck = fck / cur_ld; 3008 unsigned long lck = fck / cur_ld;
3334 3009
3335 for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { 3010 for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) {
3336 unsigned long pck = lck / cur_pd; 3011 unsigned long pck = lck / cur_pd;
3337 long old_delta = abs(best_pck - req_pck); 3012 long old_delta = abs(best_pck - req_pck);
3338 long new_delta = abs(pck - req_pck); 3013 long new_delta = abs(pck - req_pck);
@@ -3367,7 +3042,7 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3367{ 3042{
3368 if (cinfo->lck_div > 255 || cinfo->lck_div == 0) 3043 if (cinfo->lck_div > 255 || cinfo->lck_div == 0)
3369 return -EINVAL; 3044 return -EINVAL;
3370 if (cinfo->pck_div < 1 || cinfo->pck_div > 255) 3045 if (cinfo->pck_div < 2 || cinfo->pck_div > 255)
3371 return -EINVAL; 3046 return -EINVAL;
3372 3047
3373 cinfo->lck = dispc_fclk_rate / cinfo->lck_div; 3048 cinfo->lck = dispc_fclk_rate / cinfo->lck_div;
@@ -3376,16 +3051,18 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
3376 return 0; 3051 return 0;
3377} 3052}
3378 3053
3379void dispc_mgr_set_clock_div(enum omap_channel channel, 3054int dispc_set_clock_div(enum omap_channel channel,
3380 const struct dispc_clock_info *cinfo) 3055 struct dispc_clock_info *cinfo)
3381{ 3056{
3382 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); 3057 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div);
3383 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); 3058 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div);
3384 3059
3385 dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); 3060 dispc_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div);
3061
3062 return 0;
3386} 3063}
3387 3064
3388int dispc_mgr_get_clock_div(enum omap_channel channel, 3065int dispc_get_clock_div(enum omap_channel channel,
3389 struct dispc_clock_info *cinfo) 3066 struct dispc_clock_info *cinfo)
3390{ 3067{
3391 unsigned long fck; 3068 unsigned long fck;
@@ -3401,247 +3078,617 @@ int dispc_mgr_get_clock_div(enum omap_channel channel,
3401 return 0; 3078 return 0;
3402} 3079}
3403 3080
3404u32 dispc_read_irqstatus(void) 3081/* dispc.irq_lock has to be locked by the caller */
3082static void _omap_dispc_set_irqs(void)
3405{ 3083{
3406 return dispc_read_reg(DISPC_IRQSTATUS); 3084 u32 mask;
3407} 3085 u32 old_mask;
3408EXPORT_SYMBOL(dispc_read_irqstatus); 3086 int i;
3087 struct omap_dispc_isr_data *isr_data;
3409 3088
3410void dispc_clear_irqstatus(u32 mask) 3089 mask = dispc.irq_error_mask;
3411{ 3090
3412 dispc_write_reg(DISPC_IRQSTATUS, mask); 3091 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3092 isr_data = &dispc.registered_isr[i];
3093
3094 if (isr_data->isr == NULL)
3095 continue;
3096
3097 mask |= isr_data->mask;
3098 }
3099
3100 old_mask = dispc_read_reg(DISPC_IRQENABLE);
3101 /* clear the irqstatus for newly enabled irqs */
3102 dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask);
3103
3104 dispc_write_reg(DISPC_IRQENABLE, mask);
3413} 3105}
3414EXPORT_SYMBOL(dispc_clear_irqstatus);
3415 3106
3416u32 dispc_read_irqenable(void) 3107int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
3417{ 3108{
3418 return dispc_read_reg(DISPC_IRQENABLE); 3109 int i;
3110 int ret;
3111 unsigned long flags;
3112 struct omap_dispc_isr_data *isr_data;
3113
3114 if (isr == NULL)
3115 return -EINVAL;
3116
3117 spin_lock_irqsave(&dispc.irq_lock, flags);
3118
3119 /* check for duplicate entry */
3120 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3121 isr_data = &dispc.registered_isr[i];
3122 if (isr_data->isr == isr && isr_data->arg == arg &&
3123 isr_data->mask == mask) {
3124 ret = -EINVAL;
3125 goto err;
3126 }
3127 }
3128
3129 isr_data = NULL;
3130 ret = -EBUSY;
3131
3132 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3133 isr_data = &dispc.registered_isr[i];
3134
3135 if (isr_data->isr != NULL)
3136 continue;
3137
3138 isr_data->isr = isr;
3139 isr_data->arg = arg;
3140 isr_data->mask = mask;
3141 ret = 0;
3142
3143 break;
3144 }
3145
3146 if (ret)
3147 goto err;
3148
3149 _omap_dispc_set_irqs();
3150
3151 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3152
3153 return 0;
3154err:
3155 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3156
3157 return ret;
3419} 3158}
3420EXPORT_SYMBOL(dispc_read_irqenable); 3159EXPORT_SYMBOL(omap_dispc_register_isr);
3421 3160
3422void dispc_write_irqenable(u32 mask) 3161int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask)
3423{ 3162{
3424 u32 old_mask = dispc_read_reg(DISPC_IRQENABLE); 3163 int i;
3164 unsigned long flags;
3165 int ret = -EINVAL;
3166 struct omap_dispc_isr_data *isr_data;
3425 3167
3426 /* clear the irqstatus for newly enabled irqs */ 3168 spin_lock_irqsave(&dispc.irq_lock, flags);
3427 dispc_clear_irqstatus((mask ^ old_mask) & mask);
3428 3169
3429 dispc_write_reg(DISPC_IRQENABLE, mask); 3170 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3171 isr_data = &dispc.registered_isr[i];
3172 if (isr_data->isr != isr || isr_data->arg != arg ||
3173 isr_data->mask != mask)
3174 continue;
3175
3176 /* found the correct isr */
3177
3178 isr_data->isr = NULL;
3179 isr_data->arg = NULL;
3180 isr_data->mask = 0;
3181
3182 ret = 0;
3183 break;
3184 }
3185
3186 if (ret == 0)
3187 _omap_dispc_set_irqs();
3188
3189 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3190
3191 return ret;
3430} 3192}
3431EXPORT_SYMBOL(dispc_write_irqenable); 3193EXPORT_SYMBOL(omap_dispc_unregister_isr);
3432 3194
3433void dispc_enable_sidle(void) 3195#ifdef DEBUG
3196static void print_irq_status(u32 status)
3434{ 3197{
3435 REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */ 3198 if ((status & dispc.irq_error_mask) == 0)
3199 return;
3200
3201 printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status);
3202
3203#define PIS(x) \
3204 if (status & DISPC_IRQ_##x) \
3205 printk(#x " ");
3206 PIS(GFX_FIFO_UNDERFLOW);
3207 PIS(OCP_ERR);
3208 PIS(VID1_FIFO_UNDERFLOW);
3209 PIS(VID2_FIFO_UNDERFLOW);
3210 PIS(SYNC_LOST);
3211 PIS(SYNC_LOST_DIGIT);
3212 if (dss_has_feature(FEAT_MGR_LCD2))
3213 PIS(SYNC_LOST2);
3214#undef PIS
3215
3216 printk("\n");
3436} 3217}
3218#endif
3437 3219
3438void dispc_disable_sidle(void) 3220/* Called from dss.c. Note that we don't touch clocks here,
3221 * but we presume they are on because we got an IRQ. However,
3222 * an irq handler may turn the clocks off, so we may not have
3223 * clock later in the function. */
3224static irqreturn_t omap_dispc_irq_handler(int irq, void *arg)
3439{ 3225{
3440 REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */ 3226 int i;
3227 u32 irqstatus, irqenable;
3228 u32 handledirqs = 0;
3229 u32 unhandled_errors;
3230 struct omap_dispc_isr_data *isr_data;
3231 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS];
3232
3233 spin_lock(&dispc.irq_lock);
3234
3235 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
3236 irqenable = dispc_read_reg(DISPC_IRQENABLE);
3237
3238 /* IRQ is not for us */
3239 if (!(irqstatus & irqenable)) {
3240 spin_unlock(&dispc.irq_lock);
3241 return IRQ_NONE;
3242 }
3243
3244#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3245 spin_lock(&dispc.irq_stats_lock);
3246 dispc.irq_stats.irq_count++;
3247 dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
3248 spin_unlock(&dispc.irq_stats_lock);
3249#endif
3250
3251#ifdef DEBUG
3252 if (dss_debug)
3253 print_irq_status(irqstatus);
3254#endif
3255 /* Ack the interrupt. Do it here before clocks are possibly turned
3256 * off */
3257 dispc_write_reg(DISPC_IRQSTATUS, irqstatus);
3258 /* flush posted write */
3259 dispc_read_reg(DISPC_IRQSTATUS);
3260
3261 /* make a copy and unlock, so that isrs can unregister
3262 * themselves */
3263 memcpy(registered_isr, dispc.registered_isr,
3264 sizeof(registered_isr));
3265
3266 spin_unlock(&dispc.irq_lock);
3267
3268 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3269 isr_data = &registered_isr[i];
3270
3271 if (!isr_data->isr)
3272 continue;
3273
3274 if (isr_data->mask & irqstatus) {
3275 isr_data->isr(isr_data->arg, irqstatus);
3276 handledirqs |= isr_data->mask;
3277 }
3278 }
3279
3280 spin_lock(&dispc.irq_lock);
3281
3282 unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask;
3283
3284 if (unhandled_errors) {
3285 dispc.error_irqs |= unhandled_errors;
3286
3287 dispc.irq_error_mask &= ~unhandled_errors;
3288 _omap_dispc_set_irqs();
3289
3290 schedule_work(&dispc.error_work);
3291 }
3292
3293 spin_unlock(&dispc.irq_lock);
3294
3295 return IRQ_HANDLED;
3441} 3296}
3442 3297
3443static void _omap_dispc_initial_config(void) 3298static void dispc_error_worker(struct work_struct *work)
3444{ 3299{
3445 u32 l; 3300 int i;
3301 u32 errors;
3302 unsigned long flags;
3303
3304 spin_lock_irqsave(&dispc.irq_lock, flags);
3305 errors = dispc.error_irqs;
3306 dispc.error_irqs = 0;
3307 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3308
3309 if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) {
3310 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n");
3311 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3312 struct omap_overlay *ovl;
3313 ovl = omap_dss_get_overlay(i);
3314
3315 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3316 continue;
3317
3318 if (ovl->id == 0) {
3319 dispc_enable_plane(ovl->id, 0);
3320 dispc_go(ovl->manager->id);
3321 mdelay(50);
3322 break;
3323 }
3324 }
3325 }
3446 3326
3447 /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ 3327 if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) {
3448 if (dss_has_feature(FEAT_CORE_CLK_DIV)) { 3328 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n");
3449 l = dispc_read_reg(DISPC_DIVISOR); 3329 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3450 /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ 3330 struct omap_overlay *ovl;
3451 l = FLD_MOD(l, 1, 0, 0); 3331 ovl = omap_dss_get_overlay(i);
3452 l = FLD_MOD(l, 1, 23, 16); 3332
3453 dispc_write_reg(DISPC_DIVISOR, l); 3333 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3334 continue;
3335
3336 if (ovl->id == 1) {
3337 dispc_enable_plane(ovl->id, 0);
3338 dispc_go(ovl->manager->id);
3339 mdelay(50);
3340 break;
3341 }
3342 }
3454 } 3343 }
3455 3344
3456 /* FUNCGATED */ 3345 if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) {
3457 if (dss_has_feature(FEAT_FUNCGATED)) 3346 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n");
3458 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3347 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3348 struct omap_overlay *ovl;
3349 ovl = omap_dss_get_overlay(i);
3459 3350
3460 dispc_setup_color_conv_coef(); 3351 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3352 continue;
3461 3353
3462 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); 3354 if (ovl->id == 2) {
3355 dispc_enable_plane(ovl->id, 0);
3356 dispc_go(ovl->manager->id);
3357 mdelay(50);
3358 break;
3359 }
3360 }
3361 }
3463 3362
3464 dispc_init_fifos(); 3363 if (errors & DISPC_IRQ_SYNC_LOST) {
3364 struct omap_overlay_manager *manager = NULL;
3365 bool enable = false;
3465 3366
3466 dispc_configure_burst_sizes(); 3367 DSSERR("SYNC_LOST, disabling LCD\n");
3467 3368
3468 dispc_ovl_enable_zorder_planes(); 3369 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3469} 3370 struct omap_overlay_manager *mgr;
3470 3371 mgr = omap_dss_get_overlay_manager(i);
3471static const struct dispc_features omap24xx_dispc_feats __initconst = {
3472 .sw_start = 5,
3473 .fp_start = 15,
3474 .bp_start = 27,
3475 .sw_max = 64,
3476 .vp_max = 255,
3477 .hp_max = 256,
3478 .mgr_width_start = 10,
3479 .mgr_height_start = 26,
3480 .mgr_width_max = 2048,
3481 .mgr_height_max = 2048,
3482 .calc_scaling = dispc_ovl_calc_scaling_24xx,
3483 .calc_core_clk = calc_core_clk_24xx,
3484 .num_fifos = 3,
3485 .no_framedone_tv = true,
3486};
3487 3372
3488static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { 3373 if (mgr->id == OMAP_DSS_CHANNEL_LCD) {
3489 .sw_start = 5, 3374 manager = mgr;
3490 .fp_start = 15, 3375 enable = mgr->device->state ==
3491 .bp_start = 27, 3376 OMAP_DSS_DISPLAY_ACTIVE;
3492 .sw_max = 64, 3377 mgr->device->driver->disable(mgr->device);
3493 .vp_max = 255, 3378 break;
3494 .hp_max = 256, 3379 }
3495 .mgr_width_start = 10, 3380 }
3496 .mgr_height_start = 26,
3497 .mgr_width_max = 2048,
3498 .mgr_height_max = 2048,
3499 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3500 .calc_core_clk = calc_core_clk_34xx,
3501 .num_fifos = 3,
3502 .no_framedone_tv = true,
3503};
3504 3381
3505static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { 3382 if (manager) {
3506 .sw_start = 7, 3383 struct omap_dss_device *dssdev = manager->device;
3507 .fp_start = 19, 3384 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3508 .bp_start = 31, 3385 struct omap_overlay *ovl;
3509 .sw_max = 256, 3386 ovl = omap_dss_get_overlay(i);
3510 .vp_max = 4095,
3511 .hp_max = 4096,
3512 .mgr_width_start = 10,
3513 .mgr_height_start = 26,
3514 .mgr_width_max = 2048,
3515 .mgr_height_max = 2048,
3516 .calc_scaling = dispc_ovl_calc_scaling_34xx,
3517 .calc_core_clk = calc_core_clk_34xx,
3518 .num_fifos = 3,
3519 .no_framedone_tv = true,
3520};
3521 3387
3522static const struct dispc_features omap44xx_dispc_feats __initconst = { 3388 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3523 .sw_start = 7, 3389 continue;
3524 .fp_start = 19,
3525 .bp_start = 31,
3526 .sw_max = 256,
3527 .vp_max = 4095,
3528 .hp_max = 4096,
3529 .mgr_width_start = 10,
3530 .mgr_height_start = 26,
3531 .mgr_width_max = 2048,
3532 .mgr_height_max = 2048,
3533 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3534 .calc_core_clk = calc_core_clk_44xx,
3535 .num_fifos = 5,
3536 .gfx_fifo_workaround = true,
3537};
3538 3390
3539static const struct dispc_features omap54xx_dispc_feats __initconst = { 3391 if (ovl->id != 0 && ovl->manager == manager)
3540 .sw_start = 7, 3392 dispc_enable_plane(ovl->id, 0);
3541 .fp_start = 19, 3393 }
3542 .bp_start = 31,
3543 .sw_max = 256,
3544 .vp_max = 4095,
3545 .hp_max = 4096,
3546 .mgr_width_start = 11,
3547 .mgr_height_start = 27,
3548 .mgr_width_max = 4096,
3549 .mgr_height_max = 4096,
3550 .calc_scaling = dispc_ovl_calc_scaling_44xx,
3551 .calc_core_clk = calc_core_clk_44xx,
3552 .num_fifos = 5,
3553 .gfx_fifo_workaround = true,
3554};
3555 3394
3556static int __init dispc_init_features(struct platform_device *pdev) 3395 dispc_go(manager->id);
3557{ 3396 mdelay(50);
3558 const struct dispc_features *src; 3397 if (enable)
3559 struct dispc_features *dst; 3398 dssdev->driver->enable(dssdev);
3399 }
3400 }
3560 3401
3561 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); 3402 if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) {
3562 if (!dst) { 3403 struct omap_overlay_manager *manager = NULL;
3563 dev_err(&pdev->dev, "Failed to allocate DISPC Features\n"); 3404 bool enable = false;
3564 return -ENOMEM; 3405
3406 DSSERR("SYNC_LOST_DIGIT, disabling TV\n");
3407
3408 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3409 struct omap_overlay_manager *mgr;
3410 mgr = omap_dss_get_overlay_manager(i);
3411
3412 if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) {
3413 manager = mgr;
3414 enable = mgr->device->state ==
3415 OMAP_DSS_DISPLAY_ACTIVE;
3416 mgr->device->driver->disable(mgr->device);
3417 break;
3418 }
3419 }
3420
3421 if (manager) {
3422 struct omap_dss_device *dssdev = manager->device;
3423 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3424 struct omap_overlay *ovl;
3425 ovl = omap_dss_get_overlay(i);
3426
3427 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3428 continue;
3429
3430 if (ovl->id != 0 && ovl->manager == manager)
3431 dispc_enable_plane(ovl->id, 0);
3432 }
3433
3434 dispc_go(manager->id);
3435 mdelay(50);
3436 if (enable)
3437 dssdev->driver->enable(dssdev);
3438 }
3565 } 3439 }
3566 3440
3567 switch (omapdss_get_version()) { 3441 if (errors & DISPC_IRQ_SYNC_LOST2) {
3568 case OMAPDSS_VER_OMAP24xx: 3442 struct omap_overlay_manager *manager = NULL;
3569 src = &omap24xx_dispc_feats; 3443 bool enable = false;
3570 break;
3571 3444
3572 case OMAPDSS_VER_OMAP34xx_ES1: 3445 DSSERR("SYNC_LOST for LCD2, disabling LCD2\n");
3573 src = &omap34xx_rev1_0_dispc_feats;
3574 break;
3575 3446
3576 case OMAPDSS_VER_OMAP34xx_ES3: 3447 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3577 case OMAPDSS_VER_OMAP3630: 3448 struct omap_overlay_manager *mgr;
3578 case OMAPDSS_VER_AM35xx: 3449 mgr = omap_dss_get_overlay_manager(i);
3579 src = &omap34xx_rev3_0_dispc_feats;
3580 break;
3581 3450
3582 case OMAPDSS_VER_OMAP4430_ES1: 3451 if (mgr->id == OMAP_DSS_CHANNEL_LCD2) {
3583 case OMAPDSS_VER_OMAP4430_ES2: 3452 manager = mgr;
3584 case OMAPDSS_VER_OMAP4: 3453 enable = mgr->device->state ==
3585 src = &omap44xx_dispc_feats; 3454 OMAP_DSS_DISPLAY_ACTIVE;
3586 break; 3455 mgr->device->driver->disable(mgr->device);
3456 break;
3457 }
3458 }
3587 3459
3588 case OMAPDSS_VER_OMAP5: 3460 if (manager) {
3589 src = &omap54xx_dispc_feats; 3461 struct omap_dss_device *dssdev = manager->device;
3590 break; 3462 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
3463 struct omap_overlay *ovl;
3464 ovl = omap_dss_get_overlay(i);
3591 3465
3592 default: 3466 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
3593 return -ENODEV; 3467 continue;
3468
3469 if (ovl->id != 0 && ovl->manager == manager)
3470 dispc_enable_plane(ovl->id, 0);
3471 }
3472
3473 dispc_go(manager->id);
3474 mdelay(50);
3475 if (enable)
3476 dssdev->driver->enable(dssdev);
3477 }
3478 }
3479
3480 if (errors & DISPC_IRQ_OCP_ERR) {
3481 DSSERR("OCP_ERR\n");
3482 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3483 struct omap_overlay_manager *mgr;
3484 mgr = omap_dss_get_overlay_manager(i);
3485
3486 if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
3487 mgr->device->driver->disable(mgr->device);
3488 }
3489 }
3490
3491 spin_lock_irqsave(&dispc.irq_lock, flags);
3492 dispc.irq_error_mask |= errors;
3493 _omap_dispc_set_irqs();
3494 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3495}
3496
3497int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout)
3498{
3499 void dispc_irq_wait_handler(void *data, u32 mask)
3500 {
3501 complete((struct completion *)data);
3594 } 3502 }
3595 3503
3596 memcpy(dst, src, sizeof(*dst)); 3504 int r;
3597 dispc.feat = dst; 3505 DECLARE_COMPLETION_ONSTACK(completion);
3506
3507 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3508 irqmask);
3509
3510 if (r)
3511 return r;
3512
3513 timeout = wait_for_completion_timeout(&completion, timeout);
3514
3515 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3516
3517 if (timeout == 0)
3518 return -ETIMEDOUT;
3519
3520 if (timeout == -ERESTARTSYS)
3521 return -ERESTARTSYS;
3598 3522
3599 return 0; 3523 return 0;
3600} 3524}
3601 3525
3602int dispc_request_irq(irq_handler_t handler, void *dev_id) 3526int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
3527 unsigned long timeout)
3603{ 3528{
3604 return devm_request_irq(&dispc.pdev->dev, dispc.irq, handler, 3529 void dispc_irq_wait_handler(void *data, u32 mask)
3605 IRQF_SHARED, "OMAP DISPC", dev_id); 3530 {
3531 complete((struct completion *)data);
3532 }
3533
3534 int r;
3535 DECLARE_COMPLETION_ONSTACK(completion);
3536
3537 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
3538 irqmask);
3539
3540 if (r)
3541 return r;
3542
3543 timeout = wait_for_completion_interruptible_timeout(&completion,
3544 timeout);
3545
3546 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
3547
3548 if (timeout == 0)
3549 return -ETIMEDOUT;
3550
3551 if (timeout == -ERESTARTSYS)
3552 return -ERESTARTSYS;
3553
3554 return 0;
3606} 3555}
3607EXPORT_SYMBOL(dispc_request_irq);
3608 3556
3609void dispc_free_irq(void *dev_id) 3557#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3558void dispc_fake_vsync_irq(void)
3610{ 3559{
3611 devm_free_irq(&dispc.pdev->dev, dispc.irq, dev_id); 3560 u32 irqstatus = DISPC_IRQ_VSYNC;
3561 int i;
3562
3563 WARN_ON(!in_interrupt());
3564
3565 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3566 struct omap_dispc_isr_data *isr_data;
3567 isr_data = &dispc.registered_isr[i];
3568
3569 if (!isr_data->isr)
3570 continue;
3571
3572 if (isr_data->mask & irqstatus)
3573 isr_data->isr(isr_data->arg, irqstatus);
3574 }
3575}
3576#endif
3577
3578static void _omap_dispc_initialize_irq(void)
3579{
3580 unsigned long flags;
3581
3582 spin_lock_irqsave(&dispc.irq_lock, flags);
3583
3584 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr));
3585
3586 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR;
3587 if (dss_has_feature(FEAT_MGR_LCD2))
3588 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST2;
3589
3590 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS,
3591 * so clear it */
3592 dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS));
3593
3594 _omap_dispc_set_irqs();
3595
3596 spin_unlock_irqrestore(&dispc.irq_lock, flags);
3597}
3598
3599void dispc_enable_sidle(void)
3600{
3601 REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */
3602}
3603
3604void dispc_disable_sidle(void)
3605{
3606 REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
3607}
3608
3609static void _omap_dispc_initial_config(void)
3610{
3611 u32 l;
3612
3613 /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */
3614 if (dss_has_feature(FEAT_CORE_CLK_DIV)) {
3615 l = dispc_read_reg(DISPC_DIVISOR);
3616 /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */
3617 l = FLD_MOD(l, 1, 0, 0);
3618 l = FLD_MOD(l, 1, 23, 16);
3619 dispc_write_reg(DISPC_DIVISOR, l);
3620 }
3621
3622 /* FUNCGATED */
3623 if (dss_has_feature(FEAT_FUNCGATED))
3624 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9);
3625
3626 /* L3 firewall setting: enable access to OCM RAM */
3627 /* XXX this should be somewhere in plat-omap */
3628 if (cpu_is_omap24xx())
3629 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0));
3630
3631 _dispc_setup_color_conv_coef();
3632
3633 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY);
3634
3635 dispc_read_plane_fifo_sizes();
3636
3637 dispc_configure_burst_sizes();
3612} 3638}
3613EXPORT_SYMBOL(dispc_free_irq);
3614 3639
3615/* DISPC HW IP initialisation */ 3640/* DISPC HW IP initialisation */
3616static int __init omap_dispchw_probe(struct platform_device *pdev) 3641static int omap_dispchw_probe(struct platform_device *pdev)
3617{ 3642{
3618 u32 rev; 3643 u32 rev;
3619 int r = 0; 3644 int r = 0;
3620 struct resource *dispc_mem; 3645 struct resource *dispc_mem;
3646 struct clk *clk;
3621 3647
3622 dispc.pdev = pdev; 3648 dispc.pdev = pdev;
3623 3649
3624 r = dispc_init_features(dispc.pdev); 3650 clk = clk_get(&pdev->dev, "fck");
3625 if (r) 3651 if (IS_ERR(clk)) {
3626 return r; 3652 DSSERR("can't get fck\n");
3653 r = PTR_ERR(clk);
3654 goto err_get_clk;
3655 }
3656
3657 dispc.dss_clk = clk;
3658
3659 spin_lock_init(&dispc.irq_lock);
3660
3661#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3662 spin_lock_init(&dispc.irq_stats_lock);
3663 dispc.irq_stats.last_reset = jiffies;
3664#endif
3665
3666 INIT_WORK(&dispc.error_work, dispc_error_worker);
3627 3667
3628 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); 3668 dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0);
3629 if (!dispc_mem) { 3669 if (!dispc_mem) {
3630 DSSERR("can't get IORESOURCE_MEM DISPC\n"); 3670 DSSERR("can't get IORESOURCE_MEM DISPC\n");
3631 return -EINVAL; 3671 r = -EINVAL;
3672 goto err_ioremap;
3632 } 3673 }
3633 3674 dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem));
3634 dispc.base = devm_ioremap(&pdev->dev, dispc_mem->start,
3635 resource_size(dispc_mem));
3636 if (!dispc.base) { 3675 if (!dispc.base) {
3637 DSSERR("can't ioremap DISPC\n"); 3676 DSSERR("can't ioremap DISPC\n");
3638 return -ENOMEM; 3677 r = -ENOMEM;
3678 goto err_ioremap;
3639 } 3679 }
3640
3641 dispc.irq = platform_get_irq(dispc.pdev, 0); 3680 dispc.irq = platform_get_irq(dispc.pdev, 0);
3642 if (dispc.irq < 0) { 3681 if (dispc.irq < 0) {
3643 DSSERR("platform_get_irq failed\n"); 3682 DSSERR("platform_get_irq failed\n");
3644 return -ENODEV; 3683 r = -ENODEV;
3684 goto err_irq;
3685 }
3686
3687 r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED,
3688 "OMAP DISPC", dispc.pdev);
3689 if (r < 0) {
3690 DSSERR("request_irq failed\n");
3691 goto err_irq;
3645 } 3692 }
3646 3693
3647 pm_runtime_enable(&pdev->dev); 3694 pm_runtime_enable(&pdev->dev);
@@ -3652,37 +3699,56 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
3652 3699
3653 _omap_dispc_initial_config(); 3700 _omap_dispc_initial_config();
3654 3701
3702 _omap_dispc_initialize_irq();
3703
3655 rev = dispc_read_reg(DISPC_REVISION); 3704 rev = dispc_read_reg(DISPC_REVISION);
3656 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", 3705 dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n",
3657 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 3706 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
3658 3707
3659 dispc_runtime_put(); 3708 dispc_runtime_put();
3660 3709
3661 dss_debugfs_create_file("dispc", dispc_dump_regs);
3662
3663 return 0; 3710 return 0;
3664 3711
3665err_runtime_get: 3712err_runtime_get:
3666 pm_runtime_disable(&pdev->dev); 3713 pm_runtime_disable(&pdev->dev);
3714 free_irq(dispc.irq, dispc.pdev);
3715err_irq:
3716 iounmap(dispc.base);
3717err_ioremap:
3718 clk_put(dispc.dss_clk);
3719err_get_clk:
3667 return r; 3720 return r;
3668} 3721}
3669 3722
3670static int __exit omap_dispchw_remove(struct platform_device *pdev) 3723static int omap_dispchw_remove(struct platform_device *pdev)
3671{ 3724{
3672 pm_runtime_disable(&pdev->dev); 3725 pm_runtime_disable(&pdev->dev);
3673 3726
3727 clk_put(dispc.dss_clk);
3728
3729 free_irq(dispc.irq, dispc.pdev);
3730 iounmap(dispc.base);
3674 return 0; 3731 return 0;
3675} 3732}
3676 3733
3677static int dispc_runtime_suspend(struct device *dev) 3734static int dispc_runtime_suspend(struct device *dev)
3678{ 3735{
3679 dispc_save_context(); 3736 dispc_save_context();
3737 clk_disable(dispc.dss_clk);
3738 dss_runtime_put();
3680 3739
3681 return 0; 3740 return 0;
3682} 3741}
3683 3742
3684static int dispc_runtime_resume(struct device *dev) 3743static int dispc_runtime_resume(struct device *dev)
3685{ 3744{
3745 int r;
3746
3747 r = dss_runtime_get();
3748 if (r < 0)
3749 return r;
3750
3751 clk_enable(dispc.dss_clk);
3686 dispc_restore_context(); 3752 dispc_restore_context();
3687 3753
3688 return 0; 3754 return 0;
@@ -3694,7 +3760,8 @@ static const struct dev_pm_ops dispc_pm_ops = {
3694}; 3760};
3695 3761
3696static struct platform_driver omap_dispchw_driver = { 3762static struct platform_driver omap_dispchw_driver = {
3697 .remove = __exit_p(omap_dispchw_remove), 3763 .probe = omap_dispchw_probe,
3764 .remove = omap_dispchw_remove,
3698 .driver = { 3765 .driver = {
3699 .name = "omapdss_dispc", 3766 .name = "omapdss_dispc",
3700 .owner = THIS_MODULE, 3767 .owner = THIS_MODULE,
@@ -3702,12 +3769,12 @@ static struct platform_driver omap_dispchw_driver = {
3702 }, 3769 },
3703}; 3770};
3704 3771
3705int __init dispc_init_platform_driver(void) 3772int dispc_init_platform_driver(void)
3706{ 3773{
3707 return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe); 3774 return platform_driver_register(&omap_dispchw_driver);
3708} 3775}
3709 3776
3710void __exit dispc_uninit_platform_driver(void) 3777void dispc_uninit_platform_driver(void)
3711{ 3778{
3712 platform_driver_unregister(&omap_dispchw_driver); 3779 return platform_driver_unregister(&omap_dispchw_driver);
3713} 3780}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 222363c6e62..6c9ee0a0efb 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -36,9 +36,6 @@
36#define DISPC_CONTROL2 0x0238 36#define DISPC_CONTROL2 0x0238
37#define DISPC_CONFIG2 0x0620 37#define DISPC_CONFIG2 0x0620
38#define DISPC_DIVISOR 0x0804 38#define DISPC_DIVISOR 0x0804
39#define DISPC_GLOBAL_BUFFER 0x0800
40#define DISPC_CONTROL3 0x0848
41#define DISPC_CONFIG3 0x084C
42 39
43/* DISPC overlay registers */ 40/* DISPC overlay registers */
44#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ 41#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
@@ -100,17 +97,6 @@
100#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \ 97#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
101 DISPC_PRELOAD_OFFSET(n)) 98 DISPC_PRELOAD_OFFSET(n))
102 99
103/* DISPC up/downsampling FIR filter coefficient structure */
104struct dispc_coef {
105 s8 hc4_vc22;
106 s8 hc3_vc2;
107 u8 hc2_vc1;
108 s8 hc1_vc0;
109 s8 hc0_vc00;
110};
111
112const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
113
114/* DISPC manager/channel specific registers */ 100/* DISPC manager/channel specific registers */
115static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel) 101static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
116{ 102{
@@ -121,11 +107,8 @@ static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
121 return 0x0050; 107 return 0x0050;
122 case OMAP_DSS_CHANNEL_LCD2: 108 case OMAP_DSS_CHANNEL_LCD2:
123 return 0x03AC; 109 return 0x03AC;
124 case OMAP_DSS_CHANNEL_LCD3:
125 return 0x0814;
126 default: 110 default:
127 BUG(); 111 BUG();
128 return 0;
129 } 112 }
130} 113}
131 114
@@ -138,11 +121,8 @@ static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
138 return 0x0058; 121 return 0x0058;
139 case OMAP_DSS_CHANNEL_LCD2: 122 case OMAP_DSS_CHANNEL_LCD2:
140 return 0x03B0; 123 return 0x03B0;
141 case OMAP_DSS_CHANNEL_LCD3:
142 return 0x0818;
143 default: 124 default:
144 BUG(); 125 BUG();
145 return 0;
146 } 126 }
147} 127}
148 128
@@ -153,14 +133,10 @@ static inline u16 DISPC_TIMING_H(enum omap_channel channel)
153 return 0x0064; 133 return 0x0064;
154 case OMAP_DSS_CHANNEL_DIGIT: 134 case OMAP_DSS_CHANNEL_DIGIT:
155 BUG(); 135 BUG();
156 return 0;
157 case OMAP_DSS_CHANNEL_LCD2: 136 case OMAP_DSS_CHANNEL_LCD2:
158 return 0x0400; 137 return 0x0400;
159 case OMAP_DSS_CHANNEL_LCD3:
160 return 0x0840;
161 default: 138 default:
162 BUG(); 139 BUG();
163 return 0;
164 } 140 }
165} 141}
166 142
@@ -171,14 +147,10 @@ static inline u16 DISPC_TIMING_V(enum omap_channel channel)
171 return 0x0068; 147 return 0x0068;
172 case OMAP_DSS_CHANNEL_DIGIT: 148 case OMAP_DSS_CHANNEL_DIGIT:
173 BUG(); 149 BUG();
174 return 0;
175 case OMAP_DSS_CHANNEL_LCD2: 150 case OMAP_DSS_CHANNEL_LCD2:
176 return 0x0404; 151 return 0x0404;
177 case OMAP_DSS_CHANNEL_LCD3:
178 return 0x0844;
179 default: 152 default:
180 BUG(); 153 BUG();
181 return 0;
182 } 154 }
183} 155}
184 156
@@ -189,14 +161,10 @@ static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
189 return 0x006C; 161 return 0x006C;
190 case OMAP_DSS_CHANNEL_DIGIT: 162 case OMAP_DSS_CHANNEL_DIGIT:
191 BUG(); 163 BUG();
192 return 0;
193 case OMAP_DSS_CHANNEL_LCD2: 164 case OMAP_DSS_CHANNEL_LCD2:
194 return 0x0408; 165 return 0x0408;
195 case OMAP_DSS_CHANNEL_LCD3:
196 return 0x083C;
197 default: 166 default:
198 BUG(); 167 BUG();
199 return 0;
200 } 168 }
201} 169}
202 170
@@ -207,14 +175,10 @@ static inline u16 DISPC_DIVISORo(enum omap_channel channel)
207 return 0x0070; 175 return 0x0070;
208 case OMAP_DSS_CHANNEL_DIGIT: 176 case OMAP_DSS_CHANNEL_DIGIT:
209 BUG(); 177 BUG();
210 return 0;
211 case OMAP_DSS_CHANNEL_LCD2: 178 case OMAP_DSS_CHANNEL_LCD2:
212 return 0x040C; 179 return 0x040C;
213 case OMAP_DSS_CHANNEL_LCD3:
214 return 0x0838;
215 default: 180 default:
216 BUG(); 181 BUG();
217 return 0;
218 } 182 }
219} 183}
220 184
@@ -228,11 +192,8 @@ static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
228 return 0x0078; 192 return 0x0078;
229 case OMAP_DSS_CHANNEL_LCD2: 193 case OMAP_DSS_CHANNEL_LCD2:
230 return 0x03CC; 194 return 0x03CC;
231 case OMAP_DSS_CHANNEL_LCD3:
232 return 0x0834;
233 default: 195 default:
234 BUG(); 196 BUG();
235 return 0;
236 } 197 }
237} 198}
238 199
@@ -243,14 +204,10 @@ static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
243 return 0x01D4; 204 return 0x01D4;
244 case OMAP_DSS_CHANNEL_DIGIT: 205 case OMAP_DSS_CHANNEL_DIGIT:
245 BUG(); 206 BUG();
246 return 0;
247 case OMAP_DSS_CHANNEL_LCD2: 207 case OMAP_DSS_CHANNEL_LCD2:
248 return 0x03C0; 208 return 0x03C0;
249 case OMAP_DSS_CHANNEL_LCD3:
250 return 0x0828;
251 default: 209 default:
252 BUG(); 210 BUG();
253 return 0;
254 } 211 }
255} 212}
256 213
@@ -261,14 +218,10 @@ static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
261 return 0x01D8; 218 return 0x01D8;
262 case OMAP_DSS_CHANNEL_DIGIT: 219 case OMAP_DSS_CHANNEL_DIGIT:
263 BUG(); 220 BUG();
264 return 0;
265 case OMAP_DSS_CHANNEL_LCD2: 221 case OMAP_DSS_CHANNEL_LCD2:
266 return 0x03C4; 222 return 0x03C4;
267 case OMAP_DSS_CHANNEL_LCD3:
268 return 0x082C;
269 default: 223 default:
270 BUG(); 224 BUG();
271 return 0;
272 } 225 }
273} 226}
274 227
@@ -279,14 +232,10 @@ static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
279 return 0x01DC; 232 return 0x01DC;
280 case OMAP_DSS_CHANNEL_DIGIT: 233 case OMAP_DSS_CHANNEL_DIGIT:
281 BUG(); 234 BUG();
282 return 0;
283 case OMAP_DSS_CHANNEL_LCD2: 235 case OMAP_DSS_CHANNEL_LCD2:
284 return 0x03C8; 236 return 0x03C8;
285 case OMAP_DSS_CHANNEL_LCD3:
286 return 0x0830;
287 default: 237 default:
288 BUG(); 238 BUG();
289 return 0;
290 } 239 }
291} 240}
292 241
@@ -297,14 +246,10 @@ static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
297 return 0x0220; 246 return 0x0220;
298 case OMAP_DSS_CHANNEL_DIGIT: 247 case OMAP_DSS_CHANNEL_DIGIT:
299 BUG(); 248 BUG();
300 return 0;
301 case OMAP_DSS_CHANNEL_LCD2: 249 case OMAP_DSS_CHANNEL_LCD2:
302 return 0x03BC; 250 return 0x03BC;
303 case OMAP_DSS_CHANNEL_LCD3:
304 return 0x0824;
305 default: 251 default:
306 BUG(); 252 BUG();
307 return 0;
308 } 253 }
309} 254}
310 255
@@ -315,14 +260,10 @@ static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
315 return 0x0224; 260 return 0x0224;
316 case OMAP_DSS_CHANNEL_DIGIT: 261 case OMAP_DSS_CHANNEL_DIGIT:
317 BUG(); 262 BUG();
318 return 0;
319 case OMAP_DSS_CHANNEL_LCD2: 263 case OMAP_DSS_CHANNEL_LCD2:
320 return 0x03B8; 264 return 0x03B8;
321 case OMAP_DSS_CHANNEL_LCD3:
322 return 0x0820;
323 default: 265 default:
324 BUG(); 266 BUG();
325 return 0;
326 } 267 }
327} 268}
328 269
@@ -333,14 +274,10 @@ static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
333 return 0x0228; 274 return 0x0228;
334 case OMAP_DSS_CHANNEL_DIGIT: 275 case OMAP_DSS_CHANNEL_DIGIT:
335 BUG(); 276 BUG();
336 return 0;
337 case OMAP_DSS_CHANNEL_LCD2: 277 case OMAP_DSS_CHANNEL_LCD2:
338 return 0x03B4; 278 return 0x03B4;
339 case OMAP_DSS_CHANNEL_LCD3:
340 return 0x081C;
341 default: 279 default:
342 BUG(); 280 BUG();
343 return 0;
344 } 281 }
345} 282}
346 283
@@ -354,13 +291,8 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
354 return 0x00BC; 291 return 0x00BC;
355 case OMAP_DSS_VIDEO2: 292 case OMAP_DSS_VIDEO2:
356 return 0x014C; 293 return 0x014C;
357 case OMAP_DSS_VIDEO3:
358 return 0x0300;
359 case OMAP_DSS_WB:
360 return 0x0500;
361 default: 294 default:
362 BUG(); 295 BUG();
363 return 0;
364 } 296 }
365} 297}
366 298
@@ -372,12 +304,8 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
372 case OMAP_DSS_VIDEO1: 304 case OMAP_DSS_VIDEO1:
373 case OMAP_DSS_VIDEO2: 305 case OMAP_DSS_VIDEO2:
374 return 0x0000; 306 return 0x0000;
375 case OMAP_DSS_VIDEO3:
376 case OMAP_DSS_WB:
377 return 0x0008;
378 default: 307 default:
379 BUG(); 308 BUG();
380 return 0;
381 } 309 }
382} 310}
383 311
@@ -388,12 +316,8 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
388 case OMAP_DSS_VIDEO1: 316 case OMAP_DSS_VIDEO1:
389 case OMAP_DSS_VIDEO2: 317 case OMAP_DSS_VIDEO2:
390 return 0x0004; 318 return 0x0004;
391 case OMAP_DSS_VIDEO3:
392 case OMAP_DSS_WB:
393 return 0x000C;
394 default: 319 default:
395 BUG(); 320 BUG();
396 return 0;
397 } 321 }
398} 322}
399 323
@@ -402,18 +326,12 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
402 switch (plane) { 326 switch (plane) {
403 case OMAP_DSS_GFX: 327 case OMAP_DSS_GFX:
404 BUG(); 328 BUG();
405 return 0;
406 case OMAP_DSS_VIDEO1: 329 case OMAP_DSS_VIDEO1:
407 return 0x0544; 330 return 0x0544;
408 case OMAP_DSS_VIDEO2: 331 case OMAP_DSS_VIDEO2:
409 return 0x04BC; 332 return 0x04BC;
410 case OMAP_DSS_VIDEO3:
411 return 0x0310;
412 case OMAP_DSS_WB:
413 return 0x0118;
414 default: 333 default:
415 BUG(); 334 BUG();
416 return 0;
417 } 335 }
418} 336}
419 337
@@ -422,18 +340,12 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
422 switch (plane) { 340 switch (plane) {
423 case OMAP_DSS_GFX: 341 case OMAP_DSS_GFX:
424 BUG(); 342 BUG();
425 return 0;
426 case OMAP_DSS_VIDEO1: 343 case OMAP_DSS_VIDEO1:
427 return 0x0548; 344 return 0x0548;
428 case OMAP_DSS_VIDEO2: 345 case OMAP_DSS_VIDEO2:
429 return 0x04C0; 346 return 0x04C0;
430 case OMAP_DSS_VIDEO3:
431 return 0x0314;
432 case OMAP_DSS_WB:
433 return 0x011C;
434 default: 347 default:
435 BUG(); 348 BUG();
436 return 0;
437 } 349 }
438} 350}
439 351
@@ -444,11 +356,8 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
444 case OMAP_DSS_VIDEO1: 356 case OMAP_DSS_VIDEO1:
445 case OMAP_DSS_VIDEO2: 357 case OMAP_DSS_VIDEO2:
446 return 0x0008; 358 return 0x0008;
447 case OMAP_DSS_VIDEO3:
448 return 0x009C;
449 default: 359 default:
450 BUG(); 360 BUG();
451 return 0;
452 } 361 }
453} 362}
454 363
@@ -459,12 +368,8 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
459 case OMAP_DSS_VIDEO1: 368 case OMAP_DSS_VIDEO1:
460 case OMAP_DSS_VIDEO2: 369 case OMAP_DSS_VIDEO2:
461 return 0x000C; 370 return 0x000C;
462 case OMAP_DSS_VIDEO3:
463 case OMAP_DSS_WB:
464 return 0x00A8;
465 default: 371 default:
466 BUG(); 372 BUG();
467 return 0;
468 } 373 }
469} 374}
470 375
@@ -476,12 +381,8 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
476 case OMAP_DSS_VIDEO1: 381 case OMAP_DSS_VIDEO1:
477 case OMAP_DSS_VIDEO2: 382 case OMAP_DSS_VIDEO2:
478 return 0x0010; 383 return 0x0010;
479 case OMAP_DSS_VIDEO3:
480 case OMAP_DSS_WB:
481 return 0x0070;
482 default: 384 default:
483 BUG(); 385 BUG();
484 return 0;
485 } 386 }
486} 387}
487 388
@@ -490,18 +391,12 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
490 switch (plane) { 391 switch (plane) {
491 case OMAP_DSS_GFX: 392 case OMAP_DSS_GFX:
492 BUG(); 393 BUG();
493 return 0;
494 case OMAP_DSS_VIDEO1: 394 case OMAP_DSS_VIDEO1:
495 return 0x0568; 395 return 0x0568;
496 case OMAP_DSS_VIDEO2: 396 case OMAP_DSS_VIDEO2:
497 return 0x04DC; 397 return 0x04DC;
498 case OMAP_DSS_VIDEO3:
499 return 0x032C;
500 case OMAP_DSS_WB:
501 return 0x0310;
502 default: 398 default:
503 BUG(); 399 BUG();
504 return 0;
505 } 400 }
506} 401}
507 402
@@ -513,12 +408,8 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
513 case OMAP_DSS_VIDEO1: 408 case OMAP_DSS_VIDEO1:
514 case OMAP_DSS_VIDEO2: 409 case OMAP_DSS_VIDEO2:
515 return 0x0014; 410 return 0x0014;
516 case OMAP_DSS_VIDEO3:
517 case OMAP_DSS_WB:
518 return 0x008C;
519 default: 411 default:
520 BUG(); 412 BUG();
521 return 0;
522 } 413 }
523} 414}
524 415
@@ -530,12 +421,8 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
530 case OMAP_DSS_VIDEO1: 421 case OMAP_DSS_VIDEO1:
531 case OMAP_DSS_VIDEO2: 422 case OMAP_DSS_VIDEO2:
532 return 0x0018; 423 return 0x0018;
533 case OMAP_DSS_VIDEO3:
534 case OMAP_DSS_WB:
535 return 0x0088;
536 default: 424 default:
537 BUG(); 425 BUG();
538 return 0;
539 } 426 }
540} 427}
541 428
@@ -547,12 +434,8 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
547 case OMAP_DSS_VIDEO1: 434 case OMAP_DSS_VIDEO1:
548 case OMAP_DSS_VIDEO2: 435 case OMAP_DSS_VIDEO2:
549 return 0x001C; 436 return 0x001C;
550 case OMAP_DSS_VIDEO3:
551 case OMAP_DSS_WB:
552 return 0x00A4;
553 default: 437 default:
554 BUG(); 438 BUG();
555 return 0;
556 } 439 }
557} 440}
558 441
@@ -564,12 +447,8 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
564 case OMAP_DSS_VIDEO1: 447 case OMAP_DSS_VIDEO1:
565 case OMAP_DSS_VIDEO2: 448 case OMAP_DSS_VIDEO2:
566 return 0x0020; 449 return 0x0020;
567 case OMAP_DSS_VIDEO3:
568 case OMAP_DSS_WB:
569 return 0x0098;
570 default: 450 default:
571 BUG(); 451 BUG();
572 return 0;
573 } 452 }
574} 453}
575 454
@@ -580,12 +459,9 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
580 return 0x0034; 459 return 0x0034;
581 case OMAP_DSS_VIDEO1: 460 case OMAP_DSS_VIDEO1:
582 case OMAP_DSS_VIDEO2: 461 case OMAP_DSS_VIDEO2:
583 case OMAP_DSS_VIDEO3:
584 BUG(); 462 BUG();
585 return 0;
586 default: 463 default:
587 BUG(); 464 BUG();
588 return 0;
589 } 465 }
590} 466}
591 467
@@ -596,12 +472,9 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
596 return 0x0038; 472 return 0x0038;
597 case OMAP_DSS_VIDEO1: 473 case OMAP_DSS_VIDEO1:
598 case OMAP_DSS_VIDEO2: 474 case OMAP_DSS_VIDEO2:
599 case OMAP_DSS_VIDEO3:
600 BUG(); 475 BUG();
601 return 0;
602 default: 476 default:
603 BUG(); 477 BUG();
604 return 0;
605 } 478 }
606} 479}
607 480
@@ -610,16 +483,11 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
610 switch (plane) { 483 switch (plane) {
611 case OMAP_DSS_GFX: 484 case OMAP_DSS_GFX:
612 BUG(); 485 BUG();
613 return 0;
614 case OMAP_DSS_VIDEO1: 486 case OMAP_DSS_VIDEO1:
615 case OMAP_DSS_VIDEO2: 487 case OMAP_DSS_VIDEO2:
616 return 0x0024; 488 return 0x0024;
617 case OMAP_DSS_VIDEO3:
618 case OMAP_DSS_WB:
619 return 0x0090;
620 default: 489 default:
621 BUG(); 490 BUG();
622 return 0;
623 } 491 }
624} 492}
625 493
@@ -628,18 +496,12 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
628 switch (plane) { 496 switch (plane) {
629 case OMAP_DSS_GFX: 497 case OMAP_DSS_GFX:
630 BUG(); 498 BUG();
631 return 0;
632 case OMAP_DSS_VIDEO1: 499 case OMAP_DSS_VIDEO1:
633 return 0x0580; 500 return 0x0580;
634 case OMAP_DSS_VIDEO2: 501 case OMAP_DSS_VIDEO2:
635 return 0x055C; 502 return 0x055C;
636 case OMAP_DSS_VIDEO3:
637 return 0x0424;
638 case OMAP_DSS_WB:
639 return 0x290;
640 default: 503 default:
641 BUG(); 504 BUG();
642 return 0;
643 } 505 }
644} 506}
645 507
@@ -648,16 +510,11 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
648 switch (plane) { 510 switch (plane) {
649 case OMAP_DSS_GFX: 511 case OMAP_DSS_GFX:
650 BUG(); 512 BUG();
651 return 0;
652 case OMAP_DSS_VIDEO1: 513 case OMAP_DSS_VIDEO1:
653 case OMAP_DSS_VIDEO2: 514 case OMAP_DSS_VIDEO2:
654 return 0x0028; 515 return 0x0028;
655 case OMAP_DSS_VIDEO3:
656 case OMAP_DSS_WB:
657 return 0x0094;
658 default: 516 default:
659 BUG(); 517 BUG();
660 return 0;
661 } 518 }
662} 519}
663 520
@@ -667,16 +524,11 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
667 switch (plane) { 524 switch (plane) {
668 case OMAP_DSS_GFX: 525 case OMAP_DSS_GFX:
669 BUG(); 526 BUG();
670 return 0;
671 case OMAP_DSS_VIDEO1: 527 case OMAP_DSS_VIDEO1:
672 case OMAP_DSS_VIDEO2: 528 case OMAP_DSS_VIDEO2:
673 return 0x002C; 529 return 0x002C;
674 case OMAP_DSS_VIDEO3:
675 case OMAP_DSS_WB:
676 return 0x0000;
677 default: 530 default:
678 BUG(); 531 BUG();
679 return 0;
680 } 532 }
681} 533}
682 534
@@ -685,18 +537,12 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
685 switch (plane) { 537 switch (plane) {
686 case OMAP_DSS_GFX: 538 case OMAP_DSS_GFX:
687 BUG(); 539 BUG();
688 return 0;
689 case OMAP_DSS_VIDEO1: 540 case OMAP_DSS_VIDEO1:
690 return 0x0584; 541 return 0x0584;
691 case OMAP_DSS_VIDEO2: 542 case OMAP_DSS_VIDEO2:
692 return 0x0560; 543 return 0x0560;
693 case OMAP_DSS_VIDEO3:
694 return 0x0428;
695 case OMAP_DSS_WB:
696 return 0x0294;
697 default: 544 default:
698 BUG(); 545 BUG();
699 return 0;
700 } 546 }
701} 547}
702 548
@@ -705,16 +551,11 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
705 switch (plane) { 551 switch (plane) {
706 case OMAP_DSS_GFX: 552 case OMAP_DSS_GFX:
707 BUG(); 553 BUG();
708 return 0;
709 case OMAP_DSS_VIDEO1: 554 case OMAP_DSS_VIDEO1:
710 case OMAP_DSS_VIDEO2: 555 case OMAP_DSS_VIDEO2:
711 return 0x0030; 556 return 0x0030;
712 case OMAP_DSS_VIDEO3:
713 case OMAP_DSS_WB:
714 return 0x0004;
715 default: 557 default:
716 BUG(); 558 BUG();
717 return 0;
718 } 559 }
719} 560}
720 561
@@ -723,18 +564,12 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
723 switch (plane) { 564 switch (plane) {
724 case OMAP_DSS_GFX: 565 case OMAP_DSS_GFX:
725 BUG(); 566 BUG();
726 return 0;
727 case OMAP_DSS_VIDEO1: 567 case OMAP_DSS_VIDEO1:
728 return 0x0588; 568 return 0x0588;
729 case OMAP_DSS_VIDEO2: 569 case OMAP_DSS_VIDEO2:
730 return 0x0564; 570 return 0x0564;
731 case OMAP_DSS_VIDEO3:
732 return 0x042C;
733 case OMAP_DSS_WB:
734 return 0x0298;
735 default: 571 default:
736 BUG(); 572 BUG();
737 return 0;
738 } 573 }
739} 574}
740 575
@@ -744,16 +579,11 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
744 switch (plane) { 579 switch (plane) {
745 case OMAP_DSS_GFX: 580 case OMAP_DSS_GFX:
746 BUG(); 581 BUG();
747 return 0;
748 case OMAP_DSS_VIDEO1: 582 case OMAP_DSS_VIDEO1:
749 case OMAP_DSS_VIDEO2: 583 case OMAP_DSS_VIDEO2:
750 return 0x0034 + i * 0x8; 584 return 0x0034 + i * 0x8;
751 case OMAP_DSS_VIDEO3:
752 case OMAP_DSS_WB:
753 return 0x0010 + i * 0x8;
754 default: 585 default:
755 BUG(); 586 BUG();
756 return 0;
757 } 587 }
758} 588}
759 589
@@ -763,18 +593,12 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
763 switch (plane) { 593 switch (plane) {
764 case OMAP_DSS_GFX: 594 case OMAP_DSS_GFX:
765 BUG(); 595 BUG();
766 return 0;
767 case OMAP_DSS_VIDEO1: 596 case OMAP_DSS_VIDEO1:
768 return 0x058C + i * 0x8; 597 return 0x058C + i * 0x8;
769 case OMAP_DSS_VIDEO2: 598 case OMAP_DSS_VIDEO2:
770 return 0x0568 + i * 0x8; 599 return 0x0568 + i * 0x8;
771 case OMAP_DSS_VIDEO3:
772 return 0x0430 + i * 0x8;
773 case OMAP_DSS_WB:
774 return 0x02A0 + i * 0x8;
775 default: 600 default:
776 BUG(); 601 BUG();
777 return 0;
778 } 602 }
779} 603}
780 604
@@ -784,16 +608,11 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
784 switch (plane) { 608 switch (plane) {
785 case OMAP_DSS_GFX: 609 case OMAP_DSS_GFX:
786 BUG(); 610 BUG();
787 return 0;
788 case OMAP_DSS_VIDEO1: 611 case OMAP_DSS_VIDEO1:
789 case OMAP_DSS_VIDEO2: 612 case OMAP_DSS_VIDEO2:
790 return 0x0038 + i * 0x8; 613 return 0x0038 + i * 0x8;
791 case OMAP_DSS_VIDEO3:
792 case OMAP_DSS_WB:
793 return 0x0014 + i * 0x8;
794 default: 614 default:
795 BUG(); 615 BUG();
796 return 0;
797 } 616 }
798} 617}
799 618
@@ -803,18 +622,12 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
803 switch (plane) { 622 switch (plane) {
804 case OMAP_DSS_GFX: 623 case OMAP_DSS_GFX:
805 BUG(); 624 BUG();
806 return 0;
807 case OMAP_DSS_VIDEO1: 625 case OMAP_DSS_VIDEO1:
808 return 0x0590 + i * 8; 626 return 0x0590 + i * 8;
809 case OMAP_DSS_VIDEO2: 627 case OMAP_DSS_VIDEO2:
810 return 0x056C + i * 0x8; 628 return 0x056C + i * 0x8;
811 case OMAP_DSS_VIDEO3:
812 return 0x0434 + i * 0x8;
813 case OMAP_DSS_WB:
814 return 0x02A4 + i * 0x8;
815 default: 629 default:
816 BUG(); 630 BUG();
817 return 0;
818 } 631 }
819} 632}
820 633
@@ -824,15 +637,11 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
824 switch (plane) { 637 switch (plane) {
825 case OMAP_DSS_GFX: 638 case OMAP_DSS_GFX:
826 BUG(); 639 BUG();
827 return 0;
828 case OMAP_DSS_VIDEO1: 640 case OMAP_DSS_VIDEO1:
829 case OMAP_DSS_VIDEO2: 641 case OMAP_DSS_VIDEO2:
830 case OMAP_DSS_VIDEO3:
831 case OMAP_DSS_WB:
832 return 0x0074 + i * 0x4; 642 return 0x0074 + i * 0x4;
833 default: 643 default:
834 BUG(); 644 BUG();
835 return 0;
836 } 645 }
837} 646}
838 647
@@ -842,17 +651,12 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
842 switch (plane) { 651 switch (plane) {
843 case OMAP_DSS_GFX: 652 case OMAP_DSS_GFX:
844 BUG(); 653 BUG();
845 return 0;
846 case OMAP_DSS_VIDEO1: 654 case OMAP_DSS_VIDEO1:
847 return 0x0124 + i * 0x4; 655 return 0x0124 + i * 0x4;
848 case OMAP_DSS_VIDEO2: 656 case OMAP_DSS_VIDEO2:
849 return 0x00B4 + i * 0x4; 657 return 0x00B4 + i * 0x4;
850 case OMAP_DSS_VIDEO3:
851 case OMAP_DSS_WB:
852 return 0x0050 + i * 0x4;
853 default: 658 default:
854 BUG(); 659 BUG();
855 return 0;
856 } 660 }
857} 661}
858 662
@@ -862,18 +666,12 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
862 switch (plane) { 666 switch (plane) {
863 case OMAP_DSS_GFX: 667 case OMAP_DSS_GFX:
864 BUG(); 668 BUG();
865 return 0;
866 case OMAP_DSS_VIDEO1: 669 case OMAP_DSS_VIDEO1:
867 return 0x05CC + i * 0x4; 670 return 0x05CC + i * 0x4;
868 case OMAP_DSS_VIDEO2: 671 case OMAP_DSS_VIDEO2:
869 return 0x05A8 + i * 0x4; 672 return 0x05A8 + i * 0x4;
870 case OMAP_DSS_VIDEO3:
871 return 0x0470 + i * 0x4;
872 case OMAP_DSS_WB:
873 return 0x02E0 + i * 0x4;
874 default: 673 default:
875 BUG(); 674 BUG();
876 return 0;
877 } 675 }
878} 676}
879 677
@@ -886,11 +684,8 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
886 return 0x0174; 684 return 0x0174;
887 case OMAP_DSS_VIDEO2: 685 case OMAP_DSS_VIDEO2:
888 return 0x00E8; 686 return 0x00E8;
889 case OMAP_DSS_VIDEO3:
890 return 0x00A0;
891 default: 687 default:
892 BUG(); 688 BUG();
893 return 0;
894 } 689 }
895} 690}
896#endif 691#endif
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c
deleted file mode 100644
index 038c15b0421..00000000000
--- a/drivers/video/omap2/dss/dispc_coefs.c
+++ /dev/null
@@ -1,325 +0,0 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc_coefs.c
3 *
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Chandrabhanu Mahapatra <cmahapatra@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <video/omapdss.h>
22
23#include "dispc.h"
24
25static const struct dispc_coef coef3_M8[8] = {
26 { 0, 0, 128, 0, 0 },
27 { 0, -4, 123, 9, 0 },
28 { 0, -4, 108, 24, 0 },
29 { 0, -2, 87, 43, 0 },
30 { 0, 64, 64, 0, 0 },
31 { 0, 43, 87, -2, 0 },
32 { 0, 24, 108, -4, 0 },
33 { 0, 9, 123, -4, 0 },
34};
35
36static const struct dispc_coef coef3_M9[8] = {
37 { 0, 6, 116, 6, 0 },
38 { 0, 0, 112, 16, 0 },
39 { 0, -2, 100, 30, 0 },
40 { 0, -2, 83, 47, 0 },
41 { 0, 64, 64, 0, 0 },
42 { 0, 47, 83, -2, 0 },
43 { 0, 30, 100, -2, 0 },
44 { 0, 16, 112, 0, 0 },
45};
46
47static const struct dispc_coef coef3_M10[8] = {
48 { 0, 10, 108, 10, 0 },
49 { 0, 3, 104, 21, 0 },
50 { 0, 0, 94, 34, 0 },
51 { 0, -1, 80, 49, 0 },
52 { 0, 64, 64, 0, 0 },
53 { 0, 49, 80, -1, 0 },
54 { 0, 34, 94, 0, 0 },
55 { 0, 21, 104, 3, 0 },
56};
57
58static const struct dispc_coef coef3_M11[8] = {
59 { 0, 14, 100, 14, 0 },
60 { 0, 6, 98, 24, 0 },
61 { 0, 2, 90, 36, 0 },
62 { 0, 0, 78, 50, 0 },
63 { 0, 64, 64, 0, 0 },
64 { 0, 50, 78, 0, 0 },
65 { 0, 36, 90, 2, 0 },
66 { 0, 24, 98, 6, 0 },
67};
68
69static const struct dispc_coef coef3_M12[8] = {
70 { 0, 16, 96, 16, 0 },
71 { 0, 9, 93, 26, 0 },
72 { 0, 4, 86, 38, 0 },
73 { 0, 1, 76, 51, 0 },
74 { 0, 64, 64, 0, 0 },
75 { 0, 51, 76, 1, 0 },
76 { 0, 38, 86, 4, 0 },
77 { 0, 26, 93, 9, 0 },
78};
79
80static const struct dispc_coef coef3_M13[8] = {
81 { 0, 18, 92, 18, 0 },
82 { 0, 10, 90, 28, 0 },
83 { 0, 5, 83, 40, 0 },
84 { 0, 1, 75, 52, 0 },
85 { 0, 64, 64, 0, 0 },
86 { 0, 52, 75, 1, 0 },
87 { 0, 40, 83, 5, 0 },
88 { 0, 28, 90, 10, 0 },
89};
90
91static const struct dispc_coef coef3_M14[8] = {
92 { 0, 20, 88, 20, 0 },
93 { 0, 12, 86, 30, 0 },
94 { 0, 6, 81, 41, 0 },
95 { 0, 2, 74, 52, 0 },
96 { 0, 64, 64, 0, 0 },
97 { 0, 52, 74, 2, 0 },
98 { 0, 41, 81, 6, 0 },
99 { 0, 30, 86, 12, 0 },
100};
101
102static const struct dispc_coef coef3_M16[8] = {
103 { 0, 22, 84, 22, 0 },
104 { 0, 14, 82, 32, 0 },
105 { 0, 8, 78, 42, 0 },
106 { 0, 3, 72, 53, 0 },
107 { 0, 64, 64, 0, 0 },
108 { 0, 53, 72, 3, 0 },
109 { 0, 42, 78, 8, 0 },
110 { 0, 32, 82, 14, 0 },
111};
112
113static const struct dispc_coef coef3_M19[8] = {
114 { 0, 24, 80, 24, 0 },
115 { 0, 16, 79, 33, 0 },
116 { 0, 9, 76, 43, 0 },
117 { 0, 4, 70, 54, 0 },
118 { 0, 64, 64, 0, 0 },
119 { 0, 54, 70, 4, 0 },
120 { 0, 43, 76, 9, 0 },
121 { 0, 33, 79, 16, 0 },
122};
123
124static const struct dispc_coef coef3_M22[8] = {
125 { 0, 25, 78, 25, 0 },
126 { 0, 17, 77, 34, 0 },
127 { 0, 10, 74, 44, 0 },
128 { 0, 5, 69, 54, 0 },
129 { 0, 64, 64, 0, 0 },
130 { 0, 54, 69, 5, 0 },
131 { 0, 44, 74, 10, 0 },
132 { 0, 34, 77, 17, 0 },
133};
134
135static const struct dispc_coef coef3_M26[8] = {
136 { 0, 26, 76, 26, 0 },
137 { 0, 19, 74, 35, 0 },
138 { 0, 11, 72, 45, 0 },
139 { 0, 5, 69, 54, 0 },
140 { 0, 64, 64, 0, 0 },
141 { 0, 54, 69, 5, 0 },
142 { 0, 45, 72, 11, 0 },
143 { 0, 35, 74, 19, 0 },
144};
145
146static const struct dispc_coef coef3_M32[8] = {
147 { 0, 27, 74, 27, 0 },
148 { 0, 19, 73, 36, 0 },
149 { 0, 12, 71, 45, 0 },
150 { 0, 6, 68, 54, 0 },
151 { 0, 64, 64, 0, 0 },
152 { 0, 54, 68, 6, 0 },
153 { 0, 45, 71, 12, 0 },
154 { 0, 36, 73, 19, 0 },
155};
156
157static const struct dispc_coef coef5_M8[8] = {
158 { 0, 0, 128, 0, 0 },
159 { -2, 14, 125, -10, 1 },
160 { -6, 33, 114, -15, 2 },
161 { -10, 55, 98, -16, 1 },
162 { 0, -14, 78, 78, -14 },
163 { 1, -16, 98, 55, -10 },
164 { 2, -15, 114, 33, -6 },
165 { 1, -10, 125, 14, -2 },
166};
167
168static const struct dispc_coef coef5_M9[8] = {
169 { -3, 10, 114, 10, -3 },
170 { -6, 24, 111, 0, -1 },
171 { -8, 40, 103, -7, 0 },
172 { -11, 58, 91, -11, 1 },
173 { 0, -12, 76, 76, -12 },
174 { 1, -11, 91, 58, -11 },
175 { 0, -7, 103, 40, -8 },
176 { -1, 0, 111, 24, -6 },
177};
178
179static const struct dispc_coef coef5_M10[8] = {
180 { -4, 18, 100, 18, -4 },
181 { -6, 30, 99, 8, -3 },
182 { -8, 44, 93, 0, -1 },
183 { -9, 58, 84, -5, 0 },
184 { 0, -8, 72, 72, -8 },
185 { 0, -5, 84, 58, -9 },
186 { -1, 0, 93, 44, -8 },
187 { -3, 8, 99, 30, -6 },
188};
189
190static const struct dispc_coef coef5_M11[8] = {
191 { -5, 23, 92, 23, -5 },
192 { -6, 34, 90, 13, -3 },
193 { -6, 45, 85, 6, -2 },
194 { -6, 57, 78, 0, -1 },
195 { 0, -4, 68, 68, -4 },
196 { -1, 0, 78, 57, -6 },
197 { -2, 6, 85, 45, -6 },
198 { -3, 13, 90, 34, -6 },
199};
200
201static const struct dispc_coef coef5_M12[8] = {
202 { -4, 26, 84, 26, -4 },
203 { -5, 36, 82, 18, -3 },
204 { -4, 46, 78, 10, -2 },
205 { -3, 55, 72, 5, -1 },
206 { 0, 0, 64, 64, 0 },
207 { -1, 5, 72, 55, -3 },
208 { -2, 10, 78, 46, -4 },
209 { -3, 18, 82, 36, -5 },
210};
211
212static const struct dispc_coef coef5_M13[8] = {
213 { -3, 28, 78, 28, -3 },
214 { -3, 37, 76, 21, -3 },
215 { -2, 45, 73, 14, -2 },
216 { 0, 53, 68, 8, -1 },
217 { 0, 3, 61, 61, 3 },
218 { -1, 8, 68, 53, 0 },
219 { -2, 14, 73, 45, -2 },
220 { -3, 21, 76, 37, -3 },
221};
222
223static const struct dispc_coef coef5_M14[8] = {
224 { -2, 30, 72, 30, -2 },
225 { -1, 37, 71, 23, -2 },
226 { 0, 45, 69, 16, -2 },
227 { 3, 52, 64, 10, -1 },
228 { 0, 6, 58, 58, 6 },
229 { -1, 10, 64, 52, 3 },
230 { -2, 16, 69, 45, 0 },
231 { -2, 23, 71, 37, -1 },
232};
233
234static const struct dispc_coef coef5_M16[8] = {
235 { 0, 31, 66, 31, 0 },
236 { 1, 38, 65, 25, -1 },
237 { 3, 44, 62, 20, -1 },
238 { 6, 49, 59, 14, 0 },
239 { 0, 10, 54, 54, 10 },
240 { 0, 14, 59, 49, 6 },
241 { -1, 20, 62, 44, 3 },
242 { -1, 25, 65, 38, 1 },
243};
244
245static const struct dispc_coef coef5_M19[8] = {
246 { 3, 32, 58, 32, 3 },
247 { 4, 38, 58, 27, 1 },
248 { 7, 42, 55, 23, 1 },
249 { 10, 46, 54, 18, 0 },
250 { 0, 14, 50, 50, 14 },
251 { 0, 18, 54, 46, 10 },
252 { 1, 23, 55, 42, 7 },
253 { 1, 27, 58, 38, 4 },
254};
255
256static const struct dispc_coef coef5_M22[8] = {
257 { 4, 33, 54, 33, 4 },
258 { 6, 37, 54, 28, 3 },
259 { 9, 41, 53, 24, 1 },
260 { 12, 45, 51, 20, 0 },
261 { 0, 16, 48, 48, 16 },
262 { 0, 20, 51, 45, 12 },
263 { 1, 24, 53, 41, 9 },
264 { 3, 28, 54, 37, 6 },
265};
266
267static const struct dispc_coef coef5_M26[8] = {
268 { 6, 33, 50, 33, 6 },
269 { 8, 36, 51, 29, 4 },
270 { 11, 40, 50, 25, 2 },
271 { 14, 43, 48, 22, 1 },
272 { 0, 18, 46, 46, 18 },
273 { 1, 22, 48, 43, 14 },
274 { 2, 25, 50, 40, 11 },
275 { 4, 29, 51, 36, 8 },
276};
277
278static const struct dispc_coef coef5_M32[8] = {
279 { 7, 33, 48, 33, 7 },
280 { 10, 36, 48, 29, 5 },
281 { 13, 39, 47, 26, 3 },
282 { 16, 42, 46, 23, 1 },
283 { 0, 19, 45, 45, 19 },
284 { 1, 23, 46, 42, 16 },
285 { 3, 26, 47, 39, 13 },
286 { 5, 29, 48, 36, 10 },
287};
288
289const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
290{
291 int i;
292 static const struct {
293 int Mmin;
294 int Mmax;
295 const struct dispc_coef *coef_3;
296 const struct dispc_coef *coef_5;
297 } coefs[] = {
298 { 27, 32, coef3_M32, coef5_M32 },
299 { 23, 26, coef3_M26, coef5_M26 },
300 { 20, 22, coef3_M22, coef5_M22 },
301 { 17, 19, coef3_M19, coef5_M19 },
302 { 15, 16, coef3_M16, coef5_M16 },
303 { 14, 14, coef3_M14, coef5_M14 },
304 { 13, 13, coef3_M13, coef5_M13 },
305 { 12, 12, coef3_M12, coef5_M12 },
306 { 11, 11, coef3_M11, coef5_M11 },
307 { 10, 10, coef3_M10, coef5_M10 },
308 { 9, 9, coef3_M9, coef5_M9 },
309 { 4, 8, coef3_M8, coef5_M8 },
310 /*
311 * When upscaling more than two times, blockiness and outlines
312 * around the image are observed when M8 tables are used. M11,
313 * M16 and M19 tables are used to prevent this.
314 */
315 { 3, 3, coef3_M11, coef5_M11 },
316 { 2, 2, coef3_M16, coef5_M16 },
317 { 0, 1, coef3_M19, coef5_M19 },
318 };
319
320 inc /= 128;
321 for (i = 0; i < ARRAY_SIZE(coefs); ++i)
322 if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
323 return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
324 return NULL;
325}
diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/omap2/dss/display-sysfs.c
deleted file mode 100644
index 18211a9ab35..00000000000
--- a/drivers/video/omap2/dss/display-sysfs.c
+++ /dev/null
@@ -1,321 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "DISPLAY"
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/jiffies.h>
26#include <linux/platform_device.h>
27
28#include <video/omapdss.h>
29#include "dss.h"
30#include "dss_features.h"
31
32static ssize_t display_enabled_show(struct device *dev,
33 struct device_attribute *attr, char *buf)
34{
35 struct omap_dss_device *dssdev = to_dss_device(dev);
36 bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
37
38 return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
39}
40
41static ssize_t display_enabled_store(struct device *dev,
42 struct device_attribute *attr,
43 const char *buf, size_t size)
44{
45 struct omap_dss_device *dssdev = to_dss_device(dev);
46 int r;
47 bool enabled;
48
49 r = strtobool(buf, &enabled);
50 if (r)
51 return r;
52
53 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
54 if (enabled) {
55 r = dssdev->driver->enable(dssdev);
56 if (r)
57 return r;
58 } else {
59 dssdev->driver->disable(dssdev);
60 }
61 }
62
63 return size;
64}
65
66static ssize_t display_tear_show(struct device *dev,
67 struct device_attribute *attr, char *buf)
68{
69 struct omap_dss_device *dssdev = to_dss_device(dev);
70 return snprintf(buf, PAGE_SIZE, "%d\n",
71 dssdev->driver->get_te ?
72 dssdev->driver->get_te(dssdev) : 0);
73}
74
75static ssize_t display_tear_store(struct device *dev,
76 struct device_attribute *attr, const char *buf, size_t size)
77{
78 struct omap_dss_device *dssdev = to_dss_device(dev);
79 int r;
80 bool te;
81
82 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
83 return -ENOENT;
84
85 r = strtobool(buf, &te);
86 if (r)
87 return r;
88
89 r = dssdev->driver->enable_te(dssdev, te);
90 if (r)
91 return r;
92
93 return size;
94}
95
96static ssize_t display_timings_show(struct device *dev,
97 struct device_attribute *attr, char *buf)
98{
99 struct omap_dss_device *dssdev = to_dss_device(dev);
100 struct omap_video_timings t;
101
102 if (!dssdev->driver->get_timings)
103 return -ENOENT;
104
105 dssdev->driver->get_timings(dssdev, &t);
106
107 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
108 t.pixel_clock,
109 t.x_res, t.hfp, t.hbp, t.hsw,
110 t.y_res, t.vfp, t.vbp, t.vsw);
111}
112
113static ssize_t display_timings_store(struct device *dev,
114 struct device_attribute *attr, const char *buf, size_t size)
115{
116 struct omap_dss_device *dssdev = to_dss_device(dev);
117 struct omap_video_timings t = dssdev->panel.timings;
118 int r, found;
119
120 if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
121 return -ENOENT;
122
123 found = 0;
124#ifdef CONFIG_OMAP2_DSS_VENC
125 if (strncmp("pal", buf, 3) == 0) {
126 t = omap_dss_pal_timings;
127 found = 1;
128 } else if (strncmp("ntsc", buf, 4) == 0) {
129 t = omap_dss_ntsc_timings;
130 found = 1;
131 }
132#endif
133 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
134 &t.pixel_clock,
135 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
136 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
137 return -EINVAL;
138
139 r = dssdev->driver->check_timings(dssdev, &t);
140 if (r)
141 return r;
142
143 dssdev->driver->disable(dssdev);
144 dssdev->driver->set_timings(dssdev, &t);
145 r = dssdev->driver->enable(dssdev);
146 if (r)
147 return r;
148
149 return size;
150}
151
152static ssize_t display_rotate_show(struct device *dev,
153 struct device_attribute *attr, char *buf)
154{
155 struct omap_dss_device *dssdev = to_dss_device(dev);
156 int rotate;
157 if (!dssdev->driver->get_rotate)
158 return -ENOENT;
159 rotate = dssdev->driver->get_rotate(dssdev);
160 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
161}
162
163static ssize_t display_rotate_store(struct device *dev,
164 struct device_attribute *attr, const char *buf, size_t size)
165{
166 struct omap_dss_device *dssdev = to_dss_device(dev);
167 int rot, r;
168
169 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
170 return -ENOENT;
171
172 r = kstrtoint(buf, 0, &rot);
173 if (r)
174 return r;
175
176 r = dssdev->driver->set_rotate(dssdev, rot);
177 if (r)
178 return r;
179
180 return size;
181}
182
183static ssize_t display_mirror_show(struct device *dev,
184 struct device_attribute *attr, char *buf)
185{
186 struct omap_dss_device *dssdev = to_dss_device(dev);
187 int mirror;
188 if (!dssdev->driver->get_mirror)
189 return -ENOENT;
190 mirror = dssdev->driver->get_mirror(dssdev);
191 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
192}
193
194static ssize_t display_mirror_store(struct device *dev,
195 struct device_attribute *attr, const char *buf, size_t size)
196{
197 struct omap_dss_device *dssdev = to_dss_device(dev);
198 int r;
199 bool mirror;
200
201 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
202 return -ENOENT;
203
204 r = strtobool(buf, &mirror);
205 if (r)
206 return r;
207
208 r = dssdev->driver->set_mirror(dssdev, mirror);
209 if (r)
210 return r;
211
212 return size;
213}
214
215static ssize_t display_wss_show(struct device *dev,
216 struct device_attribute *attr, char *buf)
217{
218 struct omap_dss_device *dssdev = to_dss_device(dev);
219 unsigned int wss;
220
221 if (!dssdev->driver->get_wss)
222 return -ENOENT;
223
224 wss = dssdev->driver->get_wss(dssdev);
225
226 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
227}
228
229static ssize_t display_wss_store(struct device *dev,
230 struct device_attribute *attr, const char *buf, size_t size)
231{
232 struct omap_dss_device *dssdev = to_dss_device(dev);
233 u32 wss;
234 int r;
235
236 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
237 return -ENOENT;
238
239 r = kstrtou32(buf, 0, &wss);
240 if (r)
241 return r;
242
243 if (wss > 0xfffff)
244 return -EINVAL;
245
246 r = dssdev->driver->set_wss(dssdev, wss);
247 if (r)
248 return r;
249
250 return size;
251}
252
253static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
254 display_enabled_show, display_enabled_store);
255static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
256 display_tear_show, display_tear_store);
257static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
258 display_timings_show, display_timings_store);
259static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
260 display_rotate_show, display_rotate_store);
261static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
262 display_mirror_show, display_mirror_store);
263static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
264 display_wss_show, display_wss_store);
265
266static struct device_attribute *display_sysfs_attrs[] = {
267 &dev_attr_enabled,
268 &dev_attr_tear_elim,
269 &dev_attr_timings,
270 &dev_attr_rotate,
271 &dev_attr_mirror,
272 &dev_attr_wss,
273 NULL
274};
275
276int display_init_sysfs(struct platform_device *pdev,
277 struct omap_dss_device *dssdev)
278{
279 struct device_attribute *attr;
280 int i, r;
281
282 /* create device sysfs files */
283 i = 0;
284 while ((attr = display_sysfs_attrs[i++]) != NULL) {
285 r = device_create_file(&dssdev->dev, attr);
286 if (r) {
287 for (i = i - 2; i >= 0; i--) {
288 attr = display_sysfs_attrs[i];
289 device_remove_file(&dssdev->dev, attr);
290 }
291
292 DSSERR("failed to create sysfs file\n");
293 return r;
294 }
295 }
296
297 /* create display? sysfs links */
298 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
299 dev_name(&dssdev->dev));
300 if (r) {
301 while ((attr = display_sysfs_attrs[i++]) != NULL)
302 device_remove_file(&dssdev->dev, attr);
303
304 DSSERR("failed to create sysfs display link\n");
305 return r;
306 }
307
308 return 0;
309}
310
311void display_uninit_sysfs(struct platform_device *pdev,
312 struct omap_dss_device *dssdev)
313{
314 struct device_attribute *attr;
315 int i = 0;
316
317 sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
318
319 while ((attr = display_sysfs_attrs[i++]) != NULL)
320 device_remove_file(&dssdev->dev, attr);
321}
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 0aa8ad8f966..94495e45ec5 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -31,6 +31,249 @@
31#include "dss.h" 31#include "dss.h"
32#include "dss_features.h" 32#include "dss_features.h"
33 33
34static ssize_t display_enabled_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 bool enabled = dssdev->state != OMAP_DSS_DISPLAY_DISABLED;
39
40 return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
41}
42
43static ssize_t display_enabled_store(struct device *dev,
44 struct device_attribute *attr,
45 const char *buf, size_t size)
46{
47 struct omap_dss_device *dssdev = to_dss_device(dev);
48 int r, enabled;
49
50 r = kstrtoint(buf, 0, &enabled);
51 if (r)
52 return r;
53
54 enabled = !!enabled;
55
56 if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
57 if (enabled) {
58 r = dssdev->driver->enable(dssdev);
59 if (r)
60 return r;
61 } else {
62 dssdev->driver->disable(dssdev);
63 }
64 }
65
66 return size;
67}
68
69static ssize_t display_tear_show(struct device *dev,
70 struct device_attribute *attr, char *buf)
71{
72 struct omap_dss_device *dssdev = to_dss_device(dev);
73 return snprintf(buf, PAGE_SIZE, "%d\n",
74 dssdev->driver->get_te ?
75 dssdev->driver->get_te(dssdev) : 0);
76}
77
78static ssize_t display_tear_store(struct device *dev,
79 struct device_attribute *attr, const char *buf, size_t size)
80{
81 struct omap_dss_device *dssdev = to_dss_device(dev);
82 int te, r;
83
84 if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
85 return -ENOENT;
86
87 r = kstrtoint(buf, 0, &te);
88 if (r)
89 return r;
90
91 te = !!te;
92
93 r = dssdev->driver->enable_te(dssdev, te);
94 if (r)
95 return r;
96
97 return size;
98}
99
100static ssize_t display_timings_show(struct device *dev,
101 struct device_attribute *attr, char *buf)
102{
103 struct omap_dss_device *dssdev = to_dss_device(dev);
104 struct omap_video_timings t;
105
106 if (!dssdev->driver->get_timings)
107 return -ENOENT;
108
109 dssdev->driver->get_timings(dssdev, &t);
110
111 return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
112 t.pixel_clock,
113 t.x_res, t.hfp, t.hbp, t.hsw,
114 t.y_res, t.vfp, t.vbp, t.vsw);
115}
116
117static ssize_t display_timings_store(struct device *dev,
118 struct device_attribute *attr, const char *buf, size_t size)
119{
120 struct omap_dss_device *dssdev = to_dss_device(dev);
121 struct omap_video_timings t;
122 int r, found;
123
124 if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
125 return -ENOENT;
126
127 found = 0;
128#ifdef CONFIG_OMAP2_DSS_VENC
129 if (strncmp("pal", buf, 3) == 0) {
130 t = omap_dss_pal_timings;
131 found = 1;
132 } else if (strncmp("ntsc", buf, 4) == 0) {
133 t = omap_dss_ntsc_timings;
134 found = 1;
135 }
136#endif
137 if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
138 &t.pixel_clock,
139 &t.x_res, &t.hfp, &t.hbp, &t.hsw,
140 &t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
141 return -EINVAL;
142
143 r = dssdev->driver->check_timings(dssdev, &t);
144 if (r)
145 return r;
146
147 dssdev->driver->set_timings(dssdev, &t);
148
149 return size;
150}
151
152static ssize_t display_rotate_show(struct device *dev,
153 struct device_attribute *attr, char *buf)
154{
155 struct omap_dss_device *dssdev = to_dss_device(dev);
156 int rotate;
157 if (!dssdev->driver->get_rotate)
158 return -ENOENT;
159 rotate = dssdev->driver->get_rotate(dssdev);
160 return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
161}
162
163static ssize_t display_rotate_store(struct device *dev,
164 struct device_attribute *attr, const char *buf, size_t size)
165{
166 struct omap_dss_device *dssdev = to_dss_device(dev);
167 int rot, r;
168
169 if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
170 return -ENOENT;
171
172 r = kstrtoint(buf, 0, &rot);
173 if (r)
174 return r;
175
176 r = dssdev->driver->set_rotate(dssdev, rot);
177 if (r)
178 return r;
179
180 return size;
181}
182
183static ssize_t display_mirror_show(struct device *dev,
184 struct device_attribute *attr, char *buf)
185{
186 struct omap_dss_device *dssdev = to_dss_device(dev);
187 int mirror;
188 if (!dssdev->driver->get_mirror)
189 return -ENOENT;
190 mirror = dssdev->driver->get_mirror(dssdev);
191 return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
192}
193
194static ssize_t display_mirror_store(struct device *dev,
195 struct device_attribute *attr, const char *buf, size_t size)
196{
197 struct omap_dss_device *dssdev = to_dss_device(dev);
198 int mirror, r;
199
200 if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
201 return -ENOENT;
202
203 r = kstrtoint(buf, 0, &mirror);
204 if (r)
205 return r;
206
207 mirror = !!mirror;
208
209 r = dssdev->driver->set_mirror(dssdev, mirror);
210 if (r)
211 return r;
212
213 return size;
214}
215
216static ssize_t display_wss_show(struct device *dev,
217 struct device_attribute *attr, char *buf)
218{
219 struct omap_dss_device *dssdev = to_dss_device(dev);
220 unsigned int wss;
221
222 if (!dssdev->driver->get_wss)
223 return -ENOENT;
224
225 wss = dssdev->driver->get_wss(dssdev);
226
227 return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
228}
229
230static ssize_t display_wss_store(struct device *dev,
231 struct device_attribute *attr, const char *buf, size_t size)
232{
233 struct omap_dss_device *dssdev = to_dss_device(dev);
234 u32 wss;
235 int r;
236
237 if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
238 return -ENOENT;
239
240 r = kstrtou32(buf, 0, &wss);
241 if (r)
242 return r;
243
244 if (wss > 0xfffff)
245 return -EINVAL;
246
247 r = dssdev->driver->set_wss(dssdev, wss);
248 if (r)
249 return r;
250
251 return size;
252}
253
254static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
255 display_enabled_show, display_enabled_store);
256static DEVICE_ATTR(tear_elim, S_IRUGO|S_IWUSR,
257 display_tear_show, display_tear_store);
258static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
259 display_timings_show, display_timings_store);
260static DEVICE_ATTR(rotate, S_IRUGO|S_IWUSR,
261 display_rotate_show, display_rotate_store);
262static DEVICE_ATTR(mirror, S_IRUGO|S_IWUSR,
263 display_mirror_show, display_mirror_store);
264static DEVICE_ATTR(wss, S_IRUGO|S_IWUSR,
265 display_wss_show, display_wss_store);
266
267static struct device_attribute *display_sysfs_attrs[] = {
268 &dev_attr_enabled,
269 &dev_attr_tear_elim,
270 &dev_attr_timings,
271 &dev_attr_rotate,
272 &dev_attr_mirror,
273 &dev_attr_wss,
274 NULL
275};
276
34void omapdss_default_get_resolution(struct omap_dss_device *dssdev, 277void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
35 u16 *xres, u16 *yres) 278 u16 *xres, u16 *yres)
36{ 279{
@@ -39,6 +282,16 @@ void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
39} 282}
40EXPORT_SYMBOL(omapdss_default_get_resolution); 283EXPORT_SYMBOL(omapdss_default_get_resolution);
41 284
285void default_get_overlay_fifo_thresholds(enum omap_plane plane,
286 u32 fifo_size, u32 burst_size,
287 u32 *fifo_low, u32 *fifo_high)
288{
289 unsigned buf_unit = dss_feat_get_buffer_size_unit();
290
291 *fifo_high = fifo_size - buf_unit;
292 *fifo_low = fifo_size - burst_size;
293}
294
42int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) 295int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
43{ 296{
44 switch (dssdev->type) { 297 switch (dssdev->type) {
@@ -49,12 +302,8 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
49 return 16; 302 return 16;
50 303
51 case OMAP_DISPLAY_TYPE_DBI: 304 case OMAP_DISPLAY_TYPE_DBI:
52 if (dssdev->ctrl.pixel_size == 24)
53 return 24;
54 else
55 return 16;
56 case OMAP_DISPLAY_TYPE_DSI: 305 case OMAP_DISPLAY_TYPE_DSI:
57 if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) 306 if (dssdev->ctrl.pixel_size == 24)
58 return 24; 307 return 24;
59 else 308 else
60 return 16; 309 return 16;
@@ -64,20 +313,125 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
64 return 24; 313 return 24;
65 default: 314 default:
66 BUG(); 315 BUG();
67 return 0;
68 } 316 }
69} 317}
70EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); 318EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
71 319
72void omapdss_default_get_timings(struct omap_dss_device *dssdev, 320/* Checks if replication logic should be used. Only use for active matrix,
73 struct omap_video_timings *timings) 321 * when overlay is in RGB12U or RGB16 mode, and LCD interface is
322 * 18bpp or 24bpp */
323bool dss_use_replication(struct omap_dss_device *dssdev,
324 enum omap_color_mode mode)
325{
326 int bpp;
327
328 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16)
329 return false;
330
331 if (dssdev->type == OMAP_DISPLAY_TYPE_DPI &&
332 (dssdev->panel.config & OMAP_DSS_LCD_TFT) == 0)
333 return false;
334
335 switch (dssdev->type) {
336 case OMAP_DISPLAY_TYPE_DPI:
337 bpp = dssdev->phy.dpi.data_lines;
338 break;
339 case OMAP_DISPLAY_TYPE_HDMI:
340 case OMAP_DISPLAY_TYPE_VENC:
341 case OMAP_DISPLAY_TYPE_SDI:
342 bpp = 24;
343 break;
344 case OMAP_DISPLAY_TYPE_DBI:
345 case OMAP_DISPLAY_TYPE_DSI:
346 bpp = dssdev->ctrl.pixel_size;
347 break;
348 default:
349 BUG();
350 }
351
352 return bpp > 16;
353}
354
355void dss_init_device(struct platform_device *pdev,
356 struct omap_dss_device *dssdev)
74{ 357{
75 *timings = dssdev->panel.timings; 358 struct device_attribute *attr;
359 int i;
360 int r;
361
362 switch (dssdev->type) {
363#ifdef CONFIG_OMAP2_DSS_DPI
364 case OMAP_DISPLAY_TYPE_DPI:
365 r = dpi_init_display(dssdev);
366 break;
367#endif
368#ifdef CONFIG_OMAP2_DSS_RFBI
369 case OMAP_DISPLAY_TYPE_DBI:
370 r = rfbi_init_display(dssdev);
371 break;
372#endif
373#ifdef CONFIG_OMAP2_DSS_VENC
374 case OMAP_DISPLAY_TYPE_VENC:
375 r = venc_init_display(dssdev);
376 break;
377#endif
378#ifdef CONFIG_OMAP2_DSS_SDI
379 case OMAP_DISPLAY_TYPE_SDI:
380 r = sdi_init_display(dssdev);
381 break;
382#endif
383#ifdef CONFIG_OMAP2_DSS_DSI
384 case OMAP_DISPLAY_TYPE_DSI:
385 r = dsi_init_display(dssdev);
386 break;
387#endif
388 case OMAP_DISPLAY_TYPE_HDMI:
389 r = hdmi_init_display(dssdev);
390 break;
391 default:
392 DSSERR("Support for display '%s' not compiled in.\n",
393 dssdev->name);
394 return;
395 }
396
397 if (r) {
398 DSSERR("failed to init display %s\n", dssdev->name);
399 return;
400 }
401
402 /* create device sysfs files */
403 i = 0;
404 while ((attr = display_sysfs_attrs[i++]) != NULL) {
405 r = device_create_file(&dssdev->dev, attr);
406 if (r)
407 DSSERR("failed to create sysfs file\n");
408 }
409
410 /* create display? sysfs links */
411 r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
412 dev_name(&dssdev->dev));
413 if (r)
414 DSSERR("failed to create sysfs display link\n");
415}
416
417void dss_uninit_device(struct platform_device *pdev,
418 struct omap_dss_device *dssdev)
419{
420 struct device_attribute *attr;
421 int i = 0;
422
423 sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
424
425 while ((attr = display_sysfs_attrs[i++]) != NULL)
426 device_remove_file(&dssdev->dev, attr);
427
428 if (dssdev->manager)
429 dssdev->manager->unset_device(dssdev->manager);
76} 430}
77EXPORT_SYMBOL(omapdss_default_get_timings);
78 431
79static int dss_suspend_device(struct device *dev, void *data) 432static int dss_suspend_device(struct device *dev, void *data)
80{ 433{
434 int r;
81 struct omap_dss_device *dssdev = to_dss_device(dev); 435 struct omap_dss_device *dssdev = to_dss_device(dev);
82 436
83 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 437 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
@@ -85,7 +439,15 @@ static int dss_suspend_device(struct device *dev, void *data)
85 return 0; 439 return 0;
86 } 440 }
87 441
88 dssdev->driver->disable(dssdev); 442 if (!dssdev->driver->suspend) {
443 DSSERR("display '%s' doesn't implement suspend\n",
444 dssdev->name);
445 return -ENOSYS;
446 }
447
448 r = dssdev->driver->suspend(dssdev);
449 if (r)
450 return r;
89 451
90 dssdev->activate_after_resume = true; 452 dssdev->activate_after_resume = true;
91 453
@@ -112,8 +474,8 @@ static int dss_resume_device(struct device *dev, void *data)
112 int r; 474 int r;
113 struct omap_dss_device *dssdev = to_dss_device(dev); 475 struct omap_dss_device *dssdev = to_dss_device(dev);
114 476
115 if (dssdev->activate_after_resume) { 477 if (dssdev->activate_after_resume && dssdev->driver->resume) {
116 r = dssdev->driver->enable(dssdev); 478 r = dssdev->driver->resume(dssdev);
117 if (r) 479 if (r)
118 return r; 480 return r;
119 } 481 }
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 4af136a04e5..f053b180ecd 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -24,84 +24,55 @@
24 24
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/export.h>
28#include <linux/err.h> 27#include <linux/err.h>
29#include <linux/errno.h> 28#include <linux/errno.h>
30#include <linux/platform_device.h> 29#include <linux/platform_device.h>
31#include <linux/regulator/consumer.h> 30#include <linux/regulator/consumer.h>
32#include <linux/string.h>
33 31
34#include <video/omapdss.h> 32#include <video/omapdss.h>
33#include <plat/cpu.h>
35 34
36#include "dss.h" 35#include "dss.h"
37#include "dss_features.h"
38 36
39static struct { 37static struct {
40 struct regulator *vdds_dsi_reg; 38 struct regulator *vdds_dsi_reg;
41 struct platform_device *dsidev; 39 struct platform_device *dsidev;
42
43 struct mutex lock;
44
45 struct omap_video_timings timings;
46 struct dss_lcd_mgr_config mgr_config;
47 int data_lines;
48
49 struct omap_dss_output output;
50} dpi; 40} dpi;
51 41
52static struct platform_device *dpi_get_dsidev(enum omap_channel channel) 42static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
53{ 43{
54 /* 44 int dsi_module;
55 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
56 * would also be used for DISPC fclk. Meaning, when the DPI output is
57 * disabled, DISPC clock will be disabled, and TV out will stop.
58 */
59 switch (omapdss_get_version()) {
60 case OMAPDSS_VER_OMAP24xx:
61 case OMAPDSS_VER_OMAP34xx_ES1:
62 case OMAPDSS_VER_OMAP34xx_ES3:
63 case OMAPDSS_VER_OMAP3630:
64 case OMAPDSS_VER_AM35xx:
65 return NULL;
66 default:
67 break;
68 }
69 45
70 switch (channel) { 46 dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
71 case OMAP_DSS_CHANNEL_LCD: 47
72 return dsi_get_dsidev_from_id(0); 48 return dsi_get_dsidev_from_id(dsi_module);
73 case OMAP_DSS_CHANNEL_LCD2:
74 return dsi_get_dsidev_from_id(1);
75 default:
76 return NULL;
77 }
78} 49}
79 50
80static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel) 51static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
81{ 52{
82 switch (channel) { 53 if (dssdev->clocks.dispc.dispc_fclk_src ==
83 case OMAP_DSS_CHANNEL_LCD: 54 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
84 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC; 55 dssdev->clocks.dispc.dispc_fclk_src ==
85 case OMAP_DSS_CHANNEL_LCD2: 56 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
86 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; 57 dssdev->clocks.dispc.channel.lcd_clk_src ==
87 default: 58 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
88 /* this shouldn't happen */ 59 dssdev->clocks.dispc.channel.lcd_clk_src ==
89 WARN_ON(1); 60 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
90 return OMAP_DSS_CLK_SRC_FCK; 61 return true;
91 } 62 else
63 return false;
92} 64}
93 65
94static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, 66static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
95 unsigned long pck_req, unsigned long *fck, int *lck_div, 67 unsigned long pck_req, unsigned long *fck, int *lck_div,
96 int *pck_div) 68 int *pck_div)
97{ 69{
98 struct omap_overlay_manager *mgr = dssdev->output->manager;
99 struct dsi_clock_info dsi_cinfo; 70 struct dsi_clock_info dsi_cinfo;
100 struct dispc_clock_info dispc_cinfo; 71 struct dispc_clock_info dispc_cinfo;
101 int r; 72 int r;
102 73
103 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo, 74 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req,
104 &dispc_cinfo); 75 &dsi_cinfo, &dispc_cinfo);
105 if (r) 76 if (r)
106 return r; 77 return r;
107 78
@@ -109,10 +80,11 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
109 if (r) 80 if (r)
110 return r; 81 return r;
111 82
112 dss_select_lcd_clk_source(mgr->id, 83 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
113 dpi_get_alt_clk_src(mgr->id));
114 84
115 dpi.mgr_config.clock_info = dispc_cinfo; 85 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
86 if (r)
87 return r;
116 88
117 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 89 *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
118 *lck_div = dispc_cinfo.lck_div; 90 *lck_div = dispc_cinfo.lck_div;
@@ -121,7 +93,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev,
121 return 0; 93 return 0;
122} 94}
123 95
124static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, 96static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
125 unsigned long pck_req, unsigned long *fck, int *lck_div, 97 unsigned long pck_req, unsigned long *fck, int *lck_div,
126 int *pck_div) 98 int *pck_div)
127{ 99{
@@ -129,7 +101,7 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
129 struct dispc_clock_info dispc_cinfo; 101 struct dispc_clock_info dispc_cinfo;
130 int r; 102 int r;
131 103
132 r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo); 104 r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo);
133 if (r) 105 if (r)
134 return r; 106 return r;
135 107
@@ -137,7 +109,9 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
137 if (r) 109 if (r)
138 return r; 110 return r;
139 111
140 dpi.mgr_config.clock_info = dispc_cinfo; 112 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
113 if (r)
114 return r;
141 115
142 *fck = dss_cinfo.fck; 116 *fck = dss_cinfo.fck;
143 *lck_div = dispc_cinfo.lck_div; 117 *lck_div = dispc_cinfo.lck_div;
@@ -148,19 +122,24 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev,
148 122
149static int dpi_set_mode(struct omap_dss_device *dssdev) 123static int dpi_set_mode(struct omap_dss_device *dssdev)
150{ 124{
151 struct omap_video_timings *t = &dpi.timings; 125 struct omap_video_timings *t = &dssdev->panel.timings;
152 struct omap_overlay_manager *mgr = dssdev->output->manager;
153 int lck_div = 0, pck_div = 0; 126 int lck_div = 0, pck_div = 0;
154 unsigned long fck = 0; 127 unsigned long fck = 0;
155 unsigned long pck; 128 unsigned long pck;
129 bool is_tft;
156 int r = 0; 130 int r = 0;
157 131
158 if (dpi.dsidev) 132 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
159 r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck, 133 dssdev->panel.acbi, dssdev->panel.acb);
160 &lck_div, &pck_div); 134
135 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
136
137 if (dpi_use_dsi_pll(dssdev))
138 r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000,
139 &fck, &lck_div, &pck_div);
161 else 140 else
162 r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck, 141 r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
163 &lck_div, &pck_div); 142 &fck, &lck_div, &pck_div);
164 if (r) 143 if (r)
165 return r; 144 return r;
166 145
@@ -174,67 +153,52 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
174 t->pixel_clock = pck; 153 t->pixel_clock = pck;
175 } 154 }
176 155
177 dss_mgr_set_timings(mgr, t); 156 dispc_set_lcd_timings(dssdev->manager->id, t);
178 157
179 return 0; 158 return 0;
180} 159}
181 160
182static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) 161static void dpi_basic_init(struct omap_dss_device *dssdev)
183{ 162{
184 struct omap_overlay_manager *mgr = dssdev->output->manager; 163 bool is_tft;
185 164
186 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 165 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
187 166
188 dpi.mgr_config.stallmode = false; 167 dispc_set_parallel_interface_mode(dssdev->manager->id,
189 dpi.mgr_config.fifohandcheck = false; 168 OMAP_DSS_PARALLELMODE_BYPASS);
190 169 dispc_set_lcd_display_type(dssdev->manager->id, is_tft ?
191 dpi.mgr_config.video_port_width = dpi.data_lines; 170 OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN);
192 171 dispc_set_tft_data_lines(dssdev->manager->id,
193 dpi.mgr_config.lcden_sig_polarity = 0; 172 dssdev->phy.dpi.data_lines);
194
195 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config);
196} 173}
197 174
198int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) 175int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
199{ 176{
200 struct omap_dss_output *out = dssdev->output;
201 int r; 177 int r;
202 178
203 mutex_lock(&dpi.lock);
204
205 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) {
206 DSSERR("no VDSS_DSI regulator\n");
207 r = -ENODEV;
208 goto err_no_reg;
209 }
210
211 if (out == NULL || out->manager == NULL) {
212 DSSERR("failed to enable display: no output/manager\n");
213 r = -ENODEV;
214 goto err_no_out_mgr;
215 }
216
217 r = omap_dss_start_device(dssdev); 179 r = omap_dss_start_device(dssdev);
218 if (r) { 180 if (r) {
219 DSSERR("failed to start device\n"); 181 DSSERR("failed to start device\n");
220 goto err_start_dev; 182 goto err_start_dev;
221 } 183 }
222 184
223 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) { 185 if (cpu_is_omap34xx()) {
224 r = regulator_enable(dpi.vdds_dsi_reg); 186 r = regulator_enable(dpi.vdds_dsi_reg);
225 if (r) 187 if (r)
226 goto err_reg_enable; 188 goto err_reg_enable;
227 } 189 }
228 190
191 r = dss_runtime_get();
192 if (r)
193 goto err_get_dss;
194
229 r = dispc_runtime_get(); 195 r = dispc_runtime_get();
230 if (r) 196 if (r)
231 goto err_get_dispc; 197 goto err_get_dispc;
232 198
233 r = dss_dpi_select_source(dssdev->channel); 199 dpi_basic_init(dssdev);
234 if (r)
235 goto err_src_sel;
236 200
237 if (dpi.dsidev) { 201 if (dpi_use_dsi_pll(dssdev)) {
238 r = dsi_runtime_get(dpi.dsidev); 202 r = dsi_runtime_get(dpi.dsidev);
239 if (r) 203 if (r)
240 goto err_get_dsi; 204 goto err_get_dsi;
@@ -248,98 +212,100 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
248 if (r) 212 if (r)
249 goto err_set_mode; 213 goto err_set_mode;
250 214
251 dpi_config_lcd_manager(dssdev);
252
253 mdelay(2); 215 mdelay(2);
254 216
255 r = dss_mgr_enable(out->manager); 217 dssdev->manager->enable(dssdev->manager);
256 if (r)
257 goto err_mgr_enable;
258
259 mutex_unlock(&dpi.lock);
260 218
261 return 0; 219 return 0;
262 220
263err_mgr_enable:
264err_set_mode: 221err_set_mode:
265 if (dpi.dsidev) 222 if (dpi_use_dsi_pll(dssdev))
266 dsi_pll_uninit(dpi.dsidev, true); 223 dsi_pll_uninit(dpi.dsidev, true);
267err_dsi_pll_init: 224err_dsi_pll_init:
268 if (dpi.dsidev) 225 if (dpi_use_dsi_pll(dssdev))
269 dsi_runtime_put(dpi.dsidev); 226 dsi_runtime_put(dpi.dsidev);
270err_get_dsi: 227err_get_dsi:
271err_src_sel:
272 dispc_runtime_put(); 228 dispc_runtime_put();
273err_get_dispc: 229err_get_dispc:
274 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 230 dss_runtime_put();
231err_get_dss:
232 if (cpu_is_omap34xx())
275 regulator_disable(dpi.vdds_dsi_reg); 233 regulator_disable(dpi.vdds_dsi_reg);
276err_reg_enable: 234err_reg_enable:
277 omap_dss_stop_device(dssdev); 235 omap_dss_stop_device(dssdev);
278err_start_dev: 236err_start_dev:
279err_no_out_mgr:
280err_no_reg:
281 mutex_unlock(&dpi.lock);
282 return r; 237 return r;
283} 238}
284EXPORT_SYMBOL(omapdss_dpi_display_enable); 239EXPORT_SYMBOL(omapdss_dpi_display_enable);
285 240
286void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 241void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
287{ 242{
288 struct omap_overlay_manager *mgr = dssdev->output->manager; 243 dssdev->manager->disable(dssdev->manager);
289 244
290 mutex_lock(&dpi.lock); 245 if (dpi_use_dsi_pll(dssdev)) {
291 246 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
292 dss_mgr_disable(mgr);
293
294 if (dpi.dsidev) {
295 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
296 dsi_pll_uninit(dpi.dsidev, true); 247 dsi_pll_uninit(dpi.dsidev, true);
297 dsi_runtime_put(dpi.dsidev); 248 dsi_runtime_put(dpi.dsidev);
298 } 249 }
299 250
300 dispc_runtime_put(); 251 dispc_runtime_put();
252 dss_runtime_put();
301 253
302 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 254 if (cpu_is_omap34xx())
303 regulator_disable(dpi.vdds_dsi_reg); 255 regulator_disable(dpi.vdds_dsi_reg);
304 256
305 omap_dss_stop_device(dssdev); 257 omap_dss_stop_device(dssdev);
306
307 mutex_unlock(&dpi.lock);
308} 258}
309EXPORT_SYMBOL(omapdss_dpi_display_disable); 259EXPORT_SYMBOL(omapdss_dpi_display_disable);
310 260
311void omapdss_dpi_set_timings(struct omap_dss_device *dssdev, 261void dpi_set_timings(struct omap_dss_device *dssdev,
312 struct omap_video_timings *timings) 262 struct omap_video_timings *timings)
313{ 263{
264 int r;
265
314 DSSDBG("dpi_set_timings\n"); 266 DSSDBG("dpi_set_timings\n");
267 dssdev->panel.timings = *timings;
268 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
269 r = dss_runtime_get();
270 if (r)
271 return;
315 272
316 mutex_lock(&dpi.lock); 273 r = dispc_runtime_get();
274 if (r) {
275 dss_runtime_put();
276 return;
277 }
317 278
318 dpi.timings = *timings; 279 dpi_set_mode(dssdev);
280 dispc_go(dssdev->manager->id);
319 281
320 mutex_unlock(&dpi.lock); 282 dispc_runtime_put();
283 dss_runtime_put();
284 }
321} 285}
322EXPORT_SYMBOL(omapdss_dpi_set_timings); 286EXPORT_SYMBOL(dpi_set_timings);
323 287
324int dpi_check_timings(struct omap_dss_device *dssdev, 288int dpi_check_timings(struct omap_dss_device *dssdev,
325 struct omap_video_timings *timings) 289 struct omap_video_timings *timings)
326{ 290{
291 bool is_tft;
327 int r; 292 int r;
328 struct omap_overlay_manager *mgr = dssdev->output->manager;
329 int lck_div, pck_div; 293 int lck_div, pck_div;
330 unsigned long fck; 294 unsigned long fck;
331 unsigned long pck; 295 unsigned long pck;
332 struct dispc_clock_info dispc_cinfo; 296 struct dispc_clock_info dispc_cinfo;
333 297
334 if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) 298 if (!dispc_lcd_timings_ok(timings))
335 return -EINVAL; 299 return -EINVAL;
336 300
337 if (timings->pixel_clock == 0) 301 if (timings->pixel_clock == 0)
338 return -EINVAL; 302 return -EINVAL;
339 303
340 if (dpi.dsidev) { 304 is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
305
306 if (dpi_use_dsi_pll(dssdev)) {
341 struct dsi_clock_info dsi_cinfo; 307 struct dsi_clock_info dsi_cinfo;
342 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, 308 r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft,
343 timings->pixel_clock * 1000, 309 timings->pixel_clock * 1000,
344 &dsi_cinfo, &dispc_cinfo); 310 &dsi_cinfo, &dispc_cinfo);
345 311
@@ -349,7 +315,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
349 fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 315 fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
350 } else { 316 } else {
351 struct dss_clock_info dss_cinfo; 317 struct dss_clock_info dss_cinfo;
352 r = dss_calc_clock_div(timings->pixel_clock * 1000, 318 r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000,
353 &dss_cinfo, &dispc_cinfo); 319 &dss_cinfo, &dispc_cinfo);
354 320
355 if (r) 321 if (r)
@@ -369,46 +335,11 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
369} 335}
370EXPORT_SYMBOL(dpi_check_timings); 336EXPORT_SYMBOL(dpi_check_timings);
371 337
372void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) 338int dpi_init_display(struct omap_dss_device *dssdev)
373{
374 mutex_lock(&dpi.lock);
375
376 dpi.data_lines = data_lines;
377
378 mutex_unlock(&dpi.lock);
379}
380EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
381
382static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
383{
384 int r;
385
386 /* do initial setup with the PLL to see if it is operational */
387
388 r = dsi_runtime_get(dsidev);
389 if (r)
390 return r;
391
392 r = dsi_pll_init(dsidev, 0, 1);
393 if (r) {
394 dsi_runtime_put(dsidev);
395 return r;
396 }
397
398 dsi_pll_uninit(dsidev, true);
399 dsi_runtime_put(dsidev);
400
401 return 0;
402}
403
404static int __init dpi_init_display(struct omap_dss_device *dssdev)
405{ 339{
406 struct platform_device *dsidev;
407
408 DSSDBG("init_display\n"); 340 DSSDBG("init_display\n");
409 341
410 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && 342 if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) {
411 dpi.vdds_dsi_reg == NULL) {
412 struct regulator *vdds_dsi; 343 struct regulator *vdds_dsi;
413 344
414 vdds_dsi = dss_get_vdds_dsi(); 345 vdds_dsi = dss_get_vdds_dsi();
@@ -421,147 +352,21 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev)
421 dpi.vdds_dsi_reg = vdds_dsi; 352 dpi.vdds_dsi_reg = vdds_dsi;
422 } 353 }
423 354
424 /* 355 if (dpi_use_dsi_pll(dssdev)) {
425 * XXX We shouldn't need dssdev->channel for this. The dsi pll clock 356 enum omap_dss_clk_source dispc_fclk_src =
426 * source for DPI is SoC integration detail, not something that should 357 dssdev->clocks.dispc.dispc_fclk_src;
427 * be configured in the dssdev 358 dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
428 */
429 dsidev = dpi_get_dsidev(dssdev->channel);
430
431 if (dsidev && dpi_verify_dsi_pll(dsidev)) {
432 dsidev = NULL;
433 DSSWARN("DSI PLL not operational\n");
434 }
435
436 if (dsidev)
437 DSSDBG("using DSI PLL for DPI clock\n");
438
439 dpi.dsidev = dsidev;
440
441 return 0;
442}
443
444static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
445{
446 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
447 const char *def_disp_name = omapdss_get_default_display_name();
448 struct omap_dss_device *def_dssdev;
449 int i;
450
451 def_dssdev = NULL;
452
453 for (i = 0; i < pdata->num_devices; ++i) {
454 struct omap_dss_device *dssdev = pdata->devices[i];
455
456 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
457 continue;
458
459 if (def_dssdev == NULL)
460 def_dssdev = dssdev;
461
462 if (def_disp_name != NULL &&
463 strcmp(dssdev->name, def_disp_name) == 0) {
464 def_dssdev = dssdev;
465 break;
466 }
467 }
468
469 return def_dssdev;
470}
471
472static void __init dpi_probe_pdata(struct platform_device *dpidev)
473{
474 struct omap_dss_device *plat_dssdev;
475 struct omap_dss_device *dssdev;
476 int r;
477
478 plat_dssdev = dpi_find_dssdev(dpidev);
479
480 if (!plat_dssdev)
481 return;
482
483 dssdev = dss_alloc_and_init_device(&dpidev->dev);
484 if (!dssdev)
485 return;
486
487 dss_copy_device_pdata(dssdev, plat_dssdev);
488
489 r = dpi_init_display(dssdev);
490 if (r) {
491 DSSERR("device %s init failed: %d\n", dssdev->name, r);
492 dss_put_device(dssdev);
493 return;
494 }
495
496 r = omapdss_output_set_device(&dpi.output, dssdev);
497 if (r) {
498 DSSERR("failed to connect output to new device: %s\n",
499 dssdev->name);
500 dss_put_device(dssdev);
501 return;
502 }
503
504 r = dss_add_device(dssdev);
505 if (r) {
506 DSSERR("device %s register failed: %d\n", dssdev->name, r);
507 omapdss_output_unset_device(&dpi.output);
508 dss_put_device(dssdev);
509 return;
510 } 359 }
511}
512
513static void __init dpi_init_output(struct platform_device *pdev)
514{
515 struct omap_dss_output *out = &dpi.output;
516
517 out->pdev = pdev;
518 out->id = OMAP_DSS_OUTPUT_DPI;
519 out->type = OMAP_DISPLAY_TYPE_DPI;
520
521 dss_register_output(out);
522}
523
524static void __exit dpi_uninit_output(struct platform_device *pdev)
525{
526 struct omap_dss_output *out = &dpi.output;
527
528 dss_unregister_output(out);
529}
530
531static int __init omap_dpi_probe(struct platform_device *pdev)
532{
533 mutex_init(&dpi.lock);
534
535 dpi_init_output(pdev);
536
537 dpi_probe_pdata(pdev);
538 360
539 return 0; 361 return 0;
540} 362}
541 363
542static int __exit omap_dpi_remove(struct platform_device *pdev) 364int dpi_init(void)
543{ 365{
544 dss_unregister_child_devices(&pdev->dev);
545
546 dpi_uninit_output(pdev);
547
548 return 0; 366 return 0;
549} 367}
550 368
551static struct platform_driver omap_dpi_driver = { 369void dpi_exit(void)
552 .remove = __exit_p(omap_dpi_remove),
553 .driver = {
554 .name = "omapdss_dpi",
555 .owner = THIS_MODULE,
556 },
557};
558
559int __init dpi_init_platform_driver(void)
560{ 370{
561 return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe);
562} 371}
563 372
564void __exit dpi_uninit_platform_driver(void)
565{
566 platform_driver_unregister(&omap_dpi_driver);
567}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 28d41d16b7b..7adbbeb8433 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -27,7 +27,6 @@
27#include <linux/interrupt.h> 27#include <linux/interrupt.h>
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/mutex.h> 29#include <linux/mutex.h>
30#include <linux/module.h>
31#include <linux/semaphore.h> 30#include <linux/semaphore.h>
32#include <linux/seq_file.h> 31#include <linux/seq_file.h>
33#include <linux/platform_device.h> 32#include <linux/platform_device.h>
@@ -40,11 +39,12 @@
40#include <linux/pm_runtime.h> 39#include <linux/pm_runtime.h>
41 40
42#include <video/omapdss.h> 41#include <video/omapdss.h>
43#include <video/mipi_display.h> 42#include <plat/clock.h>
44 43
45#include "dss.h" 44#include "dss.h"
46#include "dss_features.h" 45#include "dss_features.h"
47 46
47/*#define VERBOSE_IRQ*/
48#define DSI_CATCH_MISSING_TE 48#define DSI_CATCH_MISSING_TE
49 49
50struct dsi_reg { u16 idx; }; 50struct dsi_reg { u16 idx; };
@@ -131,7 +131,7 @@ struct dsi_reg { u16 idx; };
131#define DSI_IRQ_TA_TIMEOUT (1 << 20) 131#define DSI_IRQ_TA_TIMEOUT (1 << 20)
132#define DSI_IRQ_ERROR_MASK \ 132#define DSI_IRQ_ERROR_MASK \
133 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \ 133 (DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
134 DSI_IRQ_TA_TIMEOUT | DSI_IRQ_SYNC_LOST) 134 DSI_IRQ_TA_TIMEOUT)
135#define DSI_IRQ_CHANNEL_MASK 0xf 135#define DSI_IRQ_CHANNEL_MASK 0xf
136 136
137/* Virtual channel interrupts */ 137/* Virtual channel interrupts */
@@ -198,24 +198,21 @@ struct dsi_reg { u16 idx; };
198 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \ 198 DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
199 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5) 199 DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
200 200
201#define DSI_DT_DCS_SHORT_WRITE_0 0x05
202#define DSI_DT_DCS_SHORT_WRITE_1 0x15
203#define DSI_DT_DCS_READ 0x06
204#define DSI_DT_SET_MAX_RET_PKG_SIZE 0x37
205#define DSI_DT_NULL_PACKET 0x09
206#define DSI_DT_DCS_LONG_WRITE 0x39
207
208#define DSI_DT_RX_ACK_WITH_ERR 0x02
209#define DSI_DT_RX_DCS_LONG_READ 0x1c
210#define DSI_DT_RX_SHORT_READ_1 0x21
211#define DSI_DT_RX_SHORT_READ_2 0x22
212
201typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); 213typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
202 214
203#define DSI_MAX_NR_ISRS 2 215#define DSI_MAX_NR_ISRS 2
204#define DSI_MAX_NR_LANES 5
205
206enum dsi_lane_function {
207 DSI_LANE_UNUSED = 0,
208 DSI_LANE_CLK,
209 DSI_LANE_DATA1,
210 DSI_LANE_DATA2,
211 DSI_LANE_DATA3,
212 DSI_LANE_DATA4,
213};
214
215struct dsi_lane_config {
216 enum dsi_lane_function function;
217 u8 polarity;
218};
219 216
220struct dsi_isr_data { 217struct dsi_isr_data {
221 omap_dsi_isr_t isr; 218 omap_dsi_isr_t isr;
@@ -231,9 +228,27 @@ enum fifo_size {
231 DSI_FIFO_SIZE_128 = 4, 228 DSI_FIFO_SIZE_128 = 4,
232}; 229};
233 230
234enum dsi_vc_source { 231enum dsi_vc_mode {
235 DSI_VC_SOURCE_L4 = 0, 232 DSI_VC_MODE_L4 = 0,
236 DSI_VC_SOURCE_VP, 233 DSI_VC_MODE_VP,
234};
235
236enum dsi_lane {
237 DSI_CLK_P = 1 << 0,
238 DSI_CLK_N = 1 << 1,
239 DSI_DATA1_P = 1 << 2,
240 DSI_DATA1_N = 1 << 3,
241 DSI_DATA2_P = 1 << 4,
242 DSI_DATA2_N = 1 << 5,
243 DSI_DATA3_P = 1 << 6,
244 DSI_DATA3_N = 1 << 7,
245 DSI_DATA4_P = 1 << 8,
246 DSI_DATA4_N = 1 << 9,
247};
248
249struct dsi_update_region {
250 u16 x, y, w, h;
251 struct omap_dss_device *device;
237}; 252};
238 253
239struct dsi_irq_stats { 254struct dsi_irq_stats {
@@ -254,20 +269,20 @@ struct dsi_data {
254 struct platform_device *pdev; 269 struct platform_device *pdev;
255 void __iomem *base; 270 void __iomem *base;
256 271
257 int module_id;
258
259 int irq; 272 int irq;
260 273
261 struct clk *dss_clk; 274 struct clk *dss_clk;
262 struct clk *sys_clk; 275 struct clk *sys_clk;
263 276
277 void (*dsi_mux_pads)(bool enable);
278
264 struct dsi_clock_info current_cinfo; 279 struct dsi_clock_info current_cinfo;
265 280
266 bool vdds_dsi_enabled; 281 bool vdds_dsi_enabled;
267 struct regulator *vdds_dsi_reg; 282 struct regulator *vdds_dsi_reg;
268 283
269 struct { 284 struct {
270 enum dsi_vc_source source; 285 enum dsi_vc_mode mode;
271 struct omap_dss_device *dssdev; 286 struct omap_dss_device *dssdev;
272 enum fifo_size fifo_size; 287 enum fifo_size fifo_size;
273 int vc_id; 288 int vc_id;
@@ -284,9 +299,7 @@ struct dsi_data {
284 struct dsi_isr_tables isr_tables_copy; 299 struct dsi_isr_tables isr_tables_copy;
285 300
286 int update_channel; 301 int update_channel;
287#ifdef DEBUG 302 struct dsi_update_region update_region;
288 unsigned update_bytes;
289#endif
290 303
291 bool te_enabled; 304 bool te_enabled;
292 bool ulps_enabled; 305 bool ulps_enabled;
@@ -323,20 +336,9 @@ struct dsi_data {
323 unsigned long fint_min, fint_max; 336 unsigned long fint_min, fint_max;
324 unsigned long lpdiv_max; 337 unsigned long lpdiv_max;
325 338
326 unsigned num_lanes_supported; 339 int num_data_lanes;
327
328 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
329 unsigned num_lanes_used;
330 340
331 unsigned scp_clk_refcount; 341 unsigned scp_clk_refcount;
332
333 struct dss_lcd_mgr_config mgr_config;
334 struct omap_video_timings timings;
335 enum omap_dss_dsi_pixel_format pix_fmt;
336 enum omap_dss_dsi_mode mode;
337 struct omap_dss_dsi_videomode_timings vm_timings;
338
339 struct omap_dss_output output;
340}; 342};
341 343
342struct dsi_packet_sent_handler_data { 344struct dsi_packet_sent_handler_data {
@@ -344,9 +346,11 @@ struct dsi_packet_sent_handler_data {
344 struct completion *completion; 346 struct completion *completion;
345}; 347};
346 348
349static struct platform_device *dsi_pdev_map[MAX_NUM_DSI];
350
347#ifdef DEBUG 351#ifdef DEBUG
348static bool dsi_perf; 352static unsigned int dsi_perf;
349module_param(dsi_perf, bool, 0644); 353module_param_named(dsi_perf, dsi_perf, bool, 0644);
350#endif 354#endif
351 355
352static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev) 356static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dsidev)
@@ -356,28 +360,22 @@ static inline struct dsi_data *dsi_get_dsidrv_data(struct platform_device *dside
356 360
357static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev) 361static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss_device *dssdev)
358{ 362{
359 return dssdev->output->pdev; 363 return dsi_pdev_map[dssdev->phy.dsi.module];
360} 364}
361 365
362struct platform_device *dsi_get_dsidev_from_id(int module) 366struct platform_device *dsi_get_dsidev_from_id(int module)
363{ 367{
364 struct omap_dss_output *out; 368 return dsi_pdev_map[module];
365 enum omap_dss_output_id id; 369}
366
367 switch (module) {
368 case 0:
369 id = OMAP_DSS_OUTPUT_DSI1;
370 break;
371 case 1:
372 id = OMAP_DSS_OUTPUT_DSI2;
373 break;
374 default:
375 return NULL;
376 }
377 370
378 out = omap_dss_get_output(id); 371static int dsi_get_dsidev_id(struct platform_device *dsidev)
372{
373 /* TEMP: Pass 0 as the dsi module index till the time the dsi platform
374 * device names aren't changed to the form "omapdss_dsi.0",
375 * "omapdss_dsi.1" and so on */
376 BUG_ON(dsidev->id != -1);
379 377
380 return out ? out->pdev : NULL; 378 return 0;
381} 379}
382 380
383static inline void dsi_write_reg(struct platform_device *dsidev, 381static inline void dsi_write_reg(struct platform_device *dsidev,
@@ -429,45 +427,14 @@ static void dsi_completion_handler(void *data, u32 mask)
429static inline int wait_for_bit_change(struct platform_device *dsidev, 427static inline int wait_for_bit_change(struct platform_device *dsidev,
430 const struct dsi_reg idx, int bitnum, int value) 428 const struct dsi_reg idx, int bitnum, int value)
431{ 429{
432 unsigned long timeout; 430 int t = 100000;
433 ktime_t wait;
434 int t;
435
436 /* first busyloop to see if the bit changes right away */
437 t = 100;
438 while (t-- > 0) {
439 if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
440 return value;
441 }
442
443 /* then loop for 500ms, sleeping for 1ms in between */
444 timeout = jiffies + msecs_to_jiffies(500);
445 while (time_before(jiffies, timeout)) {
446 if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
447 return value;
448 431
449 wait = ns_to_ktime(1000 * 1000); 432 while (REG_GET(dsidev, idx, bitnum, bitnum) != value) {
450 set_current_state(TASK_UNINTERRUPTIBLE); 433 if (--t == 0)
451 schedule_hrtimeout(&wait, HRTIMER_MODE_REL); 434 return !value;
452 } 435 }
453 436
454 return !value; 437 return value;
455}
456
457u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
458{
459 switch (fmt) {
460 case OMAP_DSS_DSI_FMT_RGB888:
461 case OMAP_DSS_DSI_FMT_RGB666:
462 return 24;
463 case OMAP_DSS_DSI_FMT_RGB666_PACKED:
464 return 18;
465 case OMAP_DSS_DSI_FMT_RGB565:
466 return 16;
467 default:
468 BUG();
469 return 0;
470 }
471} 438}
472 439
473#ifdef DEBUG 440#ifdef DEBUG
@@ -507,7 +474,9 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
507 474
508 total_us = setup_us + trans_us; 475 total_us = setup_us + trans_us;
509 476
510 total_bytes = dsi->update_bytes; 477 total_bytes = dsi->update_region.w *
478 dsi->update_region.h *
479 dsi->update_region.device->ctrl.pixel_size / 8;
511 480
512 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " 481 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
513 "%u bytes, %u kbytes/sec\n", 482 "%u bytes, %u kbytes/sec\n",
@@ -534,38 +503,42 @@ static inline void dsi_perf_show(struct platform_device *dsidev,
534} 503}
535#endif 504#endif
536 505
537static int verbose_irq;
538
539static void print_irq_status(u32 status) 506static void print_irq_status(u32 status)
540{ 507{
541 if (status == 0) 508 if (status == 0)
542 return; 509 return;
543 510
544 if (!verbose_irq && (status & ~DSI_IRQ_CHANNEL_MASK) == 0) 511#ifndef VERBOSE_IRQ
512 if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0)
545 return; 513 return;
514#endif
515 printk(KERN_DEBUG "DSI IRQ: 0x%x: ", status);
546 516
547#define PIS(x) (status & DSI_IRQ_##x) ? (#x " ") : "" 517#define PIS(x) \
548 518 if (status & DSI_IRQ_##x) \
549 pr_debug("DSI IRQ: 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", 519 printk(#x " ");
550 status, 520#ifdef VERBOSE_IRQ
551 verbose_irq ? PIS(VC0) : "", 521 PIS(VC0);
552 verbose_irq ? PIS(VC1) : "", 522 PIS(VC1);
553 verbose_irq ? PIS(VC2) : "", 523 PIS(VC2);
554 verbose_irq ? PIS(VC3) : "", 524 PIS(VC3);
555 PIS(WAKEUP), 525#endif
556 PIS(RESYNC), 526 PIS(WAKEUP);
557 PIS(PLL_LOCK), 527 PIS(RESYNC);
558 PIS(PLL_UNLOCK), 528 PIS(PLL_LOCK);
559 PIS(PLL_RECALL), 529 PIS(PLL_UNLOCK);
560 PIS(COMPLEXIO_ERR), 530 PIS(PLL_RECALL);
561 PIS(HS_TX_TIMEOUT), 531 PIS(COMPLEXIO_ERR);
562 PIS(LP_RX_TIMEOUT), 532 PIS(HS_TX_TIMEOUT);
563 PIS(TE_TRIGGER), 533 PIS(LP_RX_TIMEOUT);
564 PIS(ACK_TRIGGER), 534 PIS(TE_TRIGGER);
565 PIS(SYNC_LOST), 535 PIS(ACK_TRIGGER);
566 PIS(LDO_POWER_GOOD), 536 PIS(SYNC_LOST);
567 PIS(TA_TIMEOUT)); 537 PIS(LDO_POWER_GOOD);
538 PIS(TA_TIMEOUT);
568#undef PIS 539#undef PIS
540
541 printk("\n");
569} 542}
570 543
571static void print_irq_status_vc(int channel, u32 status) 544static void print_irq_status_vc(int channel, u32 status)
@@ -573,24 +546,28 @@ static void print_irq_status_vc(int channel, u32 status)
573 if (status == 0) 546 if (status == 0)
574 return; 547 return;
575 548
576 if (!verbose_irq && (status & ~DSI_VC_IRQ_PACKET_SENT) == 0) 549#ifndef VERBOSE_IRQ
550 if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0)
577 return; 551 return;
552#endif
553 printk(KERN_DEBUG "DSI VC(%d) IRQ 0x%x: ", channel, status);
578 554
579#define PIS(x) (status & DSI_VC_IRQ_##x) ? (#x " ") : "" 555#define PIS(x) \
580 556 if (status & DSI_VC_IRQ_##x) \
581 pr_debug("DSI VC(%d) IRQ 0x%x: %s%s%s%s%s%s%s%s%s\n", 557 printk(#x " ");
582 channel, 558 PIS(CS);
583 status, 559 PIS(ECC_CORR);
584 PIS(CS), 560#ifdef VERBOSE_IRQ
585 PIS(ECC_CORR), 561 PIS(PACKET_SENT);
586 PIS(ECC_NO_CORR), 562#endif
587 verbose_irq ? PIS(PACKET_SENT) : "", 563 PIS(FIFO_TX_OVF);
588 PIS(BTA), 564 PIS(FIFO_RX_OVF);
589 PIS(FIFO_TX_OVF), 565 PIS(BTA);
590 PIS(FIFO_RX_OVF), 566 PIS(ECC_NO_CORR);
591 PIS(FIFO_TX_UDF), 567 PIS(FIFO_TX_UDF);
592 PIS(PP_BUSY_CHANGE)); 568 PIS(PP_BUSY_CHANGE);
593#undef PIS 569#undef PIS
570 printk("\n");
594} 571}
595 572
596static void print_irq_status_cio(u32 status) 573static void print_irq_status_cio(u32 status)
@@ -598,31 +575,34 @@ static void print_irq_status_cio(u32 status)
598 if (status == 0) 575 if (status == 0)
599 return; 576 return;
600 577
601#define PIS(x) (status & DSI_CIO_IRQ_##x) ? (#x " ") : "" 578 printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status);
602 579
603 pr_debug("DSI CIO IRQ 0x%x: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", 580#define PIS(x) \
604 status, 581 if (status & DSI_CIO_IRQ_##x) \
605 PIS(ERRSYNCESC1), 582 printk(#x " ");
606 PIS(ERRSYNCESC2), 583 PIS(ERRSYNCESC1);
607 PIS(ERRSYNCESC3), 584 PIS(ERRSYNCESC2);
608 PIS(ERRESC1), 585 PIS(ERRSYNCESC3);
609 PIS(ERRESC2), 586 PIS(ERRESC1);
610 PIS(ERRESC3), 587 PIS(ERRESC2);
611 PIS(ERRCONTROL1), 588 PIS(ERRESC3);
612 PIS(ERRCONTROL2), 589 PIS(ERRCONTROL1);
613 PIS(ERRCONTROL3), 590 PIS(ERRCONTROL2);
614 PIS(STATEULPS1), 591 PIS(ERRCONTROL3);
615 PIS(STATEULPS2), 592 PIS(STATEULPS1);
616 PIS(STATEULPS3), 593 PIS(STATEULPS2);
617 PIS(ERRCONTENTIONLP0_1), 594 PIS(STATEULPS3);
618 PIS(ERRCONTENTIONLP1_1), 595 PIS(ERRCONTENTIONLP0_1);
619 PIS(ERRCONTENTIONLP0_2), 596 PIS(ERRCONTENTIONLP1_1);
620 PIS(ERRCONTENTIONLP1_2), 597 PIS(ERRCONTENTIONLP0_2);
621 PIS(ERRCONTENTIONLP0_3), 598 PIS(ERRCONTENTIONLP1_2);
622 PIS(ERRCONTENTIONLP1_3), 599 PIS(ERRCONTENTIONLP0_3);
623 PIS(ULPSACTIVENOT_ALL0), 600 PIS(ERRCONTENTIONLP1_3);
624 PIS(ULPSACTIVENOT_ALL1)); 601 PIS(ULPSACTIVENOT_ALL0);
602 PIS(ULPSACTIVENOT_ALL1);
625#undef PIS 603#undef PIS
604
605 printk("\n");
626} 606}
627 607
628#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 608#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
@@ -1083,8 +1063,8 @@ void dsi_runtime_put(struct platform_device *dsidev)
1083 1063
1084 DSSDBG("dsi_runtime_put\n"); 1064 DSSDBG("dsi_runtime_put\n");
1085 1065
1086 r = pm_runtime_put_sync(&dsi->pdev->dev); 1066 r = pm_runtime_put(&dsi->pdev->dev);
1087 WARN_ON(r < 0 && r != -ENOSYS); 1067 WARN_ON(r < 0);
1088} 1068}
1089 1069
1090/* source clock for DSI PLL. this could also be PCLKFREE */ 1070/* source clock for DSI PLL. this could also be PCLKFREE */
@@ -1094,9 +1074,9 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1094 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1074 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1095 1075
1096 if (enable) 1076 if (enable)
1097 clk_prepare_enable(dsi->sys_clk); 1077 clk_enable(dsi->sys_clk);
1098 else 1078 else
1099 clk_disable_unprepare(dsi->sys_clk); 1079 clk_disable(dsi->sys_clk);
1100 1080
1101 if (enable && dsi->pll_locked) { 1081 if (enable && dsi->pll_locked) {
1102 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) 1082 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
@@ -1104,16 +1084,28 @@ static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1104 } 1084 }
1105} 1085}
1106 1086
1087#ifdef DEBUG
1107static void _dsi_print_reset_status(struct platform_device *dsidev) 1088static void _dsi_print_reset_status(struct platform_device *dsidev)
1108{ 1089{
1109 u32 l; 1090 u32 l;
1110 int b0, b1, b2; 1091 int b0, b1, b2;
1111 1092
1093 if (!dss_debug)
1094 return;
1095
1112 /* A dummy read using the SCP interface to any DSIPHY register is 1096 /* A dummy read using the SCP interface to any DSIPHY register is
1113 * required after DSIPHY reset to complete the reset of the DSI complex 1097 * required after DSIPHY reset to complete the reset of the DSI complex
1114 * I/O. */ 1098 * I/O. */
1115 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 1099 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
1116 1100
1101 printk(KERN_DEBUG "DSI resets: ");
1102
1103 l = dsi_read_reg(dsidev, DSI_PLL_STATUS);
1104 printk("PLL (%d) ", FLD_GET(l, 0, 0));
1105
1106 l = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
1107 printk("CIO (%d) ", FLD_GET(l, 29, 29));
1108
1117 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { 1109 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
1118 b0 = 28; 1110 b0 = 28;
1119 b1 = 27; 1111 b1 = 27;
@@ -1124,21 +1116,18 @@ static void _dsi_print_reset_status(struct platform_device *dsidev)
1124 b2 = 26; 1116 b2 = 26;
1125 } 1117 }
1126 1118
1127#define DSI_FLD_GET(fld, start, end)\ 1119 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
1128 FLD_GET(dsi_read_reg(dsidev, DSI_##fld), start, end) 1120 printk("PHY (%x%x%x, %d, %d, %d)\n",
1129 1121 FLD_GET(l, b0, b0),
1130 pr_debug("DSI resets: PLL (%d) CIO (%d) PHY (%x%x%x, %d, %d, %d)\n", 1122 FLD_GET(l, b1, b1),
1131 DSI_FLD_GET(PLL_STATUS, 0, 0), 1123 FLD_GET(l, b2, b2),
1132 DSI_FLD_GET(COMPLEXIO_CFG1, 29, 29), 1124 FLD_GET(l, 29, 29),
1133 DSI_FLD_GET(DSIPHY_CFG5, b0, b0), 1125 FLD_GET(l, 30, 30),
1134 DSI_FLD_GET(DSIPHY_CFG5, b1, b1), 1126 FLD_GET(l, 31, 31));
1135 DSI_FLD_GET(DSIPHY_CFG5, b2, b2),
1136 DSI_FLD_GET(DSIPHY_CFG5, 29, 29),
1137 DSI_FLD_GET(DSIPHY_CFG5, 30, 30),
1138 DSI_FLD_GET(DSIPHY_CFG5, 31, 31));
1139
1140#undef DSI_FLD_GET
1141} 1127}
1128#else
1129#define _dsi_print_reset_status(x)
1130#endif
1142 1131
1143static inline int dsi_if_enable(struct platform_device *dsidev, bool enable) 1132static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
1144{ 1133{
@@ -1179,9 +1168,10 @@ static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
1179static unsigned long dsi_fclk_rate(struct platform_device *dsidev) 1168static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1180{ 1169{
1181 unsigned long r; 1170 unsigned long r;
1171 int dsi_module = dsi_get_dsidev_id(dsidev);
1182 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1172 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1183 1173
1184 if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) { 1174 if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
1185 /* DSI FCLK source is DSS_CLK_FCK */ 1175 /* DSI FCLK source is DSS_CLK_FCK */
1186 r = clk_get_rate(dsi->dss_clk); 1176 r = clk_get_rate(dsi->dss_clk);
1187 } else { 1177 } else {
@@ -1273,9 +1263,10 @@ static int dsi_pll_power(struct platform_device *dsidev,
1273} 1263}
1274 1264
1275/* calculate clock rates using dividers in cinfo */ 1265/* calculate clock rates using dividers in cinfo */
1276static int dsi_calc_clock_rates(struct platform_device *dsidev, 1266static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
1277 struct dsi_clock_info *cinfo) 1267 struct dsi_clock_info *cinfo)
1278{ 1268{
1269 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
1279 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1270 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1280 1271
1281 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) 1272 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
@@ -1290,8 +1281,21 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
1290 if (cinfo->regm_dsi > dsi->regm_dsi_max) 1281 if (cinfo->regm_dsi > dsi->regm_dsi_max)
1291 return -EINVAL; 1282 return -EINVAL;
1292 1283
1293 cinfo->clkin = clk_get_rate(dsi->sys_clk); 1284 if (cinfo->use_sys_clk) {
1294 cinfo->fint = cinfo->clkin / cinfo->regn; 1285 cinfo->clkin = clk_get_rate(dsi->sys_clk);
1286 /* XXX it is unclear if highfreq should be used
1287 * with DSS_SYS_CLK source also */
1288 cinfo->highfreq = 0;
1289 } else {
1290 cinfo->clkin = dispc_pclk_rate(dssdev->manager->id);
1291
1292 if (cinfo->clkin < 32000000)
1293 cinfo->highfreq = 0;
1294 else
1295 cinfo->highfreq = 1;
1296 }
1297
1298 cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
1295 1299
1296 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) 1300 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
1297 return -EINVAL; 1301 return -EINVAL;
@@ -1316,7 +1320,7 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev,
1316 return 0; 1320 return 0;
1317} 1321}
1318 1322
1319int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, 1323int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
1320 unsigned long req_pck, struct dsi_clock_info *dsi_cinfo, 1324 unsigned long req_pck, struct dsi_clock_info *dsi_cinfo,
1321 struct dispc_clock_info *dispc_cinfo) 1325 struct dispc_clock_info *dispc_cinfo)
1322{ 1326{
@@ -1335,8 +1339,8 @@ int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
1335 dsi->cache_cinfo.clkin == dss_sys_clk) { 1339 dsi->cache_cinfo.clkin == dss_sys_clk) {
1336 DSSDBG("DSI clock info found from cache\n"); 1340 DSSDBG("DSI clock info found from cache\n");
1337 *dsi_cinfo = dsi->cache_cinfo; 1341 *dsi_cinfo = dsi->cache_cinfo;
1338 dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk, 1342 dispc_find_clk_divs(is_tft, req_pck,
1339 dispc_cinfo); 1343 dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo);
1340 return 0; 1344 return 0;
1341 } 1345 }
1342 1346
@@ -1358,21 +1362,27 @@ retry:
1358 1362
1359 memset(&cur, 0, sizeof(cur)); 1363 memset(&cur, 0, sizeof(cur));
1360 cur.clkin = dss_sys_clk; 1364 cur.clkin = dss_sys_clk;
1365 cur.use_sys_clk = 1;
1366 cur.highfreq = 0;
1361 1367
1362 /* 0.75MHz < Fint = clkin / regn < 2.1MHz */ 1368 /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
1369 /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
1363 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ 1370 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
1364 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { 1371 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1365 cur.fint = cur.clkin / cur.regn; 1372 if (cur.highfreq == 0)
1373 cur.fint = cur.clkin / cur.regn;
1374 else
1375 cur.fint = cur.clkin / (2 * cur.regn);
1366 1376
1367 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) 1377 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1368 continue; 1378 continue;
1369 1379
1370 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ 1380 /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
1371 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { 1381 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1372 unsigned long a, b; 1382 unsigned long a, b;
1373 1383
1374 a = 2 * cur.regm * (cur.clkin/1000); 1384 a = 2 * cur.regm * (cur.clkin/1000);
1375 b = cur.regn; 1385 b = cur.regn * (cur.highfreq + 1);
1376 cur.clkin4ddr = a / b * 1000; 1386 cur.clkin4ddr = a / b * 1000;
1377 1387
1378 if (cur.clkin4ddr > 1800 * 1000 * 1000) 1388 if (cur.clkin4ddr > 1800 * 1000 * 1000)
@@ -1386,11 +1396,6 @@ retry:
1386 cur.dsi_pll_hsdiv_dispc_clk = 1396 cur.dsi_pll_hsdiv_dispc_clk =
1387 cur.clkin4ddr / cur.regm_dispc; 1397 cur.clkin4ddr / cur.regm_dispc;
1388 1398
1389 if (cur.regm_dispc > 1 &&
1390 cur.regm_dispc % 2 != 0 &&
1391 req_pck >= 1000000)
1392 continue;
1393
1394 /* this will narrow down the search a bit, 1399 /* this will narrow down the search a bit,
1395 * but still give pixclocks below what was 1400 * but still give pixclocks below what was
1396 * requested */ 1401 * requested */
@@ -1407,7 +1412,7 @@ retry:
1407 1412
1408 match = 1; 1413 match = 1;
1409 1414
1410 dispc_find_clk_divs(req_pck, 1415 dispc_find_clk_divs(is_tft, req_pck,
1411 cur.dsi_pll_hsdiv_dispc_clk, 1416 cur.dsi_pll_hsdiv_dispc_clk,
1412 &cur_dispc); 1417 &cur_dispc);
1413 1418
@@ -1453,148 +1458,6 @@ found:
1453 return 0; 1458 return 0;
1454} 1459}
1455 1460
1456static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev,
1457 unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo)
1458{
1459 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1460 struct dsi_clock_info cur, best;
1461
1462 DSSDBG("dsi_pll_calc_ddrfreq\n");
1463
1464 memset(&best, 0, sizeof(best));
1465 memset(&cur, 0, sizeof(cur));
1466
1467 cur.clkin = clk_get_rate(dsi->sys_clk);
1468
1469 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1470 cur.fint = cur.clkin / cur.regn;
1471
1472 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1473 continue;
1474
1475 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1476 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1477 unsigned long a, b;
1478
1479 a = 2 * cur.regm * (cur.clkin/1000);
1480 b = cur.regn;
1481 cur.clkin4ddr = a / b * 1000;
1482
1483 if (cur.clkin4ddr > 1800 * 1000 * 1000)
1484 break;
1485
1486 if (abs(cur.clkin4ddr - req_clkin4ddr) <
1487 abs(best.clkin4ddr - req_clkin4ddr)) {
1488 best = cur;
1489 DSSDBG("best %ld\n", best.clkin4ddr);
1490 }
1491
1492 if (cur.clkin4ddr == req_clkin4ddr)
1493 goto found;
1494 }
1495 }
1496found:
1497 if (cinfo)
1498 *cinfo = best;
1499
1500 return 0;
1501}
1502
1503static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev,
1504 struct dsi_clock_info *cinfo)
1505{
1506 unsigned long max_dsi_fck;
1507
1508 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1509
1510 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck);
1511 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi;
1512}
1513
1514static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev,
1515 unsigned long req_pck, struct dsi_clock_info *cinfo,
1516 struct dispc_clock_info *dispc_cinfo)
1517{
1518 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1519 unsigned regm_dispc, best_regm_dispc;
1520 unsigned long dispc_clk, best_dispc_clk;
1521 int min_fck_per_pck;
1522 unsigned long max_dss_fck;
1523 struct dispc_clock_info best_dispc;
1524 bool match;
1525
1526 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1527
1528 min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
1529
1530 if (min_fck_per_pck &&
1531 req_pck * min_fck_per_pck > max_dss_fck) {
1532 DSSERR("Requested pixel clock not possible with the current "
1533 "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
1534 "the constraint off.\n");
1535 min_fck_per_pck = 0;
1536 }
1537
1538retry:
1539 best_regm_dispc = 0;
1540 best_dispc_clk = 0;
1541 memset(&best_dispc, 0, sizeof(best_dispc));
1542 match = false;
1543
1544 for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) {
1545 struct dispc_clock_info cur_dispc;
1546
1547 dispc_clk = cinfo->clkin4ddr / regm_dispc;
1548
1549 /* this will narrow down the search a bit,
1550 * but still give pixclocks below what was
1551 * requested */
1552 if (dispc_clk < req_pck)
1553 break;
1554
1555 if (dispc_clk > max_dss_fck)
1556 continue;
1557
1558 if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck)
1559 continue;
1560
1561 match = true;
1562
1563 dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc);
1564
1565 if (abs(cur_dispc.pck - req_pck) <
1566 abs(best_dispc.pck - req_pck)) {
1567 best_regm_dispc = regm_dispc;
1568 best_dispc_clk = dispc_clk;
1569 best_dispc = cur_dispc;
1570
1571 if (cur_dispc.pck == req_pck)
1572 goto found;
1573 }
1574 }
1575
1576 if (!match) {
1577 if (min_fck_per_pck) {
1578 DSSERR("Could not find suitable clock settings.\n"
1579 "Turning FCK/PCK constraint off and"
1580 "trying again.\n");
1581 min_fck_per_pck = 0;
1582 goto retry;
1583 }
1584
1585 DSSERR("Could not find suitable clock settings.\n");
1586
1587 return -EINVAL;
1588 }
1589found:
1590 cinfo->regm_dispc = best_regm_dispc;
1591 cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk;
1592
1593 *dispc_cinfo = best_dispc;
1594
1595 return 0;
1596}
1597
1598int dsi_pll_set_clock_div(struct platform_device *dsidev, 1461int dsi_pll_set_clock_div(struct platform_device *dsidev,
1599 struct dsi_clock_info *cinfo) 1462 struct dsi_clock_info *cinfo)
1600{ 1463{
@@ -1605,9 +1468,11 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1605 u8 regn_start, regn_end, regm_start, regm_end; 1468 u8 regn_start, regn_end, regm_start, regm_end;
1606 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; 1469 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
1607 1470
1608 DSSDBG("DSI PLL clock config starts"); 1471 DSSDBGF();
1472
1473 dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk;
1474 dsi->current_cinfo.highfreq = cinfo->highfreq;
1609 1475
1610 dsi->current_cinfo.clkin = cinfo->clkin;
1611 dsi->current_cinfo.fint = cinfo->fint; 1476 dsi->current_cinfo.fint = cinfo->fint;
1612 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; 1477 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
1613 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = 1478 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
@@ -1622,13 +1487,17 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1622 1487
1623 DSSDBG("DSI Fint %ld\n", cinfo->fint); 1488 DSSDBG("DSI Fint %ld\n", cinfo->fint);
1624 1489
1625 DSSDBG("clkin rate %ld\n", cinfo->clkin); 1490 DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
1491 cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree",
1492 cinfo->clkin,
1493 cinfo->highfreq);
1626 1494
1627 /* DSIPHY == CLKIN4DDR */ 1495 /* DSIPHY == CLKIN4DDR */
1628 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n", 1496 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n",
1629 cinfo->regm, 1497 cinfo->regm,
1630 cinfo->regn, 1498 cinfo->regn,
1631 cinfo->clkin, 1499 cinfo->clkin,
1500 cinfo->highfreq + 1,
1632 cinfo->clkin4ddr); 1501 cinfo->clkin4ddr);
1633 1502
1634 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", 1503 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
@@ -1671,27 +1540,25 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1671 1540
1672 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max); 1541 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1673 1542
1674 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1675
1676 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) { 1543 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1677 f = cinfo->fint < 1000000 ? 0x3 : 1544 f = cinfo->fint < 1000000 ? 0x3 :
1678 cinfo->fint < 1250000 ? 0x4 : 1545 cinfo->fint < 1250000 ? 0x4 :
1679 cinfo->fint < 1500000 ? 0x5 : 1546 cinfo->fint < 1500000 ? 0x5 :
1680 cinfo->fint < 1750000 ? 0x6 : 1547 cinfo->fint < 1750000 ? 0x6 :
1681 0x7; 1548 0x7;
1682
1683 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1684 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1685 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1686
1687 l = FLD_MOD(l, f, 4, 1); /* PLL_SELFREQDCO */
1688 } 1549 }
1689 1550
1551 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1552
1553 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1554 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1555 l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
1556 11, 11); /* DSI_PLL_CLKSEL */
1557 l = FLD_MOD(l, cinfo->highfreq,
1558 12, 12); /* DSI_PLL_HIGHFREQ */
1690 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1559 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1691 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1560 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1692 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1561 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1693 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1694 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1695 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l); 1562 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1696 1563
1697 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */ 1564 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
@@ -1741,21 +1608,11 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1741 1608
1742 DSSDBG("PLL init\n"); 1609 DSSDBG("PLL init\n");
1743 1610
1744 /*
1745 * It seems that on many OMAPs we need to enable both to have a
1746 * functional HSDivider.
1747 */
1748 enable_hsclk = enable_hsdiv = true;
1749
1750 if (dsi->vdds_dsi_reg == NULL) { 1611 if (dsi->vdds_dsi_reg == NULL) {
1751 struct regulator *vdds_dsi; 1612 struct regulator *vdds_dsi;
1752 1613
1753 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); 1614 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
1754 1615
1755 /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
1756 if (IS_ERR(vdds_dsi))
1757 vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
1758
1759 if (IS_ERR(vdds_dsi)) { 1616 if (IS_ERR(vdds_dsi)) {
1760 DSSERR("can't get VDDS_DSI regulator\n"); 1617 DSSERR("can't get VDDS_DSI regulator\n");
1761 return PTR_ERR(vdds_dsi); 1618 return PTR_ERR(vdds_dsi);
@@ -1843,7 +1700,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1843 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1700 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1844 struct dsi_clock_info *cinfo = &dsi->current_cinfo; 1701 struct dsi_clock_info *cinfo = &dsi->current_cinfo;
1845 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; 1702 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
1846 int dsi_module = dsi->module_id; 1703 int dsi_module = dsi_get_dsidev_id(dsidev);
1847 1704
1848 dispc_clk_src = dss_get_dispc_clk_source(); 1705 dispc_clk_src = dss_get_dispc_clk_source();
1849 dsi_clk_src = dss_get_dsi_clk_source(dsi_module); 1706 dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
@@ -1853,26 +1710,25 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1853 1710
1854 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); 1711 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
1855 1712
1856 seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin); 1713 seq_printf(s, "dsi pll source = %s\n",
1714 cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree");
1857 1715
1858 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); 1716 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
1859 1717
1860 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", 1718 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
1861 cinfo->clkin4ddr, cinfo->regm); 1719 cinfo->clkin4ddr, cinfo->regm);
1862 1720
1863 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n", 1721 seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n",
1864 dss_feat_get_clk_source_name(dsi_module == 0 ? 1722 dss_get_generic_clk_source_name(dispc_clk_src),
1865 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : 1723 dss_feat_get_clk_source_name(dispc_clk_src),
1866 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
1867 cinfo->dsi_pll_hsdiv_dispc_clk, 1724 cinfo->dsi_pll_hsdiv_dispc_clk,
1868 cinfo->regm_dispc, 1725 cinfo->regm_dispc,
1869 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1726 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1870 "off" : "on"); 1727 "off" : "on");
1871 1728
1872 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n", 1729 seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
1873 dss_feat_get_clk_source_name(dsi_module == 0 ? 1730 dss_get_generic_clk_source_name(dsi_clk_src),
1874 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : 1731 dss_feat_get_clk_source_name(dsi_clk_src),
1875 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
1876 cinfo->dsi_pll_hsdiv_dsi_clk, 1732 cinfo->dsi_pll_hsdiv_dsi_clk,
1877 cinfo->regm_dsi, 1733 cinfo->regm_dsi,
1878 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1734 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
@@ -1915,6 +1771,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
1915 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1771 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1916 unsigned long flags; 1772 unsigned long flags;
1917 struct dsi_irq_stats stats; 1773 struct dsi_irq_stats stats;
1774 int dsi_module = dsi_get_dsidev_id(dsidev);
1918 1775
1919 spin_lock_irqsave(&dsi->irq_stats_lock, flags); 1776 spin_lock_irqsave(&dsi->irq_stats_lock, flags);
1920 1777
@@ -1931,7 +1788,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
1931#define PIS(x) \ 1788#define PIS(x) \
1932 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); 1789 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
1933 1790
1934 seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1); 1791 seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1);
1935 PIS(VC0); 1792 PIS(VC0);
1936 PIS(VC1); 1793 PIS(VC1);
1937 PIS(VC2); 1794 PIS(VC2);
@@ -2011,6 +1868,22 @@ static void dsi2_dump_irqs(struct seq_file *s)
2011 1868
2012 dsi_dump_dsidev_irqs(dsidev, s); 1869 dsi_dump_dsidev_irqs(dsidev, s);
2013} 1870}
1871
1872void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
1873 const struct file_operations *debug_fops)
1874{
1875 struct platform_device *dsidev;
1876
1877 dsidev = dsi_get_dsidev_from_id(0);
1878 if (dsidev)
1879 debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir,
1880 &dsi1_dump_irqs, debug_fops);
1881
1882 dsidev = dsi_get_dsidev_from_id(1);
1883 if (dsidev)
1884 debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir,
1885 &dsi2_dump_irqs, debug_fops);
1886}
2014#endif 1887#endif
2015 1888
2016static void dsi_dump_dsidev_regs(struct platform_device *dsidev, 1889static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
@@ -2111,6 +1984,21 @@ static void dsi2_dump_regs(struct seq_file *s)
2111 dsi_dump_dsidev_regs(dsidev, s); 1984 dsi_dump_dsidev_regs(dsidev, s);
2112} 1985}
2113 1986
1987void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
1988 const struct file_operations *debug_fops)
1989{
1990 struct platform_device *dsidev;
1991
1992 dsidev = dsi_get_dsidev_from_id(0);
1993 if (dsidev)
1994 debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir,
1995 &dsi1_dump_regs, debug_fops);
1996
1997 dsidev = dsi_get_dsidev_from_id(1);
1998 if (dsidev)
1999 debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir,
2000 &dsi2_dump_regs, debug_fops);
2001}
2114enum dsi_cio_power_state { 2002enum dsi_cio_power_state {
2115 DSI_COMPLEXIO_POWER_OFF = 0x0, 2003 DSI_COMPLEXIO_POWER_OFF = 0x0,
2116 DSI_COMPLEXIO_POWER_ON = 0x1, 2004 DSI_COMPLEXIO_POWER_ON = 0x1,
@@ -2139,6 +2027,34 @@ static int dsi_cio_power(struct platform_device *dsidev,
2139 return 0; 2027 return 0;
2140} 2028}
2141 2029
2030/* Number of data lanes present on DSI interface */
2031static inline int dsi_get_num_data_lanes(struct platform_device *dsidev)
2032{
2033 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
2034 * of data lanes as 2 by default */
2035 if (dss_has_feature(FEAT_DSI_GNQ))
2036 return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */
2037 else
2038 return 2;
2039}
2040
2041/* Number of data lanes used by the dss device */
2042static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
2043{
2044 int num_data_lanes = 0;
2045
2046 if (dssdev->phy.dsi.data1_lane != 0)
2047 num_data_lanes++;
2048 if (dssdev->phy.dsi.data2_lane != 0)
2049 num_data_lanes++;
2050 if (dssdev->phy.dsi.data3_lane != 0)
2051 num_data_lanes++;
2052 if (dssdev->phy.dsi.data4_lane != 0)
2053 num_data_lanes++;
2054
2055 return num_data_lanes;
2056}
2057
2142static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) 2058static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2143{ 2059{
2144 int val; 2060 int val;
@@ -2165,60 +2081,64 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2165 return 1194 * 3; /* 1194x24 bits */ 2081 return 1194 * 3; /* 1194x24 bits */
2166 case 6: 2082 case 6:
2167 return 1365 * 3; /* 1365x24 bits */ 2083 return 1365 * 3; /* 1365x24 bits */
2168 case 7:
2169 return 1920 * 3; /* 1920x24 bits */
2170 default: 2084 default:
2171 BUG(); 2085 BUG();
2172 return 0;
2173 } 2086 }
2174} 2087}
2175 2088
2176static int dsi_set_lane_config(struct platform_device *dsidev) 2089static void dsi_set_lane_config(struct omap_dss_device *dssdev)
2177{ 2090{
2178 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2091 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2179 static const u8 offsets[] = { 0, 4, 8, 12, 16 };
2180 static const enum dsi_lane_function functions[] = {
2181 DSI_LANE_CLK,
2182 DSI_LANE_DATA1,
2183 DSI_LANE_DATA2,
2184 DSI_LANE_DATA3,
2185 DSI_LANE_DATA4,
2186 };
2187 u32 r; 2092 u32 r;
2188 int i; 2093 int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
2189
2190 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
2191 2094
2192 for (i = 0; i < dsi->num_lanes_used; ++i) { 2095 int clk_lane = dssdev->phy.dsi.clk_lane;
2193 unsigned offset = offsets[i]; 2096 int data1_lane = dssdev->phy.dsi.data1_lane;
2194 unsigned polarity, lane_number; 2097 int data2_lane = dssdev->phy.dsi.data2_lane;
2195 unsigned t; 2098 int clk_pol = dssdev->phy.dsi.clk_pol;
2099 int data1_pol = dssdev->phy.dsi.data1_pol;
2100 int data2_pol = dssdev->phy.dsi.data2_pol;
2196 2101
2197 for (t = 0; t < dsi->num_lanes_supported; ++t) 2102 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
2198 if (dsi->lanes[t].function == functions[i]) 2103 r = FLD_MOD(r, clk_lane, 2, 0);
2199 break; 2104 r = FLD_MOD(r, clk_pol, 3, 3);
2200 2105 r = FLD_MOD(r, data1_lane, 6, 4);
2201 if (t == dsi->num_lanes_supported) 2106 r = FLD_MOD(r, data1_pol, 7, 7);
2202 return -EINVAL; 2107 r = FLD_MOD(r, data2_lane, 10, 8);
2203 2108 r = FLD_MOD(r, data2_pol, 11, 11);
2204 lane_number = t; 2109 if (num_data_lanes_dssdev > 2) {
2205 polarity = dsi->lanes[t].polarity; 2110 int data3_lane = dssdev->phy.dsi.data3_lane;
2206 2111 int data3_pol = dssdev->phy.dsi.data3_pol;
2207 r = FLD_MOD(r, lane_number + 1, offset + 2, offset); 2112
2208 r = FLD_MOD(r, polarity, offset + 3, offset + 3); 2113 r = FLD_MOD(r, data3_lane, 14, 12);
2114 r = FLD_MOD(r, data3_pol, 15, 15);
2209 } 2115 }
2116 if (num_data_lanes_dssdev > 3) {
2117 int data4_lane = dssdev->phy.dsi.data4_lane;
2118 int data4_pol = dssdev->phy.dsi.data4_pol;
2210 2119
2211 /* clear the unused lanes */ 2120 r = FLD_MOD(r, data4_lane, 18, 16);
2212 for (; i < dsi->num_lanes_supported; ++i) { 2121 r = FLD_MOD(r, data4_pol, 19, 19);
2213 unsigned offset = offsets[i];
2214
2215 r = FLD_MOD(r, 0, offset + 2, offset);
2216 r = FLD_MOD(r, 0, offset + 3, offset + 3);
2217 } 2122 }
2218
2219 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); 2123 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
2220 2124
2221 return 0; 2125 /* The configuration of the DSI complex I/O (number of data lanes,
2126 position, differential order) should not be changed while
2127 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
2128 the hardware to take into account a new configuration of the complex
2129 I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
2130 follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
2131 then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
2132 DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
2133 DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
2134 DSI complex I/O configuration is unknown. */
2135
2136 /*
2137 REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
2138 REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
2139 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
2140 REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
2141 */
2222} 2142}
2223 2143
2224static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns) 2144static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
@@ -2298,16 +2218,9 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2298 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r); 2218 dsi_write_reg(dsidev, DSI_DSIPHY_CFG0, r);
2299 2219
2300 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 2220 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
2301 r = FLD_MOD(r, tlpx_half, 20, 16); 2221 r = FLD_MOD(r, tlpx_half, 22, 16);
2302 r = FLD_MOD(r, tclk_trail, 15, 8); 2222 r = FLD_MOD(r, tclk_trail, 15, 8);
2303 r = FLD_MOD(r, tclk_zero, 7, 0); 2223 r = FLD_MOD(r, tclk_zero, 7, 0);
2304
2305 if (dss_has_feature(FEAT_DSI_PHY_DCC)) {
2306 r = FLD_MOD(r, 0, 21, 21); /* DCCEN = disable */
2307 r = FLD_MOD(r, 1, 22, 22); /* CLKINP_DIVBY2EN = enable */
2308 r = FLD_MOD(r, 1, 23, 23); /* CLKINP_SEL = enable */
2309 }
2310
2311 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r); 2224 dsi_write_reg(dsidev, DSI_DSIPHY_CFG1, r);
2312 2225
2313 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2); 2226 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG2);
@@ -2315,27 +2228,49 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2315 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r); 2228 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
2316} 2229}
2317 2230
2318/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ 2231static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
2319static void dsi_cio_enable_lane_override(struct platform_device *dsidev, 2232 enum dsi_lane lanes)
2320 unsigned mask_p, unsigned mask_n)
2321{ 2233{
2234 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2322 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2235 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2323 int i; 2236 int clk_lane = dssdev->phy.dsi.clk_lane;
2324 u32 l; 2237 int data1_lane = dssdev->phy.dsi.data1_lane;
2325 u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26; 2238 int data2_lane = dssdev->phy.dsi.data2_lane;
2326 2239 int data3_lane = dssdev->phy.dsi.data3_lane;
2327 l = 0; 2240 int data4_lane = dssdev->phy.dsi.data4_lane;
2328 2241 int clk_pol = dssdev->phy.dsi.clk_pol;
2329 for (i = 0; i < dsi->num_lanes_supported; ++i) { 2242 int data1_pol = dssdev->phy.dsi.data1_pol;
2330 unsigned p = dsi->lanes[i].polarity; 2243 int data2_pol = dssdev->phy.dsi.data2_pol;
2331 2244 int data3_pol = dssdev->phy.dsi.data3_pol;
2332 if (mask_p & (1 << i)) 2245 int data4_pol = dssdev->phy.dsi.data4_pol;
2333 l |= 1 << (i * 2 + (p ? 0 : 1)); 2246
2334 2247 u32 l = 0;
2335 if (mask_n & (1 << i)) 2248 u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26;
2336 l |= 1 << (i * 2 + (p ? 1 : 0)); 2249
2337 } 2250 if (lanes & DSI_CLK_P)
2338 2251 l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
2252 if (lanes & DSI_CLK_N)
2253 l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
2254
2255 if (lanes & DSI_DATA1_P)
2256 l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
2257 if (lanes & DSI_DATA1_N)
2258 l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
2259
2260 if (lanes & DSI_DATA2_P)
2261 l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
2262 if (lanes & DSI_DATA2_N)
2263 l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
2264
2265 if (lanes & DSI_DATA3_P)
2266 l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1));
2267 if (lanes & DSI_DATA3_N)
2268 l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0));
2269
2270 if (lanes & DSI_DATA4_P)
2271 l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1));
2272 if (lanes & DSI_DATA4_N)
2273 l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0));
2339 /* 2274 /*
2340 * Bits in REGLPTXSCPDAT4TO0DXDY: 2275 * Bits in REGLPTXSCPDAT4TO0DXDY:
2341 * 17: DY0 18: DX0 2276 * 17: DY0 18: DX0
@@ -2365,42 +2300,54 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2365 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17); 2300 REG_FLD_MOD(dsidev, DSI_DSIPHY_CFG10, 0, 22, 17);
2366} 2301}
2367 2302
2368static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev) 2303static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2369{ 2304{
2370 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2305 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2371 int t, i; 2306 int t;
2372 bool in_use[DSI_MAX_NR_LANES]; 2307 int bits[3];
2373 static const u8 offsets_old[] = { 28, 27, 26 }; 2308 bool in_use[3];
2374 static const u8 offsets_new[] = { 24, 25, 26, 27, 28 }; 2309
2375 const u8 *offsets; 2310 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
2376 2311 bits[0] = 28;
2377 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) 2312 bits[1] = 27;
2378 offsets = offsets_old; 2313 bits[2] = 26;
2379 else 2314 } else {
2380 offsets = offsets_new; 2315 bits[0] = 24;
2316 bits[1] = 25;
2317 bits[2] = 26;
2318 }
2319
2320 in_use[0] = false;
2321 in_use[1] = false;
2322 in_use[2] = false;
2381 2323
2382 for (i = 0; i < dsi->num_lanes_supported; ++i) 2324 if (dssdev->phy.dsi.clk_lane != 0)
2383 in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED; 2325 in_use[dssdev->phy.dsi.clk_lane - 1] = true;
2326 if (dssdev->phy.dsi.data1_lane != 0)
2327 in_use[dssdev->phy.dsi.data1_lane - 1] = true;
2328 if (dssdev->phy.dsi.data2_lane != 0)
2329 in_use[dssdev->phy.dsi.data2_lane - 1] = true;
2384 2330
2385 t = 100000; 2331 t = 100000;
2386 while (true) { 2332 while (true) {
2387 u32 l; 2333 u32 l;
2334 int i;
2388 int ok; 2335 int ok;
2389 2336
2390 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 2337 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
2391 2338
2392 ok = 0; 2339 ok = 0;
2393 for (i = 0; i < dsi->num_lanes_supported; ++i) { 2340 for (i = 0; i < 3; ++i) {
2394 if (!in_use[i] || (l & (1 << offsets[i]))) 2341 if (!in_use[i] || (l & (1 << bits[i])))
2395 ok++; 2342 ok++;
2396 } 2343 }
2397 2344
2398 if (ok == dsi->num_lanes_supported) 2345 if (ok == 3)
2399 break; 2346 break;
2400 2347
2401 if (--t == 0) { 2348 if (--t == 0) {
2402 for (i = 0; i < dsi->num_lanes_supported; ++i) { 2349 for (i = 0; i < 3; ++i) {
2403 if (!in_use[i] || (l & (1 << offsets[i]))) 2350 if (!in_use[i] || (l & (1 << bits[i])))
2404 continue; 2351 continue;
2405 2352
2406 DSSERR("CIO TXCLKESC%d domain not coming " \ 2353 DSSERR("CIO TXCLKESC%d domain not coming " \
@@ -2413,32 +2360,18 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct platform_device *dsidev)
2413 return 0; 2360 return 0;
2414} 2361}
2415 2362
2416/* return bitmask of enabled lanes, lane0 being the lsb */ 2363static int dsi_cio_init(struct omap_dss_device *dssdev)
2417static unsigned dsi_get_lane_mask(struct platform_device *dsidev)
2418{
2419 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2420 unsigned mask = 0;
2421 int i;
2422
2423 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2424 if (dsi->lanes[i].function != DSI_LANE_UNUSED)
2425 mask |= 1 << i;
2426 }
2427
2428 return mask;
2429}
2430
2431static int dsi_cio_init(struct platform_device *dsidev)
2432{ 2364{
2365 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2433 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2366 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2434 int r; 2367 int r;
2368 int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
2435 u32 l; 2369 u32 l;
2436 2370
2437 DSSDBG("DSI CIO init starts"); 2371 DSSDBGF();
2438 2372
2439 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); 2373 if (dsi->dsi_mux_pads)
2440 if (r) 2374 dsi->dsi_mux_pads(true);
2441 return r;
2442 2375
2443 dsi_enable_scp_clk(dsidev); 2376 dsi_enable_scp_clk(dsidev);
2444 2377
@@ -2453,9 +2386,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
2453 goto err_scp_clk_dom; 2386 goto err_scp_clk_dom;
2454 } 2387 }
2455 2388
2456 r = dsi_set_lane_config(dsidev); 2389 dsi_set_lane_config(dssdev);
2457 if (r)
2458 goto err_scp_clk_dom;
2459 2390
2460 /* set TX STOP MODE timer to maximum for this operation */ 2391 /* set TX STOP MODE timer to maximum for this operation */
2461 l = dsi_read_reg(dsidev, DSI_TIMING1); 2392 l = dsi_read_reg(dsidev, DSI_TIMING1);
@@ -2466,8 +2397,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
2466 dsi_write_reg(dsidev, DSI_TIMING1, l); 2397 dsi_write_reg(dsidev, DSI_TIMING1, l);
2467 2398
2468 if (dsi->ulps_enabled) { 2399 if (dsi->ulps_enabled) {
2469 unsigned mask_p; 2400 u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P;
2470 int i;
2471 2401
2472 DSSDBG("manual ulps exit\n"); 2402 DSSDBG("manual ulps exit\n");
2473 2403
@@ -2476,19 +2406,16 @@ static int dsi_cio_init(struct platform_device *dsidev)
2476 * ULPS exit sequence, as after reset the DSS HW thinks 2406 * ULPS exit sequence, as after reset the DSS HW thinks
2477 * that we are not in ULPS mode, and refuses to send the 2407 * that we are not in ULPS mode, and refuses to send the
2478 * sequence. So we need to send the ULPS exit sequence 2408 * sequence. So we need to send the ULPS exit sequence
2479 * manually by setting positive lines high and negative lines 2409 * manually.
2480 * low for 1ms.
2481 */ 2410 */
2482 2411
2483 mask_p = 0; 2412 if (num_data_lanes_dssdev > 2)
2413 lane_mask |= DSI_DATA3_P;
2484 2414
2485 for (i = 0; i < dsi->num_lanes_supported; ++i) { 2415 if (num_data_lanes_dssdev > 3)
2486 if (dsi->lanes[i].function == DSI_LANE_UNUSED) 2416 lane_mask |= DSI_DATA4_P;
2487 continue;
2488 mask_p |= 1 << i;
2489 }
2490 2417
2491 dsi_cio_enable_lane_override(dsidev, mask_p, 0); 2418 dsi_cio_enable_lane_override(dssdev, lane_mask);
2492 } 2419 }
2493 2420
2494 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); 2421 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2505,7 +2432,7 @@ static int dsi_cio_init(struct platform_device *dsidev)
2505 dsi_if_enable(dsidev, false); 2432 dsi_if_enable(dsidev, false);
2506 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */ 2433 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); /* LP_CLK_ENABLE */
2507 2434
2508 r = dsi_cio_wait_tx_clk_esc_reset(dsidev); 2435 r = dsi_cio_wait_tx_clk_esc_reset(dssdev);
2509 if (r) 2436 if (r)
2510 goto err_tx_clk_esc_rst; 2437 goto err_tx_clk_esc_rst;
2511 2438
@@ -2525,12 +2452,6 @@ static int dsi_cio_init(struct platform_device *dsidev)
2525 2452
2526 dsi_cio_timings(dsidev); 2453 dsi_cio_timings(dsidev);
2527 2454
2528 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
2529 /* DDR_CLK_ALWAYS_ON */
2530 REG_FLD_MOD(dsidev, DSI_CLK_CTRL,
2531 dsi->vm_timings.ddr_clk_always_on, 13, 13);
2532 }
2533
2534 dsi->ulps_enabled = false; 2455 dsi->ulps_enabled = false;
2535 2456
2536 DSSDBG("CIO init done\n"); 2457 DSSDBG("CIO init done\n");
@@ -2546,7 +2467,8 @@ err_cio_pwr:
2546 dsi_cio_disable_lane_override(dsidev); 2467 dsi_cio_disable_lane_override(dsidev);
2547err_scp_clk_dom: 2468err_scp_clk_dom:
2548 dsi_disable_scp_clk(dsidev); 2469 dsi_disable_scp_clk(dsidev);
2549 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); 2470 if (dsi->dsi_mux_pads)
2471 dsi->dsi_mux_pads(false);
2550 return r; 2472 return r;
2551} 2473}
2552 2474
@@ -2554,12 +2476,10 @@ static void dsi_cio_uninit(struct platform_device *dsidev)
2554{ 2476{
2555 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2477 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2556 2478
2557 /* DDR_CLK_ALWAYS_ON */
2558 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
2559
2560 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); 2479 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2561 dsi_disable_scp_clk(dsidev); 2480 dsi_disable_scp_clk(dsidev);
2562 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dsidev)); 2481 if (dsi->dsi_mux_pads)
2482 dsi->dsi_mux_pads(false);
2563} 2483}
2564 2484
2565static void dsi_config_tx_fifo(struct platform_device *dsidev, 2485static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2583,7 +2503,6 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev,
2583 if (add + size > 4) { 2503 if (add + size > 4) {
2584 DSSERR("Illegal FIFO configuration\n"); 2504 DSSERR("Illegal FIFO configuration\n");
2585 BUG(); 2505 BUG();
2586 return;
2587 } 2506 }
2588 2507
2589 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); 2508 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
@@ -2616,7 +2535,6 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev,
2616 if (add + size > 4) { 2535 if (add + size > 4) {
2617 DSSERR("Illegal FIFO configuration\n"); 2536 DSSERR("Illegal FIFO configuration\n");
2618 BUG(); 2537 BUG();
2619 return;
2620 } 2538 }
2621 2539
2622 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); 2540 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
@@ -2751,14 +2669,13 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)
2751 if (!dsi_vc_is_enabled(dsidev, channel)) 2669 if (!dsi_vc_is_enabled(dsidev, channel))
2752 return 0; 2670 return 0;
2753 2671
2754 switch (dsi->vc[channel].source) { 2672 switch (dsi->vc[channel].mode) {
2755 case DSI_VC_SOURCE_VP: 2673 case DSI_VC_MODE_VP:
2756 return dsi_sync_vc_vp(dsidev, channel); 2674 return dsi_sync_vc_vp(dsidev, channel);
2757 case DSI_VC_SOURCE_L4: 2675 case DSI_VC_MODE_L4:
2758 return dsi_sync_vc_l4(dsidev, channel); 2676 return dsi_sync_vc_l4(dsidev, channel);
2759 default: 2677 default:
2760 BUG(); 2678 BUG();
2761 return -EINVAL;
2762 } 2679 }
2763} 2680}
2764 2681
@@ -2785,7 +2702,7 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2785{ 2702{
2786 u32 r; 2703 u32 r;
2787 2704
2788 DSSDBG("Initial config of virtual channel %d", channel); 2705 DSSDBGF("%d", channel);
2789 2706
2790 r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel)); 2707 r = dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
2791 2708
@@ -2809,15 +2726,14 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel)
2809 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); 2726 dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r);
2810} 2727}
2811 2728
2812static int dsi_vc_config_source(struct platform_device *dsidev, int channel, 2729static int dsi_vc_config_l4(struct platform_device *dsidev, int channel)
2813 enum dsi_vc_source source)
2814{ 2730{
2815 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2731 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2816 2732
2817 if (dsi->vc[channel].source == source) 2733 if (dsi->vc[channel].mode == DSI_VC_MODE_L4)
2818 return 0; 2734 return 0;
2819 2735
2820 DSSDBG("Source config of virtual channel %d", channel); 2736 DSSDBGF("%d", channel);
2821 2737
2822 dsi_sync_vc(dsidev, channel); 2738 dsi_sync_vc(dsidev, channel);
2823 2739
@@ -2825,31 +2741,61 @@ static int dsi_vc_config_source(struct platform_device *dsidev, int channel,
2825 2741
2826 /* VC_BUSY */ 2742 /* VC_BUSY */
2827 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) { 2743 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
2828 DSSERR("vc(%d) busy when trying to config for VP\n", channel); 2744 DSSERR("vc(%d) busy when trying to config for L4\n", channel);
2829 return -EIO; 2745 return -EIO;
2830 } 2746 }
2831 2747
2832 /* SOURCE, 0 = L4, 1 = video port */ 2748 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
2833 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), source, 1, 1);
2834 2749
2835 /* DCS_CMD_ENABLE */ 2750 /* DCS_CMD_ENABLE */
2836 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { 2751 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
2837 bool enable = source == DSI_VC_SOURCE_VP; 2752 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 30, 30);
2838 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), enable, 30, 30); 2753
2754 dsi_vc_enable(dsidev, channel, 1);
2755
2756 dsi->vc[channel].mode = DSI_VC_MODE_L4;
2757
2758 return 0;
2759}
2760
2761static int dsi_vc_config_vp(struct platform_device *dsidev, int channel)
2762{
2763 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2764
2765 if (dsi->vc[channel].mode == DSI_VC_MODE_VP)
2766 return 0;
2767
2768 DSSDBGF("%d", channel);
2769
2770 dsi_sync_vc(dsidev, channel);
2771
2772 dsi_vc_enable(dsidev, channel, 0);
2773
2774 /* VC_BUSY */
2775 if (wait_for_bit_change(dsidev, DSI_VC_CTRL(channel), 15, 0) != 0) {
2776 DSSERR("vc(%d) busy when trying to config for VP\n", channel);
2777 return -EIO;
2839 } 2778 }
2840 2779
2780 /* SOURCE, 1 = video port */
2781 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 1, 1);
2782
2783 /* DCS_CMD_ENABLE */
2784 if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
2785 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 30, 30);
2786
2841 dsi_vc_enable(dsidev, channel, 1); 2787 dsi_vc_enable(dsidev, channel, 1);
2842 2788
2843 dsi->vc[channel].source = source; 2789 dsi->vc[channel].mode = DSI_VC_MODE_VP;
2844 2790
2845 return 0; 2791 return 0;
2846} 2792}
2847 2793
2794
2848void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel, 2795void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2849 bool enable) 2796 bool enable)
2850{ 2797{
2851 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2798 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2852 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2853 2799
2854 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable); 2800 DSSDBG("dsi_vc_enable_hs(%d, %d)\n", channel, enable);
2855 2801
@@ -2864,10 +2810,6 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
2864 dsi_if_enable(dsidev, 1); 2810 dsi_if_enable(dsidev, 1);
2865 2811
2866 dsi_force_tx_stop_mode_io(dsidev); 2812 dsi_force_tx_stop_mode_io(dsidev);
2867
2868 /* start the DDR clock by sending a NULL packet */
2869 if (dsi->vm_timings.ddr_clk_always_on && enable)
2870 dsi_vc_send_null(dssdev, channel);
2871} 2813}
2872EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs); 2814EXPORT_SYMBOL(omapdss_dsi_vc_enable_hs);
2873 2815
@@ -2931,16 +2873,16 @@ static u16 dsi_vc_flush_receive_data(struct platform_device *dsidev,
2931 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel)); 2873 val = dsi_read_reg(dsidev, DSI_VC_SHORT_PACKET_HEADER(channel));
2932 DSSERR("\trawval %#08x\n", val); 2874 DSSERR("\trawval %#08x\n", val);
2933 dt = FLD_GET(val, 5, 0); 2875 dt = FLD_GET(val, 5, 0);
2934 if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) { 2876 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
2935 u16 err = FLD_GET(val, 23, 8); 2877 u16 err = FLD_GET(val, 23, 8);
2936 dsi_show_rx_ack_with_err(err); 2878 dsi_show_rx_ack_with_err(err);
2937 } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE) { 2879 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
2938 DSSERR("\tDCS short response, 1 byte: %#x\n", 2880 DSSERR("\tDCS short response, 1 byte: %#x\n",
2939 FLD_GET(val, 23, 8)); 2881 FLD_GET(val, 23, 8));
2940 } else if (dt == MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE) { 2882 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
2941 DSSERR("\tDCS short response, 2 byte: %#x\n", 2883 DSSERR("\tDCS short response, 2 byte: %#x\n",
2942 FLD_GET(val, 23, 8)); 2884 FLD_GET(val, 23, 8));
2943 } else if (dt == MIPI_DSI_RX_DCS_LONG_READ_RESPONSE) { 2885 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
2944 DSSERR("\tDCS long response, len %d\n", 2886 DSSERR("\tDCS long response, len %d\n",
2945 FLD_GET(val, 23, 8)); 2887 FLD_GET(val, 23, 8));
2946 dsi_vc_flush_long_data(dsidev, channel); 2888 dsi_vc_flush_long_data(dsidev, channel);
@@ -2968,9 +2910,6 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
2968 2910
2969 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ 2911 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
2970 2912
2971 /* flush posted write */
2972 dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
2973
2974 return 0; 2913 return 0;
2975} 2914}
2976 2915
@@ -3068,7 +3007,7 @@ static int dsi_vc_send_long(struct platform_device *dsidev, int channel,
3068 return -EINVAL; 3007 return -EINVAL;
3069 } 3008 }
3070 3009
3071 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4); 3010 dsi_vc_config_l4(dsidev, channel);
3072 3011
3073 dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc); 3012 dsi_vc_write_long_header(dsidev, channel, data_type, len, ecc);
3074 3013
@@ -3127,7 +3066,7 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
3127 channel, 3066 channel,
3128 data_type, data & 0xff, (data >> 8) & 0xff); 3067 data_type, data & 0xff, (data >> 8) & 0xff);
3129 3068
3130 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_L4); 3069 dsi_vc_config_l4(dsidev, channel);
3131 3070
3132 if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) { 3071 if (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(channel)), 16, 16)) {
3133 DSSERR("ERROR FIFO FULL, aborting transfer\n"); 3072 DSSERR("ERROR FIFO FULL, aborting transfer\n");
@@ -3146,69 +3085,44 @@ static int dsi_vc_send_short(struct platform_device *dsidev, int channel,
3146int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel) 3085int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel)
3147{ 3086{
3148 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3087 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3088 u8 nullpkg[] = {0, 0, 0, 0};
3149 3089
3150 return dsi_vc_send_long(dsidev, channel, MIPI_DSI_NULL_PACKET, NULL, 3090 return dsi_vc_send_long(dsidev, channel, DSI_DT_NULL_PACKET, nullpkg,
3151 0, 0); 3091 4, 0);
3152} 3092}
3153EXPORT_SYMBOL(dsi_vc_send_null); 3093EXPORT_SYMBOL(dsi_vc_send_null);
3154 3094
3155static int dsi_vc_write_nosync_common(struct platform_device *dsidev, 3095int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3156 int channel, u8 *data, int len, enum dss_dsi_content_type type) 3096 u8 *data, int len)
3157{ 3097{
3098 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3158 int r; 3099 int r;
3159 3100
3160 if (len == 0) { 3101 BUG_ON(len == 0);
3161 BUG_ON(type == DSS_DSI_CONTENT_DCS); 3102
3162 r = dsi_vc_send_short(dsidev, channel, 3103 if (len == 1) {
3163 MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM, 0, 0); 3104 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_0,
3164 } else if (len == 1) { 3105 data[0], 0);
3165 r = dsi_vc_send_short(dsidev, channel,
3166 type == DSS_DSI_CONTENT_GENERIC ?
3167 MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM :
3168 MIPI_DSI_DCS_SHORT_WRITE, data[0], 0);
3169 } else if (len == 2) { 3106 } else if (len == 2) {
3170 r = dsi_vc_send_short(dsidev, channel, 3107 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_SHORT_WRITE_1,
3171 type == DSS_DSI_CONTENT_GENERIC ?
3172 MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM :
3173 MIPI_DSI_DCS_SHORT_WRITE_PARAM,
3174 data[0] | (data[1] << 8), 0); 3108 data[0] | (data[1] << 8), 0);
3175 } else { 3109 } else {
3176 r = dsi_vc_send_long(dsidev, channel, 3110 /* 0x39 = DCS Long Write */
3177 type == DSS_DSI_CONTENT_GENERIC ? 3111 r = dsi_vc_send_long(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
3178 MIPI_DSI_GENERIC_LONG_WRITE : 3112 data, len, 0);
3179 MIPI_DSI_DCS_LONG_WRITE, data, len, 0);
3180 } 3113 }
3181 3114
3182 return r; 3115 return r;
3183} 3116}
3184
3185int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
3186 u8 *data, int len)
3187{
3188 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3189
3190 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3191 DSS_DSI_CONTENT_DCS);
3192}
3193EXPORT_SYMBOL(dsi_vc_dcs_write_nosync); 3117EXPORT_SYMBOL(dsi_vc_dcs_write_nosync);
3194 3118
3195int dsi_vc_generic_write_nosync(struct omap_dss_device *dssdev, int channel, 3119int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3196 u8 *data, int len) 3120 int len)
3197{
3198 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3199
3200 return dsi_vc_write_nosync_common(dsidev, channel, data, len,
3201 DSS_DSI_CONTENT_GENERIC);
3202}
3203EXPORT_SYMBOL(dsi_vc_generic_write_nosync);
3204
3205static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3206 u8 *data, int len, enum dss_dsi_content_type type)
3207{ 3121{
3208 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3122 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3209 int r; 3123 int r;
3210 3124
3211 r = dsi_vc_write_nosync_common(dsidev, channel, data, len, type); 3125 r = dsi_vc_dcs_write_nosync(dssdev, channel, data, len);
3212 if (r) 3126 if (r)
3213 goto err; 3127 goto err;
3214 3128
@@ -3226,39 +3140,18 @@ static int dsi_vc_write_common(struct omap_dss_device *dssdev, int channel,
3226 3140
3227 return 0; 3141 return 0;
3228err: 3142err:
3229 DSSERR("dsi_vc_write_common(ch %d, cmd 0x%02x, len %d) failed\n", 3143 DSSERR("dsi_vc_dcs_write(ch %d, cmd 0x%02x, len %d) failed\n",
3230 channel, data[0], len); 3144 channel, data[0], len);
3231 return r; 3145 return r;
3232} 3146}
3233
3234int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3235 int len)
3236{
3237 return dsi_vc_write_common(dssdev, channel, data, len,
3238 DSS_DSI_CONTENT_DCS);
3239}
3240EXPORT_SYMBOL(dsi_vc_dcs_write); 3147EXPORT_SYMBOL(dsi_vc_dcs_write);
3241 3148
3242int dsi_vc_generic_write(struct omap_dss_device *dssdev, int channel, u8 *data,
3243 int len)
3244{
3245 return dsi_vc_write_common(dssdev, channel, data, len,
3246 DSS_DSI_CONTENT_GENERIC);
3247}
3248EXPORT_SYMBOL(dsi_vc_generic_write);
3249
3250int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd) 3149int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd)
3251{ 3150{
3252 return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1); 3151 return dsi_vc_dcs_write(dssdev, channel, &dcs_cmd, 1);
3253} 3152}
3254EXPORT_SYMBOL(dsi_vc_dcs_write_0); 3153EXPORT_SYMBOL(dsi_vc_dcs_write_0);
3255 3154
3256int dsi_vc_generic_write_0(struct omap_dss_device *dssdev, int channel)
3257{
3258 return dsi_vc_generic_write(dssdev, channel, NULL, 0);
3259}
3260EXPORT_SYMBOL(dsi_vc_generic_write_0);
3261
3262int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd, 3155int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3263 u8 param) 3156 u8 param)
3264{ 3157{
@@ -3269,86 +3162,25 @@ int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3269} 3162}
3270EXPORT_SYMBOL(dsi_vc_dcs_write_1); 3163EXPORT_SYMBOL(dsi_vc_dcs_write_1);
3271 3164
3272int dsi_vc_generic_write_1(struct omap_dss_device *dssdev, int channel, 3165int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3273 u8 param) 3166 u8 *buf, int buflen)
3274{
3275 return dsi_vc_generic_write(dssdev, channel, &param, 1);
3276}
3277EXPORT_SYMBOL(dsi_vc_generic_write_1);
3278
3279int dsi_vc_generic_write_2(struct omap_dss_device *dssdev, int channel,
3280 u8 param1, u8 param2)
3281{
3282 u8 buf[2];
3283 buf[0] = param1;
3284 buf[1] = param2;
3285 return dsi_vc_generic_write(dssdev, channel, buf, 2);
3286}
3287EXPORT_SYMBOL(dsi_vc_generic_write_2);
3288
3289static int dsi_vc_dcs_send_read_request(struct platform_device *dsidev,
3290 int channel, u8 dcs_cmd)
3291{ 3167{
3168 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3292 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3169 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3170 u32 val;
3171 u8 dt;
3293 int r; 3172 int r;
3294 3173
3295 if (dsi->debug_read) 3174 if (dsi->debug_read)
3296 DSSDBG("dsi_vc_dcs_send_read_request(ch%d, dcs_cmd %x)\n", 3175 DSSDBG("dsi_vc_dcs_read(ch%d, dcs_cmd %x)\n", channel, dcs_cmd);
3297 channel, dcs_cmd);
3298
3299 r = dsi_vc_send_short(dsidev, channel, MIPI_DSI_DCS_READ, dcs_cmd, 0);
3300 if (r) {
3301 DSSERR("dsi_vc_dcs_send_read_request(ch %d, cmd 0x%02x)"
3302 " failed\n", channel, dcs_cmd);
3303 return r;
3304 }
3305
3306 return 0;
3307}
3308 3176
3309static int dsi_vc_generic_send_read_request(struct platform_device *dsidev, 3177 r = dsi_vc_send_short(dsidev, channel, DSI_DT_DCS_READ, dcs_cmd, 0);
3310 int channel, u8 *reqdata, int reqlen) 3178 if (r)
3311{ 3179 goto err;
3312 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3313 u16 data;
3314 u8 data_type;
3315 int r;
3316
3317 if (dsi->debug_read)
3318 DSSDBG("dsi_vc_generic_send_read_request(ch %d, reqlen %d)\n",
3319 channel, reqlen);
3320
3321 if (reqlen == 0) {
3322 data_type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
3323 data = 0;
3324 } else if (reqlen == 1) {
3325 data_type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
3326 data = reqdata[0];
3327 } else if (reqlen == 2) {
3328 data_type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
3329 data = reqdata[0] | (reqdata[1] << 8);
3330 } else {
3331 BUG();
3332 return -EINVAL;
3333 }
3334
3335 r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
3336 if (r) {
3337 DSSERR("dsi_vc_generic_send_read_request(ch %d, reqlen %d)"
3338 " failed\n", channel, reqlen);
3339 return r;
3340 }
3341
3342 return 0;
3343}
3344 3180
3345static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel, 3181 r = dsi_vc_send_bta_sync(dssdev, channel);
3346 u8 *buf, int buflen, enum dss_dsi_content_type type) 3182 if (r)
3347{ 3183 goto err;
3348 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3349 u32 val;
3350 u8 dt;
3351 int r;
3352 3184
3353 /* RX_FIFO_NOT_EMPTY */ 3185 /* RX_FIFO_NOT_EMPTY */
3354 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) { 3186 if (REG_GET(dsidev, DSI_VC_CTRL(channel), 20, 20) == 0) {
@@ -3361,20 +3193,16 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3361 if (dsi->debug_read) 3193 if (dsi->debug_read)
3362 DSSDBG("\theader: %08x\n", val); 3194 DSSDBG("\theader: %08x\n", val);
3363 dt = FLD_GET(val, 5, 0); 3195 dt = FLD_GET(val, 5, 0);
3364 if (dt == MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT) { 3196 if (dt == DSI_DT_RX_ACK_WITH_ERR) {
3365 u16 err = FLD_GET(val, 23, 8); 3197 u16 err = FLD_GET(val, 23, 8);
3366 dsi_show_rx_ack_with_err(err); 3198 dsi_show_rx_ack_with_err(err);
3367 r = -EIO; 3199 r = -EIO;
3368 goto err; 3200 goto err;
3369 3201
3370 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? 3202 } else if (dt == DSI_DT_RX_SHORT_READ_1) {
3371 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE :
3372 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE)) {
3373 u8 data = FLD_GET(val, 15, 8); 3203 u8 data = FLD_GET(val, 15, 8);
3374 if (dsi->debug_read) 3204 if (dsi->debug_read)
3375 DSSDBG("\t%s short response, 1 byte: %02x\n", 3205 DSSDBG("\tDCS short response, 1 byte: %02x\n", data);
3376 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3377 "DCS", data);
3378 3206
3379 if (buflen < 1) { 3207 if (buflen < 1) {
3380 r = -EIO; 3208 r = -EIO;
@@ -3384,14 +3212,10 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3384 buf[0] = data; 3212 buf[0] = data;
3385 3213
3386 return 1; 3214 return 1;
3387 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? 3215 } else if (dt == DSI_DT_RX_SHORT_READ_2) {
3388 MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE :
3389 MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE)) {
3390 u16 data = FLD_GET(val, 23, 8); 3216 u16 data = FLD_GET(val, 23, 8);
3391 if (dsi->debug_read) 3217 if (dsi->debug_read)
3392 DSSDBG("\t%s short response, 2 byte: %04x\n", 3218 DSSDBG("\tDCS short response, 2 byte: %04x\n", data);
3393 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3394 "DCS", data);
3395 3219
3396 if (buflen < 2) { 3220 if (buflen < 2) {
3397 r = -EIO; 3221 r = -EIO;
@@ -3402,15 +3226,11 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3402 buf[1] = (data >> 8) & 0xff; 3226 buf[1] = (data >> 8) & 0xff;
3403 3227
3404 return 2; 3228 return 2;
3405 } else if (dt == (type == DSS_DSI_CONTENT_GENERIC ? 3229 } else if (dt == DSI_DT_RX_DCS_LONG_READ) {
3406 MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE :
3407 MIPI_DSI_RX_DCS_LONG_READ_RESPONSE)) {
3408 int w; 3230 int w;
3409 int len = FLD_GET(val, 23, 8); 3231 int len = FLD_GET(val, 23, 8);
3410 if (dsi->debug_read) 3232 if (dsi->debug_read)
3411 DSSDBG("\t%s long response, len %d\n", 3233 DSSDBG("\tDCS long response, len %d\n", len);
3412 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" :
3413 "DCS", len);
3414 3234
3415 if (len > buflen) { 3235 if (len > buflen) {
3416 r = -EIO; 3236 r = -EIO;
@@ -3444,127 +3264,60 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3444 goto err; 3264 goto err;
3445 } 3265 }
3446 3266
3267 BUG();
3447err: 3268err:
3448 DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, 3269 DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n",
3449 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); 3270 channel, dcs_cmd);
3450
3451 return r; 3271 return r;
3452}
3453 3272
3454int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3455 u8 *buf, int buflen)
3456{
3457 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3458 int r;
3459
3460 r = dsi_vc_dcs_send_read_request(dsidev, channel, dcs_cmd);
3461 if (r)
3462 goto err;
3463
3464 r = dsi_vc_send_bta_sync(dssdev, channel);
3465 if (r)
3466 goto err;
3467
3468 r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
3469 DSS_DSI_CONTENT_DCS);
3470 if (r < 0)
3471 goto err;
3472
3473 if (r != buflen) {
3474 r = -EIO;
3475 goto err;
3476 }
3477
3478 return 0;
3479err:
3480 DSSERR("dsi_vc_dcs_read(ch %d, cmd 0x%02x) failed\n", channel, dcs_cmd);
3481 return r;
3482} 3273}
3483EXPORT_SYMBOL(dsi_vc_dcs_read); 3274EXPORT_SYMBOL(dsi_vc_dcs_read);
3484 3275
3485static int dsi_vc_generic_read(struct omap_dss_device *dssdev, int channel, 3276int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3486 u8 *reqdata, int reqlen, u8 *buf, int buflen) 3277 u8 *data)
3487{ 3278{
3488 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3489 int r; 3279 int r;
3490 3280
3491 r = dsi_vc_generic_send_read_request(dsidev, channel, reqdata, reqlen); 3281 r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, data, 1);
3492 if (r)
3493 return r;
3494 3282
3495 r = dsi_vc_send_bta_sync(dssdev, channel);
3496 if (r)
3497 return r;
3498
3499 r = dsi_vc_read_rx_fifo(dsidev, channel, buf, buflen,
3500 DSS_DSI_CONTENT_GENERIC);
3501 if (r < 0) 3283 if (r < 0)
3502 return r; 3284 return r;
3503 3285
3504 if (r != buflen) { 3286 if (r != 1)
3505 r = -EIO; 3287 return -EIO;
3506 return r;
3507 }
3508 3288
3509 return 0; 3289 return 0;
3510} 3290}
3291EXPORT_SYMBOL(dsi_vc_dcs_read_1);
3511 3292
3512int dsi_vc_generic_read_0(struct omap_dss_device *dssdev, int channel, u8 *buf, 3293int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
3513 int buflen) 3294 u8 *data1, u8 *data2)
3514{ 3295{
3296 u8 buf[2];
3515 int r; 3297 int r;
3516 3298
3517 r = dsi_vc_generic_read(dssdev, channel, NULL, 0, buf, buflen); 3299 r = dsi_vc_dcs_read(dssdev, channel, dcs_cmd, buf, 2);
3518 if (r) {
3519 DSSERR("dsi_vc_generic_read_0(ch %d) failed\n", channel);
3520 return r;
3521 }
3522
3523 return 0;
3524}
3525EXPORT_SYMBOL(dsi_vc_generic_read_0);
3526 3300
3527int dsi_vc_generic_read_1(struct omap_dss_device *dssdev, int channel, u8 param, 3301 if (r < 0)
3528 u8 *buf, int buflen)
3529{
3530 int r;
3531
3532 r = dsi_vc_generic_read(dssdev, channel, &param, 1, buf, buflen);
3533 if (r) {
3534 DSSERR("dsi_vc_generic_read_1(ch %d) failed\n", channel);
3535 return r; 3302 return r;
3536 }
3537
3538 return 0;
3539}
3540EXPORT_SYMBOL(dsi_vc_generic_read_1);
3541
3542int dsi_vc_generic_read_2(struct omap_dss_device *dssdev, int channel,
3543 u8 param1, u8 param2, u8 *buf, int buflen)
3544{
3545 int r;
3546 u8 reqdata[2];
3547 3303
3548 reqdata[0] = param1; 3304 if (r != 2)
3549 reqdata[1] = param2; 3305 return -EIO;
3550 3306
3551 r = dsi_vc_generic_read(dssdev, channel, reqdata, 2, buf, buflen); 3307 *data1 = buf[0];
3552 if (r) { 3308 *data2 = buf[1];
3553 DSSERR("dsi_vc_generic_read_2(ch %d) failed\n", channel);
3554 return r;
3555 }
3556 3309
3557 return 0; 3310 return 0;
3558} 3311}
3559EXPORT_SYMBOL(dsi_vc_generic_read_2); 3312EXPORT_SYMBOL(dsi_vc_dcs_read_2);
3560 3313
3561int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel, 3314int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
3562 u16 len) 3315 u16 len)
3563{ 3316{
3564 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3317 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3565 3318
3566 return dsi_vc_send_short(dsidev, channel, 3319 return dsi_vc_send_short(dsidev, channel, DSI_DT_SET_MAX_RET_PKG_SIZE,
3567 MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, len, 0); 3320 len, 0);
3568} 3321}
3569EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size); 3322EXPORT_SYMBOL(dsi_vc_set_max_rx_packet_size);
3570 3323
@@ -3572,10 +3325,9 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3572{ 3325{
3573 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3326 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3574 DECLARE_COMPLETION_ONSTACK(completion); 3327 DECLARE_COMPLETION_ONSTACK(completion);
3575 int r, i; 3328 int r;
3576 unsigned mask;
3577 3329
3578 DSSDBG("Entering ULPS"); 3330 DSSDBGF();
3579 3331
3580 WARN_ON(!dsi_bus_is_locked(dsidev)); 3332 WARN_ON(!dsi_bus_is_locked(dsidev));
3581 3333
@@ -3584,11 +3336,9 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3584 if (dsi->ulps_enabled) 3336 if (dsi->ulps_enabled)
3585 return 0; 3337 return 0;
3586 3338
3587 /* DDR_CLK_ALWAYS_ON */
3588 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) { 3339 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
3589 dsi_if_enable(dsidev, 0); 3340 DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n");
3590 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); 3341 return -EIO;
3591 dsi_if_enable(dsidev, 1);
3592 } 3342 }
3593 3343
3594 dsi_sync_vc(dsidev, 0); 3344 dsi_sync_vc(dsidev, 0);
@@ -3618,19 +3368,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3618 if (r) 3368 if (r)
3619 return r; 3369 return r;
3620 3370
3621 mask = 0;
3622
3623 for (i = 0; i < dsi->num_lanes_supported; ++i) {
3624 if (dsi->lanes[i].function == DSI_LANE_UNUSED)
3625 continue;
3626 mask |= 1 << i;
3627 }
3628 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */ 3371 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
3629 /* LANEx_ULPS_SIG2 */ 3372 /* LANEx_ULPS_SIG2 */
3630 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5); 3373 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2),
3631 3374 7, 5);
3632 /* flush posted write and wait for SCP interface to finish the write */
3633 dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
3634 3375
3635 if (wait_for_completion_timeout(&completion, 3376 if (wait_for_completion_timeout(&completion,
3636 msecs_to_jiffies(1000)) == 0) { 3377 msecs_to_jiffies(1000)) == 0) {
@@ -3643,10 +3384,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3643 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); 3384 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3644 3385
3645 /* Reset LANEx_ULPS_SIG2 */ 3386 /* Reset LANEx_ULPS_SIG2 */
3646 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5); 3387 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
3647 3388 7, 5);
3648 /* flush posted write and wait for SCP interface to finish the write */
3649 dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
3650 3389
3651 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); 3390 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
3652 3391
@@ -3769,256 +3508,9 @@ static void dsi_set_hs_tx_timeout(struct platform_device *dsidev,
3769 ticks, x4 ? " x4" : "", x16 ? " x16" : "", 3508 ticks, x4 ? " x4" : "", x16 ? " x16" : "",
3770 (total_ticks * 1000) / (fck / 1000 / 1000)); 3509 (total_ticks * 1000) / (fck / 1000 / 1000));
3771} 3510}
3772
3773static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev)
3774{
3775 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3776 int num_line_buffers;
3777
3778 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
3779 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3780 unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
3781 struct omap_video_timings *timings = &dsi->timings;
3782 /*
3783 * Don't use line buffers if width is greater than the video
3784 * port's line buffer size
3785 */
3786 if (line_buf_size <= timings->x_res * bpp / 8)
3787 num_line_buffers = 0;
3788 else
3789 num_line_buffers = 2;
3790 } else {
3791 /* Use maximum number of line buffers in command mode */
3792 num_line_buffers = 2;
3793 }
3794
3795 /* LINE_BUFFER */
3796 REG_FLD_MOD(dsidev, DSI_CTRL, num_line_buffers, 13, 12);
3797}
3798
3799static void dsi_config_vp_sync_events(struct platform_device *dsidev)
3800{
3801 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3802 bool vsync_end = dsi->vm_timings.vp_vsync_end;
3803 bool hsync_end = dsi->vm_timings.vp_hsync_end;
3804 u32 r;
3805
3806 r = dsi_read_reg(dsidev, DSI_CTRL);
3807 r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */
3808 r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */
3809 r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */
3810 r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */
3811 r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */
3812 r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */
3813 r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */
3814 dsi_write_reg(dsidev, DSI_CTRL, r);
3815}
3816
3817static void dsi_config_blanking_modes(struct platform_device *dsidev)
3818{
3819 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3820 int blanking_mode = dsi->vm_timings.blanking_mode;
3821 int hfp_blanking_mode = dsi->vm_timings.hfp_blanking_mode;
3822 int hbp_blanking_mode = dsi->vm_timings.hbp_blanking_mode;
3823 int hsa_blanking_mode = dsi->vm_timings.hsa_blanking_mode;
3824 u32 r;
3825
3826 /*
3827 * 0 = TX FIFO packets sent or LPS in corresponding blanking periods
3828 * 1 = Long blanking packets are sent in corresponding blanking periods
3829 */
3830 r = dsi_read_reg(dsidev, DSI_CTRL);
3831 r = FLD_MOD(r, blanking_mode, 20, 20); /* BLANKING_MODE */
3832 r = FLD_MOD(r, hfp_blanking_mode, 21, 21); /* HFP_BLANKING */
3833 r = FLD_MOD(r, hbp_blanking_mode, 22, 22); /* HBP_BLANKING */
3834 r = FLD_MOD(r, hsa_blanking_mode, 23, 23); /* HSA_BLANKING */
3835 dsi_write_reg(dsidev, DSI_CTRL, r);
3836}
3837
3838/*
3839 * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
3840 * results in maximum transition time for data and clock lanes to enter and
3841 * exit HS mode. Hence, this is the scenario where the least amount of command
3842 * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
3843 * clock cycles that can be used to interleave command mode data in HS so that
3844 * all scenarios are satisfied.
3845 */
3846static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
3847 int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
3848{
3849 int transition;
3850
3851 /*
3852 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
3853 * time of data lanes only, if it isn't set, we need to consider HS
3854 * transition time of both data and clock lanes. HS transition time
3855 * of Scenario 3 is considered.
3856 */
3857 if (ddr_alwon) {
3858 transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
3859 } else {
3860 int trans1, trans2;
3861 trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
3862 trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
3863 enter_hs + 1;
3864 transition = max(trans1, trans2);
3865 }
3866
3867 return blank > transition ? blank - transition : 0;
3868}
3869
3870/*
3871 * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
3872 * results in maximum transition time for data lanes to enter and exit LP mode.
3873 * Hence, this is the scenario where the least amount of command mode data can
3874 * be interleaved. We program the minimum amount of bytes that can be
3875 * interleaved in LP so that all scenarios are satisfied.
3876 */
3877static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
3878 int lp_clk_div, int tdsi_fclk)
3879{
3880 int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */
3881 int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */
3882 int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */
3883 int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */
3884 int lp_inter; /* cmd mode data that can be interleaved, in bytes */
3885
3886 /* maximum LP transition time according to Scenario 1 */
3887 trans_lp = exit_hs + max(enter_hs, 2) + 1;
3888
3889 /* CLKIN4DDR = 16 * TXBYTECLKHS */
3890 tlp_avail = thsbyte_clk * (blank - trans_lp);
3891
3892 ttxclkesc = tdsi_fclk * lp_clk_div;
3893
3894 lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
3895 26) / 16;
3896
3897 return max(lp_inter, 0);
3898}
3899
3900static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3901{
3902 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3903 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3904 int blanking_mode;
3905 int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
3906 int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
3907 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3908 int tclk_trail, ths_exit, exiths_clk;
3909 bool ddr_alwon;
3910 struct omap_video_timings *timings = &dsi->timings;
3911 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3912 int ndl = dsi->num_lanes_used - 1;
3913 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
3914 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
3915 int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
3916 int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
3917 int bl_interleave_hs = 0, bl_interleave_lp = 0;
3918 u32 r;
3919
3920 r = dsi_read_reg(dsidev, DSI_CTRL);
3921 blanking_mode = FLD_GET(r, 20, 20);
3922 hfp_blanking_mode = FLD_GET(r, 21, 21);
3923 hbp_blanking_mode = FLD_GET(r, 22, 22);
3924 hsa_blanking_mode = FLD_GET(r, 23, 23);
3925
3926 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
3927 hbp = FLD_GET(r, 11, 0);
3928 hfp = FLD_GET(r, 23, 12);
3929 hsa = FLD_GET(r, 31, 24);
3930
3931 r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
3932 ddr_clk_post = FLD_GET(r, 7, 0);
3933 ddr_clk_pre = FLD_GET(r, 15, 8);
3934
3935 r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
3936 exit_hs_mode_lat = FLD_GET(r, 15, 0);
3937 enter_hs_mode_lat = FLD_GET(r, 31, 16);
3938
3939 r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
3940 lp_clk_div = FLD_GET(r, 12, 0);
3941 ddr_alwon = FLD_GET(r, 13, 13);
3942
3943 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
3944 ths_exit = FLD_GET(r, 7, 0);
3945
3946 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3947 tclk_trail = FLD_GET(r, 15, 8);
3948
3949 exiths_clk = ths_exit + tclk_trail;
3950
3951 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
3952 bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
3953
3954 if (!hsa_blanking_mode) {
3955 hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
3956 enter_hs_mode_lat, exit_hs_mode_lat,
3957 exiths_clk, ddr_clk_pre, ddr_clk_post);
3958 hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
3959 enter_hs_mode_lat, exit_hs_mode_lat,
3960 lp_clk_div, dsi_fclk_hsdiv);
3961 }
3962
3963 if (!hfp_blanking_mode) {
3964 hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
3965 enter_hs_mode_lat, exit_hs_mode_lat,
3966 exiths_clk, ddr_clk_pre, ddr_clk_post);
3967 hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
3968 enter_hs_mode_lat, exit_hs_mode_lat,
3969 lp_clk_div, dsi_fclk_hsdiv);
3970 }
3971
3972 if (!hbp_blanking_mode) {
3973 hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
3974 enter_hs_mode_lat, exit_hs_mode_lat,
3975 exiths_clk, ddr_clk_pre, ddr_clk_post);
3976
3977 hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
3978 enter_hs_mode_lat, exit_hs_mode_lat,
3979 lp_clk_div, dsi_fclk_hsdiv);
3980 }
3981
3982 if (!blanking_mode) {
3983 bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
3984 enter_hs_mode_lat, exit_hs_mode_lat,
3985 exiths_clk, ddr_clk_pre, ddr_clk_post);
3986
3987 bl_interleave_lp = dsi_compute_interleave_lp(bllp,
3988 enter_hs_mode_lat, exit_hs_mode_lat,
3989 lp_clk_div, dsi_fclk_hsdiv);
3990 }
3991
3992 DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3993 hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
3994 bl_interleave_hs);
3995
3996 DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3997 hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
3998 bl_interleave_lp);
3999
4000 r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
4001 r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
4002 r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
4003 r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
4004 dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
4005
4006 r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
4007 r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
4008 r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
4009 r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
4010 dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
4011
4012 r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
4013 r = FLD_MOD(r, bl_interleave_hs, 31, 15);
4014 r = FLD_MOD(r, bl_interleave_lp, 16, 0);
4015 dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
4016}
4017
4018static int dsi_proto_config(struct omap_dss_device *dssdev) 3511static int dsi_proto_config(struct omap_dss_device *dssdev)
4019{ 3512{
4020 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3513 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4021 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4022 u32 r; 3514 u32 r;
4023 int buswidth = 0; 3515 int buswidth = 0;
4024 3516
@@ -4038,7 +3530,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
4038 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true); 3530 dsi_set_lp_rx_timeout(dsidev, 0x1fff, true, true);
4039 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true); 3531 dsi_set_hs_tx_timeout(dsidev, 0x1fff, true, true);
4040 3532
4041 switch (dsi_get_pixel_size(dsi->pix_fmt)) { 3533 switch (dssdev->ctrl.pixel_size) {
4042 case 16: 3534 case 16:
4043 buswidth = 0; 3535 buswidth = 0;
4044 break; 3536 break;
@@ -4050,7 +3542,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
4050 break; 3542 break;
4051 default: 3543 default:
4052 BUG(); 3544 BUG();
4053 return -EINVAL;
4054 } 3545 }
4055 3546
4056 r = dsi_read_reg(dsidev, DSI_CTRL); 3547 r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -4060,6 +3551,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
4060 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/ 3551 r = FLD_MOD(r, 1, 4, 4); /* VP_CLK_RATIO, always 1, see errata*/
4061 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */ 3552 r = FLD_MOD(r, buswidth, 7, 6); /* VP_DATA_BUS_WIDTH */
4062 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */ 3553 r = FLD_MOD(r, 0, 8, 8); /* VP_CLK_POL */
3554 r = FLD_MOD(r, 2, 13, 12); /* LINE_BUFFER, 2 lines */
4063 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */ 3555 r = FLD_MOD(r, 1, 14, 14); /* TRIGGER_RESET_MODE */
4064 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */ 3556 r = FLD_MOD(r, 1, 19, 19); /* EOT_ENABLE */
4065 if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) { 3557 if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
@@ -4070,14 +3562,6 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
4070 3562
4071 dsi_write_reg(dsidev, DSI_CTRL, r); 3563 dsi_write_reg(dsidev, DSI_CTRL, r);
4072 3564
4073 dsi_config_vp_num_line_buffers(dsidev);
4074
4075 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4076 dsi_config_vp_sync_events(dsidev);
4077 dsi_config_blanking_modes(dsidev);
4078 dsi_config_cmd_mode_interleaving(dssdev);
4079 }
4080
4081 dsi_vc_initial_config(dsidev, 0); 3565 dsi_vc_initial_config(dsidev, 0);
4082 dsi_vc_initial_config(dsidev, 1); 3566 dsi_vc_initial_config(dsidev, 1);
4083 dsi_vc_initial_config(dsidev, 2); 3567 dsi_vc_initial_config(dsidev, 2);
@@ -4086,9 +3570,9 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
4086 return 0; 3570 return 0;
4087} 3571}
4088 3572
4089static void dsi_proto_timings(struct platform_device *dsidev) 3573static void dsi_proto_timings(struct omap_dss_device *dssdev)
4090{ 3574{
4091 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3575 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4092 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 3576 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
4093 unsigned tclk_pre, tclk_post; 3577 unsigned tclk_pre, tclk_post;
4094 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; 3578 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
@@ -4096,7 +3580,6 @@ static void dsi_proto_timings(struct platform_device *dsidev)
4096 unsigned ddr_clk_pre, ddr_clk_post; 3580 unsigned ddr_clk_pre, ddr_clk_post;
4097 unsigned enter_hs_mode_lat, exit_hs_mode_lat; 3581 unsigned enter_hs_mode_lat, exit_hs_mode_lat;
4098 unsigned ths_eot; 3582 unsigned ths_eot;
4099 int ndl = dsi->num_lanes_used - 1;
4100 u32 r; 3583 u32 r;
4101 3584
4102 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); 3585 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -4107,7 +3590,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
4107 ths_exit = FLD_GET(r, 7, 0); 3590 ths_exit = FLD_GET(r, 7, 0);
4108 3591
4109 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1); 3592 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
4110 tlpx = FLD_GET(r, 20, 16) * 2; 3593 tlpx = FLD_GET(r, 22, 16) * 2;
4111 tclk_trail = FLD_GET(r, 15, 8); 3594 tclk_trail = FLD_GET(r, 15, 8);
4112 tclk_zero = FLD_GET(r, 7, 0); 3595 tclk_zero = FLD_GET(r, 7, 0);
4113 3596
@@ -4119,7 +3602,7 @@ static void dsi_proto_timings(struct platform_device *dsidev)
4119 /* min 60ns + 52*UI */ 3602 /* min 60ns + 52*UI */
4120 tclk_post = ns2ddr(dsidev, 60) + 26; 3603 tclk_post = ns2ddr(dsidev, 60) + 26;
4121 3604
4122 ths_eot = DIV_ROUND_UP(4, ndl); 3605 ths_eot = DIV_ROUND_UP(4, dsi_get_num_data_lanes_dssdev(dssdev));
4123 3606
4124 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare, 3607 ddr_clk_pre = DIV_ROUND_UP(tclk_pre + tlpx + tclk_zero + tclk_prepare,
4125 4); 3608 4);
@@ -4149,273 +3632,168 @@ static void dsi_proto_timings(struct platform_device *dsidev)
4149 3632
4150 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n", 3633 DSSDBG("enter_hs_mode_lat %u, exit_hs_mode_lat %u\n",
4151 enter_hs_mode_lat, exit_hs_mode_lat); 3634 enter_hs_mode_lat, exit_hs_mode_lat);
4152
4153 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4154 /* TODO: Implement a video mode check_timings function */
4155 int hsa = dsi->vm_timings.hsa;
4156 int hfp = dsi->vm_timings.hfp;
4157 int hbp = dsi->vm_timings.hbp;
4158 int vsa = dsi->vm_timings.vsa;
4159 int vfp = dsi->vm_timings.vfp;
4160 int vbp = dsi->vm_timings.vbp;
4161 int window_sync = dsi->vm_timings.window_sync;
4162 bool hsync_end = dsi->vm_timings.vp_hsync_end;
4163 struct omap_video_timings *timings = &dsi->timings;
4164 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
4165 int tl, t_he, width_bytes;
4166
4167 t_he = hsync_end ?
4168 ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
4169
4170 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
4171
4172 /* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
4173 tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
4174 DIV_ROUND_UP(width_bytes + 6, ndl) + hbp;
4175
4176 DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
4177 hfp, hsync_end ? hsa : 0, tl);
4178 DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
4179 vsa, timings->y_res);
4180
4181 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
4182 r = FLD_MOD(r, hbp, 11, 0); /* HBP */
4183 r = FLD_MOD(r, hfp, 23, 12); /* HFP */
4184 r = FLD_MOD(r, hsync_end ? hsa : 0, 31, 24); /* HSA */
4185 dsi_write_reg(dsidev, DSI_VM_TIMING1, r);
4186
4187 r = dsi_read_reg(dsidev, DSI_VM_TIMING2);
4188 r = FLD_MOD(r, vbp, 7, 0); /* VBP */
4189 r = FLD_MOD(r, vfp, 15, 8); /* VFP */
4190 r = FLD_MOD(r, vsa, 23, 16); /* VSA */
4191 r = FLD_MOD(r, window_sync, 27, 24); /* WINDOW_SYNC */
4192 dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
4193
4194 r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
4195 r = FLD_MOD(r, timings->y_res, 14, 0); /* VACT */
4196 r = FLD_MOD(r, tl, 31, 16); /* TL */
4197 dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
4198 }
4199} 3635}
4200 3636
4201int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
4202 const struct omap_dsi_pin_config *pin_cfg)
4203{
4204 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4205 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4206 int num_pins;
4207 const int *pins;
4208 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
4209 int num_lanes;
4210 int i;
4211
4212 static const enum dsi_lane_function functions[] = {
4213 DSI_LANE_CLK,
4214 DSI_LANE_DATA1,
4215 DSI_LANE_DATA2,
4216 DSI_LANE_DATA3,
4217 DSI_LANE_DATA4,
4218 };
4219
4220 num_pins = pin_cfg->num_pins;
4221 pins = pin_cfg->pins;
4222
4223 if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2
4224 || num_pins % 2 != 0)
4225 return -EINVAL;
4226
4227 for (i = 0; i < DSI_MAX_NR_LANES; ++i)
4228 lanes[i].function = DSI_LANE_UNUSED;
4229
4230 num_lanes = 0;
4231
4232 for (i = 0; i < num_pins; i += 2) {
4233 u8 lane, pol;
4234 int dx, dy;
4235
4236 dx = pins[i];
4237 dy = pins[i + 1];
4238
4239 if (dx < 0 || dx >= dsi->num_lanes_supported * 2)
4240 return -EINVAL;
4241 3637
4242 if (dy < 0 || dy >= dsi->num_lanes_supported * 2) 3638#define DSI_DECL_VARS \
4243 return -EINVAL; 3639 int __dsi_cb = 0; u32 __dsi_cv = 0;
4244 3640
4245 if (dx & 1) { 3641#define DSI_FLUSH(dsidev, ch) \
4246 if (dy != dx - 1) 3642 if (__dsi_cb > 0) { \
4247 return -EINVAL; 3643 /*DSSDBG("sending long packet %#010x\n", __dsi_cv);*/ \
4248 pol = 1; 3644 dsi_write_reg(dsidev, DSI_VC_LONG_PACKET_PAYLOAD(ch), __dsi_cv); \
4249 } else { 3645 __dsi_cb = __dsi_cv = 0; \
4250 if (dy != dx + 1)
4251 return -EINVAL;
4252 pol = 0;
4253 }
4254
4255 lane = dx / 2;
4256
4257 lanes[lane].function = functions[i / 2];
4258 lanes[lane].polarity = pol;
4259 num_lanes++;
4260 } 3646 }
4261 3647
4262 memcpy(dsi->lanes, lanes, sizeof(dsi->lanes)); 3648#define DSI_PUSH(dsidev, ch, data) \
4263 dsi->num_lanes_used = num_lanes; 3649 do { \
4264 3650 __dsi_cv |= (data) << (__dsi_cb * 8); \
4265 return 0; 3651 /*DSSDBG("cv = %#010x, cb = %d\n", __dsi_cv, __dsi_cb);*/ \
4266} 3652 if (++__dsi_cb > 3) \
4267EXPORT_SYMBOL(omapdss_dsi_configure_pins); 3653 DSI_FLUSH(dsidev, ch); \
3654 } while (0)
4268 3655
4269int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, 3656static int dsi_update_screen_l4(struct omap_dss_device *dssdev,
4270 unsigned long ddr_clk, unsigned long lp_clk) 3657 int x, int y, int w, int h)
4271{ 3658{
3659 /* Note: supports only 24bit colors in 32bit container */
4272 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3660 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4273 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3661 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4274 struct dsi_clock_info cinfo; 3662 int first = 1;
4275 struct dispc_clock_info dispc_cinfo; 3663 int fifo_stalls = 0;
4276 unsigned lp_clk_div; 3664 int max_dsi_packet_size;
4277 unsigned long dsi_fclk; 3665 int max_data_per_packet;
4278 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3666 int max_pixels_per_packet;
4279 unsigned long pck; 3667 int pixels_left;
4280 int r; 3668 int bytespp = dssdev->ctrl.pixel_size / 8;
3669 int scr_width;
3670 u32 __iomem *data;
3671 int start_offset;
3672 int horiz_inc;
3673 int current_x;
3674 struct omap_overlay *ovl;
3675
3676 debug_irq = 0;
3677
3678 DSSDBG("dsi_update_screen_l4 (%d,%d %dx%d)\n",
3679 x, y, w, h);
3680
3681 ovl = dssdev->manager->overlays[0];
3682
3683 if (ovl->info.color_mode != OMAP_DSS_COLOR_RGB24U)
3684 return -EINVAL;
4281 3685
4282 DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk); 3686 if (dssdev->ctrl.pixel_size != 24)
3687 return -EINVAL;
4283 3688
4284 mutex_lock(&dsi->lock); 3689 scr_width = ovl->info.screen_width;
3690 data = ovl->info.vaddr;
4285 3691
4286 /* Calculate PLL output clock */ 3692 start_offset = scr_width * y + x;
4287 r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo); 3693 horiz_inc = scr_width - w;
4288 if (r) 3694 current_x = x;
4289 goto err;
4290 3695
4291 /* Calculate PLL's DSI clock */ 3696 /* We need header(4) + DCSCMD(1) + pixels(numpix*bytespp) bytes
4292 dsi_pll_calc_dsi_fck(dsidev, &cinfo); 3697 * in fifo */
4293 3698
4294 /* Calculate PLL's DISPC clock and pck & lck divs */ 3699 /* When using CPU, max long packet size is TX buffer size */
4295 pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; 3700 max_dsi_packet_size = dsi->vc[0].fifo_size * 32 * 4;
4296 DSSDBG("finding dispc dividers for pck %lu\n", pck);
4297 r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo);
4298 if (r)
4299 goto err;
4300 3701
4301 /* Calculate LP clock */ 3702 /* we seem to get better perf if we divide the tx fifo to half,
4302 dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; 3703 and while the other half is being sent, we fill the other half
4303 lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); 3704 max_dsi_packet_size /= 2; */
4304 3705
4305 dssdev->clocks.dsi.regn = cinfo.regn; 3706 max_data_per_packet = max_dsi_packet_size - 4 - 1;
4306 dssdev->clocks.dsi.regm = cinfo.regm;
4307 dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc;
4308 dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi;
4309 3707
4310 dssdev->clocks.dsi.lp_clk_div = lp_clk_div; 3708 max_pixels_per_packet = max_data_per_packet / bytespp;
4311 3709
4312 dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div; 3710 DSSDBG("max_pixels_per_packet %d\n", max_pixels_per_packet);
4313 dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div;
4314 3711
4315 dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; 3712 pixels_left = w * h;
4316 3713
4317 dssdev->clocks.dispc.channel.lcd_clk_src = 3714 DSSDBG("total pixels %d\n", pixels_left);
4318 dsi->module_id == 0 ?
4319 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
4320 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
4321 3715
4322 dssdev->clocks.dsi.dsi_fclk_src = 3716 data += start_offset;
4323 dsi->module_id == 0 ?
4324 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
4325 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI;
4326 3717
4327 mutex_unlock(&dsi->lock); 3718 while (pixels_left > 0) {
4328 return 0; 3719 /* 0x2c = write_memory_start */
4329err: 3720 /* 0x3c = write_memory_continue */
4330 mutex_unlock(&dsi->lock); 3721 u8 dcs_cmd = first ? 0x2c : 0x3c;
4331 return r; 3722 int pixels;
4332} 3723 DSI_DECL_VARS;
4333EXPORT_SYMBOL(omapdss_dsi_set_clocks); 3724 first = 0;
4334 3725
4335int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 3726#if 1
4336{ 3727 /* using fifo not empty */
4337 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3728 /* TX_FIFO_NOT_EMPTY */
4338 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3729 while (FLD_GET(dsi_read_reg(dsidev, DSI_VC_CTRL(0)), 5, 5)) {
4339 struct omap_overlay_manager *mgr = dssdev->output->manager; 3730 fifo_stalls++;
4340 int bpp = dsi_get_pixel_size(dsi->pix_fmt); 3731 if (fifo_stalls > 0xfffff) {
4341 u8 data_type; 3732 DSSERR("fifo stalls overflow, pixels left %d\n",
4342 u16 word_count; 3733 pixels_left);
4343 int r; 3734 dsi_if_enable(dsidev, 0);
4344 3735 return -EIO;
4345 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 3736 }
4346 switch (dsi->pix_fmt) { 3737 udelay(1);
4347 case OMAP_DSS_DSI_FMT_RGB888: 3738 }
4348 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 3739#elif 1
4349 break; 3740 /* using fifo emptiness */
4350 case OMAP_DSS_DSI_FMT_RGB666: 3741 while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS, 7, 0)+1)*4 <
4351 data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 3742 max_dsi_packet_size) {
4352 break; 3743 fifo_stalls++;
4353 case OMAP_DSS_DSI_FMT_RGB666_PACKED: 3744 if (fifo_stalls > 0xfffff) {
4354 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; 3745 DSSERR("fifo stalls overflow, pixels left %d\n",
4355 break; 3746 pixels_left);
4356 case OMAP_DSS_DSI_FMT_RGB565: 3747 dsi_if_enable(dsidev, 0);
4357 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; 3748 return -EIO;
4358 break; 3749 }
4359 default: 3750 }
4360 BUG(); 3751#else
4361 return -EINVAL; 3752 while ((REG_GET(dsidev, DSI_TX_FIFO_VC_EMPTINESS,
4362 }; 3753 7, 0) + 1) * 4 == 0) {
3754 fifo_stalls++;
3755 if (fifo_stalls > 0xfffff) {
3756 DSSERR("fifo stalls overflow, pixels left %d\n",
3757 pixels_left);
3758 dsi_if_enable(dsidev, 0);
3759 return -EIO;
3760 }
3761 }
3762#endif
3763 pixels = min(max_pixels_per_packet, pixels_left);
4363 3764
4364 dsi_if_enable(dsidev, false); 3765 pixels_left -= pixels;
4365 dsi_vc_enable(dsidev, channel, false);
4366 3766
4367 /* MODE, 1 = video mode */ 3767 dsi_vc_write_long_header(dsidev, 0, DSI_DT_DCS_LONG_WRITE,
4368 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 3768 1 + pixels * bytespp, 0);
4369 3769
4370 word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8); 3770 DSI_PUSH(dsidev, 0, dcs_cmd);
4371 3771
4372 dsi_vc_write_long_header(dsidev, channel, data_type, 3772 while (pixels-- > 0) {
4373 word_count, 0); 3773 u32 pix = __raw_readl(data++);
4374 3774
4375 dsi_vc_enable(dsidev, channel, true); 3775 DSI_PUSH(dsidev, 0, (pix >> 16) & 0xff);
4376 dsi_if_enable(dsidev, true); 3776 DSI_PUSH(dsidev, 0, (pix >> 8) & 0xff);
4377 } 3777 DSI_PUSH(dsidev, 0, (pix >> 0) & 0xff);
4378 3778
4379 r = dss_mgr_enable(mgr); 3779 current_x++;
4380 if (r) { 3780 if (current_x == x+w) {
4381 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { 3781 current_x = x;
4382 dsi_if_enable(dsidev, false); 3782 data += horiz_inc;
4383 dsi_vc_enable(dsidev, channel, false); 3783 }
4384 } 3784 }
4385 3785
4386 return r; 3786 DSI_FLUSH(dsidev, 0);
4387 } 3787 }
4388 3788
4389 return 0; 3789 return 0;
4390} 3790}
4391EXPORT_SYMBOL(dsi_enable_video_output);
4392 3791
4393void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) 3792static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
3793 u16 x, u16 y, u16 w, u16 h)
4394{ 3794{
4395 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3795 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4396 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3796 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4397 struct omap_overlay_manager *mgr = dssdev->output->manager;
4398
4399 if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
4400 dsi_if_enable(dsidev, false);
4401 dsi_vc_enable(dsidev, channel, false);
4402
4403 /* MODE, 0 = command mode */
4404 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
4405
4406 dsi_vc_enable(dsidev, channel, true);
4407 dsi_if_enable(dsidev, true);
4408 }
4409
4410 dss_mgr_disable(mgr);
4411}
4412EXPORT_SYMBOL(dsi_disable_video_output);
4413
4414static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4415{
4416 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4417 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4418 struct omap_overlay_manager *mgr = dssdev->output->manager;
4419 unsigned bytespp; 3797 unsigned bytespp;
4420 unsigned bytespl; 3798 unsigned bytespl;
4421 unsigned bytespf; 3799 unsigned bytespf;
@@ -4426,14 +3804,13 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4426 int r; 3804 int r;
4427 const unsigned channel = dsi->update_channel; 3805 const unsigned channel = dsi->update_channel;
4428 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 3806 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
4429 u16 w = dsi->timings.x_res;
4430 u16 h = dsi->timings.y_res;
4431 3807
4432 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); 3808 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
3809 x, y, w, h);
4433 3810
4434 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); 3811 dsi_vc_config_vp(dsidev, channel);
4435 3812
4436 bytespp = dsi_get_pixel_size(dsi->pix_fmt) / 8; 3813 bytespp = dssdev->ctrl.pixel_size / 8;
4437 bytespl = w * bytespp; 3814 bytespl = w * bytespp;
4438 bytespf = bytespl * h; 3815 bytespf = bytespl * h;
4439 3816
@@ -4454,7 +3831,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4454 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */ 3831 l = FLD_VAL(total_len, 23, 0); /* TE_SIZE */
4455 dsi_write_reg(dsidev, DSI_VC_TE(channel), l); 3832 dsi_write_reg(dsidev, DSI_VC_TE(channel), l);
4456 3833
4457 dsi_vc_write_long_header(dsidev, channel, MIPI_DSI_DCS_LONG_WRITE, 3834 dsi_vc_write_long_header(dsidev, channel, DSI_DT_DCS_LONG_WRITE,
4458 packet_len, 0); 3835 packet_len, 0);
4459 3836
4460 if (dsi->te_enabled) 3837 if (dsi->te_enabled)
@@ -4477,9 +3854,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev)
4477 msecs_to_jiffies(250)); 3854 msecs_to_jiffies(250));
4478 BUG_ON(r == 0); 3855 BUG_ON(r == 0);
4479 3856
4480 dss_mgr_set_timings(mgr, &dsi->timings); 3857 dss_start_update(dssdev);
4481
4482 dss_mgr_start_update(mgr);
4483 3858
4484 if (dsi->te_enabled) { 3859 if (dsi->te_enabled) {
4485 /* disable LP_RX_TO, so that we can receive TE. Time to wait 3860 /* disable LP_RX_TO, so that we can receive TE. Time to wait
@@ -4535,9 +3910,10 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
4535 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT); 3910 dsi_handle_framedone(dsi->pdev, -ETIMEDOUT);
4536} 3911}
4537 3912
4538static void dsi_framedone_irq_callback(void *data) 3913static void dsi_framedone_irq_callback(void *data, u32 mask)
4539{ 3914{
4540 struct platform_device *dsidev = (struct platform_device *) data; 3915 struct omap_dss_device *dssdev = (struct omap_dss_device *) data;
3916 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4541 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3917 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4542 3918
4543 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and 3919 /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
@@ -4545,135 +3921,144 @@ static void dsi_framedone_irq_callback(void *data)
4545 * and is sending the data. 3921 * and is sending the data.
4546 */ 3922 */
4547 3923
4548 cancel_delayed_work(&dsi->framedone_timeout_work); 3924 __cancel_delayed_work(&dsi->framedone_timeout_work);
4549 3925
4550 dsi_handle_framedone(dsidev, 0); 3926 dsi_handle_framedone(dsidev, 0);
3927
3928#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3929 dispc_fake_vsync_irq();
3930#endif
4551} 3931}
4552 3932
4553int omap_dsi_update(struct omap_dss_device *dssdev, int channel, 3933int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
4554 void (*callback)(int, void *), void *data) 3934 u16 *x, u16 *y, u16 *w, u16 *h,
3935 bool enlarge_update_area)
4555{ 3936{
4556 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3937 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4557 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4558 u16 dw, dh; 3938 u16 dw, dh;
4559 3939
4560 dsi_perf_mark_setup(dsidev); 3940 dssdev->driver->get_resolution(dssdev, &dw, &dh);
4561 3941
4562 dsi->update_channel = channel; 3942 if (*x > dw || *y > dh)
3943 return -EINVAL;
4563 3944
4564 dsi->framedone_callback = callback; 3945 if (*x + *w > dw)
4565 dsi->framedone_data = data; 3946 return -EINVAL;
4566 3947
4567 dw = dsi->timings.x_res; 3948 if (*y + *h > dh)
4568 dh = dsi->timings.y_res; 3949 return -EINVAL;
4569 3950
4570#ifdef DEBUG 3951 if (*w == 1)
4571 dsi->update_bytes = dw * dh * 3952 return -EINVAL;
4572 dsi_get_pixel_size(dsi->pix_fmt) / 8; 3953
4573#endif 3954 if (*w == 0 || *h == 0)
4574 dsi_update_screen_dispc(dssdev); 3955 return -EINVAL;
3956
3957 dsi_perf_mark_setup(dsidev);
3958
3959 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
3960 dss_setup_partial_planes(dssdev, x, y, w, h,
3961 enlarge_update_area);
3962 dispc_set_lcd_size(dssdev->manager->id, *w, *h);
3963 }
4575 3964
4576 return 0; 3965 return 0;
4577} 3966}
4578EXPORT_SYMBOL(omap_dsi_update); 3967EXPORT_SYMBOL(omap_dsi_prepare_update);
4579
4580/* Display funcs */
4581 3968
4582static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) 3969int omap_dsi_update(struct omap_dss_device *dssdev,
3970 int channel,
3971 u16 x, u16 y, u16 w, u16 h,
3972 void (*callback)(int, void *), void *data)
4583{ 3973{
4584 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3974 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4585 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3975 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4586 struct dispc_clock_info dispc_cinfo;
4587 int r;
4588 unsigned long long fck;
4589 3976
4590 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3977 dsi->update_channel = channel;
4591 3978
4592 dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; 3979 /* OMAP DSS cannot send updates of odd widths.
4593 dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; 3980 * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
3981 * here to make sure we catch erroneous updates. Otherwise we'll only
3982 * see rather obscure HW error happening, as DSS halts. */
3983 BUG_ON(x % 2 == 1);
4594 3984
4595 r = dispc_calc_clock_rates(fck, &dispc_cinfo); 3985 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
4596 if (r) { 3986 dsi->framedone_callback = callback;
4597 DSSERR("Failed to calc dispc clocks\n"); 3987 dsi->framedone_data = data;
4598 return r; 3988
4599 } 3989 dsi->update_region.x = x;
3990 dsi->update_region.y = y;
3991 dsi->update_region.w = w;
3992 dsi->update_region.h = h;
3993 dsi->update_region.device = dssdev;
3994
3995 dsi_update_screen_dispc(dssdev, x, y, w, h);
3996 } else {
3997 int r;
4600 3998
4601 dsi->mgr_config.clock_info = dispc_cinfo; 3999 r = dsi_update_screen_l4(dssdev, x, y, w, h);
4000 if (r)
4001 return r;
4002
4003 dsi_perf_show(dsidev, "L4");
4004 callback(0, data);
4005 }
4602 4006
4603 return 0; 4007 return 0;
4604} 4008}
4009EXPORT_SYMBOL(omap_dsi_update);
4010
4011/* Display funcs */
4605 4012
4606static int dsi_display_init_dispc(struct omap_dss_device *dssdev) 4013static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4607{ 4014{
4608 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4609 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4610 struct omap_overlay_manager *mgr = dssdev->output->manager;
4611 int r; 4015 int r;
4016 u32 irq;
4612 4017
4613 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { 4018 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4614 dsi->timings.hsw = 1; 4019 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4615 dsi->timings.hfp = 1;
4616 dsi->timings.hbp = 1;
4617 dsi->timings.vsw = 1;
4618 dsi->timings.vfp = 0;
4619 dsi->timings.vbp = 0;
4620
4621 r = dss_mgr_register_framedone_handler(mgr,
4622 dsi_framedone_irq_callback, dsidev);
4623 if (r) {
4624 DSSERR("can't register FRAMEDONE handler\n");
4625 goto err;
4626 }
4627 4020
4628 dsi->mgr_config.stallmode = true; 4021 r = omap_dispc_register_isr(dsi_framedone_irq_callback, (void *) dssdev,
4629 dsi->mgr_config.fifohandcheck = true; 4022 irq);
4630 } else { 4023 if (r) {
4631 dsi->mgr_config.stallmode = false; 4024 DSSERR("can't get FRAMEDONE irq\n");
4632 dsi->mgr_config.fifohandcheck = false; 4025 return r;
4633 } 4026 }
4634 4027
4635 /* 4028 dispc_set_lcd_display_type(dssdev->manager->id,
4636 * override interlace, logic level and edge related parameters in 4029 OMAP_DSS_LCD_DISPLAY_TFT);
4637 * omap_video_timings with default values
4638 */
4639 dsi->timings.interlace = false;
4640 dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4641 dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
4642 dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
4643 dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
4644 dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
4645 4030
4646 dss_mgr_set_timings(mgr, &dsi->timings); 4031 dispc_set_parallel_interface_mode(dssdev->manager->id,
4032 OMAP_DSS_PARALLELMODE_DSI);
4033 dispc_enable_fifohandcheck(dssdev->manager->id, 1);
4647 4034
4648 r = dsi_configure_dispc_clocks(dssdev); 4035 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
4649 if (r)
4650 goto err1;
4651 4036
4652 dsi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 4037 {
4653 dsi->mgr_config.video_port_width = 4038 struct omap_video_timings timings = {
4654 dsi_get_pixel_size(dsi->pix_fmt); 4039 .hsw = 1,
4655 dsi->mgr_config.lcden_sig_polarity = 0; 4040 .hfp = 1,
4041 .hbp = 1,
4042 .vsw = 1,
4043 .vfp = 0,
4044 .vbp = 0,
4045 };
4656 4046
4657 dss_mgr_set_lcd_config(mgr, &dsi->mgr_config); 4047 dispc_set_lcd_timings(dssdev->manager->id, &timings);
4048 }
4658 4049
4659 return 0; 4050 return 0;
4660err1:
4661 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE)
4662 dss_mgr_unregister_framedone_handler(mgr,
4663 dsi_framedone_irq_callback, dsidev);
4664err:
4665 return r;
4666} 4051}
4667 4052
4668static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) 4053static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev)
4669{ 4054{
4670 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4055 u32 irq;
4671 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4056
4672 struct omap_overlay_manager *mgr = dssdev->output->manager; 4057 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4058 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4673 4059
4674 if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) 4060 omap_dispc_unregister_isr(dsi_framedone_irq_callback, (void *) dssdev,
4675 dss_mgr_unregister_framedone_handler(mgr, 4061 irq);
4676 dsi_framedone_irq_callback, dsidev);
4677} 4062}
4678 4063
4679static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) 4064static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
@@ -4682,11 +4067,13 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
4682 struct dsi_clock_info cinfo; 4067 struct dsi_clock_info cinfo;
4683 int r; 4068 int r;
4684 4069
4070 /* we always use DSS_CLK_SYSCK as input clock */
4071 cinfo.use_sys_clk = true;
4685 cinfo.regn = dssdev->clocks.dsi.regn; 4072 cinfo.regn = dssdev->clocks.dsi.regn;
4686 cinfo.regm = dssdev->clocks.dsi.regm; 4073 cinfo.regm = dssdev->clocks.dsi.regm;
4687 cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; 4074 cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
4688 cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; 4075 cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
4689 r = dsi_calc_clock_rates(dsidev, &cinfo); 4076 r = dsi_calc_clock_rates(dssdev, &cinfo);
4690 if (r) { 4077 if (r) {
4691 DSSERR("Failed to calc dsi clocks\n"); 4078 DSSERR("Failed to calc dsi clocks\n");
4692 return r; 4079 return r;
@@ -4701,11 +4088,37 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
4701 return 0; 4088 return 0;
4702} 4089}
4703 4090
4091static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
4092{
4093 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4094 struct dispc_clock_info dispc_cinfo;
4095 int r;
4096 unsigned long long fck;
4097
4098 fck = dsi_get_pll_hsdiv_dispc_rate(dsidev);
4099
4100 dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div;
4101 dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div;
4102
4103 r = dispc_calc_clock_rates(fck, &dispc_cinfo);
4104 if (r) {
4105 DSSERR("Failed to calc dispc clocks\n");
4106 return r;
4107 }
4108
4109 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
4110 if (r) {
4111 DSSERR("Failed to set dispc clocks\n");
4112 return r;
4113 }
4114
4115 return 0;
4116}
4117
4704static int dsi_display_init_dsi(struct omap_dss_device *dssdev) 4118static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4705{ 4119{
4706 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4120 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4707 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4121 int dsi_module = dsi_get_dsidev_id(dsidev);
4708 struct omap_overlay_manager *mgr = dssdev->output->manager;
4709 int r; 4122 int r;
4710 4123
4711 r = dsi_pll_init(dsidev, true, true); 4124 r = dsi_pll_init(dsidev, true, true);
@@ -4716,19 +4129,24 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4716 if (r) 4129 if (r)
4717 goto err1; 4130 goto err1;
4718 4131
4719 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); 4132 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
4720 dss_select_lcd_clk_source(mgr->id, 4133 dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src);
4134 dss_select_lcd_clk_source(dssdev->manager->id,
4721 dssdev->clocks.dispc.channel.lcd_clk_src); 4135 dssdev->clocks.dispc.channel.lcd_clk_src);
4722 4136
4723 DSSDBG("PLL OK\n"); 4137 DSSDBG("PLL OK\n");
4724 4138
4725 r = dsi_cio_init(dsidev); 4139 r = dsi_configure_dispc_clocks(dssdev);
4140 if (r)
4141 goto err2;
4142
4143 r = dsi_cio_init(dssdev);
4726 if (r) 4144 if (r)
4727 goto err2; 4145 goto err2;
4728 4146
4729 _dsi_print_reset_status(dsidev); 4147 _dsi_print_reset_status(dsidev);
4730 4148
4731 dsi_proto_timings(dsidev); 4149 dsi_proto_timings(dssdev);
4732 dsi_set_lp_clk_divisor(dssdev); 4150 dsi_set_lp_clk_divisor(dssdev);
4733 4151
4734 if (1) 4152 if (1)
@@ -4750,9 +4168,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4750err3: 4168err3:
4751 dsi_cio_uninit(dsidev); 4169 dsi_cio_uninit(dsidev);
4752err2: 4170err2:
4753 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4171 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4754 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); 4172 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
4755
4756err1: 4173err1:
4757 dsi_pll_uninit(dsidev, true); 4174 dsi_pll_uninit(dsidev, true);
4758err0: 4175err0:
@@ -4764,7 +4181,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4764{ 4181{
4765 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4182 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4766 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4183 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4767 struct omap_overlay_manager *mgr = dssdev->output->manager; 4184 int dsi_module = dsi_get_dsidev_id(dsidev);
4768 4185
4769 if (enter_ulps && !dsi->ulps_enabled) 4186 if (enter_ulps && !dsi->ulps_enabled)
4770 dsi_enter_ulps(dsidev); 4187 dsi_enter_ulps(dsidev);
@@ -4776,8 +4193,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4776 dsi_vc_enable(dsidev, 2, 0); 4193 dsi_vc_enable(dsidev, 2, 0);
4777 dsi_vc_enable(dsidev, 3, 0); 4194 dsi_vc_enable(dsidev, 3, 0);
4778 4195
4779 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4196 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4780 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); 4197 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
4781 dsi_cio_uninit(dsidev); 4198 dsi_cio_uninit(dsidev);
4782 dsi_pll_uninit(dsidev, disconnect_lanes); 4199 dsi_pll_uninit(dsidev, disconnect_lanes);
4783} 4200}
@@ -4786,7 +4203,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4786{ 4203{
4787 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4204 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4788 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4205 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4789 struct omap_dss_output *out = dssdev->output;
4790 int r = 0; 4206 int r = 0;
4791 4207
4792 DSSDBG("dsi_display_enable\n"); 4208 DSSDBG("dsi_display_enable\n");
@@ -4795,12 +4211,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev)
4795 4211
4796 mutex_lock(&dsi->lock); 4212 mutex_lock(&dsi->lock);
4797 4213
4798 if (out == NULL || out->manager == NULL) {
4799 DSSERR("failed to enable display: no output/manager\n");
4800 r = -ENODEV;
4801 goto err_start_dev;
4802 }
4803
4804 r = omap_dss_start_device(dssdev); 4214 r = omap_dss_start_device(dssdev);
4805 if (r) { 4215 if (r) {
4806 DSSERR("failed to start device\n"); 4216 DSSERR("failed to start device\n");
@@ -4881,93 +4291,31 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4881} 4291}
4882EXPORT_SYMBOL(omapdss_dsi_enable_te); 4292EXPORT_SYMBOL(omapdss_dsi_enable_te);
4883 4293
4884void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, 4294void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
4885 struct omap_video_timings *timings) 4295 u32 fifo_size, u32 burst_size,
4886{ 4296 u32 *fifo_low, u32 *fifo_high)
4887 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4888 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4889
4890 mutex_lock(&dsi->lock);
4891
4892 dsi->timings = *timings;
4893
4894 mutex_unlock(&dsi->lock);
4895}
4896EXPORT_SYMBOL(omapdss_dsi_set_timings);
4897
4898void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
4899{
4900 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4901 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4902
4903 mutex_lock(&dsi->lock);
4904
4905 dsi->timings.x_res = w;
4906 dsi->timings.y_res = h;
4907
4908 mutex_unlock(&dsi->lock);
4909}
4910EXPORT_SYMBOL(omapdss_dsi_set_size);
4911
4912void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
4913 enum omap_dss_dsi_pixel_format fmt)
4914{ 4297{
4915 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4298 *fifo_high = fifo_size - burst_size;
4916 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4299 *fifo_low = fifo_size - burst_size * 2;
4917
4918 mutex_lock(&dsi->lock);
4919
4920 dsi->pix_fmt = fmt;
4921
4922 mutex_unlock(&dsi->lock);
4923} 4300}
4924EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
4925 4301
4926void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, 4302int dsi_init_display(struct omap_dss_device *dssdev)
4927 enum omap_dss_dsi_mode mode)
4928{ 4303{
4929 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4304 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4930 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4305 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4931 4306 int dsi_module = dsi_get_dsidev_id(dsidev);
4932 mutex_lock(&dsi->lock);
4933
4934 dsi->mode = mode;
4935
4936 mutex_unlock(&dsi->lock);
4937}
4938EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
4939
4940void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
4941 struct omap_dss_dsi_videomode_timings *timings)
4942{
4943 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4944 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4945
4946 mutex_lock(&dsi->lock);
4947
4948 dsi->vm_timings = *timings;
4949
4950 mutex_unlock(&dsi->lock);
4951}
4952EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings);
4953
4954static int __init dsi_init_display(struct omap_dss_device *dssdev)
4955{
4956 struct platform_device *dsidev =
4957 dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
4958 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4959 4307
4960 DSSDBG("DSI init\n"); 4308 DSSDBG("DSI init\n");
4961 4309
4310 /* XXX these should be figured out dynamically */
4311 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
4312 OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
4313
4962 if (dsi->vdds_dsi_reg == NULL) { 4314 if (dsi->vdds_dsi_reg == NULL) {
4963 struct regulator *vdds_dsi; 4315 struct regulator *vdds_dsi;
4964 4316
4965 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi"); 4317 vdds_dsi = regulator_get(&dsi->pdev->dev, "vdds_dsi");
4966 4318
4967 /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */
4968 if (IS_ERR(vdds_dsi))
4969 vdds_dsi = regulator_get(&dsi->pdev->dev, "VCXIO");
4970
4971 if (IS_ERR(vdds_dsi)) { 4319 if (IS_ERR(vdds_dsi)) {
4972 DSSERR("can't get VDDS_DSI regulator\n"); 4320 DSSERR("can't get VDDS_DSI regulator\n");
4973 return PTR_ERR(vdds_dsi); 4321 return PTR_ERR(vdds_dsi);
@@ -4976,6 +4324,12 @@ static int __init dsi_init_display(struct omap_dss_device *dssdev)
4976 dsi->vdds_dsi_reg = vdds_dsi; 4324 dsi->vdds_dsi_reg = vdds_dsi;
4977 } 4325 }
4978 4326
4327 if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) {
4328 DSSERR("DSI%d can't support more than %d data lanes\n",
4329 dsi_module + 1, dsi->num_data_lanes);
4330 return -EINVAL;
4331 }
4332
4979 return 0; 4333 return 0;
4980} 4334}
4981 4335
@@ -5081,7 +4435,10 @@ static int dsi_get_clocks(struct platform_device *dsidev)
5081 4435
5082 dsi->dss_clk = clk; 4436 dsi->dss_clk = clk;
5083 4437
5084 clk = clk_get(&dsidev->dev, "sys_clk"); 4438 if (cpu_is_omap34xx() || cpu_is_omap3630())
4439 clk = clk_get(&dsidev->dev, "dss2_alwon_fck");
4440 else
4441 clk = clk_get(&dsidev->dev, "sys_clk");
5085 if (IS_ERR(clk)) { 4442 if (IS_ERR(clk)) {
5086 DSSERR("can't get sys_clk\n"); 4443 DSSERR("can't get sys_clk\n");
5087 clk_put(dsi->dss_clk); 4444 clk_put(dsi->dss_clk);
@@ -5104,118 +4461,30 @@ static void dsi_put_clocks(struct platform_device *dsidev)
5104 clk_put(dsi->sys_clk); 4461 clk_put(dsi->sys_clk);
5105} 4462}
5106 4463
5107static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
5108{
5109 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
5110 struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
5111 const char *def_disp_name = omapdss_get_default_display_name();
5112 struct omap_dss_device *def_dssdev;
5113 int i;
5114
5115 def_dssdev = NULL;
5116
5117 for (i = 0; i < pdata->num_devices; ++i) {
5118 struct omap_dss_device *dssdev = pdata->devices[i];
5119
5120 if (dssdev->type != OMAP_DISPLAY_TYPE_DSI)
5121 continue;
5122
5123 if (dssdev->phy.dsi.module != dsi->module_id)
5124 continue;
5125
5126 if (def_dssdev == NULL)
5127 def_dssdev = dssdev;
5128
5129 if (def_disp_name != NULL &&
5130 strcmp(dssdev->name, def_disp_name) == 0) {
5131 def_dssdev = dssdev;
5132 break;
5133 }
5134 }
5135
5136 return def_dssdev;
5137}
5138
5139static void __init dsi_probe_pdata(struct platform_device *dsidev)
5140{
5141 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5142 struct omap_dss_device *plat_dssdev;
5143 struct omap_dss_device *dssdev;
5144 int r;
5145
5146 plat_dssdev = dsi_find_dssdev(dsidev);
5147
5148 if (!plat_dssdev)
5149 return;
5150
5151 dssdev = dss_alloc_and_init_device(&dsidev->dev);
5152 if (!dssdev)
5153 return;
5154
5155 dss_copy_device_pdata(dssdev, plat_dssdev);
5156
5157 r = dsi_init_display(dssdev);
5158 if (r) {
5159 DSSERR("device %s init failed: %d\n", dssdev->name, r);
5160 dss_put_device(dssdev);
5161 return;
5162 }
5163
5164 r = omapdss_output_set_device(&dsi->output, dssdev);
5165 if (r) {
5166 DSSERR("failed to connect output to new device: %s\n",
5167 dssdev->name);
5168 dss_put_device(dssdev);
5169 return;
5170 }
5171
5172 r = dss_add_device(dssdev);
5173 if (r) {
5174 DSSERR("device %s register failed: %d\n", dssdev->name, r);
5175 omapdss_output_unset_device(&dsi->output);
5176 dss_put_device(dssdev);
5177 return;
5178 }
5179}
5180
5181static void __init dsi_init_output(struct platform_device *dsidev)
5182{
5183 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5184 struct omap_dss_output *out = &dsi->output;
5185
5186 out->pdev = dsidev;
5187 out->id = dsi->module_id == 0 ?
5188 OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
5189
5190 out->type = OMAP_DISPLAY_TYPE_DSI;
5191
5192 dss_register_output(out);
5193}
5194
5195static void __exit dsi_uninit_output(struct platform_device *dsidev)
5196{
5197 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5198 struct omap_dss_output *out = &dsi->output;
5199
5200 dss_unregister_output(out);
5201}
5202
5203/* DSI1 HW IP initialisation */ 4464/* DSI1 HW IP initialisation */
5204static int __init omap_dsihw_probe(struct platform_device *dsidev) 4465static int omap_dsi1hw_probe(struct platform_device *dsidev)
5205{ 4466{
4467 struct omap_display_platform_data *dss_plat_data;
4468 struct omap_dss_board_info *board_info;
5206 u32 rev; 4469 u32 rev;
5207 int r, i; 4470 int r, i, dsi_module = dsi_get_dsidev_id(dsidev);
5208 struct resource *dsi_mem; 4471 struct resource *dsi_mem;
5209 struct dsi_data *dsi; 4472 struct dsi_data *dsi;
5210 4473
5211 dsi = devm_kzalloc(&dsidev->dev, sizeof(*dsi), GFP_KERNEL); 4474 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
5212 if (!dsi) 4475 if (!dsi) {
5213 return -ENOMEM; 4476 r = -ENOMEM;
4477 goto err_alloc;
4478 }
5214 4479
5215 dsi->module_id = dsidev->id;
5216 dsi->pdev = dsidev; 4480 dsi->pdev = dsidev;
4481 dsi_pdev_map[dsi_module] = dsidev;
5217 dev_set_drvdata(&dsidev->dev, dsi); 4482 dev_set_drvdata(&dsidev->dev, dsi);
5218 4483
4484 dss_plat_data = dsidev->dev.platform_data;
4485 board_info = dss_plat_data->board_data;
4486 dsi->dsi_mux_pads = board_info->dsi_mux_pads;
4487
5219 spin_lock_init(&dsi->irq_lock); 4488 spin_lock_init(&dsi->irq_lock);
5220 spin_lock_init(&dsi->errors_lock); 4489 spin_lock_init(&dsi->errors_lock);
5221 dsi->errors = 0; 4490 dsi->errors = 0;
@@ -5228,8 +4497,14 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
5228 mutex_init(&dsi->lock); 4497 mutex_init(&dsi->lock);
5229 sema_init(&dsi->bus_lock, 1); 4498 sema_init(&dsi->bus_lock, 1);
5230 4499
5231 INIT_DEFERRABLE_WORK(&dsi->framedone_timeout_work, 4500 r = dsi_get_clocks(dsidev);
5232 dsi_framedone_timeout_work_callback); 4501 if (r)
4502 goto err_get_clk;
4503
4504 pm_runtime_enable(&dsidev->dev);
4505
4506 INIT_DELAYED_WORK_DEFERRABLE(&dsi->framedone_timeout_work,
4507 dsi_framedone_timeout_work_callback);
5233 4508
5234#ifdef DSI_CATCH_MISSING_TE 4509#ifdef DSI_CATCH_MISSING_TE
5235 init_timer(&dsi->te_timer); 4510 init_timer(&dsi->te_timer);
@@ -5239,95 +4514,70 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev)
5239 dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0); 4514 dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0);
5240 if (!dsi_mem) { 4515 if (!dsi_mem) {
5241 DSSERR("can't get IORESOURCE_MEM DSI\n"); 4516 DSSERR("can't get IORESOURCE_MEM DSI\n");
5242 return -EINVAL; 4517 r = -EINVAL;
4518 goto err_ioremap;
5243 } 4519 }
5244 4520 dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
5245 dsi->base = devm_ioremap(&dsidev->dev, dsi_mem->start,
5246 resource_size(dsi_mem));
5247 if (!dsi->base) { 4521 if (!dsi->base) {
5248 DSSERR("can't ioremap DSI\n"); 4522 DSSERR("can't ioremap DSI\n");
5249 return -ENOMEM; 4523 r = -ENOMEM;
4524 goto err_ioremap;
5250 } 4525 }
5251
5252 dsi->irq = platform_get_irq(dsi->pdev, 0); 4526 dsi->irq = platform_get_irq(dsi->pdev, 0);
5253 if (dsi->irq < 0) { 4527 if (dsi->irq < 0) {
5254 DSSERR("platform_get_irq failed\n"); 4528 DSSERR("platform_get_irq failed\n");
5255 return -ENODEV; 4529 r = -ENODEV;
4530 goto err_get_irq;
5256 } 4531 }
5257 4532
5258 r = devm_request_irq(&dsidev->dev, dsi->irq, omap_dsi_irq_handler, 4533 r = request_irq(dsi->irq, omap_dsi_irq_handler, IRQF_SHARED,
5259 IRQF_SHARED, dev_name(&dsidev->dev), dsi->pdev); 4534 dev_name(&dsidev->dev), dsi->pdev);
5260 if (r < 0) { 4535 if (r < 0) {
5261 DSSERR("request_irq failed\n"); 4536 DSSERR("request_irq failed\n");
5262 return r; 4537 goto err_get_irq;
5263 } 4538 }
5264 4539
5265 /* DSI VCs initialization */ 4540 /* DSI VCs initialization */
5266 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { 4541 for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) {
5267 dsi->vc[i].source = DSI_VC_SOURCE_L4; 4542 dsi->vc[i].mode = DSI_VC_MODE_L4;
5268 dsi->vc[i].dssdev = NULL; 4543 dsi->vc[i].dssdev = NULL;
5269 dsi->vc[i].vc_id = 0; 4544 dsi->vc[i].vc_id = 0;
5270 } 4545 }
5271 4546
5272 dsi_calc_clock_param_ranges(dsidev); 4547 dsi_calc_clock_param_ranges(dsidev);
5273 4548
5274 r = dsi_get_clocks(dsidev);
5275 if (r)
5276 return r;
5277
5278 pm_runtime_enable(&dsidev->dev);
5279
5280 r = dsi_runtime_get(dsidev); 4549 r = dsi_runtime_get(dsidev);
5281 if (r) 4550 if (r)
5282 goto err_runtime_get; 4551 goto err_get_dsi;
5283 4552
5284 rev = dsi_read_reg(dsidev, DSI_REVISION); 4553 rev = dsi_read_reg(dsidev, DSI_REVISION);
5285 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", 4554 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
5286 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 4555 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
5287 4556
5288 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number 4557 dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
5289 * of data to 3 by default */
5290 if (dss_has_feature(FEAT_DSI_GNQ))
5291 /* NB_DATA_LANES */
5292 dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
5293 else
5294 dsi->num_lanes_supported = 3;
5295
5296 dsi_init_output(dsidev);
5297
5298 dsi_probe_pdata(dsidev);
5299 4558
5300 dsi_runtime_put(dsidev); 4559 dsi_runtime_put(dsidev);
5301 4560
5302 if (dsi->module_id == 0)
5303 dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs);
5304 else if (dsi->module_id == 1)
5305 dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs);
5306
5307#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
5308 if (dsi->module_id == 0)
5309 dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs);
5310 else if (dsi->module_id == 1)
5311 dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs);
5312#endif
5313 return 0; 4561 return 0;
5314 4562
5315err_runtime_get: 4563err_get_dsi:
4564 free_irq(dsi->irq, dsi->pdev);
4565err_get_irq:
4566 iounmap(dsi->base);
4567err_ioremap:
5316 pm_runtime_disable(&dsidev->dev); 4568 pm_runtime_disable(&dsidev->dev);
5317 dsi_put_clocks(dsidev); 4569err_get_clk:
4570 kfree(dsi);
4571err_alloc:
5318 return r; 4572 return r;
5319} 4573}
5320 4574
5321static int __exit omap_dsihw_remove(struct platform_device *dsidev) 4575static int omap_dsi1hw_remove(struct platform_device *dsidev)
5322{ 4576{
5323 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4577 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5324 4578
5325 WARN_ON(dsi->scp_clk_refcount > 0); 4579 WARN_ON(dsi->scp_clk_refcount > 0);
5326 4580
5327 dss_unregister_child_devices(&dsidev->dev);
5328
5329 dsi_uninit_output(dsidev);
5330
5331 pm_runtime_disable(&dsidev->dev); 4581 pm_runtime_disable(&dsidev->dev);
5332 4582
5333 dsi_put_clocks(dsidev); 4583 dsi_put_clocks(dsidev);
@@ -5342,25 +4592,47 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
5342 dsi->vdds_dsi_reg = NULL; 4592 dsi->vdds_dsi_reg = NULL;
5343 } 4593 }
5344 4594
4595 free_irq(dsi->irq, dsi->pdev);
4596 iounmap(dsi->base);
4597
4598 kfree(dsi);
4599
5345 return 0; 4600 return 0;
5346} 4601}
5347 4602
5348static int dsi_runtime_suspend(struct device *dev) 4603static int dsi_runtime_suspend(struct device *dev)
5349{ 4604{
4605 struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
4606
4607 clk_disable(dsi->dss_clk);
4608
5350 dispc_runtime_put(); 4609 dispc_runtime_put();
4610 dss_runtime_put();
5351 4611
5352 return 0; 4612 return 0;
5353} 4613}
5354 4614
5355static int dsi_runtime_resume(struct device *dev) 4615static int dsi_runtime_resume(struct device *dev)
5356{ 4616{
4617 struct dsi_data *dsi = dsi_get_dsidrv_data(to_platform_device(dev));
5357 int r; 4618 int r;
5358 4619
4620 r = dss_runtime_get();
4621 if (r)
4622 goto err_get_dss;
4623
5359 r = dispc_runtime_get(); 4624 r = dispc_runtime_get();
5360 if (r) 4625 if (r)
5361 return r; 4626 goto err_get_dispc;
4627
4628 clk_enable(dsi->dss_clk);
5362 4629
5363 return 0; 4630 return 0;
4631
4632err_get_dispc:
4633 dss_runtime_put();
4634err_get_dss:
4635 return r;
5364} 4636}
5365 4637
5366static const struct dev_pm_ops dsi_pm_ops = { 4638static const struct dev_pm_ops dsi_pm_ops = {
@@ -5368,21 +4640,22 @@ static const struct dev_pm_ops dsi_pm_ops = {
5368 .runtime_resume = dsi_runtime_resume, 4640 .runtime_resume = dsi_runtime_resume,
5369}; 4641};
5370 4642
5371static struct platform_driver omap_dsihw_driver = { 4643static struct platform_driver omap_dsi1hw_driver = {
5372 .remove = __exit_p(omap_dsihw_remove), 4644 .probe = omap_dsi1hw_probe,
4645 .remove = omap_dsi1hw_remove,
5373 .driver = { 4646 .driver = {
5374 .name = "omapdss_dsi", 4647 .name = "omapdss_dsi1",
5375 .owner = THIS_MODULE, 4648 .owner = THIS_MODULE,
5376 .pm = &dsi_pm_ops, 4649 .pm = &dsi_pm_ops,
5377 }, 4650 },
5378}; 4651};
5379 4652
5380int __init dsi_init_platform_driver(void) 4653int dsi_init_platform_driver(void)
5381{ 4654{
5382 return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe); 4655 return platform_driver_register(&omap_dsi1hw_driver);
5383} 4656}
5384 4657
5385void __exit dsi_uninit_platform_driver(void) 4658void dsi_uninit_platform_driver(void)
5386{ 4659{
5387 platform_driver_unregister(&omap_dsihw_driver); 4660 return platform_driver_unregister(&omap_dsi1hw_driver);
5388} 4661}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 054c2a22b3f..0f9c3a6457a 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -24,18 +24,15 @@
24 24
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/export.h>
28#include <linux/err.h> 27#include <linux/err.h>
29#include <linux/delay.h> 28#include <linux/delay.h>
30#include <linux/seq_file.h> 29#include <linux/seq_file.h>
31#include <linux/clk.h> 30#include <linux/clk.h>
32#include <linux/platform_device.h> 31#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 32#include <linux/pm_runtime.h>
34#include <linux/gfp.h>
35#include <linux/sizes.h>
36 33
37#include <video/omapdss.h> 34#include <video/omapdss.h>
38 35#include <plat/clock.h>
39#include "dss.h" 36#include "dss.h"
40#include "dss_features.h" 37#include "dss_features.h"
41 38
@@ -61,23 +58,12 @@ struct dss_reg {
61#define REG_FLD_MOD(idx, val, start, end) \ 58#define REG_FLD_MOD(idx, val, start, end) \
62 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) 59 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
63 60
64static int dss_runtime_get(void);
65static void dss_runtime_put(void);
66
67struct dss_features {
68 u8 fck_div_max;
69 u8 dss_fck_multiplier;
70 const char *clk_name;
71 int (*dpi_select_source)(enum omap_channel channel);
72};
73
74static struct { 61static struct {
75 struct platform_device *pdev; 62 struct platform_device *pdev;
76 void __iomem *base; 63 void __iomem *base;
77 64
78 struct clk *dpll4_m4_ck; 65 struct clk *dpll4_m4_ck;
79 struct clk *dss_clk; 66 struct clk *dss_clk;
80 unsigned long dss_clk_rate;
81 67
82 unsigned long cache_req_pck; 68 unsigned long cache_req_pck;
83 unsigned long cache_prate; 69 unsigned long cache_prate;
@@ -90,16 +76,12 @@ static struct {
90 76
91 bool ctx_valid; 77 bool ctx_valid;
92 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 78 u32 ctx[DSS_SZ_REGS / sizeof(u32)];
93
94 const struct dss_features *feat;
95} dss; 79} dss;
96 80
97static const char * const dss_generic_clk_source_names[] = { 81static const char * const dss_generic_clk_source_names[] = {
98 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", 82 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
99 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", 83 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
100 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 84 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
101 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC",
102 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
103}; 85};
104 86
105static inline void dss_write_reg(const struct dss_reg idx, u32 val) 87static inline void dss_write_reg(const struct dss_reg idx, u32 val)
@@ -155,22 +137,7 @@ static void dss_restore_context(void)
155#undef SR 137#undef SR
156#undef RR 138#undef RR
157 139
158int dss_get_ctx_loss_count(void) 140void dss_sdi_init(u8 datapairs)
159{
160 struct omap_dss_board_info *board_data = dss.pdev->dev.platform_data;
161 int cnt;
162
163 if (!board_data->get_context_loss_count)
164 return -ENOENT;
165
166 cnt = board_data->get_context_loss_count(&dss.pdev->dev);
167
168 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
169
170 return cnt;
171}
172
173void dss_sdi_init(int datapairs)
174{ 141{
175 u32 l; 142 u32 l;
176 143
@@ -262,6 +229,7 @@ const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
262 return dss_generic_clk_source_names[clk_src]; 229 return dss_generic_clk_source_names[clk_src];
263} 230}
264 231
232
265void dss_dump_clocks(struct seq_file *s) 233void dss_dump_clocks(struct seq_file *s)
266{ 234{
267 unsigned long dpll4_ck_rate; 235 unsigned long dpll4_ck_rate;
@@ -284,10 +252,18 @@ void dss_dump_clocks(struct seq_file *s)
284 252
285 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); 253 seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
286 254
287 seq_printf(s, "%s (%s) = %lu / %lu * %d = %lu\n", 255 if (cpu_is_omap3630() || cpu_is_omap44xx())
288 fclk_name, fclk_real_name, dpll4_ck_rate, 256 seq_printf(s, "%s (%s) = %lu / %lu = %lu\n",
289 dpll4_ck_rate / dpll4_m4_ck_rate, 257 fclk_name, fclk_real_name,
290 dss.feat->dss_fck_multiplier, fclk_rate); 258 dpll4_ck_rate,
259 dpll4_ck_rate / dpll4_m4_ck_rate,
260 fclk_rate);
261 else
262 seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n",
263 fclk_name, fclk_real_name,
264 dpll4_ck_rate,
265 dpll4_ck_rate / dpll4_m4_ck_rate,
266 fclk_rate);
291 } else { 267 } else {
292 seq_printf(s, "%s (%s) = %lu\n", 268 seq_printf(s, "%s (%s) = %lu\n",
293 fclk_name, fclk_real_name, 269 fclk_name, fclk_real_name,
@@ -297,7 +273,7 @@ void dss_dump_clocks(struct seq_file *s)
297 dss_runtime_put(); 273 dss_runtime_put();
298} 274}
299 275
300static void dss_dump_regs(struct seq_file *s) 276void dss_dump_regs(struct seq_file *s)
301{ 277{
302#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) 278#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
303 279
@@ -320,7 +296,7 @@ static void dss_dump_regs(struct seq_file *s)
320#undef DUMPREG 296#undef DUMPREG
321} 297}
322 298
323static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) 299void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
324{ 300{
325 struct platform_device *dsidev; 301 struct platform_device *dsidev;
326 int b; 302 int b;
@@ -342,7 +318,6 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
342 break; 318 break;
343 default: 319 default:
344 BUG(); 320 BUG();
345 return;
346 } 321 }
347 322
348 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); 323 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
@@ -356,7 +331,7 @@ void dss_select_dsi_clk_source(int dsi_module,
356 enum omap_dss_clk_source clk_src) 331 enum omap_dss_clk_source clk_src)
357{ 332{
358 struct platform_device *dsidev; 333 struct platform_device *dsidev;
359 int b, pos; 334 int b;
360 335
361 switch (clk_src) { 336 switch (clk_src) {
362 case OMAP_DSS_CLK_SRC_FCK: 337 case OMAP_DSS_CLK_SRC_FCK:
@@ -376,11 +351,9 @@ void dss_select_dsi_clk_source(int dsi_module,
376 break; 351 break;
377 default: 352 default:
378 BUG(); 353 BUG();
379 return;
380 } 354 }
381 355
382 pos = dsi_module == 0 ? 1 : 10; 356 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
383 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */
384 357
385 dss.dsi_clk_source[dsi_module] = clk_src; 358 dss.dsi_clk_source[dsi_module] = clk_src;
386} 359}
@@ -391,10 +364,8 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
391 struct platform_device *dsidev; 364 struct platform_device *dsidev;
392 int b, ix, pos; 365 int b, ix, pos;
393 366
394 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { 367 if (!dss_has_feature(FEAT_LCD_CLK_SRC))
395 dss_select_dispc_clk_source(clk_src);
396 return; 368 return;
397 }
398 369
399 switch (clk_src) { 370 switch (clk_src) {
400 case OMAP_DSS_CLK_SRC_FCK: 371 case OMAP_DSS_CLK_SRC_FCK:
@@ -407,23 +378,19 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
407 dsi_wait_pll_hsdiv_dispc_active(dsidev); 378 dsi_wait_pll_hsdiv_dispc_active(dsidev);
408 break; 379 break;
409 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 380 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
410 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 && 381 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2);
411 channel != OMAP_DSS_CHANNEL_LCD3);
412 b = 1; 382 b = 1;
413 dsidev = dsi_get_dsidev_from_id(1); 383 dsidev = dsi_get_dsidev_from_id(1);
414 dsi_wait_pll_hsdiv_dispc_active(dsidev); 384 dsi_wait_pll_hsdiv_dispc_active(dsidev);
415 break; 385 break;
416 default: 386 default:
417 BUG(); 387 BUG();
418 return;
419 } 388 }
420 389
421 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 390 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
422 (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19);
423 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ 391 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */
424 392
425 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 393 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
426 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
427 dss.lcd_clk_source[ix] = clk_src; 394 dss.lcd_clk_source[ix] = clk_src;
428} 395}
429 396
@@ -440,8 +407,7 @@ enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
440enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) 407enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
441{ 408{
442 if (dss_has_feature(FEAT_LCD_CLK_SRC)) { 409 if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
443 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 410 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
444 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2);
445 return dss.lcd_clk_source[ix]; 411 return dss.lcd_clk_source[ix];
446 } else { 412 } else {
447 /* LCD_CLK source is the same as DISPC_FCLK source for 413 /* LCD_CLK source is the same as DISPC_FCLK source for
@@ -455,15 +421,17 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo)
455{ 421{
456 if (dss.dpll4_m4_ck) { 422 if (dss.dpll4_m4_ck) {
457 unsigned long prate; 423 unsigned long prate;
424 u16 fck_div_max = 16;
458 425
459 if (cinfo->fck_div > dss.feat->fck_div_max || 426 if (cpu_is_omap3630() || cpu_is_omap44xx())
460 cinfo->fck_div == 0) 427 fck_div_max = 32;
428
429 if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0)
461 return -EINVAL; 430 return -EINVAL;
462 431
463 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); 432 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
464 433
465 cinfo->fck = prate / cinfo->fck_div * 434 cinfo->fck = prate / cinfo->fck_div;
466 dss.feat->dss_fck_multiplier;
467 } else { 435 } else {
468 if (cinfo->fck_div != 0) 436 if (cinfo->fck_div != 0)
469 return -EINVAL; 437 return -EINVAL;
@@ -490,11 +458,27 @@ int dss_set_clock_div(struct dss_clock_info *cinfo)
490 return -EINVAL; 458 return -EINVAL;
491 } 459 }
492 460
493 dss.dss_clk_rate = clk_get_rate(dss.dss_clk); 461 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
462
463 return 0;
464}
494 465
495 WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch"); 466int dss_get_clock_div(struct dss_clock_info *cinfo)
467{
468 cinfo->fck = clk_get_rate(dss.dss_clk);
496 469
497 DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); 470 if (dss.dpll4_m4_ck) {
471 unsigned long prate;
472
473 prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
474
475 if (cpu_is_omap3630() || cpu_is_omap44xx())
476 cinfo->fck_div = prate / (cinfo->fck);
477 else
478 cinfo->fck_div = prate / (cinfo->fck / 2);
479 } else {
480 cinfo->fck_div = 0;
481 }
498 482
499 return 0; 483 return 0;
500} 484}
@@ -507,42 +491,8 @@ unsigned long dss_get_dpll4_rate(void)
507 return 0; 491 return 0;
508} 492}
509 493
510unsigned long dss_get_dispc_clk_rate(void) 494int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
511{ 495 struct dss_clock_info *dss_cinfo,
512 return dss.dss_clk_rate;
513}
514
515static int dss_setup_default_clock(void)
516{
517 unsigned long max_dss_fck, prate;
518 unsigned fck_div;
519 struct dss_clock_info dss_cinfo = { 0 };
520 int r;
521
522 if (dss.dpll4_m4_ck == NULL)
523 return 0;
524
525 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
526
527 prate = dss_get_dpll4_rate();
528
529 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier,
530 max_dss_fck);
531
532 dss_cinfo.fck_div = fck_div;
533
534 r = dss_calc_clock_rates(&dss_cinfo);
535 if (r)
536 return r;
537
538 r = dss_set_clock_div(&dss_cinfo);
539 if (r)
540 return r;
541
542 return 0;
543}
544
545int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
546 struct dispc_clock_info *dispc_cinfo) 496 struct dispc_clock_info *dispc_cinfo)
547{ 497{
548 unsigned long prate; 498 unsigned long prate;
@@ -551,7 +501,7 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
551 501
552 unsigned long fck, max_dss_fck; 502 unsigned long fck, max_dss_fck;
553 503
554 u16 fck_div; 504 u16 fck_div, fck_div_max = 16;
555 505
556 int match = 0; 506 int match = 0;
557 int min_fck_per_pck; 507 int min_fck_per_pck;
@@ -561,8 +511,9 @@ int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo,
561 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 511 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
562 512
563 fck = clk_get_rate(dss.dss_clk); 513 fck = clk_get_rate(dss.dss_clk);
564 if (req_pck == dss.cache_req_pck && prate == dss.cache_prate && 514 if (req_pck == dss.cache_req_pck &&
565 dss.cache_dss_cinfo.fck == fck) { 515 ((cpu_is_omap34xx() && prate == dss.cache_prate) ||
516 dss.cache_dss_cinfo.fck == fck)) {
566 DSSDBG("dispc clock info found from cache.\n"); 517 DSSDBG("dispc clock info found from cache.\n");
567 *dss_cinfo = dss.cache_dss_cinfo; 518 *dss_cinfo = dss.cache_dss_cinfo;
568 *dispc_cinfo = dss.cache_dispc_cinfo; 519 *dispc_cinfo = dss.cache_dispc_cinfo;
@@ -589,7 +540,7 @@ retry:
589 fck = clk_get_rate(dss.dss_clk); 540 fck = clk_get_rate(dss.dss_clk);
590 fck_div = 1; 541 fck_div = 1;
591 542
592 dispc_find_clk_divs(req_pck, fck, &cur_dispc); 543 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
593 match = 1; 544 match = 1;
594 545
595 best_dss.fck = fck; 546 best_dss.fck = fck;
@@ -599,10 +550,16 @@ retry:
599 550
600 goto found; 551 goto found;
601 } else { 552 } else {
602 for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) { 553 if (cpu_is_omap3630() || cpu_is_omap44xx())
554 fck_div_max = 32;
555
556 for (fck_div = fck_div_max; fck_div > 0; --fck_div) {
603 struct dispc_clock_info cur_dispc; 557 struct dispc_clock_info cur_dispc;
604 558
605 fck = prate / fck_div * dss.feat->dss_fck_multiplier; 559 if (fck_div_max == 32)
560 fck = prate / fck_div;
561 else
562 fck = prate / fck_div * 2;
606 563
607 if (fck > max_dss_fck) 564 if (fck > max_dss_fck)
608 continue; 565 continue;
@@ -613,7 +570,7 @@ retry:
613 570
614 match = 1; 571 match = 1;
615 572
616 dispc_find_clk_divs(req_pck, fck, &cur_dispc); 573 dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
617 574
618 if (abs(cur_dispc.pck - req_pck) < 575 if (abs(cur_dispc.pck - req_pck) <
619 abs(best_dispc.pck - req_pck)) { 576 abs(best_dispc.pck - req_pck)) {
@@ -677,91 +634,9 @@ void dss_set_dac_pwrdn_bgz(bool enable)
677 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ 634 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
678} 635}
679 636
680void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src) 637void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi)
681{ 638{
682 enum omap_display_type dp; 639 REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */
683 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
684
685 /* Complain about invalid selections */
686 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC));
687 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI));
688
689 /* Select only if we have options */
690 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI))
691 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */
692}
693
694enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
695{
696 enum omap_display_type displays;
697
698 displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT);
699 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0)
700 return DSS_VENC_TV_CLK;
701
702 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0)
703 return DSS_HDMI_M_PCLK;
704
705 return REG_GET(DSS_CONTROL, 15, 15);
706}
707
708static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
709{
710 if (channel != OMAP_DSS_CHANNEL_LCD)
711 return -EINVAL;
712
713 return 0;
714}
715
716static int dss_dpi_select_source_omap4(enum omap_channel channel)
717{
718 int val;
719
720 switch (channel) {
721 case OMAP_DSS_CHANNEL_LCD2:
722 val = 0;
723 break;
724 case OMAP_DSS_CHANNEL_DIGIT:
725 val = 1;
726 break;
727 default:
728 return -EINVAL;
729 }
730
731 REG_FLD_MOD(DSS_CONTROL, val, 17, 17);
732
733 return 0;
734}
735
736static int dss_dpi_select_source_omap5(enum omap_channel channel)
737{
738 int val;
739
740 switch (channel) {
741 case OMAP_DSS_CHANNEL_LCD:
742 val = 1;
743 break;
744 case OMAP_DSS_CHANNEL_LCD2:
745 val = 2;
746 break;
747 case OMAP_DSS_CHANNEL_LCD3:
748 val = 3;
749 break;
750 case OMAP_DSS_CHANNEL_DIGIT:
751 val = 0;
752 break;
753 default:
754 return -EINVAL;
755 }
756
757 REG_FLD_MOD(DSS_CONTROL, val, 17, 16);
758
759 return 0;
760}
761
762int dss_dpi_select_source(enum omap_channel channel)
763{
764 return dss.feat->dpi_select_source(channel);
765} 640}
766 641
767static int dss_get_clocks(void) 642static int dss_get_clocks(void)
@@ -778,14 +653,21 @@ static int dss_get_clocks(void)
778 653
779 dss.dss_clk = clk; 654 dss.dss_clk = clk;
780 655
781 if (dss.feat->clk_name) { 656 if (cpu_is_omap34xx()) {
782 clk = clk_get(NULL, dss.feat->clk_name); 657 clk = clk_get(NULL, "dpll4_m4_ck");
783 if (IS_ERR(clk)) { 658 if (IS_ERR(clk)) {
784 DSSERR("Failed to get %s\n", dss.feat->clk_name); 659 DSSERR("Failed to get dpll4_m4_ck\n");
785 r = PTR_ERR(clk); 660 r = PTR_ERR(clk);
786 goto err; 661 goto err;
787 } 662 }
788 } else { 663 } else if (cpu_is_omap44xx()) {
664 clk = clk_get(NULL, "dpll_per_m5x2_ck");
665 if (IS_ERR(clk)) {
666 DSSERR("Failed to get dpll_per_m5x2_ck\n");
667 r = PTR_ERR(clk);
668 goto err;
669 }
670 } else { /* omap24xx */
789 clk = NULL; 671 clk = NULL;
790 } 672 }
791 673
@@ -809,7 +691,12 @@ static void dss_put_clocks(void)
809 clk_put(dss.dss_clk); 691 clk_put(dss.dss_clk);
810} 692}
811 693
812static int dss_runtime_get(void) 694struct clk *dss_get_ick(void)
695{
696 return clk_get(&dss.pdev->dev, "ick");
697}
698
699int dss_runtime_get(void)
813{ 700{
814 int r; 701 int r;
815 702
@@ -820,18 +707,18 @@ static int dss_runtime_get(void)
820 return r < 0 ? r : 0; 707 return r < 0 ? r : 0;
821} 708}
822 709
823static void dss_runtime_put(void) 710void dss_runtime_put(void)
824{ 711{
825 int r; 712 int r;
826 713
827 DSSDBG("dss_runtime_put\n"); 714 DSSDBG("dss_runtime_put\n");
828 715
829 r = pm_runtime_put_sync(&dss.pdev->dev); 716 r = pm_runtime_put(&dss.pdev->dev);
830 WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY); 717 WARN_ON(r < 0);
831} 718}
832 719
833/* DEBUGFS */ 720/* DEBUGFS */
834#if defined(CONFIG_OMAP2_DSS_DEBUGFS) 721#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
835void dss_debug_dump_clocks(struct seq_file *s) 722void dss_debug_dump_clocks(struct seq_file *s)
836{ 723{
837 dss_dump_clocks(s); 724 dss_dump_clocks(s);
@@ -842,89 +729,8 @@ void dss_debug_dump_clocks(struct seq_file *s)
842} 729}
843#endif 730#endif
844 731
845static const struct dss_features omap24xx_dss_feats __initconst = {
846 .fck_div_max = 16,
847 .dss_fck_multiplier = 2,
848 .clk_name = NULL,
849 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
850};
851
852static const struct dss_features omap34xx_dss_feats __initconst = {
853 .fck_div_max = 16,
854 .dss_fck_multiplier = 2,
855 .clk_name = "dpll4_m4_ck",
856 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
857};
858
859static const struct dss_features omap3630_dss_feats __initconst = {
860 .fck_div_max = 32,
861 .dss_fck_multiplier = 1,
862 .clk_name = "dpll4_m4_ck",
863 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
864};
865
866static const struct dss_features omap44xx_dss_feats __initconst = {
867 .fck_div_max = 32,
868 .dss_fck_multiplier = 1,
869 .clk_name = "dpll_per_m5x2_ck",
870 .dpi_select_source = &dss_dpi_select_source_omap4,
871};
872
873static const struct dss_features omap54xx_dss_feats __initconst = {
874 .fck_div_max = 64,
875 .dss_fck_multiplier = 1,
876 .clk_name = "dpll_per_h12x2_ck",
877 .dpi_select_source = &dss_dpi_select_source_omap5,
878};
879
880static int __init dss_init_features(struct platform_device *pdev)
881{
882 const struct dss_features *src;
883 struct dss_features *dst;
884
885 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
886 if (!dst) {
887 dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
888 return -ENOMEM;
889 }
890
891 switch (omapdss_get_version()) {
892 case OMAPDSS_VER_OMAP24xx:
893 src = &omap24xx_dss_feats;
894 break;
895
896 case OMAPDSS_VER_OMAP34xx_ES1:
897 case OMAPDSS_VER_OMAP34xx_ES3:
898 case OMAPDSS_VER_AM35xx:
899 src = &omap34xx_dss_feats;
900 break;
901
902 case OMAPDSS_VER_OMAP3630:
903 src = &omap3630_dss_feats;
904 break;
905
906 case OMAPDSS_VER_OMAP4430_ES1:
907 case OMAPDSS_VER_OMAP4430_ES2:
908 case OMAPDSS_VER_OMAP4:
909 src = &omap44xx_dss_feats;
910 break;
911
912 case OMAPDSS_VER_OMAP5:
913 src = &omap54xx_dss_feats;
914 break;
915
916 default:
917 return -ENODEV;
918 }
919
920 memcpy(dst, src, sizeof(*dst));
921 dss.feat = dst;
922
923 return 0;
924}
925
926/* DSS HW IP initialisation */ 732/* DSS HW IP initialisation */
927static int __init omap_dsshw_probe(struct platform_device *pdev) 733static int omap_dsshw_probe(struct platform_device *pdev)
928{ 734{
929 struct resource *dss_mem; 735 struct resource *dss_mem;
930 u32 rev; 736 u32 rev;
@@ -932,30 +738,22 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
932 738
933 dss.pdev = pdev; 739 dss.pdev = pdev;
934 740
935 r = dss_init_features(dss.pdev);
936 if (r)
937 return r;
938
939 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 741 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0);
940 if (!dss_mem) { 742 if (!dss_mem) {
941 DSSERR("can't get IORESOURCE_MEM DSS\n"); 743 DSSERR("can't get IORESOURCE_MEM DSS\n");
942 return -EINVAL; 744 r = -EINVAL;
745 goto err_ioremap;
943 } 746 }
944 747 dss.base = ioremap(dss_mem->start, resource_size(dss_mem));
945 dss.base = devm_ioremap(&pdev->dev, dss_mem->start,
946 resource_size(dss_mem));
947 if (!dss.base) { 748 if (!dss.base) {
948 DSSERR("can't ioremap DSS\n"); 749 DSSERR("can't ioremap DSS\n");
949 return -ENOMEM; 750 r = -ENOMEM;
751 goto err_ioremap;
950 } 752 }
951 753
952 r = dss_get_clocks(); 754 r = dss_get_clocks();
953 if (r) 755 if (r)
954 return r; 756 goto err_clocks;
955
956 r = dss_setup_default_clock();
957 if (r)
958 goto err_setup_clocks;
959 757
960 pm_runtime_enable(&pdev->dev); 758 pm_runtime_enable(&pdev->dev);
961 759
@@ -963,13 +761,9 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
963 if (r) 761 if (r)
964 goto err_runtime_get; 762 goto err_runtime_get;
965 763
966 dss.dss_clk_rate = clk_get_rate(dss.dss_clk);
967
968 /* Select DPLL */ 764 /* Select DPLL */
969 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); 765 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
970 766
971 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
972
973#ifdef CONFIG_OMAP2_DSS_VENC 767#ifdef CONFIG_OMAP2_DSS_VENC
974 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ 768 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
975 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ 769 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
@@ -981,25 +775,45 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
981 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 775 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
982 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 776 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
983 777
778 r = dpi_init();
779 if (r) {
780 DSSERR("Failed to initialize DPI\n");
781 goto err_dpi;
782 }
783
784 r = sdi_init();
785 if (r) {
786 DSSERR("Failed to initialize SDI\n");
787 goto err_sdi;
788 }
789
984 rev = dss_read_reg(DSS_REVISION); 790 rev = dss_read_reg(DSS_REVISION);
985 printk(KERN_INFO "OMAP DSS rev %d.%d\n", 791 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
986 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 792 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
987 793
988 dss_runtime_put(); 794 dss_runtime_put();
989 795
990 dss_debugfs_create_file("dss", dss_dump_regs);
991
992 return 0; 796 return 0;
993 797err_sdi:
798 dpi_exit();
799err_dpi:
800 dss_runtime_put();
994err_runtime_get: 801err_runtime_get:
995 pm_runtime_disable(&pdev->dev); 802 pm_runtime_disable(&pdev->dev);
996err_setup_clocks:
997 dss_put_clocks(); 803 dss_put_clocks();
804err_clocks:
805 iounmap(dss.base);
806err_ioremap:
998 return r; 807 return r;
999} 808}
1000 809
1001static int __exit omap_dsshw_remove(struct platform_device *pdev) 810static int omap_dsshw_remove(struct platform_device *pdev)
1002{ 811{
812 dpi_exit();
813 sdi_exit();
814
815 iounmap(dss.base);
816
1003 pm_runtime_disable(&pdev->dev); 817 pm_runtime_disable(&pdev->dev);
1004 818
1005 dss_put_clocks(); 819 dss_put_clocks();
@@ -1010,24 +824,13 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev)
1010static int dss_runtime_suspend(struct device *dev) 824static int dss_runtime_suspend(struct device *dev)
1011{ 825{
1012 dss_save_context(); 826 dss_save_context();
1013 dss_set_min_bus_tput(dev, 0); 827 clk_disable(dss.dss_clk);
1014 return 0; 828 return 0;
1015} 829}
1016 830
1017static int dss_runtime_resume(struct device *dev) 831static int dss_runtime_resume(struct device *dev)
1018{ 832{
1019 int r; 833 clk_enable(dss.dss_clk);
1020 /*
1021 * Set an arbitrarily high tput request to ensure OPP100.
1022 * What we should really do is to make a request to stay in OPP100,
1023 * without any tput requirements, but that is not currently possible
1024 * via the PM layer.
1025 */
1026
1027 r = dss_set_min_bus_tput(dev, 1000000000);
1028 if (r)
1029 return r;
1030
1031 dss_restore_context(); 834 dss_restore_context();
1032 return 0; 835 return 0;
1033} 836}
@@ -1038,7 +841,8 @@ static const struct dev_pm_ops dss_pm_ops = {
1038}; 841};
1039 842
1040static struct platform_driver omap_dsshw_driver = { 843static struct platform_driver omap_dsshw_driver = {
1041 .remove = __exit_p(omap_dsshw_remove), 844 .probe = omap_dsshw_probe,
845 .remove = omap_dsshw_remove,
1042 .driver = { 846 .driver = {
1043 .name = "omapdss_dss", 847 .name = "omapdss_dss",
1044 .owner = THIS_MODULE, 848 .owner = THIS_MODULE,
@@ -1046,12 +850,12 @@ static struct platform_driver omap_dsshw_driver = {
1046 }, 850 },
1047}; 851};
1048 852
1049int __init dss_init_platform_driver(void) 853int dss_init_platform_driver(void)
1050{ 854{
1051 return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); 855 return platform_driver_register(&omap_dsshw_driver);
1052} 856}
1053 857
1054void dss_uninit_platform_driver(void) 858void dss_uninit_platform_driver(void)
1055{ 859{
1056 platform_driver_unregister(&omap_dsshw_driver); 860 return platform_driver_unregister(&omap_dsshw_driver);
1057} 861}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 610c8e563da..9c94b1152c2 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -23,20 +23,44 @@
23#ifndef __OMAP2_DSS_H 23#ifndef __OMAP2_DSS_H
24#define __OMAP2_DSS_H 24#define __OMAP2_DSS_H
25 25
26#include <linux/interrupt.h> 26#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
27#define DEBUG
28#endif
27 29
28#ifdef pr_fmt 30#ifdef DEBUG
29#undef pr_fmt 31extern unsigned int dss_debug;
32#ifdef DSS_SUBSYS_NAME
33#define DSSDBG(format, ...) \
34 if (dss_debug) \
35 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
36 ## __VA_ARGS__)
37#else
38#define DSSDBG(format, ...) \
39 if (dss_debug) \
40 printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
30#endif 41#endif
31 42
32#ifdef DSS_SUBSYS_NAME 43#ifdef DSS_SUBSYS_NAME
33#define pr_fmt(fmt) DSS_SUBSYS_NAME ": " fmt 44#define DSSDBGF(format, ...) \
45 if (dss_debug) \
46 printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
47 ": %s(" format ")\n", \
48 __func__, \
49 ## __VA_ARGS__)
34#else 50#else
35#define pr_fmt(fmt) fmt 51#define DSSDBGF(format, ...) \
52 if (dss_debug) \
53 printk(KERN_DEBUG "omapdss: " \
54 ": %s(" format ")\n", \
55 __func__, \
56 ## __VA_ARGS__)
57#endif
58
59#else /* DEBUG */
60#define DSSDBG(format, ...)
61#define DSSDBGF(format, ...)
36#endif 62#endif
37 63
38#define DSSDBG(format, ...) \
39 pr_debug(format, ## __VA_ARGS__)
40 64
41#ifdef DSS_SUBSYS_NAME 65#ifdef DSS_SUBSYS_NAME
42#define DSSERR(format, ...) \ 66#define DSSERR(format, ...) \
@@ -73,10 +97,10 @@
73#define FLD_MOD(orig, val, start, end) \ 97#define FLD_MOD(orig, val, start, end) \
74 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) 98 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
75 99
76enum dss_io_pad_mode { 100enum omap_parallel_interface_mode {
77 DSS_IO_PAD_MODE_RESET, 101 OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
78 DSS_IO_PAD_MODE_RFBI, 102 OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
79 DSS_IO_PAD_MODE_BYPASS, 103 OMAP_DSS_PARALLELMODE_DSI,
80}; 104};
81 105
82enum dss_hdmi_venc_clk_source_select { 106enum dss_hdmi_venc_clk_source_select {
@@ -84,22 +108,6 @@ enum dss_hdmi_venc_clk_source_select {
84 DSS_HDMI_M_PCLK = 1, 108 DSS_HDMI_M_PCLK = 1,
85}; 109};
86 110
87enum dss_dsi_content_type {
88 DSS_DSI_CONTENT_DCS,
89 DSS_DSI_CONTENT_GENERIC,
90};
91
92enum dss_writeback_channel {
93 DSS_WB_LCD1_MGR = 0,
94 DSS_WB_LCD2_MGR = 1,
95 DSS_WB_TV_MGR = 2,
96 DSS_WB_OVL0 = 3,
97 DSS_WB_OVL1 = 4,
98 DSS_WB_OVL2 = 5,
99 DSS_WB_OVL3 = 6,
100 DSS_WB_LCD3_MGR = 7,
101};
102
103struct dss_clock_info { 111struct dss_clock_info {
104 /* rates that we get with dividers below */ 112 /* rates that we get with dividers below */
105 unsigned long fck; 113 unsigned long fck;
@@ -137,123 +145,86 @@ struct dsi_clock_info {
137 u16 regm_dsi; /* OMAP3: REGM4 145 u16 regm_dsi; /* OMAP3: REGM4
138 * OMAP4: REGM5 */ 146 * OMAP4: REGM5 */
139 u16 lp_clk_div; 147 u16 lp_clk_div;
140};
141 148
142struct reg_field { 149 u8 highfreq;
143 u16 reg; 150 bool use_sys_clk;
144 u8 high;
145 u8 low;
146}; 151};
147 152
148struct dss_lcd_mgr_config { 153/* HDMI PLL structure */
149 enum dss_io_pad_mode io_pad_mode; 154struct hdmi_pll_info {
150 155 u16 regn;
151 bool stallmode; 156 u16 regm;
152 bool fifohandcheck; 157 u32 regmf;
153 158 u16 regm2;
154 struct dispc_clock_info clock_info; 159 u16 regsd;
155 160 u16 dcofreq;
156 int video_port_width;
157
158 int lcden_sig_polarity;
159}; 161};
160 162
161struct seq_file; 163struct seq_file;
162struct platform_device; 164struct platform_device;
163 165
164/* core */ 166/* core */
165struct platform_device *dss_get_core_pdev(void);
166struct bus_type *dss_get_bus(void); 167struct bus_type *dss_get_bus(void);
167struct regulator *dss_get_vdds_dsi(void); 168struct regulator *dss_get_vdds_dsi(void);
168struct regulator *dss_get_vdds_sdi(void); 169struct regulator *dss_get_vdds_sdi(void);
169int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
170void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
171int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
172int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
173
174struct omap_dss_device *dss_alloc_and_init_device(struct device *parent);
175int dss_add_device(struct omap_dss_device *dssdev);
176void dss_unregister_device(struct omap_dss_device *dssdev);
177void dss_unregister_child_devices(struct device *parent);
178void dss_put_device(struct omap_dss_device *dssdev);
179void dss_copy_device_pdata(struct omap_dss_device *dst,
180 const struct omap_dss_device *src);
181
182/* output */
183void dss_register_output(struct omap_dss_output *out);
184void dss_unregister_output(struct omap_dss_output *out);
185 170
186/* display */ 171/* display */
187int dss_suspend_all_devices(void); 172int dss_suspend_all_devices(void);
188int dss_resume_all_devices(void); 173int dss_resume_all_devices(void);
189void dss_disable_all_devices(void); 174void dss_disable_all_devices(void);
190 175
191int display_init_sysfs(struct platform_device *pdev, 176void dss_init_device(struct platform_device *pdev,
192 struct omap_dss_device *dssdev); 177 struct omap_dss_device *dssdev);
193void display_uninit_sysfs(struct platform_device *pdev, 178void dss_uninit_device(struct platform_device *pdev,
194 struct omap_dss_device *dssdev); 179 struct omap_dss_device *dssdev);
180bool dss_use_replication(struct omap_dss_device *dssdev,
181 enum omap_color_mode mode);
182void default_get_overlay_fifo_thresholds(enum omap_plane plane,
183 u32 fifo_size, u32 burst_size,
184 u32 *fifo_low, u32 *fifo_high);
195 185
196/* manager */ 186/* manager */
197int dss_init_overlay_managers(struct platform_device *pdev); 187int dss_init_overlay_managers(struct platform_device *pdev);
198void dss_uninit_overlay_managers(struct platform_device *pdev); 188void dss_uninit_overlay_managers(struct platform_device *pdev);
199int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 189int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
200 const struct omap_overlay_manager_info *info); 190void dss_setup_partial_planes(struct omap_dss_device *dssdev,
201int dss_mgr_check_timings(struct omap_overlay_manager *mgr, 191 u16 *x, u16 *y, u16 *w, u16 *h,
202 const struct omap_video_timings *timings); 192 bool enlarge_update_area);
203int dss_mgr_check(struct omap_overlay_manager *mgr, 193void dss_start_update(struct omap_dss_device *dssdev);
204 struct omap_overlay_manager_info *info,
205 const struct omap_video_timings *mgr_timings,
206 const struct dss_lcd_mgr_config *config,
207 struct omap_overlay_info **overlay_infos);
208
209static inline bool dss_mgr_is_lcd(enum omap_channel id)
210{
211 if (id == OMAP_DSS_CHANNEL_LCD || id == OMAP_DSS_CHANNEL_LCD2 ||
212 id == OMAP_DSS_CHANNEL_LCD3)
213 return true;
214 else
215 return false;
216}
217
218int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
219 struct platform_device *pdev);
220void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr);
221 194
222/* overlay */ 195/* overlay */
223void dss_init_overlays(struct platform_device *pdev); 196void dss_init_overlays(struct platform_device *pdev);
224void dss_uninit_overlays(struct platform_device *pdev); 197void dss_uninit_overlays(struct platform_device *pdev);
198int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
225void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 199void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
226int dss_ovl_simple_check(struct omap_overlay *ovl, 200#ifdef L4_EXAMPLE
227 const struct omap_overlay_info *info); 201void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
228int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 202#endif
229 const struct omap_video_timings *mgr_timings); 203void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
230bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
231 enum omap_color_mode mode);
232int dss_overlay_kobj_init(struct omap_overlay *ovl,
233 struct platform_device *pdev);
234void dss_overlay_kobj_uninit(struct omap_overlay *ovl);
235 204
236/* DSS */ 205/* DSS */
237int dss_init_platform_driver(void) __init; 206int dss_init_platform_driver(void);
238void dss_uninit_platform_driver(void); 207void dss_uninit_platform_driver(void);
239 208
240unsigned long dss_get_dispc_clk_rate(void); 209int dss_runtime_get(void);
241int dss_dpi_select_source(enum omap_channel channel); 210void dss_runtime_put(void);
211
212struct clk *dss_get_ick(void);
213
242void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 214void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
243enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
244const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 215const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
245void dss_dump_clocks(struct seq_file *s); 216void dss_dump_clocks(struct seq_file *s);
246 217
247#if defined(CONFIG_OMAP2_DSS_DEBUGFS) 218void dss_dump_regs(struct seq_file *s);
219#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
248void dss_debug_dump_clocks(struct seq_file *s); 220void dss_debug_dump_clocks(struct seq_file *s);
249#endif 221#endif
250 222
251int dss_get_ctx_loss_count(void); 223void dss_sdi_init(u8 datapairs);
252
253void dss_sdi_init(int datapairs);
254int dss_sdi_enable(void); 224int dss_sdi_enable(void);
255void dss_sdi_disable(void); 225void dss_sdi_disable(void);
256 226
227void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
257void dss_select_dsi_clk_source(int dsi_module, 228void dss_select_dsi_clk_source(int dsi_module,
258 enum omap_dss_clk_source clk_src); 229 enum omap_dss_clk_source clk_src);
259void dss_select_lcd_clk_source(enum omap_channel channel, 230void dss_select_lcd_clk_source(enum omap_channel channel,
@@ -268,12 +239,25 @@ void dss_set_dac_pwrdn_bgz(bool enable);
268unsigned long dss_get_dpll4_rate(void); 239unsigned long dss_get_dpll4_rate(void);
269int dss_calc_clock_rates(struct dss_clock_info *cinfo); 240int dss_calc_clock_rates(struct dss_clock_info *cinfo);
270int dss_set_clock_div(struct dss_clock_info *cinfo); 241int dss_set_clock_div(struct dss_clock_info *cinfo);
271int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, 242int dss_get_clock_div(struct dss_clock_info *cinfo);
243int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
244 struct dss_clock_info *dss_cinfo,
272 struct dispc_clock_info *dispc_cinfo); 245 struct dispc_clock_info *dispc_cinfo);
273 246
274/* SDI */ 247/* SDI */
275int sdi_init_platform_driver(void) __init; 248#ifdef CONFIG_OMAP2_DSS_SDI
276void sdi_uninit_platform_driver(void) __exit; 249int sdi_init(void);
250void sdi_exit(void);
251int sdi_init_display(struct omap_dss_device *display);
252#else
253static inline int sdi_init(void)
254{
255 return 0;
256}
257static inline void sdi_exit(void)
258{
259}
260#endif
277 261
278/* DSI */ 262/* DSI */
279#ifdef CONFIG_OMAP2_DSS_DSI 263#ifdef CONFIG_OMAP2_DSS_DSI
@@ -281,42 +265,50 @@ void sdi_uninit_platform_driver(void) __exit;
281struct dentry; 265struct dentry;
282struct file_operations; 266struct file_operations;
283 267
284int dsi_init_platform_driver(void) __init; 268int dsi_init_platform_driver(void);
285void dsi_uninit_platform_driver(void) __exit; 269void dsi_uninit_platform_driver(void);
286 270
287int dsi_runtime_get(struct platform_device *dsidev); 271int dsi_runtime_get(struct platform_device *dsidev);
288void dsi_runtime_put(struct platform_device *dsidev); 272void dsi_runtime_put(struct platform_device *dsidev);
289 273
290void dsi_dump_clocks(struct seq_file *s); 274void dsi_dump_clocks(struct seq_file *s);
275void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
276 const struct file_operations *debug_fops);
277void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
278 const struct file_operations *debug_fops);
291 279
280int dsi_init_display(struct omap_dss_device *display);
292void dsi_irq_handler(void); 281void dsi_irq_handler(void);
293u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
294
295unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); 282unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
296int dsi_pll_set_clock_div(struct platform_device *dsidev, 283int dsi_pll_set_clock_div(struct platform_device *dsidev,
297 struct dsi_clock_info *cinfo); 284 struct dsi_clock_info *cinfo);
298int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, 285int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
299 unsigned long req_pck, struct dsi_clock_info *cinfo, 286 unsigned long req_pck, struct dsi_clock_info *cinfo,
300 struct dispc_clock_info *dispc_cinfo); 287 struct dispc_clock_info *dispc_cinfo);
301int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, 288int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
302 bool enable_hsdiv); 289 bool enable_hsdiv);
303void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); 290void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
291void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
292 u32 fifo_size, u32 burst_size,
293 u32 *fifo_low, u32 *fifo_high);
304void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); 294void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
305void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); 295void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
306struct platform_device *dsi_get_dsidev_from_id(int module); 296struct platform_device *dsi_get_dsidev_from_id(int module);
307#else 297#else
308static inline int dsi_runtime_get(struct platform_device *dsidev) 298static inline int dsi_init_platform_driver(void)
309{ 299{
310 return 0; 300 return 0;
311} 301}
312static inline void dsi_runtime_put(struct platform_device *dsidev) 302static inline void dsi_uninit_platform_driver(void)
313{ 303{
314} 304}
315static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) 305static inline int dsi_runtime_get(struct platform_device *dsidev)
316{ 306{
317 WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
318 return 0; 307 return 0;
319} 308}
309static inline void dsi_runtime_put(struct platform_device *dsidev)
310{
311}
320static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) 312static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
321{ 313{
322 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); 314 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
@@ -329,7 +321,7 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
329 return -ENODEV; 321 return -ENODEV;
330} 322}
331static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, 323static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
332 unsigned long req_pck, 324 bool is_tft, unsigned long req_pck,
333 struct dsi_clock_info *dsi_cinfo, 325 struct dsi_clock_info *dsi_cinfo,
334 struct dispc_clock_info *dispc_cinfo) 326 struct dispc_clock_info *dispc_cinfo)
335{ 327{
@@ -354,122 +346,180 @@ static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
354} 346}
355static inline struct platform_device *dsi_get_dsidev_from_id(int module) 347static inline struct platform_device *dsi_get_dsidev_from_id(int module)
356{ 348{
349 WARN("%s: DSI not compiled in, returning platform device as NULL\n",
350 __func__);
357 return NULL; 351 return NULL;
358} 352}
359#endif 353#endif
360 354
361/* DPI */ 355/* DPI */
362int dpi_init_platform_driver(void) __init; 356#ifdef CONFIG_OMAP2_DSS_DPI
363void dpi_uninit_platform_driver(void) __exit; 357int dpi_init(void);
358void dpi_exit(void);
359int dpi_init_display(struct omap_dss_device *dssdev);
360#else
361static inline int dpi_init(void)
362{
363 return 0;
364}
365static inline void dpi_exit(void)
366{
367}
368#endif
364 369
365/* DISPC */ 370/* DISPC */
366int dispc_init_platform_driver(void) __init; 371int dispc_init_platform_driver(void);
367void dispc_uninit_platform_driver(void) __exit; 372void dispc_uninit_platform_driver(void);
368void dispc_dump_clocks(struct seq_file *s); 373void dispc_dump_clocks(struct seq_file *s);
374void dispc_dump_irqs(struct seq_file *s);
375void dispc_dump_regs(struct seq_file *s);
376void dispc_irq_handler(void);
377void dispc_fake_vsync_irq(void);
378
379int dispc_runtime_get(void);
380void dispc_runtime_put(void);
369 381
370void dispc_enable_sidle(void); 382void dispc_enable_sidle(void);
371void dispc_disable_sidle(void); 383void dispc_disable_sidle(void);
372 384
385void dispc_lcd_enable_signal_polarity(bool act_high);
373void dispc_lcd_enable_signal(bool enable); 386void dispc_lcd_enable_signal(bool enable);
374void dispc_pck_free_enable(bool enable); 387void dispc_pck_free_enable(bool enable);
388void dispc_enable_fifohandcheck(enum omap_channel channel, bool enable);
389
390void dispc_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
391void dispc_set_digit_size(u16 width, u16 height);
392u32 dispc_get_plane_fifo_size(enum omap_plane plane);
393void dispc_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
375void dispc_enable_fifomerge(bool enable); 394void dispc_enable_fifomerge(bool enable);
395u32 dispc_get_burst_size(enum omap_plane plane);
396void dispc_enable_cpr(enum omap_channel channel, bool enable);
397void dispc_set_cpr_coef(enum omap_channel channel,
398 struct omap_dss_cpr_coefs *coefs);
399
400void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
401void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
402void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
403void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
404void dispc_set_channel_out(enum omap_plane plane,
405 enum omap_channel channel_out);
406
376void dispc_enable_gamma_table(bool enable); 407void dispc_enable_gamma_table(bool enable);
408int dispc_setup_plane(enum omap_plane plane,
409 u32 paddr, u16 screen_width,
410 u16 pos_x, u16 pos_y,
411 u16 width, u16 height,
412 u16 out_width, u16 out_height,
413 enum omap_color_mode color_mode,
414 bool ilace,
415 enum omap_dss_rotation_type rotation_type,
416 u8 rotation, bool mirror,
417 u8 global_alpha, u8 pre_mult_alpha,
418 enum omap_channel channel,
419 u32 puv_addr);
420
421bool dispc_go_busy(enum omap_channel channel);
422void dispc_go(enum omap_channel channel);
423void dispc_enable_channel(enum omap_channel channel, bool enable);
424bool dispc_is_channel_enabled(enum omap_channel channel);
425int dispc_enable_plane(enum omap_plane plane, bool enable);
426void dispc_enable_replication(enum omap_plane plane, bool enable);
427
428void dispc_set_parallel_interface_mode(enum omap_channel channel,
429 enum omap_parallel_interface_mode mode);
430void dispc_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
431void dispc_set_lcd_display_type(enum omap_channel channel,
432 enum omap_lcd_display_type type);
377void dispc_set_loadmode(enum omap_dss_load_mode mode); 433void dispc_set_loadmode(enum omap_dss_load_mode mode);
378 434
379bool dispc_mgr_timings_ok(enum omap_channel channel, 435void dispc_set_default_color(enum omap_channel channel, u32 color);
380 const struct omap_video_timings *timings); 436u32 dispc_get_default_color(enum omap_channel channel);
437void dispc_set_trans_key(enum omap_channel ch,
438 enum omap_dss_trans_key_type type,
439 u32 trans_key);
440void dispc_get_trans_key(enum omap_channel ch,
441 enum omap_dss_trans_key_type *type,
442 u32 *trans_key);
443void dispc_enable_trans_key(enum omap_channel ch, bool enable);
444void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
445bool dispc_trans_key_enabled(enum omap_channel ch);
446bool dispc_alpha_blending_enabled(enum omap_channel ch);
447
448bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
449void dispc_set_lcd_timings(enum omap_channel channel,
450 struct omap_video_timings *timings);
381unsigned long dispc_fclk_rate(void); 451unsigned long dispc_fclk_rate(void);
382void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, 452unsigned long dispc_lclk_rate(enum omap_channel channel);
453unsigned long dispc_pclk_rate(enum omap_channel channel);
454void dispc_set_pol_freq(enum omap_channel channel,
455 enum omap_panel_config config, u8 acbi, u8 acb);
456void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
383 struct dispc_clock_info *cinfo); 457 struct dispc_clock_info *cinfo);
384int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, 458int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
385 struct dispc_clock_info *cinfo); 459 struct dispc_clock_info *cinfo);
386 460int dispc_set_clock_div(enum omap_channel channel,
387 461 struct dispc_clock_info *cinfo);
388void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); 462int dispc_get_clock_div(enum omap_channel channel,
389void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
390 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
391 bool manual_update);
392
393unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
394unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
395unsigned long dispc_core_clk_rate(void);
396void dispc_mgr_set_clock_div(enum omap_channel channel,
397 const struct dispc_clock_info *cinfo);
398int dispc_mgr_get_clock_div(enum omap_channel channel,
399 struct dispc_clock_info *cinfo); 463 struct dispc_clock_info *cinfo);
400 464
401u32 dispc_wb_get_framedone_irq(void);
402bool dispc_wb_go_busy(void);
403void dispc_wb_go(void);
404void dispc_wb_enable(bool enable);
405bool dispc_wb_is_enabled(void);
406void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
407int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
408 bool mem_to_mem, const struct omap_video_timings *timings);
409 465
410/* VENC */ 466/* VENC */
411#ifdef CONFIG_OMAP2_DSS_VENC 467#ifdef CONFIG_OMAP2_DSS_VENC
412int venc_init_platform_driver(void) __init; 468int venc_init_platform_driver(void);
413void venc_uninit_platform_driver(void) __exit; 469void venc_uninit_platform_driver(void);
414unsigned long venc_get_pixel_clock(void); 470void venc_dump_regs(struct seq_file *s);
471int venc_init_display(struct omap_dss_device *display);
415#else 472#else
416static inline unsigned long venc_get_pixel_clock(void) 473static inline int venc_init_platform_driver(void)
417{ 474{
418 WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
419 return 0; 475 return 0;
420} 476}
477static inline void venc_uninit_platform_driver(void)
478{
479}
421#endif 480#endif
422int omapdss_venc_display_enable(struct omap_dss_device *dssdev);
423void omapdss_venc_display_disable(struct omap_dss_device *dssdev);
424void omapdss_venc_set_timings(struct omap_dss_device *dssdev,
425 struct omap_video_timings *timings);
426int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
427 struct omap_video_timings *timings);
428u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev);
429int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss);
430void omapdss_venc_set_type(struct omap_dss_device *dssdev,
431 enum omap_dss_venc_type type);
432void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev,
433 bool invert_polarity);
434int venc_panel_init(void);
435void venc_panel_exit(void);
436 481
437/* HDMI */ 482/* HDMI */
438#ifdef CONFIG_OMAP4_DSS_HDMI 483#ifdef CONFIG_OMAP4_DSS_HDMI
439int hdmi_init_platform_driver(void) __init; 484int hdmi_init_platform_driver(void);
440void hdmi_uninit_platform_driver(void) __exit; 485void hdmi_uninit_platform_driver(void);
441unsigned long hdmi_get_pixel_clock(void); 486int hdmi_init_display(struct omap_dss_device *dssdev);
442#else 487#else
443static inline unsigned long hdmi_get_pixel_clock(void) 488static inline int hdmi_init_display(struct omap_dss_device *dssdev)
444{ 489{
445 WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
446 return 0; 490 return 0;
447} 491}
492static inline int hdmi_init_platform_driver(void)
493{
494 return 0;
495}
496static inline void hdmi_uninit_platform_driver(void)
497{
498}
448#endif 499#endif
449int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); 500int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev);
450void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); 501void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev);
451int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev); 502void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev);
452void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev);
453void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev,
454 struct omap_video_timings *timings);
455int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 503int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
456 struct omap_video_timings *timings); 504 struct omap_video_timings *timings);
457int omapdss_hdmi_read_edid(u8 *buf, int len);
458bool omapdss_hdmi_detect(void);
459int hdmi_panel_init(void); 505int hdmi_panel_init(void);
460void hdmi_panel_exit(void); 506void hdmi_panel_exit(void);
461#ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO
462int hdmi_audio_enable(void);
463void hdmi_audio_disable(void);
464int hdmi_audio_start(void);
465void hdmi_audio_stop(void);
466bool hdmi_mode_has_audio(void);
467int hdmi_audio_config(struct omap_dss_audio *audio);
468#endif
469 507
470/* RFBI */ 508/* RFBI */
471int rfbi_init_platform_driver(void) __init; 509#ifdef CONFIG_OMAP2_DSS_RFBI
472void rfbi_uninit_platform_driver(void) __exit; 510int rfbi_init_platform_driver(void);
511void rfbi_uninit_platform_driver(void);
512void rfbi_dump_regs(struct seq_file *s);
513int rfbi_init_display(struct omap_dss_device *display);
514#else
515static inline int rfbi_init_platform_driver(void)
516{
517 return 0;
518}
519static inline void rfbi_uninit_platform_driver(void)
520{
521}
522#endif
473 523
474 524
475#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 525#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index 18688c12e30..b415c4ee621 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -18,12 +18,12 @@
18 */ 18 */
19 19
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/types.h> 21#include <linux/types.h>
23#include <linux/err.h> 22#include <linux/err.h>
24#include <linux/slab.h> 23#include <linux/slab.h>
25 24
26#include <video/omapdss.h> 25#include <video/omapdss.h>
26#include <plat/cpu.h>
27 27
28#include "dss.h" 28#include "dss.h"
29#include "dss_features.h" 29#include "dss_features.h"
@@ -41,21 +41,15 @@ struct omap_dss_features {
41 const struct dss_reg_field *reg_fields; 41 const struct dss_reg_field *reg_fields;
42 const int num_reg_fields; 42 const int num_reg_fields;
43 43
44 const enum dss_feat_id *features; 44 const u32 has_feature;
45 const int num_features;
46 45
47 const int num_mgrs; 46 const int num_mgrs;
48 const int num_ovls; 47 const int num_ovls;
49 const int num_wbs;
50 const enum omap_display_type *supported_displays; 48 const enum omap_display_type *supported_displays;
51 const enum omap_dss_output_id *supported_outputs;
52 const enum omap_color_mode *supported_color_modes; 49 const enum omap_color_mode *supported_color_modes;
53 const enum omap_overlay_caps *overlay_caps;
54 const char * const *clksrc_names; 50 const char * const *clksrc_names;
55 const struct dss_param_range *dss_params; 51 const struct dss_param_range *dss_params;
56 52
57 const enum omap_dss_rotation_type supported_rotation_types;
58
59 const u32 buffer_size_unit; 53 const u32 buffer_size_unit;
60 const u32 burst_size_unit; 54 const u32 burst_size_unit;
61}; 55};
@@ -108,21 +102,6 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
108 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, 102 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
109}; 103};
110 104
111static const struct dss_reg_field omap5_dss_reg_fields[] = {
112 [FEAT_REG_FIRHINC] = { 12, 0 },
113 [FEAT_REG_FIRVINC] = { 28, 16 },
114 [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 },
115 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 },
116 [FEAT_REG_FIFOSIZE] = { 15, 0 },
117 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
118 [FEAT_REG_VERTICALACCU] = { 26, 16 },
119 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
120 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
121 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
122 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
123 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
124};
125
126static const enum omap_display_type omap2_dss_supported_displays[] = { 105static const enum omap_display_type omap2_dss_supported_displays[] = {
127 /* OMAP_DSS_CHANNEL_LCD */ 106 /* OMAP_DSS_CHANNEL_LCD */
128 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, 107 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
@@ -161,76 +140,6 @@ static const enum omap_display_type omap4_dss_supported_displays[] = {
161 OMAP_DISPLAY_TYPE_DSI, 140 OMAP_DISPLAY_TYPE_DSI,
162}; 141};
163 142
164static const enum omap_display_type omap5_dss_supported_displays[] = {
165 /* OMAP_DSS_CHANNEL_LCD */
166 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
167 OMAP_DISPLAY_TYPE_DSI,
168
169 /* OMAP_DSS_CHANNEL_DIGIT */
170 OMAP_DISPLAY_TYPE_HDMI | OMAP_DISPLAY_TYPE_DPI,
171
172 /* OMAP_DSS_CHANNEL_LCD2 */
173 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
174 OMAP_DISPLAY_TYPE_DSI,
175};
176
177static const enum omap_dss_output_id omap2_dss_supported_outputs[] = {
178 /* OMAP_DSS_CHANNEL_LCD */
179 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
180
181 /* OMAP_DSS_CHANNEL_DIGIT */
182 OMAP_DSS_OUTPUT_VENC,
183};
184
185static const enum omap_dss_output_id omap3430_dss_supported_outputs[] = {
186 /* OMAP_DSS_CHANNEL_LCD */
187 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
188 OMAP_DSS_OUTPUT_SDI | OMAP_DSS_OUTPUT_DSI1,
189
190 /* OMAP_DSS_CHANNEL_DIGIT */
191 OMAP_DSS_OUTPUT_VENC,
192};
193
194static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
195 /* OMAP_DSS_CHANNEL_LCD */
196 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
197 OMAP_DSS_OUTPUT_DSI1,
198
199 /* OMAP_DSS_CHANNEL_DIGIT */
200 OMAP_DSS_OUTPUT_VENC,
201};
202
203static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
204 /* OMAP_DSS_CHANNEL_LCD */
205 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
206 OMAP_DSS_OUTPUT_DSI1,
207
208 /* OMAP_DSS_CHANNEL_DIGIT */
209 OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
210 OMAP_DSS_OUTPUT_DPI,
211
212 /* OMAP_DSS_CHANNEL_LCD2 */
213 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
214 OMAP_DSS_OUTPUT_DSI2,
215};
216
217static const enum omap_dss_output_id omap5_dss_supported_outputs[] = {
218 /* OMAP_DSS_CHANNEL_LCD */
219 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
220 OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2,
221
222 /* OMAP_DSS_CHANNEL_DIGIT */
223 OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI,
224
225 /* OMAP_DSS_CHANNEL_LCD2 */
226 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
227 OMAP_DSS_OUTPUT_DSI1,
228
229 /* OMAP_DSS_CHANNEL_LCD3 */
230 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
231 OMAP_DSS_OUTPUT_DSI2,
232};
233
234static const enum omap_color_mode omap2_dss_supported_color_modes[] = { 143static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
235 /* OMAP_DSS_GFX */ 144 /* OMAP_DSS_GFX */
236 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 | 145 OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
@@ -279,8 +188,7 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
279 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U | 188 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
280 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 | 189 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
281 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 | 190 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
282 OMAP_DSS_COLOR_ARGB16_1555 | OMAP_DSS_COLOR_RGBX16 | 191 OMAP_DSS_COLOR_ARGB16_1555,
283 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_XRGB16_1555,
284 192
285 /* OMAP_DSS_VIDEO1 */ 193 /* OMAP_DSS_VIDEO1 */
286 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U | 194 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
@@ -301,90 +209,6 @@ static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
301 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 | 209 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
302 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 | 210 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
303 OMAP_DSS_COLOR_RGBX32, 211 OMAP_DSS_COLOR_RGBX32,
304
305 /* OMAP_DSS_VIDEO3 */
306 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
307 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
308 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
309 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
310 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
311 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
312 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
313 OMAP_DSS_COLOR_RGBX32,
314
315 /* OMAP_DSS_WB */
316 OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
317 OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
318 OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
319 OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
320 OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
321 OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
322 OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
323 OMAP_DSS_COLOR_RGBX32,
324};
325
326static const enum omap_overlay_caps omap2_dss_overlay_caps[] = {
327 /* OMAP_DSS_GFX */
328 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
329
330 /* OMAP_DSS_VIDEO1 */
331 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
332 OMAP_DSS_OVL_CAP_REPLICATION,
333
334 /* OMAP_DSS_VIDEO2 */
335 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
336 OMAP_DSS_OVL_CAP_REPLICATION,
337};
338
339static const enum omap_overlay_caps omap3430_dss_overlay_caps[] = {
340 /* OMAP_DSS_GFX */
341 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_POS |
342 OMAP_DSS_OVL_CAP_REPLICATION,
343
344 /* OMAP_DSS_VIDEO1 */
345 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
346 OMAP_DSS_OVL_CAP_REPLICATION,
347
348 /* OMAP_DSS_VIDEO2 */
349 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
350 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
351};
352
353static const enum omap_overlay_caps omap3630_dss_overlay_caps[] = {
354 /* OMAP_DSS_GFX */
355 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
356 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
357
358 /* OMAP_DSS_VIDEO1 */
359 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_POS |
360 OMAP_DSS_OVL_CAP_REPLICATION,
361
362 /* OMAP_DSS_VIDEO2 */
363 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
364 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_POS |
365 OMAP_DSS_OVL_CAP_REPLICATION,
366};
367
368static const enum omap_overlay_caps omap4_dss_overlay_caps[] = {
369 /* OMAP_DSS_GFX */
370 OMAP_DSS_OVL_CAP_GLOBAL_ALPHA | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA |
371 OMAP_DSS_OVL_CAP_ZORDER | OMAP_DSS_OVL_CAP_POS |
372 OMAP_DSS_OVL_CAP_REPLICATION,
373
374 /* OMAP_DSS_VIDEO1 */
375 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
376 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
377 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
378
379 /* OMAP_DSS_VIDEO2 */
380 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
381 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
382 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
383
384 /* OMAP_DSS_VIDEO3 */
385 OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_GLOBAL_ALPHA |
386 OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA | OMAP_DSS_OVL_CAP_ZORDER |
387 OMAP_DSS_OVL_CAP_POS | OMAP_DSS_OVL_CAP_REPLICATION,
388}; 212};
389 213
390static const char * const omap2_dss_clk_source_names[] = { 214static const char * const omap2_dss_clk_source_names[] = {
@@ -407,213 +231,34 @@ static const char * const omap4_dss_clk_source_names[] = {
407 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2", 231 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
408}; 232};
409 233
410static const char * const omap5_dss_clk_source_names[] = {
411 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DPLL_DSI1_A_CLK1",
412 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DPLL_DSI1_A_CLK2",
413 [OMAP_DSS_CLK_SRC_FCK] = "DSS_CLK",
414 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DPLL_DSI1_C_CLK1",
415 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DPLL_DSI1_C_CLK2",
416};
417
418static const struct dss_param_range omap2_dss_param_range[] = { 234static const struct dss_param_range omap2_dss_param_range[] = {
419 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 235 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
420 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
421 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, 236 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
422 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, 237 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
423 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, 238 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
424 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, 239 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 },
425 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, 240 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
426 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, 241 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
427 [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
428 /*
429 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
430 * scaler cannot scale a image with width more than 768.
431 */
432 [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
433}; 242};
434 243
435static const struct dss_param_range omap3_dss_param_range[] = { 244static const struct dss_param_range omap3_dss_param_range[] = {
436 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 245 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
437 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
438 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, 246 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
439 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, 247 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
440 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, 248 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
441 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, 249 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
442 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 250 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
443 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 251 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
444 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
445 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
446 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
447}; 252};
448 253
449static const struct dss_param_range omap4_dss_param_range[] = { 254static const struct dss_param_range omap4_dss_param_range[] = {
450 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, 255 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
451 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
452 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
453 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
454 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
455 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
456 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
457 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
458 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
459 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
460 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
461};
462
463static const struct dss_param_range omap5_dss_param_range[] = {
464 [FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
465 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
466 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, 256 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
467 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, 257 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
468 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, 258 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
469 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, 259 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
470 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 260 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
471 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 261 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
472 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
473 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
474 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
475};
476
477static const enum dss_feat_id omap2_dss_feat_list[] = {
478 FEAT_LCDENABLEPOL,
479 FEAT_LCDENABLESIGNAL,
480 FEAT_PCKFREEENABLE,
481 FEAT_FUNCGATED,
482 FEAT_ROWREPEATENABLE,
483 FEAT_RESIZECONF,
484};
485
486static const enum dss_feat_id omap3430_dss_feat_list[] = {
487 FEAT_LCDENABLEPOL,
488 FEAT_LCDENABLESIGNAL,
489 FEAT_PCKFREEENABLE,
490 FEAT_FUNCGATED,
491 FEAT_LINEBUFFERSPLIT,
492 FEAT_ROWREPEATENABLE,
493 FEAT_RESIZECONF,
494 FEAT_DSI_PLL_FREQSEL,
495 FEAT_DSI_REVERSE_TXCLKESC,
496 FEAT_VENC_REQUIRES_TV_DAC_CLK,
497 FEAT_CPR,
498 FEAT_PRELOAD,
499 FEAT_FIR_COEF_V,
500 FEAT_ALPHA_FIXED_ZORDER,
501 FEAT_FIFO_MERGE,
502 FEAT_OMAP3_DSI_FIFO_BUG,
503 FEAT_DPI_USES_VDDS_DSI,
504};
505
506static const enum dss_feat_id am35xx_dss_feat_list[] = {
507 FEAT_LCDENABLEPOL,
508 FEAT_LCDENABLESIGNAL,
509 FEAT_PCKFREEENABLE,
510 FEAT_FUNCGATED,
511 FEAT_LINEBUFFERSPLIT,
512 FEAT_ROWREPEATENABLE,
513 FEAT_RESIZECONF,
514 FEAT_DSI_PLL_FREQSEL,
515 FEAT_DSI_REVERSE_TXCLKESC,
516 FEAT_VENC_REQUIRES_TV_DAC_CLK,
517 FEAT_CPR,
518 FEAT_PRELOAD,
519 FEAT_FIR_COEF_V,
520 FEAT_ALPHA_FIXED_ZORDER,
521 FEAT_FIFO_MERGE,
522 FEAT_OMAP3_DSI_FIFO_BUG,
523};
524
525static const enum dss_feat_id omap3630_dss_feat_list[] = {
526 FEAT_LCDENABLEPOL,
527 FEAT_LCDENABLESIGNAL,
528 FEAT_PCKFREEENABLE,
529 FEAT_FUNCGATED,
530 FEAT_LINEBUFFERSPLIT,
531 FEAT_ROWREPEATENABLE,
532 FEAT_RESIZECONF,
533 FEAT_DSI_PLL_PWR_BUG,
534 FEAT_DSI_PLL_FREQSEL,
535 FEAT_CPR,
536 FEAT_PRELOAD,
537 FEAT_FIR_COEF_V,
538 FEAT_ALPHA_FIXED_ZORDER,
539 FEAT_FIFO_MERGE,
540 FEAT_OMAP3_DSI_FIFO_BUG,
541};
542
543static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
544 FEAT_MGR_LCD2,
545 FEAT_CORE_CLK_DIV,
546 FEAT_LCD_CLK_SRC,
547 FEAT_DSI_DCS_CMD_CONFIG_VC,
548 FEAT_DSI_VC_OCP_WIDTH,
549 FEAT_DSI_GNQ,
550 FEAT_HANDLE_UV_SEPARATE,
551 FEAT_ATTR2,
552 FEAT_CPR,
553 FEAT_PRELOAD,
554 FEAT_FIR_COEF_V,
555 FEAT_ALPHA_FREE_ZORDER,
556 FEAT_FIFO_MERGE,
557 FEAT_BURST_2D,
558};
559
560static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
561 FEAT_MGR_LCD2,
562 FEAT_CORE_CLK_DIV,
563 FEAT_LCD_CLK_SRC,
564 FEAT_DSI_DCS_CMD_CONFIG_VC,
565 FEAT_DSI_VC_OCP_WIDTH,
566 FEAT_DSI_GNQ,
567 FEAT_HDMI_CTS_SWMODE,
568 FEAT_HANDLE_UV_SEPARATE,
569 FEAT_ATTR2,
570 FEAT_CPR,
571 FEAT_PRELOAD,
572 FEAT_FIR_COEF_V,
573 FEAT_ALPHA_FREE_ZORDER,
574 FEAT_FIFO_MERGE,
575 FEAT_BURST_2D,
576};
577
578static const enum dss_feat_id omap4_dss_feat_list[] = {
579 FEAT_MGR_LCD2,
580 FEAT_CORE_CLK_DIV,
581 FEAT_LCD_CLK_SRC,
582 FEAT_DSI_DCS_CMD_CONFIG_VC,
583 FEAT_DSI_VC_OCP_WIDTH,
584 FEAT_DSI_GNQ,
585 FEAT_HDMI_CTS_SWMODE,
586 FEAT_HDMI_AUDIO_USE_MCLK,
587 FEAT_HANDLE_UV_SEPARATE,
588 FEAT_ATTR2,
589 FEAT_CPR,
590 FEAT_PRELOAD,
591 FEAT_FIR_COEF_V,
592 FEAT_ALPHA_FREE_ZORDER,
593 FEAT_FIFO_MERGE,
594 FEAT_BURST_2D,
595};
596
597static const enum dss_feat_id omap5_dss_feat_list[] = {
598 FEAT_MGR_LCD2,
599 FEAT_CORE_CLK_DIV,
600 FEAT_LCD_CLK_SRC,
601 FEAT_DSI_DCS_CMD_CONFIG_VC,
602 FEAT_DSI_VC_OCP_WIDTH,
603 FEAT_DSI_GNQ,
604 FEAT_HDMI_CTS_SWMODE,
605 FEAT_HDMI_AUDIO_USE_MCLK,
606 FEAT_HANDLE_UV_SEPARATE,
607 FEAT_ATTR2,
608 FEAT_CPR,
609 FEAT_PRELOAD,
610 FEAT_FIR_COEF_V,
611 FEAT_ALPHA_FREE_ZORDER,
612 FEAT_FIFO_MERGE,
613 FEAT_BURST_2D,
614 FEAT_DSI_PLL_SELFREQDCO,
615 FEAT_DSI_PLL_REFSEL,
616 FEAT_DSI_PHY_DCC,
617}; 262};
618 263
619/* OMAP2 DSS Features */ 264/* OMAP2 DSS Features */
@@ -621,18 +266,17 @@ static const struct omap_dss_features omap2_dss_features = {
621 .reg_fields = omap2_dss_reg_fields, 266 .reg_fields = omap2_dss_reg_fields,
622 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields), 267 .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
623 268
624 .features = omap2_dss_feat_list, 269 .has_feature =
625 .num_features = ARRAY_SIZE(omap2_dss_feat_list), 270 FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL |
271 FEAT_PCKFREEENABLE | FEAT_FUNCGATED |
272 FEAT_ROWREPEATENABLE | FEAT_RESIZECONF,
626 273
627 .num_mgrs = 2, 274 .num_mgrs = 2,
628 .num_ovls = 3, 275 .num_ovls = 3,
629 .supported_displays = omap2_dss_supported_displays, 276 .supported_displays = omap2_dss_supported_displays,
630 .supported_outputs = omap2_dss_supported_outputs,
631 .supported_color_modes = omap2_dss_supported_color_modes, 277 .supported_color_modes = omap2_dss_supported_color_modes,
632 .overlay_caps = omap2_dss_overlay_caps,
633 .clksrc_names = omap2_dss_clk_source_names, 278 .clksrc_names = omap2_dss_clk_source_names,
634 .dss_params = omap2_dss_param_range, 279 .dss_params = omap2_dss_param_range,
635 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
636 .buffer_size_unit = 1, 280 .buffer_size_unit = 1,
637 .burst_size_unit = 8, 281 .burst_size_unit = 8,
638}; 282};
@@ -642,42 +286,21 @@ static const struct omap_dss_features omap3430_dss_features = {
642 .reg_fields = omap3_dss_reg_fields, 286 .reg_fields = omap3_dss_reg_fields,
643 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 287 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
644 288
645 .features = omap3430_dss_feat_list, 289 .has_feature =
646 .num_features = ARRAY_SIZE(omap3430_dss_feat_list), 290 FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
647 291 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
648 .num_mgrs = 2, 292 FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
649 .num_ovls = 3, 293 FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
650 .supported_displays = omap3430_dss_supported_displays, 294 FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC |
651 .supported_outputs = omap3430_dss_supported_outputs, 295 FEAT_VENC_REQUIRES_TV_DAC_CLK | FEAT_CPR | FEAT_PRELOAD |
652 .supported_color_modes = omap3_dss_supported_color_modes, 296 FEAT_FIR_COEF_V,
653 .overlay_caps = omap3430_dss_overlay_caps,
654 .clksrc_names = omap3_dss_clk_source_names,
655 .dss_params = omap3_dss_param_range,
656 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
657 .buffer_size_unit = 1,
658 .burst_size_unit = 8,
659};
660
661/*
662 * AM35xx DSS Features. This is basically OMAP3 DSS Features without the
663 * vdds_dsi regulator.
664 */
665static const struct omap_dss_features am35xx_dss_features = {
666 .reg_fields = omap3_dss_reg_fields,
667 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
668
669 .features = am35xx_dss_feat_list,
670 .num_features = ARRAY_SIZE(am35xx_dss_feat_list),
671 297
672 .num_mgrs = 2, 298 .num_mgrs = 2,
673 .num_ovls = 3, 299 .num_ovls = 3,
674 .supported_displays = omap3430_dss_supported_displays, 300 .supported_displays = omap3430_dss_supported_displays,
675 .supported_outputs = omap3430_dss_supported_outputs,
676 .supported_color_modes = omap3_dss_supported_color_modes, 301 .supported_color_modes = omap3_dss_supported_color_modes,
677 .overlay_caps = omap3430_dss_overlay_caps,
678 .clksrc_names = omap3_dss_clk_source_names, 302 .clksrc_names = omap3_dss_clk_source_names,
679 .dss_params = omap3_dss_param_range, 303 .dss_params = omap3_dss_param_range,
680 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
681 .buffer_size_unit = 1, 304 .buffer_size_unit = 1,
682 .burst_size_unit = 8, 305 .burst_size_unit = 8,
683}; 306};
@@ -686,18 +309,21 @@ static const struct omap_dss_features omap3630_dss_features = {
686 .reg_fields = omap3_dss_reg_fields, 309 .reg_fields = omap3_dss_reg_fields,
687 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 310 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
688 311
689 .features = omap3630_dss_feat_list, 312 .has_feature =
690 .num_features = ARRAY_SIZE(omap3630_dss_feat_list), 313 FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
314 FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
315 FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
316 FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
317 FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
318 FEAT_DSI_PLL_FREQSEL | FEAT_CPR | FEAT_PRELOAD |
319 FEAT_FIR_COEF_V,
691 320
692 .num_mgrs = 2, 321 .num_mgrs = 2,
693 .num_ovls = 3, 322 .num_ovls = 3,
694 .supported_displays = omap3630_dss_supported_displays, 323 .supported_displays = omap3630_dss_supported_displays,
695 .supported_outputs = omap3630_dss_supported_outputs,
696 .supported_color_modes = omap3_dss_supported_color_modes, 324 .supported_color_modes = omap3_dss_supported_color_modes,
697 .overlay_caps = omap3630_dss_overlay_caps,
698 .clksrc_names = omap3_dss_clk_source_names, 325 .clksrc_names = omap3_dss_clk_source_names,
699 .dss_params = omap3_dss_param_range, 326 .dss_params = omap3_dss_param_range,
700 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
701 .buffer_size_unit = 1, 327 .buffer_size_unit = 1,
702 .burst_size_unit = 8, 328 .burst_size_unit = 8,
703}; 329};
@@ -708,41 +334,20 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
708 .reg_fields = omap4_dss_reg_fields, 334 .reg_fields = omap4_dss_reg_fields,
709 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), 335 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
710 336
711 .features = omap4430_es1_0_dss_feat_list, 337 .has_feature =
712 .num_features = ARRAY_SIZE(omap4430_es1_0_dss_feat_list), 338 FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
713 339 FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
714 .num_mgrs = 3, 340 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
715 .num_ovls = 4, 341 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
716 .num_wbs = 1, 342 FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 |
717 .supported_displays = omap4_dss_supported_displays, 343 FEAT_CPR | FEAT_PRELOAD | FEAT_FIR_COEF_V,
718 .supported_outputs = omap4_dss_supported_outputs,
719 .supported_color_modes = omap4_dss_supported_color_modes,
720 .overlay_caps = omap4_dss_overlay_caps,
721 .clksrc_names = omap4_dss_clk_source_names,
722 .dss_params = omap4_dss_param_range,
723 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
724 .buffer_size_unit = 16,
725 .burst_size_unit = 16,
726};
727
728/* For OMAP4430 ES 2.0, 2.1 and 2.2 revisions */
729static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
730 .reg_fields = omap4_dss_reg_fields,
731 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
732
733 .features = omap4430_es2_0_1_2_dss_feat_list,
734 .num_features = ARRAY_SIZE(omap4430_es2_0_1_2_dss_feat_list),
735 344
736 .num_mgrs = 3, 345 .num_mgrs = 3,
737 .num_ovls = 4, 346 .num_ovls = 3,
738 .num_wbs = 1,
739 .supported_displays = omap4_dss_supported_displays, 347 .supported_displays = omap4_dss_supported_displays,
740 .supported_outputs = omap4_dss_supported_outputs,
741 .supported_color_modes = omap4_dss_supported_color_modes, 348 .supported_color_modes = omap4_dss_supported_color_modes,
742 .overlay_caps = omap4_dss_overlay_caps,
743 .clksrc_names = omap4_dss_clk_source_names, 349 .clksrc_names = omap4_dss_clk_source_names,
744 .dss_params = omap4_dss_param_range, 350 .dss_params = omap4_dss_param_range,
745 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
746 .buffer_size_unit = 16, 351 .buffer_size_unit = 16,
747 .burst_size_unit = 16, 352 .burst_size_unit = 16,
748}; 353};
@@ -752,106 +357,35 @@ static const struct omap_dss_features omap4_dss_features = {
752 .reg_fields = omap4_dss_reg_fields, 357 .reg_fields = omap4_dss_reg_fields,
753 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), 358 .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
754 359
755 .features = omap4_dss_feat_list, 360 .has_feature =
756 .num_features = ARRAY_SIZE(omap4_dss_feat_list), 361 FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
362 FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
363 FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
364 FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
365 FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
366 FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
367 FEAT_PRELOAD | FEAT_FIR_COEF_V,
757 368
758 .num_mgrs = 3, 369 .num_mgrs = 3,
759 .num_ovls = 4, 370 .num_ovls = 3,
760 .num_wbs = 1,
761 .supported_displays = omap4_dss_supported_displays, 371 .supported_displays = omap4_dss_supported_displays,
762 .supported_outputs = omap4_dss_supported_outputs,
763 .supported_color_modes = omap4_dss_supported_color_modes, 372 .supported_color_modes = omap4_dss_supported_color_modes,
764 .overlay_caps = omap4_dss_overlay_caps,
765 .clksrc_names = omap4_dss_clk_source_names, 373 .clksrc_names = omap4_dss_clk_source_names,
766 .dss_params = omap4_dss_param_range, 374 .dss_params = omap4_dss_param_range,
767 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
768 .buffer_size_unit = 16, 375 .buffer_size_unit = 16,
769 .burst_size_unit = 16, 376 .burst_size_unit = 16,
770}; 377};
771 378
772/* OMAP5 DSS Features */
773static const struct omap_dss_features omap5_dss_features = {
774 .reg_fields = omap5_dss_reg_fields,
775 .num_reg_fields = ARRAY_SIZE(omap5_dss_reg_fields),
776
777 .features = omap5_dss_feat_list,
778 .num_features = ARRAY_SIZE(omap5_dss_feat_list),
779
780 .num_mgrs = 3,
781 .num_ovls = 4,
782 .supported_displays = omap5_dss_supported_displays,
783 .supported_outputs = omap5_dss_supported_outputs,
784 .supported_color_modes = omap4_dss_supported_color_modes,
785 .overlay_caps = omap4_dss_overlay_caps,
786 .clksrc_names = omap5_dss_clk_source_names,
787 .dss_params = omap5_dss_param_range,
788 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
789 .buffer_size_unit = 16,
790 .burst_size_unit = 16,
791};
792
793#if defined(CONFIG_OMAP4_DSS_HDMI)
794/* HDMI OMAP4 Functions*/
795static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
796
797 .video_configure = ti_hdmi_4xxx_basic_configure,
798 .phy_enable = ti_hdmi_4xxx_phy_enable,
799 .phy_disable = ti_hdmi_4xxx_phy_disable,
800 .read_edid = ti_hdmi_4xxx_read_edid,
801 .detect = ti_hdmi_4xxx_detect,
802 .pll_enable = ti_hdmi_4xxx_pll_enable,
803 .pll_disable = ti_hdmi_4xxx_pll_disable,
804 .video_enable = ti_hdmi_4xxx_wp_video_start,
805 .video_disable = ti_hdmi_4xxx_wp_video_stop,
806 .dump_wrapper = ti_hdmi_4xxx_wp_dump,
807 .dump_core = ti_hdmi_4xxx_core_dump,
808 .dump_pll = ti_hdmi_4xxx_pll_dump,
809 .dump_phy = ti_hdmi_4xxx_phy_dump,
810#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
811 .audio_enable = ti_hdmi_4xxx_wp_audio_enable,
812 .audio_disable = ti_hdmi_4xxx_wp_audio_disable,
813 .audio_start = ti_hdmi_4xxx_audio_start,
814 .audio_stop = ti_hdmi_4xxx_audio_stop,
815 .audio_config = ti_hdmi_4xxx_audio_config,
816 .audio_get_dma_port = ti_hdmi_4xxx_audio_get_dma_port,
817#endif
818
819};
820
821void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
822 enum omapdss_version version)
823{
824 switch (version) {
825 case OMAPDSS_VER_OMAP4430_ES1:
826 case OMAPDSS_VER_OMAP4430_ES2:
827 case OMAPDSS_VER_OMAP4:
828 ip_data->ops = &omap4_hdmi_functions;
829 break;
830 default:
831 ip_data->ops = NULL;
832 }
833
834 WARN_ON(ip_data->ops == NULL);
835}
836#endif
837
838/* Functions returning values related to a DSS feature */ 379/* Functions returning values related to a DSS feature */
839int dss_feat_get_num_mgrs(void) 380int dss_feat_get_num_mgrs(void)
840{ 381{
841 return omap_current_dss_features->num_mgrs; 382 return omap_current_dss_features->num_mgrs;
842} 383}
843EXPORT_SYMBOL(dss_feat_get_num_mgrs);
844 384
845int dss_feat_get_num_ovls(void) 385int dss_feat_get_num_ovls(void)
846{ 386{
847 return omap_current_dss_features->num_ovls; 387 return omap_current_dss_features->num_ovls;
848} 388}
849EXPORT_SYMBOL(dss_feat_get_num_ovls);
850
851int dss_feat_get_num_wbs(void)
852{
853 return omap_current_dss_features->num_wbs;
854}
855 389
856unsigned long dss_feat_get_param_min(enum dss_range_param param) 390unsigned long dss_feat_get_param_min(enum dss_range_param param)
857{ 391{
@@ -867,24 +401,11 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
867{ 401{
868 return omap_current_dss_features->supported_displays[channel]; 402 return omap_current_dss_features->supported_displays[channel];
869} 403}
870EXPORT_SYMBOL(dss_feat_get_supported_displays);
871
872enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel)
873{
874 return omap_current_dss_features->supported_outputs[channel];
875}
876EXPORT_SYMBOL(dss_feat_get_supported_outputs);
877 404
878enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) 405enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
879{ 406{
880 return omap_current_dss_features->supported_color_modes[plane]; 407 return omap_current_dss_features->supported_color_modes[plane];
881} 408}
882EXPORT_SYMBOL(dss_feat_get_supported_color_modes);
883
884enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane)
885{
886 return omap_current_dss_features->overlay_caps[plane];
887}
888 409
889bool dss_feat_color_mode_supported(enum omap_plane plane, 410bool dss_feat_color_mode_supported(enum omap_plane plane,
890 enum omap_color_mode color_mode) 411 enum omap_color_mode color_mode)
@@ -911,16 +432,7 @@ u32 dss_feat_get_burst_size_unit(void)
911/* DSS has_feature check */ 432/* DSS has_feature check */
912bool dss_has_feature(enum dss_feat_id id) 433bool dss_has_feature(enum dss_feat_id id)
913{ 434{
914 int i; 435 return omap_current_dss_features->has_feature & id;
915 const enum dss_feat_id *features = omap_current_dss_features->features;
916 const int num_features = omap_current_dss_features->num_features;
917
918 for (i = 0; i < num_features; i++) {
919 if (features[i] == id)
920 return true;
921 }
922
923 return false;
924} 436}
925 437
926void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end) 438void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
@@ -932,49 +444,18 @@ void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
932 *end = omap_current_dss_features->reg_fields[id].end; 444 *end = omap_current_dss_features->reg_fields[id].end;
933} 445}
934 446
935bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type) 447void dss_features_init(void)
936{
937 return omap_current_dss_features->supported_rotation_types & rot_type;
938}
939
940void dss_features_init(enum omapdss_version version)
941{ 448{
942 switch (version) { 449 if (cpu_is_omap24xx())
943 case OMAPDSS_VER_OMAP24xx:
944 omap_current_dss_features = &omap2_dss_features; 450 omap_current_dss_features = &omap2_dss_features;
945 break; 451 else if (cpu_is_omap3630())
946
947 case OMAPDSS_VER_OMAP34xx_ES1:
948 case OMAPDSS_VER_OMAP34xx_ES3:
949 omap_current_dss_features = &omap3430_dss_features;
950 break;
951
952 case OMAPDSS_VER_OMAP3630:
953 omap_current_dss_features = &omap3630_dss_features; 452 omap_current_dss_features = &omap3630_dss_features;
954 break; 453 else if (cpu_is_omap34xx())
955 454 omap_current_dss_features = &omap3430_dss_features;
956 case OMAPDSS_VER_OMAP4430_ES1: 455 else if (omap_rev() == OMAP4430_REV_ES1_0)
957 omap_current_dss_features = &omap4430_es1_0_dss_features; 456 omap_current_dss_features = &omap4430_es1_0_dss_features;
958 break; 457 else if (cpu_is_omap44xx())
959
960 case OMAPDSS_VER_OMAP4430_ES2:
961 omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
962 break;
963
964 case OMAPDSS_VER_OMAP4:
965 omap_current_dss_features = &omap4_dss_features; 458 omap_current_dss_features = &omap4_dss_features;
966 break; 459 else
967
968 case OMAPDSS_VER_OMAP5:
969 omap_current_dss_features = &omap5_dss_features;
970 break;
971
972 case OMAPDSS_VER_AM35xx:
973 omap_current_dss_features = &am35xx_dss_features;
974 break;
975
976 default:
977 DSSWARN("Unsupported OMAP version"); 460 DSSWARN("Unsupported OMAP version");
978 break;
979 }
980} 461}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 489b9bec4a6..b7398cbcda5 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -20,54 +20,41 @@
20#ifndef __OMAP2_DSS_FEATURES_H 20#ifndef __OMAP2_DSS_FEATURES_H
21#define __OMAP2_DSS_FEATURES_H 21#define __OMAP2_DSS_FEATURES_H
22 22
23#if defined(CONFIG_OMAP4_DSS_HDMI) 23#define MAX_DSS_MANAGERS 3
24#include "ti_hdmi.h" 24#define MAX_DSS_OVERLAYS 3
25#endif 25#define MAX_DSS_LCD_MANAGERS 2
26
27#define MAX_DSS_MANAGERS 4
28#define MAX_DSS_OVERLAYS 4
29#define MAX_DSS_LCD_MANAGERS 3
30#define MAX_NUM_DSI 2 26#define MAX_NUM_DSI 2
31 27
32/* DSS has feature id */ 28/* DSS has feature id */
33enum dss_feat_id { 29enum dss_feat_id {
34 FEAT_LCDENABLEPOL, 30 FEAT_GLOBAL_ALPHA = 1 << 0,
35 FEAT_LCDENABLESIGNAL, 31 FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
36 FEAT_PCKFREEENABLE, 32 FEAT_PRE_MULT_ALPHA = 1 << 2,
37 FEAT_FUNCGATED, 33 FEAT_LCDENABLEPOL = 1 << 3,
38 FEAT_MGR_LCD2, 34 FEAT_LCDENABLESIGNAL = 1 << 4,
39 FEAT_MGR_LCD3, 35 FEAT_PCKFREEENABLE = 1 << 5,
40 FEAT_LINEBUFFERSPLIT, 36 FEAT_FUNCGATED = 1 << 6,
41 FEAT_ROWREPEATENABLE, 37 FEAT_MGR_LCD2 = 1 << 7,
42 FEAT_RESIZECONF, 38 FEAT_LINEBUFFERSPLIT = 1 << 8,
39 FEAT_ROWREPEATENABLE = 1 << 9,
40 FEAT_RESIZECONF = 1 << 10,
43 /* Independent core clk divider */ 41 /* Independent core clk divider */
44 FEAT_CORE_CLK_DIV, 42 FEAT_CORE_CLK_DIV = 1 << 11,
45 FEAT_LCD_CLK_SRC, 43 FEAT_LCD_CLK_SRC = 1 << 12,
46 /* DSI-PLL power command 0x3 is not working */ 44 /* DSI-PLL power command 0x3 is not working */
47 FEAT_DSI_PLL_PWR_BUG, 45 FEAT_DSI_PLL_PWR_BUG = 1 << 13,
48 FEAT_DSI_PLL_FREQSEL, 46 FEAT_DSI_PLL_FREQSEL = 1 << 14,
49 FEAT_DSI_DCS_CMD_CONFIG_VC, 47 FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15,
50 FEAT_DSI_VC_OCP_WIDTH, 48 FEAT_DSI_VC_OCP_WIDTH = 1 << 16,
51 FEAT_DSI_REVERSE_TXCLKESC, 49 FEAT_DSI_REVERSE_TXCLKESC = 1 << 17,
52 FEAT_DSI_GNQ, 50 FEAT_DSI_GNQ = 1 << 18,
53 FEAT_DPI_USES_VDDS_DSI, 51 FEAT_HDMI_CTS_SWMODE = 1 << 19,
54 FEAT_HDMI_CTS_SWMODE, 52 FEAT_HANDLE_UV_SEPARATE = 1 << 20,
55 FEAT_HDMI_AUDIO_USE_MCLK, 53 FEAT_ATTR2 = 1 << 21,
56 FEAT_HANDLE_UV_SEPARATE, 54 FEAT_VENC_REQUIRES_TV_DAC_CLK = 1 << 22,
57 FEAT_ATTR2, 55 FEAT_CPR = 1 << 23,
58 FEAT_VENC_REQUIRES_TV_DAC_CLK, 56 FEAT_PRELOAD = 1 << 24,
59 FEAT_CPR, 57 FEAT_FIR_COEF_V = 1 << 25,
60 FEAT_PRELOAD,
61 FEAT_FIR_COEF_V,
62 FEAT_ALPHA_FIXED_ZORDER,
63 FEAT_ALPHA_FREE_ZORDER,
64 FEAT_FIFO_MERGE,
65 /* An unknown HW bug causing the normal FIFO thresholds not to work */
66 FEAT_OMAP3_DSI_FIFO_BUG,
67 FEAT_BURST_2D,
68 FEAT_DSI_PLL_SELFREQDCO,
69 FEAT_DSI_PLL_REFSEL,
70 FEAT_DSI_PHY_DCC,
71}; 58};
72 59
73/* DSS register field id */ 60/* DSS register field id */
@@ -88,23 +75,21 @@ enum dss_feat_reg_field {
88 75
89enum dss_range_param { 76enum dss_range_param {
90 FEAT_PARAM_DSS_FCK, 77 FEAT_PARAM_DSS_FCK,
91 FEAT_PARAM_DSS_PCD,
92 FEAT_PARAM_DSIPLL_REGN, 78 FEAT_PARAM_DSIPLL_REGN,
93 FEAT_PARAM_DSIPLL_REGM, 79 FEAT_PARAM_DSIPLL_REGM,
94 FEAT_PARAM_DSIPLL_REGM_DISPC, 80 FEAT_PARAM_DSIPLL_REGM_DISPC,
95 FEAT_PARAM_DSIPLL_REGM_DSI, 81 FEAT_PARAM_DSIPLL_REGM_DSI,
96 FEAT_PARAM_DSIPLL_FINT, 82 FEAT_PARAM_DSIPLL_FINT,
97 FEAT_PARAM_DSIPLL_LPDIV, 83 FEAT_PARAM_DSIPLL_LPDIV,
98 FEAT_PARAM_DSI_FCK,
99 FEAT_PARAM_DOWNSCALE,
100 FEAT_PARAM_LINEWIDTH,
101}; 84};
102 85
103/* DSS Feature Functions */ 86/* DSS Feature Functions */
104int dss_feat_get_num_wbs(void); 87int dss_feat_get_num_mgrs(void);
88int dss_feat_get_num_ovls(void);
105unsigned long dss_feat_get_param_min(enum dss_range_param param); 89unsigned long dss_feat_get_param_min(enum dss_range_param param);
106unsigned long dss_feat_get_param_max(enum dss_range_param param); 90unsigned long dss_feat_get_param_max(enum dss_range_param param);
107enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); 91enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
92enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
108bool dss_feat_color_mode_supported(enum omap_plane plane, 93bool dss_feat_color_mode_supported(enum omap_plane plane,
109 enum omap_color_mode color_mode); 94 enum omap_color_mode color_mode);
110const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id); 95const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
@@ -112,13 +97,7 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
112u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ 97u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
113u32 dss_feat_get_burst_size_unit(void); /* in bytes */ 98u32 dss_feat_get_burst_size_unit(void); /* in bytes */
114 99
115bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
116
117bool dss_has_feature(enum dss_feat_id id); 100bool dss_has_feature(enum dss_feat_id id);
118void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); 101void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
119void dss_features_init(enum omapdss_version version); 102void dss_features_init(void);
120#if defined(CONFIG_OMAP4_DSS_HDMI)
121void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
122 enum omapdss_version version);
123#endif
124#endif 103#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 769d0828581..256f27a9064 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -32,45 +32,31 @@
32#include <linux/platform_device.h> 32#include <linux/platform_device.h>
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#include <linux/gpio.h>
36#include <linux/regulator/consumer.h>
37#include <video/omapdss.h> 35#include <video/omapdss.h>
36#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
37 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
38#include <sound/soc.h>
39#include <sound/pcm_params.h>
40#endif
38 41
39#include "ti_hdmi.h"
40#include "dss.h" 42#include "dss.h"
43#include "hdmi.h"
41#include "dss_features.h" 44#include "dss_features.h"
42 45
43#define HDMI_WP 0x0
44#define HDMI_CORE_SYS 0x400
45#define HDMI_CORE_AV 0x900
46#define HDMI_PLLCTRL 0x200
47#define HDMI_PHY 0x300
48
49/* HDMI EDID Length move this */
50#define HDMI_EDID_MAX_LENGTH 256
51#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
52#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
53#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
54#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
55#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
56
57#define HDMI_DEFAULT_REGN 16
58#define HDMI_DEFAULT_REGM2 1
59
60static struct { 46static struct {
61 struct mutex lock; 47 struct mutex lock;
48 struct omap_display_platform_data *pdata;
62 struct platform_device *pdev; 49 struct platform_device *pdev;
63 50 void __iomem *base_wp; /* HDMI wrapper */
64 struct hdmi_ip_data ip_data; 51 int code;
52 int mode;
53 u8 edid[HDMI_EDID_MAX_LENGTH];
54 u8 edid_set;
55 bool custom_set;
56 struct hdmi_config cfg;
65 57
66 struct clk *sys_clk; 58 struct clk *sys_clk;
67 struct regulator *vdda_hdmi_dac_reg; 59 struct clk *hdmi_clk;
68
69 int ct_cp_hpd_gpio;
70 int ls_oe_gpio;
71 int hpd_gpio;
72
73 struct omap_dss_output output;
74} hdmi; 60} hdmi;
75 61
76/* 62/*
@@ -87,223 +73,101 @@ static struct {
87 * map it to corresponding CEA or VESA index. 73 * map it to corresponding CEA or VESA index.
88 */ 74 */
89 75
90static const struct hdmi_config cea_timings[] = { 76static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = {
91 { 77 { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0},
92 { 640, 480, 25200, 96, 16, 48, 2, 10, 33, 78 { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1},
93 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, 79 { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1},
94 false, }, 80 { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0},
95 { 1, HDMI_HDMI }, 81 { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0},
96 }, 82 { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0},
97 { 83 { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0},
98 { 720, 480, 27027, 62, 16, 60, 6, 9, 30, 84 { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1},
99 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, 85 { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1},
100 false, }, 86 { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1},
101 { 2, HDMI_HDMI }, 87 { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0},
102 }, 88 { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0},
103 { 89 { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1},
104 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20, 90 { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0},
105 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, 91 { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1},
106 false, }, 92 /* VESA From Here */
107 { 4, HDMI_HDMI }, 93 { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0},
108 }, 94 { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1},
109 { 95 { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1},
110 { 1920, 540, 74250, 44, 88, 148, 5, 2, 15, 96 { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0},
111 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, 97 { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0},
112 true, }, 98 { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1},
113 { 5, HDMI_HDMI }, 99 { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1},
114 }, 100 { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1},
115 { 101 { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0},
116 { 1440, 240, 27027, 124, 38, 114, 3, 4, 15, 102 { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0},
117 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, 103 { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0},
118 true, }, 104 { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0},
119 { 6, HDMI_HDMI }, 105 { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1},
120 }, 106 { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1},
121 { 107 { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1},
122 { 1920, 1080, 148500, 44, 88, 148, 5, 4, 36, 108 { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1},
123 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, 109 { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1},
124 false, }, 110 { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1},
125 { 16, HDMI_HDMI }, 111 { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}
126 },
127 {
128 { 720, 576, 27000, 64, 12, 68, 5, 5, 39,
129 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
130 false, },
131 { 17, HDMI_HDMI },
132 },
133 {
134 { 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
135 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
136 false, },
137 { 19, HDMI_HDMI },
138 },
139 {
140 { 1920, 540, 74250, 44, 528, 148, 5, 2, 15,
141 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
142 true, },
143 { 20, HDMI_HDMI },
144 },
145 {
146 { 1440, 288, 27000, 126, 24, 138, 3, 2, 19,
147 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
148 true, },
149 { 21, HDMI_HDMI },
150 },
151 {
152 { 1440, 576, 54000, 128, 24, 136, 5, 5, 39,
153 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
154 false, },
155 { 29, HDMI_HDMI },
156 },
157 {
158 { 1920, 1080, 148500, 44, 528, 148, 5, 4, 36,
159 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
160 false, },
161 { 31, HDMI_HDMI },
162 },
163 {
164 { 1920, 1080, 74250, 44, 638, 148, 5, 4, 36,
165 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
166 false, },
167 { 32, HDMI_HDMI },
168 },
169 {
170 { 2880, 480, 108108, 248, 64, 240, 6, 9, 30,
171 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
172 false, },
173 { 35, HDMI_HDMI },
174 },
175 {
176 { 2880, 576, 108000, 256, 48, 272, 5, 5, 39,
177 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
178 false, },
179 { 37, HDMI_HDMI },
180 },
181}; 112};
182 113
183static const struct hdmi_config vesa_timings[] = { 114/*
184/* VESA From Here */ 115 * This is a static mapping array which maps the timing values
185 { 116 * with corresponding CEA / VESA code
186 { 640, 480, 25175, 96, 16, 48, 2, 11, 31, 117 */
187 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW, 118static const int code_index[OMAP_HDMI_TIMINGS_NB] = {
188 false, }, 119 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32,
189 { 4, HDMI_DVI }, 120 /* <--15 CEA 17--> vesa*/
190 }, 121 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A,
191 { 122 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B
192 { 800, 600, 40000, 128, 40, 88, 4, 1, 23, 123};
193 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, 124
194 false, }, 125/*
195 { 9, HDMI_DVI }, 126 * This is reverse static mapping which maps the CEA / VESA code
196 }, 127 * to the corresponding timing values
197 { 128 */
198 { 848, 480, 33750, 112, 16, 112, 8, 6, 23, 129static const int code_cea[39] = {
199 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH, 130 -1, 0, 3, 3, 2, 8, 5, 5, -1, -1,
200 false, }, 131 -1, -1, -1, -1, -1, -1, 9, 10, 10, 1,
201 { 0xE, HDMI_DVI }, 132 7, 6, 6, -1, -1, -1, -1, -1, -1, 11,
202 }, 133 11, 12, 14, -1, -1, 13, 13, 4, 4
203 {
204 { 1280, 768, 79500, 128, 64, 192, 7, 3, 20,
205 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
206 false, },
207 { 0x17, HDMI_DVI },
208 },
209 {
210 { 1280, 800, 83500, 128, 72, 200, 6, 3, 22,
211 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
212 false, },
213 { 0x1C, HDMI_DVI },
214 },
215 {
216 { 1360, 768, 85500, 112, 64, 256, 6, 3, 18,
217 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
218 false, },
219 { 0x27, HDMI_DVI },
220 },
221 {
222 { 1280, 960, 108000, 112, 96, 312, 3, 1, 36,
223 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
224 false, },
225 { 0x20, HDMI_DVI },
226 },
227 {
228 { 1280, 1024, 108000, 112, 48, 248, 3, 1, 38,
229 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
230 false, },
231 { 0x23, HDMI_DVI },
232 },
233 {
234 { 1024, 768, 65000, 136, 24, 160, 6, 3, 29,
235 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
236 false, },
237 { 0x10, HDMI_DVI },
238 },
239 {
240 { 1400, 1050, 121750, 144, 88, 232, 4, 3, 32,
241 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
242 false, },
243 { 0x2A, HDMI_DVI },
244 },
245 {
246 { 1440, 900, 106500, 152, 80, 232, 6, 3, 25,
247 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
248 false, },
249 { 0x2F, HDMI_DVI },
250 },
251 {
252 { 1680, 1050, 146250, 176 , 104, 280, 6, 3, 30,
253 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
254 false, },
255 { 0x3A, HDMI_DVI },
256 },
257 {
258 { 1366, 768, 85500, 143, 70, 213, 3, 3, 24,
259 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
260 false, },
261 { 0x51, HDMI_DVI },
262 },
263 {
264 { 1920, 1080, 148500, 44, 148, 80, 5, 4, 36,
265 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
266 false, },
267 { 0x52, HDMI_DVI },
268 },
269 {
270 { 1280, 768, 68250, 32, 48, 80, 7, 3, 12,
271 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
272 false, },
273 { 0x16, HDMI_DVI },
274 },
275 {
276 { 1400, 1050, 101000, 32, 48, 80, 4, 3, 23,
277 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
278 false, },
279 { 0x29, HDMI_DVI },
280 },
281 {
282 { 1680, 1050, 119000, 32, 48, 80, 6, 3, 21,
283 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
284 false, },
285 { 0x39, HDMI_DVI },
286 },
287 {
288 { 1280, 800, 79500, 32, 48, 80, 6, 3, 14,
289 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
290 false, },
291 { 0x1B, HDMI_DVI },
292 },
293 {
294 { 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
295 OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
296 false, },
297 { 0x55, HDMI_DVI },
298 },
299 {
300 { 1920, 1200, 154000, 32, 48, 80, 6, 3, 26,
301 OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
302 false, },
303 { 0x44, HDMI_DVI },
304 },
305}; 134};
306 135
136static const int code_vesa[85] = {
137 -1, -1, -1, -1, 15, -1, -1, -1, -1, 16,
138 -1, -1, -1, -1, 17, -1, 23, -1, -1, -1,
139 -1, -1, 29, 18, -1, -1, -1, 32, 19, -1,
140 -1, -1, 21, -1, -1, 22, -1, -1, -1, 20,
141 -1, 30, 24, -1, -1, -1, -1, 25, -1, -1,
142 -1, -1, -1, -1, -1, -1, -1, 31, 26, -1,
143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145 -1, 27, 28, -1, 33};
146
147static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0};
148
149static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val)
150{
151 __raw_writel(val, hdmi.base_wp + idx.idx);
152}
153
154static inline u32 hdmi_read_reg(const struct hdmi_reg idx)
155{
156 return __raw_readl(hdmi.base_wp + idx.idx);
157}
158
159static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx,
160 int b2, int b1, u32 val)
161{
162 u32 t = 0;
163 while (val != REG_GET(idx, b2, b1)) {
164 udelay(1);
165 if (t++ > 10000)
166 return !val;
167 }
168 return val;
169}
170
307static int hdmi_runtime_get(void) 171static int hdmi_runtime_get(void)
308{ 172{
309 int r; 173 int r;
@@ -312,10 +176,7 @@ static int hdmi_runtime_get(void)
312 176
313 r = pm_runtime_get_sync(&hdmi.pdev->dev); 177 r = pm_runtime_get_sync(&hdmi.pdev->dev);
314 WARN_ON(r < 0); 178 WARN_ON(r < 0);
315 if (r < 0) 179 return r < 0 ? r : 0;
316 return r;
317
318 return 0;
319} 180}
320 181
321static void hdmi_runtime_put(void) 182static void hdmi_runtime_put(void)
@@ -324,141 +185,885 @@ static void hdmi_runtime_put(void)
324 185
325 DSSDBG("hdmi_runtime_put\n"); 186 DSSDBG("hdmi_runtime_put\n");
326 187
327 r = pm_runtime_put_sync(&hdmi.pdev->dev); 188 r = pm_runtime_put(&hdmi.pdev->dev);
328 WARN_ON(r < 0 && r != -ENOSYS); 189 WARN_ON(r < 0);
329} 190}
330 191
331static int __init hdmi_init_display(struct omap_dss_device *dssdev) 192int hdmi_init_display(struct omap_dss_device *dssdev)
332{ 193{
333 int r; 194 DSSDBG("init_display\n");
334 195
335 struct gpio gpios[] = { 196 return 0;
336 { hdmi.ct_cp_hpd_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ct_cp_hpd" }, 197}
337 { hdmi.ls_oe_gpio, GPIOF_OUT_INIT_LOW, "hdmi_ls_oe" },
338 { hdmi.hpd_gpio, GPIOF_DIR_IN, "hdmi_hpd" },
339 };
340 198
341 DSSDBG("init_display\n"); 199static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq,
200 struct hdmi_pll_info *fmt, u16 sd)
201{
202 u32 r;
342 203
343 dss_init_hdmi_ip_ops(&hdmi.ip_data, omapdss_get_version()); 204 /* PLL start always use manual mode */
205 REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
344 206
345 if (hdmi.vdda_hdmi_dac_reg == NULL) { 207 r = hdmi_read_reg(PLLCTRL_CFG1);
346 struct regulator *reg; 208 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
209 r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */
347 210
348 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); 211 hdmi_write_reg(PLLCTRL_CFG1, r);
349 212
350 /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ 213 r = hdmi_read_reg(PLLCTRL_CFG2);
351 if (IS_ERR(reg))
352 reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC");
353 214
354 if (IS_ERR(reg)) { 215 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
355 DSSERR("can't get VDDA_HDMI_DAC regulator\n"); 216 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
356 return PTR_ERR(reg); 217 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
357 } 218
219 if (dcofreq) {
220 /* divider programming for frequency beyond 1000Mhz */
221 REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10);
222 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
223 } else {
224 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
225 }
226
227 hdmi_write_reg(PLLCTRL_CFG2, r);
228
229 r = hdmi_read_reg(PLLCTRL_CFG4);
230 r = FLD_MOD(r, fmt->regm2, 24, 18);
231 r = FLD_MOD(r, fmt->regmf, 17, 0);
232
233 hdmi_write_reg(PLLCTRL_CFG4, r);
234
235 /* go now */
236 REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0);
237
238 /* wait for bit change */
239 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) {
240 DSSERR("PLL GO bit not set\n");
241 return -ETIMEDOUT;
242 }
243
244 /* Wait till the lock bit is set in PLL status */
245 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
246 DSSWARN("cannot lock PLL\n");
247 DSSWARN("CFG1 0x%x\n",
248 hdmi_read_reg(PLLCTRL_CFG1));
249 DSSWARN("CFG2 0x%x\n",
250 hdmi_read_reg(PLLCTRL_CFG2));
251 DSSWARN("CFG4 0x%x\n",
252 hdmi_read_reg(PLLCTRL_CFG4));
253 return -ETIMEDOUT;
254 }
255
256 DSSDBG("PLL locked!\n");
257
258 return 0;
259}
358 260
359 hdmi.vdda_hdmi_dac_reg = reg; 261/* PHY_PWR_CMD */
262static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val)
263{
264 /* Command for power control of HDMI PHY */
265 REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6);
266
267 /* Status of the power control of HDMI PHY */
268 if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
269 DSSERR("Failed to set PHY power mode to %d\n", val);
270 return -ETIMEDOUT;
360 } 271 }
361 272
362 r = gpio_request_array(gpios, ARRAY_SIZE(gpios)); 273 return 0;
274}
275
276/* PLL_PWR_CMD */
277static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val)
278{
279 /* Command for power control of HDMI PLL */
280 REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2);
281
282 /* wait till PHY_PWR_STATUS is set */
283 if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) {
284 DSSERR("Failed to set PHY_PWR_STATUS\n");
285 return -ETIMEDOUT;
286 }
287
288 return 0;
289}
290
291static int hdmi_pll_reset(void)
292{
293 /* SYSRESET controlled by power FSM */
294 REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
295
296 /* READ 0x0 reset is in progress */
297 if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
298 DSSERR("Failed to sysreset PLL\n");
299 return -ETIMEDOUT;
300 }
301
302 return 0;
303}
304
305static int hdmi_phy_init(void)
306{
307 u16 r = 0;
308
309 r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
310 if (r)
311 return r;
312
313 r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
363 if (r) 314 if (r)
364 return r; 315 return r;
365 316
317 /*
318 * Read address 0 in order to get the SCP reset done completed
319 * Dummy access performed to make sure reset is done
320 */
321 hdmi_read_reg(HDMI_TXPHY_TX_CTRL);
322
323 /*
324 * Write to phy address 0 to configure the clock
325 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
326 */
327 REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
328
329 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
330 hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
331
332 /* Setup max LDO voltage */
333 REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
334
335 /* Write to phy address 3 to change the polarity control */
336 REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
337
366 return 0; 338 return 0;
367} 339}
368 340
369static void hdmi_uninit_display(struct omap_dss_device *dssdev) 341static int hdmi_pll_program(struct hdmi_pll_info *fmt)
370{ 342{
371 DSSDBG("uninit_display\n"); 343 u16 r = 0;
344 enum hdmi_clk_refsel refsel;
345
346 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
347 if (r)
348 return r;
349
350 r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
351 if (r)
352 return r;
353
354 r = hdmi_pll_reset();
355 if (r)
356 return r;
357
358 refsel = HDMI_REFSEL_SYSCLK;
359
360 r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd);
361 if (r)
362 return r;
363
364 return 0;
365}
372 366
373 gpio_free(hdmi.ct_cp_hpd_gpio); 367static void hdmi_phy_off(void)
374 gpio_free(hdmi.ls_oe_gpio); 368{
375 gpio_free(hdmi.hpd_gpio); 369 hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
376} 370}
377 371
378static const struct hdmi_config *hdmi_find_timing( 372static int hdmi_core_ddc_edid(u8 *pedid, int ext)
379 const struct hdmi_config *timings_arr,
380 int len)
381{ 373{
382 int i; 374 u32 i, j;
375 char checksum = 0;
376 u32 offset = 0;
377
378 /* Turn on CLK for DDC */
379 REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0);
380
381 /*
382 * SW HACK : Without the Delay DDC(i2c bus) reads 0 values /
383 * right shifted values( The behavior is not consistent and seen only
384 * with some TV's)
385 */
386 usleep_range(800, 1000);
387
388 if (!ext) {
389 /* Clk SCL Devices */
390 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0);
391
392 /* HDMI_CORE_DDC_STATUS_IN_PROG */
393 if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
394 4, 4, 0) != 0) {
395 DSSERR("Failed to program DDC\n");
396 return -ETIMEDOUT;
397 }
398
399 /* Clear FIFO */
400 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0);
401
402 /* HDMI_CORE_DDC_STATUS_IN_PROG */
403 if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS,
404 4, 4, 0) != 0) {
405 DSSERR("Failed to program DDC\n");
406 return -ETIMEDOUT;
407 }
408
409 } else {
410 if (ext % 2 != 0)
411 offset = 0x80;
412 }
413
414 /* Load Segment Address Register */
415 REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0);
416
417 /* Load Slave Address Register */
418 REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
383 419
384 for (i = 0; i < len; i++) { 420 /* Load Offset Address Register */
385 if (timings_arr[i].cm.code == hdmi.ip_data.cfg.cm.code) 421 REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0);
386 return &timings_arr[i]; 422
423 /* Load Byte Count */
424 REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
425 REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
426
427 /* Set DDC_CMD */
428 if (ext)
429 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0);
430 else
431 REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0);
432
433 /* HDMI_CORE_DDC_STATUS_BUS_LOW */
434 if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
435 DSSWARN("I2C Bus Low?\n");
436 return -EIO;
437 }
438 /* HDMI_CORE_DDC_STATUS_NO_ACK */
439 if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
440 DSSWARN("I2C No Ack\n");
441 return -EIO;
442 }
443
444 i = ext * 128;
445 j = 0;
446 while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) ||
447 (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) &&
448 j < 128) {
449
450 if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) {
451 /* FIFO not empty */
452 pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0);
453 j++;
454 }
387 } 455 }
388 return NULL; 456
457 for (j = 0; j < 128; j++)
458 checksum += pedid[j];
459
460 if (checksum != 0) {
461 DSSERR("E-EDID checksum failed!!\n");
462 return -EIO;
463 }
464
465 return 0;
389} 466}
390 467
391static const struct hdmi_config *hdmi_get_timings(void) 468static int read_edid(u8 *pedid, u16 max_length)
392{ 469{
393 const struct hdmi_config *arr; 470 int r = 0, n = 0, i = 0;
394 int len; 471 int max_ext_blocks = (max_length / 128) - 1;
395 472
396 if (hdmi.ip_data.cfg.cm.mode == HDMI_DVI) { 473 r = hdmi_core_ddc_edid(pedid, 0);
397 arr = vesa_timings; 474 if (r) {
398 len = ARRAY_SIZE(vesa_timings); 475 return r;
399 } else { 476 } else {
400 arr = cea_timings; 477 n = pedid[0x7e];
401 len = ARRAY_SIZE(cea_timings); 478
402 } 479 /*
403 480 * README: need to comply with max_length set by the caller.
404 return hdmi_find_timing(arr, len); 481 * Better implementation should be to allocate necessary
482 * memory to store EDID according to nb_block field found
483 * in first block
484 */
485 if (n > max_ext_blocks)
486 n = max_ext_blocks;
487
488 for (i = 1; i <= n; i++) {
489 r = hdmi_core_ddc_edid(pedid, i);
490 if (r)
491 return r;
492 }
493 }
494 return 0;
405} 495}
406 496
407static bool hdmi_timings_compare(struct omap_video_timings *timing1, 497static int get_timings_index(void)
408 const struct omap_video_timings *timing2)
409{ 498{
410 int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync; 499 int code;
411 500
412 if ((DIV_ROUND_CLOSEST(timing2->pixel_clock, 1000) == 501 if (hdmi.mode == 0)
413 DIV_ROUND_CLOSEST(timing1->pixel_clock, 1000)) && 502 code = code_vesa[hdmi.code];
414 (timing2->x_res == timing1->x_res) && 503 else
415 (timing2->y_res == timing1->y_res)) { 504 code = code_cea[hdmi.code];
416 505
417 timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp; 506 if (code == -1) {
418 timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp; 507 /* HDMI code 4 corresponds to 640 * 480 VGA */
419 timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp; 508 hdmi.code = 4;
420 timing1_vsync = timing2->vfp + timing2->vsw + timing2->vbp; 509 /* DVI mode 1 corresponds to HDMI 0 to DVI */
421 510 hdmi.mode = HDMI_DVI;
422 DSSDBG("timing1_hsync = %d timing1_vsync = %d"\ 511
423 "timing2_hsync = %d timing2_vsync = %d\n", 512 code = code_vesa[hdmi.code];
424 timing1_hsync, timing1_vsync,
425 timing2_hsync, timing2_vsync);
426
427 if ((timing1_hsync == timing2_hsync) &&
428 (timing1_vsync == timing2_vsync)) {
429 return true;
430 }
431 } 513 }
432 return false; 514 return code;
433} 515}
434 516
435static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) 517static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
436{ 518{
437 int i; 519 int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0;
520 int timing_vsync = 0, timing_hsync = 0;
521 struct omap_video_timings temp;
438 struct hdmi_cm cm = {-1}; 522 struct hdmi_cm cm = {-1};
439 DSSDBG("hdmi_get_code\n"); 523 DSSDBG("hdmi_get_code\n");
440 524
441 for (i = 0; i < ARRAY_SIZE(cea_timings); i++) { 525 for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) {
442 if (hdmi_timings_compare(timing, &cea_timings[i].timings)) { 526 temp = cea_vesa_timings[i].timings;
443 cm = cea_timings[i].cm; 527 if ((temp.pixel_clock == timing->pixel_clock) &&
444 goto end; 528 (temp.x_res == timing->x_res) &&
529 (temp.y_res == timing->y_res)) {
530
531 temp_hsync = temp.hfp + temp.hsw + temp.hbp;
532 timing_hsync = timing->hfp + timing->hsw + timing->hbp;
533 temp_vsync = temp.vfp + temp.vsw + temp.vbp;
534 timing_vsync = timing->vfp + timing->vsw + timing->vbp;
535
536 DSSDBG("temp_hsync = %d , temp_vsync = %d"
537 "timing_hsync = %d, timing_vsync = %d\n",
538 temp_hsync, temp_hsync,
539 timing_hsync, timing_vsync);
540
541 if ((temp_hsync == timing_hsync) &&
542 (temp_vsync == timing_vsync)) {
543 code = i;
544 cm.code = code_index[i];
545 if (code < 14)
546 cm.mode = HDMI_HDMI;
547 else
548 cm.mode = HDMI_DVI;
549 DSSDBG("Hdmi_code = %d mode = %d\n",
550 cm.code, cm.mode);
551 break;
552 }
553 }
554 }
555
556 return cm;
557}
558
559static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid ,
560 struct omap_video_timings *timings)
561{
562 /* X and Y resolution */
563 timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) |
564 edid[current_descriptor_addrs + 2]);
565 timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) |
566 edid[current_descriptor_addrs + 5]);
567
568 timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) |
569 edid[current_descriptor_addrs]);
570
571 timings->pixel_clock = 10 * timings->pixel_clock;
572
573 /* HORIZONTAL FRONT PORCH */
574 timings->hfp = edid[current_descriptor_addrs + 8] |
575 ((edid[current_descriptor_addrs + 11] & 0xc0) << 2);
576 /* HORIZONTAL SYNC WIDTH */
577 timings->hsw = edid[current_descriptor_addrs + 9] |
578 ((edid[current_descriptor_addrs + 11] & 0x30) << 4);
579 /* HORIZONTAL BACK PORCH */
580 timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) |
581 edid[current_descriptor_addrs + 3]) -
582 (timings->hfp + timings->hsw);
583 /* VERTICAL FRONT PORCH */
584 timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) |
585 ((edid[current_descriptor_addrs + 11] & 0x0f) << 2);
586 /* VERTICAL SYNC WIDTH */
587 timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) |
588 ((edid[current_descriptor_addrs + 11] & 0x03) << 4);
589 /* VERTICAL BACK PORCH */
590 timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) |
591 edid[current_descriptor_addrs + 6]) -
592 (timings->vfp + timings->vsw);
593
594}
595
596/* Description : This function gets the resolution information from EDID */
597static void get_edid_timing_data(u8 *edid)
598{
599 u8 count;
600 u16 current_descriptor_addrs;
601 struct hdmi_cm cm;
602 struct omap_video_timings edid_timings;
603
604 /* search block 0, there are 4 DTDs arranged in priority order */
605 for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) {
606 current_descriptor_addrs =
607 EDID_DESCRIPTOR_BLOCK0_ADDRESS +
608 count * EDID_TIMING_DESCRIPTOR_SIZE;
609 get_horz_vert_timing_info(current_descriptor_addrs,
610 edid, &edid_timings);
611 cm = hdmi_get_code(&edid_timings);
612 DSSDBG("Block0[%d] value matches code = %d , mode = %d\n",
613 count, cm.code, cm.mode);
614 if (cm.code == -1) {
615 continue;
616 } else {
617 hdmi.code = cm.code;
618 hdmi.mode = cm.mode;
619 DSSDBG("code = %d , mode = %d\n",
620 hdmi.code, hdmi.mode);
621 return;
445 } 622 }
446 } 623 }
447 for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) { 624 if (edid[0x7e] != 0x00) {
448 if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) { 625 for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR;
449 cm = vesa_timings[i].cm; 626 count++) {
450 goto end; 627 current_descriptor_addrs =
628 EDID_DESCRIPTOR_BLOCK1_ADDRESS +
629 count * EDID_TIMING_DESCRIPTOR_SIZE;
630 get_horz_vert_timing_info(current_descriptor_addrs,
631 edid, &edid_timings);
632 cm = hdmi_get_code(&edid_timings);
633 DSSDBG("Block1[%d] value matches code = %d, mode = %d",
634 count, cm.code, cm.mode);
635 if (cm.code == -1) {
636 continue;
637 } else {
638 hdmi.code = cm.code;
639 hdmi.mode = cm.mode;
640 DSSDBG("code = %d , mode = %d\n",
641 hdmi.code, hdmi.mode);
642 return;
643 }
451 } 644 }
452 } 645 }
453 646
454end: return cm; 647 DSSINFO("no valid timing found , falling back to VGA\n");
648 hdmi.code = 4; /* setting default value of 640 480 VGA */
649 hdmi.mode = HDMI_DVI;
650}
651
652static void hdmi_read_edid(struct omap_video_timings *dp)
653{
654 int ret = 0, code;
655
656 memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH);
657
658 if (!hdmi.edid_set)
659 ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH);
660
661 if (!ret) {
662 if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) {
663 /* search for timings of default resolution */
664 get_edid_timing_data(hdmi.edid);
665 hdmi.edid_set = true;
666 }
667 } else {
668 DSSWARN("failed to read E-EDID\n");
669 }
670
671 if (!hdmi.edid_set) {
672 DSSINFO("fallback to VGA\n");
673 hdmi.code = 4; /* setting default value of 640 480 VGA */
674 hdmi.mode = HDMI_DVI;
675 }
676
677 code = get_timings_index();
678
679 *dp = cea_vesa_timings[code].timings;
680}
681
682static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
683 struct hdmi_core_infoframe_avi *avi_cfg,
684 struct hdmi_core_packet_enable_repeat *repeat_cfg)
685{
686 DSSDBG("Enter hdmi_core_init\n");
687
688 /* video core */
689 video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
690 video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
691 video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
692 video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
693 video_cfg->hdmi_dvi = HDMI_DVI;
694 video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
695
696 /* info frame */
697 avi_cfg->db1_format = 0;
698 avi_cfg->db1_active_info = 0;
699 avi_cfg->db1_bar_info_dv = 0;
700 avi_cfg->db1_scan_info = 0;
701 avi_cfg->db2_colorimetry = 0;
702 avi_cfg->db2_aspect_ratio = 0;
703 avi_cfg->db2_active_fmt_ar = 0;
704 avi_cfg->db3_itc = 0;
705 avi_cfg->db3_ec = 0;
706 avi_cfg->db3_q_range = 0;
707 avi_cfg->db3_nup_scaling = 0;
708 avi_cfg->db4_videocode = 0;
709 avi_cfg->db5_pixel_repeat = 0;
710 avi_cfg->db6_7_line_eoftop = 0 ;
711 avi_cfg->db8_9_line_sofbottom = 0;
712 avi_cfg->db10_11_pixel_eofleft = 0;
713 avi_cfg->db12_13_pixel_sofright = 0;
714
715 /* packet enable and repeat */
716 repeat_cfg->audio_pkt = 0;
717 repeat_cfg->audio_pkt_repeat = 0;
718 repeat_cfg->avi_infoframe = 0;
719 repeat_cfg->avi_infoframe_repeat = 0;
720 repeat_cfg->gen_cntrl_pkt = 0;
721 repeat_cfg->gen_cntrl_pkt_repeat = 0;
722 repeat_cfg->generic_pkt = 0;
723 repeat_cfg->generic_pkt_repeat = 0;
724}
725
726static void hdmi_core_powerdown_disable(void)
727{
728 DSSDBG("Enter hdmi_core_powerdown_disable\n");
729 REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0);
730}
731
732static void hdmi_core_swreset_release(void)
733{
734 DSSDBG("Enter hdmi_core_swreset_release\n");
735 REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0);
736}
737
738static void hdmi_core_swreset_assert(void)
739{
740 DSSDBG("Enter hdmi_core_swreset_assert\n");
741 REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0);
742}
743
744/* DSS_HDMI_CORE_VIDEO_CONFIG */
745static void hdmi_core_video_config(struct hdmi_core_video_config *cfg)
746{
747 u32 r = 0;
748
749 /* sys_ctrl1 default configuration not tunable */
750 r = hdmi_read_reg(HDMI_CORE_CTRL1);
751 r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
752 r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
753 r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
754 r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
755 hdmi_write_reg(HDMI_CORE_CTRL1, r);
756
757 REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
758
759 /* Vid_Mode */
760 r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE);
761
762 /* dither truncation configuration */
763 if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
764 r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
765 r = FLD_MOD(r, 1, 5, 5);
766 } else {
767 r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
768 r = FLD_MOD(r, 0, 5, 5);
769 }
770 hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r);
771
772 /* HDMI_Ctrl */
773 r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL);
774 r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
775 r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
776 r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
777 hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r);
778
779 /* TMDS_CTRL */
780 REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL,
781 cfg->tclk_sel_clkmult, 6, 5);
782}
783
784static void hdmi_core_aux_infoframe_avi_config(
785 struct hdmi_core_infoframe_avi info_avi)
786{
787 u32 val;
788 char sum = 0, checksum = 0;
789
790 sum += 0x82 + 0x002 + 0x00D;
791 hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082);
792 hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002);
793 hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D);
794
795 val = (info_avi.db1_format << 5) |
796 (info_avi.db1_active_info << 4) |
797 (info_avi.db1_bar_info_dv << 2) |
798 (info_avi.db1_scan_info);
799 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val);
800 sum += val;
801
802 val = (info_avi.db2_colorimetry << 6) |
803 (info_avi.db2_aspect_ratio << 4) |
804 (info_avi.db2_active_fmt_ar);
805 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val);
806 sum += val;
807
808 val = (info_avi.db3_itc << 7) |
809 (info_avi.db3_ec << 4) |
810 (info_avi.db3_q_range << 2) |
811 (info_avi.db3_nup_scaling);
812 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val);
813 sum += val;
814
815 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode);
816 sum += info_avi.db4_videocode;
817
818 val = info_avi.db5_pixel_repeat;
819 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val);
820 sum += val;
821
822 val = info_avi.db6_7_line_eoftop & 0x00FF;
823 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val);
824 sum += val;
825
826 val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
827 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val);
828 sum += val;
829
830 val = info_avi.db8_9_line_sofbottom & 0x00FF;
831 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val);
832 sum += val;
833
834 val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
835 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val);
836 sum += val;
837
838 val = info_avi.db10_11_pixel_eofleft & 0x00FF;
839 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val);
840 sum += val;
841
842 val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
843 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val);
844 sum += val;
845
846 val = info_avi.db12_13_pixel_sofright & 0x00FF;
847 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val);
848 sum += val;
849
850 val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
851 hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val);
852 sum += val;
853
854 checksum = 0x100 - sum;
855 hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum);
856}
857
858static void hdmi_core_av_packet_config(
859 struct hdmi_core_packet_enable_repeat repeat_cfg)
860{
861 /* enable/repeat the infoframe */
862 hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1,
863 (repeat_cfg.audio_pkt << 5) |
864 (repeat_cfg.audio_pkt_repeat << 4) |
865 (repeat_cfg.avi_infoframe << 1) |
866 (repeat_cfg.avi_infoframe_repeat));
867
868 /* enable/repeat the packet */
869 hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2,
870 (repeat_cfg.gen_cntrl_pkt << 3) |
871 (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
872 (repeat_cfg.generic_pkt << 1) |
873 (repeat_cfg.generic_pkt_repeat));
874}
875
876static void hdmi_wp_init(struct omap_video_timings *timings,
877 struct hdmi_video_format *video_fmt,
878 struct hdmi_video_interface *video_int)
879{
880 DSSDBG("Enter hdmi_wp_init\n");
881
882 timings->hbp = 0;
883 timings->hfp = 0;
884 timings->hsw = 0;
885 timings->vbp = 0;
886 timings->vfp = 0;
887 timings->vsw = 0;
888
889 video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
890 video_fmt->y_res = 0;
891 video_fmt->x_res = 0;
892
893 video_int->vsp = 0;
894 video_int->hsp = 0;
895
896 video_int->interlacing = 0;
897 video_int->tm = 0; /* HDMI_TIMING_SLAVE */
898
899}
900
901static void hdmi_wp_video_start(bool start)
902{
903 REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31);
904}
905
906static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
907 struct omap_video_timings *timings, struct hdmi_config *param)
908{
909 DSSDBG("Enter hdmi_wp_video_init_format\n");
910
911 video_fmt->y_res = param->timings.timings.y_res;
912 video_fmt->x_res = param->timings.timings.x_res;
913
914 timings->hbp = param->timings.timings.hbp;
915 timings->hfp = param->timings.timings.hfp;
916 timings->hsw = param->timings.timings.hsw;
917 timings->vbp = param->timings.timings.vbp;
918 timings->vfp = param->timings.timings.vfp;
919 timings->vsw = param->timings.timings.vsw;
920}
921
922static void hdmi_wp_video_config_format(
923 struct hdmi_video_format *video_fmt)
924{
925 u32 l = 0;
926
927 REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8);
928
929 l |= FLD_VAL(video_fmt->y_res, 31, 16);
930 l |= FLD_VAL(video_fmt->x_res, 15, 0);
931 hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l);
932}
933
934static void hdmi_wp_video_config_interface(
935 struct hdmi_video_interface *video_int)
936{
937 u32 r;
938 DSSDBG("Enter hdmi_wp_video_config_interface\n");
939
940 r = hdmi_read_reg(HDMI_WP_VIDEO_CFG);
941 r = FLD_MOD(r, video_int->vsp, 7, 7);
942 r = FLD_MOD(r, video_int->hsp, 6, 6);
943 r = FLD_MOD(r, video_int->interlacing, 3, 3);
944 r = FLD_MOD(r, video_int->tm, 1, 0);
945 hdmi_write_reg(HDMI_WP_VIDEO_CFG, r);
946}
947
948static void hdmi_wp_video_config_timing(
949 struct omap_video_timings *timings)
950{
951 u32 timing_h = 0;
952 u32 timing_v = 0;
953
954 DSSDBG("Enter hdmi_wp_video_config_timing\n");
955
956 timing_h |= FLD_VAL(timings->hbp, 31, 20);
957 timing_h |= FLD_VAL(timings->hfp, 19, 8);
958 timing_h |= FLD_VAL(timings->hsw, 7, 0);
959 hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h);
960
961 timing_v |= FLD_VAL(timings->vbp, 31, 20);
962 timing_v |= FLD_VAL(timings->vfp, 19, 8);
963 timing_v |= FLD_VAL(timings->vsw, 7, 0);
964 hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v);
965}
966
967static void hdmi_basic_configure(struct hdmi_config *cfg)
968{
969 /* HDMI */
970 struct omap_video_timings video_timing;
971 struct hdmi_video_format video_format;
972 struct hdmi_video_interface video_interface;
973 /* HDMI core */
974 struct hdmi_core_infoframe_avi avi_cfg;
975 struct hdmi_core_video_config v_core_cfg;
976 struct hdmi_core_packet_enable_repeat repeat_cfg;
977
978 hdmi_wp_init(&video_timing, &video_format,
979 &video_interface);
980
981 hdmi_core_init(&v_core_cfg,
982 &avi_cfg,
983 &repeat_cfg);
984
985 hdmi_wp_video_init_format(&video_format,
986 &video_timing, cfg);
987
988 hdmi_wp_video_config_timing(&video_timing);
989
990 /* video config */
991 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
455 992
993 hdmi_wp_video_config_format(&video_format);
994
995 video_interface.vsp = cfg->timings.vsync_pol;
996 video_interface.hsp = cfg->timings.hsync_pol;
997 video_interface.interlacing = cfg->interlace;
998 video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */
999
1000 hdmi_wp_video_config_interface(&video_interface);
1001
1002 /*
1003 * configure core video part
1004 * set software reset in the core
1005 */
1006 hdmi_core_swreset_assert();
1007
1008 /* power down off */
1009 hdmi_core_powerdown_disable();
1010
1011 v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
1012 v_core_cfg.hdmi_dvi = cfg->cm.mode;
1013
1014 hdmi_core_video_config(&v_core_cfg);
1015
1016 /* release software reset in the core */
1017 hdmi_core_swreset_release();
1018
1019 /*
1020 * configure packet
1021 * info frame video see doc CEA861-D page 65
1022 */
1023 avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
1024 avi_cfg.db1_active_info =
1025 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
1026 avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
1027 avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
1028 avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
1029 avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
1030 avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
1031 avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
1032 avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
1033 avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
1034 avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
1035 avi_cfg.db4_videocode = cfg->cm.code;
1036 avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
1037 avi_cfg.db6_7_line_eoftop = 0;
1038 avi_cfg.db8_9_line_sofbottom = 0;
1039 avi_cfg.db10_11_pixel_eofleft = 0;
1040 avi_cfg.db12_13_pixel_sofright = 0;
1041
1042 hdmi_core_aux_infoframe_avi_config(avi_cfg);
1043
1044 /* enable/repeat the infoframe */
1045 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
1046 repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
1047 /* wakeup */
1048 repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
1049 repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
1050 hdmi_core_av_packet_config(repeat_cfg);
456} 1051}
457 1052
458unsigned long hdmi_get_pixel_clock(void) 1053static void update_hdmi_timings(struct hdmi_config *cfg,
1054 struct omap_video_timings *timings, int code)
459{ 1055{
460 /* HDMI Pixel Clock in Mhz */ 1056 cfg->timings.timings.x_res = timings->x_res;
461 return hdmi.ip_data.cfg.timings.pixel_clock * 1000; 1057 cfg->timings.timings.y_res = timings->y_res;
1058 cfg->timings.timings.hbp = timings->hbp;
1059 cfg->timings.timings.hfp = timings->hfp;
1060 cfg->timings.timings.hsw = timings->hsw;
1061 cfg->timings.timings.vbp = timings->vbp;
1062 cfg->timings.timings.vfp = timings->vfp;
1063 cfg->timings.timings.vsw = timings->vsw;
1064 cfg->timings.timings.pixel_clock = timings->pixel_clock;
1065 cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol;
1066 cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
462} 1067}
463 1068
464static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, 1069static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
@@ -472,161 +1077,123 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
472 * Input clock is predivided by N + 1 1077 * Input clock is predivided by N + 1
473 * out put of which is reference clk 1078 * out put of which is reference clk
474 */ 1079 */
475 if (dssdev->clocks.hdmi.regn == 0) 1080 pi->regn = dssdev->clocks.hdmi.regn;
476 pi->regn = HDMI_DEFAULT_REGN; 1081 refclk = clkin / (pi->regn + 1);
477 else
478 pi->regn = dssdev->clocks.hdmi.regn;
479
480 refclk = clkin / pi->regn;
481
482 if (dssdev->clocks.hdmi.regm2 == 0)
483 pi->regm2 = HDMI_DEFAULT_REGM2;
484 else
485 pi->regm2 = dssdev->clocks.hdmi.regm2;
486 1082
487 /* 1083 /*
488 * multiplier is pixel_clk/ref_clk 1084 * multiplier is pixel_clk/ref_clk
489 * Multiplying by 100 to avoid fractional part removal 1085 * Multiplying by 100 to avoid fractional part removal
490 */ 1086 */
491 pi->regm = phy * pi->regm2 / refclk; 1087 pi->regm = (phy * 100 / (refclk)) / 100;
1088 pi->regm2 = dssdev->clocks.hdmi.regm2;
492 1089
493 /* 1090 /*
494 * fractional multiplier is remainder of the difference between 1091 * fractional multiplier is remainder of the difference between
495 * multiplier and actual phy(required pixel clock thus should be 1092 * multiplier and actual phy(required pixel clock thus should be
496 * multiplied by 2^18(262144) divided by the reference clock 1093 * multiplied by 2^18(262144) divided by the reference clock
497 */ 1094 */
498 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144; 1095 mf = (phy - pi->regm * refclk) * 262144;
499 pi->regmf = pi->regm2 * mf / refclk; 1096 pi->regmf = mf / (refclk);
500 1097
501 /* 1098 /*
502 * Dcofreq should be set to 1 if required pixel clock 1099 * Dcofreq should be set to 1 if required pixel clock
503 * is greater than 1000MHz 1100 * is greater than 1000MHz
504 */ 1101 */
505 pi->dcofreq = phy > 1000 * 100; 1102 pi->dcofreq = phy > 1000 * 100;
506 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10; 1103 pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10;
507
508 /* Set the reference clock to sysclk reference */
509 pi->refsel = HDMI_REFSEL_SYSCLK;
510 1104
511 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); 1105 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
512 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); 1106 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
513} 1107}
514 1108
515static int hdmi_power_on_core(struct omap_dss_device *dssdev) 1109static int hdmi_power_on(struct omap_dss_device *dssdev)
516{
517 int r;
518
519 gpio_set_value(hdmi.ct_cp_hpd_gpio, 1);
520 gpio_set_value(hdmi.ls_oe_gpio, 1);
521
522 /* wait 300us after CT_CP_HPD for the 5V power output to reach 90% */
523 udelay(300);
524
525 r = regulator_enable(hdmi.vdda_hdmi_dac_reg);
526 if (r)
527 goto err_vdac_enable;
528
529 r = hdmi_runtime_get();
530 if (r)
531 goto err_runtime_get;
532
533 /* Make selection of HDMI in DSS */
534 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
535
536 return 0;
537
538err_runtime_get:
539 regulator_disable(hdmi.vdda_hdmi_dac_reg);
540err_vdac_enable:
541 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
542 gpio_set_value(hdmi.ls_oe_gpio, 0);
543 return r;
544}
545
546static void hdmi_power_off_core(struct omap_dss_device *dssdev)
547{
548 hdmi_runtime_put();
549 regulator_disable(hdmi.vdda_hdmi_dac_reg);
550 gpio_set_value(hdmi.ct_cp_hpd_gpio, 0);
551 gpio_set_value(hdmi.ls_oe_gpio, 0);
552}
553
554static int hdmi_power_on_full(struct omap_dss_device *dssdev)
555{ 1110{
556 int r; 1111 int r, code = 0;
1112 struct hdmi_pll_info pll_data;
557 struct omap_video_timings *p; 1113 struct omap_video_timings *p;
558 struct omap_overlay_manager *mgr = dssdev->output->manager;
559 unsigned long phy; 1114 unsigned long phy;
560 1115
561 r = hdmi_power_on_core(dssdev); 1116 r = hdmi_runtime_get();
562 if (r) 1117 if (r)
563 return r; 1118 return r;
564 1119
565 dss_mgr_disable(mgr); 1120 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
566 1121
567 p = &hdmi.ip_data.cfg.timings; 1122 p = &dssdev->panel.timings;
568 1123
569 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); 1124 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n",
1125 dssdev->panel.timings.x_res,
1126 dssdev->panel.timings.y_res);
1127
1128 if (!hdmi.custom_set) {
1129 DSSDBG("Read EDID as no EDID is not set on poweron\n");
1130 hdmi_read_edid(p);
1131 }
1132 code = get_timings_index();
1133 dssdev->panel.timings = cea_vesa_timings[code].timings;
1134 update_hdmi_timings(&hdmi.cfg, p, code);
570 1135
571 phy = p->pixel_clock; 1136 phy = p->pixel_clock;
572 1137
573 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 1138 hdmi_compute_pll(dssdev, phy, &pll_data);
574 1139
575 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 1140 hdmi_wp_video_start(0);
576 1141
577 /* config the PLL and PHY hdmi_set_pll_pwrfirst */ 1142 /* config the PLL and PHY first */
578 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 1143 r = hdmi_pll_program(&pll_data);
579 if (r) { 1144 if (r) {
580 DSSDBG("Failed to lock PLL\n"); 1145 DSSDBG("Failed to lock PLL\n");
581 goto err_pll_enable; 1146 goto err;
582 } 1147 }
583 1148
584 r = hdmi.ip_data.ops->phy_enable(&hdmi.ip_data); 1149 r = hdmi_phy_init();
585 if (r) { 1150 if (r) {
586 DSSDBG("Failed to start PHY\n"); 1151 DSSDBG("Failed to start PHY\n");
587 goto err_phy_enable; 1152 goto err;
588 } 1153 }
589 1154
590 hdmi.ip_data.ops->video_configure(&hdmi.ip_data); 1155 hdmi.cfg.cm.mode = hdmi.mode;
1156 hdmi.cfg.cm.code = hdmi.code;
1157 hdmi_basic_configure(&hdmi.cfg);
1158
1159 /* Make selection of HDMI in DSS */
1160 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
1161
1162 /* Select the dispc clock source as PRCM clock, to ensure that it is not
1163 * DSI PLL source as the clock selected by DSI PLL might not be
1164 * sufficient for the resolution selected / that can be changed
1165 * dynamically by user. This can be moved to single location , say
1166 * Boardfile.
1167 */
1168 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
591 1169
592 /* bypass TV gamma table */ 1170 /* bypass TV gamma table */
593 dispc_enable_gamma_table(0); 1171 dispc_enable_gamma_table(0);
594 1172
595 /* tv size */ 1173 /* tv size */
596 dss_mgr_set_timings(mgr, p); 1174 dispc_set_digit_size(dssdev->panel.timings.x_res,
1175 dssdev->panel.timings.y_res);
597 1176
598 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data); 1177 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1);
599 if (r)
600 goto err_vid_enable;
601 1178
602 r = dss_mgr_enable(mgr); 1179 hdmi_wp_video_start(1);
603 if (r)
604 goto err_mgr_enable;
605 1180
606 return 0; 1181 return 0;
607 1182err:
608err_mgr_enable: 1183 hdmi_runtime_put();
609 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
610err_vid_enable:
611 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
612err_phy_enable:
613 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
614err_pll_enable:
615 hdmi_power_off_core(dssdev);
616 return -EIO; 1184 return -EIO;
617} 1185}
618 1186
619static void hdmi_power_off_full(struct omap_dss_device *dssdev) 1187static void hdmi_power_off(struct omap_dss_device *dssdev)
620{ 1188{
621 struct omap_overlay_manager *mgr = dssdev->output->manager; 1189 dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0);
622
623 dss_mgr_disable(mgr);
624 1190
625 hdmi.ip_data.ops->video_disable(&hdmi.ip_data); 1191 hdmi_wp_video_start(0);
626 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 1192 hdmi_phy_off();
627 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 1193 hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF);
1194 hdmi_runtime_put();
628 1195
629 hdmi_power_off_core(dssdev); 1196 hdmi.edid_set = 0;
630} 1197}
631 1198
632int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, 1199int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
@@ -636,6 +1203,7 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
636 1203
637 cm = hdmi_get_code(timings); 1204 cm = hdmi_get_code(timings);
638 if (cm.code == -1) { 1205 if (cm.code == -1) {
1206 DSSERR("Invalid timing entered\n");
639 return -EINVAL; 1207 return -EINVAL;
640 } 1208 }
641 1209
@@ -643,108 +1211,52 @@ int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev,
643 1211
644} 1212}
645 1213
646void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev, 1214void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
647 struct omap_video_timings *timings)
648{ 1215{
649 struct hdmi_cm cm; 1216 struct hdmi_cm cm;
650 const struct hdmi_config *t;
651
652 mutex_lock(&hdmi.lock);
653
654 cm = hdmi_get_code(timings);
655 hdmi.ip_data.cfg.cm = cm;
656
657 t = hdmi_get_timings();
658 if (t != NULL)
659 hdmi.ip_data.cfg = *t;
660 1217
661 mutex_unlock(&hdmi.lock); 1218 hdmi.custom_set = 1;
662} 1219 cm = hdmi_get_code(&dssdev->panel.timings);
663 1220 hdmi.code = cm.code;
664static void hdmi_dump_regs(struct seq_file *s) 1221 hdmi.mode = cm.mode;
665{ 1222 omapdss_hdmi_display_enable(dssdev);
666 mutex_lock(&hdmi.lock); 1223 hdmi.custom_set = 0;
667
668 if (hdmi_runtime_get()) {
669 mutex_unlock(&hdmi.lock);
670 return;
671 }
672
673 hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
674 hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
675 hdmi.ip_data.ops->dump_phy(&hdmi.ip_data, s);
676 hdmi.ip_data.ops->dump_core(&hdmi.ip_data, s);
677
678 hdmi_runtime_put();
679 mutex_unlock(&hdmi.lock);
680}
681
682int omapdss_hdmi_read_edid(u8 *buf, int len)
683{
684 int r;
685
686 mutex_lock(&hdmi.lock);
687
688 r = hdmi_runtime_get();
689 BUG_ON(r);
690
691 r = hdmi.ip_data.ops->read_edid(&hdmi.ip_data, buf, len);
692
693 hdmi_runtime_put();
694 mutex_unlock(&hdmi.lock);
695
696 return r;
697}
698
699bool omapdss_hdmi_detect(void)
700{
701 int r;
702
703 mutex_lock(&hdmi.lock);
704
705 r = hdmi_runtime_get();
706 BUG_ON(r);
707
708 r = hdmi.ip_data.ops->detect(&hdmi.ip_data);
709
710 hdmi_runtime_put();
711 mutex_unlock(&hdmi.lock);
712
713 return r == 1;
714} 1224}
715 1225
716int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) 1226int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
717{ 1227{
718 struct omap_dss_output *out = dssdev->output;
719 int r = 0; 1228 int r = 0;
720 1229
721 DSSDBG("ENTER hdmi_display_enable\n"); 1230 DSSDBG("ENTER hdmi_display_enable\n");
722 1231
723 mutex_lock(&hdmi.lock); 1232 mutex_lock(&hdmi.lock);
724 1233
725 if (out == NULL || out->manager == NULL) {
726 DSSERR("failed to enable display: no output/manager\n");
727 r = -ENODEV;
728 goto err0;
729 }
730
731 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio;
732
733 r = omap_dss_start_device(dssdev); 1234 r = omap_dss_start_device(dssdev);
734 if (r) { 1235 if (r) {
735 DSSERR("failed to start device\n"); 1236 DSSERR("failed to start device\n");
736 goto err0; 1237 goto err0;
737 } 1238 }
738 1239
739 r = hdmi_power_on_full(dssdev); 1240 if (dssdev->platform_enable) {
1241 r = dssdev->platform_enable(dssdev);
1242 if (r) {
1243 DSSERR("failed to enable GPIO's\n");
1244 goto err1;
1245 }
1246 }
1247
1248 r = hdmi_power_on(dssdev);
740 if (r) { 1249 if (r) {
741 DSSERR("failed to power on device\n"); 1250 DSSERR("failed to power on device\n");
742 goto err1; 1251 goto err2;
743 } 1252 }
744 1253
745 mutex_unlock(&hdmi.lock); 1254 mutex_unlock(&hdmi.lock);
746 return 0; 1255 return 0;
747 1256
1257err2:
1258 if (dssdev->platform_disable)
1259 dssdev->platform_disable(dssdev);
748err1: 1260err1:
749 omap_dss_stop_device(dssdev); 1261 omap_dss_stop_device(dssdev);
750err0: 1262err0:
@@ -758,395 +1270,527 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
758 1270
759 mutex_lock(&hdmi.lock); 1271 mutex_lock(&hdmi.lock);
760 1272
761 hdmi_power_off_full(dssdev); 1273 hdmi_power_off(dssdev);
1274
1275 if (dssdev->platform_disable)
1276 dssdev->platform_disable(dssdev);
762 1277
763 omap_dss_stop_device(dssdev); 1278 omap_dss_stop_device(dssdev);
764 1279
765 mutex_unlock(&hdmi.lock); 1280 mutex_unlock(&hdmi.lock);
766} 1281}
767 1282
768int omapdss_hdmi_core_enable(struct omap_dss_device *dssdev) 1283#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1284 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1285static void hdmi_wp_audio_config_format(
1286 struct hdmi_audio_format *aud_fmt)
769{ 1287{
770 int r = 0; 1288 u32 r;
1289
1290 DSSDBG("Enter hdmi_wp_audio_config_format\n");
1291
1292 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
1293 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
1294 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
1295 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
1296 r = FLD_MOD(r, aud_fmt->type, 4, 4);
1297 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
1298 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
1299 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
1300 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
1301 hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
1302}
771 1303
772 DSSDBG("ENTER omapdss_hdmi_core_enable\n"); 1304static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
1305{
1306 u32 r;
773 1307
774 mutex_lock(&hdmi.lock); 1308 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
775 1309
776 hdmi.ip_data.hpd_gpio = hdmi.hpd_gpio; 1310 r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
1311 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
1312 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
1313 hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
777 1314
778 r = hdmi_power_on_core(dssdev); 1315 r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
779 if (r) { 1316 r = FLD_MOD(r, aud_dma->mode, 9, 9);
780 DSSERR("failed to power on device\n"); 1317 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
781 goto err0; 1318 hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
782 } 1319}
783 1320
784 mutex_unlock(&hdmi.lock); 1321static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
785 return 0; 1322{
1323 u32 r;
1324
1325 /* audio clock recovery parameters */
1326 r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
1327 r = FLD_MOD(r, cfg->use_mclk, 2, 2);
1328 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1329 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1330 hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
1331
1332 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1333 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1334 REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
1335
1336 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
1337 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
1338 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
1339 REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1340 } else {
1341 /*
1342 * HDMI IP uses this configuration to divide the MCLK to
1343 * update CTS value.
1344 */
1345 REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1346
1347 /* Configure clock for audio packets */
1348 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1349 cfg->aud_par_busclk, 7, 0);
1350 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
1351 (cfg->aud_par_busclk >> 8), 7, 0);
1352 REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
1353 (cfg->aud_par_busclk >> 16), 7, 0);
1354 }
786 1355
787err0: 1356 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
788 mutex_unlock(&hdmi.lock); 1357 REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
789 return r; 1358
1359 /* I2S parameters */
1360 REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
1361
1362 r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
1363 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1364 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1365 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1366 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1367 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1368 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1369 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1370 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1371 hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
1372
1373 r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
1374 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1375 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1376 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1377 hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
1378
1379 REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
1380
1381 /* Audio channels and mode parameters */
1382 REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
1383 r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
1384 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
1385 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
1386 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1387 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1388 hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
790} 1389}
791 1390
792void omapdss_hdmi_core_disable(struct omap_dss_device *dssdev) 1391static void hdmi_core_audio_infoframe_config(
1392 struct hdmi_core_infoframe_audio *info_aud)
793{ 1393{
794 DSSDBG("Enter omapdss_hdmi_core_disable\n"); 1394 u8 val;
1395 u8 sum = 0, checksum = 0;
795 1396
796 mutex_lock(&hdmi.lock); 1397 /*
1398 * Set audio info frame type, version and length as
1399 * described in HDMI 1.4a Section 8.2.2 specification.
1400 * Checksum calculation is defined in Section 5.3.5.
1401 */
1402 hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
1403 hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
1404 hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1405 sum += 0x84 + 0x001 + 0x00a;
797 1406
798 hdmi_power_off_core(dssdev); 1407 val = (info_aud->db1_coding_type << 4)
1408 | (info_aud->db1_channel_count - 1);
1409 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
1410 sum += val;
799 1411
800 mutex_unlock(&hdmi.lock); 1412 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
801} 1413 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
1414 sum += val;
802 1415
803static int hdmi_get_clocks(struct platform_device *pdev) 1416 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
804{
805 struct clk *clk;
806 1417
807 clk = clk_get(&pdev->dev, "sys_clk"); 1418 val = info_aud->db4_channel_alloc;
808 if (IS_ERR(clk)) { 1419 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
809 DSSERR("can't get sys_clk\n"); 1420 sum += val;
810 return PTR_ERR(clk);
811 }
812 1421
813 hdmi.sys_clk = clk; 1422 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
1423 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
1424 sum += val;
814 1425
815 return 0; 1426 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
816} 1427 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
1428 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
1429 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
1430 hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
817 1431
818static void hdmi_put_clocks(void) 1432 checksum = 0x100 - sum;
819{ 1433 hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
820 if (hdmi.sys_clk) 1434
821 clk_put(hdmi.sys_clk); 1435 /*
1436 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
1437 * is available.
1438 */
822} 1439}
823 1440
824#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 1441static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
825int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
826{ 1442{
827 u32 deep_color; 1443 u32 r;
828 bool deep_color_correct = false; 1444 u32 deep_color = 0;
829 u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock; 1445 u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
830 1446
831 if (n == NULL || cts == NULL) 1447 if (n == NULL || cts == NULL)
832 return -EINVAL; 1448 return -EINVAL;
833
834 /* TODO: When implemented, query deep color mode here. */
835 deep_color = 100;
836
837 /* 1449 /*
838 * When using deep color, the default N value (as in the HDMI 1450 * Obtain current deep color configuration. This needed
839 * specification) yields to an non-integer CTS. Hence, we 1451 * to calculate the TMDS clock based on the pixel clock.
840 * modify it while keeping the restrictions described in
841 * section 7.2.1 of the HDMI 1.4a specification.
842 */ 1452 */
843 switch (sample_freq) { 1453 r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
844 case 32000: 1454 switch (r) {
845 case 48000: 1455 case 1: /* No deep color selected */
846 case 96000: 1456 deep_color = 100;
847 case 192000:
848 if (deep_color == 125)
849 if (pclk == 27027 || pclk == 74250)
850 deep_color_correct = true;
851 if (deep_color == 150)
852 if (pclk == 27027)
853 deep_color_correct = true;
854 break; 1457 break;
855 case 44100: 1458 case 2: /* 10-bit deep color selected */
856 case 88200: 1459 deep_color = 125;
857 case 176400: 1460 break;
858 if (deep_color == 125) 1461 case 3: /* 12-bit deep color selected */
859 if (pclk == 27027) 1462 deep_color = 150;
860 deep_color_correct = true;
861 break; 1463 break;
862 default: 1464 default:
863 return -EINVAL; 1465 return -EINVAL;
864 } 1466 }
865 1467
866 if (deep_color_correct) { 1468 switch (sample_freq) {
867 switch (sample_freq) { 1469 case 32000:
868 case 32000: 1470 if ((deep_color == 125) && ((pclk == 54054)
869 *n = 8192; 1471 || (pclk == 74250)))
870 break;
871 case 44100:
872 *n = 12544;
873 break;
874 case 48000:
875 *n = 8192; 1472 *n = 8192;
876 break; 1473 else
877 case 88200:
878 *n = 25088;
879 break;
880 case 96000:
881 *n = 16384;
882 break;
883 case 176400:
884 *n = 50176;
885 break;
886 case 192000:
887 *n = 32768;
888 break;
889 default:
890 return -EINVAL;
891 }
892 } else {
893 switch (sample_freq) {
894 case 32000:
895 *n = 4096; 1474 *n = 4096;
896 break; 1475 break;
897 case 44100: 1476 case 44100:
898 *n = 6272; 1477 *n = 6272;
899 break; 1478 break;
900 case 48000: 1479 case 48000:
1480 if ((deep_color == 125) && ((pclk == 54054)
1481 || (pclk == 74250)))
1482 *n = 8192;
1483 else
901 *n = 6144; 1484 *n = 6144;
902 break; 1485 break;
903 case 88200: 1486 default:
904 *n = 12544; 1487 *n = 0;
905 break; 1488 return -EINVAL;
906 case 96000:
907 *n = 12288;
908 break;
909 case 176400:
910 *n = 25088;
911 break;
912 case 192000:
913 *n = 24576;
914 break;
915 default:
916 return -EINVAL;
917 }
918 } 1489 }
1490
919 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ 1491 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
920 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); 1492 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
921 1493
922 return 0; 1494 return 0;
923} 1495}
924 1496
925int hdmi_audio_enable(void) 1497static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
1498 struct snd_pcm_hw_params *params,
1499 struct snd_soc_dai *dai)
926{ 1500{
927 DSSDBG("audio_enable\n"); 1501 struct hdmi_audio_format audio_format;
1502 struct hdmi_audio_dma audio_dma;
1503 struct hdmi_core_audio_config core_cfg;
1504 struct hdmi_core_infoframe_audio aud_if_cfg;
1505 int err, n, cts;
1506 enum hdmi_core_audio_sample_freq sample_freq;
1507
1508 switch (params_format(params)) {
1509 case SNDRV_PCM_FORMAT_S16_LE:
1510 core_cfg.i2s_cfg.word_max_length =
1511 HDMI_AUDIO_I2S_MAX_WORD_20BITS;
1512 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
1513 core_cfg.i2s_cfg.in_length_bits =
1514 HDMI_AUDIO_I2S_INPUT_LENGTH_16;
1515 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1516 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
1517 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
1518 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1519 audio_dma.transfer_size = 0x10;
1520 break;
1521 case SNDRV_PCM_FORMAT_S24_LE:
1522 core_cfg.i2s_cfg.word_max_length =
1523 HDMI_AUDIO_I2S_MAX_WORD_24BITS;
1524 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
1525 core_cfg.i2s_cfg.in_length_bits =
1526 HDMI_AUDIO_I2S_INPUT_LENGTH_24;
1527 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
1528 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
1529 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1530 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1531 audio_dma.transfer_size = 0x20;
1532 break;
1533 default:
1534 return -EINVAL;
1535 }
928 1536
929 return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data); 1537 switch (params_rate(params)) {
930} 1538 case 32000:
1539 sample_freq = HDMI_AUDIO_FS_32000;
1540 break;
1541 case 44100:
1542 sample_freq = HDMI_AUDIO_FS_44100;
1543 break;
1544 case 48000:
1545 sample_freq = HDMI_AUDIO_FS_48000;
1546 break;
1547 default:
1548 return -EINVAL;
1549 }
931 1550
932void hdmi_audio_disable(void) 1551 err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
933{ 1552 if (err < 0)
934 DSSDBG("audio_disable\n"); 1553 return err;
935 1554
936 hdmi.ip_data.ops->audio_disable(&hdmi.ip_data); 1555 /* Audio wrapper config */
937} 1556 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
1557 audio_format.active_chnnls_msk = 0x03;
1558 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
1559 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
1560 /* Disable start/stop signals of IEC 60958 blocks */
1561 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF;
938 1562
939int hdmi_audio_start(void) 1563 audio_dma.block_size = 0xC0;
940{ 1564 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
941 DSSDBG("audio_start\n"); 1565 audio_dma.fifo_threshold = 0x20; /* in number of samples */
942 1566
943 return hdmi.ip_data.ops->audio_start(&hdmi.ip_data); 1567 hdmi_wp_audio_config_dma(&audio_dma);
944} 1568 hdmi_wp_audio_config_format(&audio_format);
945 1569
946void hdmi_audio_stop(void) 1570 /*
947{ 1571 * I2S config
948 DSSDBG("audio_stop\n"); 1572 */
1573 core_cfg.i2s_cfg.en_high_bitrate_aud = false;
1574 /* Only used with high bitrate audio */
1575 core_cfg.i2s_cfg.cbit_order = false;
1576 /* Serial data and word select should change on sck rising edge */
1577 core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
1578 core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
1579 /* Set I2S word select polarity */
1580 core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
1581 core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
1582 /* Set serial data to word select shift. See Phillips spec. */
1583 core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
1584 /* Enable one of the four available serial data channels */
1585 core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
1586
1587 /* Core audio config */
1588 core_cfg.freq_sample = sample_freq;
1589 core_cfg.n = n;
1590 core_cfg.cts = cts;
1591 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
1592 core_cfg.aud_par_busclk = 0;
1593 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
1594 core_cfg.use_mclk = false;
1595 } else {
1596 core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
1597 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
1598 core_cfg.use_mclk = true;
1599 core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
1600 }
1601 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
1602 core_cfg.en_spdif = false;
1603 /* Use sample frequency from channel status word */
1604 core_cfg.fs_override = true;
1605 /* Enable ACR packets */
1606 core_cfg.en_acr_pkt = true;
1607 /* Disable direct streaming digital audio */
1608 core_cfg.en_dsd_audio = false;
1609 /* Use parallel audio interface */
1610 core_cfg.en_parallel_aud_input = true;
1611
1612 hdmi_core_audio_config(&core_cfg);
949 1613
950 hdmi.ip_data.ops->audio_stop(&hdmi.ip_data); 1614 /*
1615 * Configure packet
1616 * info frame audio see doc CEA861-D page 74
1617 */
1618 aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
1619 aud_if_cfg.db1_channel_count = 2;
1620 aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
1621 aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
1622 aud_if_cfg.db4_channel_alloc = 0x00;
1623 aud_if_cfg.db5_downmix_inh = false;
1624 aud_if_cfg.db5_lsv = 0;
1625
1626 hdmi_core_audio_infoframe_config(&aud_if_cfg);
1627 return 0;
951} 1628}
952 1629
953bool hdmi_mode_has_audio(void) 1630static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
1631 struct snd_soc_dai *dai)
954{ 1632{
955 if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI) 1633 int err = 0;
956 return true; 1634 switch (cmd) {
957 else 1635 case SNDRV_PCM_TRIGGER_START:
958 return false; 1636 case SNDRV_PCM_TRIGGER_RESUME:
959} 1637 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1638 REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
1639 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
1640 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
1641 break;
960 1642
961int hdmi_audio_config(struct omap_dss_audio *audio) 1643 case SNDRV_PCM_TRIGGER_STOP:
962{ 1644 case SNDRV_PCM_TRIGGER_SUSPEND:
963 return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio); 1645 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1646 REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
1647 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
1648 REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
1649 break;
1650 default:
1651 err = -EINVAL;
1652 }
1653 return err;
964} 1654}
965 1655
966#endif 1656static int hdmi_audio_startup(struct snd_pcm_substream *substream,
967 1657 struct snd_soc_dai *dai)
968static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
969{ 1658{
970 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 1659 if (!hdmi.mode) {
971 const char *def_disp_name = omapdss_get_default_display_name(); 1660 pr_err("Current video settings do not support audio.\n");
972 struct omap_dss_device *def_dssdev; 1661 return -EIO;
973 int i;
974
975 def_dssdev = NULL;
976
977 for (i = 0; i < pdata->num_devices; ++i) {
978 struct omap_dss_device *dssdev = pdata->devices[i];
979
980 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
981 continue;
982
983 if (def_dssdev == NULL)
984 def_dssdev = dssdev;
985
986 if (def_disp_name != NULL &&
987 strcmp(dssdev->name, def_disp_name) == 0) {
988 def_dssdev = dssdev;
989 break;
990 }
991 } 1662 }
992 1663 return 0;
993 return def_dssdev;
994} 1664}
995 1665
996static void __init hdmi_probe_pdata(struct platform_device *pdev) 1666static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
997{ 1667};
998 struct omap_dss_device *plat_dssdev;
999 struct omap_dss_device *dssdev;
1000 struct omap_dss_hdmi_data *priv;
1001 int r;
1002
1003 plat_dssdev = hdmi_find_dssdev(pdev);
1004
1005 if (!plat_dssdev)
1006 return;
1007
1008 dssdev = dss_alloc_and_init_device(&pdev->dev);
1009 if (!dssdev)
1010 return;
1011
1012 dss_copy_device_pdata(dssdev, plat_dssdev);
1013 1668
1014 priv = dssdev->data; 1669static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
1670 .hw_params = hdmi_audio_hw_params,
1671 .trigger = hdmi_audio_trigger,
1672 .startup = hdmi_audio_startup,
1673};
1015 1674
1016 hdmi.ct_cp_hpd_gpio = priv->ct_cp_hpd_gpio; 1675static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
1017 hdmi.ls_oe_gpio = priv->ls_oe_gpio; 1676 .name = "hdmi-audio-codec",
1018 hdmi.hpd_gpio = priv->hpd_gpio; 1677 .playback = {
1678 .channels_min = 2,
1679 .channels_max = 2,
1680 .rates = SNDRV_PCM_RATE_32000 |
1681 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
1682 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1683 SNDRV_PCM_FMTBIT_S24_LE,
1684 },
1685 .ops = &hdmi_audio_codec_ops,
1686};
1687#endif
1019 1688
1020 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; 1689static int hdmi_get_clocks(struct platform_device *pdev)
1690{
1691 struct clk *clk;
1021 1692
1022 r = hdmi_init_display(dssdev); 1693 clk = clk_get(&pdev->dev, "sys_clk");
1023 if (r) { 1694 if (IS_ERR(clk)) {
1024 DSSERR("device %s init failed: %d\n", dssdev->name, r); 1695 DSSERR("can't get sys_clk\n");
1025 dss_put_device(dssdev); 1696 return PTR_ERR(clk);
1026 return;
1027 } 1697 }
1028 1698
1029 r = omapdss_output_set_device(&hdmi.output, dssdev); 1699 hdmi.sys_clk = clk;
1030 if (r) {
1031 DSSERR("failed to connect output to new device: %s\n",
1032 dssdev->name);
1033 dss_put_device(dssdev);
1034 return;
1035 }
1036 1700
1037 r = dss_add_device(dssdev); 1701 clk = clk_get(&pdev->dev, "dss_48mhz_clk");
1038 if (r) { 1702 if (IS_ERR(clk)) {
1039 DSSERR("device %s register failed: %d\n", dssdev->name, r); 1703 DSSERR("can't get hdmi_clk\n");
1040 omapdss_output_unset_device(&hdmi.output); 1704 clk_put(hdmi.sys_clk);
1041 hdmi_uninit_display(dssdev); 1705 return PTR_ERR(clk);
1042 dss_put_device(dssdev);
1043 return;
1044 } 1706 }
1045}
1046 1707
1047static void __init hdmi_init_output(struct platform_device *pdev) 1708 hdmi.hdmi_clk = clk;
1048{
1049 struct omap_dss_output *out = &hdmi.output;
1050 1709
1051 out->pdev = pdev; 1710 return 0;
1052 out->id = OMAP_DSS_OUTPUT_HDMI;
1053 out->type = OMAP_DISPLAY_TYPE_HDMI;
1054
1055 dss_register_output(out);
1056} 1711}
1057 1712
1058static void __exit hdmi_uninit_output(struct platform_device *pdev) 1713static void hdmi_put_clocks(void)
1059{ 1714{
1060 struct omap_dss_output *out = &hdmi.output; 1715 if (hdmi.sys_clk)
1061 1716 clk_put(hdmi.sys_clk);
1062 dss_unregister_output(out); 1717 if (hdmi.hdmi_clk)
1718 clk_put(hdmi.hdmi_clk);
1063} 1719}
1064 1720
1065/* HDMI HW IP initialisation */ 1721/* HDMI HW IP initialisation */
1066static int __init omapdss_hdmihw_probe(struct platform_device *pdev) 1722static int omapdss_hdmihw_probe(struct platform_device *pdev)
1067{ 1723{
1068 struct resource *res; 1724 struct resource *hdmi_mem;
1069 int r; 1725 int r;
1070 1726
1727 hdmi.pdata = pdev->dev.platform_data;
1071 hdmi.pdev = pdev; 1728 hdmi.pdev = pdev;
1072 1729
1073 mutex_init(&hdmi.lock); 1730 mutex_init(&hdmi.lock);
1074 mutex_init(&hdmi.ip_data.lock);
1075 1731
1076 res = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); 1732 hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
1077 if (!res) { 1733 if (!hdmi_mem) {
1078 DSSERR("can't get IORESOURCE_MEM HDMI\n"); 1734 DSSERR("can't get IORESOURCE_MEM HDMI\n");
1079 return -EINVAL; 1735 return -EINVAL;
1080 } 1736 }
1081 1737
1082 /* Base address taken from platform */ 1738 /* Base address taken from platform */
1083 hdmi.ip_data.base_wp = devm_request_and_ioremap(&pdev->dev, res); 1739 hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem));
1084 if (!hdmi.ip_data.base_wp) { 1740 if (!hdmi.base_wp) {
1085 DSSERR("can't ioremap WP\n"); 1741 DSSERR("can't ioremap WP\n");
1086 return -ENOMEM; 1742 return -ENOMEM;
1087 } 1743 }
1088 1744
1089 r = hdmi_get_clocks(pdev); 1745 r = hdmi_get_clocks(pdev);
1090 if (r) { 1746 if (r) {
1091 DSSERR("can't get clocks\n"); 1747 iounmap(hdmi.base_wp);
1092 return r; 1748 return r;
1093 } 1749 }
1094 1750
1095 pm_runtime_enable(&pdev->dev); 1751 pm_runtime_enable(&pdev->dev);
1096 1752
1097 hdmi.ip_data.core_sys_offset = HDMI_CORE_SYS; 1753 hdmi_panel_init();
1098 hdmi.ip_data.core_av_offset = HDMI_CORE_AV;
1099 hdmi.ip_data.pll_offset = HDMI_PLLCTRL;
1100 hdmi.ip_data.phy_offset = HDMI_PHY;
1101 1754
1102 r = hdmi_panel_init(); 1755#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1756 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1757
1758 /* Register ASoC codec DAI */
1759 r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
1760 &hdmi_codec_dai_drv, 1);
1103 if (r) { 1761 if (r) {
1104 DSSERR("can't init panel\n"); 1762 DSSERR("can't register ASoC HDMI audio codec\n");
1105 goto err_panel_init; 1763 return r;
1106 } 1764 }
1107 1765#endif
1108 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
1109
1110 hdmi_init_output(pdev);
1111
1112 hdmi_probe_pdata(pdev);
1113
1114 return 0;
1115
1116err_panel_init:
1117 hdmi_put_clocks();
1118 return r;
1119}
1120
1121static int __exit hdmi_remove_child(struct device *dev, void *data)
1122{
1123 struct omap_dss_device *dssdev = to_dss_device(dev);
1124 hdmi_uninit_display(dssdev);
1125 return 0; 1766 return 0;
1126} 1767}
1127 1768
1128static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) 1769static int omapdss_hdmihw_remove(struct platform_device *pdev)
1129{ 1770{
1130 device_for_each_child(&pdev->dev, NULL, hdmi_remove_child);
1131
1132 dss_unregister_child_devices(&pdev->dev);
1133
1134 hdmi_panel_exit(); 1771 hdmi_panel_exit();
1135 1772
1136 hdmi_uninit_output(pdev); 1773#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
1774 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
1775 snd_soc_unregister_codec(&pdev->dev);
1776#endif
1137 1777
1138 pm_runtime_disable(&pdev->dev); 1778 pm_runtime_disable(&pdev->dev);
1139 1779
1140 hdmi_put_clocks(); 1780 hdmi_put_clocks();
1141 1781
1782 iounmap(hdmi.base_wp);
1783
1142 return 0; 1784 return 0;
1143} 1785}
1144 1786
1145static int hdmi_runtime_suspend(struct device *dev) 1787static int hdmi_runtime_suspend(struct device *dev)
1146{ 1788{
1147 clk_disable_unprepare(hdmi.sys_clk); 1789 clk_disable(hdmi.hdmi_clk);
1790 clk_disable(hdmi.sys_clk);
1148 1791
1149 dispc_runtime_put(); 1792 dispc_runtime_put();
1793 dss_runtime_put();
1150 1794
1151 return 0; 1795 return 0;
1152} 1796}
@@ -1155,13 +1799,24 @@ static int hdmi_runtime_resume(struct device *dev)
1155{ 1799{
1156 int r; 1800 int r;
1157 1801
1802 r = dss_runtime_get();
1803 if (r < 0)
1804 goto err_get_dss;
1805
1158 r = dispc_runtime_get(); 1806 r = dispc_runtime_get();
1159 if (r < 0) 1807 if (r < 0)
1160 return r; 1808 goto err_get_dispc;
1809
1161 1810
1162 clk_prepare_enable(hdmi.sys_clk); 1811 clk_enable(hdmi.sys_clk);
1812 clk_enable(hdmi.hdmi_clk);
1163 1813
1164 return 0; 1814 return 0;
1815
1816err_get_dispc:
1817 dss_runtime_put();
1818err_get_dss:
1819 return r;
1165} 1820}
1166 1821
1167static const struct dev_pm_ops hdmi_pm_ops = { 1822static const struct dev_pm_ops hdmi_pm_ops = {
@@ -1170,7 +1825,8 @@ static const struct dev_pm_ops hdmi_pm_ops = {
1170}; 1825};
1171 1826
1172static struct platform_driver omapdss_hdmihw_driver = { 1827static struct platform_driver omapdss_hdmihw_driver = {
1173 .remove = __exit_p(omapdss_hdmihw_remove), 1828 .probe = omapdss_hdmihw_probe,
1829 .remove = omapdss_hdmihw_remove,
1174 .driver = { 1830 .driver = {
1175 .name = "omapdss_hdmi", 1831 .name = "omapdss_hdmi",
1176 .owner = THIS_MODULE, 1832 .owner = THIS_MODULE,
@@ -1178,12 +1834,12 @@ static struct platform_driver omapdss_hdmihw_driver = {
1178 }, 1834 },
1179}; 1835};
1180 1836
1181int __init hdmi_init_platform_driver(void) 1837int hdmi_init_platform_driver(void)
1182{ 1838{
1183 return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe); 1839 return platform_driver_register(&omapdss_hdmihw_driver);
1184} 1840}
1185 1841
1186void __exit hdmi_uninit_platform_driver(void) 1842void hdmi_uninit_platform_driver(void)
1187{ 1843{
1188 platform_driver_unregister(&omapdss_hdmihw_driver); 1844 return platform_driver_unregister(&omapdss_hdmihw_driver);
1189} 1845}
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
deleted file mode 100644
index dfb8eda81b6..00000000000
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ /dev/null
@@ -1,414 +0,0 @@
1/*
2 * hdmi_panel.c
3 *
4 * HDMI library support functions for TI OMAP4 processors.
5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 * Authors: Mythri P k <mythripk@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/kernel.h>
23#include <linux/err.h>
24#include <linux/io.h>
25#include <linux/mutex.h>
26#include <linux/module.h>
27#include <video/omapdss.h>
28#include <linux/slab.h>
29
30#include "dss.h"
31
32static struct {
33 /* This protects the panel ops, mainly when accessing the HDMI IP. */
34 struct mutex lock;
35#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
36 /* This protects the audio ops, specifically. */
37 spinlock_t audio_lock;
38#endif
39} hdmi;
40
41
42static int hdmi_panel_probe(struct omap_dss_device *dssdev)
43{
44 /* Initialize default timings to VGA in DVI mode */
45 const struct omap_video_timings default_timings = {
46 .x_res = 640,
47 .y_res = 480,
48 .pixel_clock = 25175,
49 .hsw = 96,
50 .hfp = 16,
51 .hbp = 48,
52 .vsw = 2,
53 .vfp = 11,
54 .vbp = 31,
55
56 .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
57 .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
58
59 .interlace = false,
60 };
61
62 DSSDBG("ENTER hdmi_panel_probe\n");
63
64 dssdev->panel.timings = default_timings;
65
66 DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n",
67 dssdev->panel.timings.x_res,
68 dssdev->panel.timings.y_res);
69
70 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
71
72 return 0;
73}
74
75static void hdmi_panel_remove(struct omap_dss_device *dssdev)
76{
77
78}
79
80#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
81static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
82{
83 unsigned long flags;
84 int r;
85
86 mutex_lock(&hdmi.lock);
87 spin_lock_irqsave(&hdmi.audio_lock, flags);
88
89 /* enable audio only if the display is active and supports audio */
90 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
91 !hdmi_mode_has_audio()) {
92 DSSERR("audio not supported or display is off\n");
93 r = -EPERM;
94 goto err;
95 }
96
97 r = hdmi_audio_enable();
98
99 if (!r)
100 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
101
102err:
103 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
104 mutex_unlock(&hdmi.lock);
105 return r;
106}
107
108static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
109{
110 unsigned long flags;
111
112 spin_lock_irqsave(&hdmi.audio_lock, flags);
113
114 hdmi_audio_disable();
115
116 dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
117
118 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
119}
120
121static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
122{
123 unsigned long flags;
124 int r;
125
126 spin_lock_irqsave(&hdmi.audio_lock, flags);
127 /*
128 * No need to check the panel state. It was checked when trasitioning
129 * to AUDIO_ENABLED.
130 */
131 if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) {
132 DSSERR("audio start from invalid state\n");
133 r = -EPERM;
134 goto err;
135 }
136
137 r = hdmi_audio_start();
138
139 if (!r)
140 dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
141
142err:
143 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
144 return r;
145}
146
147static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
148{
149 unsigned long flags;
150
151 spin_lock_irqsave(&hdmi.audio_lock, flags);
152
153 hdmi_audio_stop();
154 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
155
156 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
157}
158
159static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
160{
161 bool r = false;
162
163 mutex_lock(&hdmi.lock);
164
165 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
166 goto err;
167
168 if (!hdmi_mode_has_audio())
169 goto err;
170
171 r = true;
172err:
173 mutex_unlock(&hdmi.lock);
174 return r;
175}
176
177static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
178 struct omap_dss_audio *audio)
179{
180 unsigned long flags;
181 int r;
182
183 mutex_lock(&hdmi.lock);
184 spin_lock_irqsave(&hdmi.audio_lock, flags);
185
186 /* config audio only if the display is active and supports audio */
187 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
188 !hdmi_mode_has_audio()) {
189 DSSERR("audio not supported or display is off\n");
190 r = -EPERM;
191 goto err;
192 }
193
194 r = hdmi_audio_config(audio);
195
196 if (!r)
197 dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
198
199err:
200 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
201 mutex_unlock(&hdmi.lock);
202 return r;
203}
204
205#else
206static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
207{
208 return -EPERM;
209}
210
211static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
212{
213}
214
215static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
216{
217 return -EPERM;
218}
219
220static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
221{
222}
223
224static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
225{
226 return false;
227}
228
229static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
230 struct omap_dss_audio *audio)
231{
232 return -EPERM;
233}
234#endif
235
236static int hdmi_panel_enable(struct omap_dss_device *dssdev)
237{
238 int r = 0;
239 DSSDBG("ENTER hdmi_panel_enable\n");
240
241 mutex_lock(&hdmi.lock);
242
243 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
244 r = -EINVAL;
245 goto err;
246 }
247
248 omapdss_hdmi_display_set_timing(dssdev, &dssdev->panel.timings);
249
250 r = omapdss_hdmi_display_enable(dssdev);
251 if (r) {
252 DSSERR("failed to power on\n");
253 goto err;
254 }
255
256 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
257
258err:
259 mutex_unlock(&hdmi.lock);
260
261 return r;
262}
263
264static void hdmi_panel_disable(struct omap_dss_device *dssdev)
265{
266 mutex_lock(&hdmi.lock);
267
268 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
269 /*
270 * TODO: notify audio users that the display was disabled. For
271 * now, disable audio locally to not break our audio state
272 * machine.
273 */
274 hdmi_panel_audio_disable(dssdev);
275 omapdss_hdmi_display_disable(dssdev);
276 }
277
278 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
279
280 mutex_unlock(&hdmi.lock);
281}
282
283static void hdmi_get_timings(struct omap_dss_device *dssdev,
284 struct omap_video_timings *timings)
285{
286 mutex_lock(&hdmi.lock);
287
288 *timings = dssdev->panel.timings;
289
290 mutex_unlock(&hdmi.lock);
291}
292
293static void hdmi_set_timings(struct omap_dss_device *dssdev,
294 struct omap_video_timings *timings)
295{
296 DSSDBG("hdmi_set_timings\n");
297
298 mutex_lock(&hdmi.lock);
299
300 /*
301 * TODO: notify audio users that there was a timings change. For
302 * now, disable audio locally to not break our audio state machine.
303 */
304 hdmi_panel_audio_disable(dssdev);
305
306 omapdss_hdmi_display_set_timing(dssdev, timings);
307 dssdev->panel.timings = *timings;
308
309 mutex_unlock(&hdmi.lock);
310}
311
312static int hdmi_check_timings(struct omap_dss_device *dssdev,
313 struct omap_video_timings *timings)
314{
315 int r = 0;
316
317 DSSDBG("hdmi_check_timings\n");
318
319 mutex_lock(&hdmi.lock);
320
321 r = omapdss_hdmi_display_check_timing(dssdev, timings);
322
323 mutex_unlock(&hdmi.lock);
324 return r;
325}
326
327static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
328{
329 int r;
330 bool need_enable;
331
332 mutex_lock(&hdmi.lock);
333
334 need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
335
336 if (need_enable) {
337 r = omapdss_hdmi_core_enable(dssdev);
338 if (r)
339 goto err;
340 }
341
342 r = omapdss_hdmi_read_edid(buf, len);
343
344 if (need_enable)
345 omapdss_hdmi_core_disable(dssdev);
346err:
347 mutex_unlock(&hdmi.lock);
348
349 return r;
350}
351
352static bool hdmi_detect(struct omap_dss_device *dssdev)
353{
354 int r;
355 bool need_enable;
356
357 mutex_lock(&hdmi.lock);
358
359 need_enable = dssdev->state == OMAP_DSS_DISPLAY_DISABLED;
360
361 if (need_enable) {
362 r = omapdss_hdmi_core_enable(dssdev);
363 if (r)
364 goto err;
365 }
366
367 r = omapdss_hdmi_detect();
368
369 if (need_enable)
370 omapdss_hdmi_core_disable(dssdev);
371err:
372 mutex_unlock(&hdmi.lock);
373
374 return r;
375}
376
377static struct omap_dss_driver hdmi_driver = {
378 .probe = hdmi_panel_probe,
379 .remove = hdmi_panel_remove,
380 .enable = hdmi_panel_enable,
381 .disable = hdmi_panel_disable,
382 .get_timings = hdmi_get_timings,
383 .set_timings = hdmi_set_timings,
384 .check_timings = hdmi_check_timings,
385 .read_edid = hdmi_read_edid,
386 .detect = hdmi_detect,
387 .audio_enable = hdmi_panel_audio_enable,
388 .audio_disable = hdmi_panel_audio_disable,
389 .audio_start = hdmi_panel_audio_start,
390 .audio_stop = hdmi_panel_audio_stop,
391 .audio_supported = hdmi_panel_audio_supported,
392 .audio_config = hdmi_panel_audio_config,
393 .driver = {
394 .name = "hdmi_panel",
395 .owner = THIS_MODULE,
396 },
397};
398
399int hdmi_panel_init(void)
400{
401 mutex_init(&hdmi.lock);
402
403#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
404 spin_lock_init(&hdmi.audio_lock);
405#endif
406
407 return omap_dss_register_driver(&hdmi_driver);
408}
409
410void hdmi_panel_exit(void)
411{
412 omap_dss_unregister_driver(&hdmi_driver);
413
414}
diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/omap2/dss/manager-sysfs.c
deleted file mode 100644
index 9a2fb59b6f8..00000000000
--- a/drivers/video/omap2/dss/manager-sysfs.c
+++ /dev/null
@@ -1,512 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "MANAGER"
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/jiffies.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
37}
38
39static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 struct omap_dss_device *dssdev = mgr->get_device(mgr);
42
43 return snprintf(buf, PAGE_SIZE, "%s\n", dssdev ?
44 dssdev->name : "<none>");
45}
46
47static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
48 const char *buf, size_t size)
49{
50 int r = 0;
51 size_t len = size;
52 struct omap_dss_device *dssdev = NULL;
53
54 int match(struct omap_dss_device *dssdev, void *data)
55 {
56 const char *str = data;
57 return sysfs_streq(dssdev->name, str);
58 }
59
60 if (buf[size-1] == '\n')
61 --len;
62
63 if (len > 0)
64 dssdev = omap_dss_find_device((void *)buf, match);
65
66 if (len > 0 && dssdev == NULL)
67 return -EINVAL;
68
69 if (dssdev)
70 DSSDBG("display %s found\n", dssdev->name);
71
72 if (mgr->output) {
73 r = mgr->unset_output(mgr);
74 if (r) {
75 DSSERR("failed to unset current output\n");
76 goto put_device;
77 }
78 }
79
80 if (dssdev) {
81 struct omap_dss_output *out = dssdev->output;
82
83 /*
84 * a registered device should have an output connected to it
85 * already
86 */
87 if (!out) {
88 DSSERR("device has no output connected to it\n");
89 goto put_device;
90 }
91
92 r = mgr->set_output(mgr, out);
93 if (r) {
94 DSSERR("failed to set manager output\n");
95 goto put_device;
96 }
97
98 r = mgr->apply(mgr);
99 if (r) {
100 DSSERR("failed to apply dispc config\n");
101 goto put_device;
102 }
103 }
104
105put_device:
106 if (dssdev)
107 omap_dss_put_device(dssdev);
108
109 return r ? r : size;
110}
111
112static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
113 char *buf)
114{
115 struct omap_overlay_manager_info info;
116
117 mgr->get_manager_info(mgr, &info);
118
119 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
120}
121
122static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
123 const char *buf, size_t size)
124{
125 struct omap_overlay_manager_info info;
126 u32 color;
127 int r;
128
129 r = kstrtouint(buf, 0, &color);
130 if (r)
131 return r;
132
133 mgr->get_manager_info(mgr, &info);
134
135 info.default_color = color;
136
137 r = mgr->set_manager_info(mgr, &info);
138 if (r)
139 return r;
140
141 r = mgr->apply(mgr);
142 if (r)
143 return r;
144
145 return size;
146}
147
148static const char *trans_key_type_str[] = {
149 "gfx-destination",
150 "video-source",
151};
152
153static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
154 char *buf)
155{
156 enum omap_dss_trans_key_type key_type;
157 struct omap_overlay_manager_info info;
158
159 mgr->get_manager_info(mgr, &info);
160
161 key_type = info.trans_key_type;
162 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
163
164 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
165}
166
167static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
168 const char *buf, size_t size)
169{
170 enum omap_dss_trans_key_type key_type;
171 struct omap_overlay_manager_info info;
172 int r;
173
174 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
175 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
176 if (sysfs_streq(buf, trans_key_type_str[key_type]))
177 break;
178 }
179
180 if (key_type == ARRAY_SIZE(trans_key_type_str))
181 return -EINVAL;
182
183 mgr->get_manager_info(mgr, &info);
184
185 info.trans_key_type = key_type;
186
187 r = mgr->set_manager_info(mgr, &info);
188 if (r)
189 return r;
190
191 r = mgr->apply(mgr);
192 if (r)
193 return r;
194
195 return size;
196}
197
198static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
199 char *buf)
200{
201 struct omap_overlay_manager_info info;
202
203 mgr->get_manager_info(mgr, &info);
204
205 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
206}
207
208static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
209 const char *buf, size_t size)
210{
211 struct omap_overlay_manager_info info;
212 u32 key_value;
213 int r;
214
215 r = kstrtouint(buf, 0, &key_value);
216 if (r)
217 return r;
218
219 mgr->get_manager_info(mgr, &info);
220
221 info.trans_key = key_value;
222
223 r = mgr->set_manager_info(mgr, &info);
224 if (r)
225 return r;
226
227 r = mgr->apply(mgr);
228 if (r)
229 return r;
230
231 return size;
232}
233
234static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
235 char *buf)
236{
237 struct omap_overlay_manager_info info;
238
239 mgr->get_manager_info(mgr, &info);
240
241 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
242}
243
244static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
245 const char *buf, size_t size)
246{
247 struct omap_overlay_manager_info info;
248 bool enable;
249 int r;
250
251 r = strtobool(buf, &enable);
252 if (r)
253 return r;
254
255 mgr->get_manager_info(mgr, &info);
256
257 info.trans_enabled = enable;
258
259 r = mgr->set_manager_info(mgr, &info);
260 if (r)
261 return r;
262
263 r = mgr->apply(mgr);
264 if (r)
265 return r;
266
267 return size;
268}
269
270static ssize_t manager_alpha_blending_enabled_show(
271 struct omap_overlay_manager *mgr, char *buf)
272{
273 struct omap_overlay_manager_info info;
274
275 mgr->get_manager_info(mgr, &info);
276
277 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
278
279 return snprintf(buf, PAGE_SIZE, "%d\n",
280 info.partial_alpha_enabled);
281}
282
283static ssize_t manager_alpha_blending_enabled_store(
284 struct omap_overlay_manager *mgr,
285 const char *buf, size_t size)
286{
287 struct omap_overlay_manager_info info;
288 bool enable;
289 int r;
290
291 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
292
293 r = strtobool(buf, &enable);
294 if (r)
295 return r;
296
297 mgr->get_manager_info(mgr, &info);
298
299 info.partial_alpha_enabled = enable;
300
301 r = mgr->set_manager_info(mgr, &info);
302 if (r)
303 return r;
304
305 r = mgr->apply(mgr);
306 if (r)
307 return r;
308
309 return size;
310}
311
312static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
313 char *buf)
314{
315 struct omap_overlay_manager_info info;
316
317 mgr->get_manager_info(mgr, &info);
318
319 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
320}
321
322static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
323 const char *buf, size_t size)
324{
325 struct omap_overlay_manager_info info;
326 int r;
327 bool enable;
328
329 if (!dss_has_feature(FEAT_CPR))
330 return -ENODEV;
331
332 r = strtobool(buf, &enable);
333 if (r)
334 return r;
335
336 mgr->get_manager_info(mgr, &info);
337
338 if (info.cpr_enable == enable)
339 return size;
340
341 info.cpr_enable = enable;
342
343 r = mgr->set_manager_info(mgr, &info);
344 if (r)
345 return r;
346
347 r = mgr->apply(mgr);
348 if (r)
349 return r;
350
351 return size;
352}
353
354static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
355 char *buf)
356{
357 struct omap_overlay_manager_info info;
358
359 mgr->get_manager_info(mgr, &info);
360
361 return snprintf(buf, PAGE_SIZE,
362 "%d %d %d %d %d %d %d %d %d\n",
363 info.cpr_coefs.rr,
364 info.cpr_coefs.rg,
365 info.cpr_coefs.rb,
366 info.cpr_coefs.gr,
367 info.cpr_coefs.gg,
368 info.cpr_coefs.gb,
369 info.cpr_coefs.br,
370 info.cpr_coefs.bg,
371 info.cpr_coefs.bb);
372}
373
374static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
375 const char *buf, size_t size)
376{
377 struct omap_overlay_manager_info info;
378 struct omap_dss_cpr_coefs coefs;
379 int r, i;
380 s16 *arr;
381
382 if (!dss_has_feature(FEAT_CPR))
383 return -ENODEV;
384
385 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
386 &coefs.rr, &coefs.rg, &coefs.rb,
387 &coefs.gr, &coefs.gg, &coefs.gb,
388 &coefs.br, &coefs.bg, &coefs.bb) != 9)
389 return -EINVAL;
390
391 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
392 coefs.gr, coefs.gg, coefs.gb,
393 coefs.br, coefs.bg, coefs.bb };
394
395 for (i = 0; i < 9; ++i) {
396 if (arr[i] < -512 || arr[i] > 511)
397 return -EINVAL;
398 }
399
400 mgr->get_manager_info(mgr, &info);
401
402 info.cpr_coefs = coefs;
403
404 r = mgr->set_manager_info(mgr, &info);
405 if (r)
406 return r;
407
408 r = mgr->apply(mgr);
409 if (r)
410 return r;
411
412 return size;
413}
414
415struct manager_attribute {
416 struct attribute attr;
417 ssize_t (*show)(struct omap_overlay_manager *, char *);
418 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
419};
420
421#define MANAGER_ATTR(_name, _mode, _show, _store) \
422 struct manager_attribute manager_attr_##_name = \
423 __ATTR(_name, _mode, _show, _store)
424
425static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
426static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
427 manager_display_show, manager_display_store);
428static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
429 manager_default_color_show, manager_default_color_store);
430static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
431 manager_trans_key_type_show, manager_trans_key_type_store);
432static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
433 manager_trans_key_value_show, manager_trans_key_value_store);
434static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
435 manager_trans_key_enabled_show,
436 manager_trans_key_enabled_store);
437static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
438 manager_alpha_blending_enabled_show,
439 manager_alpha_blending_enabled_store);
440static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
441 manager_cpr_enable_show,
442 manager_cpr_enable_store);
443static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
444 manager_cpr_coef_show,
445 manager_cpr_coef_store);
446
447
448static struct attribute *manager_sysfs_attrs[] = {
449 &manager_attr_name.attr,
450 &manager_attr_display.attr,
451 &manager_attr_default_color.attr,
452 &manager_attr_trans_key_type.attr,
453 &manager_attr_trans_key_value.attr,
454 &manager_attr_trans_key_enabled.attr,
455 &manager_attr_alpha_blending_enabled.attr,
456 &manager_attr_cpr_enable.attr,
457 &manager_attr_cpr_coef.attr,
458 NULL
459};
460
461static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
462 char *buf)
463{
464 struct omap_overlay_manager *manager;
465 struct manager_attribute *manager_attr;
466
467 manager = container_of(kobj, struct omap_overlay_manager, kobj);
468 manager_attr = container_of(attr, struct manager_attribute, attr);
469
470 if (!manager_attr->show)
471 return -ENOENT;
472
473 return manager_attr->show(manager, buf);
474}
475
476static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
477 const char *buf, size_t size)
478{
479 struct omap_overlay_manager *manager;
480 struct manager_attribute *manager_attr;
481
482 manager = container_of(kobj, struct omap_overlay_manager, kobj);
483 manager_attr = container_of(attr, struct manager_attribute, attr);
484
485 if (!manager_attr->store)
486 return -ENOENT;
487
488 return manager_attr->store(manager, buf, size);
489}
490
491static const struct sysfs_ops manager_sysfs_ops = {
492 .show = manager_attr_show,
493 .store = manager_attr_store,
494};
495
496static struct kobj_type manager_ktype = {
497 .sysfs_ops = &manager_sysfs_ops,
498 .default_attrs = manager_sysfs_attrs,
499};
500
501int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
502 struct platform_device *pdev)
503{
504 return kobject_init_and_add(&mgr->kobj, &manager_ktype,
505 &pdev->dev.kobj, "manager%d", mgr->id);
506}
507
508void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
509{
510 kobject_del(&mgr->kobj);
511 kobject_put(&mgr->kobj);
512}
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 2551eaa14c4..13d72d5c714 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -26,223 +26,1649 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/spinlock.h>
29#include <linux/jiffies.h> 30#include <linux/jiffies.h>
30 31
31#include <video/omapdss.h> 32#include <video/omapdss.h>
33#include <plat/cpu.h>
32 34
33#include "dss.h" 35#include "dss.h"
34#include "dss_features.h" 36#include "dss_features.h"
35 37
36static int num_managers; 38static int num_managers;
37static struct omap_overlay_manager *managers; 39static struct list_head manager_list;
38 40
39int dss_init_overlay_managers(struct platform_device *pdev) 41static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
40{ 42{
41 int i, r; 43 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
44}
42 45
43 num_managers = dss_feat_get_num_mgrs(); 46static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
47{
48 return snprintf(buf, PAGE_SIZE, "%s\n",
49 mgr->device ? mgr->device->name : "<none>");
50}
44 51
45 managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers, 52static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
46 GFP_KERNEL); 53 const char *buf, size_t size)
54{
55 int r = 0;
56 size_t len = size;
57 struct omap_dss_device *dssdev = NULL;
47 58
48 BUG_ON(managers == NULL); 59 int match(struct omap_dss_device *dssdev, void *data)
60 {
61 const char *str = data;
62 return sysfs_streq(dssdev->name, str);
63 }
49 64
50 for (i = 0; i < num_managers; ++i) { 65 if (buf[size-1] == '\n')
51 struct omap_overlay_manager *mgr = &managers[i]; 66 --len;
52 67
53 switch (i) { 68 if (len > 0)
54 case 0: 69 dssdev = omap_dss_find_device((void *)buf, match);
55 mgr->name = "lcd"; 70
56 mgr->id = OMAP_DSS_CHANNEL_LCD; 71 if (len > 0 && dssdev == NULL)
57 break; 72 return -EINVAL;
58 case 1: 73
59 mgr->name = "tv"; 74 if (dssdev)
60 mgr->id = OMAP_DSS_CHANNEL_DIGIT; 75 DSSDBG("display %s found\n", dssdev->name);
61 break; 76
62 case 2: 77 if (mgr->device) {
63 mgr->name = "lcd2"; 78 r = mgr->unset_device(mgr);
64 mgr->id = OMAP_DSS_CHANNEL_LCD2; 79 if (r) {
65 break; 80 DSSERR("failed to unset display\n");
66 case 3: 81 goto put_device;
67 mgr->name = "lcd3";
68 mgr->id = OMAP_DSS_CHANNEL_LCD3;
69 break;
70 } 82 }
83 }
71 84
72 mgr->caps = 0; 85 if (dssdev) {
73 mgr->supported_displays = 86 r = mgr->set_device(mgr, dssdev);
74 dss_feat_get_supported_displays(mgr->id); 87 if (r) {
75 mgr->supported_outputs = 88 DSSERR("failed to set manager\n");
76 dss_feat_get_supported_outputs(mgr->id); 89 goto put_device;
90 }
91
92 r = mgr->apply(mgr);
93 if (r) {
94 DSSERR("failed to apply dispc config\n");
95 goto put_device;
96 }
97 }
98
99put_device:
100 if (dssdev)
101 omap_dss_put_device(dssdev);
102
103 return r ? r : size;
104}
105
106static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
107 char *buf)
108{
109 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.default_color);
110}
111
112static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
113 const char *buf, size_t size)
114{
115 struct omap_overlay_manager_info info;
116 u32 color;
117 int r;
118
119 if (sscanf(buf, "%d", &color) != 1)
120 return -EINVAL;
121
122 mgr->get_manager_info(mgr, &info);
123
124 info.default_color = color;
125
126 r = mgr->set_manager_info(mgr, &info);
127 if (r)
128 return r;
129
130 r = mgr->apply(mgr);
131 if (r)
132 return r;
133
134 return size;
135}
136
137static const char *trans_key_type_str[] = {
138 "gfx-destination",
139 "video-source",
140};
141
142static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
143 char *buf)
144{
145 enum omap_dss_trans_key_type key_type;
146
147 key_type = mgr->info.trans_key_type;
148 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
149
150 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
151}
152
153static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
154 const char *buf, size_t size)
155{
156 enum omap_dss_trans_key_type key_type;
157 struct omap_overlay_manager_info info;
158 int r;
159
160 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
161 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
162 if (sysfs_streq(buf, trans_key_type_str[key_type]))
163 break;
164 }
165
166 if (key_type == ARRAY_SIZE(trans_key_type_str))
167 return -EINVAL;
168
169 mgr->get_manager_info(mgr, &info);
170
171 info.trans_key_type = key_type;
172
173 r = mgr->set_manager_info(mgr, &info);
174 if (r)
175 return r;
176
177 r = mgr->apply(mgr);
178 if (r)
179 return r;
180
181 return size;
182}
183
184static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
185 char *buf)
186{
187 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_key);
188}
189
190static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
191 const char *buf, size_t size)
192{
193 struct omap_overlay_manager_info info;
194 u32 key_value;
195 int r;
196
197 if (sscanf(buf, "%d", &key_value) != 1)
198 return -EINVAL;
199
200 mgr->get_manager_info(mgr, &info);
201
202 info.trans_key = key_value;
203
204 r = mgr->set_manager_info(mgr, &info);
205 if (r)
206 return r;
207
208 r = mgr->apply(mgr);
209 if (r)
210 return r;
211
212 return size;
213}
214
215static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
216 char *buf)
217{
218 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled);
219}
220
221static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
222 const char *buf, size_t size)
223{
224 struct omap_overlay_manager_info info;
225 int enable;
226 int r;
227
228 if (sscanf(buf, "%d", &enable) != 1)
229 return -EINVAL;
230
231 mgr->get_manager_info(mgr, &info);
232
233 info.trans_enabled = enable ? true : false;
234
235 r = mgr->set_manager_info(mgr, &info);
236 if (r)
237 return r;
238
239 r = mgr->apply(mgr);
240 if (r)
241 return r;
242
243 return size;
244}
245
246static ssize_t manager_alpha_blending_enabled_show(
247 struct omap_overlay_manager *mgr, char *buf)
248{
249 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.alpha_enabled);
250}
251
252static ssize_t manager_alpha_blending_enabled_store(
253 struct omap_overlay_manager *mgr,
254 const char *buf, size_t size)
255{
256 struct omap_overlay_manager_info info;
257 int enable;
258 int r;
259
260 if (sscanf(buf, "%d", &enable) != 1)
261 return -EINVAL;
262
263 mgr->get_manager_info(mgr, &info);
264
265 info.alpha_enabled = enable ? true : false;
266
267 r = mgr->set_manager_info(mgr, &info);
268 if (r)
269 return r;
270
271 r = mgr->apply(mgr);
272 if (r)
273 return r;
274
275 return size;
276}
277
278static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
279 char *buf)
280{
281 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable);
282}
283
284static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
285 const char *buf, size_t size)
286{
287 struct omap_overlay_manager_info info;
288 int v;
289 int r;
290 bool enable;
77 291
78 INIT_LIST_HEAD(&mgr->overlays); 292 if (!dss_has_feature(FEAT_CPR))
293 return -ENODEV;
79 294
80 r = dss_manager_kobj_init(mgr, pdev); 295 r = kstrtoint(buf, 0, &v);
296 if (r)
297 return r;
298
299 enable = !!v;
300
301 mgr->get_manager_info(mgr, &info);
302
303 if (info.cpr_enable == enable)
304 return size;
305
306 info.cpr_enable = enable;
307
308 r = mgr->set_manager_info(mgr, &info);
309 if (r)
310 return r;
311
312 r = mgr->apply(mgr);
313 if (r)
314 return r;
315
316 return size;
317}
318
319static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
320 char *buf)
321{
322 struct omap_overlay_manager_info info;
323
324 mgr->get_manager_info(mgr, &info);
325
326 return snprintf(buf, PAGE_SIZE,
327 "%d %d %d %d %d %d %d %d %d\n",
328 info.cpr_coefs.rr,
329 info.cpr_coefs.rg,
330 info.cpr_coefs.rb,
331 info.cpr_coefs.gr,
332 info.cpr_coefs.gg,
333 info.cpr_coefs.gb,
334 info.cpr_coefs.br,
335 info.cpr_coefs.bg,
336 info.cpr_coefs.bb);
337}
338
339static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
340 const char *buf, size_t size)
341{
342 struct omap_overlay_manager_info info;
343 struct omap_dss_cpr_coefs coefs;
344 int r, i;
345 s16 *arr;
346
347 if (!dss_has_feature(FEAT_CPR))
348 return -ENODEV;
349
350 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
351 &coefs.rr, &coefs.rg, &coefs.rb,
352 &coefs.gr, &coefs.gg, &coefs.gb,
353 &coefs.br, &coefs.bg, &coefs.bb) != 9)
354 return -EINVAL;
355
356 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
357 coefs.gr, coefs.gg, coefs.gb,
358 coefs.br, coefs.bg, coefs.bb };
359
360 for (i = 0; i < 9; ++i) {
361 if (arr[i] < -512 || arr[i] > 511)
362 return -EINVAL;
363 }
364
365 mgr->get_manager_info(mgr, &info);
366
367 info.cpr_coefs = coefs;
368
369 r = mgr->set_manager_info(mgr, &info);
370 if (r)
371 return r;
372
373 r = mgr->apply(mgr);
374 if (r)
375 return r;
376
377 return size;
378}
379
380struct manager_attribute {
381 struct attribute attr;
382 ssize_t (*show)(struct omap_overlay_manager *, char *);
383 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
384};
385
386#define MANAGER_ATTR(_name, _mode, _show, _store) \
387 struct manager_attribute manager_attr_##_name = \
388 __ATTR(_name, _mode, _show, _store)
389
390static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
391static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
392 manager_display_show, manager_display_store);
393static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
394 manager_default_color_show, manager_default_color_store);
395static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
396 manager_trans_key_type_show, manager_trans_key_type_store);
397static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
398 manager_trans_key_value_show, manager_trans_key_value_store);
399static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
400 manager_trans_key_enabled_show,
401 manager_trans_key_enabled_store);
402static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
403 manager_alpha_blending_enabled_show,
404 manager_alpha_blending_enabled_store);
405static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
406 manager_cpr_enable_show,
407 manager_cpr_enable_store);
408static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
409 manager_cpr_coef_show,
410 manager_cpr_coef_store);
411
412
413static struct attribute *manager_sysfs_attrs[] = {
414 &manager_attr_name.attr,
415 &manager_attr_display.attr,
416 &manager_attr_default_color.attr,
417 &manager_attr_trans_key_type.attr,
418 &manager_attr_trans_key_value.attr,
419 &manager_attr_trans_key_enabled.attr,
420 &manager_attr_alpha_blending_enabled.attr,
421 &manager_attr_cpr_enable.attr,
422 &manager_attr_cpr_coef.attr,
423 NULL
424};
425
426static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
427 char *buf)
428{
429 struct omap_overlay_manager *manager;
430 struct manager_attribute *manager_attr;
431
432 manager = container_of(kobj, struct omap_overlay_manager, kobj);
433 manager_attr = container_of(attr, struct manager_attribute, attr);
434
435 if (!manager_attr->show)
436 return -ENOENT;
437
438 return manager_attr->show(manager, buf);
439}
440
441static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
442 const char *buf, size_t size)
443{
444 struct omap_overlay_manager *manager;
445 struct manager_attribute *manager_attr;
446
447 manager = container_of(kobj, struct omap_overlay_manager, kobj);
448 manager_attr = container_of(attr, struct manager_attribute, attr);
449
450 if (!manager_attr->store)
451 return -ENOENT;
452
453 return manager_attr->store(manager, buf, size);
454}
455
456static const struct sysfs_ops manager_sysfs_ops = {
457 .show = manager_attr_show,
458 .store = manager_attr_store,
459};
460
461static struct kobj_type manager_ktype = {
462 .sysfs_ops = &manager_sysfs_ops,
463 .default_attrs = manager_sysfs_attrs,
464};
465
466/*
467 * We have 4 levels of cache for the dispc settings. First two are in SW and
468 * the latter two in HW.
469 *
470 * +--------------------+
471 * |overlay/manager_info|
472 * +--------------------+
473 * v
474 * apply()
475 * v
476 * +--------------------+
477 * | dss_cache |
478 * +--------------------+
479 * v
480 * configure()
481 * v
482 * +--------------------+
483 * | shadow registers |
484 * +--------------------+
485 * v
486 * VFP or lcd/digit_enable
487 * v
488 * +--------------------+
489 * | registers |
490 * +--------------------+
491 */
492
493struct overlay_cache_data {
494 /* If true, cache changed, but not written to shadow registers. Set
495 * in apply(), cleared when registers written. */
496 bool dirty;
497 /* If true, shadow registers contain changed values not yet in real
498 * registers. Set when writing to shadow registers, cleared at
499 * VSYNC/EVSYNC */
500 bool shadow_dirty;
501
502 bool enabled;
503
504 struct omap_overlay_info info;
505
506 enum omap_channel channel;
507 bool replication;
508 bool ilace;
509
510 u32 fifo_low;
511 u32 fifo_high;
512};
513
514struct manager_cache_data {
515 /* If true, cache changed, but not written to shadow registers. Set
516 * in apply(), cleared when registers written. */
517 bool dirty;
518 /* If true, shadow registers contain changed values not yet in real
519 * registers. Set when writing to shadow registers, cleared at
520 * VSYNC/EVSYNC */
521 bool shadow_dirty;
522
523 struct omap_overlay_manager_info info;
524
525 bool manual_update;
526 bool do_manual_update;
527
528 /* manual update region */
529 u16 x, y, w, h;
530
531 /* enlarge the update area if the update area contains scaled
532 * overlays */
533 bool enlarge_update_area;
534};
535
536static struct {
537 spinlock_t lock;
538 struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
539 struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
540
541 bool irq_enabled;
542} dss_cache;
543
544
545
546static int omap_dss_set_device(struct omap_overlay_manager *mgr,
547 struct omap_dss_device *dssdev)
548{
549 int i;
550 int r;
551
552 if (dssdev->manager) {
553 DSSERR("display '%s' already has a manager '%s'\n",
554 dssdev->name, dssdev->manager->name);
555 return -EINVAL;
556 }
557
558 if ((mgr->supported_displays & dssdev->type) == 0) {
559 DSSERR("display '%s' does not support manager '%s'\n",
560 dssdev->name, mgr->name);
561 return -EINVAL;
562 }
563
564 for (i = 0; i < mgr->num_overlays; i++) {
565 struct omap_overlay *ovl = mgr->overlays[i];
566
567 if (ovl->manager != mgr || !ovl->info.enabled)
568 continue;
569
570 r = dss_check_overlay(ovl, dssdev);
81 if (r) 571 if (r)
82 DSSERR("failed to create sysfs file\n"); 572 return r;
83 } 573 }
84 574
575 dssdev->manager = mgr;
576 mgr->device = dssdev;
577 mgr->device_changed = true;
578
85 return 0; 579 return 0;
86} 580}
87 581
88void dss_uninit_overlay_managers(struct platform_device *pdev) 582static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
89{ 583{
584 if (!mgr->device) {
585 DSSERR("failed to unset display, display not set.\n");
586 return -EINVAL;
587 }
588
589 mgr->device->manager = NULL;
590 mgr->device = NULL;
591 mgr->device_changed = true;
592
593 return 0;
594}
595
596static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
597{
598 unsigned long timeout = msecs_to_jiffies(500);
599 u32 irq;
600
601 if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
602 irq = DISPC_IRQ_EVSYNC_ODD;
603 } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) {
604 irq = DISPC_IRQ_EVSYNC_EVEN;
605 } else {
606 if (mgr->id == OMAP_DSS_CHANNEL_LCD)
607 irq = DISPC_IRQ_VSYNC;
608 else
609 irq = DISPC_IRQ_VSYNC2;
610 }
611 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
612}
613
614static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
615{
616 unsigned long timeout = msecs_to_jiffies(500);
617 struct manager_cache_data *mc;
618 u32 irq;
619 int r;
90 int i; 620 int i;
621 struct omap_dss_device *dssdev = mgr->device;
91 622
92 for (i = 0; i < num_managers; ++i) { 623 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
93 struct omap_overlay_manager *mgr = &managers[i]; 624 return 0;
94 dss_manager_kobj_uninit(mgr); 625
626 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
627 return 0;
628
629 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
630 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
631 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
632 } else {
633 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
634 DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
95 } 635 }
96 636
97 kfree(managers); 637 mc = &dss_cache.manager_cache[mgr->id];
98 managers = NULL; 638 i = 0;
99 num_managers = 0; 639 while (1) {
640 unsigned long flags;
641 bool shadow_dirty, dirty;
642
643 spin_lock_irqsave(&dss_cache.lock, flags);
644 dirty = mc->dirty;
645 shadow_dirty = mc->shadow_dirty;
646 spin_unlock_irqrestore(&dss_cache.lock, flags);
647
648 if (!dirty && !shadow_dirty) {
649 r = 0;
650 break;
651 }
652
653 /* 4 iterations is the worst case:
654 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
655 * 2 - first VSYNC, dirty = true
656 * 3 - dirty = false, shadow_dirty = true
657 * 4 - shadow_dirty = false */
658 if (i++ == 3) {
659 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
660 mgr->id);
661 r = 0;
662 break;
663 }
664
665 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
666 if (r == -ERESTARTSYS)
667 break;
668
669 if (r) {
670 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
671 break;
672 }
673 }
674
675 return r;
100} 676}
101 677
102int omap_dss_get_num_overlay_managers(void) 678int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
103{ 679{
104 return num_managers; 680 unsigned long timeout = msecs_to_jiffies(500);
681 struct overlay_cache_data *oc;
682 struct omap_dss_device *dssdev;
683 u32 irq;
684 int r;
685 int i;
686
687 if (!ovl->manager)
688 return 0;
689
690 dssdev = ovl->manager->device;
691
692 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
693 return 0;
694
695 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
696 return 0;
697
698 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
699 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
700 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
701 } else {
702 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
703 DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
704 }
705
706 oc = &dss_cache.overlay_cache[ovl->id];
707 i = 0;
708 while (1) {
709 unsigned long flags;
710 bool shadow_dirty, dirty;
711
712 spin_lock_irqsave(&dss_cache.lock, flags);
713 dirty = oc->dirty;
714 shadow_dirty = oc->shadow_dirty;
715 spin_unlock_irqrestore(&dss_cache.lock, flags);
716
717 if (!dirty && !shadow_dirty) {
718 r = 0;
719 break;
720 }
721
722 /* 4 iterations is the worst case:
723 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
724 * 2 - first VSYNC, dirty = true
725 * 3 - dirty = false, shadow_dirty = true
726 * 4 - shadow_dirty = false */
727 if (i++ == 3) {
728 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
729 ovl->id);
730 r = 0;
731 break;
732 }
733
734 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
735 if (r == -ERESTARTSYS)
736 break;
737
738 if (r) {
739 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
740 break;
741 }
742 }
743
744 return r;
105} 745}
106EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
107 746
108struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) 747static int overlay_enabled(struct omap_overlay *ovl)
748{
749 return ovl->info.enabled && ovl->manager && ovl->manager->device;
750}
751
752/* Is rect1 a subset of rect2? */
753static bool rectangle_subset(int x1, int y1, int w1, int h1,
754 int x2, int y2, int w2, int h2)
755{
756 if (x1 < x2 || y1 < y2)
757 return false;
758
759 if (x1 + w1 > x2 + w2)
760 return false;
761
762 if (y1 + h1 > y2 + h2)
763 return false;
764
765 return true;
766}
767
768/* Do rect1 and rect2 overlap? */
769static bool rectangle_intersects(int x1, int y1, int w1, int h1,
770 int x2, int y2, int w2, int h2)
109{ 771{
110 if (num >= num_managers) 772 if (x1 >= x2 + w2)
111 return NULL; 773 return false;
112 774
113 return &managers[num]; 775 if (x2 >= x1 + w1)
776 return false;
777
778 if (y1 >= y2 + h2)
779 return false;
780
781 if (y2 >= y1 + h1)
782 return false;
783
784 return true;
114} 785}
115EXPORT_SYMBOL(omap_dss_get_overlay_manager);
116 786
117int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 787static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
118 const struct omap_overlay_manager_info *info)
119{ 788{
120 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { 789 struct omap_overlay_info *oi = &oc->info;
121 /* 790
122 * OMAP3 supports only graphics source transparency color key 791 if (oi->out_width != 0 && oi->width != oi->out_width)
123 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 792 return true;
124 * Alpha Mode. 793
794 if (oi->out_height != 0 && oi->height != oi->out_height)
795 return true;
796
797 return false;
798}
799
800static int configure_overlay(enum omap_plane plane)
801{
802 struct overlay_cache_data *c;
803 struct manager_cache_data *mc;
804 struct omap_overlay_info *oi;
805 struct omap_overlay_manager_info *mi;
806 u16 outw, outh;
807 u16 x, y, w, h;
808 u32 paddr;
809 int r;
810 u16 orig_w, orig_h, orig_outw, orig_outh;
811
812 DSSDBGF("%d", plane);
813
814 c = &dss_cache.overlay_cache[plane];
815 oi = &c->info;
816
817 if (!c->enabled) {
818 dispc_enable_plane(plane, 0);
819 return 0;
820 }
821
822 mc = &dss_cache.manager_cache[c->channel];
823 mi = &mc->info;
824
825 x = oi->pos_x;
826 y = oi->pos_y;
827 w = oi->width;
828 h = oi->height;
829 outw = oi->out_width == 0 ? oi->width : oi->out_width;
830 outh = oi->out_height == 0 ? oi->height : oi->out_height;
831 paddr = oi->paddr;
832
833 orig_w = w;
834 orig_h = h;
835 orig_outw = outw;
836 orig_outh = outh;
837
838 if (mc->manual_update && mc->do_manual_update) {
839 unsigned bpp;
840 unsigned scale_x_m = w, scale_x_d = outw;
841 unsigned scale_y_m = h, scale_y_d = outh;
842
843 /* If the overlay is outside the update region, disable it */
844 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
845 x, y, outw, outh)) {
846 dispc_enable_plane(plane, 0);
847 return 0;
848 }
849
850 switch (oi->color_mode) {
851 case OMAP_DSS_COLOR_NV12:
852 bpp = 8;
853 break;
854 case OMAP_DSS_COLOR_RGB16:
855 case OMAP_DSS_COLOR_ARGB16:
856 case OMAP_DSS_COLOR_YUV2:
857 case OMAP_DSS_COLOR_UYVY:
858 case OMAP_DSS_COLOR_RGBA16:
859 case OMAP_DSS_COLOR_RGBX16:
860 case OMAP_DSS_COLOR_ARGB16_1555:
861 case OMAP_DSS_COLOR_XRGB16_1555:
862 bpp = 16;
863 break;
864
865 case OMAP_DSS_COLOR_RGB24P:
866 bpp = 24;
867 break;
868
869 case OMAP_DSS_COLOR_RGB24U:
870 case OMAP_DSS_COLOR_ARGB32:
871 case OMAP_DSS_COLOR_RGBA32:
872 case OMAP_DSS_COLOR_RGBX32:
873 bpp = 32;
874 break;
875
876 default:
877 BUG();
878 }
879
880 if (mc->x > oi->pos_x) {
881 x = 0;
882 outw -= (mc->x - oi->pos_x);
883 paddr += (mc->x - oi->pos_x) *
884 scale_x_m / scale_x_d * bpp / 8;
885 } else {
886 x = oi->pos_x - mc->x;
887 }
888
889 if (mc->y > oi->pos_y) {
890 y = 0;
891 outh -= (mc->y - oi->pos_y);
892 paddr += (mc->y - oi->pos_y) *
893 scale_y_m / scale_y_d *
894 oi->screen_width * bpp / 8;
895 } else {
896 y = oi->pos_y - mc->y;
897 }
898
899 if (mc->w < (x + outw))
900 outw -= (x + outw) - (mc->w);
901
902 if (mc->h < (y + outh))
903 outh -= (y + outh) - (mc->h);
904
905 w = w * outw / orig_outw;
906 h = h * outh / orig_outh;
907
908 /* YUV mode overlay's input width has to be even and the
909 * algorithm above may adjust the width to be odd.
910 *
911 * Here we adjust the width if needed, preferring to increase
912 * the width if the original width was bigger.
125 */ 913 */
126 if (info->partial_alpha_enabled && info->trans_enabled 914 if ((w & 1) &&
127 && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) { 915 (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
128 DSSERR("check_manager: illegal transparency key\n"); 916 oi->color_mode == OMAP_DSS_COLOR_UYVY)) {
129 return -EINVAL; 917 if (orig_w > w)
918 w += 1;
919 else
920 w -= 1;
130 } 921 }
131 } 922 }
132 923
924 r = dispc_setup_plane(plane,
925 paddr,
926 oi->screen_width,
927 x, y,
928 w, h,
929 outw, outh,
930 oi->color_mode,
931 c->ilace,
932 oi->rotation_type,
933 oi->rotation,
934 oi->mirror,
935 oi->global_alpha,
936 oi->pre_mult_alpha,
937 c->channel,
938 oi->p_uv_addr);
939
940 if (r) {
941 /* this shouldn't happen */
942 DSSERR("dispc_setup_plane failed for ovl %d\n", plane);
943 dispc_enable_plane(plane, 0);
944 return r;
945 }
946
947 dispc_enable_replication(plane, c->replication);
948
949 dispc_set_fifo_threshold(plane, c->fifo_low, c->fifo_high);
950
951 dispc_enable_plane(plane, 1);
952
133 return 0; 953 return 0;
134} 954}
135 955
136static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr, 956static void configure_manager(enum omap_channel channel)
137 struct omap_overlay_info **overlay_infos) 957{
958 struct omap_overlay_manager_info *mi;
959
960 DSSDBGF("%d", channel);
961
962 /* picking info from the cache */
963 mi = &dss_cache.manager_cache[channel].info;
964
965 dispc_set_default_color(channel, mi->default_color);
966 dispc_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
967 dispc_enable_trans_key(channel, mi->trans_enabled);
968 dispc_enable_alpha_blending(channel, mi->alpha_enabled);
969 if (dss_has_feature(FEAT_CPR)) {
970 dispc_enable_cpr(channel, mi->cpr_enable);
971 dispc_set_cpr_coef(channel, &mi->cpr_coefs);
972 }
973}
974
975/* configure_dispc() tries to write values from cache to shadow registers.
976 * It writes only to those managers/overlays that are not busy.
977 * returns 0 if everything could be written to shadow registers.
978 * returns 1 if not everything could be written to shadow registers. */
979static int configure_dispc(void)
138{ 980{
139 struct omap_overlay *ovl1, *ovl2; 981 struct overlay_cache_data *oc;
140 struct omap_overlay_info *info1, *info2; 982 struct manager_cache_data *mc;
983 const int num_ovls = dss_feat_get_num_ovls();
984 const int num_mgrs = dss_feat_get_num_mgrs();
985 int i;
986 int r;
987 bool mgr_busy[MAX_DSS_MANAGERS];
988 bool mgr_go[MAX_DSS_MANAGERS];
989 bool busy;
990
991 r = 0;
992 busy = false;
993
994 for (i = 0; i < num_mgrs; i++) {
995 mgr_busy[i] = dispc_go_busy(i);
996 mgr_go[i] = false;
997 }
141 998
142 list_for_each_entry(ovl1, &mgr->overlays, list) { 999 /* Commit overlay settings */
143 info1 = overlay_infos[ovl1->id]; 1000 for (i = 0; i < num_ovls; ++i) {
1001 oc = &dss_cache.overlay_cache[i];
1002 mc = &dss_cache.manager_cache[oc->channel];
144 1003
145 if (info1 == NULL) 1004 if (!oc->dirty)
146 continue; 1005 continue;
147 1006
148 list_for_each_entry(ovl2, &mgr->overlays, list) { 1007 if (mc->manual_update && !mc->do_manual_update)
149 if (ovl1 == ovl2) 1008 continue;
150 continue;
151 1009
152 info2 = overlay_infos[ovl2->id]; 1010 if (mgr_busy[oc->channel]) {
1011 busy = true;
1012 continue;
1013 }
153 1014
154 if (info2 == NULL) 1015 r = configure_overlay(i);
155 continue; 1016 if (r)
1017 DSSERR("configure_overlay %d failed\n", i);
156 1018
157 if (info1->zorder == info2->zorder) { 1019 oc->dirty = false;
158 DSSERR("overlays %d and %d have the same " 1020 oc->shadow_dirty = true;
159 "zorder %d\n", 1021 mgr_go[oc->channel] = true;
160 ovl1->id, ovl2->id, info1->zorder); 1022 }
161 return -EINVAL; 1023
162 } 1024 /* Commit manager settings */
1025 for (i = 0; i < num_mgrs; ++i) {
1026 mc = &dss_cache.manager_cache[i];
1027
1028 if (!mc->dirty)
1029 continue;
1030
1031 if (mc->manual_update && !mc->do_manual_update)
1032 continue;
1033
1034 if (mgr_busy[i]) {
1035 busy = true;
1036 continue;
163 } 1037 }
1038
1039 configure_manager(i);
1040 mc->dirty = false;
1041 mc->shadow_dirty = true;
1042 mgr_go[i] = true;
164 } 1043 }
165 1044
166 return 0; 1045 /* set GO */
1046 for (i = 0; i < num_mgrs; ++i) {
1047 mc = &dss_cache.manager_cache[i];
1048
1049 if (!mgr_go[i])
1050 continue;
1051
1052 /* We don't need GO with manual update display. LCD iface will
1053 * always be turned off after frame, and new settings will be
1054 * taken in to use at next update */
1055 if (!mc->manual_update)
1056 dispc_go(i);
1057 }
1058
1059 if (busy)
1060 r = 1;
1061 else
1062 r = 0;
1063
1064 return r;
167} 1065}
168 1066
169int dss_mgr_check_timings(struct omap_overlay_manager *mgr, 1067/* Make the coordinates even. There are some strange problems with OMAP and
170 const struct omap_video_timings *timings) 1068 * partial DSI update when the update widths are odd. */
1069static void make_even(u16 *x, u16 *w)
171{ 1070{
172 if (!dispc_mgr_timings_ok(mgr->id, timings)) { 1071 u16 x1, x2;
173 DSSERR("check_manager: invalid timings\n");
174 return -EINVAL;
175 }
176 1072
177 return 0; 1073 x1 = *x;
1074 x2 = *x + *w;
1075
1076 x1 &= ~1;
1077 x2 = ALIGN(x2, 2);
1078
1079 *x = x1;
1080 *w = x2 - x1;
178} 1081}
179 1082
180static int dss_mgr_check_lcd_config(struct omap_overlay_manager *mgr, 1083/* Configure dispc for partial update. Return possibly modified update
181 const struct dss_lcd_mgr_config *config) 1084 * area */
1085void dss_setup_partial_planes(struct omap_dss_device *dssdev,
1086 u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
182{ 1087{
183 struct dispc_clock_info cinfo = config->clock_info; 1088 struct overlay_cache_data *oc;
184 int dl = config->video_port_width; 1089 struct manager_cache_data *mc;
185 bool stallmode = config->stallmode; 1090 struct omap_overlay_info *oi;
186 bool fifohandcheck = config->fifohandcheck; 1091 const int num_ovls = dss_feat_get_num_ovls();
1092 struct omap_overlay_manager *mgr;
1093 int i;
1094 u16 x, y, w, h;
1095 unsigned long flags;
1096 bool area_changed;
187 1097
188 if (cinfo.lck_div < 1 || cinfo.lck_div > 255) 1098 x = *xi;
189 return -EINVAL; 1099 y = *yi;
1100 w = *wi;
1101 h = *hi;
190 1102
191 if (cinfo.pck_div < 1 || cinfo.pck_div > 255) 1103 DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
192 return -EINVAL; 1104 *xi, *yi, *wi, *hi);
193 1105
194 if (dl != 12 && dl != 16 && dl != 18 && dl != 24) 1106 mgr = dssdev->manager;
195 return -EINVAL;
196 1107
197 /* fifohandcheck should be used only with stallmode */ 1108 if (!mgr) {
198 if (stallmode == false && fifohandcheck == true) 1109 DSSDBG("no manager\n");
199 return -EINVAL; 1110 return;
1111 }
1112
1113 make_even(&x, &w);
1114
1115 spin_lock_irqsave(&dss_cache.lock, flags);
200 1116
201 /* 1117 /*
202 * io pad mode can be only checked by using dssdev connected to the 1118 * Execute the outer loop until the inner loop has completed
203 * manager. Ignore checking these for now, add checks when manager 1119 * once without increasing the update area. This will ensure that
204 * is capable of holding information related to the connected interface 1120 * all scaled overlays end up completely within the update area.
205 */ 1121 */
1122 do {
1123 area_changed = false;
206 1124
207 return 0; 1125 /* We need to show the whole overlay if it is scaled. So look
1126 * for those, and make the update area larger if found.
1127 * Also mark the overlay cache dirty */
1128 for (i = 0; i < num_ovls; ++i) {
1129 unsigned x1, y1, x2, y2;
1130 unsigned outw, outh;
1131
1132 oc = &dss_cache.overlay_cache[i];
1133 oi = &oc->info;
1134
1135 if (oc->channel != mgr->id)
1136 continue;
1137
1138 oc->dirty = true;
1139
1140 if (!enlarge_update_area)
1141 continue;
1142
1143 if (!oc->enabled)
1144 continue;
1145
1146 if (!dispc_is_overlay_scaled(oc))
1147 continue;
1148
1149 outw = oi->out_width == 0 ?
1150 oi->width : oi->out_width;
1151 outh = oi->out_height == 0 ?
1152 oi->height : oi->out_height;
1153
1154 /* is the overlay outside the update region? */
1155 if (!rectangle_intersects(x, y, w, h,
1156 oi->pos_x, oi->pos_y,
1157 outw, outh))
1158 continue;
1159
1160 /* if the overlay totally inside the update region? */
1161 if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
1162 x, y, w, h))
1163 continue;
1164
1165 if (x > oi->pos_x)
1166 x1 = oi->pos_x;
1167 else
1168 x1 = x;
1169
1170 if (y > oi->pos_y)
1171 y1 = oi->pos_y;
1172 else
1173 y1 = y;
1174
1175 if ((x + w) < (oi->pos_x + outw))
1176 x2 = oi->pos_x + outw;
1177 else
1178 x2 = x + w;
1179
1180 if ((y + h) < (oi->pos_y + outh))
1181 y2 = oi->pos_y + outh;
1182 else
1183 y2 = y + h;
1184
1185 x = x1;
1186 y = y1;
1187 w = x2 - x1;
1188 h = y2 - y1;
1189
1190 make_even(&x, &w);
1191
1192 DSSDBG("changing upd area due to ovl(%d) "
1193 "scaling %d,%d %dx%d\n",
1194 i, x, y, w, h);
1195
1196 area_changed = true;
1197 }
1198 } while (area_changed);
1199
1200 mc = &dss_cache.manager_cache[mgr->id];
1201 mc->do_manual_update = true;
1202 mc->enlarge_update_area = enlarge_update_area;
1203 mc->x = x;
1204 mc->y = y;
1205 mc->w = w;
1206 mc->h = h;
1207
1208 configure_dispc();
1209
1210 mc->do_manual_update = false;
1211
1212 spin_unlock_irqrestore(&dss_cache.lock, flags);
1213
1214 *xi = x;
1215 *yi = y;
1216 *wi = w;
1217 *hi = h;
208} 1218}
209 1219
210int dss_mgr_check(struct omap_overlay_manager *mgr, 1220void dss_start_update(struct omap_dss_device *dssdev)
211 struct omap_overlay_manager_info *info,
212 const struct omap_video_timings *mgr_timings,
213 const struct dss_lcd_mgr_config *lcd_config,
214 struct omap_overlay_info **overlay_infos)
215{ 1221{
1222 struct manager_cache_data *mc;
1223 struct overlay_cache_data *oc;
1224 const int num_ovls = dss_feat_get_num_ovls();
1225 const int num_mgrs = dss_feat_get_num_mgrs();
1226 struct omap_overlay_manager *mgr;
1227 int i;
1228
1229 mgr = dssdev->manager;
1230
1231 for (i = 0; i < num_ovls; ++i) {
1232 oc = &dss_cache.overlay_cache[i];
1233 if (oc->channel != mgr->id)
1234 continue;
1235
1236 oc->shadow_dirty = false;
1237 }
1238
1239 for (i = 0; i < num_mgrs; ++i) {
1240 mc = &dss_cache.manager_cache[i];
1241 if (mgr->id != i)
1242 continue;
1243
1244 mc->shadow_dirty = false;
1245 }
1246
1247 dssdev->manager->enable(dssdev->manager);
1248}
1249
1250static void dss_apply_irq_handler(void *data, u32 mask)
1251{
1252 struct manager_cache_data *mc;
1253 struct overlay_cache_data *oc;
1254 const int num_ovls = dss_feat_get_num_ovls();
1255 const int num_mgrs = dss_feat_get_num_mgrs();
1256 int i, r;
1257 bool mgr_busy[MAX_DSS_MANAGERS];
1258 u32 irq_mask;
1259
1260 for (i = 0; i < num_mgrs; i++)
1261 mgr_busy[i] = dispc_go_busy(i);
1262
1263 spin_lock(&dss_cache.lock);
1264
1265 for (i = 0; i < num_ovls; ++i) {
1266 oc = &dss_cache.overlay_cache[i];
1267 if (!mgr_busy[oc->channel])
1268 oc->shadow_dirty = false;
1269 }
1270
1271 for (i = 0; i < num_mgrs; ++i) {
1272 mc = &dss_cache.manager_cache[i];
1273 if (!mgr_busy[i])
1274 mc->shadow_dirty = false;
1275 }
1276
1277 r = configure_dispc();
1278 if (r == 1)
1279 goto end;
1280
1281 /* re-read busy flags */
1282 for (i = 0; i < num_mgrs; i++)
1283 mgr_busy[i] = dispc_go_busy(i);
1284
1285 /* keep running as long as there are busy managers, so that
1286 * we can collect overlay-applied information */
1287 for (i = 0; i < num_mgrs; ++i) {
1288 if (mgr_busy[i])
1289 goto end;
1290 }
1291
1292 irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1293 DISPC_IRQ_EVSYNC_EVEN;
1294 if (dss_has_feature(FEAT_MGR_LCD2))
1295 irq_mask |= DISPC_IRQ_VSYNC2;
1296
1297 omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask);
1298 dss_cache.irq_enabled = false;
1299
1300end:
1301 spin_unlock(&dss_cache.lock);
1302}
1303
1304static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
1305{
1306 struct overlay_cache_data *oc;
1307 struct manager_cache_data *mc;
1308 int i;
216 struct omap_overlay *ovl; 1309 struct omap_overlay *ovl;
1310 int num_planes_enabled = 0;
1311 bool use_fifomerge;
1312 unsigned long flags;
217 int r; 1313 int r;
218 1314
219 if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) { 1315 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
220 r = dss_mgr_check_zorder(mgr, overlay_infos);
221 if (r)
222 return r;
223 }
224 1316
225 r = dss_mgr_check_timings(mgr, mgr_timings); 1317 r = dispc_runtime_get();
226 if (r) 1318 if (r)
227 return r; 1319 return r;
228 1320
229 r = dss_mgr_check_lcd_config(mgr, lcd_config); 1321 spin_lock_irqsave(&dss_cache.lock, flags);
230 if (r) 1322
1323 /* Configure overlays */
1324 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1325 struct omap_dss_device *dssdev;
1326
1327 ovl = omap_dss_get_overlay(i);
1328
1329 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1330 continue;
1331
1332 oc = &dss_cache.overlay_cache[ovl->id];
1333
1334 if (!overlay_enabled(ovl)) {
1335 if (oc->enabled) {
1336 oc->enabled = false;
1337 oc->dirty = true;
1338 }
1339 continue;
1340 }
1341
1342 if (!ovl->info_dirty) {
1343 if (oc->enabled)
1344 ++num_planes_enabled;
1345 continue;
1346 }
1347
1348 dssdev = ovl->manager->device;
1349
1350 if (dss_check_overlay(ovl, dssdev)) {
1351 if (oc->enabled) {
1352 oc->enabled = false;
1353 oc->dirty = true;
1354 }
1355 continue;
1356 }
1357
1358 ovl->info_dirty = false;
1359 oc->dirty = true;
1360 oc->info = ovl->info;
1361
1362 oc->replication =
1363 dss_use_replication(dssdev, ovl->info.color_mode);
1364
1365 oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
1366
1367 oc->channel = ovl->manager->id;
1368
1369 oc->enabled = true;
1370
1371 ++num_planes_enabled;
1372 }
1373
1374 /* Configure managers */
1375 list_for_each_entry(mgr, &manager_list, list) {
1376 struct omap_dss_device *dssdev;
1377
1378 if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
1379 continue;
1380
1381 mc = &dss_cache.manager_cache[mgr->id];
1382
1383 if (mgr->device_changed) {
1384 mgr->device_changed = false;
1385 mgr->info_dirty = true;
1386 }
1387
1388 if (!mgr->info_dirty)
1389 continue;
1390
1391 if (!mgr->device)
1392 continue;
1393
1394 dssdev = mgr->device;
1395
1396 mgr->info_dirty = false;
1397 mc->dirty = true;
1398 mc->info = mgr->info;
1399
1400 mc->manual_update =
1401 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1402 }
1403
1404 /* XXX TODO: Try to get fifomerge working. The problem is that it
1405 * affects both managers, not individually but at the same time. This
1406 * means the change has to be well synchronized. I guess the proper way
1407 * is to have a two step process for fifo merge:
1408 * fifomerge enable:
1409 * 1. disable other planes, leaving one plane enabled
1410 * 2. wait until the planes are disabled on HW
1411 * 3. config merged fifo thresholds, enable fifomerge
1412 * fifomerge disable:
1413 * 1. config unmerged fifo thresholds, disable fifomerge
1414 * 2. wait until fifo changes are in HW
1415 * 3. enable planes
1416 */
1417 use_fifomerge = false;
1418
1419 /* Configure overlay fifos */
1420 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1421 struct omap_dss_device *dssdev;
1422 u32 size, burst_size;
1423
1424 ovl = omap_dss_get_overlay(i);
1425
1426 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
1427 continue;
1428
1429 oc = &dss_cache.overlay_cache[ovl->id];
1430
1431 if (!oc->enabled)
1432 continue;
1433
1434 dssdev = ovl->manager->device;
1435
1436 size = dispc_get_plane_fifo_size(ovl->id);
1437 if (use_fifomerge)
1438 size *= 3;
1439
1440 burst_size = dispc_get_burst_size(ovl->id);
1441
1442 switch (dssdev->type) {
1443 case OMAP_DISPLAY_TYPE_DPI:
1444 case OMAP_DISPLAY_TYPE_DBI:
1445 case OMAP_DISPLAY_TYPE_SDI:
1446 case OMAP_DISPLAY_TYPE_VENC:
1447 case OMAP_DISPLAY_TYPE_HDMI:
1448 default_get_overlay_fifo_thresholds(ovl->id, size,
1449 burst_size, &oc->fifo_low,
1450 &oc->fifo_high);
1451 break;
1452#ifdef CONFIG_OMAP2_DSS_DSI
1453 case OMAP_DISPLAY_TYPE_DSI:
1454 dsi_get_overlay_fifo_thresholds(ovl->id, size,
1455 burst_size, &oc->fifo_low,
1456 &oc->fifo_high);
1457 break;
1458#endif
1459 default:
1460 BUG();
1461 }
1462 }
1463
1464 r = 0;
1465 if (!dss_cache.irq_enabled) {
1466 u32 mask;
1467
1468 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1469 DISPC_IRQ_EVSYNC_EVEN;
1470 if (dss_has_feature(FEAT_MGR_LCD2))
1471 mask |= DISPC_IRQ_VSYNC2;
1472
1473 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
1474 dss_cache.irq_enabled = true;
1475 }
1476 configure_dispc();
1477
1478 spin_unlock_irqrestore(&dss_cache.lock, flags);
1479
1480 dispc_runtime_put();
1481
1482 return r;
1483}
1484
1485static int dss_check_manager(struct omap_overlay_manager *mgr)
1486{
1487 /* OMAP supports only graphics source transparency color key and alpha
1488 * blending simultaneously. See TRM 15.4.2.4.2.2 Alpha Mode */
1489
1490 if (mgr->info.alpha_enabled && mgr->info.trans_enabled &&
1491 mgr->info.trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST)
1492 return -EINVAL;
1493
1494 return 0;
1495}
1496
1497static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr,
1498 struct omap_overlay_manager_info *info)
1499{
1500 int r;
1501 struct omap_overlay_manager_info old_info;
1502
1503 old_info = mgr->info;
1504 mgr->info = *info;
1505
1506 r = dss_check_manager(mgr);
1507 if (r) {
1508 mgr->info = old_info;
231 return r; 1509 return r;
1510 }
232 1511
233 list_for_each_entry(ovl, &mgr->overlays, list) { 1512 mgr->info_dirty = true;
234 struct omap_overlay_info *oi;
235 int r;
236 1513
237 oi = overlay_infos[ovl->id]; 1514 return 0;
1515}
238 1516
239 if (oi == NULL) 1517static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
1518 struct omap_overlay_manager_info *info)
1519{
1520 *info = mgr->info;
1521}
1522
1523static int dss_mgr_enable(struct omap_overlay_manager *mgr)
1524{
1525 dispc_enable_channel(mgr->id, 1);
1526 return 0;
1527}
1528
1529static int dss_mgr_disable(struct omap_overlay_manager *mgr)
1530{
1531 dispc_enable_channel(mgr->id, 0);
1532 return 0;
1533}
1534
1535static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
1536{
1537 ++num_managers;
1538 list_add_tail(&manager->list, &manager_list);
1539}
1540
1541int dss_init_overlay_managers(struct platform_device *pdev)
1542{
1543 int i, r;
1544
1545 spin_lock_init(&dss_cache.lock);
1546
1547 INIT_LIST_HEAD(&manager_list);
1548
1549 num_managers = 0;
1550
1551 for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
1552 struct omap_overlay_manager *mgr;
1553 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1554
1555 BUG_ON(mgr == NULL);
1556
1557 switch (i) {
1558 case 0:
1559 mgr->name = "lcd";
1560 mgr->id = OMAP_DSS_CHANNEL_LCD;
1561 break;
1562 case 1:
1563 mgr->name = "tv";
1564 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
1565 break;
1566 case 2:
1567 mgr->name = "lcd2";
1568 mgr->id = OMAP_DSS_CHANNEL_LCD2;
1569 break;
1570 }
1571
1572 mgr->set_device = &omap_dss_set_device;
1573 mgr->unset_device = &omap_dss_unset_device;
1574 mgr->apply = &omap_dss_mgr_apply;
1575 mgr->set_manager_info = &omap_dss_mgr_set_info;
1576 mgr->get_manager_info = &omap_dss_mgr_get_info;
1577 mgr->wait_for_go = &dss_mgr_wait_for_go;
1578 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1579
1580 mgr->enable = &dss_mgr_enable;
1581 mgr->disable = &dss_mgr_disable;
1582
1583 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
1584 mgr->supported_displays =
1585 dss_feat_get_supported_displays(mgr->id);
1586
1587 dss_overlay_setup_dispc_manager(mgr);
1588
1589 omap_dss_add_overlay_manager(mgr);
1590
1591 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1592 &pdev->dev.kobj, "manager%d", i);
1593
1594 if (r) {
1595 DSSERR("failed to create sysfs file\n");
240 continue; 1596 continue;
1597 }
1598 }
1599
1600#ifdef L4_EXAMPLE
1601 {
1602 int omap_dss_mgr_apply_l4(struct omap_overlay_manager *mgr)
1603 {
1604 DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);
1605
1606 return 0;
1607 }
1608
1609 struct omap_overlay_manager *mgr;
1610 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1611
1612 BUG_ON(mgr == NULL);
1613
1614 mgr->name = "l4";
1615 mgr->supported_displays =
1616 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI;
1617
1618 mgr->set_device = &omap_dss_set_device;
1619 mgr->unset_device = &omap_dss_unset_device;
1620 mgr->apply = &omap_dss_mgr_apply_l4;
1621 mgr->set_manager_info = &omap_dss_mgr_set_info;
1622 mgr->get_manager_info = &omap_dss_mgr_get_info;
1623
1624 dss_overlay_setup_l4_manager(mgr);
1625
1626 omap_dss_add_overlay_manager(mgr);
1627
1628 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1629 &pdev->dev.kobj, "managerl4");
241 1630
242 r = dss_ovl_check(ovl, oi, mgr_timings);
243 if (r) 1631 if (r)
244 return r; 1632 DSSERR("failed to create sysfs file\n");
245 } 1633 }
1634#endif
246 1635
247 return 0; 1636 return 0;
248} 1637}
1638
1639void dss_uninit_overlay_managers(struct platform_device *pdev)
1640{
1641 struct omap_overlay_manager *mgr;
1642
1643 while (!list_empty(&manager_list)) {
1644 mgr = list_first_entry(&manager_list,
1645 struct omap_overlay_manager, list);
1646 list_del(&mgr->list);
1647 kobject_del(&mgr->kobj);
1648 kobject_put(&mgr->kobj);
1649 kfree(mgr);
1650 }
1651
1652 num_managers = 0;
1653}
1654
1655int omap_dss_get_num_overlay_managers(void)
1656{
1657 return num_managers;
1658}
1659EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
1660
1661struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
1662{
1663 int i = 0;
1664 struct omap_overlay_manager *mgr;
1665
1666 list_for_each_entry(mgr, &manager_list, list) {
1667 if (i++ == num)
1668 return mgr;
1669 }
1670
1671 return NULL;
1672}
1673EXPORT_SYMBOL(omap_dss_get_overlay_manager);
1674
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c
deleted file mode 100644
index 79dea1a1a73..00000000000
--- a/drivers/video/omap2/dss/output.c
+++ /dev/null
@@ -1,180 +0,0 @@
1/*
2 * Copyright (C) 2012 Texas Instruments Ltd
3 * Author: Archit Taneja <archit@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22
23#include <video/omapdss.h>
24
25#include "dss.h"
26
27static LIST_HEAD(output_list);
28static DEFINE_MUTEX(output_lock);
29
30int omapdss_output_set_device(struct omap_dss_output *out,
31 struct omap_dss_device *dssdev)
32{
33 int r;
34
35 mutex_lock(&output_lock);
36
37 if (out->device) {
38 DSSERR("output already has device %s connected to it\n",
39 out->device->name);
40 r = -EINVAL;
41 goto err;
42 }
43
44 if (out->type != dssdev->type) {
45 DSSERR("output type and display type don't match\n");
46 r = -EINVAL;
47 goto err;
48 }
49
50 out->device = dssdev;
51 dssdev->output = out;
52
53 mutex_unlock(&output_lock);
54
55 return 0;
56err:
57 mutex_unlock(&output_lock);
58
59 return r;
60}
61EXPORT_SYMBOL(omapdss_output_set_device);
62
63int omapdss_output_unset_device(struct omap_dss_output *out)
64{
65 int r;
66
67 mutex_lock(&output_lock);
68
69 if (!out->device) {
70 DSSERR("output doesn't have a device connected to it\n");
71 r = -EINVAL;
72 goto err;
73 }
74
75 if (out->device->state != OMAP_DSS_DISPLAY_DISABLED) {
76 DSSERR("device %s is not disabled, cannot unset device\n",
77 out->device->name);
78 r = -EINVAL;
79 goto err;
80 }
81
82 out->device->output = NULL;
83 out->device = NULL;
84
85 mutex_unlock(&output_lock);
86
87 return 0;
88err:
89 mutex_unlock(&output_lock);
90
91 return r;
92}
93EXPORT_SYMBOL(omapdss_output_unset_device);
94
95void dss_register_output(struct omap_dss_output *out)
96{
97 list_add_tail(&out->list, &output_list);
98}
99
100void dss_unregister_output(struct omap_dss_output *out)
101{
102 list_del(&out->list);
103}
104
105struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id)
106{
107 struct omap_dss_output *out;
108
109 list_for_each_entry(out, &output_list, list) {
110 if (out->id == id)
111 return out;
112 }
113
114 return NULL;
115}
116
117static const struct dss_mgr_ops *dss_mgr_ops;
118
119int dss_install_mgr_ops(const struct dss_mgr_ops *mgr_ops)
120{
121 if (dss_mgr_ops)
122 return -EBUSY;
123
124 dss_mgr_ops = mgr_ops;
125
126 return 0;
127}
128EXPORT_SYMBOL(dss_install_mgr_ops);
129
130void dss_uninstall_mgr_ops(void)
131{
132 dss_mgr_ops = NULL;
133}
134EXPORT_SYMBOL(dss_uninstall_mgr_ops);
135
136void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
137 const struct omap_video_timings *timings)
138{
139 dss_mgr_ops->set_timings(mgr, timings);
140}
141EXPORT_SYMBOL(dss_mgr_set_timings);
142
143void dss_mgr_set_lcd_config(struct omap_overlay_manager *mgr,
144 const struct dss_lcd_mgr_config *config)
145{
146 dss_mgr_ops->set_lcd_config(mgr, config);
147}
148EXPORT_SYMBOL(dss_mgr_set_lcd_config);
149
150int dss_mgr_enable(struct omap_overlay_manager *mgr)
151{
152 return dss_mgr_ops->enable(mgr);
153}
154EXPORT_SYMBOL(dss_mgr_enable);
155
156void dss_mgr_disable(struct omap_overlay_manager *mgr)
157{
158 dss_mgr_ops->disable(mgr);
159}
160EXPORT_SYMBOL(dss_mgr_disable);
161
162void dss_mgr_start_update(struct omap_overlay_manager *mgr)
163{
164 dss_mgr_ops->start_update(mgr);
165}
166EXPORT_SYMBOL(dss_mgr_start_update);
167
168int dss_mgr_register_framedone_handler(struct omap_overlay_manager *mgr,
169 void (*handler)(void *), void *data)
170{
171 return dss_mgr_ops->register_framedone_handler(mgr, handler, data);
172}
173EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
174
175void dss_mgr_unregister_framedone_handler(struct omap_overlay_manager *mgr,
176 void (*handler)(void *), void *data)
177{
178 dss_mgr_ops->unregister_framedone_handler(mgr, handler, data);
179}
180EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/omap2/dss/overlay-sysfs.c
deleted file mode 100644
index 4cc5ddebfb3..00000000000
--- a/drivers/video/omap2/dss/overlay-sysfs.c
+++ /dev/null
@@ -1,456 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "OVERLAY"
22
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/sysfs.h>
26#include <linux/kobject.h>
27#include <linux/platform_device.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
37}
38
39static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n",
42 ovl->manager ? ovl->manager->name : "<none>");
43}
44
45static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
46 size_t size)
47{
48 int i, r;
49 struct omap_overlay_manager *mgr = NULL;
50 struct omap_overlay_manager *old_mgr;
51 int len = size;
52
53 if (buf[size-1] == '\n')
54 --len;
55
56 if (len > 0) {
57 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
58 mgr = omap_dss_get_overlay_manager(i);
59
60 if (sysfs_streq(buf, mgr->name))
61 break;
62
63 mgr = NULL;
64 }
65 }
66
67 if (len > 0 && mgr == NULL)
68 return -EINVAL;
69
70 if (mgr)
71 DSSDBG("manager %s found\n", mgr->name);
72
73 if (mgr == ovl->manager)
74 return size;
75
76 old_mgr = ovl->manager;
77
78 r = dispc_runtime_get();
79 if (r)
80 return r;
81
82 /* detach old manager */
83 if (old_mgr) {
84 r = ovl->unset_manager(ovl);
85 if (r) {
86 DSSERR("detach failed\n");
87 goto err;
88 }
89
90 r = old_mgr->apply(old_mgr);
91 if (r)
92 goto err;
93 }
94
95 if (mgr) {
96 r = ovl->set_manager(ovl, mgr);
97 if (r) {
98 DSSERR("Failed to attach overlay\n");
99 goto err;
100 }
101
102 r = mgr->apply(mgr);
103 if (r)
104 goto err;
105 }
106
107 dispc_runtime_put();
108
109 return size;
110
111err:
112 dispc_runtime_put();
113 return r;
114}
115
116static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
117{
118 struct omap_overlay_info info;
119
120 ovl->get_overlay_info(ovl, &info);
121
122 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
123 info.width, info.height);
124}
125
126static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
127{
128 struct omap_overlay_info info;
129
130 ovl->get_overlay_info(ovl, &info);
131
132 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
133}
134
135static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
136{
137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
142 info.pos_x, info.pos_y);
143}
144
145static ssize_t overlay_position_store(struct omap_overlay *ovl,
146 const char *buf, size_t size)
147{
148 int r;
149 char *last;
150 struct omap_overlay_info info;
151
152 ovl->get_overlay_info(ovl, &info);
153
154 info.pos_x = simple_strtoul(buf, &last, 10);
155 ++last;
156 if (last - buf >= size)
157 return -EINVAL;
158
159 info.pos_y = simple_strtoul(last, &last, 10);
160
161 r = ovl->set_overlay_info(ovl, &info);
162 if (r)
163 return r;
164
165 if (ovl->manager) {
166 r = ovl->manager->apply(ovl->manager);
167 if (r)
168 return r;
169 }
170
171 return size;
172}
173
174static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
175{
176 struct omap_overlay_info info;
177
178 ovl->get_overlay_info(ovl, &info);
179
180 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
181 info.out_width, info.out_height);
182}
183
184static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
185 const char *buf, size_t size)
186{
187 int r;
188 char *last;
189 struct omap_overlay_info info;
190
191 ovl->get_overlay_info(ovl, &info);
192
193 info.out_width = simple_strtoul(buf, &last, 10);
194 ++last;
195 if (last - buf >= size)
196 return -EINVAL;
197
198 info.out_height = simple_strtoul(last, &last, 10);
199
200 r = ovl->set_overlay_info(ovl, &info);
201 if (r)
202 return r;
203
204 if (ovl->manager) {
205 r = ovl->manager->apply(ovl->manager);
206 if (r)
207 return r;
208 }
209
210 return size;
211}
212
213static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
214{
215 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
216}
217
218static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
219 size_t size)
220{
221 int r;
222 bool enable;
223
224 r = strtobool(buf, &enable);
225 if (r)
226 return r;
227
228 if (enable)
229 r = ovl->enable(ovl);
230 else
231 r = ovl->disable(ovl);
232
233 if (r)
234 return r;
235
236 return size;
237}
238
239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240{
241 struct omap_overlay_info info;
242
243 ovl->get_overlay_info(ovl, &info);
244
245 return snprintf(buf, PAGE_SIZE, "%d\n",
246 info.global_alpha);
247}
248
249static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
250 const char *buf, size_t size)
251{
252 int r;
253 u8 alpha;
254 struct omap_overlay_info info;
255
256 if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
257 return -ENODEV;
258
259 r = kstrtou8(buf, 0, &alpha);
260 if (r)
261 return r;
262
263 ovl->get_overlay_info(ovl, &info);
264
265 info.global_alpha = alpha;
266
267 r = ovl->set_overlay_info(ovl, &info);
268 if (r)
269 return r;
270
271 if (ovl->manager) {
272 r = ovl->manager->apply(ovl->manager);
273 if (r)
274 return r;
275 }
276
277 return size;
278}
279
280static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
281 char *buf)
282{
283 struct omap_overlay_info info;
284
285 ovl->get_overlay_info(ovl, &info);
286
287 return snprintf(buf, PAGE_SIZE, "%d\n",
288 info.pre_mult_alpha);
289}
290
291static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
292 const char *buf, size_t size)
293{
294 int r;
295 u8 alpha;
296 struct omap_overlay_info info;
297
298 if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
299 return -ENODEV;
300
301 r = kstrtou8(buf, 0, &alpha);
302 if (r)
303 return r;
304
305 ovl->get_overlay_info(ovl, &info);
306
307 info.pre_mult_alpha = alpha;
308
309 r = ovl->set_overlay_info(ovl, &info);
310 if (r)
311 return r;
312
313 if (ovl->manager) {
314 r = ovl->manager->apply(ovl->manager);
315 if (r)
316 return r;
317 }
318
319 return size;
320}
321
322static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
323{
324 struct omap_overlay_info info;
325
326 ovl->get_overlay_info(ovl, &info);
327
328 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
329}
330
331static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
332 const char *buf, size_t size)
333{
334 int r;
335 u8 zorder;
336 struct omap_overlay_info info;
337
338 if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
339 return -ENODEV;
340
341 r = kstrtou8(buf, 0, &zorder);
342 if (r)
343 return r;
344
345 ovl->get_overlay_info(ovl, &info);
346
347 info.zorder = zorder;
348
349 r = ovl->set_overlay_info(ovl, &info);
350 if (r)
351 return r;
352
353 if (ovl->manager) {
354 r = ovl->manager->apply(ovl->manager);
355 if (r)
356 return r;
357 }
358
359 return size;
360}
361
362struct overlay_attribute {
363 struct attribute attr;
364 ssize_t (*show)(struct omap_overlay *, char *);
365 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
366};
367
368#define OVERLAY_ATTR(_name, _mode, _show, _store) \
369 struct overlay_attribute overlay_attr_##_name = \
370 __ATTR(_name, _mode, _show, _store)
371
372static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
373static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
374 overlay_manager_show, overlay_manager_store);
375static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
376static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
377static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
378 overlay_position_show, overlay_position_store);
379static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
380 overlay_output_size_show, overlay_output_size_store);
381static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
382 overlay_enabled_show, overlay_enabled_store);
383static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
384 overlay_global_alpha_show, overlay_global_alpha_store);
385static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
386 overlay_pre_mult_alpha_show,
387 overlay_pre_mult_alpha_store);
388static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
389 overlay_zorder_show, overlay_zorder_store);
390
391static struct attribute *overlay_sysfs_attrs[] = {
392 &overlay_attr_name.attr,
393 &overlay_attr_manager.attr,
394 &overlay_attr_input_size.attr,
395 &overlay_attr_screen_width.attr,
396 &overlay_attr_position.attr,
397 &overlay_attr_output_size.attr,
398 &overlay_attr_enabled.attr,
399 &overlay_attr_global_alpha.attr,
400 &overlay_attr_pre_mult_alpha.attr,
401 &overlay_attr_zorder.attr,
402 NULL
403};
404
405static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
406 char *buf)
407{
408 struct omap_overlay *overlay;
409 struct overlay_attribute *overlay_attr;
410
411 overlay = container_of(kobj, struct omap_overlay, kobj);
412 overlay_attr = container_of(attr, struct overlay_attribute, attr);
413
414 if (!overlay_attr->show)
415 return -ENOENT;
416
417 return overlay_attr->show(overlay, buf);
418}
419
420static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
421 const char *buf, size_t size)
422{
423 struct omap_overlay *overlay;
424 struct overlay_attribute *overlay_attr;
425
426 overlay = container_of(kobj, struct omap_overlay, kobj);
427 overlay_attr = container_of(attr, struct overlay_attribute, attr);
428
429 if (!overlay_attr->store)
430 return -ENOENT;
431
432 return overlay_attr->store(overlay, buf, size);
433}
434
435static const struct sysfs_ops overlay_sysfs_ops = {
436 .show = overlay_attr_show,
437 .store = overlay_attr_store,
438};
439
440static struct kobj_type overlay_ktype = {
441 .sysfs_ops = &overlay_sysfs_ops,
442 .default_attrs = overlay_sysfs_attrs,
443};
444
445int dss_overlay_kobj_init(struct omap_overlay *ovl,
446 struct platform_device *pdev)
447{
448 return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
449 &pdev->dev.kobj, "overlay%d", ovl->id);
450}
451
452void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
453{
454 kobject_del(&ovl->kobj);
455 kobject_put(&ovl->kobj);
456}
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index eccde322c28..c84380c53c3 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -26,140 +26,409 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/sysfs.h> 28#include <linux/sysfs.h>
29#include <linux/kobject.h>
29#include <linux/platform_device.h> 30#include <linux/platform_device.h>
30#include <linux/delay.h> 31#include <linux/delay.h>
31#include <linux/slab.h> 32#include <linux/slab.h>
32 33
33#include <video/omapdss.h> 34#include <video/omapdss.h>
35#include <plat/cpu.h>
34 36
35#include "dss.h" 37#include "dss.h"
36#include "dss_features.h" 38#include "dss_features.h"
37 39
38static int num_overlays; 40static int num_overlays;
39static struct omap_overlay *overlays; 41static struct list_head overlay_list;
40 42
41int omap_dss_get_num_overlays(void) 43static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
42{ 44{
43 return num_overlays; 45 return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
44} 46}
45EXPORT_SYMBOL(omap_dss_get_num_overlays);
46 47
47struct omap_overlay *omap_dss_get_overlay(int num) 48static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
48{ 49{
49 if (num >= num_overlays) 50 return snprintf(buf, PAGE_SIZE, "%s\n",
50 return NULL; 51 ovl->manager ? ovl->manager->name : "<none>");
51
52 return &overlays[num];
53} 52}
54EXPORT_SYMBOL(omap_dss_get_overlay);
55 53
56void dss_init_overlays(struct platform_device *pdev) 54static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
55 size_t size)
57{ 56{
58 int i, r; 57 int i, r;
58 struct omap_overlay_manager *mgr = NULL;
59 struct omap_overlay_manager *old_mgr;
60 int len = size;
59 61
60 num_overlays = dss_feat_get_num_ovls(); 62 if (buf[size-1] == '\n')
63 --len;
61 64
62 overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays, 65 if (len > 0) {
63 GFP_KERNEL); 66 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
67 mgr = omap_dss_get_overlay_manager(i);
64 68
65 BUG_ON(overlays == NULL); 69 if (sysfs_streq(buf, mgr->name))
70 break;
66 71
67 for (i = 0; i < num_overlays; ++i) { 72 mgr = NULL;
68 struct omap_overlay *ovl = &overlays[i]; 73 }
74 }
69 75
70 switch (i) { 76 if (len > 0 && mgr == NULL)
71 case 0: 77 return -EINVAL;
72 ovl->name = "gfx"; 78
73 ovl->id = OMAP_DSS_GFX; 79 if (mgr)
74 break; 80 DSSDBG("manager %s found\n", mgr->name);
75 case 1: 81
76 ovl->name = "vid1"; 82 if (mgr == ovl->manager)
77 ovl->id = OMAP_DSS_VIDEO1; 83 return size;
78 break; 84
79 case 2: 85 old_mgr = ovl->manager;
80 ovl->name = "vid2"; 86
81 ovl->id = OMAP_DSS_VIDEO2; 87 r = dispc_runtime_get();
82 break; 88 if (r)
83 case 3: 89 return r;
84 ovl->name = "vid3"; 90
85 ovl->id = OMAP_DSS_VIDEO3; 91 /* detach old manager */
86 break; 92 if (old_mgr) {
93 r = ovl->unset_manager(ovl);
94 if (r) {
95 DSSERR("detach failed\n");
96 goto err;
87 } 97 }
88 98
89 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 99 r = old_mgr->apply(old_mgr);
90 ovl->supported_modes = 100 if (r)
91 dss_feat_get_supported_color_modes(ovl->id); 101 goto err;
102 }
92 103
93 r = dss_overlay_kobj_init(ovl, pdev); 104 if (mgr) {
105 r = ovl->set_manager(ovl, mgr);
106 if (r) {
107 DSSERR("Failed to attach overlay\n");
108 goto err;
109 }
110
111 r = mgr->apply(mgr);
94 if (r) 112 if (r)
95 DSSERR("failed to create sysfs file\n"); 113 goto err;
96 } 114 }
115
116 dispc_runtime_put();
117
118 return size;
119
120err:
121 dispc_runtime_put();
122 return r;
97} 123}
98 124
99void dss_uninit_overlays(struct platform_device *pdev) 125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
100{ 126{
101 int i; 127 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
128 ovl->info.width, ovl->info.height);
129}
102 130
103 for (i = 0; i < num_overlays; ++i) { 131static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
104 struct omap_overlay *ovl = &overlays[i]; 132{
105 dss_overlay_kobj_uninit(ovl); 133 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
106 } 134}
107 135
108 kfree(overlays); 136static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
109 overlays = NULL; 137{
110 num_overlays = 0; 138 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
139 ovl->info.pos_x, ovl->info.pos_y);
111} 140}
112 141
113int dss_ovl_simple_check(struct omap_overlay *ovl, 142static ssize_t overlay_position_store(struct omap_overlay *ovl,
114 const struct omap_overlay_info *info) 143 const char *buf, size_t size)
115{ 144{
116 if (info->paddr == 0) { 145 int r;
117 DSSERR("check_overlay: paddr cannot be 0\n"); 146 char *last;
147 struct omap_overlay_info info;
148
149 ovl->get_overlay_info(ovl, &info);
150
151 info.pos_x = simple_strtoul(buf, &last, 10);
152 ++last;
153 if (last - buf >= size)
118 return -EINVAL; 154 return -EINVAL;
119 }
120 155
121 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 156 info.pos_y = simple_strtoul(last, &last, 10);
122 if (info->out_width != 0 && info->width != info->out_width) {
123 DSSERR("check_overlay: overlay %d doesn't support "
124 "scaling\n", ovl->id);
125 return -EINVAL;
126 }
127 157
128 if (info->out_height != 0 && info->height != info->out_height) { 158 r = ovl->set_overlay_info(ovl, &info);
129 DSSERR("check_overlay: overlay %d doesn't support " 159 if (r)
130 "scaling\n", ovl->id); 160 return r;
131 return -EINVAL; 161
132 } 162 if (ovl->manager) {
163 r = ovl->manager->apply(ovl->manager);
164 if (r)
165 return r;
133 } 166 }
134 167
135 if ((ovl->supported_modes & info->color_mode) == 0) { 168 return size;
136 DSSERR("check_overlay: overlay %d doesn't support mode %d\n", 169}
137 ovl->id, info->color_mode); 170
171static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
172{
173 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
174 ovl->info.out_width, ovl->info.out_height);
175}
176
177static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
178 const char *buf, size_t size)
179{
180 int r;
181 char *last;
182 struct omap_overlay_info info;
183
184 ovl->get_overlay_info(ovl, &info);
185
186 info.out_width = simple_strtoul(buf, &last, 10);
187 ++last;
188 if (last - buf >= size)
138 return -EINVAL; 189 return -EINVAL;
190
191 info.out_height = simple_strtoul(last, &last, 10);
192
193 r = ovl->set_overlay_info(ovl, &info);
194 if (r)
195 return r;
196
197 if (ovl->manager) {
198 r = ovl->manager->apply(ovl->manager);
199 if (r)
200 return r;
139 } 201 }
140 202
141 if (info->zorder >= omap_dss_get_num_overlays()) { 203 return size;
142 DSSERR("check_overlay: zorder %d too high\n", info->zorder); 204}
143 return -EINVAL; 205
206static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
207{
208 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
209}
210
211static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
212 size_t size)
213{
214 int r, enable;
215 struct omap_overlay_info info;
216
217 ovl->get_overlay_info(ovl, &info);
218
219 r = kstrtoint(buf, 0, &enable);
220 if (r)
221 return r;
222
223 info.enabled = !!enable;
224
225 r = ovl->set_overlay_info(ovl, &info);
226 if (r)
227 return r;
228
229 if (ovl->manager) {
230 r = ovl->manager->apply(ovl->manager);
231 if (r)
232 return r;
144 } 233 }
145 234
146 if (dss_feat_rotation_type_supported(info->rotation_type) == 0) { 235 return size;
147 DSSERR("check_overlay: rotation type %d not supported\n", 236}
148 info->rotation_type); 237
149 return -EINVAL; 238static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
239{
240 return snprintf(buf, PAGE_SIZE, "%d\n",
241 ovl->info.global_alpha);
242}
243
244static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
245 const char *buf, size_t size)
246{
247 int r;
248 u8 alpha;
249 struct omap_overlay_info info;
250
251 if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
252 return -ENODEV;
253
254 r = kstrtou8(buf, 0, &alpha);
255 if (r)
256 return r;
257
258 ovl->get_overlay_info(ovl, &info);
259
260 /* Video1 plane does not support global alpha
261 * to always make it 255 completely opaque
262 */
263 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
264 ovl->id == OMAP_DSS_VIDEO1)
265 info.global_alpha = 255;
266 else
267 info.global_alpha = alpha;
268
269 r = ovl->set_overlay_info(ovl, &info);
270 if (r)
271 return r;
272
273 if (ovl->manager) {
274 r = ovl->manager->apply(ovl->manager);
275 if (r)
276 return r;
150 } 277 }
151 278
152 return 0; 279 return size;
280}
281
282static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
283 char *buf)
284{
285 return snprintf(buf, PAGE_SIZE, "%d\n",
286 ovl->info.pre_mult_alpha);
153} 287}
154 288
155int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info, 289static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
156 const struct omap_video_timings *mgr_timings) 290 const char *buf, size_t size)
157{ 291{
292 int r;
293 u8 alpha;
294 struct omap_overlay_info info;
295
296 r = kstrtou8(buf, 0, &alpha);
297 if (r)
298 return r;
299
300 ovl->get_overlay_info(ovl, &info);
301
302 /* only GFX and Video2 plane support pre alpha multiplied
303 * set zero for Video1 plane
304 */
305 if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
306 ovl->id == OMAP_DSS_VIDEO1)
307 info.pre_mult_alpha = 0;
308 else
309 info.pre_mult_alpha = alpha;
310
311 r = ovl->set_overlay_info(ovl, &info);
312 if (r)
313 return r;
314
315 if (ovl->manager) {
316 r = ovl->manager->apply(ovl->manager);
317 if (r)
318 return r;
319 }
320
321 return size;
322}
323
324struct overlay_attribute {
325 struct attribute attr;
326 ssize_t (*show)(struct omap_overlay *, char *);
327 ssize_t (*store)(struct omap_overlay *, const char *, size_t);
328};
329
330#define OVERLAY_ATTR(_name, _mode, _show, _store) \
331 struct overlay_attribute overlay_attr_##_name = \
332 __ATTR(_name, _mode, _show, _store)
333
334static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
335static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
336 overlay_manager_show, overlay_manager_store);
337static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
338static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
339static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
340 overlay_position_show, overlay_position_store);
341static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
342 overlay_output_size_show, overlay_output_size_store);
343static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
344 overlay_enabled_show, overlay_enabled_store);
345static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
346 overlay_global_alpha_show, overlay_global_alpha_store);
347static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
348 overlay_pre_mult_alpha_show,
349 overlay_pre_mult_alpha_store);
350
351static struct attribute *overlay_sysfs_attrs[] = {
352 &overlay_attr_name.attr,
353 &overlay_attr_manager.attr,
354 &overlay_attr_input_size.attr,
355 &overlay_attr_screen_width.attr,
356 &overlay_attr_position.attr,
357 &overlay_attr_output_size.attr,
358 &overlay_attr_enabled.attr,
359 &overlay_attr_global_alpha.attr,
360 &overlay_attr_pre_mult_alpha.attr,
361 NULL
362};
363
364static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
365 char *buf)
366{
367 struct omap_overlay *overlay;
368 struct overlay_attribute *overlay_attr;
369
370 overlay = container_of(kobj, struct omap_overlay, kobj);
371 overlay_attr = container_of(attr, struct overlay_attribute, attr);
372
373 if (!overlay_attr->show)
374 return -ENOENT;
375
376 return overlay_attr->show(overlay, buf);
377}
378
379static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
380 const char *buf, size_t size)
381{
382 struct omap_overlay *overlay;
383 struct overlay_attribute *overlay_attr;
384
385 overlay = container_of(kobj, struct omap_overlay, kobj);
386 overlay_attr = container_of(attr, struct overlay_attribute, attr);
387
388 if (!overlay_attr->store)
389 return -ENOENT;
390
391 return overlay_attr->store(overlay, buf, size);
392}
393
394static const struct sysfs_ops overlay_sysfs_ops = {
395 .show = overlay_attr_show,
396 .store = overlay_attr_store,
397};
398
399static struct kobj_type overlay_ktype = {
400 .sysfs_ops = &overlay_sysfs_ops,
401 .default_attrs = overlay_sysfs_attrs,
402};
403
404/* Check if overlay parameters are compatible with display */
405int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
406{
407 struct omap_overlay_info *info;
158 u16 outw, outh; 408 u16 outw, outh;
159 u16 dw, dh; 409 u16 dw, dh;
160 410
161 dw = mgr_timings->x_res; 411 if (!dssdev)
162 dh = mgr_timings->y_res; 412 return 0;
413
414 if (!ovl->info.enabled)
415 return 0;
416
417 info = &ovl->info;
418
419 if (info->paddr == 0) {
420 DSSDBG("check_overlay failed: paddr 0\n");
421 return -EINVAL;
422 }
423
424 dssdev->driver->get_resolution(dssdev, &dw, &dh);
425
426 DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
427 ovl->id,
428 info->pos_x, info->pos_y,
429 info->width, info->height,
430 info->out_width, info->out_height,
431 dw, dh);
163 432
164 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 433 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
165 outw = info->width; 434 outw = info->width;
@@ -177,31 +446,319 @@ int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
177 } 446 }
178 447
179 if (dw < info->pos_x + outw) { 448 if (dw < info->pos_x + outw) {
180 DSSERR("overlay %d horizontally not inside the display area " 449 DSSDBG("check_overlay failed 1: %d < %d + %d\n",
181 "(%d + %d >= %d)\n", 450 dw, info->pos_x, outw);
182 ovl->id, info->pos_x, outw, dw);
183 return -EINVAL; 451 return -EINVAL;
184 } 452 }
185 453
186 if (dh < info->pos_y + outh) { 454 if (dh < info->pos_y + outh) {
187 DSSERR("overlay %d vertically not inside the display area " 455 DSSDBG("check_overlay failed 2: %d < %d + %d\n",
188 "(%d + %d >= %d)\n", 456 dh, info->pos_y, outh);
189 ovl->id, info->pos_y, outh, dh); 457 return -EINVAL;
458 }
459
460 if ((ovl->supported_modes & info->color_mode) == 0) {
461 DSSERR("overlay doesn't support mode %d\n", info->color_mode);
190 return -EINVAL; 462 return -EINVAL;
191 } 463 }
192 464
193 return 0; 465 return 0;
194} 466}
195 467
196/* 468static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
197 * Checks if replication logic should be used. Only use when overlay is in 469 struct omap_overlay_info *info)
198 * RGB12U or RGB16 mode, and video port width interface is 18bpp or 24bpp
199 */
200bool dss_ovl_use_replication(struct dss_lcd_mgr_config config,
201 enum omap_color_mode mode)
202{ 470{
203 if (mode != OMAP_DSS_COLOR_RGB12U && mode != OMAP_DSS_COLOR_RGB16) 471 int r;
204 return false; 472 struct omap_overlay_info old_info;
205 473
206 return config.video_port_width > 16; 474 old_info = ovl->info;
475 ovl->info = *info;
476
477 if (ovl->manager) {
478 r = dss_check_overlay(ovl, ovl->manager->device);
479 if (r) {
480 ovl->info = old_info;
481 return r;
482 }
483 }
484
485 ovl->info_dirty = true;
486
487 return 0;
207} 488}
489
490static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
491 struct omap_overlay_info *info)
492{
493 *info = ovl->info;
494}
495
496static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
497{
498 return dss_mgr_wait_for_go_ovl(ovl);
499}
500
501static int omap_dss_set_manager(struct omap_overlay *ovl,
502 struct omap_overlay_manager *mgr)
503{
504 if (!mgr)
505 return -EINVAL;
506
507 if (ovl->manager) {
508 DSSERR("overlay '%s' already has a manager '%s'\n",
509 ovl->name, ovl->manager->name);
510 return -EINVAL;
511 }
512
513 if (ovl->info.enabled) {
514 DSSERR("overlay has to be disabled to change the manager\n");
515 return -EINVAL;
516 }
517
518 ovl->manager = mgr;
519
520 /* XXX: When there is an overlay on a DSI manual update display, and
521 * the overlay is first disabled, then moved to tv, and enabled, we
522 * seem to get SYNC_LOST_DIGIT error.
523 *
524 * Waiting doesn't seem to help, but updating the manual update display
525 * after disabling the overlay seems to fix this. This hints that the
526 * overlay is perhaps somehow tied to the LCD output until the output
527 * is updated.
528 *
529 * Userspace workaround for this is to update the LCD after disabling
530 * the overlay, but before moving the overlay to TV.
531 */
532 dispc_set_channel_out(ovl->id, mgr->id);
533
534 return 0;
535}
536
537static int omap_dss_unset_manager(struct omap_overlay *ovl)
538{
539 int r;
540
541 if (!ovl->manager) {
542 DSSERR("failed to detach overlay: manager not set\n");
543 return -EINVAL;
544 }
545
546 if (ovl->info.enabled) {
547 DSSERR("overlay has to be disabled to unset the manager\n");
548 return -EINVAL;
549 }
550
551 r = ovl->wait_for_go(ovl);
552 if (r)
553 return r;
554
555 ovl->manager = NULL;
556
557 return 0;
558}
559
560int omap_dss_get_num_overlays(void)
561{
562 return num_overlays;
563}
564EXPORT_SYMBOL(omap_dss_get_num_overlays);
565
566struct omap_overlay *omap_dss_get_overlay(int num)
567{
568 int i = 0;
569 struct omap_overlay *ovl;
570
571 list_for_each_entry(ovl, &overlay_list, list) {
572 if (i++ == num)
573 return ovl;
574 }
575
576 return NULL;
577}
578EXPORT_SYMBOL(omap_dss_get_overlay);
579
580static void omap_dss_add_overlay(struct omap_overlay *overlay)
581{
582 ++num_overlays;
583 list_add_tail(&overlay->list, &overlay_list);
584}
585
586static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
587
588void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
589{
590 mgr->num_overlays = dss_feat_get_num_ovls();
591 mgr->overlays = dispc_overlays;
592}
593
594#ifdef L4_EXAMPLE
595static struct omap_overlay *l4_overlays[1];
596void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
597{
598 mgr->num_overlays = 1;
599 mgr->overlays = l4_overlays;
600}
601#endif
602
603void dss_init_overlays(struct platform_device *pdev)
604{
605 int i, r;
606
607 INIT_LIST_HEAD(&overlay_list);
608
609 num_overlays = 0;
610
611 for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
612 struct omap_overlay *ovl;
613 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
614
615 BUG_ON(ovl == NULL);
616
617 switch (i) {
618 case 0:
619 ovl->name = "gfx";
620 ovl->id = OMAP_DSS_GFX;
621 ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
622 ovl->info.global_alpha = 255;
623 break;
624 case 1:
625 ovl->name = "vid1";
626 ovl->id = OMAP_DSS_VIDEO1;
627 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
628 OMAP_DSS_OVL_CAP_DISPC;
629 ovl->info.global_alpha = 255;
630 break;
631 case 2:
632 ovl->name = "vid2";
633 ovl->id = OMAP_DSS_VIDEO2;
634 ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
635 OMAP_DSS_OVL_CAP_DISPC;
636 ovl->info.global_alpha = 255;
637 break;
638 }
639
640 ovl->set_manager = &omap_dss_set_manager;
641 ovl->unset_manager = &omap_dss_unset_manager;
642 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
643 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
644 ovl->wait_for_go = &dss_ovl_wait_for_go;
645
646 ovl->supported_modes =
647 dss_feat_get_supported_color_modes(ovl->id);
648
649 omap_dss_add_overlay(ovl);
650
651 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
652 &pdev->dev.kobj, "overlay%d", i);
653
654 if (r) {
655 DSSERR("failed to create sysfs file\n");
656 continue;
657 }
658
659 dispc_overlays[i] = ovl;
660 }
661
662#ifdef L4_EXAMPLE
663 {
664 struct omap_overlay *ovl;
665 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
666
667 BUG_ON(ovl == NULL);
668
669 ovl->name = "l4";
670 ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
671
672 ovl->set_manager = &omap_dss_set_manager;
673 ovl->unset_manager = &omap_dss_unset_manager;
674 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
675 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
676
677 omap_dss_add_overlay(ovl);
678
679 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
680 &pdev->dev.kobj, "overlayl4");
681
682 if (r)
683 DSSERR("failed to create sysfs file\n");
684
685 l4_overlays[0] = ovl;
686 }
687#endif
688}
689
690/* connect overlays to the new device, if not already connected. if force
691 * selected, connect always. */
692void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
693{
694 int i;
695 struct omap_overlay_manager *lcd_mgr;
696 struct omap_overlay_manager *tv_mgr;
697 struct omap_overlay_manager *lcd2_mgr = NULL;
698 struct omap_overlay_manager *mgr = NULL;
699
700 lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD);
701 tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV);
702 if (dss_has_feature(FEAT_MGR_LCD2))
703 lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2);
704
705 if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) {
706 if (!lcd2_mgr->device || force) {
707 if (lcd2_mgr->device)
708 lcd2_mgr->unset_device(lcd2_mgr);
709 lcd2_mgr->set_device(lcd2_mgr, dssdev);
710 mgr = lcd2_mgr;
711 }
712 } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC
713 && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) {
714 if (!lcd_mgr->device || force) {
715 if (lcd_mgr->device)
716 lcd_mgr->unset_device(lcd_mgr);
717 lcd_mgr->set_device(lcd_mgr, dssdev);
718 mgr = lcd_mgr;
719 }
720 }
721
722 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
723 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
724 if (!tv_mgr->device || force) {
725 if (tv_mgr->device)
726 tv_mgr->unset_device(tv_mgr);
727 tv_mgr->set_device(tv_mgr, dssdev);
728 mgr = tv_mgr;
729 }
730 }
731
732 if (mgr) {
733 dispc_runtime_get();
734
735 for (i = 0; i < dss_feat_get_num_ovls(); i++) {
736 struct omap_overlay *ovl;
737 ovl = omap_dss_get_overlay(i);
738 if (!ovl->manager || force) {
739 if (ovl->manager)
740 omap_dss_unset_manager(ovl);
741 omap_dss_set_manager(ovl, mgr);
742 }
743 }
744
745 dispc_runtime_put();
746 }
747}
748
749void dss_uninit_overlays(struct platform_device *pdev)
750{
751 struct omap_overlay *ovl;
752
753 while (!list_empty(&overlay_list)) {
754 ovl = list_first_entry(&overlay_list,
755 struct omap_overlay, list);
756 list_del(&ovl->list);
757 kobject_del(&ovl->kobj);
758 kobject_put(&ovl->kobj);
759 kfree(ovl);
760 }
761
762 num_overlays = 0;
763}
764
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index e903dd3f54d..39f4c597026 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -24,7 +24,6 @@
24 24
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/dma-mapping.h> 26#include <linux/dma-mapping.h>
27#include <linux/export.h>
28#include <linux/vmalloc.h> 27#include <linux/vmalloc.h>
29#include <linux/clk.h> 28#include <linux/clk.h>
30#include <linux/io.h> 29#include <linux/io.h>
@@ -111,13 +110,6 @@ static struct {
111 struct omap_dss_device *dssdev[2]; 110 struct omap_dss_device *dssdev[2];
112 111
113 struct semaphore bus_lock; 112 struct semaphore bus_lock;
114
115 struct omap_video_timings timings;
116 int pixel_size;
117 int data_lines;
118 struct rfbi_timings intf_timings;
119
120 struct omap_dss_output output;
121} rfbi; 113} rfbi;
122 114
123static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 115static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
@@ -147,8 +139,8 @@ static void rfbi_runtime_put(void)
147 139
148 DSSDBG("rfbi_runtime_put\n"); 140 DSSDBG("rfbi_runtime_put\n");
149 141
150 r = pm_runtime_put_sync(&rfbi.pdev->dev); 142 r = pm_runtime_put(&rfbi.pdev->dev);
151 WARN_ON(r < 0 && r != -ENOSYS); 143 WARN_ON(r < 0);
152} 144}
153 145
154void rfbi_bus_lock(void) 146void rfbi_bus_lock(void)
@@ -307,25 +299,19 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
307} 299}
308EXPORT_SYMBOL(omap_rfbi_write_pixels); 300EXPORT_SYMBOL(omap_rfbi_write_pixels);
309 301
310static int rfbi_transfer_area(struct omap_dss_device *dssdev, 302static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
311 void (*callback)(void *data), void *data) 303 u16 height, void (*callback)(void *data), void *data)
312{ 304{
313 u32 l; 305 u32 l;
314 int r;
315 struct omap_overlay_manager *mgr = dssdev->output->manager;
316 u16 width = rfbi.timings.x_res;
317 u16 height = rfbi.timings.y_res;
318 306
319 /*BUG_ON(callback == 0);*/ 307 /*BUG_ON(callback == 0);*/
320 BUG_ON(rfbi.framedone_callback != NULL); 308 BUG_ON(rfbi.framedone_callback != NULL);
321 309
322 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 310 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
323 311
324 dss_mgr_set_timings(mgr, &rfbi.timings); 312 dispc_set_lcd_size(dssdev->manager->id, width, height);
325 313
326 r = dss_mgr_enable(mgr); 314 dispc_enable_channel(dssdev->manager->id, true);
327 if (r)
328 return r;
329 315
330 rfbi.framedone_callback = callback; 316 rfbi.framedone_callback = callback;
331 rfbi.framedone_callback_data = data; 317 rfbi.framedone_callback_data = data;
@@ -338,11 +324,9 @@ static int rfbi_transfer_area(struct omap_dss_device *dssdev,
338 l = FLD_MOD(l, 1, 4, 4); /* ITE */ 324 l = FLD_MOD(l, 1, 4, 4); /* ITE */
339 325
340 rfbi_write_reg(RFBI_CONTROL, l); 326 rfbi_write_reg(RFBI_CONTROL, l);
341
342 return 0;
343} 327}
344 328
345static void framedone_callback(void *data) 329static void framedone_callback(void *data, u32 mask)
346{ 330{
347 void (*callback)(void *data); 331 void (*callback)(void *data);
348 332
@@ -770,47 +754,69 @@ static int rfbi_configure(int rfbi_module, int bpp, int lines)
770 return 0; 754 return 0;
771} 755}
772 756
773int omap_rfbi_configure(struct omap_dss_device *dssdev) 757int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
758 int data_lines)
774{ 759{
775 return rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size, 760 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
776 rfbi.data_lines);
777} 761}
778EXPORT_SYMBOL(omap_rfbi_configure); 762EXPORT_SYMBOL(omap_rfbi_configure);
779 763
780int omap_rfbi_update(struct omap_dss_device *dssdev, void (*callback)(void *), 764int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
781 void *data) 765 u16 *x, u16 *y, u16 *w, u16 *h)
782{ 766{
783 return rfbi_transfer_area(dssdev, callback, data); 767 u16 dw, dh;
784}
785EXPORT_SYMBOL(omap_rfbi_update);
786 768
787void omapdss_rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) 769 dssdev->driver->get_resolution(dssdev, &dw, &dh);
788{
789 rfbi.timings.x_res = w;
790 rfbi.timings.y_res = h;
791}
792EXPORT_SYMBOL(omapdss_rfbi_set_size);
793 770
794void omapdss_rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size) 771 if (*x > dw || *y > dh)
795{ 772 return -EINVAL;
796 rfbi.pixel_size = pixel_size;
797}
798EXPORT_SYMBOL(omapdss_rfbi_set_pixel_size);
799 773
800void omapdss_rfbi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) 774 if (*x + *w > dw)
801{ 775 return -EINVAL;
802 rfbi.data_lines = data_lines; 776
777 if (*y + *h > dh)
778 return -EINVAL;
779
780 if (*w == 1)
781 return -EINVAL;
782
783 if (*w == 0 || *h == 0)
784 return -EINVAL;
785
786 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
787 dss_setup_partial_planes(dssdev, x, y, w, h, true);
788 dispc_set_lcd_size(dssdev->manager->id, *w, *h);
789 }
790
791 return 0;
803} 792}
804EXPORT_SYMBOL(omapdss_rfbi_set_data_lines); 793EXPORT_SYMBOL(omap_rfbi_prepare_update);
805 794
806void omapdss_rfbi_set_interface_timings(struct omap_dss_device *dssdev, 795int omap_rfbi_update(struct omap_dss_device *dssdev,
807 struct rfbi_timings *timings) 796 u16 x, u16 y, u16 w, u16 h,
797 void (*callback)(void *), void *data)
808{ 798{
809 rfbi.intf_timings = *timings; 799 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
800 rfbi_transfer_area(dssdev, w, h, callback, data);
801 } else {
802 struct omap_overlay *ovl;
803 void __iomem *addr;
804 int scr_width;
805
806 ovl = dssdev->manager->overlays[0];
807 scr_width = ovl->info.screen_width;
808 addr = ovl->info.vaddr;
809
810 omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
811
812 callback(data);
813 }
814
815 return 0;
810} 816}
811EXPORT_SYMBOL(omapdss_rfbi_set_interface_timings); 817EXPORT_SYMBOL(omap_rfbi_update);
812 818
813static void rfbi_dump_regs(struct seq_file *s) 819void rfbi_dump_regs(struct seq_file *s)
814{ 820{
815#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) 821#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
816 822
@@ -850,54 +856,10 @@ static void rfbi_dump_regs(struct seq_file *s)
850#undef DUMPREG 856#undef DUMPREG
851} 857}
852 858
853static void rfbi_config_lcd_manager(struct omap_dss_device *dssdev)
854{
855 struct omap_overlay_manager *mgr = dssdev->output->manager;
856 struct dss_lcd_mgr_config mgr_config;
857
858 mgr_config.io_pad_mode = DSS_IO_PAD_MODE_RFBI;
859
860 mgr_config.stallmode = true;
861 /* Do we need fifohandcheck for RFBI? */
862 mgr_config.fifohandcheck = false;
863
864 mgr_config.video_port_width = rfbi.pixel_size;
865 mgr_config.lcden_sig_polarity = 0;
866
867 dss_mgr_set_lcd_config(mgr, &mgr_config);
868
869 /*
870 * Set rfbi.timings with default values, the x_res and y_res fields
871 * are expected to be already configured by the panel driver via
872 * omapdss_rfbi_set_size()
873 */
874 rfbi.timings.hsw = 1;
875 rfbi.timings.hfp = 1;
876 rfbi.timings.hbp = 1;
877 rfbi.timings.vsw = 1;
878 rfbi.timings.vfp = 0;
879 rfbi.timings.vbp = 0;
880
881 rfbi.timings.interlace = false;
882 rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
883 rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
884 rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
885 rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
886 rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
887
888 dss_mgr_set_timings(mgr, &rfbi.timings);
889}
890
891int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 859int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
892{ 860{
893 struct omap_dss_output *out = dssdev->output;
894 int r; 861 int r;
895 862
896 if (out == NULL || out->manager == NULL) {
897 DSSERR("failed to enable display: no output/manager\n");
898 return -ENODEV;
899 }
900
901 r = rfbi_runtime_get(); 863 r = rfbi_runtime_get();
902 if (r) 864 if (r)
903 return r; 865 return r;
@@ -908,19 +870,28 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
908 goto err0; 870 goto err0;
909 } 871 }
910 872
911 r = dss_mgr_register_framedone_handler(out->manager, 873 r = omap_dispc_register_isr(framedone_callback, NULL,
912 framedone_callback, NULL); 874 DISPC_IRQ_FRAMEDONE);
913 if (r) { 875 if (r) {
914 DSSERR("can't get FRAMEDONE irq\n"); 876 DSSERR("can't get FRAMEDONE irq\n");
915 goto err1; 877 goto err1;
916 } 878 }
917 879
918 rfbi_config_lcd_manager(dssdev); 880 dispc_set_lcd_display_type(dssdev->manager->id,
881 OMAP_DSS_LCD_DISPLAY_TFT);
882
883 dispc_set_parallel_interface_mode(dssdev->manager->id,
884 OMAP_DSS_PARALLELMODE_RFBI);
919 885
920 rfbi_configure(dssdev->phy.rfbi.channel, rfbi.pixel_size, 886 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);
921 rfbi.data_lines); 887
888 rfbi_configure(dssdev->phy.rfbi.channel,
889 dssdev->ctrl.pixel_size,
890 dssdev->phy.rfbi.data_lines);
891
892 rfbi_set_timings(dssdev->phy.rfbi.channel,
893 &dssdev->ctrl.rfbi_timings);
922 894
923 rfbi_set_timings(dssdev->phy.rfbi.channel, &rfbi.intf_timings);
924 895
925 return 0; 896 return 0;
926err1: 897err1:
@@ -933,111 +904,23 @@ EXPORT_SYMBOL(omapdss_rfbi_display_enable);
933 904
934void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) 905void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
935{ 906{
936 struct omap_dss_output *out = dssdev->output; 907 omap_dispc_unregister_isr(framedone_callback, NULL,
937 908 DISPC_IRQ_FRAMEDONE);
938 dss_mgr_unregister_framedone_handler(out->manager,
939 framedone_callback, NULL);
940 omap_dss_stop_device(dssdev); 909 omap_dss_stop_device(dssdev);
941 910
942 rfbi_runtime_put(); 911 rfbi_runtime_put();
943} 912}
944EXPORT_SYMBOL(omapdss_rfbi_display_disable); 913EXPORT_SYMBOL(omapdss_rfbi_display_disable);
945 914
946static int __init rfbi_init_display(struct omap_dss_device *dssdev) 915int rfbi_init_display(struct omap_dss_device *dssdev)
947{ 916{
948 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 917 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
918 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
949 return 0; 919 return 0;
950} 920}
951 921
952static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
953{
954 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
955 const char *def_disp_name = omapdss_get_default_display_name();
956 struct omap_dss_device *def_dssdev;
957 int i;
958
959 def_dssdev = NULL;
960
961 for (i = 0; i < pdata->num_devices; ++i) {
962 struct omap_dss_device *dssdev = pdata->devices[i];
963
964 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
965 continue;
966
967 if (def_dssdev == NULL)
968 def_dssdev = dssdev;
969
970 if (def_disp_name != NULL &&
971 strcmp(dssdev->name, def_disp_name) == 0) {
972 def_dssdev = dssdev;
973 break;
974 }
975 }
976
977 return def_dssdev;
978}
979
980static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
981{
982 struct omap_dss_device *plat_dssdev;
983 struct omap_dss_device *dssdev;
984 int r;
985
986 plat_dssdev = rfbi_find_dssdev(rfbidev);
987
988 if (!plat_dssdev)
989 return;
990
991 dssdev = dss_alloc_and_init_device(&rfbidev->dev);
992 if (!dssdev)
993 return;
994
995 dss_copy_device_pdata(dssdev, plat_dssdev);
996
997 r = rfbi_init_display(dssdev);
998 if (r) {
999 DSSERR("device %s init failed: %d\n", dssdev->name, r);
1000 dss_put_device(dssdev);
1001 return;
1002 }
1003
1004 r = omapdss_output_set_device(&rfbi.output, dssdev);
1005 if (r) {
1006 DSSERR("failed to connect output to new device: %s\n",
1007 dssdev->name);
1008 dss_put_device(dssdev);
1009 return;
1010 }
1011
1012 r = dss_add_device(dssdev);
1013 if (r) {
1014 DSSERR("device %s register failed: %d\n", dssdev->name, r);
1015 omapdss_output_unset_device(&rfbi.output);
1016 dss_put_device(dssdev);
1017 return;
1018 }
1019}
1020
1021static void __init rfbi_init_output(struct platform_device *pdev)
1022{
1023 struct omap_dss_output *out = &rfbi.output;
1024
1025 out->pdev = pdev;
1026 out->id = OMAP_DSS_OUTPUT_DBI;
1027 out->type = OMAP_DISPLAY_TYPE_DBI;
1028
1029 dss_register_output(out);
1030}
1031
1032static void __exit rfbi_uninit_output(struct platform_device *pdev)
1033{
1034 struct omap_dss_output *out = &rfbi.output;
1035
1036 dss_unregister_output(out);
1037}
1038
1039/* RFBI HW IP initialisation */ 922/* RFBI HW IP initialisation */
1040static int __init omap_rfbihw_probe(struct platform_device *pdev) 923static int omap_rfbihw_probe(struct platform_device *pdev)
1041{ 924{
1042 u32 rev; 925 u32 rev;
1043 struct resource *rfbi_mem; 926 struct resource *rfbi_mem;
@@ -1051,67 +934,66 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev)
1051 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); 934 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
1052 if (!rfbi_mem) { 935 if (!rfbi_mem) {
1053 DSSERR("can't get IORESOURCE_MEM RFBI\n"); 936 DSSERR("can't get IORESOURCE_MEM RFBI\n");
1054 return -EINVAL; 937 r = -EINVAL;
938 goto err_ioremap;
1055 } 939 }
1056 940 rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem));
1057 rfbi.base = devm_ioremap(&pdev->dev, rfbi_mem->start,
1058 resource_size(rfbi_mem));
1059 if (!rfbi.base) { 941 if (!rfbi.base) {
1060 DSSERR("can't ioremap RFBI\n"); 942 DSSERR("can't ioremap RFBI\n");
1061 return -ENOMEM; 943 r = -ENOMEM;
944 goto err_ioremap;
1062 } 945 }
1063 946
1064 clk = clk_get(&pdev->dev, "ick"); 947 pm_runtime_enable(&pdev->dev);
948
949 r = rfbi_runtime_get();
950 if (r)
951 goto err_get_rfbi;
952
953 msleep(10);
954
955 if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630())
956 clk = dss_get_ick();
957 else
958 clk = clk_get(&pdev->dev, "ick");
1065 if (IS_ERR(clk)) { 959 if (IS_ERR(clk)) {
1066 DSSERR("can't get ick\n"); 960 DSSERR("can't get ick\n");
1067 return PTR_ERR(clk); 961 r = PTR_ERR(clk);
962 goto err_get_ick;
1068 } 963 }
1069 964
1070 rfbi.l4_khz = clk_get_rate(clk) / 1000; 965 rfbi.l4_khz = clk_get_rate(clk) / 1000;
1071 966
1072 clk_put(clk); 967 clk_put(clk);
1073 968
1074 pm_runtime_enable(&pdev->dev);
1075
1076 r = rfbi_runtime_get();
1077 if (r)
1078 goto err_runtime_get;
1079
1080 msleep(10);
1081
1082 rev = rfbi_read_reg(RFBI_REVISION); 969 rev = rfbi_read_reg(RFBI_REVISION);
1083 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", 970 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n",
1084 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 971 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1085 972
1086 rfbi_runtime_put(); 973 rfbi_runtime_put();
1087 974
1088 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1089
1090 rfbi_init_output(pdev);
1091
1092 rfbi_probe_pdata(pdev);
1093
1094 return 0; 975 return 0;
1095 976
1096err_runtime_get: 977err_get_ick:
978 rfbi_runtime_put();
979err_get_rfbi:
1097 pm_runtime_disable(&pdev->dev); 980 pm_runtime_disable(&pdev->dev);
981 iounmap(rfbi.base);
982err_ioremap:
1098 return r; 983 return r;
1099} 984}
1100 985
1101static int __exit omap_rfbihw_remove(struct platform_device *pdev) 986static int omap_rfbihw_remove(struct platform_device *pdev)
1102{ 987{
1103 dss_unregister_child_devices(&pdev->dev);
1104
1105 rfbi_uninit_output(pdev);
1106
1107 pm_runtime_disable(&pdev->dev); 988 pm_runtime_disable(&pdev->dev);
1108 989 iounmap(rfbi.base);
1109 return 0; 990 return 0;
1110} 991}
1111 992
1112static int rfbi_runtime_suspend(struct device *dev) 993static int rfbi_runtime_suspend(struct device *dev)
1113{ 994{
1114 dispc_runtime_put(); 995 dispc_runtime_put();
996 dss_runtime_put();
1115 997
1116 return 0; 998 return 0;
1117} 999}
@@ -1120,11 +1002,20 @@ static int rfbi_runtime_resume(struct device *dev)
1120{ 1002{
1121 int r; 1003 int r;
1122 1004
1005 r = dss_runtime_get();
1006 if (r < 0)
1007 goto err_get_dss;
1008
1123 r = dispc_runtime_get(); 1009 r = dispc_runtime_get();
1124 if (r < 0) 1010 if (r < 0)
1125 return r; 1011 goto err_get_dispc;
1126 1012
1127 return 0; 1013 return 0;
1014
1015err_get_dispc:
1016 dss_runtime_put();
1017err_get_dss:
1018 return r;
1128} 1019}
1129 1020
1130static const struct dev_pm_ops rfbi_pm_ops = { 1021static const struct dev_pm_ops rfbi_pm_ops = {
@@ -1133,7 +1024,8 @@ static const struct dev_pm_ops rfbi_pm_ops = {
1133}; 1024};
1134 1025
1135static struct platform_driver omap_rfbihw_driver = { 1026static struct platform_driver omap_rfbihw_driver = {
1136 .remove = __exit_p(omap_rfbihw_remove), 1027 .probe = omap_rfbihw_probe,
1028 .remove = omap_rfbihw_remove,
1137 .driver = { 1029 .driver = {
1138 .name = "omapdss_rfbi", 1030 .name = "omapdss_rfbi",
1139 .owner = THIS_MODULE, 1031 .owner = THIS_MODULE,
@@ -1141,12 +1033,12 @@ static struct platform_driver omap_rfbihw_driver = {
1141 }, 1033 },
1142}; 1034};
1143 1035
1144int __init rfbi_init_platform_driver(void) 1036int rfbi_init_platform_driver(void)
1145{ 1037{
1146 return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe); 1038 return platform_driver_register(&omap_rfbihw_driver);
1147} 1039}
1148 1040
1149void __exit rfbi_uninit_platform_driver(void) 1041void rfbi_uninit_platform_driver(void)
1150{ 1042{
1151 platform_driver_unregister(&omap_rfbihw_driver); 1043 return platform_driver_unregister(&omap_rfbihw_driver);
1152} 1044}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 62b5374ce43..3a688c871a4 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -23,9 +23,6 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
26#include <linux/export.h>
27#include <linux/platform_device.h>
28#include <linux/string.h>
29 26
30#include <video/omapdss.h> 27#include <video/omapdss.h>
31#include "dss.h" 28#include "dss.h"
@@ -33,43 +30,31 @@
33static struct { 30static struct {
34 bool update_enabled; 31 bool update_enabled;
35 struct regulator *vdds_sdi_reg; 32 struct regulator *vdds_sdi_reg;
36
37 struct dss_lcd_mgr_config mgr_config;
38 struct omap_video_timings timings;
39 int datapairs;
40
41 struct omap_dss_output output;
42} sdi; 33} sdi;
43 34
44static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) 35static void sdi_basic_init(struct omap_dss_device *dssdev)
45{
46 struct omap_overlay_manager *mgr = dssdev->output->manager;
47 36
48 sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 37{
49 38 dispc_set_parallel_interface_mode(dssdev->manager->id,
50 sdi.mgr_config.stallmode = false; 39 OMAP_DSS_PARALLELMODE_BYPASS);
51 sdi.mgr_config.fifohandcheck = false;
52 40
53 sdi.mgr_config.video_port_width = 24; 41 dispc_set_lcd_display_type(dssdev->manager->id,
54 sdi.mgr_config.lcden_sig_polarity = 1; 42 OMAP_DSS_LCD_DISPLAY_TFT);
55 43
56 dss_mgr_set_lcd_config(mgr, &sdi.mgr_config); 44 dispc_set_tft_data_lines(dssdev->manager->id, 24);
45 dispc_lcd_enable_signal_polarity(1);
57} 46}
58 47
59int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) 48int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
60{ 49{
61 struct omap_dss_output *out = dssdev->output; 50 struct omap_video_timings *t = &dssdev->panel.timings;
62 struct omap_video_timings *t = &sdi.timings;
63 struct dss_clock_info dss_cinfo; 51 struct dss_clock_info dss_cinfo;
64 struct dispc_clock_info dispc_cinfo; 52 struct dispc_clock_info dispc_cinfo;
53 u16 lck_div, pck_div;
54 unsigned long fck;
65 unsigned long pck; 55 unsigned long pck;
66 int r; 56 int r;
67 57
68 if (out == NULL || out->manager == NULL) {
69 DSSERR("failed to enable display: no output/manager\n");
70 return -ENODEV;
71 }
72
73 r = omap_dss_start_device(dssdev); 58 r = omap_dss_start_device(dssdev);
74 if (r) { 59 if (r) {
75 DSSERR("failed to start device\n"); 60 DSSERR("failed to start device\n");
@@ -80,21 +65,32 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
80 if (r) 65 if (r)
81 goto err_reg_enable; 66 goto err_reg_enable;
82 67
68 r = dss_runtime_get();
69 if (r)
70 goto err_get_dss;
71
83 r = dispc_runtime_get(); 72 r = dispc_runtime_get();
84 if (r) 73 if (r)
85 goto err_get_dispc; 74 goto err_get_dispc;
86 75
76 sdi_basic_init(dssdev);
77
87 /* 15.5.9.1.2 */ 78 /* 15.5.9.1.2 */
88 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 79 dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
89 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; 80
81 dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config,
82 dssdev->panel.acbi, dssdev->panel.acb);
90 83
91 r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); 84 r = dss_calc_clock_div(1, t->pixel_clock * 1000,
85 &dss_cinfo, &dispc_cinfo);
92 if (r) 86 if (r)
93 goto err_calc_clock_div; 87 goto err_calc_clock_div;
94 88
95 sdi.mgr_config.clock_info = dispc_cinfo; 89 fck = dss_cinfo.fck;
90 lck_div = dispc_cinfo.lck_div;
91 pck_div = dispc_cinfo.pck_div;
96 92
97 pck = dss_cinfo.fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div / 1000; 93 pck = fck / lck_div / pck_div / 1000;
98 94
99 if (pck != t->pixel_clock) { 95 if (pck != t->pixel_clock) {
100 DSSWARN("Could not find exact pixel clock. Requested %d kHz, " 96 DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
@@ -105,46 +101,34 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
105 } 101 }
106 102
107 103
108 dss_mgr_set_timings(out->manager, t); 104 dispc_set_lcd_timings(dssdev->manager->id, t);
109 105
110 r = dss_set_clock_div(&dss_cinfo); 106 r = dss_set_clock_div(&dss_cinfo);
111 if (r) 107 if (r)
112 goto err_set_dss_clock_div; 108 goto err_set_dss_clock_div;
113 109
114 sdi_config_lcd_manager(dssdev); 110 r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
115 111 if (r)
116 /* 112 goto err_set_dispc_clock_div;
117 * LCLK and PCLK divisors are located in shadow registers, and we 113
118 * normally write them to DISPC registers when enabling the output. 114 dss_sdi_init(dssdev->phy.sdi.datapairs);
119 * However, SDI uses pck-free as source clock for its PLL, and pck-free
120 * is affected by the divisors. And as we need the PLL before enabling
121 * the output, we need to write the divisors early.
122 *
123 * It seems just writing to the DISPC register is enough, and we don't
124 * need to care about the shadow register mechanism for pck-free. The
125 * exact reason for this is unknown.
126 */
127 dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info);
128
129 dss_sdi_init(sdi.datapairs);
130 r = dss_sdi_enable(); 115 r = dss_sdi_enable();
131 if (r) 116 if (r)
132 goto err_sdi_enable; 117 goto err_sdi_enable;
133 mdelay(2); 118 mdelay(2);
134 119
135 r = dss_mgr_enable(out->manager); 120 dssdev->manager->enable(dssdev->manager);
136 if (r)
137 goto err_mgr_enable;
138 121
139 return 0; 122 return 0;
140 123
141err_mgr_enable:
142 dss_sdi_disable();
143err_sdi_enable: 124err_sdi_enable:
125err_set_dispc_clock_div:
144err_set_dss_clock_div: 126err_set_dss_clock_div:
145err_calc_clock_div: 127err_calc_clock_div:
146 dispc_runtime_put(); 128 dispc_runtime_put();
147err_get_dispc: 129err_get_dispc:
130 dss_runtime_put();
131err_get_dss:
148 regulator_disable(sdi.vdds_sdi_reg); 132 regulator_disable(sdi.vdds_sdi_reg);
149err_reg_enable: 133err_reg_enable:
150 omap_dss_stop_device(dssdev); 134 omap_dss_stop_device(dssdev);
@@ -155,13 +139,12 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
155 139
156void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 140void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
157{ 141{
158 struct omap_overlay_manager *mgr = dssdev->output->manager; 142 dssdev->manager->disable(dssdev->manager);
159
160 dss_mgr_disable(mgr);
161 143
162 dss_sdi_disable(); 144 dss_sdi_disable();
163 145
164 dispc_runtime_put(); 146 dispc_runtime_put();
147 dss_runtime_put();
165 148
166 regulator_disable(sdi.vdds_sdi_reg); 149 regulator_disable(sdi.vdds_sdi_reg);
167 150
@@ -169,20 +152,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
169} 152}
170EXPORT_SYMBOL(omapdss_sdi_display_disable); 153EXPORT_SYMBOL(omapdss_sdi_display_disable);
171 154
172void omapdss_sdi_set_timings(struct omap_dss_device *dssdev, 155int sdi_init_display(struct omap_dss_device *dssdev)
173 struct omap_video_timings *timings)
174{
175 sdi.timings = *timings;
176}
177EXPORT_SYMBOL(omapdss_sdi_set_timings);
178
179void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs)
180{
181 sdi.datapairs = datapairs;
182}
183EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
184
185static int __init sdi_init_display(struct omap_dss_device *dssdev)
186{ 156{
187 DSSDBG("SDI init\n"); 157 DSSDBG("SDI init\n");
188 158
@@ -202,125 +172,11 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev)
202 return 0; 172 return 0;
203} 173}
204 174
205static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) 175int sdi_init(void)
206{
207 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
208 const char *def_disp_name = omapdss_get_default_display_name();
209 struct omap_dss_device *def_dssdev;
210 int i;
211
212 def_dssdev = NULL;
213
214 for (i = 0; i < pdata->num_devices; ++i) {
215 struct omap_dss_device *dssdev = pdata->devices[i];
216
217 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
218 continue;
219
220 if (def_dssdev == NULL)
221 def_dssdev = dssdev;
222
223 if (def_disp_name != NULL &&
224 strcmp(dssdev->name, def_disp_name) == 0) {
225 def_dssdev = dssdev;
226 break;
227 }
228 }
229
230 return def_dssdev;
231}
232
233static void __init sdi_probe_pdata(struct platform_device *sdidev)
234{ 176{
235 struct omap_dss_device *plat_dssdev;
236 struct omap_dss_device *dssdev;
237 int r;
238
239 plat_dssdev = sdi_find_dssdev(sdidev);
240
241 if (!plat_dssdev)
242 return;
243
244 dssdev = dss_alloc_and_init_device(&sdidev->dev);
245 if (!dssdev)
246 return;
247
248 dss_copy_device_pdata(dssdev, plat_dssdev);
249
250 r = sdi_init_display(dssdev);
251 if (r) {
252 DSSERR("device %s init failed: %d\n", dssdev->name, r);
253 dss_put_device(dssdev);
254 return;
255 }
256
257 r = omapdss_output_set_device(&sdi.output, dssdev);
258 if (r) {
259 DSSERR("failed to connect output to new device: %s\n",
260 dssdev->name);
261 dss_put_device(dssdev);
262 return;
263 }
264
265 r = dss_add_device(dssdev);
266 if (r) {
267 DSSERR("device %s register failed: %d\n", dssdev->name, r);
268 omapdss_output_unset_device(&sdi.output);
269 dss_put_device(dssdev);
270 return;
271 }
272}
273
274static void __init sdi_init_output(struct platform_device *pdev)
275{
276 struct omap_dss_output *out = &sdi.output;
277
278 out->pdev = pdev;
279 out->id = OMAP_DSS_OUTPUT_SDI;
280 out->type = OMAP_DISPLAY_TYPE_SDI;
281
282 dss_register_output(out);
283}
284
285static void __exit sdi_uninit_output(struct platform_device *pdev)
286{
287 struct omap_dss_output *out = &sdi.output;
288
289 dss_unregister_output(out);
290}
291
292static int __init omap_sdi_probe(struct platform_device *pdev)
293{
294 sdi_init_output(pdev);
295
296 sdi_probe_pdata(pdev);
297
298 return 0; 177 return 0;
299} 178}
300 179
301static int __exit omap_sdi_remove(struct platform_device *pdev) 180void sdi_exit(void)
302{
303 dss_unregister_child_devices(&pdev->dev);
304
305 sdi_uninit_output(pdev);
306
307 return 0;
308}
309
310static struct platform_driver omap_sdi_driver = {
311 .remove = __exit_p(omap_sdi_remove),
312 .driver = {
313 .name = "omapdss_sdi",
314 .owner = THIS_MODULE,
315 },
316};
317
318int __init sdi_init_platform_driver(void)
319{
320 return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe);
321}
322
323void __exit sdi_uninit_platform_driver(void)
324{ 181{
325 platform_driver_unregister(&omap_sdi_driver);
326} 182}
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
deleted file mode 100644
index 216aa704f9d..00000000000
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ /dev/null
@@ -1,190 +0,0 @@
1/*
2 * ti_hdmi.h
3 *
4 * HDMI driver definition for TI OMAP4, DM81xx, DM38xx Processor.
5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef _TI_HDMI_H
22#define _TI_HDMI_H
23
24struct hdmi_ip_data;
25
26enum hdmi_pll_pwr {
27 HDMI_PLLPWRCMD_ALLOFF = 0,
28 HDMI_PLLPWRCMD_PLLONLY = 1,
29 HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2,
30 HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3
31};
32
33enum hdmi_core_hdmi_dvi {
34 HDMI_DVI = 0,
35 HDMI_HDMI = 1
36};
37
38enum hdmi_clk_refsel {
39 HDMI_REFSEL_PCLK = 0,
40 HDMI_REFSEL_REF1 = 1,
41 HDMI_REFSEL_REF2 = 2,
42 HDMI_REFSEL_SYSCLK = 3
43};
44
45struct hdmi_cm {
46 int code;
47 int mode;
48};
49
50struct hdmi_config {
51 struct omap_video_timings timings;
52 struct hdmi_cm cm;
53};
54
55/* HDMI PLL structure */
56struct hdmi_pll_info {
57 u16 regn;
58 u16 regm;
59 u32 regmf;
60 u16 regm2;
61 u16 regsd;
62 u16 dcofreq;
63 enum hdmi_clk_refsel refsel;
64};
65
66struct ti_hdmi_ip_ops {
67
68 void (*video_configure)(struct hdmi_ip_data *ip_data);
69
70 int (*phy_enable)(struct hdmi_ip_data *ip_data);
71
72 void (*phy_disable)(struct hdmi_ip_data *ip_data);
73
74 int (*read_edid)(struct hdmi_ip_data *ip_data, u8 *edid, int len);
75
76 bool (*detect)(struct hdmi_ip_data *ip_data);
77
78 int (*pll_enable)(struct hdmi_ip_data *ip_data);
79
80 void (*pll_disable)(struct hdmi_ip_data *ip_data);
81
82 int (*video_enable)(struct hdmi_ip_data *ip_data);
83
84 void (*video_disable)(struct hdmi_ip_data *ip_data);
85
86 void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
87
88 void (*dump_core)(struct hdmi_ip_data *ip_data, struct seq_file *s);
89
90 void (*dump_pll)(struct hdmi_ip_data *ip_data, struct seq_file *s);
91
92 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
93
94#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
95 int (*audio_enable)(struct hdmi_ip_data *ip_data);
96
97 void (*audio_disable)(struct hdmi_ip_data *ip_data);
98
99 int (*audio_start)(struct hdmi_ip_data *ip_data);
100
101 void (*audio_stop)(struct hdmi_ip_data *ip_data);
102
103 int (*audio_config)(struct hdmi_ip_data *ip_data,
104 struct omap_dss_audio *audio);
105
106 int (*audio_get_dma_port)(u32 *offset, u32 *size);
107#endif
108
109};
110
111/*
112 * Refer to section 8.2 in HDMI 1.3 specification for
113 * details about infoframe databytes
114 */
115struct hdmi_core_infoframe_avi {
116 /* Y0, Y1 rgb,yCbCr */
117 u8 db1_format;
118 /* A0 Active information Present */
119 u8 db1_active_info;
120 /* B0, B1 Bar info data valid */
121 u8 db1_bar_info_dv;
122 /* S0, S1 scan information */
123 u8 db1_scan_info;
124 /* C0, C1 colorimetry */
125 u8 db2_colorimetry;
126 /* M0, M1 Aspect ratio (4:3, 16:9) */
127 u8 db2_aspect_ratio;
128 /* R0...R3 Active format aspect ratio */
129 u8 db2_active_fmt_ar;
130 /* ITC IT content. */
131 u8 db3_itc;
132 /* EC0, EC1, EC2 Extended colorimetry */
133 u8 db3_ec;
134 /* Q1, Q0 Quantization range */
135 u8 db3_q_range;
136 /* SC1, SC0 Non-uniform picture scaling */
137 u8 db3_nup_scaling;
138 /* VIC0..6 Video format identification */
139 u8 db4_videocode;
140 /* PR0..PR3 Pixel repetition factor */
141 u8 db5_pixel_repeat;
142 /* Line number end of top bar */
143 u16 db6_7_line_eoftop;
144 /* Line number start of bottom bar */
145 u16 db8_9_line_sofbottom;
146 /* Pixel number end of left bar */
147 u16 db10_11_pixel_eofleft;
148 /* Pixel number start of right bar */
149 u16 db12_13_pixel_sofright;
150};
151
152struct hdmi_ip_data {
153 void __iomem *base_wp; /* HDMI wrapper */
154 unsigned long core_sys_offset;
155 unsigned long core_av_offset;
156 unsigned long pll_offset;
157 unsigned long phy_offset;
158 const struct ti_hdmi_ip_ops *ops;
159 struct hdmi_config cfg;
160 struct hdmi_pll_info pll_data;
161 struct hdmi_core_infoframe_avi avi_cfg;
162
163 /* ti_hdmi_4xxx_ip private data. These should be in a separate struct */
164 int hpd_gpio;
165 struct mutex lock;
166};
167int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
168void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
169int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
170bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
171int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data);
172void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data);
173int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
174void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
175void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
176void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
177void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
178void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
179void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
180#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
181int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts);
182int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data);
183void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data);
184int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
185void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
186int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
187 struct omap_dss_audio *audio);
188int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size);
189#endif
190#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
deleted file mode 100644
index e18b222ed73..00000000000
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ /dev/null
@@ -1,1430 +0,0 @@
1/*
2 * ti_hdmi_4xxx_ip.c
3 *
4 * HDMI TI81xx, TI38xx, TI OMAP4 etc IP driver Library
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Authors: Yong Zhi
7 * Mythri pk <mythripk@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published by
11 * the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along with
19 * this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <linux/interrupt.h>
27#include <linux/mutex.h>
28#include <linux/delay.h>
29#include <linux/string.h>
30#include <linux/seq_file.h>
31#include <linux/gpio.h>
32#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
33#include <sound/asound.h>
34#include <sound/asoundef.h>
35#endif
36
37#include "ti_hdmi_4xxx_ip.h"
38#include "dss.h"
39#include "dss_features.h"
40
41static inline void hdmi_write_reg(void __iomem *base_addr,
42 const u16 idx, u32 val)
43{
44 __raw_writel(val, base_addr + idx);
45}
46
47static inline u32 hdmi_read_reg(void __iomem *base_addr,
48 const u16 idx)
49{
50 return __raw_readl(base_addr + idx);
51}
52
53static inline void __iomem *hdmi_wp_base(struct hdmi_ip_data *ip_data)
54{
55 return ip_data->base_wp;
56}
57
58static inline void __iomem *hdmi_phy_base(struct hdmi_ip_data *ip_data)
59{
60 return ip_data->base_wp + ip_data->phy_offset;
61}
62
63static inline void __iomem *hdmi_pll_base(struct hdmi_ip_data *ip_data)
64{
65 return ip_data->base_wp + ip_data->pll_offset;
66}
67
68static inline void __iomem *hdmi_av_base(struct hdmi_ip_data *ip_data)
69{
70 return ip_data->base_wp + ip_data->core_av_offset;
71}
72
73static inline void __iomem *hdmi_core_sys_base(struct hdmi_ip_data *ip_data)
74{
75 return ip_data->base_wp + ip_data->core_sys_offset;
76}
77
78static inline int hdmi_wait_for_bit_change(void __iomem *base_addr,
79 const u16 idx,
80 int b2, int b1, u32 val)
81{
82 u32 t = 0;
83 while (val != REG_GET(base_addr, idx, b2, b1)) {
84 udelay(1);
85 if (t++ > 10000)
86 return !val;
87 }
88 return val;
89}
90
91static int hdmi_pll_init(struct hdmi_ip_data *ip_data)
92{
93 u32 r;
94 void __iomem *pll_base = hdmi_pll_base(ip_data);
95 struct hdmi_pll_info *fmt = &ip_data->pll_data;
96
97 /* PLL start always use manual mode */
98 REG_FLD_MOD(pll_base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0);
99
100 r = hdmi_read_reg(pll_base, PLLCTRL_CFG1);
101 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
102 r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
103
104 hdmi_write_reg(pll_base, PLLCTRL_CFG1, r);
105
106 r = hdmi_read_reg(pll_base, PLLCTRL_CFG2);
107
108 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
109 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
110 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
111 r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
112
113 if (fmt->dcofreq) {
114 /* divider programming for frequency beyond 1000Mhz */
115 REG_FLD_MOD(pll_base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
116 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
117 } else {
118 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */
119 }
120
121 hdmi_write_reg(pll_base, PLLCTRL_CFG2, r);
122
123 r = hdmi_read_reg(pll_base, PLLCTRL_CFG4);
124 r = FLD_MOD(r, fmt->regm2, 24, 18);
125 r = FLD_MOD(r, fmt->regmf, 17, 0);
126
127 hdmi_write_reg(pll_base, PLLCTRL_CFG4, r);
128
129 /* go now */
130 REG_FLD_MOD(pll_base, PLLCTRL_PLL_GO, 0x1, 0, 0);
131
132 /* wait for bit change */
133 if (hdmi_wait_for_bit_change(pll_base, PLLCTRL_PLL_GO,
134 0, 0, 1) != 1) {
135 pr_err("PLL GO bit not set\n");
136 return -ETIMEDOUT;
137 }
138
139 /* Wait till the lock bit is set in PLL status */
140 if (hdmi_wait_for_bit_change(pll_base,
141 PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) {
142 pr_err("cannot lock PLL\n");
143 pr_err("CFG1 0x%x\n",
144 hdmi_read_reg(pll_base, PLLCTRL_CFG1));
145 pr_err("CFG2 0x%x\n",
146 hdmi_read_reg(pll_base, PLLCTRL_CFG2));
147 pr_err("CFG4 0x%x\n",
148 hdmi_read_reg(pll_base, PLLCTRL_CFG4));
149 return -ETIMEDOUT;
150 }
151
152 pr_debug("PLL locked!\n");
153
154 return 0;
155}
156
157/* PHY_PWR_CMD */
158static int hdmi_set_phy_pwr(struct hdmi_ip_data *ip_data, enum hdmi_phy_pwr val)
159{
160 /* Return if already the state */
161 if (REG_GET(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, 5, 4) == val)
162 return 0;
163
164 /* Command for power control of HDMI PHY */
165 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 7, 6);
166
167 /* Status of the power control of HDMI PHY */
168 if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data),
169 HDMI_WP_PWR_CTRL, 5, 4, val) != val) {
170 pr_err("Failed to set PHY power mode to %d\n", val);
171 return -ETIMEDOUT;
172 }
173
174 return 0;
175}
176
177/* PLL_PWR_CMD */
178static int hdmi_set_pll_pwr(struct hdmi_ip_data *ip_data, enum hdmi_pll_pwr val)
179{
180 /* Command for power control of HDMI PLL */
181 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL, val, 3, 2);
182
183 /* wait till PHY_PWR_STATUS is set */
184 if (hdmi_wait_for_bit_change(hdmi_wp_base(ip_data), HDMI_WP_PWR_CTRL,
185 1, 0, val) != val) {
186 pr_err("Failed to set PLL_PWR_STATUS\n");
187 return -ETIMEDOUT;
188 }
189
190 return 0;
191}
192
193static int hdmi_pll_reset(struct hdmi_ip_data *ip_data)
194{
195 /* SYSRESET controlled by power FSM */
196 REG_FLD_MOD(hdmi_pll_base(ip_data), PLLCTRL_PLL_CONTROL, 0x0, 3, 3);
197
198 /* READ 0x0 reset is in progress */
199 if (hdmi_wait_for_bit_change(hdmi_pll_base(ip_data),
200 PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) {
201 pr_err("Failed to sysreset PLL\n");
202 return -ETIMEDOUT;
203 }
204
205 return 0;
206}
207
208int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data)
209{
210 u16 r = 0;
211
212 r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
213 if (r)
214 return r;
215
216 r = hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
217 if (r)
218 return r;
219
220 r = hdmi_pll_reset(ip_data);
221 if (r)
222 return r;
223
224 r = hdmi_pll_init(ip_data);
225 if (r)
226 return r;
227
228 return 0;
229}
230
231void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data)
232{
233 hdmi_set_pll_pwr(ip_data, HDMI_PLLPWRCMD_ALLOFF);
234}
235
236static int hdmi_check_hpd_state(struct hdmi_ip_data *ip_data)
237{
238 bool hpd;
239 int r;
240
241 mutex_lock(&ip_data->lock);
242
243 hpd = gpio_get_value(ip_data->hpd_gpio);
244
245 if (hpd)
246 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_TXON);
247 else
248 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
249
250 if (r) {
251 DSSERR("Failed to %s PHY TX power\n",
252 hpd ? "enable" : "disable");
253 goto err;
254 }
255
256err:
257 mutex_unlock(&ip_data->lock);
258 return r;
259}
260
261static irqreturn_t hpd_irq_handler(int irq, void *data)
262{
263 struct hdmi_ip_data *ip_data = data;
264
265 hdmi_check_hpd_state(ip_data);
266
267 return IRQ_HANDLED;
268}
269
270int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
271{
272 u16 r = 0;
273 void __iomem *phy_base = hdmi_phy_base(ip_data);
274
275 r = hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_LDOON);
276 if (r)
277 return r;
278
279 /*
280 * Read address 0 in order to get the SCP reset done completed
281 * Dummy access performed to make sure reset is done
282 */
283 hdmi_read_reg(phy_base, HDMI_TXPHY_TX_CTRL);
284
285 /*
286 * Write to phy address 0 to configure the clock
287 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
288 */
289 REG_FLD_MOD(phy_base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30);
290
291 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
292 hdmi_write_reg(phy_base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
293
294 /* Setup max LDO voltage */
295 REG_FLD_MOD(phy_base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
296
297 /* Write to phy address 3 to change the polarity control */
298 REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
299
300 r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
301 NULL, hpd_irq_handler,
302 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
303 IRQF_ONESHOT, "hpd", ip_data);
304 if (r) {
305 DSSERR("HPD IRQ request failed\n");
306 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
307 return r;
308 }
309
310 r = hdmi_check_hpd_state(ip_data);
311 if (r) {
312 free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
313 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
314 return r;
315 }
316
317 return 0;
318}
319
320void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data)
321{
322 free_irq(gpio_to_irq(ip_data->hpd_gpio), ip_data);
323
324 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
325}
326
327static int hdmi_core_ddc_init(struct hdmi_ip_data *ip_data)
328{
329 void __iomem *base = hdmi_core_sys_base(ip_data);
330
331 /* Turn on CLK for DDC */
332 REG_FLD_MOD(base, HDMI_CORE_AV_DPD, 0x7, 2, 0);
333
334 /* IN_PROG */
335 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 1) {
336 /* Abort transaction */
337 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xf, 3, 0);
338 /* IN_PROG */
339 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
340 4, 4, 0) != 0) {
341 DSSERR("Timeout aborting DDC transaction\n");
342 return -ETIMEDOUT;
343 }
344 }
345
346 /* Clk SCL Devices */
347 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0xA, 3, 0);
348
349 /* HDMI_CORE_DDC_STATUS_IN_PROG */
350 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
351 4, 4, 0) != 0) {
352 DSSERR("Timeout starting SCL clock\n");
353 return -ETIMEDOUT;
354 }
355
356 /* Clear FIFO */
357 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x9, 3, 0);
358
359 /* HDMI_CORE_DDC_STATUS_IN_PROG */
360 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
361 4, 4, 0) != 0) {
362 DSSERR("Timeout clearing DDC fifo\n");
363 return -ETIMEDOUT;
364 }
365
366 return 0;
367}
368
369static int hdmi_core_ddc_edid(struct hdmi_ip_data *ip_data,
370 u8 *pedid, int ext)
371{
372 void __iomem *base = hdmi_core_sys_base(ip_data);
373 u32 i;
374 char checksum;
375 u32 offset = 0;
376
377 /* HDMI_CORE_DDC_STATUS_IN_PROG */
378 if (hdmi_wait_for_bit_change(base, HDMI_CORE_DDC_STATUS,
379 4, 4, 0) != 0) {
380 DSSERR("Timeout waiting DDC to be ready\n");
381 return -ETIMEDOUT;
382 }
383
384 if (ext % 2 != 0)
385 offset = 0x80;
386
387 /* Load Segment Address Register */
388 REG_FLD_MOD(base, HDMI_CORE_DDC_SEGM, ext / 2, 7, 0);
389
390 /* Load Slave Address Register */
391 REG_FLD_MOD(base, HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1);
392
393 /* Load Offset Address Register */
394 REG_FLD_MOD(base, HDMI_CORE_DDC_OFFSET, offset, 7, 0);
395
396 /* Load Byte Count */
397 REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT1, 0x80, 7, 0);
398 REG_FLD_MOD(base, HDMI_CORE_DDC_COUNT2, 0x0, 1, 0);
399
400 /* Set DDC_CMD */
401 if (ext)
402 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x4, 3, 0);
403 else
404 REG_FLD_MOD(base, HDMI_CORE_DDC_CMD, 0x2, 3, 0);
405
406 /* HDMI_CORE_DDC_STATUS_BUS_LOW */
407 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 6, 6) == 1) {
408 pr_err("I2C Bus Low?\n");
409 return -EIO;
410 }
411 /* HDMI_CORE_DDC_STATUS_NO_ACK */
412 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 5, 5) == 1) {
413 pr_err("I2C No Ack\n");
414 return -EIO;
415 }
416
417 for (i = 0; i < 0x80; ++i) {
418 int t;
419
420 /* IN_PROG */
421 if (REG_GET(base, HDMI_CORE_DDC_STATUS, 4, 4) == 0) {
422 DSSERR("operation stopped when reading edid\n");
423 return -EIO;
424 }
425
426 t = 0;
427 /* FIFO_EMPTY */
428 while (REG_GET(base, HDMI_CORE_DDC_STATUS, 2, 2) == 1) {
429 if (t++ > 10000) {
430 DSSERR("timeout reading edid\n");
431 return -ETIMEDOUT;
432 }
433 udelay(1);
434 }
435
436 pedid[i] = REG_GET(base, HDMI_CORE_DDC_DATA, 7, 0);
437 }
438
439 checksum = 0;
440 for (i = 0; i < 0x80; ++i)
441 checksum += pedid[i];
442
443 if (checksum != 0) {
444 pr_err("E-EDID checksum failed!!\n");
445 return -EIO;
446 }
447
448 return 0;
449}
450
451int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data,
452 u8 *edid, int len)
453{
454 int r, l;
455
456 if (len < 128)
457 return -EINVAL;
458
459 r = hdmi_core_ddc_init(ip_data);
460 if (r)
461 return r;
462
463 r = hdmi_core_ddc_edid(ip_data, edid, 0);
464 if (r)
465 return r;
466
467 l = 128;
468
469 if (len >= 128 * 2 && edid[0x7e] > 0) {
470 r = hdmi_core_ddc_edid(ip_data, edid + 0x80, 1);
471 if (r)
472 return r;
473 l += 128;
474 }
475
476 return l;
477}
478
479bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data)
480{
481 return gpio_get_value(ip_data->hpd_gpio);
482}
483
484static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
485 struct hdmi_core_infoframe_avi *avi_cfg,
486 struct hdmi_core_packet_enable_repeat *repeat_cfg)
487{
488 pr_debug("Enter hdmi_core_init\n");
489
490 /* video core */
491 video_cfg->ip_bus_width = HDMI_INPUT_8BIT;
492 video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT;
493 video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE;
494 video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
495 video_cfg->hdmi_dvi = HDMI_DVI;
496 video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
497
498 /* info frame */
499 avi_cfg->db1_format = 0;
500 avi_cfg->db1_active_info = 0;
501 avi_cfg->db1_bar_info_dv = 0;
502 avi_cfg->db1_scan_info = 0;
503 avi_cfg->db2_colorimetry = 0;
504 avi_cfg->db2_aspect_ratio = 0;
505 avi_cfg->db2_active_fmt_ar = 0;
506 avi_cfg->db3_itc = 0;
507 avi_cfg->db3_ec = 0;
508 avi_cfg->db3_q_range = 0;
509 avi_cfg->db3_nup_scaling = 0;
510 avi_cfg->db4_videocode = 0;
511 avi_cfg->db5_pixel_repeat = 0;
512 avi_cfg->db6_7_line_eoftop = 0 ;
513 avi_cfg->db8_9_line_sofbottom = 0;
514 avi_cfg->db10_11_pixel_eofleft = 0;
515 avi_cfg->db12_13_pixel_sofright = 0;
516
517 /* packet enable and repeat */
518 repeat_cfg->audio_pkt = 0;
519 repeat_cfg->audio_pkt_repeat = 0;
520 repeat_cfg->avi_infoframe = 0;
521 repeat_cfg->avi_infoframe_repeat = 0;
522 repeat_cfg->gen_cntrl_pkt = 0;
523 repeat_cfg->gen_cntrl_pkt_repeat = 0;
524 repeat_cfg->generic_pkt = 0;
525 repeat_cfg->generic_pkt_repeat = 0;
526}
527
528static void hdmi_core_powerdown_disable(struct hdmi_ip_data *ip_data)
529{
530 pr_debug("Enter hdmi_core_powerdown_disable\n");
531 REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_CTRL1, 0x0, 0, 0);
532}
533
534static void hdmi_core_swreset_release(struct hdmi_ip_data *ip_data)
535{
536 pr_debug("Enter hdmi_core_swreset_release\n");
537 REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x0, 0, 0);
538}
539
540static void hdmi_core_swreset_assert(struct hdmi_ip_data *ip_data)
541{
542 pr_debug("Enter hdmi_core_swreset_assert\n");
543 REG_FLD_MOD(hdmi_core_sys_base(ip_data), HDMI_CORE_SYS_SRST, 0x1, 0, 0);
544}
545
546/* HDMI_CORE_VIDEO_CONFIG */
547static void hdmi_core_video_config(struct hdmi_ip_data *ip_data,
548 struct hdmi_core_video_config *cfg)
549{
550 u32 r = 0;
551 void __iomem *core_sys_base = hdmi_core_sys_base(ip_data);
552
553 /* sys_ctrl1 default configuration not tunable */
554 r = hdmi_read_reg(core_sys_base, HDMI_CORE_CTRL1);
555 r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5);
556 r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4);
557 r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2);
558 r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1);
559 hdmi_write_reg(core_sys_base, HDMI_CORE_CTRL1, r);
560
561 REG_FLD_MOD(core_sys_base,
562 HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6);
563
564 /* Vid_Mode */
565 r = hdmi_read_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE);
566
567 /* dither truncation configuration */
568 if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) {
569 r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6);
570 r = FLD_MOD(r, 1, 5, 5);
571 } else {
572 r = FLD_MOD(r, cfg->op_dither_truc, 7, 6);
573 r = FLD_MOD(r, 0, 5, 5);
574 }
575 hdmi_write_reg(core_sys_base, HDMI_CORE_SYS_VID_MODE, r);
576
577 /* HDMI_Ctrl */
578 r = hdmi_read_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL);
579 r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6);
580 r = FLD_MOD(r, cfg->pkt_mode, 5, 3);
581 r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0);
582 hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_HDMI_CTRL, r);
583
584 /* TMDS_CTRL */
585 REG_FLD_MOD(core_sys_base,
586 HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
587}
588
589static void hdmi_core_aux_infoframe_avi_config(struct hdmi_ip_data *ip_data)
590{
591 u32 val;
592 char sum = 0, checksum = 0;
593 void __iomem *av_base = hdmi_av_base(ip_data);
594 struct hdmi_core_infoframe_avi info_avi = ip_data->avi_cfg;
595
596 sum += 0x82 + 0x002 + 0x00D;
597 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
598 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
599 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
600
601 val = (info_avi.db1_format << 5) |
602 (info_avi.db1_active_info << 4) |
603 (info_avi.db1_bar_info_dv << 2) |
604 (info_avi.db1_scan_info);
605 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
606 sum += val;
607
608 val = (info_avi.db2_colorimetry << 6) |
609 (info_avi.db2_aspect_ratio << 4) |
610 (info_avi.db2_active_fmt_ar);
611 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
612 sum += val;
613
614 val = (info_avi.db3_itc << 7) |
615 (info_avi.db3_ec << 4) |
616 (info_avi.db3_q_range << 2) |
617 (info_avi.db3_nup_scaling);
618 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
619 sum += val;
620
621 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
622 info_avi.db4_videocode);
623 sum += info_avi.db4_videocode;
624
625 val = info_avi.db5_pixel_repeat;
626 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
627 sum += val;
628
629 val = info_avi.db6_7_line_eoftop & 0x00FF;
630 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
631 sum += val;
632
633 val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
634 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
635 sum += val;
636
637 val = info_avi.db8_9_line_sofbottom & 0x00FF;
638 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
639 sum += val;
640
641 val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
642 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
643 sum += val;
644
645 val = info_avi.db10_11_pixel_eofleft & 0x00FF;
646 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
647 sum += val;
648
649 val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
650 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
651 sum += val;
652
653 val = info_avi.db12_13_pixel_sofright & 0x00FF;
654 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
655 sum += val;
656
657 val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
658 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
659 sum += val;
660
661 checksum = 0x100 - sum;
662 hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
663}
664
665static void hdmi_core_av_packet_config(struct hdmi_ip_data *ip_data,
666 struct hdmi_core_packet_enable_repeat repeat_cfg)
667{
668 /* enable/repeat the infoframe */
669 hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL1,
670 (repeat_cfg.audio_pkt << 5) |
671 (repeat_cfg.audio_pkt_repeat << 4) |
672 (repeat_cfg.avi_infoframe << 1) |
673 (repeat_cfg.avi_infoframe_repeat));
674
675 /* enable/repeat the packet */
676 hdmi_write_reg(hdmi_av_base(ip_data), HDMI_CORE_AV_PB_CTRL2,
677 (repeat_cfg.gen_cntrl_pkt << 3) |
678 (repeat_cfg.gen_cntrl_pkt_repeat << 2) |
679 (repeat_cfg.generic_pkt << 1) |
680 (repeat_cfg.generic_pkt_repeat));
681}
682
683static void hdmi_wp_init(struct omap_video_timings *timings,
684 struct hdmi_video_format *video_fmt)
685{
686 pr_debug("Enter hdmi_wp_init\n");
687
688 timings->hbp = 0;
689 timings->hfp = 0;
690 timings->hsw = 0;
691 timings->vbp = 0;
692 timings->vfp = 0;
693 timings->vsw = 0;
694
695 video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
696 video_fmt->y_res = 0;
697 video_fmt->x_res = 0;
698
699}
700
701int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data)
702{
703 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31);
704 return 0;
705}
706
707void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data)
708{
709 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31);
710}
711
712static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
713 struct omap_video_timings *timings, struct hdmi_config *param)
714{
715 pr_debug("Enter hdmi_wp_video_init_format\n");
716
717 video_fmt->y_res = param->timings.y_res;
718 video_fmt->x_res = param->timings.x_res;
719
720 timings->hbp = param->timings.hbp;
721 timings->hfp = param->timings.hfp;
722 timings->hsw = param->timings.hsw;
723 timings->vbp = param->timings.vbp;
724 timings->vfp = param->timings.vfp;
725 timings->vsw = param->timings.vsw;
726}
727
728static void hdmi_wp_video_config_format(struct hdmi_ip_data *ip_data,
729 struct hdmi_video_format *video_fmt)
730{
731 u32 l = 0;
732
733 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG,
734 video_fmt->packing_mode, 10, 8);
735
736 l |= FLD_VAL(video_fmt->y_res, 31, 16);
737 l |= FLD_VAL(video_fmt->x_res, 15, 0);
738 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_SIZE, l);
739}
740
741static void hdmi_wp_video_config_interface(struct hdmi_ip_data *ip_data)
742{
743 u32 r;
744 bool vsync_pol, hsync_pol;
745 pr_debug("Enter hdmi_wp_video_config_interface\n");
746
747 vsync_pol = ip_data->cfg.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
748 hsync_pol = ip_data->cfg.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
749
750 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG);
751 r = FLD_MOD(r, vsync_pol, 7, 7);
752 r = FLD_MOD(r, hsync_pol, 6, 6);
753 r = FLD_MOD(r, ip_data->cfg.timings.interlace, 3, 3);
754 r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
755 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, r);
756}
757
758static void hdmi_wp_video_config_timing(struct hdmi_ip_data *ip_data,
759 struct omap_video_timings *timings)
760{
761 u32 timing_h = 0;
762 u32 timing_v = 0;
763
764 pr_debug("Enter hdmi_wp_video_config_timing\n");
765
766 timing_h |= FLD_VAL(timings->hbp, 31, 20);
767 timing_h |= FLD_VAL(timings->hfp, 19, 8);
768 timing_h |= FLD_VAL(timings->hsw, 7, 0);
769 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_H, timing_h);
770
771 timing_v |= FLD_VAL(timings->vbp, 31, 20);
772 timing_v |= FLD_VAL(timings->vfp, 19, 8);
773 timing_v |= FLD_VAL(timings->vsw, 7, 0);
774 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_TIMING_V, timing_v);
775}
776
777void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data)
778{
779 /* HDMI */
780 struct omap_video_timings video_timing;
781 struct hdmi_video_format video_format;
782 /* HDMI core */
783 struct hdmi_core_infoframe_avi avi_cfg = ip_data->avi_cfg;
784 struct hdmi_core_video_config v_core_cfg;
785 struct hdmi_core_packet_enable_repeat repeat_cfg;
786 struct hdmi_config *cfg = &ip_data->cfg;
787
788 hdmi_wp_init(&video_timing, &video_format);
789
790 hdmi_core_init(&v_core_cfg,
791 &avi_cfg,
792 &repeat_cfg);
793
794 hdmi_wp_video_init_format(&video_format, &video_timing, cfg);
795
796 hdmi_wp_video_config_timing(ip_data, &video_timing);
797
798 /* video config */
799 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
800
801 hdmi_wp_video_config_format(ip_data, &video_format);
802
803 hdmi_wp_video_config_interface(ip_data);
804
805 /*
806 * configure core video part
807 * set software reset in the core
808 */
809 hdmi_core_swreset_assert(ip_data);
810
811 /* power down off */
812 hdmi_core_powerdown_disable(ip_data);
813
814 v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
815 v_core_cfg.hdmi_dvi = cfg->cm.mode;
816
817 hdmi_core_video_config(ip_data, &v_core_cfg);
818
819 /* release software reset in the core */
820 hdmi_core_swreset_release(ip_data);
821
822 /*
823 * configure packet
824 * info frame video see doc CEA861-D page 65
825 */
826 avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
827 avi_cfg.db1_active_info =
828 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
829 avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
830 avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
831 avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
832 avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
833 avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
834 avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
835 avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
836 avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
837 avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
838 avi_cfg.db4_videocode = cfg->cm.code;
839 avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
840 avi_cfg.db6_7_line_eoftop = 0;
841 avi_cfg.db8_9_line_sofbottom = 0;
842 avi_cfg.db10_11_pixel_eofleft = 0;
843 avi_cfg.db12_13_pixel_sofright = 0;
844
845 hdmi_core_aux_infoframe_avi_config(ip_data);
846
847 /* enable/repeat the infoframe */
848 repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
849 repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON;
850 /* wakeup */
851 repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
852 repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
853 hdmi_core_av_packet_config(ip_data, repeat_cfg);
854}
855
856void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
857{
858#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r,\
859 hdmi_read_reg(hdmi_wp_base(ip_data), r))
860
861 DUMPREG(HDMI_WP_REVISION);
862 DUMPREG(HDMI_WP_SYSCONFIG);
863 DUMPREG(HDMI_WP_IRQSTATUS_RAW);
864 DUMPREG(HDMI_WP_IRQSTATUS);
865 DUMPREG(HDMI_WP_PWR_CTRL);
866 DUMPREG(HDMI_WP_IRQENABLE_SET);
867 DUMPREG(HDMI_WP_VIDEO_CFG);
868 DUMPREG(HDMI_WP_VIDEO_SIZE);
869 DUMPREG(HDMI_WP_VIDEO_TIMING_H);
870 DUMPREG(HDMI_WP_VIDEO_TIMING_V);
871 DUMPREG(HDMI_WP_WP_CLK);
872 DUMPREG(HDMI_WP_AUDIO_CFG);
873 DUMPREG(HDMI_WP_AUDIO_CFG2);
874 DUMPREG(HDMI_WP_AUDIO_CTRL);
875 DUMPREG(HDMI_WP_AUDIO_DATA);
876}
877
878void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
879{
880#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
881 hdmi_read_reg(hdmi_pll_base(ip_data), r))
882
883 DUMPPLL(PLLCTRL_PLL_CONTROL);
884 DUMPPLL(PLLCTRL_PLL_STATUS);
885 DUMPPLL(PLLCTRL_PLL_GO);
886 DUMPPLL(PLLCTRL_CFG1);
887 DUMPPLL(PLLCTRL_CFG2);
888 DUMPPLL(PLLCTRL_CFG3);
889 DUMPPLL(PLLCTRL_CFG4);
890}
891
892void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
893{
894 int i;
895
896#define CORE_REG(i, name) name(i)
897#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
898 hdmi_read_reg(hdmi_core_sys_base(ip_data), r))
899#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
900 hdmi_read_reg(hdmi_av_base(ip_data), r))
901#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
902 (i < 10) ? 32 - (int)strlen(#r) : 31 - (int)strlen(#r), " ", \
903 hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
904
905 DUMPCORE(HDMI_CORE_SYS_VND_IDL);
906 DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
907 DUMPCORE(HDMI_CORE_SYS_DEV_IDH);
908 DUMPCORE(HDMI_CORE_SYS_DEV_REV);
909 DUMPCORE(HDMI_CORE_SYS_SRST);
910 DUMPCORE(HDMI_CORE_CTRL1);
911 DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
912 DUMPCORE(HDMI_CORE_SYS_DE_DLY);
913 DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
914 DUMPCORE(HDMI_CORE_SYS_DE_TOP);
915 DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
916 DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
917 DUMPCORE(HDMI_CORE_SYS_DE_LINL);
918 DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
919 DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
920 DUMPCORE(HDMI_CORE_SYS_VID_MODE);
921 DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
922 DUMPCORE(HDMI_CORE_SYS_INTR1);
923 DUMPCORE(HDMI_CORE_SYS_INTR2);
924 DUMPCORE(HDMI_CORE_SYS_INTR3);
925 DUMPCORE(HDMI_CORE_SYS_INTR4);
926 DUMPCORE(HDMI_CORE_SYS_UMASK1);
927 DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
928
929 DUMPCORE(HDMI_CORE_DDC_ADDR);
930 DUMPCORE(HDMI_CORE_DDC_SEGM);
931 DUMPCORE(HDMI_CORE_DDC_OFFSET);
932 DUMPCORE(HDMI_CORE_DDC_COUNT1);
933 DUMPCORE(HDMI_CORE_DDC_COUNT2);
934 DUMPCORE(HDMI_CORE_DDC_STATUS);
935 DUMPCORE(HDMI_CORE_DDC_CMD);
936 DUMPCORE(HDMI_CORE_DDC_DATA);
937
938 DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL);
939 DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL);
940 DUMPCOREAV(HDMI_CORE_AV_N_SVAL1);
941 DUMPCOREAV(HDMI_CORE_AV_N_SVAL2);
942 DUMPCOREAV(HDMI_CORE_AV_N_SVAL3);
943 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1);
944 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2);
945 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3);
946 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1);
947 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2);
948 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3);
949 DUMPCOREAV(HDMI_CORE_AV_AUD_MODE);
950 DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL);
951 DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS);
952 DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S);
953 DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH);
954 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP);
955 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL);
956 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0);
957 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1);
958 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2);
959 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4);
960 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5);
961 DUMPCOREAV(HDMI_CORE_AV_ASRC);
962 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN);
963 DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL);
964 DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT);
965 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
966 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
967 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
968 DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL);
969 DUMPCOREAV(HDMI_CORE_AV_DPD);
970 DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1);
971 DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2);
972 DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE);
973 DUMPCOREAV(HDMI_CORE_AV_AVI_VERS);
974 DUMPCOREAV(HDMI_CORE_AV_AVI_LEN);
975 DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM);
976
977 for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
978 DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE);
979
980 DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE);
981 DUMPCOREAV(HDMI_CORE_AV_SPD_VERS);
982 DUMPCOREAV(HDMI_CORE_AV_SPD_LEN);
983 DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM);
984
985 for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
986 DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE);
987
988 DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE);
989 DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS);
990 DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN);
991 DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM);
992
993 for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
994 DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE);
995
996 DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE);
997 DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS);
998 DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN);
999 DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM);
1000
1001 for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
1002 DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE);
1003
1004 for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
1005 DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE);
1006
1007 DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1);
1008
1009 for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
1010 DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE);
1011
1012 DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
1013}
1014
1015void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
1016{
1017#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
1018 hdmi_read_reg(hdmi_phy_base(ip_data), r))
1019
1020 DUMPPHY(HDMI_TXPHY_TX_CTRL);
1021 DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
1022 DUMPPHY(HDMI_TXPHY_POWER_CTRL);
1023 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
1024}
1025
1026#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1027static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1028 struct hdmi_audio_format *aud_fmt)
1029{
1030 u32 r;
1031
1032 DSSDBG("Enter hdmi_wp_audio_config_format\n");
1033
1034 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG);
1035 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
1036 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
1037 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
1038 r = FLD_MOD(r, aud_fmt->type, 4, 4);
1039 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
1040 r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
1041 r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
1042 r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
1043 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
1044}
1045
1046static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
1047 struct hdmi_audio_dma *aud_dma)
1048{
1049 u32 r;
1050
1051 DSSDBG("Enter hdmi_wp_audio_config_dma\n");
1052
1053 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2);
1054 r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
1055 r = FLD_MOD(r, aud_dma->block_size, 7, 0);
1056 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG2, r);
1057
1058 r = hdmi_read_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL);
1059 r = FLD_MOD(r, aud_dma->mode, 9, 9);
1060 r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
1061 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
1062}
1063
1064static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data,
1065 struct hdmi_core_audio_config *cfg)
1066{
1067 u32 r;
1068 void __iomem *av_base = hdmi_av_base(ip_data);
1069
1070 /*
1071 * Parameters for generation of Audio Clock Recovery packets
1072 */
1073 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
1074 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
1075 REG_FLD_MOD(av_base, HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
1076
1077 if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
1078 REG_FLD_MOD(av_base, HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
1079 REG_FLD_MOD(av_base,
1080 HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
1081 REG_FLD_MOD(av_base,
1082 HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
1083 } else {
1084 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
1085 cfg->aud_par_busclk, 7, 0);
1086 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
1087 (cfg->aud_par_busclk >> 8), 7, 0);
1088 REG_FLD_MOD(av_base, HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
1089 (cfg->aud_par_busclk >> 16), 7, 0);
1090 }
1091
1092 /* Set ACR clock divisor */
1093 REG_FLD_MOD(av_base,
1094 HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
1095
1096 r = hdmi_read_reg(av_base, HDMI_CORE_AV_ACR_CTRL);
1097 /*
1098 * Use TMDS clock for ACR packets. For devices that use
1099 * the MCLK, this is the first part of the MCLK initialization.
1100 */
1101 r = FLD_MOD(r, 0, 2, 2);
1102
1103 r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
1104 r = FLD_MOD(r, cfg->cts_mode, 0, 0);
1105 hdmi_write_reg(av_base, HDMI_CORE_AV_ACR_CTRL, r);
1106
1107 /* For devices using MCLK, this completes its initialization. */
1108 if (cfg->use_mclk)
1109 REG_FLD_MOD(av_base, HDMI_CORE_AV_ACR_CTRL, 1, 2, 2);
1110
1111 /* Override of SPDIF sample frequency with value in I2S_CHST4 */
1112 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
1113 cfg->fs_override, 1, 1);
1114
1115 /*
1116 * Set IEC-60958-3 channel status word. It is passed to the IP
1117 * just as it is received. The user of the driver is responsible
1118 * for its contents.
1119 */
1120 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
1121 cfg->iec60958_cfg->status[0]);
1122 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
1123 cfg->iec60958_cfg->status[1]);
1124 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
1125 cfg->iec60958_cfg->status[2]);
1126 /* yes, this is correct: status[3] goes to CHST4 register */
1127 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
1128 cfg->iec60958_cfg->status[3]);
1129 /* yes, this is correct: status[4] goes to CHST5 register */
1130 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
1131 cfg->iec60958_cfg->status[4]);
1132
1133 /* set I2S parameters */
1134 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
1135 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1136 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1137 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1138 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1139 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1140 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
1141
1142 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
1143 cfg->i2s_cfg.in_length_bits, 3, 0);
1144
1145 /* Audio channels and mode parameters */
1146 REG_FLD_MOD(av_base, HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
1147 r = hdmi_read_reg(av_base, HDMI_CORE_AV_AUD_MODE);
1148 r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
1149 r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
1150 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1151 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1152 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
1153
1154 /* Audio channel mappings */
1155 /* TODO: Make channel mapping dynamic. For now, map channels
1156 * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
1157 * HDMI speaker order is different. See CEA-861 Section 6.6.2.
1158 */
1159 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
1160 REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
1161}
1162
1163static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data,
1164 struct snd_cea_861_aud_if *info_aud)
1165{
1166 u8 sum = 0, checksum = 0;
1167 void __iomem *av_base = hdmi_av_base(ip_data);
1168
1169 /*
1170 * Set audio info frame type, version and length as
1171 * described in HDMI 1.4a Section 8.2.2 specification.
1172 * Checksum calculation is defined in Section 5.3.5.
1173 */
1174 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_TYPE, 0x84);
1175 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_VERS, 0x01);
1176 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1177 sum += 0x84 + 0x001 + 0x00a;
1178
1179 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
1180 info_aud->db1_ct_cc);
1181 sum += info_aud->db1_ct_cc;
1182
1183 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
1184 info_aud->db2_sf_ss);
1185 sum += info_aud->db2_sf_ss;
1186
1187 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
1188 sum += info_aud->db3;
1189
1190 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
1191 sum += info_aud->db4_ca;
1192
1193 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
1194 info_aud->db5_dminh_lsv);
1195 sum += info_aud->db5_dminh_lsv;
1196
1197 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1198 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
1199 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
1200 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
1201 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
1202
1203 checksum = 0x100 - sum;
1204 hdmi_write_reg(av_base,
1205 HDMI_CORE_AV_AUDIO_CHSUM, checksum);
1206
1207 /*
1208 * TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
1209 * is available.
1210 */
1211}
1212
1213int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
1214 struct omap_dss_audio *audio)
1215{
1216 struct hdmi_audio_format audio_format;
1217 struct hdmi_audio_dma audio_dma;
1218 struct hdmi_core_audio_config core;
1219 int err, n, cts, channel_count;
1220 unsigned int fs_nr;
1221 bool word_length_16b = false;
1222
1223 if (!audio || !audio->iec || !audio->cea || !ip_data)
1224 return -EINVAL;
1225
1226 core.iec60958_cfg = audio->iec;
1227 /*
1228 * In the IEC-60958 status word, check if the audio sample word length
1229 * is 16-bit as several optimizations can be performed in such case.
1230 */
1231 if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
1232 if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
1233 word_length_16b = true;
1234
1235 /* I2S configuration. See Phillips' specification */
1236 if (word_length_16b)
1237 core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1238 else
1239 core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1240 /*
1241 * The I2S input word length is twice the lenght given in the IEC-60958
1242 * status word. If the word size is greater than
1243 * 20 bits, increment by one.
1244 */
1245 core.i2s_cfg.in_length_bits = audio->iec->status[4]
1246 & IEC958_AES4_CON_WORDLEN;
1247 if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
1248 core.i2s_cfg.in_length_bits++;
1249 core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
1250 core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
1251 core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
1252 core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
1253
1254 /* convert sample frequency to a number */
1255 switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
1256 case IEC958_AES3_CON_FS_32000:
1257 fs_nr = 32000;
1258 break;
1259 case IEC958_AES3_CON_FS_44100:
1260 fs_nr = 44100;
1261 break;
1262 case IEC958_AES3_CON_FS_48000:
1263 fs_nr = 48000;
1264 break;
1265 case IEC958_AES3_CON_FS_88200:
1266 fs_nr = 88200;
1267 break;
1268 case IEC958_AES3_CON_FS_96000:
1269 fs_nr = 96000;
1270 break;
1271 case IEC958_AES3_CON_FS_176400:
1272 fs_nr = 176400;
1273 break;
1274 case IEC958_AES3_CON_FS_192000:
1275 fs_nr = 192000;
1276 break;
1277 default:
1278 return -EINVAL;
1279 }
1280
1281 err = hdmi_compute_acr(fs_nr, &n, &cts);
1282
1283 /* Audio clock regeneration settings */
1284 core.n = n;
1285 core.cts = cts;
1286 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
1287 core.aud_par_busclk = 0;
1288 core.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
1289 core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
1290 } else {
1291 core.aud_par_busclk = (((128 * 31) - 1) << 8);
1292 core.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
1293 core.use_mclk = true;
1294 }
1295
1296 if (core.use_mclk)
1297 core.mclk_mode = HDMI_AUDIO_MCLK_128FS;
1298
1299 /* Audio channels settings */
1300 channel_count = (audio->cea->db1_ct_cc &
1301 CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
1302
1303 switch (channel_count) {
1304 case 2:
1305 audio_format.active_chnnls_msk = 0x03;
1306 break;
1307 case 3:
1308 audio_format.active_chnnls_msk = 0x07;
1309 break;
1310 case 4:
1311 audio_format.active_chnnls_msk = 0x0f;
1312 break;
1313 case 5:
1314 audio_format.active_chnnls_msk = 0x1f;
1315 break;
1316 case 6:
1317 audio_format.active_chnnls_msk = 0x3f;
1318 break;
1319 case 7:
1320 audio_format.active_chnnls_msk = 0x7f;
1321 break;
1322 case 8:
1323 audio_format.active_chnnls_msk = 0xff;
1324 break;
1325 default:
1326 return -EINVAL;
1327 }
1328
1329 /*
1330 * the HDMI IP needs to enable four stereo channels when transmitting
1331 * more than 2 audio channels
1332 */
1333 if (channel_count == 2) {
1334 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
1335 core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
1336 core.layout = HDMI_AUDIO_LAYOUT_2CH;
1337 } else {
1338 audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
1339 core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
1340 HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
1341 HDMI_AUDIO_I2S_SD3_EN;
1342 core.layout = HDMI_AUDIO_LAYOUT_8CH;
1343 }
1344
1345 core.en_spdif = false;
1346 /* use sample frequency from channel status word */
1347 core.fs_override = true;
1348 /* enable ACR packets */
1349 core.en_acr_pkt = true;
1350 /* disable direct streaming digital audio */
1351 core.en_dsd_audio = false;
1352 /* use parallel audio interface */
1353 core.en_parallel_aud_input = true;
1354
1355 /* DMA settings */
1356 if (word_length_16b)
1357 audio_dma.transfer_size = 0x10;
1358 else
1359 audio_dma.transfer_size = 0x20;
1360 audio_dma.block_size = 0xC0;
1361 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
1362 audio_dma.fifo_threshold = 0x20; /* in number of samples */
1363
1364 /* audio FIFO format settings */
1365 if (word_length_16b) {
1366 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
1367 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
1368 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1369 } else {
1370 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
1371 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
1372 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1373 }
1374 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
1375 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
1376 /* disable start/stop signals of IEC 60958 blocks */
1377 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
1378
1379 /* configure DMA and audio FIFO format*/
1380 ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma);
1381 ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format);
1382
1383 /* configure the core*/
1384 ti_hdmi_4xxx_core_audio_config(ip_data, &core);
1385
1386 /* configure CEA 861 audio infoframe*/
1387 ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea);
1388
1389 return 0;
1390}
1391
1392int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data)
1393{
1394 REG_FLD_MOD(hdmi_wp_base(ip_data),
1395 HDMI_WP_AUDIO_CTRL, true, 31, 31);
1396 return 0;
1397}
1398
1399void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data)
1400{
1401 REG_FLD_MOD(hdmi_wp_base(ip_data),
1402 HDMI_WP_AUDIO_CTRL, false, 31, 31);
1403}
1404
1405int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data)
1406{
1407 REG_FLD_MOD(hdmi_av_base(ip_data),
1408 HDMI_CORE_AV_AUD_MODE, true, 0, 0);
1409 REG_FLD_MOD(hdmi_wp_base(ip_data),
1410 HDMI_WP_AUDIO_CTRL, true, 30, 30);
1411 return 0;
1412}
1413
1414void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
1415{
1416 REG_FLD_MOD(hdmi_av_base(ip_data),
1417 HDMI_CORE_AV_AUD_MODE, false, 0, 0);
1418 REG_FLD_MOD(hdmi_wp_base(ip_data),
1419 HDMI_WP_AUDIO_CTRL, false, 30, 30);
1420}
1421
1422int ti_hdmi_4xxx_audio_get_dma_port(u32 *offset, u32 *size)
1423{
1424 if (!offset || !size)
1425 return -EINVAL;
1426 *offset = HDMI_WP_AUDIO_DATA;
1427 *size = 4;
1428 return 0;
1429}
1430#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
deleted file mode 100644
index 8366ae19e82..00000000000
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ /dev/null
@@ -1,436 +0,0 @@
1/*
2 * ti_hdmi_4xxx_ip.h
3 *
4 * HDMI header definition for DM81xx, DM38xx, TI OMAP4 etc processors.
5 *
6 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#ifndef _HDMI_TI_4xxx_H_
22#define _HDMI_TI_4xxx_H_
23
24#include <linux/string.h>
25#include <video/omapdss.h>
26#include "ti_hdmi.h"
27
28/* HDMI Wrapper */
29
30#define HDMI_WP_REVISION 0x0
31#define HDMI_WP_SYSCONFIG 0x10
32#define HDMI_WP_IRQSTATUS_RAW 0x24
33#define HDMI_WP_IRQSTATUS 0x28
34#define HDMI_WP_PWR_CTRL 0x40
35#define HDMI_WP_IRQENABLE_SET 0x2C
36#define HDMI_WP_VIDEO_CFG 0x50
37#define HDMI_WP_VIDEO_SIZE 0x60
38#define HDMI_WP_VIDEO_TIMING_H 0x68
39#define HDMI_WP_VIDEO_TIMING_V 0x6C
40#define HDMI_WP_WP_CLK 0x70
41#define HDMI_WP_AUDIO_CFG 0x80
42#define HDMI_WP_AUDIO_CFG2 0x84
43#define HDMI_WP_AUDIO_CTRL 0x88
44#define HDMI_WP_AUDIO_DATA 0x8C
45
46/* HDMI IP Core System */
47
48#define HDMI_CORE_SYS_VND_IDL 0x0
49#define HDMI_CORE_SYS_DEV_IDL 0x8
50#define HDMI_CORE_SYS_DEV_IDH 0xC
51#define HDMI_CORE_SYS_DEV_REV 0x10
52#define HDMI_CORE_SYS_SRST 0x14
53#define HDMI_CORE_CTRL1 0x20
54#define HDMI_CORE_SYS_SYS_STAT 0x24
55#define HDMI_CORE_SYS_DE_DLY 0xC8
56#define HDMI_CORE_SYS_DE_CTRL 0xCC
57#define HDMI_CORE_SYS_DE_TOP 0xD0
58#define HDMI_CORE_SYS_DE_CNTL 0xD8
59#define HDMI_CORE_SYS_DE_CNTH 0xDC
60#define HDMI_CORE_SYS_DE_LINL 0xE0
61#define HDMI_CORE_SYS_DE_LINH_1 0xE4
62#define HDMI_CORE_SYS_VID_ACEN 0x124
63#define HDMI_CORE_SYS_VID_MODE 0x128
64#define HDMI_CORE_SYS_INTR_STATE 0x1C0
65#define HDMI_CORE_SYS_INTR1 0x1C4
66#define HDMI_CORE_SYS_INTR2 0x1C8
67#define HDMI_CORE_SYS_INTR3 0x1CC
68#define HDMI_CORE_SYS_INTR4 0x1D0
69#define HDMI_CORE_SYS_UMASK1 0x1D4
70#define HDMI_CORE_SYS_TMDS_CTRL 0x208
71
72#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
73#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
74#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
75#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
76
77/* HDMI DDC E-DID */
78#define HDMI_CORE_DDC_ADDR 0x3B4
79#define HDMI_CORE_DDC_SEGM 0x3B8
80#define HDMI_CORE_DDC_OFFSET 0x3BC
81#define HDMI_CORE_DDC_COUNT1 0x3C0
82#define HDMI_CORE_DDC_COUNT2 0x3C4
83#define HDMI_CORE_DDC_STATUS 0x3C8
84#define HDMI_CORE_DDC_CMD 0x3CC
85#define HDMI_CORE_DDC_DATA 0x3D0
86
87/* HDMI IP Core Audio Video */
88
89#define HDMI_CORE_AV_ACR_CTRL 0x4
90#define HDMI_CORE_AV_FREQ_SVAL 0x8
91#define HDMI_CORE_AV_N_SVAL1 0xC
92#define HDMI_CORE_AV_N_SVAL2 0x10
93#define HDMI_CORE_AV_N_SVAL3 0x14
94#define HDMI_CORE_AV_CTS_SVAL1 0x18
95#define HDMI_CORE_AV_CTS_SVAL2 0x1C
96#define HDMI_CORE_AV_CTS_SVAL3 0x20
97#define HDMI_CORE_AV_CTS_HVAL1 0x24
98#define HDMI_CORE_AV_CTS_HVAL2 0x28
99#define HDMI_CORE_AV_CTS_HVAL3 0x2C
100#define HDMI_CORE_AV_AUD_MODE 0x50
101#define HDMI_CORE_AV_SPDIF_CTRL 0x54
102#define HDMI_CORE_AV_HW_SPDIF_FS 0x60
103#define HDMI_CORE_AV_SWAP_I2S 0x64
104#define HDMI_CORE_AV_SPDIF_ERTH 0x6C
105#define HDMI_CORE_AV_I2S_IN_MAP 0x70
106#define HDMI_CORE_AV_I2S_IN_CTRL 0x74
107#define HDMI_CORE_AV_I2S_CHST0 0x78
108#define HDMI_CORE_AV_I2S_CHST1 0x7C
109#define HDMI_CORE_AV_I2S_CHST2 0x80
110#define HDMI_CORE_AV_I2S_CHST4 0x84
111#define HDMI_CORE_AV_I2S_CHST5 0x88
112#define HDMI_CORE_AV_ASRC 0x8C
113#define HDMI_CORE_AV_I2S_IN_LEN 0x90
114#define HDMI_CORE_AV_HDMI_CTRL 0xBC
115#define HDMI_CORE_AV_AUDO_TXSTAT 0xC0
116#define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 0xCC
117#define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 0xD0
118#define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 0xD4
119#define HDMI_CORE_AV_TEST_TXCTRL 0xF0
120#define HDMI_CORE_AV_DPD 0xF4
121#define HDMI_CORE_AV_PB_CTRL1 0xF8
122#define HDMI_CORE_AV_PB_CTRL2 0xFC
123#define HDMI_CORE_AV_AVI_TYPE 0x100
124#define HDMI_CORE_AV_AVI_VERS 0x104
125#define HDMI_CORE_AV_AVI_LEN 0x108
126#define HDMI_CORE_AV_AVI_CHSUM 0x10C
127#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
128#define HDMI_CORE_AV_SPD_TYPE 0x180
129#define HDMI_CORE_AV_SPD_VERS 0x184
130#define HDMI_CORE_AV_SPD_LEN 0x188
131#define HDMI_CORE_AV_SPD_CHSUM 0x18C
132#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
133#define HDMI_CORE_AV_AUDIO_TYPE 0x200
134#define HDMI_CORE_AV_AUDIO_VERS 0x204
135#define HDMI_CORE_AV_AUDIO_LEN 0x208
136#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
137#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
138#define HDMI_CORE_AV_MPEG_TYPE 0x280
139#define HDMI_CORE_AV_MPEG_VERS 0x284
140#define HDMI_CORE_AV_MPEG_LEN 0x288
141#define HDMI_CORE_AV_MPEG_CHSUM 0x28C
142#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
143#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
144#define HDMI_CORE_AV_CP_BYTE1 0x37C
145#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
146#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC
147
148#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
149#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
150#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
151#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
152
153#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
154#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
155#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
156#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
157#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
158#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
159
160/* PLL */
161
162#define PLLCTRL_PLL_CONTROL 0x0
163#define PLLCTRL_PLL_STATUS 0x4
164#define PLLCTRL_PLL_GO 0x8
165#define PLLCTRL_CFG1 0xC
166#define PLLCTRL_CFG2 0x10
167#define PLLCTRL_CFG3 0x14
168#define PLLCTRL_CFG4 0x20
169
170/* HDMI PHY */
171
172#define HDMI_TXPHY_TX_CTRL 0x0
173#define HDMI_TXPHY_DIGITAL_CTRL 0x4
174#define HDMI_TXPHY_POWER_CTRL 0x8
175#define HDMI_TXPHY_PAD_CFG_CTRL 0xC
176
177#define REG_FLD_MOD(base, idx, val, start, end) \
178 hdmi_write_reg(base, idx, FLD_MOD(hdmi_read_reg(base, idx),\
179 val, start, end))
180#define REG_GET(base, idx, start, end) \
181 FLD_GET(hdmi_read_reg(base, idx), start, end)
182
183enum hdmi_phy_pwr {
184 HDMI_PHYPWRCMD_OFF = 0,
185 HDMI_PHYPWRCMD_LDOON = 1,
186 HDMI_PHYPWRCMD_TXON = 2
187};
188
189enum hdmi_core_inputbus_width {
190 HDMI_INPUT_8BIT = 0,
191 HDMI_INPUT_10BIT = 1,
192 HDMI_INPUT_12BIT = 2
193};
194
195enum hdmi_core_dither_trunc {
196 HDMI_OUTPUTTRUNCATION_8BIT = 0,
197 HDMI_OUTPUTTRUNCATION_10BIT = 1,
198 HDMI_OUTPUTTRUNCATION_12BIT = 2,
199 HDMI_OUTPUTDITHER_8BIT = 3,
200 HDMI_OUTPUTDITHER_10BIT = 4,
201 HDMI_OUTPUTDITHER_12BIT = 5
202};
203
204enum hdmi_core_deepcolor_ed {
205 HDMI_DEEPCOLORPACKECTDISABLE = 0,
206 HDMI_DEEPCOLORPACKECTENABLE = 1
207};
208
209enum hdmi_core_packet_mode {
210 HDMI_PACKETMODERESERVEDVALUE = 0,
211 HDMI_PACKETMODE24BITPERPIXEL = 4,
212 HDMI_PACKETMODE30BITPERPIXEL = 5,
213 HDMI_PACKETMODE36BITPERPIXEL = 6,
214 HDMI_PACKETMODE48BITPERPIXEL = 7
215};
216
217enum hdmi_core_tclkselclkmult {
218 HDMI_FPLL05IDCK = 0,
219 HDMI_FPLL10IDCK = 1,
220 HDMI_FPLL20IDCK = 2,
221 HDMI_FPLL40IDCK = 3
222};
223
224enum hdmi_core_packet_ctrl {
225 HDMI_PACKETENABLE = 1,
226 HDMI_PACKETDISABLE = 0,
227 HDMI_PACKETREPEATON = 1,
228 HDMI_PACKETREPEATOFF = 0
229};
230
231/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
232enum hdmi_core_infoframe {
233 HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
234 HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
235 HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
236 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
237 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1,
238 HDMI_INFOFRAME_AVI_DB1B_NO = 0,
239 HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
240 HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
241 HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
242 HDMI_INFOFRAME_AVI_DB1S_0 = 0,
243 HDMI_INFOFRAME_AVI_DB1S_1 = 1,
244 HDMI_INFOFRAME_AVI_DB1S_2 = 2,
245 HDMI_INFOFRAME_AVI_DB2C_NO = 0,
246 HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
247 HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
248 HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
249 HDMI_INFOFRAME_AVI_DB2M_NO = 0,
250 HDMI_INFOFRAME_AVI_DB2M_43 = 1,
251 HDMI_INFOFRAME_AVI_DB2M_169 = 2,
252 HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
253 HDMI_INFOFRAME_AVI_DB2R_43 = 9,
254 HDMI_INFOFRAME_AVI_DB2R_169 = 10,
255 HDMI_INFOFRAME_AVI_DB2R_149 = 11,
256 HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
257 HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
258 HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
259 HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
260 HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
261 HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
262 HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
263 HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
264 HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
265 HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
266 HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
267 HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
268 HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
269 HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
270 HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
271 HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
272 HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
273 HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
274 HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
275 HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
276 HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
277};
278
279enum hdmi_packing_mode {
280 HDMI_PACK_10b_RGB_YUV444 = 0,
281 HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
282 HDMI_PACK_20b_YUV422 = 2,
283 HDMI_PACK_ALREADYPACKED = 7
284};
285
286enum hdmi_core_audio_layout {
287 HDMI_AUDIO_LAYOUT_2CH = 0,
288 HDMI_AUDIO_LAYOUT_8CH = 1
289};
290
291enum hdmi_core_cts_mode {
292 HDMI_AUDIO_CTS_MODE_HW = 0,
293 HDMI_AUDIO_CTS_MODE_SW = 1
294};
295
296enum hdmi_stereo_channels {
297 HDMI_AUDIO_STEREO_NOCHANNELS = 0,
298 HDMI_AUDIO_STEREO_ONECHANNEL = 1,
299 HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
300 HDMI_AUDIO_STEREO_THREECHANNELS = 3,
301 HDMI_AUDIO_STEREO_FOURCHANNELS = 4
302};
303
304enum hdmi_audio_type {
305 HDMI_AUDIO_TYPE_LPCM = 0,
306 HDMI_AUDIO_TYPE_IEC = 1
307};
308
309enum hdmi_audio_justify {
310 HDMI_AUDIO_JUSTIFY_LEFT = 0,
311 HDMI_AUDIO_JUSTIFY_RIGHT = 1
312};
313
314enum hdmi_audio_sample_order {
315 HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
316 HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
317};
318
319enum hdmi_audio_samples_perword {
320 HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
321 HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
322};
323
324enum hdmi_audio_sample_size {
325 HDMI_AUDIO_SAMPLE_16BITS = 0,
326 HDMI_AUDIO_SAMPLE_24BITS = 1
327};
328
329enum hdmi_audio_transf_mode {
330 HDMI_AUDIO_TRANSF_DMA = 0,
331 HDMI_AUDIO_TRANSF_IRQ = 1
332};
333
334enum hdmi_audio_blk_strt_end_sig {
335 HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
336 HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
337};
338
339enum hdmi_audio_i2s_config {
340 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
341 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
342 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
343 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
344 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
345 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
346 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
347 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
348 HDMI_AUDIO_I2S_SD0_EN = 1,
349 HDMI_AUDIO_I2S_SD1_EN = 1 << 1,
350 HDMI_AUDIO_I2S_SD2_EN = 1 << 2,
351 HDMI_AUDIO_I2S_SD3_EN = 1 << 3,
352};
353
354enum hdmi_audio_mclk_mode {
355 HDMI_AUDIO_MCLK_128FS = 0,
356 HDMI_AUDIO_MCLK_256FS = 1,
357 HDMI_AUDIO_MCLK_384FS = 2,
358 HDMI_AUDIO_MCLK_512FS = 3,
359 HDMI_AUDIO_MCLK_768FS = 4,
360 HDMI_AUDIO_MCLK_1024FS = 5,
361 HDMI_AUDIO_MCLK_1152FS = 6,
362 HDMI_AUDIO_MCLK_192FS = 7
363};
364
365struct hdmi_core_video_config {
366 enum hdmi_core_inputbus_width ip_bus_width;
367 enum hdmi_core_dither_trunc op_dither_truc;
368 enum hdmi_core_deepcolor_ed deep_color_pkt;
369 enum hdmi_core_packet_mode pkt_mode;
370 enum hdmi_core_hdmi_dvi hdmi_dvi;
371 enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
372};
373
374struct hdmi_core_packet_enable_repeat {
375 u32 audio_pkt;
376 u32 audio_pkt_repeat;
377 u32 avi_infoframe;
378 u32 avi_infoframe_repeat;
379 u32 gen_cntrl_pkt;
380 u32 gen_cntrl_pkt_repeat;
381 u32 generic_pkt;
382 u32 generic_pkt_repeat;
383};
384
385struct hdmi_video_format {
386 enum hdmi_packing_mode packing_mode;
387 u32 y_res; /* Line per panel */
388 u32 x_res; /* pixel per line */
389};
390
391struct hdmi_audio_format {
392 enum hdmi_stereo_channels stereo_channels;
393 u8 active_chnnls_msk;
394 enum hdmi_audio_type type;
395 enum hdmi_audio_justify justification;
396 enum hdmi_audio_sample_order sample_order;
397 enum hdmi_audio_samples_perword samples_per_word;
398 enum hdmi_audio_sample_size sample_size;
399 enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end;
400};
401
402struct hdmi_audio_dma {
403 u8 transfer_size;
404 u8 block_size;
405 enum hdmi_audio_transf_mode mode;
406 u16 fifo_threshold;
407};
408
409struct hdmi_core_audio_i2s_config {
410 u8 in_length_bits;
411 u8 justification;
412 u8 sck_edge_mode;
413 u8 vbit;
414 u8 direction;
415 u8 shift;
416 u8 active_sds;
417};
418
419struct hdmi_core_audio_config {
420 struct hdmi_core_audio_i2s_config i2s_cfg;
421 struct snd_aes_iec958 *iec60958_cfg;
422 bool fs_override;
423 u32 n;
424 u32 cts;
425 u32 aud_par_busclk;
426 enum hdmi_core_audio_layout layout;
427 enum hdmi_core_cts_mode cts_mode;
428 bool use_mclk;
429 enum hdmi_audio_mclk_mode mclk_mode;
430 bool en_acr_pkt;
431 bool en_dsd_audio;
432 bool en_parallel_aud_input;
433 bool en_spdif;
434};
435
436#endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 006caf3cb50..173c66430da 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -36,6 +36,7 @@
36#include <linux/pm_runtime.h> 36#include <linux/pm_runtime.h>
37 37
38#include <video/omapdss.h> 38#include <video/omapdss.h>
39#include <plat/cpu.h>
39 40
40#include "dss.h" 41#include "dss.h"
41#include "dss_features.h" 42#include "dss_features.h"
@@ -271,8 +272,6 @@ const struct omap_video_timings omap_dss_pal_timings = {
271 .vsw = 5, 272 .vsw = 5,
272 .vfp = 5, 273 .vfp = 5,
273 .vbp = 41, 274 .vbp = 41,
274
275 .interlace = true,
276}; 275};
277EXPORT_SYMBOL(omap_dss_pal_timings); 276EXPORT_SYMBOL(omap_dss_pal_timings);
278 277
@@ -286,8 +285,6 @@ const struct omap_video_timings omap_dss_ntsc_timings = {
286 .vsw = 6, 285 .vsw = 6,
287 .vfp = 6, 286 .vfp = 6,
288 .vbp = 31, 287 .vbp = 31,
289
290 .interlace = true,
291}; 288};
292EXPORT_SYMBOL(omap_dss_ntsc_timings); 289EXPORT_SYMBOL(omap_dss_ntsc_timings);
293 290
@@ -298,13 +295,8 @@ static struct {
298 u32 wss_data; 295 u32 wss_data;
299 struct regulator *vdda_dac_reg; 296 struct regulator *vdda_dac_reg;
300 297
298 struct clk *tv_clk;
301 struct clk *tv_dac_clk; 299 struct clk *tv_dac_clk;
302
303 struct omap_video_timings timings;
304 enum omap_dss_venc_type type;
305 bool invert_polarity;
306
307 struct omap_dss_output output;
308} venc; 300} venc;
309 301
310static inline void venc_write_reg(int idx, u32 val) 302static inline void venc_write_reg(int idx, u32 val)
@@ -410,8 +402,8 @@ static void venc_runtime_put(void)
410 402
411 DSSDBG("venc_runtime_put\n"); 403 DSSDBG("venc_runtime_put\n");
412 404
413 r = pm_runtime_put_sync(&venc.pdev->dev); 405 r = pm_runtime_put(&venc.pdev->dev);
414 WARN_ON(r < 0 && r != -ENOSYS); 406 WARN_ON(r < 0);
415} 407}
416 408
417static const struct venc_config *venc_timings_to_config( 409static const struct venc_config *venc_timings_to_config(
@@ -424,157 +416,171 @@ static const struct venc_config *venc_timings_to_config(
424 return &venc_config_ntsc_trm; 416 return &venc_config_ntsc_trm;
425 417
426 BUG(); 418 BUG();
427 return NULL;
428} 419}
429 420
430static int venc_power_on(struct omap_dss_device *dssdev) 421static void venc_power_on(struct omap_dss_device *dssdev)
431{ 422{
432 struct omap_overlay_manager *mgr = dssdev->output->manager;
433 u32 l; 423 u32 l;
434 int r;
435
436 r = venc_runtime_get();
437 if (r)
438 goto err0;
439 424
440 venc_reset(); 425 venc_reset();
441 venc_write_config(venc_timings_to_config(&venc.timings)); 426 venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
442 427
443 dss_set_venc_output(venc.type); 428 dss_set_venc_output(dssdev->phy.venc.type);
444 dss_set_dac_pwrdn_bgz(1); 429 dss_set_dac_pwrdn_bgz(1);
445 430
446 l = 0; 431 l = 0;
447 432
448 if (venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE) 433 if (dssdev->phy.venc.type == OMAP_DSS_VENC_TYPE_COMPOSITE)
449 l |= 1 << 1; 434 l |= 1 << 1;
450 else /* S-Video */ 435 else /* S-Video */
451 l |= (1 << 0) | (1 << 2); 436 l |= (1 << 0) | (1 << 2);
452 437
453 if (venc.invert_polarity == false) 438 if (dssdev->phy.venc.invert_polarity == false)
454 l |= 1 << 3; 439 l |= 1 << 3;
455 440
456 venc_write_reg(VENC_OUTPUT_CONTROL, l); 441 venc_write_reg(VENC_OUTPUT_CONTROL, l);
457 442
458 dss_mgr_set_timings(mgr, &venc.timings); 443 dispc_set_digit_size(dssdev->panel.timings.x_res,
444 dssdev->panel.timings.y_res/2);
459 445
460 r = regulator_enable(venc.vdda_dac_reg); 446 regulator_enable(venc.vdda_dac_reg);
461 if (r)
462 goto err1;
463
464 r = dss_mgr_enable(mgr);
465 if (r)
466 goto err2;
467
468 return 0;
469 447
470err2: 448 if (dssdev->platform_enable)
471 regulator_disable(venc.vdda_dac_reg); 449 dssdev->platform_enable(dssdev);
472err1:
473 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
474 dss_set_dac_pwrdn_bgz(0);
475 450
476 venc_runtime_put(); 451 dssdev->manager->enable(dssdev->manager);
477err0:
478 return r;
479} 452}
480 453
481static void venc_power_off(struct omap_dss_device *dssdev) 454static void venc_power_off(struct omap_dss_device *dssdev)
482{ 455{
483 struct omap_overlay_manager *mgr = dssdev->output->manager;
484
485 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 456 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
486 dss_set_dac_pwrdn_bgz(0); 457 dss_set_dac_pwrdn_bgz(0);
487 458
488 dss_mgr_disable(mgr); 459 dssdev->manager->disable(dssdev->manager);
460
461 if (dssdev->platform_disable)
462 dssdev->platform_disable(dssdev);
489 463
490 regulator_disable(venc.vdda_dac_reg); 464 regulator_disable(venc.vdda_dac_reg);
465}
491 466
492 venc_runtime_put(); 467
468
469
470
471/* driver */
472static int venc_panel_probe(struct omap_dss_device *dssdev)
473{
474 dssdev->panel.timings = omap_dss_pal_timings;
475
476 return 0;
493} 477}
494 478
495unsigned long venc_get_pixel_clock(void) 479static void venc_panel_remove(struct omap_dss_device *dssdev)
496{ 480{
497 /* VENC Pixel Clock in Mhz */
498 return 13500000;
499} 481}
500 482
501int omapdss_venc_display_enable(struct omap_dss_device *dssdev) 483static int venc_panel_enable(struct omap_dss_device *dssdev)
502{ 484{
503 struct omap_dss_output *out = dssdev->output; 485 int r = 0;
504 int r;
505 486
506 DSSDBG("venc_display_enable\n"); 487 DSSDBG("venc_enable_display\n");
507 488
508 mutex_lock(&venc.venc_lock); 489 mutex_lock(&venc.venc_lock);
509 490
510 if (out == NULL || out->manager == NULL) {
511 DSSERR("Failed to enable display: no output/manager\n");
512 r = -ENODEV;
513 goto err0;
514 }
515
516 r = omap_dss_start_device(dssdev); 491 r = omap_dss_start_device(dssdev);
517 if (r) { 492 if (r) {
518 DSSERR("failed to start device\n"); 493 DSSERR("failed to start device\n");
519 goto err0; 494 goto err0;
520 } 495 }
521 496
522 if (dssdev->platform_enable) 497 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
523 dssdev->platform_enable(dssdev); 498 r = -EINVAL;
524 499 goto err1;
500 }
525 501
526 r = venc_power_on(dssdev); 502 r = venc_runtime_get();
527 if (r) 503 if (r)
528 goto err1; 504 goto err1;
529 505
506 venc_power_on(dssdev);
507
530 venc.wss_data = 0; 508 venc.wss_data = 0;
531 509
532 mutex_unlock(&venc.venc_lock); 510 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
533 511
512 mutex_unlock(&venc.venc_lock);
534 return 0; 513 return 0;
535err1: 514err1:
536 if (dssdev->platform_disable)
537 dssdev->platform_disable(dssdev);
538 omap_dss_stop_device(dssdev); 515 omap_dss_stop_device(dssdev);
539err0: 516err0:
540 mutex_unlock(&venc.venc_lock); 517 mutex_unlock(&venc.venc_lock);
518
541 return r; 519 return r;
542} 520}
543 521
544void omapdss_venc_display_disable(struct omap_dss_device *dssdev) 522static void venc_panel_disable(struct omap_dss_device *dssdev)
545{ 523{
546 DSSDBG("venc_display_disable\n"); 524 DSSDBG("venc_disable_display\n");
547 525
548 mutex_lock(&venc.venc_lock); 526 mutex_lock(&venc.venc_lock);
549 527
528 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
529 goto end;
530
531 if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) {
532 /* suspended is the same as disabled with venc */
533 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
534 goto end;
535 }
536
550 venc_power_off(dssdev); 537 venc_power_off(dssdev);
551 538
552 omap_dss_stop_device(dssdev); 539 venc_runtime_put();
553 540
554 if (dssdev->platform_disable) 541 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
555 dssdev->platform_disable(dssdev);
556 542
543 omap_dss_stop_device(dssdev);
544end:
557 mutex_unlock(&venc.venc_lock); 545 mutex_unlock(&venc.venc_lock);
558} 546}
559 547
560void omapdss_venc_set_timings(struct omap_dss_device *dssdev, 548static int venc_panel_suspend(struct omap_dss_device *dssdev)
561 struct omap_video_timings *timings)
562{ 549{
563 DSSDBG("venc_set_timings\n"); 550 venc_panel_disable(dssdev);
551 return 0;
552}
564 553
565 mutex_lock(&venc.venc_lock); 554static int venc_panel_resume(struct omap_dss_device *dssdev)
555{
556 return venc_panel_enable(dssdev);
557}
558
559static void venc_get_timings(struct omap_dss_device *dssdev,
560 struct omap_video_timings *timings)
561{
562 *timings = dssdev->panel.timings;
563}
564
565static void venc_set_timings(struct omap_dss_device *dssdev,
566 struct omap_video_timings *timings)
567{
568 DSSDBG("venc_set_timings\n");
566 569
567 /* Reset WSS data when the TV standard changes. */ 570 /* Reset WSS data when the TV standard changes. */
568 if (memcmp(&venc.timings, timings, sizeof(*timings))) 571 if (memcmp(&dssdev->panel.timings, timings, sizeof(*timings)))
569 venc.wss_data = 0; 572 venc.wss_data = 0;
570 573
571 venc.timings = *timings; 574 dssdev->panel.timings = *timings;
572 575 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
573 mutex_unlock(&venc.venc_lock); 576 /* turn the venc off and on to get new timings to use */
577 venc_panel_disable(dssdev);
578 venc_panel_enable(dssdev);
579 }
574} 580}
575 581
576int omapdss_venc_check_timings(struct omap_dss_device *dssdev, 582static int venc_check_timings(struct omap_dss_device *dssdev,
577 struct omap_video_timings *timings) 583 struct omap_video_timings *timings)
578{ 584{
579 DSSDBG("venc_check_timings\n"); 585 DSSDBG("venc_check_timings\n");
580 586
@@ -587,13 +593,13 @@ int omapdss_venc_check_timings(struct omap_dss_device *dssdev,
587 return -EINVAL; 593 return -EINVAL;
588} 594}
589 595
590u32 omapdss_venc_get_wss(struct omap_dss_device *dssdev) 596static u32 venc_get_wss(struct omap_dss_device *dssdev)
591{ 597{
592 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 598 /* Invert due to VENC_L21_WC_CTL:INV=1 */
593 return (venc.wss_data >> 8) ^ 0xfffff; 599 return (venc.wss_data >> 8) ^ 0xfffff;
594} 600}
595 601
596int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss) 602static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
597{ 603{
598 const struct venc_config *config; 604 const struct venc_config *config;
599 int r; 605 int r;
@@ -602,7 +608,7 @@ int omapdss_venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
602 608
603 mutex_lock(&venc.venc_lock); 609 mutex_lock(&venc.venc_lock);
604 610
605 config = venc_timings_to_config(&venc.timings); 611 config = venc_timings_to_config(&dssdev->panel.timings);
606 612
607 /* Invert due to VENC_L21_WC_CTL:INV=1 */ 613 /* Invert due to VENC_L21_WC_CTL:INV=1 */
608 venc.wss_data = (wss ^ 0xfffff) << 8; 614 venc.wss_data = (wss ^ 0xfffff) << 8;
@@ -622,27 +628,33 @@ err:
622 return r; 628 return r;
623} 629}
624 630
625void omapdss_venc_set_type(struct omap_dss_device *dssdev, 631static struct omap_dss_driver venc_driver = {
626 enum omap_dss_venc_type type) 632 .probe = venc_panel_probe,
627{ 633 .remove = venc_panel_remove,
628 mutex_lock(&venc.venc_lock);
629 634
630 venc.type = type; 635 .enable = venc_panel_enable,
636 .disable = venc_panel_disable,
637 .suspend = venc_panel_suspend,
638 .resume = venc_panel_resume,
631 639
632 mutex_unlock(&venc.venc_lock); 640 .get_resolution = omapdss_default_get_resolution,
633} 641 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
634 642
635void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, 643 .get_timings = venc_get_timings,
636 bool invert_polarity) 644 .set_timings = venc_set_timings,
637{ 645 .check_timings = venc_check_timings,
638 mutex_lock(&venc.venc_lock);
639 646
640 venc.invert_polarity = invert_polarity; 647 .get_wss = venc_get_wss,
648 .set_wss = venc_set_wss,
641 649
642 mutex_unlock(&venc.venc_lock); 650 .driver = {
643} 651 .name = "venc",
652 .owner = THIS_MODULE,
653 },
654};
655/* driver end */
644 656
645static int __init venc_init_display(struct omap_dss_device *dssdev) 657int venc_init_display(struct omap_dss_device *dssdev)
646{ 658{
647 DSSDBG("init_display\n"); 659 DSSDBG("init_display\n");
648 660
@@ -662,7 +674,7 @@ static int __init venc_init_display(struct omap_dss_device *dssdev)
662 return 0; 674 return 0;
663} 675}
664 676
665static void venc_dump_regs(struct seq_file *s) 677void venc_dump_regs(struct seq_file *s)
666{ 678{
667#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 679#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
668 680
@@ -720,10 +732,22 @@ static int venc_get_clocks(struct platform_device *pdev)
720{ 732{
721 struct clk *clk; 733 struct clk *clk;
722 734
735 clk = clk_get(&pdev->dev, "fck");
736 if (IS_ERR(clk)) {
737 DSSERR("can't get fck\n");
738 return PTR_ERR(clk);
739 }
740
741 venc.tv_clk = clk;
742
723 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { 743 if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) {
724 clk = clk_get(&pdev->dev, "tv_dac_clk"); 744 if (cpu_is_omap34xx() || cpu_is_omap3630())
745 clk = clk_get(&pdev->dev, "dss_96m_fck");
746 else
747 clk = clk_get(&pdev->dev, "tv_dac_clk");
725 if (IS_ERR(clk)) { 748 if (IS_ERR(clk)) {
726 DSSERR("can't get tv_dac_clk\n"); 749 DSSERR("can't get tv_dac_clk\n");
750 clk_put(venc.tv_clk);
727 return PTR_ERR(clk); 751 return PTR_ERR(clk);
728 } 752 }
729 } else { 753 } else {
@@ -737,101 +761,14 @@ static int venc_get_clocks(struct platform_device *pdev)
737 761
738static void venc_put_clocks(void) 762static void venc_put_clocks(void)
739{ 763{
764 if (venc.tv_clk)
765 clk_put(venc.tv_clk);
740 if (venc.tv_dac_clk) 766 if (venc.tv_dac_clk)
741 clk_put(venc.tv_dac_clk); 767 clk_put(venc.tv_dac_clk);
742} 768}
743 769
744static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
745{
746 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
747 const char *def_disp_name = omapdss_get_default_display_name();
748 struct omap_dss_device *def_dssdev;
749 int i;
750
751 def_dssdev = NULL;
752
753 for (i = 0; i < pdata->num_devices; ++i) {
754 struct omap_dss_device *dssdev = pdata->devices[i];
755
756 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
757 continue;
758
759 if (def_dssdev == NULL)
760 def_dssdev = dssdev;
761
762 if (def_disp_name != NULL &&
763 strcmp(dssdev->name, def_disp_name) == 0) {
764 def_dssdev = dssdev;
765 break;
766 }
767 }
768
769 return def_dssdev;
770}
771
772static void __init venc_probe_pdata(struct platform_device *vencdev)
773{
774 struct omap_dss_device *plat_dssdev;
775 struct omap_dss_device *dssdev;
776 int r;
777
778 plat_dssdev = venc_find_dssdev(vencdev);
779
780 if (!plat_dssdev)
781 return;
782
783 dssdev = dss_alloc_and_init_device(&vencdev->dev);
784 if (!dssdev)
785 return;
786
787 dss_copy_device_pdata(dssdev, plat_dssdev);
788
789 dssdev->channel = OMAP_DSS_CHANNEL_DIGIT;
790
791 r = venc_init_display(dssdev);
792 if (r) {
793 DSSERR("device %s init failed: %d\n", dssdev->name, r);
794 dss_put_device(dssdev);
795 return;
796 }
797
798 r = omapdss_output_set_device(&venc.output, dssdev);
799 if (r) {
800 DSSERR("failed to connect output to new device: %s\n",
801 dssdev->name);
802 dss_put_device(dssdev);
803 return;
804 }
805
806 r = dss_add_device(dssdev);
807 if (r) {
808 DSSERR("device %s register failed: %d\n", dssdev->name, r);
809 omapdss_output_unset_device(&venc.output);
810 dss_put_device(dssdev);
811 return;
812 }
813}
814
815static void __init venc_init_output(struct platform_device *pdev)
816{
817 struct omap_dss_output *out = &venc.output;
818
819 out->pdev = pdev;
820 out->id = OMAP_DSS_OUTPUT_VENC;
821 out->type = OMAP_DISPLAY_TYPE_VENC;
822
823 dss_register_output(out);
824}
825
826static void __exit venc_uninit_output(struct platform_device *pdev)
827{
828 struct omap_dss_output *out = &venc.output;
829
830 dss_unregister_output(out);
831}
832
833/* VENC HW IP initialisation */ 770/* VENC HW IP initialisation */
834static int __init omap_venchw_probe(struct platform_device *pdev) 771static int omap_venchw_probe(struct platform_device *pdev)
835{ 772{
836 u8 rev_id; 773 u8 rev_id;
837 struct resource *venc_mem; 774 struct resource *venc_mem;
@@ -846,75 +783,65 @@ static int __init omap_venchw_probe(struct platform_device *pdev)
846 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); 783 venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0);
847 if (!venc_mem) { 784 if (!venc_mem) {
848 DSSERR("can't get IORESOURCE_MEM VENC\n"); 785 DSSERR("can't get IORESOURCE_MEM VENC\n");
849 return -EINVAL; 786 r = -EINVAL;
787 goto err_ioremap;
850 } 788 }
851 789 venc.base = ioremap(venc_mem->start, resource_size(venc_mem));
852 venc.base = devm_ioremap(&pdev->dev, venc_mem->start,
853 resource_size(venc_mem));
854 if (!venc.base) { 790 if (!venc.base) {
855 DSSERR("can't ioremap VENC\n"); 791 DSSERR("can't ioremap VENC\n");
856 return -ENOMEM; 792 r = -ENOMEM;
793 goto err_ioremap;
857 } 794 }
858 795
859 r = venc_get_clocks(pdev); 796 r = venc_get_clocks(pdev);
860 if (r) 797 if (r)
861 return r; 798 goto err_get_clk;
862 799
863 pm_runtime_enable(&pdev->dev); 800 pm_runtime_enable(&pdev->dev);
864 801
865 r = venc_runtime_get(); 802 r = venc_runtime_get();
866 if (r) 803 if (r)
867 goto err_runtime_get; 804 goto err_get_venc;
868 805
869 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); 806 rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
870 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); 807 dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id);
871 808
872 venc_runtime_put(); 809 venc_runtime_put();
873 810
874 r = venc_panel_init(); 811 return omap_dss_register_driver(&venc_driver);
875 if (r)
876 goto err_panel_init;
877
878 dss_debugfs_create_file("venc", venc_dump_regs);
879
880 venc_init_output(pdev);
881 812
882 venc_probe_pdata(pdev); 813err_get_venc:
883
884 return 0;
885
886err_panel_init:
887err_runtime_get:
888 pm_runtime_disable(&pdev->dev); 814 pm_runtime_disable(&pdev->dev);
889 venc_put_clocks(); 815 venc_put_clocks();
816err_get_clk:
817 iounmap(venc.base);
818err_ioremap:
890 return r; 819 return r;
891} 820}
892 821
893static int __exit omap_venchw_remove(struct platform_device *pdev) 822static int omap_venchw_remove(struct platform_device *pdev)
894{ 823{
895 dss_unregister_child_devices(&pdev->dev);
896
897 if (venc.vdda_dac_reg != NULL) { 824 if (venc.vdda_dac_reg != NULL) {
898 regulator_put(venc.vdda_dac_reg); 825 regulator_put(venc.vdda_dac_reg);
899 venc.vdda_dac_reg = NULL; 826 venc.vdda_dac_reg = NULL;
900 } 827 }
901 828 omap_dss_unregister_driver(&venc_driver);
902 venc_panel_exit();
903
904 venc_uninit_output(pdev);
905 829
906 pm_runtime_disable(&pdev->dev); 830 pm_runtime_disable(&pdev->dev);
907 venc_put_clocks(); 831 venc_put_clocks();
908 832
833 iounmap(venc.base);
909 return 0; 834 return 0;
910} 835}
911 836
912static int venc_runtime_suspend(struct device *dev) 837static int venc_runtime_suspend(struct device *dev)
913{ 838{
914 if (venc.tv_dac_clk) 839 if (venc.tv_dac_clk)
915 clk_disable_unprepare(venc.tv_dac_clk); 840 clk_disable(venc.tv_dac_clk);
841 clk_disable(venc.tv_clk);
916 842
917 dispc_runtime_put(); 843 dispc_runtime_put();
844 dss_runtime_put();
918 845
919 return 0; 846 return 0;
920} 847}
@@ -923,14 +850,24 @@ static int venc_runtime_resume(struct device *dev)
923{ 850{
924 int r; 851 int r;
925 852
853 r = dss_runtime_get();
854 if (r < 0)
855 goto err_get_dss;
856
926 r = dispc_runtime_get(); 857 r = dispc_runtime_get();
927 if (r < 0) 858 if (r < 0)
928 return r; 859 goto err_get_dispc;
929 860
861 clk_enable(venc.tv_clk);
930 if (venc.tv_dac_clk) 862 if (venc.tv_dac_clk)
931 clk_prepare_enable(venc.tv_dac_clk); 863 clk_enable(venc.tv_dac_clk);
932 864
933 return 0; 865 return 0;
866
867err_get_dispc:
868 dss_runtime_put();
869err_get_dss:
870 return r;
934} 871}
935 872
936static const struct dev_pm_ops venc_pm_ops = { 873static const struct dev_pm_ops venc_pm_ops = {
@@ -939,7 +876,8 @@ static const struct dev_pm_ops venc_pm_ops = {
939}; 876};
940 877
941static struct platform_driver omap_venchw_driver = { 878static struct platform_driver omap_venchw_driver = {
942 .remove = __exit_p(omap_venchw_remove), 879 .probe = omap_venchw_probe,
880 .remove = omap_venchw_remove,
943 .driver = { 881 .driver = {
944 .name = "omapdss_venc", 882 .name = "omapdss_venc",
945 .owner = THIS_MODULE, 883 .owner = THIS_MODULE,
@@ -947,12 +885,18 @@ static struct platform_driver omap_venchw_driver = {
947 }, 885 },
948}; 886};
949 887
950int __init venc_init_platform_driver(void) 888int venc_init_platform_driver(void)
951{ 889{
952 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); 890 if (cpu_is_omap44xx())
891 return 0;
892
893 return platform_driver_register(&omap_venchw_driver);
953} 894}
954 895
955void __exit venc_uninit_platform_driver(void) 896void venc_uninit_platform_driver(void)
956{ 897{
957 platform_driver_unregister(&omap_venchw_driver); 898 if (cpu_is_omap44xx())
899 return;
900
901 return platform_driver_unregister(&omap_venchw_driver);
958} 902}
diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/omap2/dss/venc_panel.c
deleted file mode 100644
index 0d2b1a0834a..00000000000
--- a/drivers/video/omap2/dss/venc_panel.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * VENC panel driver
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/mutex.h>
24#include <linux/module.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29
30static struct {
31 struct mutex lock;
32} venc_panel;
33
34static ssize_t display_output_type_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 const char *ret;
39
40 switch (dssdev->phy.venc.type) {
41 case OMAP_DSS_VENC_TYPE_COMPOSITE:
42 ret = "composite";
43 break;
44 case OMAP_DSS_VENC_TYPE_SVIDEO:
45 ret = "svideo";
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
52}
53
54static ssize_t display_output_type_store(struct device *dev,
55 struct device_attribute *attr, const char *buf, size_t size)
56{
57 struct omap_dss_device *dssdev = to_dss_device(dev);
58 enum omap_dss_venc_type new_type;
59
60 if (sysfs_streq("composite", buf))
61 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
62 else if (sysfs_streq("svideo", buf))
63 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
64 else
65 return -EINVAL;
66
67 mutex_lock(&venc_panel.lock);
68
69 if (dssdev->phy.venc.type != new_type) {
70 dssdev->phy.venc.type = new_type;
71 omapdss_venc_set_type(dssdev, new_type);
72 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
73 omapdss_venc_display_disable(dssdev);
74 omapdss_venc_display_enable(dssdev);
75 }
76 }
77
78 mutex_unlock(&venc_panel.lock);
79
80 return size;
81}
82
83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
84 display_output_type_show, display_output_type_store);
85
86static int venc_panel_probe(struct omap_dss_device *dssdev)
87{
88 /* set default timings to PAL */
89 const struct omap_video_timings default_timings = {
90 .x_res = 720,
91 .y_res = 574,
92 .pixel_clock = 13500,
93 .hsw = 64,
94 .hfp = 12,
95 .hbp = 68,
96 .vsw = 5,
97 .vfp = 5,
98 .vbp = 41,
99
100 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
101 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
102
103 .interlace = true,
104 };
105
106 mutex_init(&venc_panel.lock);
107
108 dssdev->panel.timings = default_timings;
109
110 return device_create_file(&dssdev->dev, &dev_attr_output_type);
111}
112
113static void venc_panel_remove(struct omap_dss_device *dssdev)
114{
115 device_remove_file(&dssdev->dev, &dev_attr_output_type);
116}
117
118static int venc_panel_enable(struct omap_dss_device *dssdev)
119{
120 int r;
121
122 dev_dbg(&dssdev->dev, "venc_panel_enable\n");
123
124 mutex_lock(&venc_panel.lock);
125
126 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
127 r = -EINVAL;
128 goto err;
129 }
130
131 omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
132 omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
133 omapdss_venc_invert_vid_out_polarity(dssdev,
134 dssdev->phy.venc.invert_polarity);
135
136 r = omapdss_venc_display_enable(dssdev);
137 if (r)
138 goto err;
139
140 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
141
142 mutex_unlock(&venc_panel.lock);
143
144 return 0;
145err:
146 mutex_unlock(&venc_panel.lock);
147
148 return r;
149}
150
151static void venc_panel_disable(struct omap_dss_device *dssdev)
152{
153 dev_dbg(&dssdev->dev, "venc_panel_disable\n");
154
155 mutex_lock(&venc_panel.lock);
156
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end;
159
160 omapdss_venc_display_disable(dssdev);
161
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163end:
164 mutex_unlock(&venc_panel.lock);
165}
166
167static void venc_panel_set_timings(struct omap_dss_device *dssdev,
168 struct omap_video_timings *timings)
169{
170 dev_dbg(&dssdev->dev, "venc_panel_set_timings\n");
171
172 mutex_lock(&venc_panel.lock);
173
174 omapdss_venc_set_timings(dssdev, timings);
175 dssdev->panel.timings = *timings;
176
177 mutex_unlock(&venc_panel.lock);
178}
179
180static int venc_panel_check_timings(struct omap_dss_device *dssdev,
181 struct omap_video_timings *timings)
182{
183 dev_dbg(&dssdev->dev, "venc_panel_check_timings\n");
184
185 return omapdss_venc_check_timings(dssdev, timings);
186}
187
188static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
189{
190 dev_dbg(&dssdev->dev, "venc_panel_get_wss\n");
191
192 return omapdss_venc_get_wss(dssdev);
193}
194
195static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
196{
197 dev_dbg(&dssdev->dev, "venc_panel_set_wss\n");
198
199 return omapdss_venc_set_wss(dssdev, wss);
200}
201
202static struct omap_dss_driver venc_driver = {
203 .probe = venc_panel_probe,
204 .remove = venc_panel_remove,
205
206 .enable = venc_panel_enable,
207 .disable = venc_panel_disable,
208
209 .get_resolution = omapdss_default_get_resolution,
210 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
211
212 .set_timings = venc_panel_set_timings,
213 .check_timings = venc_panel_check_timings,
214
215 .get_wss = venc_panel_get_wss,
216 .set_wss = venc_panel_set_wss,
217
218 .driver = {
219 .name = "venc",
220 .owner = THIS_MODULE,
221 },
222};
223
224int venc_panel_init(void)
225{
226 return omap_dss_register_driver(&venc_driver);
227}
228
229void venc_panel_exit(void)
230{
231 omap_dss_unregister_driver(&venc_driver);
232}
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig
index 4cb12ce6885..aa33386c81f 100644
--- a/drivers/video/omap2/omapfb/Kconfig
+++ b/drivers/video/omap2/omapfb/Kconfig
@@ -1,7 +1,8 @@
1menuconfig FB_OMAP2 1menuconfig FB_OMAP2
2 tristate "OMAP2+ frame buffer support" 2 tristate "OMAP2+ frame buffer support (EXPERIMENTAL)"
3 depends on FB && OMAP2_DSS && !DRM_OMAP 3 depends on FB && OMAP2_DSS
4 4
5 select OMAP2_VRAM
5 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3 6 select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
6 select FB_CFB_FILLRECT 7 select FB_CFB_FILLRECT
7 select FB_CFB_COPYAREA 8 select FB_CFB_COPYAREA
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index d30b45d7264..6b1ac23dbbd 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -27,11 +27,10 @@
27#include <linux/mm.h> 27#include <linux/mm.h>
28#include <linux/omapfb.h> 28#include <linux/omapfb.h>
29#include <linux/vmalloc.h> 29#include <linux/vmalloc.h>
30#include <linux/export.h>
31#include <linux/sizes.h>
32 30
33#include <video/omapdss.h> 31#include <video/omapdss.h>
34#include <video/omapvrfb.h> 32#include <plat/vrfb.h>
33#include <plat/vram.h>
35 34
36#include "omapfb.h" 35#include "omapfb.h"
37 36
@@ -70,7 +69,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
70 69
71 DBG("omapfb_setup_plane\n"); 70 DBG("omapfb_setup_plane\n");
72 71
73 if (ofbi->num_overlays == 0) { 72 if (ofbi->num_overlays != 1) {
74 r = -EINVAL; 73 r = -EINVAL;
75 goto out; 74 goto out;
76 } 75 }
@@ -111,22 +110,28 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
111 set_fb_fix(fbi); 110 set_fb_fix(fbi);
112 } 111 }
113 112
114 if (!pi->enabled) {
115 r = ovl->disable(ovl);
116 if (r)
117 goto undo;
118 }
119
120 if (pi->enabled) { 113 if (pi->enabled) {
114 struct omap_overlay_info info;
115
121 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, 116 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
122 pi->out_width, pi->out_height); 117 pi->out_width, pi->out_height);
123 if (r) 118 if (r)
124 goto undo; 119 goto undo;
120
121 ovl->get_overlay_info(ovl, &info);
122
123 if (!info.enabled) {
124 info.enabled = pi->enabled;
125 r = ovl->set_overlay_info(ovl, &info);
126 if (r)
127 goto undo;
128 }
125 } else { 129 } else {
126 struct omap_overlay_info info; 130 struct omap_overlay_info info;
127 131
128 ovl->get_overlay_info(ovl, &info); 132 ovl->get_overlay_info(ovl, &info);
129 133
134 info.enabled = pi->enabled;
130 info.pos_x = pi->pos_x; 135 info.pos_x = pi->pos_x;
131 info.pos_y = pi->pos_y; 136 info.pos_y = pi->pos_y;
132 info.out_width = pi->out_width; 137 info.out_width = pi->out_width;
@@ -140,12 +145,6 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
140 if (ovl->manager) 145 if (ovl->manager)
141 ovl->manager->apply(ovl->manager); 146 ovl->manager->apply(ovl->manager);
142 147
143 if (pi->enabled) {
144 r = ovl->enable(ovl);
145 if (r)
146 goto undo;
147 }
148
149 /* Release the locks in a specific order to keep lockdep happy */ 148 /* Release the locks in a specific order to keep lockdep happy */
150 if (old_rg->id > new_rg->id) { 149 if (old_rg->id > new_rg->id) {
151 omapfb_put_mem_region(old_rg); 150 omapfb_put_mem_region(old_rg);
@@ -185,23 +184,23 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
185{ 184{
186 struct omapfb_info *ofbi = FB2OFB(fbi); 185 struct omapfb_info *ofbi = FB2OFB(fbi);
187 186
188 if (ofbi->num_overlays == 0) { 187 if (ofbi->num_overlays != 1) {
189 memset(pi, 0, sizeof(*pi)); 188 memset(pi, 0, sizeof(*pi));
190 } else { 189 } else {
191 struct omap_overlay *ovl; 190 struct omap_overlay *ovl;
192 struct omap_overlay_info ovli; 191 struct omap_overlay_info *ovli;
193 192
194 ovl = ofbi->overlays[0]; 193 ovl = ofbi->overlays[0];
195 ovl->get_overlay_info(ovl, &ovli); 194 ovli = &ovl->info;
196 195
197 pi->pos_x = ovli.pos_x; 196 pi->pos_x = ovli->pos_x;
198 pi->pos_y = ovli.pos_y; 197 pi->pos_y = ovli->pos_y;
199 pi->enabled = ovl->is_enabled(ovl); 198 pi->enabled = ovli->enabled;
200 pi->channel_out = 0; /* xxx */ 199 pi->channel_out = 0; /* xxx */
201 pi->mirror = 0; 200 pi->mirror = 0;
202 pi->mem_idx = get_mem_idx(ofbi); 201 pi->mem_idx = get_mem_idx(ofbi);
203 pi->out_width = ovli.out_width; 202 pi->out_width = ovli->out_width;
204 pi->out_height = ovli.out_height; 203 pi->out_height = ovli->out_height;
205 } 204 }
206 205
207 return 0; 206 return 0;
@@ -211,27 +210,20 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
211{ 210{
212 struct omapfb_info *ofbi = FB2OFB(fbi); 211 struct omapfb_info *ofbi = FB2OFB(fbi);
213 struct omapfb2_device *fbdev = ofbi->fbdev; 212 struct omapfb2_device *fbdev = ofbi->fbdev;
214 struct omap_dss_device *display = fb2display(fbi);
215 struct omapfb2_mem_region *rg; 213 struct omapfb2_mem_region *rg;
216 int r = 0, i; 214 int r = 0, i;
217 size_t size; 215 size_t size;
218 216
219 if (mi->type != OMAPFB_MEMTYPE_SDRAM) 217 if (mi->type > OMAPFB_MEMTYPE_MAX)
220 return -EINVAL; 218 return -EINVAL;
221 219
222 size = PAGE_ALIGN(mi->size); 220 size = PAGE_ALIGN(mi->size);
223 221
224 if (display && display->driver->sync)
225 display->driver->sync(display);
226
227 rg = ofbi->region; 222 rg = ofbi->region;
228 223
229 down_write_nested(&rg->lock, rg->id); 224 down_write_nested(&rg->lock, rg->id);
230 atomic_inc(&rg->lock_count); 225 atomic_inc(&rg->lock_count);
231 226
232 if (rg->size == size && rg->type == mi->type)
233 goto out;
234
235 if (atomic_read(&rg->map_count)) { 227 if (atomic_read(&rg->map_count)) {
236 r = -EBUSY; 228 r = -EBUSY;
237 goto out; 229 goto out;
@@ -245,19 +237,19 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
245 continue; 237 continue;
246 238
247 for (j = 0; j < ofbi2->num_overlays; j++) { 239 for (j = 0; j < ofbi2->num_overlays; j++) {
248 struct omap_overlay *ovl; 240 if (ofbi2->overlays[j]->info.enabled) {
249 ovl = ofbi2->overlays[j];
250 if (ovl->is_enabled(ovl)) {
251 r = -EBUSY; 241 r = -EBUSY;
252 goto out; 242 goto out;
253 } 243 }
254 } 244 }
255 } 245 }
256 246
257 r = omapfb_realloc_fbmem(fbi, size, mi->type); 247 if (rg->size != size || rg->type != mi->type) {
258 if (r) { 248 r = omapfb_realloc_fbmem(fbi, size, mi->type);
259 dev_err(fbdev->dev, "realloc fbmem failed\n"); 249 if (r) {
260 goto out; 250 dev_err(fbdev->dev, "realloc fbmem failed\n");
251 goto out;
252 }
261 } 253 }
262 254
263 out: 255 out:
@@ -283,7 +275,7 @@ static int omapfb_query_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
283 return 0; 275 return 0;
284} 276}
285 277
286static int omapfb_update_window(struct fb_info *fbi, 278static int omapfb_update_window_nolock(struct fb_info *fbi,
287 u32 x, u32 y, u32 w, u32 h) 279 u32 x, u32 y, u32 w, u32 h)
288{ 280{
289 struct omap_dss_device *display = fb2display(fbi); 281 struct omap_dss_device *display = fb2display(fbi);
@@ -303,6 +295,27 @@ static int omapfb_update_window(struct fb_info *fbi,
303 return display->driver->update(display, x, y, w, h); 295 return display->driver->update(display, x, y, w, h);
304} 296}
305 297
298/* This function is exported for SGX driver use */
299int omapfb_update_window(struct fb_info *fbi,
300 u32 x, u32 y, u32 w, u32 h)
301{
302 struct omapfb_info *ofbi = FB2OFB(fbi);
303 struct omapfb2_device *fbdev = ofbi->fbdev;
304 int r;
305
306 if (!lock_fb_info(fbi))
307 return -ENODEV;
308 omapfb_lock(fbdev);
309
310 r = omapfb_update_window_nolock(fbi, x, y, w, h);
311
312 omapfb_unlock(fbdev);
313 unlock_fb_info(fbi);
314
315 return r;
316}
317EXPORT_SYMBOL(omapfb_update_window);
318
306int omapfb_set_update_mode(struct fb_info *fbi, 319int omapfb_set_update_mode(struct fb_info *fbi,
307 enum omapfb_update_mode mode) 320 enum omapfb_update_mode mode)
308{ 321{
@@ -582,7 +595,6 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
582 struct omapfb_info *ofbi = FB2OFB(fbi); 595 struct omapfb_info *ofbi = FB2OFB(fbi);
583 struct omapfb2_device *fbdev = ofbi->fbdev; 596 struct omapfb2_device *fbdev = ofbi->fbdev;
584 struct omap_dss_device *display = fb2display(fbi); 597 struct omap_dss_device *display = fb2display(fbi);
585 struct omap_overlay_manager *mgr;
586 598
587 union { 599 union {
588 struct omapfb_update_window_old uwnd_o; 600 struct omapfb_update_window_old uwnd_o;
@@ -629,7 +641,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
629 break; 641 break;
630 } 642 }
631 643
632 r = omapfb_update_window(fbi, p.uwnd_o.x, p.uwnd_o.y, 644 r = omapfb_update_window_nolock(fbi, p.uwnd_o.x, p.uwnd_o.y,
633 p.uwnd_o.width, p.uwnd_o.height); 645 p.uwnd_o.width, p.uwnd_o.height);
634 break; 646 break;
635 647
@@ -646,7 +658,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
646 break; 658 break;
647 } 659 }
648 660
649 r = omapfb_update_window(fbi, p.uwnd.x, p.uwnd.y, 661 r = omapfb_update_window_nolock(fbi, p.uwnd.x, p.uwnd.y,
650 p.uwnd.width, p.uwnd.height); 662 p.uwnd.width, p.uwnd.height);
651 break; 663 break;
652 664
@@ -770,14 +782,12 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
770 782
771 case OMAPFB_WAITFORVSYNC: 783 case OMAPFB_WAITFORVSYNC:
772 DBG("ioctl WAITFORVSYNC\n"); 784 DBG("ioctl WAITFORVSYNC\n");
773 if (!display || !display->output || !display->output->manager) { 785 if (!display) {
774 r = -EINVAL; 786 r = -EINVAL;
775 break; 787 break;
776 } 788 }
777 789
778 mgr = display->output->manager; 790 r = display->manager->wait_for_vsync(display->manager);
779
780 r = mgr->wait_for_vsync(mgr);
781 break; 791 break;
782 792
783 case OMAPFB_WAITFORGO: 793 case OMAPFB_WAITFORGO:
@@ -836,15 +846,14 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
836 break; 846 break;
837 847
838 case OMAPFB_GET_VRAM_INFO: { 848 case OMAPFB_GET_VRAM_INFO: {
849 unsigned long vram, free, largest;
850
839 DBG("ioctl GET_VRAM_INFO\n"); 851 DBG("ioctl GET_VRAM_INFO\n");
840 852
841 /* 853 omap_vram_get_info(&vram, &free, &largest);
842 * We don't have the ability to get this vram info anymore. 854 p.vram_info.total = vram;
843 * Fill in something that should keep the applications working. 855 p.vram_info.free = free;
844 */ 856 p.vram_info.largest_free_block = largest;
845 p.vram_info.total = SZ_1M * 64;
846 p.vram_info.free = SZ_1M * 64;
847 p.vram_info.largest_free_block = SZ_1M * 64;
848 857
849 if (copy_to_user((void __user *)arg, &p.vram_info, 858 if (copy_to_user((void __user *)arg, &p.vram_info,
850 sizeof(p.vram_info))) 859 sizeof(p.vram_info)))
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ca585ef37f2..602b71a92d3 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -31,7 +31,8 @@
31#include <linux/omapfb.h> 31#include <linux/omapfb.h>
32 32
33#include <video/omapdss.h> 33#include <video/omapdss.h>
34#include <video/omapvrfb.h> 34#include <plat/vram.h>
35#include <plat/vrfb.h>
35 36
36#include "omapfb.h" 37#include "omapfb.h"
37 38
@@ -42,18 +43,18 @@
42 43
43static char *def_mode; 44static char *def_mode;
44static char *def_vram; 45static char *def_vram;
45static bool def_vrfb; 46static int def_vrfb;
46static int def_rotate; 47static int def_rotate;
47static bool def_mirror; 48static int def_mirror;
48static bool auto_update; 49static bool auto_update;
49static unsigned int auto_update_freq; 50static unsigned int auto_update_freq;
50module_param(auto_update, bool, 0); 51module_param(auto_update, bool, 0);
51module_param(auto_update_freq, uint, 0644); 52module_param(auto_update_freq, uint, 0644);
52 53
53#ifdef DEBUG 54#ifdef DEBUG
54bool omapfb_debug; 55unsigned int omapfb_debug;
55module_param_named(debug, omapfb_debug, bool, 0644); 56module_param_named(debug, omapfb_debug, bool, 0644);
56static bool omapfb_test_pattern; 57static unsigned int omapfb_test_pattern;
57module_param_named(test, omapfb_test_pattern, bool, 0644); 58module_param_named(test, omapfb_test_pattern, bool, 0644);
58#endif 59#endif
59 60
@@ -178,7 +179,6 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
178 break; 179 break;
179 default: 180 default:
180 BUG(); 181 BUG();
181 return 0;
182 } 182 }
183 183
184 offset *= vrfb->bytespp; 184 offset *= vrfb->bytespp;
@@ -732,12 +732,6 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
732 var->lower_margin = timings.vfp; 732 var->lower_margin = timings.vfp;
733 var->hsync_len = timings.hsw; 733 var->hsync_len = timings.hsw;
734 var->vsync_len = timings.vsw; 734 var->vsync_len = timings.vsw;
735 var->sync |= timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
736 FB_SYNC_HOR_HIGH_ACT : 0;
737 var->sync |= timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH ?
738 FB_SYNC_VERT_HIGH_ACT : 0;
739 var->vmode = timings.interlace ?
740 FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
741 } else { 735 } else {
742 var->pixclock = 0; 736 var->pixclock = 0;
743 var->left_margin = 0; 737 var->left_margin = 0;
@@ -746,10 +740,12 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
746 var->lower_margin = 0; 740 var->lower_margin = 0;
747 var->hsync_len = 0; 741 var->hsync_len = 0;
748 var->vsync_len = 0; 742 var->vsync_len = 0;
749 var->sync = 0;
750 var->vmode = FB_VMODE_NONINTERLACED;
751 } 743 }
752 744
745 /* TODO: get these from panel->config */
746 var->vmode = FB_VMODE_NONINTERLACED;
747 var->sync = 0;
748
753 return 0; 749 return 0;
754} 750}
755 751
@@ -812,15 +808,19 @@ static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
812static void omapfb_calc_addr(const struct omapfb_info *ofbi, 808static void omapfb_calc_addr(const struct omapfb_info *ofbi,
813 const struct fb_var_screeninfo *var, 809 const struct fb_var_screeninfo *var,
814 const struct fb_fix_screeninfo *fix, 810 const struct fb_fix_screeninfo *fix,
815 int rotation, u32 *paddr) 811 int rotation, u32 *paddr, void __iomem **vaddr)
816{ 812{
817 u32 data_start_p; 813 u32 data_start_p;
814 void __iomem *data_start_v;
818 int offset; 815 int offset;
819 816
820 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 817 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
821 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation); 818 data_start_p = omapfb_get_region_rot_paddr(ofbi, rotation);
822 else 819 data_start_v = NULL;
820 } else {
823 data_start_p = omapfb_get_region_paddr(ofbi); 821 data_start_p = omapfb_get_region_paddr(ofbi);
822 data_start_v = omapfb_get_region_vaddr(ofbi);
823 }
824 824
825 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 825 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
826 offset = calc_rotation_offset_vrfb(var, fix, rotation); 826 offset = calc_rotation_offset_vrfb(var, fix, rotation);
@@ -828,14 +828,16 @@ static void omapfb_calc_addr(const struct omapfb_info *ofbi,
828 offset = calc_rotation_offset_dma(var, fix, rotation); 828 offset = calc_rotation_offset_dma(var, fix, rotation);
829 829
830 data_start_p += offset; 830 data_start_p += offset;
831 data_start_v += offset;
831 832
832 if (offset) 833 if (offset)
833 DBG("offset %d, %d = %d\n", 834 DBG("offset %d, %d = %d\n",
834 var->xoffset, var->yoffset, offset); 835 var->xoffset, var->yoffset, offset);
835 836
836 DBG("paddr %x\n", data_start_p); 837 DBG("paddr %x, vaddr %p\n", data_start_p, data_start_v);
837 838
838 *paddr = data_start_p; 839 *paddr = data_start_p;
840 *vaddr = data_start_v;
839} 841}
840 842
841/* setup overlay according to the fb */ 843/* setup overlay according to the fb */
@@ -848,6 +850,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
848 struct fb_fix_screeninfo *fix = &fbi->fix; 850 struct fb_fix_screeninfo *fix = &fbi->fix;
849 enum omap_color_mode mode = 0; 851 enum omap_color_mode mode = 0;
850 u32 data_start_p = 0; 852 u32 data_start_p = 0;
853 void __iomem *data_start_v = NULL;
851 struct omap_overlay_info info; 854 struct omap_overlay_info info;
852 int xres, yres; 855 int xres, yres;
853 int screen_width; 856 int screen_width;
@@ -877,7 +880,8 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
877 } 880 }
878 881
879 if (ofbi->region->size) 882 if (ofbi->region->size)
880 omapfb_calc_addr(ofbi, var, fix, rotation, &data_start_p); 883 omapfb_calc_addr(ofbi, var, fix, rotation,
884 &data_start_p, &data_start_v);
881 885
882 r = fb_mode_to_dss_mode(var, &mode); 886 r = fb_mode_to_dss_mode(var, &mode);
883 if (r) { 887 if (r) {
@@ -906,6 +910,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
906 mirror = ofbi->mirror; 910 mirror = ofbi->mirror;
907 911
908 info.paddr = data_start_p; 912 info.paddr = data_start_p;
913 info.vaddr = data_start_v;
909 info.screen_width = screen_width; 914 info.screen_width = screen_width;
910 info.width = xres; 915 info.width = xres;
911 info.height = yres; 916 info.height = yres;
@@ -974,20 +979,16 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
974 outh = var->yres; 979 outh = var->yres;
975 } 980 }
976 } else { 981 } else {
977 struct omap_overlay_info info; 982 outw = ovl->info.out_width;
978 ovl->get_overlay_info(ovl, &info); 983 outh = ovl->info.out_height;
979 outw = info.out_width;
980 outh = info.out_height;
981 } 984 }
982 985
983 if (init) { 986 if (init) {
984 posx = 0; 987 posx = 0;
985 posy = 0; 988 posy = 0;
986 } else { 989 } else {
987 struct omap_overlay_info info; 990 posx = ovl->info.pos_x;
988 ovl->get_overlay_info(ovl, &info); 991 posy = ovl->info.pos_y;
989 posx = info.pos_x;
990 posy = info.pos_y;
991 } 992 }
992 993
993 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); 994 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
@@ -1126,7 +1127,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
1126 DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off); 1127 DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
1127 1128
1128 vma->vm_pgoff = off >> PAGE_SHIFT; 1129 vma->vm_pgoff = off >> PAGE_SHIFT;
1129 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ 1130 vma->vm_flags |= VM_IO | VM_RESERVED;
1130 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); 1131 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
1131 vma->vm_ops = &mmap_user_ops; 1132 vma->vm_ops = &mmap_user_ops;
1132 vma->vm_private_data = rg; 1133 vma->vm_private_data = rg;
@@ -1191,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
1191 break; 1192 break;
1192 1193
1193 if (regno < 16) { 1194 if (regno < 16) {
1194 u32 pal; 1195 u16 pal;
1195 pal = ((red >> (16 - var->red.length)) << 1196 pal = ((red >> (16 - var->red.length)) <<
1196 var->red.offset) | 1197 var->red.offset) |
1197 ((green >> (16 - var->green.length)) << 1198 ((green >> (16 - var->green.length)) <<
@@ -1257,10 +1258,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1257 1258
1258 switch (blank) { 1259 switch (blank) {
1259 case FB_BLANK_UNBLANK: 1260 case FB_BLANK_UNBLANK:
1260 if (display->state == OMAP_DSS_DISPLAY_ACTIVE) 1261 if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
1261 goto exit; 1262 goto exit;
1262 1263
1263 r = display->driver->enable(display); 1264 if (display->driver->resume)
1265 r = display->driver->resume(display);
1264 1266
1265 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) && 1267 if ((display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) &&
1266 d->update_mode == OMAPFB_AUTO_UPDATE && 1268 d->update_mode == OMAPFB_AUTO_UPDATE &&
@@ -1281,7 +1283,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
1281 if (d->auto_update_work_enabled) 1283 if (d->auto_update_work_enabled)
1282 omapfb_stop_auto_update(fbdev, display); 1284 omapfb_stop_auto_update(fbdev, display);
1283 1285
1284 display->driver->disable(display); 1286 if (display->driver->suspend)
1287 r = display->driver->suspend(display);
1285 1288
1286 break; 1289 break;
1287 1290
@@ -1332,25 +1335,24 @@ static void omapfb_free_fbmem(struct fb_info *fbi)
1332 1335
1333 rg = ofbi->region; 1336 rg = ofbi->region;
1334 1337
1335 if (rg->token == NULL)
1336 return;
1337
1338 WARN_ON(atomic_read(&rg->map_count)); 1338 WARN_ON(atomic_read(&rg->map_count));
1339 1339
1340 if (rg->paddr)
1341 if (omap_vram_free(rg->paddr, rg->size))
1342 dev_err(fbdev->dev, "VRAM FREE failed\n");
1343
1344 if (rg->vaddr)
1345 iounmap(rg->vaddr);
1346
1340 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 1347 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
1341 /* unmap the 0 angle rotation */ 1348 /* unmap the 0 angle rotation */
1342 if (rg->vrfb.vaddr[0]) { 1349 if (rg->vrfb.vaddr[0]) {
1343 iounmap(rg->vrfb.vaddr[0]); 1350 iounmap(rg->vrfb.vaddr[0]);
1351 omap_vrfb_release_ctx(&rg->vrfb);
1344 rg->vrfb.vaddr[0] = NULL; 1352 rg->vrfb.vaddr[0] = NULL;
1345 } 1353 }
1346
1347 omap_vrfb_release_ctx(&rg->vrfb);
1348 } 1354 }
1349 1355
1350 dma_free_attrs(fbdev->dev, rg->size, rg->token, rg->dma_handle,
1351 &rg->attrs);
1352
1353 rg->token = NULL;
1354 rg->vaddr = NULL; 1356 rg->vaddr = NULL;
1355 rg->paddr = 0; 1357 rg->paddr = 0;
1356 rg->alloc = 0; 1358 rg->alloc = 0;
@@ -1385,9 +1387,7 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1385 struct omapfb_info *ofbi = FB2OFB(fbi); 1387 struct omapfb_info *ofbi = FB2OFB(fbi);
1386 struct omapfb2_device *fbdev = ofbi->fbdev; 1388 struct omapfb2_device *fbdev = ofbi->fbdev;
1387 struct omapfb2_mem_region *rg; 1389 struct omapfb2_mem_region *rg;
1388 void *token; 1390 void __iomem *vaddr;
1389 DEFINE_DMA_ATTRS(attrs);
1390 dma_addr_t dma_handle;
1391 int r; 1391 int r;
1392 1392
1393 rg = ofbi->region; 1393 rg = ofbi->region;
@@ -1402,40 +1402,42 @@ static int omapfb_alloc_fbmem(struct fb_info *fbi, unsigned long size,
1402 1402
1403 size = PAGE_ALIGN(size); 1403 size = PAGE_ALIGN(size);
1404 1404
1405 dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs); 1405 if (!paddr) {
1406 1406 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
1407 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) 1407 r = omap_vram_alloc(OMAP_VRAM_MEMTYPE_SDRAM, size, &paddr);
1408 dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); 1408 } else {
1409 1409 DBG("reserving %lu bytes at %lx for fb %d\n", size, paddr,
1410 DBG("allocating %lu bytes for fb %d\n", size, ofbi->id); 1410 ofbi->id);
1411 1411 r = omap_vram_reserve(paddr, size);
1412 token = dma_alloc_attrs(fbdev->dev, size, &dma_handle, 1412 }
1413 GFP_KERNEL, &attrs);
1414 1413
1415 if (token == NULL) { 1414 if (r) {
1416 dev_err(fbdev->dev, "failed to allocate framebuffer\n"); 1415 dev_err(fbdev->dev, "failed to allocate framebuffer\n");
1417 return -ENOMEM; 1416 return -ENOMEM;
1418 } 1417 }
1419 1418
1420 DBG("allocated VRAM paddr %lx, vaddr %p\n", 1419 if (ofbi->rotation_type != OMAP_DSS_ROT_VRFB) {
1421 (unsigned long)dma_handle, token); 1420 vaddr = ioremap_wc(paddr, size);
1422 1421
1423 if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) { 1422 if (!vaddr) {
1423 dev_err(fbdev->dev, "failed to ioremap framebuffer\n");
1424 omap_vram_free(paddr, size);
1425 return -ENOMEM;
1426 }
1427
1428 DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
1429 } else {
1424 r = omap_vrfb_request_ctx(&rg->vrfb); 1430 r = omap_vrfb_request_ctx(&rg->vrfb);
1425 if (r) { 1431 if (r) {
1426 dma_free_attrs(fbdev->dev, size, token, dma_handle,
1427 &attrs);
1428 dev_err(fbdev->dev, "vrfb create ctx failed\n"); 1432 dev_err(fbdev->dev, "vrfb create ctx failed\n");
1429 return r; 1433 return r;
1430 } 1434 }
1431 }
1432 1435
1433 rg->attrs = attrs; 1436 vaddr = NULL;
1434 rg->token = token; 1437 }
1435 rg->dma_handle = dma_handle;
1436 1438
1437 rg->paddr = (unsigned long)dma_handle; 1439 rg->paddr = paddr;
1438 rg->vaddr = (void __iomem *)token; 1440 rg->vaddr = vaddr;
1439 rg->size = size; 1441 rg->size = size;
1440 rg->alloc = 1; 1442 rg->alloc = 1;
1441 1443
@@ -1490,6 +1492,60 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
1490 return omapfb_alloc_fbmem(fbi, size, paddr); 1492 return omapfb_alloc_fbmem(fbi, size, paddr);
1491} 1493}
1492 1494
1495static enum omap_color_mode fb_format_to_dss_mode(enum omapfb_color_format fmt)
1496{
1497 enum omap_color_mode mode;
1498
1499 switch (fmt) {
1500 case OMAPFB_COLOR_RGB565:
1501 mode = OMAP_DSS_COLOR_RGB16;
1502 break;
1503 case OMAPFB_COLOR_YUV422:
1504 mode = OMAP_DSS_COLOR_YUV2;
1505 break;
1506 case OMAPFB_COLOR_CLUT_8BPP:
1507 mode = OMAP_DSS_COLOR_CLUT8;
1508 break;
1509 case OMAPFB_COLOR_CLUT_4BPP:
1510 mode = OMAP_DSS_COLOR_CLUT4;
1511 break;
1512 case OMAPFB_COLOR_CLUT_2BPP:
1513 mode = OMAP_DSS_COLOR_CLUT2;
1514 break;
1515 case OMAPFB_COLOR_CLUT_1BPP:
1516 mode = OMAP_DSS_COLOR_CLUT1;
1517 break;
1518 case OMAPFB_COLOR_RGB444:
1519 mode = OMAP_DSS_COLOR_RGB12U;
1520 break;
1521 case OMAPFB_COLOR_YUY422:
1522 mode = OMAP_DSS_COLOR_UYVY;
1523 break;
1524 case OMAPFB_COLOR_ARGB16:
1525 mode = OMAP_DSS_COLOR_ARGB16;
1526 break;
1527 case OMAPFB_COLOR_RGB24U:
1528 mode = OMAP_DSS_COLOR_RGB24U;
1529 break;
1530 case OMAPFB_COLOR_RGB24P:
1531 mode = OMAP_DSS_COLOR_RGB24P;
1532 break;
1533 case OMAPFB_COLOR_ARGB32:
1534 mode = OMAP_DSS_COLOR_ARGB32;
1535 break;
1536 case OMAPFB_COLOR_RGBA32:
1537 mode = OMAP_DSS_COLOR_RGBA32;
1538 break;
1539 case OMAPFB_COLOR_RGBX32:
1540 mode = OMAP_DSS_COLOR_RGBX32;
1541 break;
1542 default:
1543 mode = -EINVAL;
1544 }
1545
1546 return mode;
1547}
1548
1493static int omapfb_parse_vram_param(const char *param, int max_entries, 1549static int omapfb_parse_vram_param(const char *param, int max_entries,
1494 unsigned long *sizes, unsigned long *paddrs) 1550 unsigned long *sizes, unsigned long *paddrs)
1495{ 1551{
@@ -1505,7 +1561,7 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
1505 1561
1506 fbnum = simple_strtoul(p, &p, 10); 1562 fbnum = simple_strtoul(p, &p, 10);
1507 1563
1508 if (p == start) 1564 if (p == param)
1509 return -EINVAL; 1565 return -EINVAL;
1510 1566
1511 if (*p != ':') 1567 if (*p != ':')
@@ -1529,9 +1585,6 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
1529 1585
1530 } 1586 }
1531 1587
1532 WARN_ONCE(paddr,
1533 "reserving memory at predefined address not supported\n");
1534
1535 paddrs[fbnum] = paddr; 1588 paddrs[fbnum] = paddr;
1536 sizes[fbnum] = size; 1589 sizes[fbnum] = size;
1537 1590
@@ -1566,6 +1619,23 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1566 memset(&vram_paddrs, 0, sizeof(vram_paddrs)); 1619 memset(&vram_paddrs, 0, sizeof(vram_paddrs));
1567 } 1620 }
1568 1621
1622 if (fbdev->dev->platform_data) {
1623 struct omapfb_platform_data *opd;
1624 opd = fbdev->dev->platform_data;
1625 for (i = 0; i < opd->mem_desc.region_cnt; ++i) {
1626 if (!vram_sizes[i]) {
1627 unsigned long size;
1628 unsigned long paddr;
1629
1630 size = opd->mem_desc.region[i].size;
1631 paddr = opd->mem_desc.region[i].paddr;
1632
1633 vram_sizes[i] = size;
1634 vram_paddrs[i] = paddr;
1635 }
1636 }
1637 }
1638
1569 for (i = 0; i < fbdev->num_fbs; i++) { 1639 for (i = 0; i < fbdev->num_fbs; i++) {
1570 /* allocate memory automatically only for fb0, or if 1640 /* allocate memory automatically only for fb0, or if
1571 * excplicitly defined with vram or plat data option */ 1641 * excplicitly defined with vram or plat data option */
@@ -1593,31 +1663,18 @@ static int omapfb_allocate_all_fbs(struct omapfb2_device *fbdev)
1593 return 0; 1663 return 0;
1594} 1664}
1595 1665
1596static void omapfb_clear_fb(struct fb_info *fbi)
1597{
1598 const struct fb_fillrect rect = {
1599 .dx = 0,
1600 .dy = 0,
1601 .width = fbi->var.xres_virtual,
1602 .height = fbi->var.yres_virtual,
1603 .color = 0,
1604 .rop = ROP_COPY,
1605 };
1606
1607 cfb_fillrect(fbi, &rect);
1608}
1609
1610int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type) 1666int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1611{ 1667{
1612 struct omapfb_info *ofbi = FB2OFB(fbi); 1668 struct omapfb_info *ofbi = FB2OFB(fbi);
1613 struct omapfb2_device *fbdev = ofbi->fbdev; 1669 struct omapfb2_device *fbdev = ofbi->fbdev;
1670 struct omap_dss_device *display = fb2display(fbi);
1614 struct omapfb2_mem_region *rg = ofbi->region; 1671 struct omapfb2_mem_region *rg = ofbi->region;
1615 unsigned long old_size = rg->size; 1672 unsigned long old_size = rg->size;
1616 unsigned long old_paddr = rg->paddr; 1673 unsigned long old_paddr = rg->paddr;
1617 int old_type = rg->type; 1674 int old_type = rg->type;
1618 int r; 1675 int r;
1619 1676
1620 if (type != OMAPFB_MEMTYPE_SDRAM) 1677 if (type > OMAPFB_MEMTYPE_MAX)
1621 return -EINVAL; 1678 return -EINVAL;
1622 1679
1623 size = PAGE_ALIGN(size); 1680 size = PAGE_ALIGN(size);
@@ -1625,6 +1682,9 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1625 if (old_size == size && old_type == type) 1682 if (old_size == size && old_type == type)
1626 return 0; 1683 return 0;
1627 1684
1685 if (display && display->driver->sync)
1686 display->driver->sync(display);
1687
1628 omapfb_free_fbmem(fbi); 1688 omapfb_free_fbmem(fbi);
1629 1689
1630 if (size == 0) { 1690 if (size == 0) {
@@ -1672,8 +1732,6 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
1672 goto err; 1732 goto err;
1673 } 1733 }
1674 1734
1675 omapfb_clear_fb(fbi);
1676
1677 return 0; 1735 return 0;
1678err: 1736err:
1679 omapfb_free_fbmem(fbi); 1737 omapfb_free_fbmem(fbi);
@@ -1775,6 +1833,32 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
1775 1833
1776 var->rotate = def_rotate; 1834 var->rotate = def_rotate;
1777 1835
1836 /*
1837 * Check if there is a default color format set in the board file,
1838 * and use this format instead the default deducted from the
1839 * display bpp.
1840 */
1841 if (fbdev->dev->platform_data) {
1842 struct omapfb_platform_data *opd;
1843 int id = ofbi->id;
1844
1845 opd = fbdev->dev->platform_data;
1846 if (opd->mem_desc.region[id].format_used) {
1847 enum omap_color_mode mode;
1848 enum omapfb_color_format format;
1849
1850 format = opd->mem_desc.region[id].format;
1851 mode = fb_format_to_dss_mode(format);
1852 if (mode < 0) {
1853 r = mode;
1854 goto err;
1855 }
1856 r = dss_mode_to_fb_mode(mode, var);
1857 if (r < 0)
1858 goto err;
1859 }
1860 }
1861
1778 if (display) { 1862 if (display) {
1779 u16 w, h; 1863 u16 w, h;
1780 int rotation = (var->rotate + ofbi->rotation[0]) % 4; 1864 int rotation = (var->rotate + ofbi->rotation[0]) % 4;
@@ -1879,6 +1963,7 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
1879 } 1963 }
1880 1964
1881 dev_set_drvdata(fbdev->dev, NULL); 1965 dev_set_drvdata(fbdev->dev, NULL);
1966 kfree(fbdev);
1882} 1967}
1883 1968
1884static int omapfb_create_framebuffers(struct omapfb2_device *fbdev) 1969static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
@@ -1957,16 +2042,6 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
1957 } 2042 }
1958 } 2043 }
1959 2044
1960 for (i = 0; i < fbdev->num_fbs; i++) {
1961 struct fb_info *fbi = fbdev->fbs[i];
1962 struct omapfb_info *ofbi = FB2OFB(fbi);
1963
1964 if (ofbi->region->size == 0)
1965 continue;
1966
1967 omapfb_clear_fb(fbi);
1968 }
1969
1970 DBG("fb_infos initialized\n"); 2045 DBG("fb_infos initialized\n");
1971 2046
1972 for (i = 0; i < fbdev->num_fbs; i++) { 2047 for (i = 0; i < fbdev->num_fbs; i++) {
@@ -2001,8 +2076,6 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
2001 if (ofbi->num_overlays > 0) { 2076 if (ofbi->num_overlays > 0) {
2002 struct omap_overlay *ovl = ofbi->overlays[0]; 2077 struct omap_overlay *ovl = ofbi->overlays[0];
2003 2078
2004 ovl->manager->apply(ovl->manager);
2005
2006 r = omapfb_overlay_enable(ovl, 1); 2079 r = omapfb_overlay_enable(ovl, 1);
2007 2080
2008 if (r) { 2081 if (r) {
@@ -2019,7 +2092,6 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
2019} 2092}
2020 2093
2021static int omapfb_mode_to_timings(const char *mode_str, 2094static int omapfb_mode_to_timings(const char *mode_str,
2022 struct omap_dss_device *display,
2023 struct omap_video_timings *timings, u8 *bpp) 2095 struct omap_video_timings *timings, u8 *bpp)
2024{ 2096{
2025 struct fb_info *fbi; 2097 struct fb_info *fbi;
@@ -2073,14 +2145,6 @@ static int omapfb_mode_to_timings(const char *mode_str,
2073 goto err; 2145 goto err;
2074 } 2146 }
2075 2147
2076 if (display->driver->get_timings) {
2077 display->driver->get_timings(display, timings);
2078 } else {
2079 timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2080 timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2081 timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
2082 }
2083
2084 timings->pixel_clock = PICOS2KHZ(var->pixclock); 2148 timings->pixel_clock = PICOS2KHZ(var->pixclock);
2085 timings->hbp = var->left_margin; 2149 timings->hbp = var->left_margin;
2086 timings->hfp = var->right_margin; 2150 timings->hfp = var->right_margin;
@@ -2090,13 +2154,6 @@ static int omapfb_mode_to_timings(const char *mode_str,
2090 timings->vsw = var->vsync_len; 2154 timings->vsw = var->vsync_len;
2091 timings->x_res = var->xres; 2155 timings->x_res = var->xres;
2092 timings->y_res = var->yres; 2156 timings->y_res = var->yres;
2093 timings->hsync_level = var->sync & FB_SYNC_HOR_HIGH_ACT ?
2094 OMAPDSS_SIG_ACTIVE_HIGH :
2095 OMAPDSS_SIG_ACTIVE_LOW;
2096 timings->vsync_level = var->sync & FB_SYNC_VERT_HIGH_ACT ?
2097 OMAPDSS_SIG_ACTIVE_HIGH :
2098 OMAPDSS_SIG_ACTIVE_LOW;
2099 timings->interlace = var->vmode & FB_VMODE_INTERLACED;
2100 2157
2101 switch (var->bits_per_pixel) { 2158 switch (var->bits_per_pixel) {
2102 case 16: 2159 case 16:
@@ -2127,7 +2184,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
2127 struct omap_video_timings timings, temp_timings; 2184 struct omap_video_timings timings, temp_timings;
2128 struct omapfb_display_data *d; 2185 struct omapfb_display_data *d;
2129 2186
2130 r = omapfb_mode_to_timings(mode_str, display, &timings, &bpp); 2187 r = omapfb_mode_to_timings(mode_str, &timings, &bpp);
2131 if (r) 2188 if (r)
2132 return r; 2189 return r;
2133 2190
@@ -2219,110 +2276,6 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
2219 return r; 2276 return r;
2220} 2277}
2221 2278
2222static void fb_videomode_to_omap_timings(struct fb_videomode *m,
2223 struct omap_dss_device *display,
2224 struct omap_video_timings *t)
2225{
2226 if (display->driver->get_timings) {
2227 display->driver->get_timings(display, t);
2228 } else {
2229 t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
2230 t->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
2231 t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
2232 }
2233
2234 t->x_res = m->xres;
2235 t->y_res = m->yres;
2236 t->pixel_clock = PICOS2KHZ(m->pixclock);
2237 t->hsw = m->hsync_len;
2238 t->hfp = m->right_margin;
2239 t->hbp = m->left_margin;
2240 t->vsw = m->vsync_len;
2241 t->vfp = m->lower_margin;
2242 t->vbp = m->upper_margin;
2243 t->hsync_level = m->sync & FB_SYNC_HOR_HIGH_ACT ?
2244 OMAPDSS_SIG_ACTIVE_HIGH :
2245 OMAPDSS_SIG_ACTIVE_LOW;
2246 t->vsync_level = m->sync & FB_SYNC_VERT_HIGH_ACT ?
2247 OMAPDSS_SIG_ACTIVE_HIGH :
2248 OMAPDSS_SIG_ACTIVE_LOW;
2249 t->interlace = m->vmode & FB_VMODE_INTERLACED;
2250}
2251
2252static int omapfb_find_best_mode(struct omap_dss_device *display,
2253 struct omap_video_timings *timings)
2254{
2255 struct fb_monspecs *specs;
2256 u8 *edid;
2257 int r, i, best_idx, len;
2258
2259 if (!display->driver->read_edid)
2260 return -ENODEV;
2261
2262 len = 0x80 * 2;
2263 edid = kmalloc(len, GFP_KERNEL);
2264 if (edid == NULL)
2265 return -ENOMEM;
2266
2267 r = display->driver->read_edid(display, edid, len);
2268 if (r < 0)
2269 goto err1;
2270
2271 specs = kzalloc(sizeof(*specs), GFP_KERNEL);
2272 if (specs == NULL) {
2273 r = -ENOMEM;
2274 goto err1;
2275 }
2276
2277 fb_edid_to_monspecs(edid, specs);
2278
2279 best_idx = -1;
2280
2281 for (i = 0; i < specs->modedb_len; ++i) {
2282 struct fb_videomode *m;
2283 struct omap_video_timings t;
2284
2285 m = &specs->modedb[i];
2286
2287 if (m->pixclock == 0)
2288 continue;
2289
2290 /* skip repeated pixel modes */
2291 if (m->xres == 2880 || m->xres == 1440)
2292 continue;
2293
2294 if (m->vmode & FB_VMODE_INTERLACED ||
2295 m->vmode & FB_VMODE_DOUBLE)
2296 continue;
2297
2298 fb_videomode_to_omap_timings(m, display, &t);
2299
2300 r = display->driver->check_timings(display, &t);
2301 if (r == 0) {
2302 best_idx = i;
2303 break;
2304 }
2305 }
2306
2307 if (best_idx == -1) {
2308 r = -ENOENT;
2309 goto err2;
2310 }
2311
2312 fb_videomode_to_omap_timings(&specs->modedb[best_idx], display,
2313 timings);
2314
2315 r = 0;
2316
2317err2:
2318 fb_destroy_modedb(specs->modedb);
2319 kfree(specs);
2320err1:
2321 kfree(edid);
2322
2323 return r;
2324}
2325
2326static int omapfb_init_display(struct omapfb2_device *fbdev, 2279static int omapfb_init_display(struct omapfb2_device *fbdev,
2327 struct omap_dss_device *dssdev) 2280 struct omap_dss_device *dssdev)
2328{ 2281{
@@ -2373,60 +2326,12 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
2373 return 0; 2326 return 0;
2374} 2327}
2375 2328
2376static int omapfb_init_connections(struct omapfb2_device *fbdev, 2329static int omapfb_probe(struct platform_device *pdev)
2377 struct omap_dss_device *def_dssdev)
2378{
2379 int i, r;
2380 struct omap_overlay_manager *mgr;
2381
2382 if (!def_dssdev->output) {
2383 dev_err(fbdev->dev, "no output for the default display\n");
2384 return -EINVAL;
2385 }
2386
2387 for (i = 0; i < fbdev->num_displays; ++i) {
2388 struct omap_dss_device *dssdev = fbdev->displays[i].dssdev;
2389 struct omap_dss_output *out = dssdev->output;
2390
2391 mgr = omap_dss_get_overlay_manager(dssdev->channel);
2392
2393 if (!mgr || !out)
2394 continue;
2395
2396 if (mgr->output)
2397 mgr->unset_output(mgr);
2398
2399 mgr->set_output(mgr, out);
2400 }
2401
2402 mgr = def_dssdev->output->manager;
2403
2404 if (!mgr) {
2405 dev_err(fbdev->dev, "no ovl manager for the default display\n");
2406 return -EINVAL;
2407 }
2408
2409 for (i = 0; i < fbdev->num_overlays; i++) {
2410 struct omap_overlay *ovl = fbdev->overlays[i];
2411
2412 if (ovl->manager)
2413 ovl->unset_manager(ovl);
2414
2415 r = ovl->set_manager(ovl, mgr);
2416 if (r)
2417 dev_warn(fbdev->dev,
2418 "failed to connect overlay %s to manager %s\n",
2419 ovl->name, mgr->name);
2420 }
2421
2422 return 0;
2423}
2424
2425static int __init omapfb_probe(struct platform_device *pdev)
2426{ 2330{
2427 struct omapfb2_device *fbdev = NULL; 2331 struct omapfb2_device *fbdev = NULL;
2428 int r = 0; 2332 int r = 0;
2429 int i; 2333 int i;
2334 struct omap_overlay *ovl;
2430 struct omap_dss_device *def_display; 2335 struct omap_dss_device *def_display;
2431 struct omap_dss_device *dssdev; 2336 struct omap_dss_device *dssdev;
2432 2337
@@ -2438,28 +2343,28 @@ static int __init omapfb_probe(struct platform_device *pdev)
2438 goto err0; 2343 goto err0;
2439 } 2344 }
2440 2345
2441 fbdev = devm_kzalloc(&pdev->dev, sizeof(struct omapfb2_device), 2346 fbdev = kzalloc(sizeof(struct omapfb2_device), GFP_KERNEL);
2442 GFP_KERNEL);
2443 if (fbdev == NULL) { 2347 if (fbdev == NULL) {
2444 r = -ENOMEM; 2348 r = -ENOMEM;
2445 goto err0; 2349 goto err0;
2446 } 2350 }
2447 2351
2448 if (def_vrfb && !omap_vrfb_supported()) { 2352 /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
2353 * available for OMAP2 and OMAP3
2354 */
2355 if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
2449 def_vrfb = 0; 2356 def_vrfb = 0;
2450 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, " 2357 dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
2451 "ignoring the module parameter vrfb=y\n"); 2358 "ignoring the module parameter vrfb=y\n");
2452 } 2359 }
2453 2360
2454 r = omapdss_compat_init();
2455 if (r)
2456 goto err0;
2457 2361
2458 mutex_init(&fbdev->mtx); 2362 mutex_init(&fbdev->mtx);
2459 2363
2460 fbdev->dev = &pdev->dev; 2364 fbdev->dev = &pdev->dev;
2461 platform_set_drvdata(pdev, fbdev); 2365 platform_set_drvdata(pdev, fbdev);
2462 2366
2367 r = 0;
2463 fbdev->num_displays = 0; 2368 fbdev->num_displays = 0;
2464 dssdev = NULL; 2369 dssdev = NULL;
2465 for_each_dss_dev(dssdev) { 2370 for_each_dss_dev(dssdev) {
@@ -2468,10 +2373,8 @@ static int __init omapfb_probe(struct platform_device *pdev)
2468 omap_dss_get_device(dssdev); 2373 omap_dss_get_device(dssdev);
2469 2374
2470 if (!dssdev->driver) { 2375 if (!dssdev->driver) {
2471 dev_warn(&pdev->dev, "no driver for display: %s\n", 2376 dev_err(&pdev->dev, "no driver for display\n");
2472 dssdev->name); 2377 r = -ENODEV;
2473 omap_dss_put_device(dssdev);
2474 continue;
2475 } 2378 }
2476 2379
2477 d = &fbdev->displays[fbdev->num_displays++]; 2380 d = &fbdev->displays[fbdev->num_displays++];
@@ -2482,6 +2385,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
2482 d->update_mode = OMAPFB_AUTO_UPDATE; 2385 d->update_mode = OMAPFB_AUTO_UPDATE;
2483 } 2386 }
2484 2387
2388 if (r)
2389 goto cleanup;
2390
2485 if (fbdev->num_displays == 0) { 2391 if (fbdev->num_displays == 0) {
2486 dev_err(&pdev->dev, "no displays\n"); 2392 dev_err(&pdev->dev, "no displays\n");
2487 r = -EINVAL; 2393 r = -EINVAL;
@@ -2496,46 +2402,9 @@ static int __init omapfb_probe(struct platform_device *pdev)
2496 for (i = 0; i < fbdev->num_managers; i++) 2402 for (i = 0; i < fbdev->num_managers; i++)
2497 fbdev->managers[i] = omap_dss_get_overlay_manager(i); 2403 fbdev->managers[i] = omap_dss_get_overlay_manager(i);
2498 2404
2499 def_display = NULL;
2500
2501 for (i = 0; i < fbdev->num_displays; ++i) {
2502 struct omap_dss_device *dssdev;
2503 const char *def_name;
2504
2505 def_name = omapdss_get_default_display_name();
2506
2507 dssdev = fbdev->displays[i].dssdev;
2508
2509 if (def_name == NULL ||
2510 (dssdev->name && strcmp(def_name, dssdev->name) == 0)) {
2511 def_display = dssdev;
2512 break;
2513 }
2514 }
2515
2516 if (def_display == NULL) {
2517 dev_err(fbdev->dev, "failed to find default display\n");
2518 r = -EINVAL;
2519 goto cleanup;
2520 }
2521
2522 r = omapfb_init_connections(fbdev, def_display);
2523 if (r) {
2524 dev_err(fbdev->dev, "failed to init overlay connections\n");
2525 goto cleanup;
2526 }
2527
2528 if (def_mode && strlen(def_mode) > 0) { 2405 if (def_mode && strlen(def_mode) > 0) {
2529 if (omapfb_parse_def_modes(fbdev)) 2406 if (omapfb_parse_def_modes(fbdev))
2530 dev_warn(&pdev->dev, "cannot parse default modes\n"); 2407 dev_warn(&pdev->dev, "cannot parse default modes\n");
2531 } else if (def_display && def_display->driver->set_timings &&
2532 def_display->driver->check_timings) {
2533 struct omap_video_timings t;
2534
2535 r = omapfb_find_best_mode(def_display, &t);
2536
2537 if (r == 0)
2538 def_display->driver->set_timings(def_display, &t);
2539 } 2408 }
2540 2409
2541 r = omapfb_create_framebuffers(fbdev); 2410 r = omapfb_create_framebuffers(fbdev);
@@ -2552,6 +2421,16 @@ static int __init omapfb_probe(struct platform_device *pdev)
2552 2421
2553 DBG("mgr->apply'ed\n"); 2422 DBG("mgr->apply'ed\n");
2554 2423
2424 /* gfx overlay should be the default one. find a display
2425 * connected to that, and use it as default display */
2426 ovl = omap_dss_get_overlay(0);
2427 if (ovl->manager && ovl->manager->device) {
2428 def_display = ovl->manager->device;
2429 } else {
2430 dev_warn(&pdev->dev, "cannot find default display\n");
2431 def_display = NULL;
2432 }
2433
2555 if (def_display) { 2434 if (def_display) {
2556 r = omapfb_init_display(fbdev, def_display); 2435 r = omapfb_init_display(fbdev, def_display);
2557 if (r) { 2436 if (r) {
@@ -2573,13 +2452,12 @@ static int __init omapfb_probe(struct platform_device *pdev)
2573 2452
2574cleanup: 2453cleanup:
2575 omapfb_free_resources(fbdev); 2454 omapfb_free_resources(fbdev);
2576 omapdss_compat_uninit();
2577err0: 2455err0:
2578 dev_err(&pdev->dev, "failed to setup omapfb\n"); 2456 dev_err(&pdev->dev, "failed to setup omapfb\n");
2579 return r; 2457 return r;
2580} 2458}
2581 2459
2582static int __exit omapfb_remove(struct platform_device *pdev) 2460static int omapfb_remove(struct platform_device *pdev)
2583{ 2461{
2584 struct omapfb2_device *fbdev = platform_get_drvdata(pdev); 2462 struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2585 2463
@@ -2589,13 +2467,12 @@ static int __exit omapfb_remove(struct platform_device *pdev)
2589 2467
2590 omapfb_free_resources(fbdev); 2468 omapfb_free_resources(fbdev);
2591 2469
2592 omapdss_compat_uninit();
2593
2594 return 0; 2470 return 0;
2595} 2471}
2596 2472
2597static struct platform_driver omapfb_driver = { 2473static struct platform_driver omapfb_driver = {
2598 .remove = __exit_p(omapfb_remove), 2474 .probe = omapfb_probe,
2475 .remove = omapfb_remove,
2599 .driver = { 2476 .driver = {
2600 .name = "omapfb", 2477 .name = "omapfb",
2601 .owner = THIS_MODULE, 2478 .owner = THIS_MODULE,
@@ -2606,7 +2483,7 @@ static int __init omapfb_init(void)
2606{ 2483{
2607 DBG("omapfb_init\n"); 2484 DBG("omapfb_init\n");
2608 2485
2609 if (platform_driver_probe(&omapfb_driver, omapfb_probe)) { 2486 if (platform_driver_register(&omapfb_driver)) {
2610 printk(KERN_ERR "failed to register omapfb driver\n"); 2487 printk(KERN_ERR "failed to register omapfb driver\n");
2611 return -ENODEV; 2488 return -ENODEV;
2612 } 2489 }
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 18fa9e1d003..153bf1aceeb 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -30,7 +30,7 @@
30#include <linux/omapfb.h> 30#include <linux/omapfb.h>
31 31
32#include <video/omapdss.h> 32#include <video/omapdss.h>
33#include <video/omapvrfb.h> 33#include <plat/vrfb.h>
34 34
35#include "omapfb.h" 35#include "omapfb.h"
36 36
@@ -104,14 +104,16 @@ static ssize_t store_mirror(struct device *dev,
104{ 104{
105 struct fb_info *fbi = dev_get_drvdata(dev); 105 struct fb_info *fbi = dev_get_drvdata(dev);
106 struct omapfb_info *ofbi = FB2OFB(fbi); 106 struct omapfb_info *ofbi = FB2OFB(fbi);
107 bool mirror; 107 int mirror;
108 int r; 108 int r;
109 struct fb_var_screeninfo new_var; 109 struct fb_var_screeninfo new_var;
110 110
111 r = strtobool(buf, &mirror); 111 r = kstrtoint(buf, 0, &mirror);
112 if (r) 112 if (r)
113 return r; 113 return r;
114 114
115 mirror = !!mirror;
116
115 if (!lock_fb_info(fbi)) 117 if (!lock_fb_info(fbi))
116 return -ENODEV; 118 return -ENODEV;
117 119
@@ -441,7 +443,6 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
441 struct fb_info *fbi = dev_get_drvdata(dev); 443 struct fb_info *fbi = dev_get_drvdata(dev);
442 struct omapfb_info *ofbi = FB2OFB(fbi); 444 struct omapfb_info *ofbi = FB2OFB(fbi);
443 struct omapfb2_device *fbdev = ofbi->fbdev; 445 struct omapfb2_device *fbdev = ofbi->fbdev;
444 struct omap_dss_device *display = fb2display(fbi);
445 struct omapfb2_mem_region *rg; 446 struct omapfb2_mem_region *rg;
446 unsigned long size; 447 unsigned long size;
447 int r; 448 int r;
@@ -456,9 +457,6 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
456 if (!lock_fb_info(fbi)) 457 if (!lock_fb_info(fbi))
457 return -ENODEV; 458 return -ENODEV;
458 459
459 if (display && display->driver->sync)
460 display->driver->sync(display);
461
462 rg = ofbi->region; 460 rg = ofbi->region;
463 461
464 down_write_nested(&rg->lock, rg->id); 462 down_write_nested(&rg->lock, rg->id);
@@ -477,9 +475,7 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
477 continue; 475 continue;
478 476
479 for (j = 0; j < ofbi2->num_overlays; j++) { 477 for (j = 0; j < ofbi2->num_overlays; j++) {
480 struct omap_overlay *ovl; 478 if (ofbi2->overlays[j]->info.enabled) {
481 ovl = ofbi2->overlays[j];
482 if (ovl->is_enabled(ovl)) {
483 r = -EBUSY; 479 r = -EBUSY;
484 goto out; 480 goto out;
485 } 481 }
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index 623cd872a36..fdf0edeccf4 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -28,13 +28,11 @@
28#endif 28#endif
29 29
30#include <linux/rwsem.h> 30#include <linux/rwsem.h>
31#include <linux/dma-attrs.h>
32#include <linux/dma-mapping.h>
33 31
34#include <video/omapdss.h> 32#include <video/omapdss.h>
35 33
36#ifdef DEBUG 34#ifdef DEBUG
37extern bool omapfb_debug; 35extern unsigned int omapfb_debug;
38#define DBG(format, ...) \ 36#define DBG(format, ...) \
39 do { \ 37 do { \
40 if (omapfb_debug) \ 38 if (omapfb_debug) \
@@ -51,9 +49,6 @@ extern bool omapfb_debug;
51 49
52struct omapfb2_mem_region { 50struct omapfb2_mem_region {
53 int id; 51 int id;
54 struct dma_attrs attrs;
55 void *token;
56 dma_addr_t dma_handle;
57 u32 paddr; 52 u32 paddr;
58 void __iomem *vaddr; 53 void __iomem *vaddr;
59 struct vrfb vrfb; 54 struct vrfb vrfb;
@@ -129,6 +124,9 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
129 124
130int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg); 125int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
131 126
127int omapfb_update_window(struct fb_info *fbi,
128 u32 x, u32 y, u32 w, u32 h);
129
132int dss_mode_to_fb_mode(enum omap_color_mode dssmode, 130int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
133 struct fb_var_screeninfo *var); 131 struct fb_var_screeninfo *var);
134 132
@@ -146,16 +144,15 @@ int omapfb_set_update_mode(struct fb_info *fbi, enum omapfb_update_mode mode);
146static inline struct omap_dss_device *fb2display(struct fb_info *fbi) 144static inline struct omap_dss_device *fb2display(struct fb_info *fbi)
147{ 145{
148 struct omapfb_info *ofbi = FB2OFB(fbi); 146 struct omapfb_info *ofbi = FB2OFB(fbi);
149 struct omap_overlay *ovl; 147 int i;
150 148
151 /* XXX: returns the display connected to first attached overlay */ 149 /* XXX: returns the display connected to first attached overlay */
150 for (i = 0; i < ofbi->num_overlays; i++) {
151 if (ofbi->overlays[i]->manager)
152 return ofbi->overlays[i]->manager->device;
153 }
152 154
153 if (ofbi->num_overlays == 0) 155 return NULL;
154 return NULL;
155
156 ovl = ofbi->overlays[0];
157
158 return ovl->get_device(ovl);
159} 156}
160 157
161static inline struct omapfb_display_data *get_display_data( 158static inline struct omapfb_display_data *get_display_data(
@@ -169,7 +166,6 @@ static inline struct omapfb_display_data *get_display_data(
169 166
170 /* This should never happen */ 167 /* This should never happen */
171 BUG(); 168 BUG();
172 return NULL;
173} 169}
174 170
175static inline void omapfb_lock(struct omapfb2_device *fbdev) 171static inline void omapfb_lock(struct omapfb2_device *fbdev)
@@ -185,10 +181,13 @@ static inline void omapfb_unlock(struct omapfb2_device *fbdev)
185static inline int omapfb_overlay_enable(struct omap_overlay *ovl, 181static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
186 int enable) 182 int enable)
187{ 183{
188 if (enable) 184 struct omap_overlay_info info;
189 return ovl->enable(ovl); 185
190 else 186 ovl->get_overlay_info(ovl, &info);
191 return ovl->disable(ovl); 187 if (info.enabled == enable)
188 return 0;
189 info.enabled = enable;
190 return ovl->set_overlay_info(ovl, &info);
192} 191}
193 192
194static inline struct omapfb2_mem_region * 193static inline struct omapfb2_mem_region *
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 5d8fdac3b80..fd227160037 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,10 @@
26#include <linux/io.h> 26#include <linux/io.h>
27#include <linux/bitops.h> 27#include <linux/bitops.h>
28#include <linux/mutex.h> 28#include <linux/mutex.h>
29#include <linux/platform_device.h>
30 29
31#include <video/omapvrfb.h> 30#include <mach/io.h>
31#include <plat/vrfb.h>
32#include <plat/sdrc.h>
32 33
33#ifdef DEBUG 34#ifdef DEBUG
34#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__) 35#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +37,10 @@
36#define DBG(format, ...) 37#define DBG(format, ...)
37#endif 38#endif
38 39
39#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context) 40#define SMS_ROT_VIRT_BASE(context, rot) \
40#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context) 41 (((context >= 4) ? 0xD0000000 : 0x70000000) \
41#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context) 42 + (0x4000000 * (context)) \
42#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot)) 43 + (0x1000000 * (rot)))
43 44
44#define OMAP_VRFB_SIZE (2048 * 2048 * 4) 45#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
45 46
@@ -53,16 +54,10 @@
53#define SMS_PW_OFFSET 4 54#define SMS_PW_OFFSET 4
54#define SMS_PS_OFFSET 0 55#define SMS_PS_OFFSET 0
55 56
57#define VRFB_NUM_CTXS 12
56/* bitmap of reserved contexts */ 58/* bitmap of reserved contexts */
57static unsigned long ctx_map; 59static unsigned long ctx_map;
58 60
59struct vrfb_ctx {
60 u32 base;
61 u32 physical_ba;
62 u32 control;
63 u32 size;
64};
65
66static DEFINE_MUTEX(ctx_lock); 61static DEFINE_MUTEX(ctx_lock);
67 62
68/* 63/*
@@ -71,34 +66,17 @@ static DEFINE_MUTEX(ctx_lock);
71 * we don't need locking, since no drivers will run until after the wake-up 66 * we don't need locking, since no drivers will run until after the wake-up
72 * has finished. 67 * has finished.
73 */ 68 */
74 69static struct {
75static void __iomem *vrfb_base; 70 u32 physical_ba;
76 71 u32 control;
77static int num_ctxs; 72 u32 size;
78static struct vrfb_ctx *ctxs; 73} vrfb_hw_context[VRFB_NUM_CTXS];
79
80static bool vrfb_loaded;
81
82static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
83{
84 __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
85}
86
87static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
88{
89 __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
90}
91
92static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
93{
94 __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
95}
96 74
97static inline void restore_hw_context(int ctx) 75static inline void restore_hw_context(int ctx)
98{ 76{
99 omap2_sms_write_rot_control(ctxs[ctx].control, ctx); 77 omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
100 omap2_sms_write_rot_size(ctxs[ctx].size, ctx); 78 omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
101 omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx); 79 omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
102} 80}
103 81
104static u32 get_image_width_roundup(u16 width, u8 bytespp) 82static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -202,10 +180,8 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
202 pixel_size_exp = 2; 180 pixel_size_exp = 2;
203 else if (bytespp == 2) 181 else if (bytespp == 2)
204 pixel_size_exp = 1; 182 pixel_size_exp = 1;
205 else { 183 else
206 BUG(); 184 BUG();
207 return;
208 }
209 185
210 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; 186 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
211 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); 187 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
@@ -219,9 +195,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
219 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET; 195 control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
220 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET; 196 control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
221 197
222 ctxs[ctx].physical_ba = paddr; 198 vrfb_hw_context[ctx].physical_ba = paddr;
223 ctxs[ctx].size = size; 199 vrfb_hw_context[ctx].size = size;
224 ctxs[ctx].control = control; 200 vrfb_hw_context[ctx].control = control;
225 201
226 omap2_sms_write_rot_physical_ba(paddr, ctx); 202 omap2_sms_write_rot_physical_ba(paddr, ctx);
227 omap2_sms_write_rot_size(size, ctx); 203 omap2_sms_write_rot_size(size, ctx);
@@ -297,11 +273,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
297 273
298 mutex_lock(&ctx_lock); 274 mutex_lock(&ctx_lock);
299 275
300 for (ctx = 0; ctx < num_ctxs; ++ctx) 276 for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
301 if ((ctx_map & (1 << ctx)) == 0) 277 if ((ctx_map & (1 << ctx)) == 0)
302 break; 278 break;
303 279
304 if (ctx == num_ctxs) { 280 if (ctx == VRFB_NUM_CTXS) {
305 pr_err("vrfb: no free contexts\n"); 281 pr_err("vrfb: no free contexts\n");
306 r = -EBUSY; 282 r = -EBUSY;
307 goto out; 283 goto out;
@@ -316,7 +292,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
316 vrfb->context = ctx; 292 vrfb->context = ctx;
317 293
318 for (rot = 0; rot < 4; ++rot) { 294 for (rot = 0; rot < 4; ++rot) {
319 paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot); 295 paddr = SMS_ROT_VIRT_BASE(ctx, rot);
320 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) { 296 if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
321 pr_err("vrfb: failed to reserve VRFB " 297 pr_err("vrfb: failed to reserve VRFB "
322 "area for ctx %d, rotation %d\n", 298 "area for ctx %d, rotation %d\n",
@@ -337,80 +313,3 @@ out:
337 return r; 313 return r;
338} 314}
339EXPORT_SYMBOL(omap_vrfb_request_ctx); 315EXPORT_SYMBOL(omap_vrfb_request_ctx);
340
341bool omap_vrfb_supported(void)
342{
343 return vrfb_loaded;
344}
345EXPORT_SYMBOL(omap_vrfb_supported);
346
347static int __init vrfb_probe(struct platform_device *pdev)
348{
349 struct resource *mem;
350 int i;
351
352 /* first resource is the register res, the rest are vrfb contexts */
353
354 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
355 if (!mem) {
356 dev_err(&pdev->dev, "can't get vrfb base address\n");
357 return -EINVAL;
358 }
359
360 vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
361 if (!vrfb_base) {
362 dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
363 return -ENOMEM;
364 }
365
366 num_ctxs = pdev->num_resources - 1;
367
368 ctxs = devm_kzalloc(&pdev->dev,
369 sizeof(struct vrfb_ctx) * num_ctxs,
370 GFP_KERNEL);
371
372 if (!ctxs)
373 return -ENOMEM;
374
375 for (i = 0; i < num_ctxs; ++i) {
376 mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
377 if (!mem) {
378 dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
379 i);
380 return -EINVAL;
381 }
382
383 ctxs[i].base = mem->start;
384 }
385
386 vrfb_loaded = true;
387
388 return 0;
389}
390
391static void __exit vrfb_remove(struct platform_device *pdev)
392{
393 vrfb_loaded = false;
394}
395
396static struct platform_driver vrfb_driver = {
397 .driver.name = "omapvrfb",
398 .remove = __exit_p(vrfb_remove),
399};
400
401static int __init vrfb_init(void)
402{
403 return platform_driver_probe(&vrfb_driver, &vrfb_probe);
404}
405
406static void __exit vrfb_exit(void)
407{
408 platform_driver_unregister(&vrfb_driver);
409}
410
411module_init(vrfb_init);
412module_exit(vrfb_exit);
413
414MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
415MODULE_DESCRIPTION("OMAP VRFB");
416MODULE_LICENSE("GPL v2");