aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-05-27 16:58:20 -0400
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-05-27 16:58:20 -0400
commitd85d135d8babbc917b370f36cbc02b7b4a2f2d99 (patch)
tree2f06e02940d87099670aa31459ad1ab41a1ca036 /drivers/video
parent5e7b911f9a3e582635801675b7fe935b16cd4af5 (diff)
parente92a5b28f71aea01b281f9c89d97a4bc5b24748f (diff)
Merge tag 'omapdss-for-3.5' of git://github.com/tomba/linux into fbdev-next
Omapdss driver changes for 3.5 merge window. Lots of normal development commits, but perhaps most notable changes are: * HDMI rework to properly decouple the HDMI audio part from the HDMI video part. * Restructure omapdss core driver so that it's possible to implement device tree support. This included changing how platform data is passed to the drivers, changing display device registration and improving the panel driver's ability to configure the underlying video output interface. * Basic support for DSI packet interleaving
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap/Kconfig8
-rw-r--r--drivers/video/omap2/displays/Kconfig8
-rw-r--r--drivers/video/omap2/displays/Makefile2
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c7
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c107
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c8
-rw-r--r--drivers/video/omap2/displays/panel-taal.c108
-rw-r--r--drivers/video/omap2/displays/panel-tfp410.c (renamed from drivers/video/omap2/displays/panel-dvi.c)186
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c22
-rw-r--r--drivers/video/omap2/dss/Kconfig13
-rw-r--r--drivers/video/omap2/dss/apply.c134
-rw-r--r--drivers/video/omap2/dss/core.c255
-rw-r--r--drivers/video/omap2/dss/dispc.c747
-rw-r--r--drivers/video/omap2/dss/dispc.h72
-rw-r--r--drivers/video/omap2/dss/display.c49
-rw-r--r--drivers/video/omap2/dss/dpi.c75
-rw-r--r--drivers/video/omap2/dss/dsi.c537
-rw-r--r--drivers/video/omap2/dss/dss.c65
-rw-r--r--drivers/video/omap2/dss/dss.h151
-rw-r--r--drivers/video/omap2/dss/dss_features.c30
-rw-r--r--drivers/video/omap2/dss/dss_features.h5
-rw-r--r--drivers/video/omap2/dss/hdmi.c443
-rw-r--r--drivers/video/omap2/dss/hdmi_panel.c236
-rw-r--r--drivers/video/omap2/dss/manager.c19
-rw-r--r--drivers/video/omap2/dss/overlay.c16
-rw-r--r--drivers/video/omap2/dss/rfbi.c84
-rw-r--r--drivers/video/omap2/dss/sdi.c63
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h32
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c480
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h161
-rw-r--r--drivers/video/omap2/dss/venc.c133
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c17
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c12
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h1
-rw-r--r--drivers/video/omap2/vrfb.c4
35 files changed, 2651 insertions, 1639 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index 1e7536d9a8fc..b48f95f0dfe2 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -39,14 +39,6 @@ config FB_OMAP_LCD_MIPID
39 the Mobile Industry Processor Interface DBI-C/DCS 39 the Mobile Industry Processor Interface DBI-C/DCS
40 specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3) 40 specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
41 41
42config FB_OMAP_BOOTLOADER_INIT
43 bool "Check bootloader initialization"
44 depends on FB_OMAP
45 help
46 Say Y here if you want to enable checking if the bootloader has
47 already initialized the display controller. In this case the
48 driver will skip the initialization.
49
50config FB_OMAP_CONSISTENT_DMA_SIZE 42config FB_OMAP_CONSISTENT_DMA_SIZE
51 int "Consistent DMA memory size (MB)" 43 int "Consistent DMA memory size (MB)"
52 depends on FB_OMAP 44 depends on FB_OMAP
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 408a9927be92..c3853c92279b 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -10,12 +10,12 @@ 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_DVI 13config PANEL_TFP410
14 tristate "DVI output" 14 tristate "TFP410 DPI-to-DVI chip"
15 depends on OMAP2_DSS_DPI && I2C 15 depends on OMAP2_DSS_DPI && I2C
16 help 16 help
17 Driver for external monitors, connected via DVI. The driver uses i2c 17 Driver for TFP410 DPI-to-DVI chip. The driver uses i2c to read EDID
18 to read EDID information from the monitor. 18 information from the monitor.
19 19
20config PANEL_LGPHILIPS_LB035Q02 20config PANEL_LGPHILIPS_LB035Q02
21 tristate "LG.Philips LB035Q02 LCD Panel" 21 tristate "LG.Philips LB035Q02 LCD Panel"
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index fbfafc6eebb4..58a5176b07b0 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,5 +1,5 @@
1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o 1obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o
2obj-$(CONFIG_PANEL_DVI) += panel-dvi.o 2obj-$(CONFIG_PANEL_TFP410) += panel-tfp410.o
3obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o 3obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
4obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o 4obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
5obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o 5obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index d26f37ac69d8..c98f2c16f744 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -738,12 +738,6 @@ static void acx_panel_set_timings(struct omap_dss_device *dssdev,
738 } 738 }
739} 739}
740 740
741static void acx_panel_get_timings(struct omap_dss_device *dssdev,
742 struct omap_video_timings *timings)
743{
744 *timings = dssdev->panel.timings;
745}
746
747static int acx_panel_check_timings(struct omap_dss_device *dssdev, 741static int acx_panel_check_timings(struct omap_dss_device *dssdev,
748 struct omap_video_timings *timings) 742 struct omap_video_timings *timings)
749{ 743{
@@ -761,7 +755,6 @@ static struct omap_dss_driver acx_panel_driver = {
761 .resume = acx_panel_resume, 755 .resume = acx_panel_resume,
762 756
763 .set_timings = acx_panel_set_timings, 757 .set_timings = acx_panel_set_timings,
764 .get_timings = acx_panel_get_timings,
765 .check_timings = acx_panel_check_timings, 758 .check_timings = acx_panel_check_timings,
766 759
767 .get_recommended_bpp = acx_get_recommended_bpp, 760 .get_recommended_bpp = acx_get_recommended_bpp,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 30fe4dfeb227..e42f9dc22123 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -386,6 +386,106 @@ static struct panel_config generic_dpi_panels[] = {
386 386
387 .name = "innolux_at080tn52", 387 .name = "innolux_at080tn52",
388 }, 388 },
389
390 /* Mitsubishi AA084SB01 */
391 {
392 {
393 .x_res = 800,
394 .y_res = 600,
395 .pixel_clock = 40000,
396
397 .hsw = 1,
398 .hfp = 254,
399 .hbp = 1,
400
401 .vsw = 1,
402 .vfp = 26,
403 .vbp = 1,
404 },
405 .config = OMAP_DSS_LCD_TFT,
406 .name = "mitsubishi_aa084sb01",
407 },
408 /* EDT ET0500G0DH6 */
409 {
410 {
411 .x_res = 800,
412 .y_res = 480,
413 .pixel_clock = 33260,
414
415 .hsw = 128,
416 .hfp = 216,
417 .hbp = 40,
418
419 .vsw = 2,
420 .vfp = 35,
421 .vbp = 10,
422 },
423 .config = OMAP_DSS_LCD_TFT,
424 .name = "edt_et0500g0dh6",
425 },
426
427 /* Prime-View PD050VL1 */
428 {
429 {
430 .x_res = 640,
431 .y_res = 480,
432
433 .pixel_clock = 25000,
434
435 .hsw = 96,
436 .hfp = 18,
437 .hbp = 46,
438
439 .vsw = 2,
440 .vfp = 10,
441 .vbp = 33,
442 },
443 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
444 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
445 .name = "primeview_pd050vl1",
446 },
447
448 /* Prime-View PM070WL4 */
449 {
450 {
451 .x_res = 800,
452 .y_res = 480,
453
454 .pixel_clock = 32000,
455
456 .hsw = 128,
457 .hfp = 42,
458 .hbp = 86,
459
460 .vsw = 2,
461 .vfp = 10,
462 .vbp = 33,
463 },
464 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
465 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
466 .name = "primeview_pm070wl4",
467 },
468
469 /* Prime-View PD104SLF */
470 {
471 {
472 .x_res = 800,
473 .y_res = 600,
474
475 .pixel_clock = 40000,
476
477 .hsw = 128,
478 .hfp = 42,
479 .hbp = 86,
480
481 .vsw = 4,
482 .vfp = 1,
483 .vbp = 23,
484 },
485 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
486 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
487 .name = "primeview_pd104slf",
488 },
389}; 489};
390 490
391struct panel_drv_data { 491struct panel_drv_data {
@@ -549,12 +649,6 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
549 dpi_set_timings(dssdev, timings); 649 dpi_set_timings(dssdev, timings);
550} 650}
551 651
552static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
553 struct omap_video_timings *timings)
554{
555 *timings = dssdev->panel.timings;
556}
557
558static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev, 652static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
559 struct omap_video_timings *timings) 653 struct omap_video_timings *timings)
560{ 654{
@@ -571,7 +665,6 @@ static struct omap_dss_driver dpi_driver = {
571 .resume = generic_dpi_panel_resume, 665 .resume = generic_dpi_panel_resume,
572 666
573 .set_timings = generic_dpi_panel_set_timings, 667 .set_timings = generic_dpi_panel_set_timings,
574 .get_timings = generic_dpi_panel_get_timings,
575 .check_timings = generic_dpi_panel_check_timings, 668 .check_timings = generic_dpi_panel_check_timings,
576 669
577 .driver = { 670 .driver = {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index dc9408dc93d1..4a34cdc1371b 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -610,12 +610,6 @@ static int n8x0_panel_resume(struct omap_dss_device *dssdev)
610 return 0; 610 return 0;
611} 611}
612 612
613static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
614 struct omap_video_timings *timings)
615{
616 *timings = dssdev->panel.timings;
617}
618
619static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev, 613static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
620 u16 *xres, u16 *yres) 614 u16 *xres, u16 *yres)
621{ 615{
@@ -678,8 +672,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
678 .get_resolution = n8x0_panel_get_resolution, 672 .get_resolution = n8x0_panel_get_resolution,
679 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 673 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
680 674
681 .get_timings = n8x0_panel_get_timings,
682
683 .driver = { 675 .driver = {
684 .name = "n8x0_panel", 676 .name = "n8x0_panel",
685 .owner = THIS_MODULE, 677 .owner = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 0f21fa5a16ae..2ce9992f403b 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -30,7 +30,6 @@
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>
34#include <linux/mutex.h> 33#include <linux/mutex.h>
35 34
36#include <video/omapdss.h> 35#include <video/omapdss.h>
@@ -55,73 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
55 54
56static int taal_panel_reset(struct omap_dss_device *dssdev); 55static int taal_panel_reset(struct omap_dss_device *dssdev);
57 56
58struct panel_regulator {
59 struct regulator *regulator;
60 const char *name;
61 int min_uV;
62 int max_uV;
63};
64
65static void free_regulators(struct panel_regulator *regulators, int n)
66{
67 int i;
68
69 for (i = 0; i < n; i++) {
70 /* disable/put in reverse order */
71 regulator_disable(regulators[n - i - 1].regulator);
72 regulator_put(regulators[n - i - 1].regulator);
73 }
74}
75
76static int init_regulators(struct omap_dss_device *dssdev,
77 struct panel_regulator *regulators, int n)
78{
79 int r, i, v;
80
81 for (i = 0; i < n; i++) {
82 struct regulator *reg;
83
84 reg = regulator_get(&dssdev->dev, regulators[i].name);
85 if (IS_ERR(reg)) {
86 dev_err(&dssdev->dev, "failed to get regulator %s\n",
87 regulators[i].name);
88 r = PTR_ERR(reg);
89 goto err;
90 }
91
92 /* FIXME: better handling of fixed vs. variable regulators */
93 v = regulator_get_voltage(reg);
94 if (v < regulators[i].min_uV || v > regulators[i].max_uV) {
95 r = regulator_set_voltage(reg, regulators[i].min_uV,
96 regulators[i].max_uV);
97 if (r) {
98 dev_err(&dssdev->dev,
99 "failed to set regulator %s voltage\n",
100 regulators[i].name);
101 regulator_put(reg);
102 goto err;
103 }
104 }
105
106 r = regulator_enable(reg);
107 if (r) {
108 dev_err(&dssdev->dev, "failed to enable regulator %s\n",
109 regulators[i].name);
110 regulator_put(reg);
111 goto err;
112 }
113
114 regulators[i].regulator = reg;
115 }
116
117 return 0;
118
119err:
120 free_regulators(regulators, i);
121
122 return r;
123}
124
125/** 57/**
126 * struct panel_config - panel configuration 58 * struct panel_config - panel configuration
127 * @name: panel name 59 * @name: panel name
@@ -150,8 +82,6 @@ struct panel_config {
150 unsigned int low; 82 unsigned int low;
151 } reset_sequence; 83 } reset_sequence;
152 84
153 struct panel_regulator *regulators;
154 int num_regulators;
155}; 85};
156 86
157enum { 87enum {
@@ -577,12 +507,6 @@ static const struct backlight_ops taal_bl_ops = {
577 .update_status = taal_bl_update_status, 507 .update_status = taal_bl_update_status,
578}; 508};
579 509
580static void taal_get_timings(struct omap_dss_device *dssdev,
581 struct omap_video_timings *timings)
582{
583 *timings = dssdev->panel.timings;
584}
585
586static void taal_get_resolution(struct omap_dss_device *dssdev, 510static void taal_get_resolution(struct omap_dss_device *dssdev,
587 u16 *xres, u16 *yres) 511 u16 *xres, u16 *yres)
588{ 512{
@@ -977,11 +901,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
977 901
978 atomic_set(&td->do_update, 0); 902 atomic_set(&td->do_update, 0);
979 903
980 r = init_regulators(dssdev, panel_config->regulators,
981 panel_config->num_regulators);
982 if (r)
983 goto err_reg;
984
985 td->workqueue = create_singlethread_workqueue("taal_esd"); 904 td->workqueue = create_singlethread_workqueue("taal_esd");
986 if (td->workqueue == NULL) { 905 if (td->workqueue == NULL) {
987 dev_err(&dssdev->dev, "can't create ESD workqueue\n"); 906 dev_err(&dssdev->dev, "can't create ESD workqueue\n");
@@ -993,6 +912,15 @@ static int taal_probe(struct omap_dss_device *dssdev)
993 912
994 dev_set_drvdata(&dssdev->dev, td); 913 dev_set_drvdata(&dssdev->dev, td);
995 914
915 if (gpio_is_valid(panel_data->reset_gpio)) {
916 r = gpio_request_one(panel_data->reset_gpio, GPIOF_OUT_INIT_LOW,
917 "taal rst");
918 if (r) {
919 dev_err(&dssdev->dev, "failed to request reset gpio\n");
920 goto err_rst_gpio;
921 }
922 }
923
996 taal_hw_reset(dssdev); 924 taal_hw_reset(dssdev);
997 925
998 if (panel_data->use_dsi_backlight) { 926 if (panel_data->use_dsi_backlight) {
@@ -1073,10 +1001,11 @@ err_gpio:
1073 if (bldev != NULL) 1001 if (bldev != NULL)
1074 backlight_device_unregister(bldev); 1002 backlight_device_unregister(bldev);
1075err_bl: 1003err_bl:
1004 if (gpio_is_valid(panel_data->reset_gpio))
1005 gpio_free(panel_data->reset_gpio);
1006err_rst_gpio:
1076 destroy_workqueue(td->workqueue); 1007 destroy_workqueue(td->workqueue);
1077err_wq: 1008err_wq:
1078 free_regulators(panel_config->regulators, panel_config->num_regulators);
1079err_reg:
1080 kfree(td); 1009 kfree(td);
1081err: 1010err:
1082 return r; 1011 return r;
@@ -1113,8 +1042,8 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1113 /* reset, to be sure that the panel is in a valid state */ 1042 /* reset, to be sure that the panel is in a valid state */
1114 taal_hw_reset(dssdev); 1043 taal_hw_reset(dssdev);
1115 1044
1116 free_regulators(td->panel_config->regulators, 1045 if (gpio_is_valid(panel_data->reset_gpio))
1117 td->panel_config->num_regulators); 1046 gpio_free(panel_data->reset_gpio);
1118 1047
1119 kfree(td); 1048 kfree(td);
1120} 1049}
@@ -1122,9 +1051,16 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
1122static int taal_power_on(struct omap_dss_device *dssdev) 1051static int taal_power_on(struct omap_dss_device *dssdev)
1123{ 1052{
1124 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1053 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1054 struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
1125 u8 id1, id2, id3; 1055 u8 id1, id2, id3;
1126 int r; 1056 int r;
1127 1057
1058 r = omapdss_dsi_configure_pins(dssdev, &panel_data->pin_config);
1059 if (r) {
1060 dev_err(&dssdev->dev, "failed to configure DSI pins\n");
1061 goto err0;
1062 };
1063
1128 r = omapdss_dsi_display_enable(dssdev); 1064 r = omapdss_dsi_display_enable(dssdev);
1129 if (r) { 1065 if (r) {
1130 dev_err(&dssdev->dev, "failed to enable DSI\n"); 1066 dev_err(&dssdev->dev, "failed to enable DSI\n");
@@ -1887,8 +1823,6 @@ static struct omap_dss_driver taal_driver = {
1887 .run_test = taal_run_test, 1823 .run_test = taal_run_test,
1888 .memory_read = taal_memory_read, 1824 .memory_read = taal_memory_read,
1889 1825
1890 .get_timings = taal_get_timings,
1891
1892 .driver = { 1826 .driver = {
1893 .name = "taal", 1827 .name = "taal",
1894 .owner = THIS_MODULE, 1828 .owner = THIS_MODULE,
diff --git a/drivers/video/omap2/displays/panel-dvi.c b/drivers/video/omap2/displays/panel-tfp410.c
index 03eb14af33e0..bff306e041ca 100644
--- a/drivers/video/omap2/displays/panel-dvi.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * DVI output support 2 * TFP410 DPI-to-DVI chip
3 * 3 *
4 * Copyright (C) 2011 Texas Instruments Inc 4 * Copyright (C) 2011 Texas Instruments Inc
5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> 5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
@@ -21,11 +21,12 @@
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <video/omapdss.h> 22#include <video/omapdss.h>
23#include <linux/i2c.h> 23#include <linux/i2c.h>
24#include <linux/gpio.h>
24#include <drm/drm_edid.h> 25#include <drm/drm_edid.h>
25 26
26#include <video/omap-panel-dvi.h> 27#include <video/omap-panel-tfp410.h>
27 28
28static const struct omap_video_timings panel_dvi_default_timings = { 29static const struct omap_video_timings tfp410_default_timings = {
29 .x_res = 640, 30 .x_res = 640,
30 .y_res = 480, 31 .y_res = 480,
31 32
@@ -44,17 +45,15 @@ struct panel_drv_data {
44 struct omap_dss_device *dssdev; 45 struct omap_dss_device *dssdev;
45 46
46 struct mutex lock; 47 struct mutex lock;
47};
48 48
49static inline struct panel_dvi_platform_data 49 int pd_gpio;
50*get_pdata(const struct omap_dss_device *dssdev) 50
51{ 51 struct i2c_adapter *i2c_adapter;
52 return dssdev->data; 52};
53}
54 53
55static int panel_dvi_power_on(struct omap_dss_device *dssdev) 54static int tfp410_power_on(struct omap_dss_device *dssdev)
56{ 55{
57 struct panel_dvi_platform_data *pdata = get_pdata(dssdev); 56 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
58 int r; 57 int r;
59 58
60 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 59 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
@@ -64,72 +63,111 @@ static int panel_dvi_power_on(struct omap_dss_device *dssdev)
64 if (r) 63 if (r)
65 goto err0; 64 goto err0;
66 65
67 if (pdata->platform_enable) { 66 if (gpio_is_valid(ddata->pd_gpio))
68 r = pdata->platform_enable(dssdev); 67 gpio_set_value_cansleep(ddata->pd_gpio, 1);
69 if (r)
70 goto err1;
71 }
72 68
73 return 0; 69 return 0;
74err1:
75 omapdss_dpi_display_disable(dssdev);
76err0: 70err0:
77 return r; 71 return r;
78} 72}
79 73
80static void panel_dvi_power_off(struct omap_dss_device *dssdev) 74static void tfp410_power_off(struct omap_dss_device *dssdev)
81{ 75{
82 struct panel_dvi_platform_data *pdata = get_pdata(dssdev); 76 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
83 77
84 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 78 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
85 return; 79 return;
86 80
87 if (pdata->platform_disable) 81 if (gpio_is_valid(ddata->pd_gpio))
88 pdata->platform_disable(dssdev); 82 gpio_set_value_cansleep(ddata->pd_gpio, 0);
89 83
90 omapdss_dpi_display_disable(dssdev); 84 omapdss_dpi_display_disable(dssdev);
91} 85}
92 86
93static int panel_dvi_probe(struct omap_dss_device *dssdev) 87static int tfp410_probe(struct omap_dss_device *dssdev)
94{ 88{
95 struct panel_drv_data *ddata; 89 struct panel_drv_data *ddata;
90 int r;
91 int i2c_bus_num;
96 92
97 ddata = kzalloc(sizeof(*ddata), GFP_KERNEL); 93 ddata = devm_kzalloc(&dssdev->dev, sizeof(*ddata), GFP_KERNEL);
98 if (!ddata) 94 if (!ddata)
99 return -ENOMEM; 95 return -ENOMEM;
100 96
101 dssdev->panel.timings = panel_dvi_default_timings; 97 dssdev->panel.timings = tfp410_default_timings;
102 dssdev->panel.config = OMAP_DSS_LCD_TFT; 98 dssdev->panel.config = OMAP_DSS_LCD_TFT;
103 99
104 ddata->dssdev = dssdev; 100 ddata->dssdev = dssdev;
105 mutex_init(&ddata->lock); 101 mutex_init(&ddata->lock);
106 102
103 if (dssdev->data) {
104 struct tfp410_platform_data *pdata = dssdev->data;
105
106 ddata->pd_gpio = pdata->power_down_gpio;
107 i2c_bus_num = pdata->i2c_bus_num;
108 } else {
109 ddata->pd_gpio = -1;
110 i2c_bus_num = -1;
111 }
112
113 if (gpio_is_valid(ddata->pd_gpio)) {
114 r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
115 "tfp410 pd");
116 if (r) {
117 dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
118 ddata->pd_gpio);
119 return r;
120 }
121 }
122
123 if (i2c_bus_num != -1) {
124 struct i2c_adapter *adapter;
125
126 adapter = i2c_get_adapter(i2c_bus_num);
127 if (!adapter) {
128 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
129 i2c_bus_num);
130 r = -EINVAL;
131 goto err_i2c;
132 }
133
134 ddata->i2c_adapter = adapter;
135 }
136
107 dev_set_drvdata(&dssdev->dev, ddata); 137 dev_set_drvdata(&dssdev->dev, ddata);
108 138
109 return 0; 139 return 0;
140err_i2c:
141 if (gpio_is_valid(ddata->pd_gpio))
142 gpio_free(ddata->pd_gpio);
143 return r;
110} 144}
111 145
112static void __exit panel_dvi_remove(struct omap_dss_device *dssdev) 146static void __exit tfp410_remove(struct omap_dss_device *dssdev)
113{ 147{
114 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 148 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
115 149
116 mutex_lock(&ddata->lock); 150 mutex_lock(&ddata->lock);
117 151
152 if (ddata->i2c_adapter)
153 i2c_put_adapter(ddata->i2c_adapter);
154
155 if (gpio_is_valid(ddata->pd_gpio))
156 gpio_free(ddata->pd_gpio);
157
118 dev_set_drvdata(&dssdev->dev, NULL); 158 dev_set_drvdata(&dssdev->dev, NULL);
119 159
120 mutex_unlock(&ddata->lock); 160 mutex_unlock(&ddata->lock);
121
122 kfree(ddata);
123} 161}
124 162
125static int panel_dvi_enable(struct omap_dss_device *dssdev) 163static int tfp410_enable(struct omap_dss_device *dssdev)
126{ 164{
127 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 165 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
128 int r; 166 int r;
129 167
130 mutex_lock(&ddata->lock); 168 mutex_lock(&ddata->lock);
131 169
132 r = panel_dvi_power_on(dssdev); 170 r = tfp410_power_on(dssdev);
133 if (r == 0) 171 if (r == 0)
134 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 172 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
135 173
@@ -138,26 +176,26 @@ static int panel_dvi_enable(struct omap_dss_device *dssdev)
138 return r; 176 return r;
139} 177}
140 178
141static void panel_dvi_disable(struct omap_dss_device *dssdev) 179static void tfp410_disable(struct omap_dss_device *dssdev)
142{ 180{
143 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 181 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
144 182
145 mutex_lock(&ddata->lock); 183 mutex_lock(&ddata->lock);
146 184
147 panel_dvi_power_off(dssdev); 185 tfp410_power_off(dssdev);
148 186
149 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 187 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
150 188
151 mutex_unlock(&ddata->lock); 189 mutex_unlock(&ddata->lock);
152} 190}
153 191
154static int panel_dvi_suspend(struct omap_dss_device *dssdev) 192static int tfp410_suspend(struct omap_dss_device *dssdev)
155{ 193{
156 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 194 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
157 195
158 mutex_lock(&ddata->lock); 196 mutex_lock(&ddata->lock);
159 197
160 panel_dvi_power_off(dssdev); 198 tfp410_power_off(dssdev);
161 199
162 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 200 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
163 201
@@ -166,14 +204,14 @@ static int panel_dvi_suspend(struct omap_dss_device *dssdev)
166 return 0; 204 return 0;
167} 205}
168 206
169static int panel_dvi_resume(struct omap_dss_device *dssdev) 207static int tfp410_resume(struct omap_dss_device *dssdev)
170{ 208{
171 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 209 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
172 int r; 210 int r;
173 211
174 mutex_lock(&ddata->lock); 212 mutex_lock(&ddata->lock);
175 213
176 r = panel_dvi_power_on(dssdev); 214 r = tfp410_power_on(dssdev);
177 if (r == 0) 215 if (r == 0)
178 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 216 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
179 217
@@ -182,7 +220,7 @@ static int panel_dvi_resume(struct omap_dss_device *dssdev)
182 return r; 220 return r;
183} 221}
184 222
185static void panel_dvi_set_timings(struct omap_dss_device *dssdev, 223static void tfp410_set_timings(struct omap_dss_device *dssdev,
186 struct omap_video_timings *timings) 224 struct omap_video_timings *timings)
187{ 225{
188 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 226 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
@@ -192,7 +230,7 @@ static void panel_dvi_set_timings(struct omap_dss_device *dssdev,
192 mutex_unlock(&ddata->lock); 230 mutex_unlock(&ddata->lock);
193} 231}
194 232
195static void panel_dvi_get_timings(struct omap_dss_device *dssdev, 233static void tfp410_get_timings(struct omap_dss_device *dssdev,
196 struct omap_video_timings *timings) 234 struct omap_video_timings *timings)
197{ 235{
198 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 236 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
@@ -202,7 +240,7 @@ static void panel_dvi_get_timings(struct omap_dss_device *dssdev,
202 mutex_unlock(&ddata->lock); 240 mutex_unlock(&ddata->lock);
203} 241}
204 242
205static int panel_dvi_check_timings(struct omap_dss_device *dssdev, 243static int tfp410_check_timings(struct omap_dss_device *dssdev,
206 struct omap_video_timings *timings) 244 struct omap_video_timings *timings)
207{ 245{
208 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 246 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
@@ -216,7 +254,7 @@ static int panel_dvi_check_timings(struct omap_dss_device *dssdev,
216} 254}
217 255
218 256
219static int panel_dvi_ddc_read(struct i2c_adapter *adapter, 257static int tfp410_ddc_read(struct i2c_adapter *adapter,
220 unsigned char *buf, u16 count, u8 offset) 258 unsigned char *buf, u16 count, u8 offset)
221{ 259{
222 int r, retries; 260 int r, retries;
@@ -247,31 +285,21 @@ static int panel_dvi_ddc_read(struct i2c_adapter *adapter,
247 return r < 0 ? r : -EIO; 285 return r < 0 ? r : -EIO;
248} 286}
249 287
250static int panel_dvi_read_edid(struct omap_dss_device *dssdev, 288static int tfp410_read_edid(struct omap_dss_device *dssdev,
251 u8 *edid, int len) 289 u8 *edid, int len)
252{ 290{
253 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 291 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
254 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
255 struct i2c_adapter *adapter;
256 int r, l, bytes_read; 292 int r, l, bytes_read;
257 293
258 mutex_lock(&ddata->lock); 294 mutex_lock(&ddata->lock);
259 295
260 if (pdata->i2c_bus_num == 0) { 296 if (!ddata->i2c_adapter) {
261 r = -ENODEV; 297 r = -ENODEV;
262 goto err; 298 goto err;
263 } 299 }
264 300
265 adapter = i2c_get_adapter(pdata->i2c_bus_num);
266 if (!adapter) {
267 dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
268 pdata->i2c_bus_num);
269 r = -EINVAL;
270 goto err;
271 }
272
273 l = min(EDID_LENGTH, len); 301 l = min(EDID_LENGTH, len);
274 r = panel_dvi_ddc_read(adapter, edid, l, 0); 302 r = tfp410_ddc_read(ddata->i2c_adapter, edid, l, 0);
275 if (r) 303 if (r)
276 goto err; 304 goto err;
277 305
@@ -281,7 +309,7 @@ static int panel_dvi_read_edid(struct omap_dss_device *dssdev,
281 if (len > EDID_LENGTH && edid[0x7e] > 0) { 309 if (len > EDID_LENGTH && edid[0x7e] > 0) {
282 l = min(EDID_LENGTH, len - EDID_LENGTH); 310 l = min(EDID_LENGTH, len - EDID_LENGTH);
283 311
284 r = panel_dvi_ddc_read(adapter, edid + EDID_LENGTH, 312 r = tfp410_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
285 l, EDID_LENGTH); 313 l, EDID_LENGTH);
286 if (r) 314 if (r)
287 goto err; 315 goto err;
@@ -298,24 +326,18 @@ err:
298 return r; 326 return r;
299} 327}
300 328
301static bool panel_dvi_detect(struct omap_dss_device *dssdev) 329static bool tfp410_detect(struct omap_dss_device *dssdev)
302{ 330{
303 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev); 331 struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
304 struct panel_dvi_platform_data *pdata = get_pdata(dssdev);
305 struct i2c_adapter *adapter;
306 unsigned char out; 332 unsigned char out;
307 int r; 333 int r;
308 334
309 mutex_lock(&ddata->lock); 335 mutex_lock(&ddata->lock);
310 336
311 if (pdata->i2c_bus_num == 0) 337 if (!ddata->i2c_adapter)
312 goto out;
313
314 adapter = i2c_get_adapter(pdata->i2c_bus_num);
315 if (!adapter)
316 goto out; 338 goto out;
317 339
318 r = panel_dvi_ddc_read(adapter, &out, 1, 0); 340 r = tfp410_ddc_read(ddata->i2c_adapter, &out, 1, 0);
319 341
320 mutex_unlock(&ddata->lock); 342 mutex_unlock(&ddata->lock);
321 343
@@ -326,38 +348,38 @@ out:
326 return true; 348 return true;
327} 349}
328 350
329static struct omap_dss_driver panel_dvi_driver = { 351static struct omap_dss_driver tfp410_driver = {
330 .probe = panel_dvi_probe, 352 .probe = tfp410_probe,
331 .remove = __exit_p(panel_dvi_remove), 353 .remove = __exit_p(tfp410_remove),
332 354
333 .enable = panel_dvi_enable, 355 .enable = tfp410_enable,
334 .disable = panel_dvi_disable, 356 .disable = tfp410_disable,
335 .suspend = panel_dvi_suspend, 357 .suspend = tfp410_suspend,
336 .resume = panel_dvi_resume, 358 .resume = tfp410_resume,
337 359
338 .set_timings = panel_dvi_set_timings, 360 .set_timings = tfp410_set_timings,
339 .get_timings = panel_dvi_get_timings, 361 .get_timings = tfp410_get_timings,
340 .check_timings = panel_dvi_check_timings, 362 .check_timings = tfp410_check_timings,
341 363
342 .read_edid = panel_dvi_read_edid, 364 .read_edid = tfp410_read_edid,
343 .detect = panel_dvi_detect, 365 .detect = tfp410_detect,
344 366
345 .driver = { 367 .driver = {
346 .name = "dvi", 368 .name = "tfp410",
347 .owner = THIS_MODULE, 369 .owner = THIS_MODULE,
348 }, 370 },
349}; 371};
350 372
351static int __init panel_dvi_init(void) 373static int __init tfp410_init(void)
352{ 374{
353 return omap_dss_register_driver(&panel_dvi_driver); 375 return omap_dss_register_driver(&tfp410_driver);
354} 376}
355 377
356static void __exit panel_dvi_exit(void) 378static void __exit tfp410_exit(void)
357{ 379{
358 omap_dss_unregister_driver(&panel_dvi_driver); 380 omap_dss_unregister_driver(&tfp410_driver);
359} 381}
360 382
361module_init(panel_dvi_init); 383module_init(tfp410_init);
362module_exit(panel_dvi_exit); 384module_exit(tfp410_exit);
363MODULE_LICENSE("GPL"); 385MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 32f3fcd7f0f0..4b6448b3c31f 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -272,13 +272,16 @@ static const struct omap_video_timings tpo_td043_timings = {
272static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) 272static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
273{ 273{
274 int nreset_gpio = tpo_td043->nreset_gpio; 274 int nreset_gpio = tpo_td043->nreset_gpio;
275 int r;
275 276
276 if (tpo_td043->powered_on) 277 if (tpo_td043->powered_on)
277 return 0; 278 return 0;
278 279
279 regulator_enable(tpo_td043->vcc_reg); 280 r = regulator_enable(tpo_td043->vcc_reg);
281 if (r != 0)
282 return r;
280 283
281 /* wait for regulator to stabilize */ 284 /* wait for panel to stabilize */
282 msleep(160); 285 msleep(160);
283 286
284 if (gpio_is_valid(nreset_gpio)) 287 if (gpio_is_valid(nreset_gpio))
@@ -470,6 +473,18 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
470 gpio_free(nreset_gpio); 473 gpio_free(nreset_gpio);
471} 474}
472 475
476static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
477 struct omap_video_timings *timings)
478{
479 dpi_set_timings(dssdev, timings);
480}
481
482static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
483 struct omap_video_timings *timings)
484{
485 return dpi_check_timings(dssdev, timings);
486}
487
473static struct omap_dss_driver tpo_td043_driver = { 488static struct omap_dss_driver tpo_td043_driver = {
474 .probe = tpo_td043_probe, 489 .probe = tpo_td043_probe,
475 .remove = tpo_td043_remove, 490 .remove = tpo_td043_remove,
@@ -481,6 +496,9 @@ static struct omap_dss_driver tpo_td043_driver = {
481 .set_mirror = tpo_td043_set_hmirror, 496 .set_mirror = tpo_td043_set_hmirror,
482 .get_mirror = tpo_td043_get_hmirror, 497 .get_mirror = tpo_td043_get_hmirror,
483 498
499 .set_timings = tpo_td043_set_timings,
500 .check_timings = tpo_td043_check_timings,
501
484 .driver = { 502 .driver = {
485 .name = "tpo_td043mtea1_panel", 503 .name = "tpo_td043mtea1_panel",
486 .owner = THIS_MODULE, 504 .owner = THIS_MODULE,
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 7be7c06a249e..43324e5ed25f 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -68,6 +68,10 @@ config OMAP4_DSS_HDMI
68 HDMI Interface. This adds the High Definition Multimedia Interface. 68 HDMI Interface. This adds the High Definition Multimedia Interface.
69 See http://www.hdmi.org/ for HDMI specification. 69 See http://www.hdmi.org/ for HDMI specification.
70 70
71config OMAP4_DSS_HDMI_AUDIO
72 bool
73 depends on OMAP4_DSS_HDMI
74
71config OMAP2_DSS_SDI 75config OMAP2_DSS_SDI
72 bool "SDI support" 76 bool "SDI support"
73 depends on ARCH_OMAP3 77 depends on ARCH_OMAP3
@@ -90,15 +94,6 @@ config OMAP2_DSS_DSI
90 94
91 See http://www.mipi.org/ for DSI spesifications. 95 See http://www.mipi.org/ for DSI spesifications.
92 96
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.
101
102config OMAP2_DSS_MIN_FCK_PER_PCK 97config OMAP2_DSS_MIN_FCK_PER_PCK
103 int "Minimum FCK/PCK ratio (for scaling)" 98 int "Minimum FCK/PCK ratio (for scaling)"
104 range 0 32 99 range 0 32
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index b10b3bc1931e..ab22cc224f3e 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -99,6 +99,11 @@ struct mgr_priv_data {
99 99
100 /* If true, a display is enabled using this manager */ 100 /* If true, a display is enabled using this manager */
101 bool enabled; 101 bool enabled;
102
103 bool extra_info_dirty;
104 bool shadow_extra_info_dirty;
105
106 struct omap_video_timings timings;
102}; 107};
103 108
104static struct { 109static struct {
@@ -176,7 +181,7 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
176} 181}
177 182
178static int dss_check_settings_low(struct omap_overlay_manager *mgr, 183static int dss_check_settings_low(struct omap_overlay_manager *mgr,
179 struct omap_dss_device *dssdev, bool applying) 184 bool applying)
180{ 185{
181 struct omap_overlay_info *oi; 186 struct omap_overlay_info *oi;
182 struct omap_overlay_manager_info *mi; 187 struct omap_overlay_manager_info *mi;
@@ -187,6 +192,9 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,
187 192
188 mp = get_mgr_priv(mgr); 193 mp = get_mgr_priv(mgr);
189 194
195 if (!mp->enabled)
196 return 0;
197
190 if (applying && mp->user_info_dirty) 198 if (applying && mp->user_info_dirty)
191 mi = &mp->user_info; 199 mi = &mp->user_info;
192 else 200 else
@@ -206,26 +214,24 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,
206 ois[ovl->id] = oi; 214 ois[ovl->id] = oi;
207 } 215 }
208 216
209 return dss_mgr_check(mgr, dssdev, mi, ois); 217 return dss_mgr_check(mgr, mi, &mp->timings, ois);
210} 218}
211 219
212/* 220/*
213 * check manager and overlay settings using overlay_info from data->info 221 * check manager and overlay settings using overlay_info from data->info
214 */ 222 */
215static int dss_check_settings(struct omap_overlay_manager *mgr, 223static int dss_check_settings(struct omap_overlay_manager *mgr)
216 struct omap_dss_device *dssdev)
217{ 224{
218 return dss_check_settings_low(mgr, dssdev, false); 225 return dss_check_settings_low(mgr, false);
219} 226}
220 227
221/* 228/*
222 * check manager and overlay settings using overlay_info from ovl->info if 229 * check manager and overlay settings using overlay_info from ovl->info if
223 * dirty and from data->info otherwise 230 * dirty and from data->info otherwise
224 */ 231 */
225static int dss_check_settings_apply(struct omap_overlay_manager *mgr, 232static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
226 struct omap_dss_device *dssdev)
227{ 233{
228 return dss_check_settings_low(mgr, dssdev, true); 234 return dss_check_settings_low(mgr, true);
229} 235}
230 236
231static bool need_isr(void) 237static bool need_isr(void)
@@ -261,6 +267,20 @@ static bool need_isr(void)
261 if (mp->shadow_info_dirty) 267 if (mp->shadow_info_dirty)
262 return true; 268 return true;
263 269
270 /*
271 * NOTE: we don't check extra_info flags for disabled
272 * managers, once the manager is enabled, the extra_info
273 * related manager changes will be taken in by HW.
274 */
275
276 /* to write new values to registers */
277 if (mp->extra_info_dirty)
278 return true;
279
280 /* to set GO bit */
281 if (mp->shadow_extra_info_dirty)
282 return true;
283
264 list_for_each_entry(ovl, &mgr->overlays, list) { 284 list_for_each_entry(ovl, &mgr->overlays, list) {
265 struct ovl_priv_data *op; 285 struct ovl_priv_data *op;
266 286
@@ -305,7 +325,7 @@ static bool need_go(struct omap_overlay_manager *mgr)
305 325
306 mp = get_mgr_priv(mgr); 326 mp = get_mgr_priv(mgr);
307 327
308 if (mp->shadow_info_dirty) 328 if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
309 return true; 329 return true;
310 330
311 list_for_each_entry(ovl, &mgr->overlays, list) { 331 list_for_each_entry(ovl, &mgr->overlays, list) {
@@ -320,20 +340,16 @@ static bool need_go(struct omap_overlay_manager *mgr)
320/* returns true if an extra_info field is currently being updated */ 340/* returns true if an extra_info field is currently being updated */
321static bool extra_info_update_ongoing(void) 341static bool extra_info_update_ongoing(void)
322{ 342{
323 const int num_ovls = omap_dss_get_num_overlays(); 343 const int num_mgrs = dss_feat_get_num_mgrs();
324 struct ovl_priv_data *op;
325 struct omap_overlay *ovl;
326 struct mgr_priv_data *mp;
327 int i; 344 int i;
328 345
329 for (i = 0; i < num_ovls; ++i) { 346 for (i = 0; i < num_mgrs; ++i) {
330 ovl = omap_dss_get_overlay(i); 347 struct omap_overlay_manager *mgr;
331 op = get_ovl_priv(ovl); 348 struct omap_overlay *ovl;
332 349 struct mgr_priv_data *mp;
333 if (!ovl->manager)
334 continue;
335 350
336 mp = get_mgr_priv(ovl->manager); 351 mgr = omap_dss_get_overlay_manager(i);
352 mp = get_mgr_priv(mgr);
337 353
338 if (!mp->enabled) 354 if (!mp->enabled)
339 continue; 355 continue;
@@ -341,8 +357,15 @@ static bool extra_info_update_ongoing(void)
341 if (!mp->updating) 357 if (!mp->updating)
342 continue; 358 continue;
343 359
344 if (op->extra_info_dirty || op->shadow_extra_info_dirty) 360 if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
345 return true; 361 return true;
362
363 list_for_each_entry(ovl, &mgr->overlays, list) {
364 struct ovl_priv_data *op = get_ovl_priv(ovl);
365
366 if (op->extra_info_dirty || op->shadow_extra_info_dirty)
367 return true;
368 }
346 } 369 }
347 370
348 return false; 371 return false;
@@ -525,11 +548,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
525 548
526 oi = &op->info; 549 oi = &op->info;
527 550
551 mp = get_mgr_priv(ovl->manager);
552
528 replication = dss_use_replication(ovl->manager->device, oi->color_mode); 553 replication = dss_use_replication(ovl->manager->device, oi->color_mode);
529 554
530 ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC; 555 ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC;
531 556
532 r = dispc_ovl_setup(ovl->id, oi, ilace, replication); 557 r = dispc_ovl_setup(ovl->id, oi, ilace, replication, &mp->timings);
533 if (r) { 558 if (r) {
534 /* 559 /*
535 * We can't do much here, as this function can be called from 560 * We can't do much here, as this function can be called from
@@ -543,8 +568,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
543 return; 568 return;
544 } 569 }
545 570
546 mp = get_mgr_priv(ovl->manager);
547
548 op->info_dirty = false; 571 op->info_dirty = false;
549 if (mp->updating) 572 if (mp->updating)
550 op->shadow_info_dirty = true; 573 op->shadow_info_dirty = true;
@@ -601,6 +624,22 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
601 } 624 }
602} 625}
603 626
627static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
628{
629 struct mgr_priv_data *mp = get_mgr_priv(mgr);
630
631 DSSDBGF("%d", mgr->id);
632
633 if (!mp->extra_info_dirty)
634 return;
635
636 dispc_mgr_set_timings(mgr->id, &mp->timings);
637
638 mp->extra_info_dirty = false;
639 if (mp->updating)
640 mp->shadow_extra_info_dirty = true;
641}
642
604static void dss_write_regs_common(void) 643static void dss_write_regs_common(void)
605{ 644{
606 const int num_mgrs = omap_dss_get_num_overlay_managers(); 645 const int num_mgrs = omap_dss_get_num_overlay_managers();
@@ -646,7 +685,7 @@ static void dss_write_regs(void)
646 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy) 685 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
647 continue; 686 continue;
648 687
649 r = dss_check_settings(mgr, mgr->device); 688 r = dss_check_settings(mgr);
650 if (r) { 689 if (r) {
651 DSSERR("cannot write registers for manager %s: " 690 DSSERR("cannot write registers for manager %s: "
652 "illegal configuration\n", mgr->name); 691 "illegal configuration\n", mgr->name);
@@ -654,6 +693,7 @@ static void dss_write_regs(void)
654 } 693 }
655 694
656 dss_mgr_write_regs(mgr); 695 dss_mgr_write_regs(mgr);
696 dss_mgr_write_regs_extra(mgr);
657 } 697 }
658} 698}
659 699
@@ -693,6 +733,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
693 733
694 mp = get_mgr_priv(mgr); 734 mp = get_mgr_priv(mgr);
695 mp->shadow_info_dirty = false; 735 mp->shadow_info_dirty = false;
736 mp->shadow_extra_info_dirty = false;
696 737
697 list_for_each_entry(ovl, &mgr->overlays, list) { 738 list_for_each_entry(ovl, &mgr->overlays, list) {
698 op = get_ovl_priv(ovl); 739 op = get_ovl_priv(ovl);
@@ -711,7 +752,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
711 752
712 WARN_ON(mp->updating); 753 WARN_ON(mp->updating);
713 754
714 r = dss_check_settings(mgr, mgr->device); 755 r = dss_check_settings(mgr);
715 if (r) { 756 if (r) {
716 DSSERR("cannot start manual update: illegal configuration\n"); 757 DSSERR("cannot start manual update: illegal configuration\n");
717 spin_unlock_irqrestore(&data_lock, flags); 758 spin_unlock_irqrestore(&data_lock, flags);
@@ -719,6 +760,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
719 } 760 }
720 761
721 dss_mgr_write_regs(mgr); 762 dss_mgr_write_regs(mgr);
763 dss_mgr_write_regs_extra(mgr);
722 764
723 dss_write_regs_common(); 765 dss_write_regs_common();
724 766
@@ -857,7 +899,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
857 899
858 spin_lock_irqsave(&data_lock, flags); 900 spin_lock_irqsave(&data_lock, flags);
859 901
860 r = dss_check_settings_apply(mgr, mgr->device); 902 r = dss_check_settings_apply(mgr);
861 if (r) { 903 if (r) {
862 spin_unlock_irqrestore(&data_lock, flags); 904 spin_unlock_irqrestore(&data_lock, flags);
863 DSSERR("failed to apply settings: illegal configuration.\n"); 905 DSSERR("failed to apply settings: illegal configuration.\n");
@@ -918,16 +960,13 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
918 bool use_fifo_merge) 960 bool use_fifo_merge)
919{ 961{
920 struct ovl_priv_data *op = get_ovl_priv(ovl); 962 struct ovl_priv_data *op = get_ovl_priv(ovl);
921 struct omap_dss_device *dssdev;
922 u32 fifo_low, fifo_high; 963 u32 fifo_low, fifo_high;
923 964
924 if (!op->enabled && !op->enabling) 965 if (!op->enabled && !op->enabling)
925 return; 966 return;
926 967
927 dssdev = ovl->manager->device;
928
929 dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, 968 dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
930 use_fifo_merge); 969 use_fifo_merge, ovl_manual_update(ovl));
931 970
932 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); 971 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
933} 972}
@@ -1050,7 +1089,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1050 1089
1051 mp->enabled = true; 1090 mp->enabled = true;
1052 1091
1053 r = dss_check_settings(mgr, mgr->device); 1092 r = dss_check_settings(mgr);
1054 if (r) { 1093 if (r) {
1055 DSSERR("failed to enable manager %d: check_settings failed\n", 1094 DSSERR("failed to enable manager %d: check_settings failed\n",
1056 mgr->id); 1095 mgr->id);
@@ -1225,6 +1264,35 @@ err:
1225 return r; 1264 return r;
1226} 1265}
1227 1266
1267static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
1268 struct omap_video_timings *timings)
1269{
1270 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1271
1272 mp->timings = *timings;
1273 mp->extra_info_dirty = true;
1274}
1275
1276void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
1277 struct omap_video_timings *timings)
1278{
1279 unsigned long flags;
1280
1281 mutex_lock(&apply_lock);
1282
1283 spin_lock_irqsave(&data_lock, flags);
1284
1285 dss_apply_mgr_timings(mgr, timings);
1286
1287 dss_write_regs();
1288 dss_set_go_bits();
1289
1290 spin_unlock_irqrestore(&data_lock, flags);
1291
1292 wait_pending_extra_info_updates();
1293
1294 mutex_unlock(&apply_lock);
1295}
1228 1296
1229int dss_ovl_set_info(struct omap_overlay *ovl, 1297int dss_ovl_set_info(struct omap_overlay *ovl,
1230 struct omap_overlay_info *info) 1298 struct omap_overlay_info *info)
@@ -1393,7 +1461,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
1393 1461
1394 op->enabling = true; 1462 op->enabling = true;
1395 1463
1396 r = dss_check_settings(ovl->manager, ovl->manager->device); 1464 r = dss_check_settings(ovl->manager);
1397 if (r) { 1465 if (r) {
1398 DSSERR("failed to enable overlay %d: check_settings failed\n", 1466 DSSERR("failed to enable overlay %d: check_settings failed\n",
1399 ovl->id); 1467 ovl->id);
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index e8a120771ac6..72ded9cd2cb0 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -43,6 +43,8 @@ static struct {
43 43
44 struct regulator *vdds_dsi_reg; 44 struct regulator *vdds_dsi_reg;
45 struct regulator *vdds_sdi_reg; 45 struct regulator *vdds_sdi_reg;
46
47 const char *default_display_name;
46} core; 48} core;
47 49
48static char *def_disp_name; 50static char *def_disp_name;
@@ -54,9 +56,6 @@ bool dss_debug;
54module_param_named(debug, dss_debug, bool, 0644); 56module_param_named(debug, dss_debug, bool, 0644);
55#endif 57#endif
56 58
57static int omap_dss_register_device(struct omap_dss_device *);
58static void omap_dss_unregister_device(struct omap_dss_device *);
59
60/* REGULATORS */ 59/* REGULATORS */
61 60
62struct regulator *dss_get_vdds_dsi(void) 61struct regulator *dss_get_vdds_dsi(void)
@@ -87,6 +86,51 @@ struct regulator *dss_get_vdds_sdi(void)
87 return reg; 86 return reg;
88} 87}
89 88
89int dss_get_ctx_loss_count(struct device *dev)
90{
91 struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
92 int cnt;
93
94 if (!board_data->get_context_loss_count)
95 return -ENOENT;
96
97 cnt = board_data->get_context_loss_count(dev);
98
99 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
100
101 return cnt;
102}
103
104int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
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_enable_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
90#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 134#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
91static int dss_debug_show(struct seq_file *s, void *unused) 135static int dss_debug_show(struct seq_file *s, void *unused)
92{ 136{
@@ -121,34 +165,6 @@ static int dss_initialize_debugfs(void)
121 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 165 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
122 &dss_debug_dump_clocks, &dss_debug_fops); 166 &dss_debug_dump_clocks, &dss_debug_fops);
123 167
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
148#ifdef CONFIG_OMAP4_DSS_HDMI
149 debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
150 &hdmi_dump_regs, &dss_debug_fops);
151#endif
152 return 0; 168 return 0;
153} 169}
154 170
@@ -157,6 +173,19 @@ static void dss_uninitialize_debugfs(void)
157 if (dss_debugfs_dir) 173 if (dss_debugfs_dir)
158 debugfs_remove_recursive(dss_debugfs_dir); 174 debugfs_remove_recursive(dss_debugfs_dir);
159} 175}
176
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}
160#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 189#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
161static inline int dss_initialize_debugfs(void) 190static inline int dss_initialize_debugfs(void)
162{ 191{
@@ -165,14 +194,18 @@ static inline int dss_initialize_debugfs(void)
165static inline void dss_uninitialize_debugfs(void) 194static inline void dss_uninitialize_debugfs(void)
166{ 195{
167} 196}
197static inline int dss_debugfs_create_file(const char *name,
198 void (*write)(struct seq_file *))
199{
200 return 0;
201}
168#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ 202#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
169 203
170/* PLATFORM DEVICE */ 204/* PLATFORM DEVICE */
171static int omap_dss_probe(struct platform_device *pdev) 205static int __init omap_dss_probe(struct platform_device *pdev)
172{ 206{
173 struct omap_dss_board_info *pdata = pdev->dev.platform_data; 207 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
174 int r; 208 int r;
175 int i;
176 209
177 core.pdev = pdev; 210 core.pdev = pdev;
178 211
@@ -187,28 +220,13 @@ static int omap_dss_probe(struct platform_device *pdev)
187 if (r) 220 if (r)
188 goto err_debugfs; 221 goto err_debugfs;
189 222
190 for (i = 0; i < pdata->num_devices; ++i) { 223 if (def_disp_name)
191 struct omap_dss_device *dssdev = pdata->devices[i]; 224 core.default_display_name = def_disp_name;
192 225 else if (pdata->default_device)
193 r = omap_dss_register_device(dssdev); 226 core.default_display_name = pdata->default_device->name;
194 if (r) {
195 DSSERR("device %d %s register failed %d\n", i,
196 dssdev->name ?: "unnamed", r);
197
198 while (--i >= 0)
199 omap_dss_unregister_device(pdata->devices[i]);
200
201 goto err_register;
202 }
203
204 if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
205 pdata->default_device = dssdev;
206 }
207 227
208 return 0; 228 return 0;
209 229
210err_register:
211 dss_uninitialize_debugfs();
212err_debugfs: 230err_debugfs:
213 231
214 return r; 232 return r;
@@ -216,17 +234,11 @@ err_debugfs:
216 234
217static int omap_dss_remove(struct platform_device *pdev) 235static int omap_dss_remove(struct platform_device *pdev)
218{ 236{
219 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
220 int i;
221
222 dss_uninitialize_debugfs(); 237 dss_uninitialize_debugfs();
223 238
224 dss_uninit_overlays(pdev); 239 dss_uninit_overlays(pdev);
225 dss_uninit_overlay_managers(pdev); 240 dss_uninit_overlay_managers(pdev);
226 241
227 for (i = 0; i < pdata->num_devices; ++i)
228 omap_dss_unregister_device(pdata->devices[i]);
229
230 return 0; 242 return 0;
231} 243}
232 244
@@ -251,7 +263,6 @@ static int omap_dss_resume(struct platform_device *pdev)
251} 263}
252 264
253static struct platform_driver omap_dss_driver = { 265static struct platform_driver omap_dss_driver = {
254 .probe = omap_dss_probe,
255 .remove = omap_dss_remove, 266 .remove = omap_dss_remove,
256 .shutdown = omap_dss_shutdown, 267 .shutdown = omap_dss_shutdown,
257 .suspend = omap_dss_suspend, 268 .suspend = omap_dss_suspend,
@@ -326,7 +337,6 @@ static int dss_driver_probe(struct device *dev)
326 int r; 337 int r;
327 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); 338 struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
328 struct omap_dss_device *dssdev = to_dss_device(dev); 339 struct omap_dss_device *dssdev = to_dss_device(dev);
329 struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
330 bool force; 340 bool force;
331 341
332 DSSDBG("driver_probe: dev %s/%s, drv %s\n", 342 DSSDBG("driver_probe: dev %s/%s, drv %s\n",
@@ -335,7 +345,8 @@ static int dss_driver_probe(struct device *dev)
335 345
336 dss_init_device(core.pdev, dssdev); 346 dss_init_device(core.pdev, dssdev);
337 347
338 force = pdata->default_device == dssdev; 348 force = core.default_display_name &&
349 strcmp(core.default_display_name, dssdev->name) == 0;
339 dss_recheck_connections(dssdev, force); 350 dss_recheck_connections(dssdev, force);
340 351
341 r = dssdrv->probe(dssdev); 352 r = dssdrv->probe(dssdev);
@@ -381,6 +392,8 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
381 if (dssdriver->get_recommended_bpp == NULL) 392 if (dssdriver->get_recommended_bpp == NULL)
382 dssdriver->get_recommended_bpp = 393 dssdriver->get_recommended_bpp =
383 omapdss_default_get_recommended_bpp; 394 omapdss_default_get_recommended_bpp;
395 if (dssdriver->get_timings == NULL)
396 dssdriver->get_timings = omapdss_default_get_timings;
384 397
385 return driver_register(&dssdriver->driver); 398 return driver_register(&dssdriver->driver);
386} 399}
@@ -427,27 +440,38 @@ static void omap_dss_dev_release(struct device *dev)
427 reset_device(dev, 0); 440 reset_device(dev, 0);
428} 441}
429 442
430static int omap_dss_register_device(struct omap_dss_device *dssdev) 443int omap_dss_register_device(struct omap_dss_device *dssdev,
444 struct device *parent, int disp_num)
431{ 445{
432 static int dev_num;
433
434 WARN_ON(!dssdev->driver_name); 446 WARN_ON(!dssdev->driver_name);
435 447
436 reset_device(&dssdev->dev, 1); 448 reset_device(&dssdev->dev, 1);
437 dssdev->dev.bus = &dss_bus_type; 449 dssdev->dev.bus = &dss_bus_type;
438 dssdev->dev.parent = &dss_bus; 450 dssdev->dev.parent = parent;
439 dssdev->dev.release = omap_dss_dev_release; 451 dssdev->dev.release = omap_dss_dev_release;
440 dev_set_name(&dssdev->dev, "display%d", dev_num++); 452 dev_set_name(&dssdev->dev, "display%d", disp_num);
441 return device_register(&dssdev->dev); 453 return device_register(&dssdev->dev);
442} 454}
443 455
444static void omap_dss_unregister_device(struct omap_dss_device *dssdev) 456void omap_dss_unregister_device(struct omap_dss_device *dssdev)
445{ 457{
446 device_unregister(&dssdev->dev); 458 device_unregister(&dssdev->dev);
447} 459}
448 460
461static int dss_unregister_dss_dev(struct device *dev, void *data)
462{
463 struct omap_dss_device *dssdev = to_dss_device(dev);
464 omap_dss_unregister_device(dssdev);
465 return 0;
466}
467
468void omap_dss_unregister_child_devices(struct device *parent)
469{
470 device_for_each_child(parent, NULL, dss_unregister_dss_dev);
471}
472
449/* BUS */ 473/* BUS */
450static int omap_dss_bus_register(void) 474static int __init omap_dss_bus_register(void)
451{ 475{
452 int r; 476 int r;
453 477
@@ -469,12 +493,56 @@ static int omap_dss_bus_register(void)
469} 493}
470 494
471/* INIT */ 495/* INIT */
496static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
497#ifdef CONFIG_OMAP2_DSS_DPI
498 dpi_init_platform_driver,
499#endif
500#ifdef CONFIG_OMAP2_DSS_SDI
501 sdi_init_platform_driver,
502#endif
503#ifdef CONFIG_OMAP2_DSS_RFBI
504 rfbi_init_platform_driver,
505#endif
506#ifdef CONFIG_OMAP2_DSS_VENC
507 venc_init_platform_driver,
508#endif
509#ifdef CONFIG_OMAP2_DSS_DSI
510 dsi_init_platform_driver,
511#endif
512#ifdef CONFIG_OMAP4_DSS_HDMI
513 hdmi_init_platform_driver,
514#endif
515};
516
517static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
518#ifdef CONFIG_OMAP2_DSS_DPI
519 dpi_uninit_platform_driver,
520#endif
521#ifdef CONFIG_OMAP2_DSS_SDI
522 sdi_uninit_platform_driver,
523#endif
524#ifdef CONFIG_OMAP2_DSS_RFBI
525 rfbi_uninit_platform_driver,
526#endif
527#ifdef CONFIG_OMAP2_DSS_VENC
528 venc_uninit_platform_driver,
529#endif
530#ifdef CONFIG_OMAP2_DSS_DSI
531 dsi_uninit_platform_driver,
532#endif
533#ifdef CONFIG_OMAP4_DSS_HDMI
534 hdmi_uninit_platform_driver,
535#endif
536};
537
538static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
472 539
473static int __init omap_dss_register_drivers(void) 540static int __init omap_dss_register_drivers(void)
474{ 541{
475 int r; 542 int r;
543 int i;
476 544
477 r = platform_driver_register(&omap_dss_driver); 545 r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
478 if (r) 546 if (r)
479 return r; 547 return r;
480 548
@@ -490,40 +558,18 @@ static int __init omap_dss_register_drivers(void)
490 goto err_dispc; 558 goto err_dispc;
491 } 559 }
492 560
493 r = rfbi_init_platform_driver(); 561 /*
494 if (r) { 562 * It's ok if the output-driver register fails. It happens, for example,
495 DSSERR("Failed to initialize rfbi platform driver\n"); 563 * when there is no output-device (e.g. SDI for OMAP4).
496 goto err_rfbi; 564 */
497 } 565 for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
498 566 r = dss_output_drv_reg_funcs[i]();
499 r = venc_init_platform_driver(); 567 if (r == 0)
500 if (r) { 568 dss_output_drv_loaded[i] = true;
501 DSSERR("Failed to initialize venc platform driver\n");
502 goto err_venc;
503 }
504
505 r = dsi_init_platform_driver();
506 if (r) {
507 DSSERR("Failed to initialize DSI platform driver\n");
508 goto err_dsi;
509 }
510
511 r = hdmi_init_platform_driver();
512 if (r) {
513 DSSERR("Failed to initialize hdmi\n");
514 goto err_hdmi;
515 } 569 }
516 570
517 return 0; 571 return 0;
518 572
519err_hdmi:
520 dsi_uninit_platform_driver();
521err_dsi:
522 venc_uninit_platform_driver();
523err_venc:
524 rfbi_uninit_platform_driver();
525err_rfbi:
526 dispc_uninit_platform_driver();
527err_dispc: 573err_dispc:
528 dss_uninit_platform_driver(); 574 dss_uninit_platform_driver();
529err_dss: 575err_dss:
@@ -534,10 +580,13 @@ err_dss:
534 580
535static void __exit omap_dss_unregister_drivers(void) 581static void __exit omap_dss_unregister_drivers(void)
536{ 582{
537 hdmi_uninit_platform_driver(); 583 int i;
538 dsi_uninit_platform_driver(); 584
539 venc_uninit_platform_driver(); 585 for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
540 rfbi_uninit_platform_driver(); 586 if (dss_output_drv_loaded[i])
587 dss_output_drv_unreg_funcs[i]();
588 }
589
541 dispc_uninit_platform_driver(); 590 dispc_uninit_platform_driver();
542 dss_uninit_platform_driver(); 591 dss_uninit_platform_driver();
543 592
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index ee30937482e1..4749ac356469 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -131,23 +131,6 @@ static inline u32 dispc_read_reg(const u16 idx)
131 return __raw_readl(dispc.base + idx); 131 return __raw_readl(dispc.base + idx);
132} 132}
133 133
134static int dispc_get_ctx_loss_count(void)
135{
136 struct device *dev = &dispc.pdev->dev;
137 struct omap_display_platform_data *pdata = dev->platform_data;
138 struct omap_dss_board_info *board_data = pdata->board_data;
139 int cnt;
140
141 if (!board_data->get_context_loss_count)
142 return -ENOENT;
143
144 cnt = board_data->get_context_loss_count(dev);
145
146 WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
147
148 return cnt;
149}
150
151#define SR(reg) \ 134#define SR(reg) \
152 dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg) 135 dispc.ctx[DISPC_##reg / sizeof(u32)] = dispc_read_reg(DISPC_##reg)
153#define RR(reg) \ 136#define RR(reg) \
@@ -251,7 +234,7 @@ static void dispc_save_context(void)
251 if (dss_has_feature(FEAT_CORE_CLK_DIV)) 234 if (dss_has_feature(FEAT_CORE_CLK_DIV))
252 SR(DIVISOR); 235 SR(DIVISOR);
253 236
254 dispc.ctx_loss_cnt = dispc_get_ctx_loss_count(); 237 dispc.ctx_loss_cnt = dss_get_ctx_loss_count(&dispc.pdev->dev);
255 dispc.ctx_valid = true; 238 dispc.ctx_valid = true;
256 239
257 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt); 240 DSSDBG("context saved, ctx_loss_count %d\n", dispc.ctx_loss_cnt);
@@ -266,7 +249,7 @@ static void dispc_restore_context(void)
266 if (!dispc.ctx_valid) 249 if (!dispc.ctx_valid)
267 return; 250 return;
268 251
269 ctx = dispc_get_ctx_loss_count(); 252 ctx = dss_get_ctx_loss_count(&dispc.pdev->dev);
270 253
271 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt) 254 if (ctx >= 0 && ctx == dispc.ctx_loss_cnt)
272 return; 255 return;
@@ -413,14 +396,6 @@ static inline bool dispc_mgr_is_lcd(enum omap_channel channel)
413 return false; 396 return false;
414} 397}
415 398
416static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
417{
418 struct omap_overlay_manager *mgr =
419 omap_dss_get_overlay_manager(channel);
420
421 return mgr ? mgr->device : NULL;
422}
423
424u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) 399u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
425{ 400{
426 switch (channel) { 401 switch (channel) {
@@ -432,6 +407,7 @@ u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
432 return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 407 return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
433 default: 408 default:
434 BUG(); 409 BUG();
410 return 0;
435 } 411 }
436} 412}
437 413
@@ -446,6 +422,7 @@ u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
446 return 0; 422 return 0;
447 default: 423 default:
448 BUG(); 424 BUG();
425 return 0;
449 } 426 }
450} 427}
451 428
@@ -764,7 +741,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
764 case OMAP_DSS_COLOR_XRGB16_1555: 741 case OMAP_DSS_COLOR_XRGB16_1555:
765 m = 0xf; break; 742 m = 0xf; break;
766 default: 743 default:
767 BUG(); break; 744 BUG(); return;
768 } 745 }
769 } else { 746 } else {
770 switch (color_mode) { 747 switch (color_mode) {
@@ -801,13 +778,25 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
801 case OMAP_DSS_COLOR_XRGB16_1555: 778 case OMAP_DSS_COLOR_XRGB16_1555:
802 m = 0xf; break; 779 m = 0xf; break;
803 default: 780 default:
804 BUG(); break; 781 BUG(); return;
805 } 782 }
806 } 783 }
807 784
808 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); 785 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
809} 786}
810 787
788static void dispc_ovl_configure_burst_type(enum omap_plane plane,
789 enum omap_dss_rotation_type rotation_type)
790{
791 if (dss_has_feature(FEAT_BURST_2D) == 0)
792 return;
793
794 if (rotation_type == OMAP_DSS_ROT_TILER)
795 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 1, 29, 29);
796 else
797 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29);
798}
799
811void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) 800void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
812{ 801{
813 int shift; 802 int shift;
@@ -845,6 +834,7 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
845 break; 834 break;
846 default: 835 default:
847 BUG(); 836 BUG();
837 return;
848 } 838 }
849 839
850 val = FLD_MOD(val, chan, shift, shift); 840 val = FLD_MOD(val, chan, shift, shift);
@@ -872,6 +862,7 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
872 break; 862 break;
873 default: 863 default:
874 BUG(); 864 BUG();
865 return 0;
875 } 866 }
876 867
877 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); 868 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
@@ -983,20 +974,13 @@ static void dispc_ovl_enable_replication(enum omap_plane plane, bool enable)
983 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift); 974 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, shift, shift);
984} 975}
985 976
986void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height) 977static void dispc_mgr_set_size(enum omap_channel channel, u16 width,
978 u16 height)
987{ 979{
988 u32 val; 980 u32 val;
989 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
990 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
991 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
992}
993 981
994void dispc_set_digit_size(u16 width, u16 height)
995{
996 u32 val;
997 BUG_ON((width > (1 << 11)) || (height > (1 << 11)));
998 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 982 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0);
999 dispc_write_reg(DISPC_SIZE_MGR(OMAP_DSS_CHANNEL_DIGIT), val); 983 dispc_write_reg(DISPC_SIZE_MGR(channel), val);
1000} 984}
1001 985
1002static void dispc_read_plane_fifo_sizes(void) 986static void dispc_read_plane_fifo_sizes(void)
@@ -1063,7 +1047,8 @@ void dispc_enable_fifomerge(bool enable)
1063} 1047}
1064 1048
1065void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 1049void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1066 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge) 1050 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
1051 bool manual_update)
1067{ 1052{
1068 /* 1053 /*
1069 * All sizes are in bytes. Both the buffer and burst are made of 1054 * All sizes are in bytes. Both the buffer and burst are made of
@@ -1091,7 +1076,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
1091 * combined fifo size 1076 * combined fifo size
1092 */ 1077 */
1093 1078
1094 if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { 1079 if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) {
1095 *fifo_low = ovl_fifo_size - burst_size * 2; 1080 *fifo_low = ovl_fifo_size - burst_size * 2;
1096 *fifo_high = total_fifo_size - burst_size; 1081 *fifo_high = total_fifo_size - burst_size;
1097 } else { 1082 } else {
@@ -1185,6 +1170,94 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane,
1185 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); 1170 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1186} 1171}
1187 1172
1173static void dispc_ovl_set_accu_uv(enum omap_plane plane,
1174 u16 orig_width, u16 orig_height, u16 out_width, u16 out_height,
1175 bool ilace, enum omap_color_mode color_mode, u8 rotation)
1176{
1177 int h_accu2_0, h_accu2_1;
1178 int v_accu2_0, v_accu2_1;
1179 int chroma_hinc, chroma_vinc;
1180 int idx;
1181
1182 struct accu {
1183 s8 h0_m, h0_n;
1184 s8 h1_m, h1_n;
1185 s8 v0_m, v0_n;
1186 s8 v1_m, v1_n;
1187 };
1188
1189 const struct accu *accu_table;
1190 const struct accu *accu_val;
1191
1192 static const struct accu accu_nv12[4] = {
1193 { 0, 1, 0, 1 , -1, 2, 0, 1 },
1194 { 1, 2, -3, 4 , 0, 1, 0, 1 },
1195 { -1, 1, 0, 1 , -1, 2, 0, 1 },
1196 { -1, 2, -1, 2 , -1, 1, 0, 1 },
1197 };
1198
1199 static const struct accu accu_nv12_ilace[4] = {
1200 { 0, 1, 0, 1 , -3, 4, -1, 4 },
1201 { -1, 4, -3, 4 , 0, 1, 0, 1 },
1202 { -1, 1, 0, 1 , -1, 4, -3, 4 },
1203 { -3, 4, -3, 4 , -1, 1, 0, 1 },
1204 };
1205
1206 static const struct accu accu_yuv[4] = {
1207 { 0, 1, 0, 1, 0, 1, 0, 1 },
1208 { 0, 1, 0, 1, 0, 1, 0, 1 },
1209 { -1, 1, 0, 1, 0, 1, 0, 1 },
1210 { 0, 1, 0, 1, -1, 1, 0, 1 },
1211 };
1212
1213 switch (rotation) {
1214 case OMAP_DSS_ROT_0:
1215 idx = 0;
1216 break;
1217 case OMAP_DSS_ROT_90:
1218 idx = 1;
1219 break;
1220 case OMAP_DSS_ROT_180:
1221 idx = 2;
1222 break;
1223 case OMAP_DSS_ROT_270:
1224 idx = 3;
1225 break;
1226 default:
1227 BUG();
1228 return;
1229 }
1230
1231 switch (color_mode) {
1232 case OMAP_DSS_COLOR_NV12:
1233 if (ilace)
1234 accu_table = accu_nv12_ilace;
1235 else
1236 accu_table = accu_nv12;
1237 break;
1238 case OMAP_DSS_COLOR_YUV2:
1239 case OMAP_DSS_COLOR_UYVY:
1240 accu_table = accu_yuv;
1241 break;
1242 default:
1243 BUG();
1244 return;
1245 }
1246
1247 accu_val = &accu_table[idx];
1248
1249 chroma_hinc = 1024 * orig_width / out_width;
1250 chroma_vinc = 1024 * orig_height / out_height;
1251
1252 h_accu2_0 = (accu_val->h0_m * chroma_hinc / accu_val->h0_n) % 1024;
1253 h_accu2_1 = (accu_val->h1_m * chroma_hinc / accu_val->h1_n) % 1024;
1254 v_accu2_0 = (accu_val->v0_m * chroma_vinc / accu_val->v0_n) % 1024;
1255 v_accu2_1 = (accu_val->v1_m * chroma_vinc / accu_val->v1_n) % 1024;
1256
1257 dispc_ovl_set_vid_accu2_0(plane, h_accu2_0, v_accu2_0);
1258 dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1);
1259}
1260
1188static void dispc_ovl_set_scaling_common(enum omap_plane plane, 1261static void dispc_ovl_set_scaling_common(enum omap_plane plane,
1189 u16 orig_width, u16 orig_height, 1262 u16 orig_width, u16 orig_height,
1190 u16 out_width, u16 out_height, 1263 u16 out_width, u16 out_height,
@@ -1258,6 +1331,10 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1258 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8); 1331 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), 0, 8, 8);
1259 return; 1332 return;
1260 } 1333 }
1334
1335 dispc_ovl_set_accu_uv(plane, orig_width, orig_height, out_width,
1336 out_height, ilace, color_mode, rotation);
1337
1261 switch (color_mode) { 1338 switch (color_mode) {
1262 case OMAP_DSS_COLOR_NV12: 1339 case OMAP_DSS_COLOR_NV12:
1263 /* UV is subsampled by 2 vertically*/ 1340 /* UV is subsampled by 2 vertically*/
@@ -1280,6 +1357,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1280 break; 1357 break;
1281 default: 1358 default:
1282 BUG(); 1359 BUG();
1360 return;
1283 } 1361 }
1284 1362
1285 if (out_width != orig_width) 1363 if (out_width != orig_width)
@@ -1297,9 +1375,6 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane,
1297 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5); 1375 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_x ? 1 : 0, 5, 5);
1298 /* set V scaling */ 1376 /* set V scaling */
1299 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); 1377 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6);
1300
1301 dispc_ovl_set_vid_accu2_0(plane, 0x80, 0);
1302 dispc_ovl_set_vid_accu2_1(plane, 0x80, 0);
1303} 1378}
1304 1379
1305static void dispc_ovl_set_scaling(enum omap_plane plane, 1380static void dispc_ovl_set_scaling(enum omap_plane plane,
@@ -1410,6 +1485,7 @@ static int color_mode_to_bpp(enum omap_color_mode color_mode)
1410 return 32; 1485 return 32;
1411 default: 1486 default:
1412 BUG(); 1487 BUG();
1488 return 0;
1413 } 1489 }
1414} 1490}
1415 1491
@@ -1423,6 +1499,7 @@ static s32 pixinc(int pixels, u8 ps)
1423 return 1 - (-pixels + 1) * ps; 1499 return 1 - (-pixels + 1) * ps;
1424 else 1500 else
1425 BUG(); 1501 BUG();
1502 return 0;
1426} 1503}
1427 1504
1428static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, 1505static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
@@ -1431,7 +1508,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1431 enum omap_color_mode color_mode, bool fieldmode, 1508 enum omap_color_mode color_mode, bool fieldmode,
1432 unsigned int field_offset, 1509 unsigned int field_offset,
1433 unsigned *offset0, unsigned *offset1, 1510 unsigned *offset0, unsigned *offset1,
1434 s32 *row_inc, s32 *pix_inc) 1511 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1435{ 1512{
1436 u8 ps; 1513 u8 ps;
1437 1514
@@ -1477,10 +1554,10 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1477 else 1554 else
1478 *offset0 = 0; 1555 *offset0 = 0;
1479 1556
1480 *row_inc = pixinc(1 + (screen_width - width) + 1557 *row_inc = pixinc(1 +
1481 (fieldmode ? screen_width : 0), 1558 (y_predecim * screen_width - x_predecim * width) +
1482 ps); 1559 (fieldmode ? screen_width : 0), ps);
1483 *pix_inc = pixinc(1, ps); 1560 *pix_inc = pixinc(x_predecim, ps);
1484 break; 1561 break;
1485 1562
1486 case OMAP_DSS_ROT_0 + 4: 1563 case OMAP_DSS_ROT_0 + 4:
@@ -1498,14 +1575,15 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
1498 *offset0 = field_offset * screen_width * ps; 1575 *offset0 = field_offset * screen_width * ps;
1499 else 1576 else
1500 *offset0 = 0; 1577 *offset0 = 0;
1501 *row_inc = pixinc(1 - (screen_width + width) - 1578 *row_inc = pixinc(1 -
1502 (fieldmode ? screen_width : 0), 1579 (y_predecim * screen_width + x_predecim * width) -
1503 ps); 1580 (fieldmode ? screen_width : 0), ps);
1504 *pix_inc = pixinc(1, ps); 1581 *pix_inc = pixinc(x_predecim, ps);
1505 break; 1582 break;
1506 1583
1507 default: 1584 default:
1508 BUG(); 1585 BUG();
1586 return;
1509 } 1587 }
1510} 1588}
1511 1589
@@ -1515,7 +1593,7 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1515 enum omap_color_mode color_mode, bool fieldmode, 1593 enum omap_color_mode color_mode, bool fieldmode,
1516 unsigned int field_offset, 1594 unsigned int field_offset,
1517 unsigned *offset0, unsigned *offset1, 1595 unsigned *offset0, unsigned *offset1,
1518 s32 *row_inc, s32 *pix_inc) 1596 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1519{ 1597{
1520 u8 ps; 1598 u8 ps;
1521 u16 fbw, fbh; 1599 u16 fbw, fbh;
@@ -1557,10 +1635,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1557 *offset0 = *offset1 + field_offset * screen_width * ps; 1635 *offset0 = *offset1 + field_offset * screen_width * ps;
1558 else 1636 else
1559 *offset0 = *offset1; 1637 *offset0 = *offset1;
1560 *row_inc = pixinc(1 + (screen_width - fbw) + 1638 *row_inc = pixinc(1 +
1561 (fieldmode ? screen_width : 0), 1639 (y_predecim * screen_width - fbw * x_predecim) +
1562 ps); 1640 (fieldmode ? screen_width : 0), ps);
1563 *pix_inc = pixinc(1, ps); 1641 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1642 color_mode == OMAP_DSS_COLOR_UYVY)
1643 *pix_inc = pixinc(x_predecim, 2 * ps);
1644 else
1645 *pix_inc = pixinc(x_predecim, ps);
1564 break; 1646 break;
1565 case OMAP_DSS_ROT_90: 1647 case OMAP_DSS_ROT_90:
1566 *offset1 = screen_width * (fbh - 1) * ps; 1648 *offset1 = screen_width * (fbh - 1) * ps;
@@ -1568,9 +1650,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1568 *offset0 = *offset1 + field_offset * ps; 1650 *offset0 = *offset1 + field_offset * ps;
1569 else 1651 else
1570 *offset0 = *offset1; 1652 *offset0 = *offset1;
1571 *row_inc = pixinc(screen_width * (fbh - 1) + 1 + 1653 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) +
1572 (fieldmode ? 1 : 0), ps); 1654 y_predecim + (fieldmode ? 1 : 0), ps);
1573 *pix_inc = pixinc(-screen_width, ps); 1655 *pix_inc = pixinc(-x_predecim * screen_width, ps);
1574 break; 1656 break;
1575 case OMAP_DSS_ROT_180: 1657 case OMAP_DSS_ROT_180:
1576 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; 1658 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps;
@@ -1579,10 +1661,13 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1579 else 1661 else
1580 *offset0 = *offset1; 1662 *offset0 = *offset1;
1581 *row_inc = pixinc(-1 - 1663 *row_inc = pixinc(-1 -
1582 (screen_width - fbw) - 1664 (y_predecim * screen_width - fbw * x_predecim) -
1583 (fieldmode ? screen_width : 0), 1665 (fieldmode ? screen_width : 0), ps);
1584 ps); 1666 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1585 *pix_inc = pixinc(-1, ps); 1667 color_mode == OMAP_DSS_COLOR_UYVY)
1668 *pix_inc = pixinc(-x_predecim, 2 * ps);
1669 else
1670 *pix_inc = pixinc(-x_predecim, ps);
1586 break; 1671 break;
1587 case OMAP_DSS_ROT_270: 1672 case OMAP_DSS_ROT_270:
1588 *offset1 = (fbw - 1) * ps; 1673 *offset1 = (fbw - 1) * ps;
@@ -1590,9 +1675,9 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1590 *offset0 = *offset1 - field_offset * ps; 1675 *offset0 = *offset1 - field_offset * ps;
1591 else 1676 else
1592 *offset0 = *offset1; 1677 *offset0 = *offset1;
1593 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - 1678 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) -
1594 (fieldmode ? 1 : 0), ps); 1679 y_predecim - (fieldmode ? 1 : 0), ps);
1595 *pix_inc = pixinc(screen_width, ps); 1680 *pix_inc = pixinc(x_predecim * screen_width, ps);
1596 break; 1681 break;
1597 1682
1598 /* mirroring */ 1683 /* mirroring */
@@ -1602,10 +1687,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1602 *offset0 = *offset1 + field_offset * screen_width * ps; 1687 *offset0 = *offset1 + field_offset * screen_width * ps;
1603 else 1688 else
1604 *offset0 = *offset1; 1689 *offset0 = *offset1;
1605 *row_inc = pixinc(screen_width * 2 - 1 + 1690 *row_inc = pixinc(y_predecim * screen_width * 2 - 1 +
1606 (fieldmode ? screen_width : 0), 1691 (fieldmode ? screen_width : 0),
1607 ps); 1692 ps);
1608 *pix_inc = pixinc(-1, ps); 1693 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1694 color_mode == OMAP_DSS_COLOR_UYVY)
1695 *pix_inc = pixinc(-x_predecim, 2 * ps);
1696 else
1697 *pix_inc = pixinc(-x_predecim, ps);
1609 break; 1698 break;
1610 1699
1611 case OMAP_DSS_ROT_90 + 4: 1700 case OMAP_DSS_ROT_90 + 4:
@@ -1614,10 +1703,10 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1614 *offset0 = *offset1 + field_offset * ps; 1703 *offset0 = *offset1 + field_offset * ps;
1615 else 1704 else
1616 *offset0 = *offset1; 1705 *offset0 = *offset1;
1617 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + 1706 *row_inc = pixinc(-screen_width * (fbh * x_predecim - 1) +
1618 (fieldmode ? 1 : 0), 1707 y_predecim + (fieldmode ? 1 : 0),
1619 ps); 1708 ps);
1620 *pix_inc = pixinc(screen_width, ps); 1709 *pix_inc = pixinc(x_predecim * screen_width, ps);
1621 break; 1710 break;
1622 1711
1623 case OMAP_DSS_ROT_180 + 4: 1712 case OMAP_DSS_ROT_180 + 4:
@@ -1626,10 +1715,14 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1626 *offset0 = *offset1 - field_offset * screen_width * ps; 1715 *offset0 = *offset1 - field_offset * screen_width * ps;
1627 else 1716 else
1628 *offset0 = *offset1; 1717 *offset0 = *offset1;
1629 *row_inc = pixinc(1 - screen_width * 2 - 1718 *row_inc = pixinc(1 - y_predecim * screen_width * 2 -
1630 (fieldmode ? screen_width : 0), 1719 (fieldmode ? screen_width : 0),
1631 ps); 1720 ps);
1632 *pix_inc = pixinc(1, ps); 1721 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1722 color_mode == OMAP_DSS_COLOR_UYVY)
1723 *pix_inc = pixinc(x_predecim, 2 * ps);
1724 else
1725 *pix_inc = pixinc(x_predecim, ps);
1633 break; 1726 break;
1634 1727
1635 case OMAP_DSS_ROT_270 + 4: 1728 case OMAP_DSS_ROT_270 + 4:
@@ -1638,34 +1731,130 @@ static void calc_dma_rotation_offset(u8 rotation, bool mirror,
1638 *offset0 = *offset1 - field_offset * ps; 1731 *offset0 = *offset1 - field_offset * ps;
1639 else 1732 else
1640 *offset0 = *offset1; 1733 *offset0 = *offset1;
1641 *row_inc = pixinc(screen_width * (fbh - 1) - 1 - 1734 *row_inc = pixinc(screen_width * (fbh * x_predecim - 1) -
1642 (fieldmode ? 1 : 0), 1735 y_predecim - (fieldmode ? 1 : 0),
1643 ps); 1736 ps);
1644 *pix_inc = pixinc(-screen_width, ps); 1737 *pix_inc = pixinc(-x_predecim * screen_width, ps);
1645 break; 1738 break;
1646 1739
1647 default: 1740 default:
1648 BUG(); 1741 BUG();
1742 return;
1743 }
1744}
1745
1746static void calc_tiler_rotation_offset(u16 screen_width, u16 width,
1747 enum omap_color_mode color_mode, bool fieldmode,
1748 unsigned int field_offset, unsigned *offset0, unsigned *offset1,
1749 s32 *row_inc, s32 *pix_inc, int x_predecim, int y_predecim)
1750{
1751 u8 ps;
1752
1753 switch (color_mode) {
1754 case OMAP_DSS_COLOR_CLUT1:
1755 case OMAP_DSS_COLOR_CLUT2:
1756 case OMAP_DSS_COLOR_CLUT4:
1757 case OMAP_DSS_COLOR_CLUT8:
1758 BUG();
1759 return;
1760 default:
1761 ps = color_mode_to_bpp(color_mode) / 8;
1762 break;
1649 } 1763 }
1764
1765 DSSDBG("scrw %d, width %d\n", screen_width, width);
1766
1767 /*
1768 * field 0 = even field = bottom field
1769 * field 1 = odd field = top field
1770 */
1771 *offset1 = 0;
1772 if (field_offset)
1773 *offset0 = *offset1 + field_offset * screen_width * ps;
1774 else
1775 *offset0 = *offset1;
1776 *row_inc = pixinc(1 + (y_predecim * screen_width - width * x_predecim) +
1777 (fieldmode ? screen_width : 0), ps);
1778 if (color_mode == OMAP_DSS_COLOR_YUV2 ||
1779 color_mode == OMAP_DSS_COLOR_UYVY)
1780 *pix_inc = pixinc(x_predecim, 2 * ps);
1781 else
1782 *pix_inc = pixinc(x_predecim, ps);
1650} 1783}
1651 1784
1652static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width, 1785/*
1786 * This function is used to avoid synclosts in OMAP3, because of some
1787 * undocumented horizontal position and timing related limitations.
1788 */
1789static int check_horiz_timing_omap3(enum omap_channel channel,
1790 const struct omap_video_timings *t, u16 pos_x,
1791 u16 width, u16 height, u16 out_width, u16 out_height)
1792{
1793 int DS = DIV_ROUND_UP(height, out_height);
1794 unsigned long nonactive, lclk, pclk;
1795 static const u8 limits[3] = { 8, 10, 20 };
1796 u64 val, blank;
1797 int i;
1798
1799 nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
1800 pclk = dispc_mgr_pclk_rate(channel);
1801 if (dispc_mgr_is_lcd(channel))
1802 lclk = dispc_mgr_lclk_rate(channel);
1803 else
1804 lclk = dispc_fclk_rate();
1805
1806 i = 0;
1807 if (out_height < height)
1808 i++;
1809 if (out_width < width)
1810 i++;
1811 blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
1812 DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
1813 if (blank <= limits[i])
1814 return -EINVAL;
1815
1816 /*
1817 * Pixel data should be prepared before visible display point starts.
1818 * So, atleast DS-2 lines must have already been fetched by DISPC
1819 * during nonactive - pos_x period.
1820 */
1821 val = div_u64((u64)(nonactive - pos_x) * lclk, pclk);
1822 DSSDBG("(nonactive - pos_x) * pcd = %llu max(0, DS - 2) * width = %d\n",
1823 val, max(0, DS - 2) * width);
1824 if (val < max(0, DS - 2) * width)
1825 return -EINVAL;
1826
1827 /*
1828 * All lines need to be refilled during the nonactive period of which
1829 * only one line can be loaded during the active period. So, atleast
1830 * DS - 1 lines should be loaded during nonactive period.
1831 */
1832 val = div_u64((u64)nonactive * lclk, pclk);
1833 DSSDBG("nonactive * pcd = %llu, max(0, DS - 1) * width = %d\n",
1834 val, max(0, DS - 1) * width);
1835 if (val < max(0, DS - 1) * width)
1836 return -EINVAL;
1837
1838 return 0;
1839}
1840
1841static unsigned long calc_core_clk_five_taps(enum omap_channel channel,
1842 const struct omap_video_timings *mgr_timings, u16 width,
1653 u16 height, u16 out_width, u16 out_height, 1843 u16 height, u16 out_width, u16 out_height,
1654 enum omap_color_mode color_mode) 1844 enum omap_color_mode color_mode)
1655{ 1845{
1656 u32 fclk = 0; 1846 u32 core_clk = 0;
1657 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 1847 u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
1658 1848
1659 if (height <= out_height && width <= out_width) 1849 if (height <= out_height && width <= out_width)
1660 return (unsigned long) pclk; 1850 return (unsigned long) pclk;
1661 1851
1662 if (height > out_height) { 1852 if (height > out_height) {
1663 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); 1853 unsigned int ppl = mgr_timings->x_res;
1664 unsigned int ppl = dssdev->panel.timings.x_res;
1665 1854
1666 tmp = pclk * height * out_width; 1855 tmp = pclk * height * out_width;
1667 do_div(tmp, 2 * out_height * ppl); 1856 do_div(tmp, 2 * out_height * ppl);
1668 fclk = tmp; 1857 core_clk = tmp;
1669 1858
1670 if (height > 2 * out_height) { 1859 if (height > 2 * out_height) {
1671 if (ppl == out_width) 1860 if (ppl == out_width)
@@ -1673,23 +1862,23 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
1673 1862
1674 tmp = pclk * (height - 2 * out_height) * out_width; 1863 tmp = pclk * (height - 2 * out_height) * out_width;
1675 do_div(tmp, 2 * out_height * (ppl - out_width)); 1864 do_div(tmp, 2 * out_height * (ppl - out_width));
1676 fclk = max(fclk, (u32) tmp); 1865 core_clk = max_t(u32, core_clk, tmp);
1677 } 1866 }
1678 } 1867 }
1679 1868
1680 if (width > out_width) { 1869 if (width > out_width) {
1681 tmp = pclk * width; 1870 tmp = pclk * width;
1682 do_div(tmp, out_width); 1871 do_div(tmp, out_width);
1683 fclk = max(fclk, (u32) tmp); 1872 core_clk = max_t(u32, core_clk, tmp);
1684 1873
1685 if (color_mode == OMAP_DSS_COLOR_RGB24U) 1874 if (color_mode == OMAP_DSS_COLOR_RGB24U)
1686 fclk <<= 1; 1875 core_clk <<= 1;
1687 } 1876 }
1688 1877
1689 return fclk; 1878 return core_clk;
1690} 1879}
1691 1880
1692static unsigned long calc_fclk(enum omap_channel channel, u16 width, 1881static unsigned long calc_core_clk(enum omap_channel channel, u16 width,
1693 u16 height, u16 out_width, u16 out_height) 1882 u16 height, u16 out_width, u16 out_height)
1694{ 1883{
1695 unsigned int hf, vf; 1884 unsigned int hf, vf;
@@ -1730,15 +1919,20 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1730} 1919}
1731 1920
1732static int dispc_ovl_calc_scaling(enum omap_plane plane, 1921static int dispc_ovl_calc_scaling(enum omap_plane plane,
1733 enum omap_channel channel, u16 width, u16 height, 1922 enum omap_channel channel,
1734 u16 out_width, u16 out_height, 1923 const struct omap_video_timings *mgr_timings,
1735 enum omap_color_mode color_mode, bool *five_taps) 1924 u16 width, u16 height, u16 out_width, u16 out_height,
1925 enum omap_color_mode color_mode, bool *five_taps,
1926 int *x_predecim, int *y_predecim, u16 pos_x)
1736{ 1927{
1737 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1928 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1738 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 1929 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1739 const int maxsinglelinewidth = 1930 const int maxsinglelinewidth =
1740 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 1931 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
1741 unsigned long fclk = 0; 1932 const int max_decim_limit = 16;
1933 unsigned long core_clk = 0;
1934 int decim_x, decim_y, error, min_factor;
1935 u16 in_width, in_height, in_width_max = 0;
1742 1936
1743 if (width == out_width && height == out_height) 1937 if (width == out_width && height == out_height)
1744 return 0; 1938 return 0;
@@ -1746,64 +1940,154 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1746 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) 1940 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
1747 return -EINVAL; 1941 return -EINVAL;
1748 1942
1749 if (out_width < width / maxdownscale || 1943 *x_predecim = max_decim_limit;
1750 out_width > width * 8) 1944 *y_predecim = max_decim_limit;
1945
1946 if (color_mode == OMAP_DSS_COLOR_CLUT1 ||
1947 color_mode == OMAP_DSS_COLOR_CLUT2 ||
1948 color_mode == OMAP_DSS_COLOR_CLUT4 ||
1949 color_mode == OMAP_DSS_COLOR_CLUT8) {
1950 *x_predecim = 1;
1951 *y_predecim = 1;
1952 *five_taps = false;
1953 return 0;
1954 }
1955
1956 decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale);
1957 decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale);
1958
1959 min_factor = min(decim_x, decim_y);
1960
1961 if (decim_x > *x_predecim || out_width > width * 8)
1751 return -EINVAL; 1962 return -EINVAL;
1752 1963
1753 if (out_height < height / maxdownscale || 1964 if (decim_y > *y_predecim || out_height > height * 8)
1754 out_height > height * 8)
1755 return -EINVAL; 1965 return -EINVAL;
1756 1966
1757 if (cpu_is_omap24xx()) { 1967 if (cpu_is_omap24xx()) {
1758 if (width > maxsinglelinewidth)
1759 DSSERR("Cannot scale max input width exceeded");
1760 *five_taps = false; 1968 *five_taps = false;
1761 fclk = calc_fclk(channel, width, height, out_width, 1969
1762 out_height); 1970 do {
1971 in_height = DIV_ROUND_UP(height, decim_y);
1972 in_width = DIV_ROUND_UP(width, decim_x);
1973 core_clk = calc_core_clk(channel, in_width, in_height,
1974 out_width, out_height);
1975 error = (in_width > maxsinglelinewidth || !core_clk ||
1976 core_clk > dispc_core_clk_rate());
1977 if (error) {
1978 if (decim_x == decim_y) {
1979 decim_x = min_factor;
1980 decim_y++;
1981 } else {
1982 swap(decim_x, decim_y);
1983 if (decim_x < decim_y)
1984 decim_x++;
1985 }
1986 }
1987 } while (decim_x <= *x_predecim && decim_y <= *y_predecim &&
1988 error);
1989
1990 if (in_width > maxsinglelinewidth) {
1991 DSSERR("Cannot scale max input width exceeded");
1992 return -EINVAL;
1993 }
1763 } else if (cpu_is_omap34xx()) { 1994 } else if (cpu_is_omap34xx()) {
1764 if (width > (maxsinglelinewidth * 2)) { 1995
1996 do {
1997 in_height = DIV_ROUND_UP(height, decim_y);
1998 in_width = DIV_ROUND_UP(width, decim_x);
1999 core_clk = calc_core_clk_five_taps(channel, mgr_timings,
2000 in_width, in_height, out_width, out_height,
2001 color_mode);
2002
2003 error = check_horiz_timing_omap3(channel, mgr_timings,
2004 pos_x, in_width, in_height, out_width,
2005 out_height);
2006
2007 if (in_width > maxsinglelinewidth)
2008 if (in_height > out_height &&
2009 in_height < out_height * 2)
2010 *five_taps = false;
2011 if (!*five_taps)
2012 core_clk = calc_core_clk(channel, in_width,
2013 in_height, out_width, out_height);
2014 error = (error || in_width > maxsinglelinewidth * 2 ||
2015 (in_width > maxsinglelinewidth && *five_taps) ||
2016 !core_clk || core_clk > dispc_core_clk_rate());
2017 if (error) {
2018 if (decim_x == decim_y) {
2019 decim_x = min_factor;
2020 decim_y++;
2021 } else {
2022 swap(decim_x, decim_y);
2023 if (decim_x < decim_y)
2024 decim_x++;
2025 }
2026 }
2027 } while (decim_x <= *x_predecim && decim_y <= *y_predecim
2028 && error);
2029
2030 if (check_horiz_timing_omap3(channel, mgr_timings, pos_x, width,
2031 height, out_width, out_height)){
2032 DSSERR("horizontal timing too tight\n");
2033 return -EINVAL;
2034 }
2035
2036 if (in_width > (maxsinglelinewidth * 2)) {
1765 DSSERR("Cannot setup scaling"); 2037 DSSERR("Cannot setup scaling");
1766 DSSERR("width exceeds maximum width possible"); 2038 DSSERR("width exceeds maximum width possible");
1767 return -EINVAL; 2039 return -EINVAL;
1768 } 2040 }
1769 fclk = calc_fclk_five_taps(channel, width, height, out_width, 2041
1770 out_height, color_mode); 2042 if (in_width > maxsinglelinewidth && *five_taps) {
1771 if (width > maxsinglelinewidth) { 2043 DSSERR("cannot setup scaling with five taps");
1772 if (height > out_height && height < out_height * 2) 2044 return -EINVAL;
1773 *five_taps = false;
1774 else {
1775 DSSERR("cannot setup scaling with five taps");
1776 return -EINVAL;
1777 }
1778 } 2045 }
1779 if (!*five_taps)
1780 fclk = calc_fclk(channel, width, height, out_width,
1781 out_height);
1782 } else { 2046 } else {
1783 if (width > maxsinglelinewidth) { 2047 int decim_x_min = decim_x;
2048 in_height = DIV_ROUND_UP(height, decim_y);
2049 in_width_max = dispc_core_clk_rate() /
2050 DIV_ROUND_UP(dispc_mgr_pclk_rate(channel),
2051 out_width);
2052 decim_x = DIV_ROUND_UP(width, in_width_max);
2053
2054 decim_x = decim_x > decim_x_min ? decim_x : decim_x_min;
2055 if (decim_x > *x_predecim)
2056 return -EINVAL;
2057
2058 do {
2059 in_width = DIV_ROUND_UP(width, decim_x);
2060 } while (decim_x <= *x_predecim &&
2061 in_width > maxsinglelinewidth && decim_x++);
2062
2063 if (in_width > maxsinglelinewidth) {
1784 DSSERR("Cannot scale width exceeds max line width"); 2064 DSSERR("Cannot scale width exceeds max line width");
1785 return -EINVAL; 2065 return -EINVAL;
1786 } 2066 }
1787 fclk = calc_fclk(channel, width, height, out_width, 2067
1788 out_height); 2068 core_clk = calc_core_clk(channel, in_width, in_height,
2069 out_width, out_height);
1789 } 2070 }
1790 2071
1791 DSSDBG("required fclk rate = %lu Hz\n", fclk); 2072 DSSDBG("required core clk rate = %lu Hz\n", core_clk);
1792 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); 2073 DSSDBG("current core clk rate = %lu Hz\n", dispc_core_clk_rate());
1793 2074
1794 if (!fclk || fclk > dispc_fclk_rate()) { 2075 if (!core_clk || core_clk > dispc_core_clk_rate()) {
1795 DSSERR("failed to set up scaling, " 2076 DSSERR("failed to set up scaling, "
1796 "required fclk rate = %lu Hz, " 2077 "required core clk rate = %lu Hz, "
1797 "current fclk rate = %lu Hz\n", 2078 "current core clk rate = %lu Hz\n",
1798 fclk, dispc_fclk_rate()); 2079 core_clk, dispc_core_clk_rate());
1799 return -EINVAL; 2080 return -EINVAL;
1800 } 2081 }
1801 2082
2083 *x_predecim = decim_x;
2084 *y_predecim = decim_y;
1802 return 0; 2085 return 0;
1803} 2086}
1804 2087
1805int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 2088int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1806 bool ilace, bool replication) 2089 bool ilace, bool replication,
2090 const struct omap_video_timings *mgr_timings)
1807{ 2091{
1808 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 2092 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1809 bool five_taps = true; 2093 bool five_taps = true;
@@ -1814,8 +2098,11 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1814 s32 pix_inc; 2098 s32 pix_inc;
1815 u16 frame_height = oi->height; 2099 u16 frame_height = oi->height;
1816 unsigned int field_offset = 0; 2100 unsigned int field_offset = 0;
1817 u16 outw, outh; 2101 u16 in_height = oi->height;
2102 u16 in_width = oi->width;
2103 u16 out_width, out_height;
1818 enum omap_channel channel; 2104 enum omap_channel channel;
2105 int x_predecim = 1, y_predecim = 1;
1819 2106
1820 channel = dispc_ovl_get_channel_out(plane); 2107 channel = dispc_ovl_get_channel_out(plane);
1821 2108
@@ -1829,32 +2116,35 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1829 if (oi->paddr == 0) 2116 if (oi->paddr == 0)
1830 return -EINVAL; 2117 return -EINVAL;
1831 2118
1832 outw = oi->out_width == 0 ? oi->width : oi->out_width; 2119 out_width = oi->out_width == 0 ? oi->width : oi->out_width;
1833 outh = oi->out_height == 0 ? oi->height : oi->out_height; 2120 out_height = oi->out_height == 0 ? oi->height : oi->out_height;
1834 2121
1835 if (ilace && oi->height == outh) 2122 if (ilace && oi->height == out_height)
1836 fieldmode = 1; 2123 fieldmode = 1;
1837 2124
1838 if (ilace) { 2125 if (ilace) {
1839 if (fieldmode) 2126 if (fieldmode)
1840 oi->height /= 2; 2127 in_height /= 2;
1841 oi->pos_y /= 2; 2128 oi->pos_y /= 2;
1842 outh /= 2; 2129 out_height /= 2;
1843 2130
1844 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 2131 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1845 "out_height %d\n", 2132 "out_height %d\n",
1846 oi->height, oi->pos_y, outh); 2133 in_height, oi->pos_y, out_height);
1847 } 2134 }
1848 2135
1849 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 2136 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
1850 return -EINVAL; 2137 return -EINVAL;
1851 2138
1852 r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, 2139 r = dispc_ovl_calc_scaling(plane, channel, mgr_timings, in_width,
1853 outw, outh, oi->color_mode, 2140 in_height, out_width, out_height, oi->color_mode,
1854 &five_taps); 2141 &five_taps, &x_predecim, &y_predecim, oi->pos_x);
1855 if (r) 2142 if (r)
1856 return r; 2143 return r;
1857 2144
2145 in_width = DIV_ROUND_UP(in_width, x_predecim);
2146 in_height = DIV_ROUND_UP(in_height, y_predecim);
2147
1858 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 2148 if (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
1859 oi->color_mode == OMAP_DSS_COLOR_UYVY || 2149 oi->color_mode == OMAP_DSS_COLOR_UYVY ||
1860 oi->color_mode == OMAP_DSS_COLOR_NV12) 2150 oi->color_mode == OMAP_DSS_COLOR_NV12)
@@ -1868,32 +2158,46 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1868 * so the integer part must be added to the base address of the 2158 * so the integer part must be added to the base address of the
1869 * bottom field. 2159 * bottom field.
1870 */ 2160 */
1871 if (!oi->height || oi->height == outh) 2161 if (!in_height || in_height == out_height)
1872 field_offset = 0; 2162 field_offset = 0;
1873 else 2163 else
1874 field_offset = oi->height / outh / 2; 2164 field_offset = in_height / out_height / 2;
1875 } 2165 }
1876 2166
1877 /* Fields are independent but interleaved in memory. */ 2167 /* Fields are independent but interleaved in memory. */
1878 if (fieldmode) 2168 if (fieldmode)
1879 field_offset = 1; 2169 field_offset = 1;
1880 2170
1881 if (oi->rotation_type == OMAP_DSS_ROT_DMA) 2171 offset0 = 0;
2172 offset1 = 0;
2173 row_inc = 0;
2174 pix_inc = 0;
2175
2176 if (oi->rotation_type == OMAP_DSS_ROT_TILER)
2177 calc_tiler_rotation_offset(oi->screen_width, in_width,
2178 oi->color_mode, fieldmode, field_offset,
2179 &offset0, &offset1, &row_inc, &pix_inc,
2180 x_predecim, y_predecim);
2181 else if (oi->rotation_type == OMAP_DSS_ROT_DMA)
1882 calc_dma_rotation_offset(oi->rotation, oi->mirror, 2182 calc_dma_rotation_offset(oi->rotation, oi->mirror,
1883 oi->screen_width, oi->width, frame_height, 2183 oi->screen_width, in_width, frame_height,
1884 oi->color_mode, fieldmode, field_offset, 2184 oi->color_mode, fieldmode, field_offset,
1885 &offset0, &offset1, &row_inc, &pix_inc); 2185 &offset0, &offset1, &row_inc, &pix_inc,
2186 x_predecim, y_predecim);
1886 else 2187 else
1887 calc_vrfb_rotation_offset(oi->rotation, oi->mirror, 2188 calc_vrfb_rotation_offset(oi->rotation, oi->mirror,
1888 oi->screen_width, oi->width, frame_height, 2189 oi->screen_width, in_width, frame_height,
1889 oi->color_mode, fieldmode, field_offset, 2190 oi->color_mode, fieldmode, field_offset,
1890 &offset0, &offset1, &row_inc, &pix_inc); 2191 &offset0, &offset1, &row_inc, &pix_inc,
2192 x_predecim, y_predecim);
1891 2193
1892 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 2194 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n",
1893 offset0, offset1, row_inc, pix_inc); 2195 offset0, offset1, row_inc, pix_inc);
1894 2196
1895 dispc_ovl_set_color_mode(plane, oi->color_mode); 2197 dispc_ovl_set_color_mode(plane, oi->color_mode);
1896 2198
2199 dispc_ovl_configure_burst_type(plane, oi->rotation_type);
2200
1897 dispc_ovl_set_ba0(plane, oi->paddr + offset0); 2201 dispc_ovl_set_ba0(plane, oi->paddr + offset0);
1898 dispc_ovl_set_ba1(plane, oi->paddr + offset1); 2202 dispc_ovl_set_ba1(plane, oi->paddr + offset1);
1899 2203
@@ -1906,19 +2210,18 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1906 dispc_ovl_set_row_inc(plane, row_inc); 2210 dispc_ovl_set_row_inc(plane, row_inc);
1907 dispc_ovl_set_pix_inc(plane, pix_inc); 2211 dispc_ovl_set_pix_inc(plane, pix_inc);
1908 2212
1909 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, 2213 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, in_width,
1910 oi->height, outw, outh); 2214 in_height, out_width, out_height);
1911 2215
1912 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 2216 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
1913 2217
1914 dispc_ovl_set_pic_size(plane, oi->width, oi->height); 2218 dispc_ovl_set_pic_size(plane, in_width, in_height);
1915 2219
1916 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 2220 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
1917 dispc_ovl_set_scaling(plane, oi->width, oi->height, 2221 dispc_ovl_set_scaling(plane, in_width, in_height, out_width,
1918 outw, outh, 2222 out_height, ilace, five_taps, fieldmode,
1919 ilace, five_taps, fieldmode,
1920 oi->color_mode, oi->rotation); 2223 oi->color_mode, oi->rotation);
1921 dispc_ovl_set_vid_size(plane, outw, outh); 2224 dispc_ovl_set_vid_size(plane, out_width, out_height);
1922 dispc_ovl_set_vid_color_conv(plane, cconv); 2225 dispc_ovl_set_vid_color_conv(plane, cconv);
1923 } 2226 }
1924 2227
@@ -2087,8 +2390,10 @@ bool dispc_mgr_is_enabled(enum omap_channel channel)
2087 return !!REG_GET(DISPC_CONTROL, 1, 1); 2390 return !!REG_GET(DISPC_CONTROL, 1, 1);
2088 else if (channel == OMAP_DSS_CHANNEL_LCD2) 2391 else if (channel == OMAP_DSS_CHANNEL_LCD2)
2089 return !!REG_GET(DISPC_CONTROL2, 0, 0); 2392 return !!REG_GET(DISPC_CONTROL2, 0, 0);
2090 else 2393 else {
2091 BUG(); 2394 BUG();
2395 return false;
2396 }
2092} 2397}
2093 2398
2094void dispc_mgr_enable(enum omap_channel channel, bool enable) 2399void dispc_mgr_enable(enum omap_channel channel, bool enable)
@@ -2285,6 +2590,12 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable)
2285 REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11); 2590 REG_FLD_MOD(DISPC_CONTROL, enable, 11, 11);
2286} 2591}
2287 2592
2593static bool _dispc_mgr_size_ok(u16 width, u16 height)
2594{
2595 return width <= dss_feat_get_param_max(FEAT_PARAM_MGR_WIDTH) &&
2596 height <= dss_feat_get_param_max(FEAT_PARAM_MGR_HEIGHT);
2597}
2598
2288static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2599static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2289 int vsw, int vfp, int vbp) 2600 int vsw, int vfp, int vbp)
2290{ 2601{
@@ -2309,11 +2620,20 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
2309 return true; 2620 return true;
2310} 2621}
2311 2622
2312bool dispc_lcd_timings_ok(struct omap_video_timings *timings) 2623bool dispc_mgr_timings_ok(enum omap_channel channel,
2624 const struct omap_video_timings *timings)
2313{ 2625{
2314 return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, 2626 bool timings_ok;
2315 timings->hbp, timings->vsw, 2627
2316 timings->vfp, timings->vbp); 2628 timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
2629
2630 if (dispc_mgr_is_lcd(channel))
2631 timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw,
2632 timings->hfp, timings->hbp,
2633 timings->vsw, timings->vfp,
2634 timings->vbp);
2635
2636 return timings_ok;
2317} 2637}
2318 2638
2319static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, 2639static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
@@ -2340,37 +2660,45 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2340} 2660}
2341 2661
2342/* change name to mode? */ 2662/* change name to mode? */
2343void dispc_mgr_set_lcd_timings(enum omap_channel channel, 2663void dispc_mgr_set_timings(enum omap_channel channel,
2344 struct omap_video_timings *timings) 2664 struct omap_video_timings *timings)
2345{ 2665{
2346 unsigned xtot, ytot; 2666 unsigned xtot, ytot;
2347 unsigned long ht, vt; 2667 unsigned long ht, vt;
2668 struct omap_video_timings t = *timings;
2669
2670 DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
2348 2671
2349 if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, 2672 if (!dispc_mgr_timings_ok(channel, &t)) {
2350 timings->hbp, timings->vsw,
2351 timings->vfp, timings->vbp))
2352 BUG(); 2673 BUG();
2674 return;
2675 }
2676
2677 if (dispc_mgr_is_lcd(channel)) {
2678 _dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
2679 t.vfp, t.vbp);
2680
2681 xtot = t.x_res + t.hfp + t.hsw + t.hbp;
2682 ytot = t.y_res + t.vfp + t.vsw + t.vbp;
2353 2683
2354 _dispc_mgr_set_lcd_timings(channel, timings->hsw, timings->hfp, 2684 ht = (timings->pixel_clock * 1000) / xtot;
2355 timings->hbp, timings->vsw, timings->vfp, 2685 vt = (timings->pixel_clock * 1000) / xtot / ytot;
2356 timings->vbp);
2357 2686
2358 dispc_mgr_set_lcd_size(channel, timings->x_res, timings->y_res); 2687 DSSDBG("pck %u\n", timings->pixel_clock);
2688 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2689 t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
2359 2690
2360 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; 2691 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
2361 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; 2692 } else {
2693 enum dss_hdmi_venc_clk_source_select source;
2362 2694
2363 ht = (timings->pixel_clock * 1000) / xtot; 2695 source = dss_get_hdmi_venc_clk_source();
2364 vt = (timings->pixel_clock * 1000) / xtot / ytot;
2365 2696
2366 DSSDBG("channel %d xres %u yres %u\n", channel, timings->x_res, 2697 if (source == DSS_VENC_TV_CLK)
2367 timings->y_res); 2698 t.y_res /= 2;
2368 DSSDBG("pck %u\n", timings->pixel_clock); 2699 }
2369 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
2370 timings->hsw, timings->hfp, timings->hbp,
2371 timings->vsw, timings->vfp, timings->vbp);
2372 2700
2373 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); 2701 dispc_mgr_set_size(channel, t.x_res, t.y_res);
2374} 2702}
2375 2703
2376static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, 2704static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div,
@@ -2411,6 +2739,7 @@ unsigned long dispc_fclk_rate(void)
2411 break; 2739 break;
2412 default: 2740 default:
2413 BUG(); 2741 BUG();
2742 return 0;
2414 } 2743 }
2415 2744
2416 return r; 2745 return r;
@@ -2441,6 +2770,7 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
2441 break; 2770 break;
2442 default: 2771 default:
2443 BUG(); 2772 BUG();
2773 return 0;
2444 } 2774 }
2445 2775
2446 return r / lcd; 2776 return r / lcd;
@@ -2462,20 +2792,35 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel)
2462 2792
2463 return r / pcd; 2793 return r / pcd;
2464 } else { 2794 } else {
2465 struct omap_dss_device *dssdev = 2795 enum dss_hdmi_venc_clk_source_select source;
2466 dispc_mgr_get_device(channel);
2467 2796
2468 switch (dssdev->type) { 2797 source = dss_get_hdmi_venc_clk_source();
2469 case OMAP_DISPLAY_TYPE_VENC: 2798
2799 switch (source) {
2800 case DSS_VENC_TV_CLK:
2470 return venc_get_pixel_clock(); 2801 return venc_get_pixel_clock();
2471 case OMAP_DISPLAY_TYPE_HDMI: 2802 case DSS_HDMI_M_PCLK:
2472 return hdmi_get_pixel_clock(); 2803 return hdmi_get_pixel_clock();
2473 default: 2804 default:
2474 BUG(); 2805 BUG();
2806 return 0;
2475 } 2807 }
2476 } 2808 }
2477} 2809}
2478 2810
2811unsigned long dispc_core_clk_rate(void)
2812{
2813 int lcd;
2814 unsigned long fclk = dispc_fclk_rate();
2815
2816 if (dss_has_feature(FEAT_CORE_CLK_DIV))
2817 lcd = REG_GET(DISPC_DIVISOR, 23, 16);
2818 else
2819 lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16);
2820
2821 return fclk / lcd;
2822}
2823
2479void dispc_dump_clocks(struct seq_file *s) 2824void dispc_dump_clocks(struct seq_file *s)
2480{ 2825{
2481 int lcd, pcd; 2826 int lcd, pcd;
@@ -2588,7 +2933,7 @@ void dispc_dump_irqs(struct seq_file *s)
2588} 2933}
2589#endif 2934#endif
2590 2935
2591void dispc_dump_regs(struct seq_file *s) 2936static void dispc_dump_regs(struct seq_file *s)
2592{ 2937{
2593 int i, j; 2938 int i, j;
2594 const char *mgr_names[] = { 2939 const char *mgr_names[] = {
@@ -3247,27 +3592,6 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
3247 return 0; 3592 return 0;
3248} 3593}
3249 3594
3250#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
3251void dispc_fake_vsync_irq(void)
3252{
3253 u32 irqstatus = DISPC_IRQ_VSYNC;
3254 int i;
3255
3256 WARN_ON(!in_interrupt());
3257
3258 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) {
3259 struct omap_dispc_isr_data *isr_data;
3260 isr_data = &dispc.registered_isr[i];
3261
3262 if (!isr_data->isr)
3263 continue;
3264
3265 if (isr_data->mask & irqstatus)
3266 isr_data->isr(isr_data->arg, irqstatus);
3267 }
3268}
3269#endif
3270
3271static void _omap_dispc_initialize_irq(void) 3595static void _omap_dispc_initialize_irq(void)
3272{ 3596{
3273 unsigned long flags; 3597 unsigned long flags;
@@ -3330,7 +3654,7 @@ static void _omap_dispc_initial_config(void)
3330} 3654}
3331 3655
3332/* DISPC HW IP initialisation */ 3656/* DISPC HW IP initialisation */
3333static int omap_dispchw_probe(struct platform_device *pdev) 3657static int __init omap_dispchw_probe(struct platform_device *pdev)
3334{ 3658{
3335 u32 rev; 3659 u32 rev;
3336 int r = 0; 3660 int r = 0;
@@ -3399,6 +3723,11 @@ static int omap_dispchw_probe(struct platform_device *pdev)
3399 3723
3400 dispc_runtime_put(); 3724 dispc_runtime_put();
3401 3725
3726 dss_debugfs_create_file("dispc", dispc_dump_regs);
3727
3728#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3729 dss_debugfs_create_file("dispc_irq", dispc_dump_irqs);
3730#endif
3402 return 0; 3731 return 0;
3403 3732
3404err_runtime_get: 3733err_runtime_get:
@@ -3407,7 +3736,7 @@ err_runtime_get:
3407 return r; 3736 return r;
3408} 3737}
3409 3738
3410static int omap_dispchw_remove(struct platform_device *pdev) 3739static int __exit omap_dispchw_remove(struct platform_device *pdev)
3411{ 3740{
3412 pm_runtime_disable(&pdev->dev); 3741 pm_runtime_disable(&pdev->dev);
3413 3742
@@ -3419,19 +3748,12 @@ static int omap_dispchw_remove(struct platform_device *pdev)
3419static int dispc_runtime_suspend(struct device *dev) 3748static int dispc_runtime_suspend(struct device *dev)
3420{ 3749{
3421 dispc_save_context(); 3750 dispc_save_context();
3422 dss_runtime_put();
3423 3751
3424 return 0; 3752 return 0;
3425} 3753}
3426 3754
3427static int dispc_runtime_resume(struct device *dev) 3755static int dispc_runtime_resume(struct device *dev)
3428{ 3756{
3429 int r;
3430
3431 r = dss_runtime_get();
3432 if (r < 0)
3433 return r;
3434
3435 dispc_restore_context(); 3757 dispc_restore_context();
3436 3758
3437 return 0; 3759 return 0;
@@ -3443,8 +3765,7 @@ static const struct dev_pm_ops dispc_pm_ops = {
3443}; 3765};
3444 3766
3445static struct platform_driver omap_dispchw_driver = { 3767static struct platform_driver omap_dispchw_driver = {
3446 .probe = omap_dispchw_probe, 3768 .remove = __exit_p(omap_dispchw_remove),
3447 .remove = omap_dispchw_remove,
3448 .driver = { 3769 .driver = {
3449 .name = "omapdss_dispc", 3770 .name = "omapdss_dispc",
3450 .owner = THIS_MODULE, 3771 .owner = THIS_MODULE,
@@ -3452,12 +3773,12 @@ static struct platform_driver omap_dispchw_driver = {
3452 }, 3773 },
3453}; 3774};
3454 3775
3455int dispc_init_platform_driver(void) 3776int __init dispc_init_platform_driver(void)
3456{ 3777{
3457 return platform_driver_register(&omap_dispchw_driver); 3778 return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe);
3458} 3779}
3459 3780
3460void dispc_uninit_platform_driver(void) 3781void __exit dispc_uninit_platform_driver(void)
3461{ 3782{
3462 return platform_driver_unregister(&omap_dispchw_driver); 3783 platform_driver_unregister(&omap_dispchw_driver);
3463} 3784}
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index 5836bd1650f9..f278080e1063 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -120,6 +120,7 @@ static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
120 return 0x03AC; 120 return 0x03AC;
121 default: 121 default:
122 BUG(); 122 BUG();
123 return 0;
123 } 124 }
124} 125}
125 126
@@ -134,6 +135,7 @@ static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
134 return 0x03B0; 135 return 0x03B0;
135 default: 136 default:
136 BUG(); 137 BUG();
138 return 0;
137 } 139 }
138} 140}
139 141
@@ -144,10 +146,12 @@ static inline u16 DISPC_TIMING_H(enum omap_channel channel)
144 return 0x0064; 146 return 0x0064;
145 case OMAP_DSS_CHANNEL_DIGIT: 147 case OMAP_DSS_CHANNEL_DIGIT:
146 BUG(); 148 BUG();
149 return 0;
147 case OMAP_DSS_CHANNEL_LCD2: 150 case OMAP_DSS_CHANNEL_LCD2:
148 return 0x0400; 151 return 0x0400;
149 default: 152 default:
150 BUG(); 153 BUG();
154 return 0;
151 } 155 }
152} 156}
153 157
@@ -158,10 +162,12 @@ static inline u16 DISPC_TIMING_V(enum omap_channel channel)
158 return 0x0068; 162 return 0x0068;
159 case OMAP_DSS_CHANNEL_DIGIT: 163 case OMAP_DSS_CHANNEL_DIGIT:
160 BUG(); 164 BUG();
165 return 0;
161 case OMAP_DSS_CHANNEL_LCD2: 166 case OMAP_DSS_CHANNEL_LCD2:
162 return 0x0404; 167 return 0x0404;
163 default: 168 default:
164 BUG(); 169 BUG();
170 return 0;
165 } 171 }
166} 172}
167 173
@@ -172,10 +178,12 @@ static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
172 return 0x006C; 178 return 0x006C;
173 case OMAP_DSS_CHANNEL_DIGIT: 179 case OMAP_DSS_CHANNEL_DIGIT:
174 BUG(); 180 BUG();
181 return 0;
175 case OMAP_DSS_CHANNEL_LCD2: 182 case OMAP_DSS_CHANNEL_LCD2:
176 return 0x0408; 183 return 0x0408;
177 default: 184 default:
178 BUG(); 185 BUG();
186 return 0;
179 } 187 }
180} 188}
181 189
@@ -186,10 +194,12 @@ static inline u16 DISPC_DIVISORo(enum omap_channel channel)
186 return 0x0070; 194 return 0x0070;
187 case OMAP_DSS_CHANNEL_DIGIT: 195 case OMAP_DSS_CHANNEL_DIGIT:
188 BUG(); 196 BUG();
197 return 0;
189 case OMAP_DSS_CHANNEL_LCD2: 198 case OMAP_DSS_CHANNEL_LCD2:
190 return 0x040C; 199 return 0x040C;
191 default: 200 default:
192 BUG(); 201 BUG();
202 return 0;
193 } 203 }
194} 204}
195 205
@@ -205,6 +215,7 @@ static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
205 return 0x03CC; 215 return 0x03CC;
206 default: 216 default:
207 BUG(); 217 BUG();
218 return 0;
208 } 219 }
209} 220}
210 221
@@ -215,10 +226,12 @@ static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
215 return 0x01D4; 226 return 0x01D4;
216 case OMAP_DSS_CHANNEL_DIGIT: 227 case OMAP_DSS_CHANNEL_DIGIT:
217 BUG(); 228 BUG();
229 return 0;
218 case OMAP_DSS_CHANNEL_LCD2: 230 case OMAP_DSS_CHANNEL_LCD2:
219 return 0x03C0; 231 return 0x03C0;
220 default: 232 default:
221 BUG(); 233 BUG();
234 return 0;
222 } 235 }
223} 236}
224 237
@@ -229,10 +242,12 @@ static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
229 return 0x01D8; 242 return 0x01D8;
230 case OMAP_DSS_CHANNEL_DIGIT: 243 case OMAP_DSS_CHANNEL_DIGIT:
231 BUG(); 244 BUG();
245 return 0;
232 case OMAP_DSS_CHANNEL_LCD2: 246 case OMAP_DSS_CHANNEL_LCD2:
233 return 0x03C4; 247 return 0x03C4;
234 default: 248 default:
235 BUG(); 249 BUG();
250 return 0;
236 } 251 }
237} 252}
238 253
@@ -243,10 +258,12 @@ static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
243 return 0x01DC; 258 return 0x01DC;
244 case OMAP_DSS_CHANNEL_DIGIT: 259 case OMAP_DSS_CHANNEL_DIGIT:
245 BUG(); 260 BUG();
261 return 0;
246 case OMAP_DSS_CHANNEL_LCD2: 262 case OMAP_DSS_CHANNEL_LCD2:
247 return 0x03C8; 263 return 0x03C8;
248 default: 264 default:
249 BUG(); 265 BUG();
266 return 0;
250 } 267 }
251} 268}
252 269
@@ -257,10 +274,12 @@ static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
257 return 0x0220; 274 return 0x0220;
258 case OMAP_DSS_CHANNEL_DIGIT: 275 case OMAP_DSS_CHANNEL_DIGIT:
259 BUG(); 276 BUG();
277 return 0;
260 case OMAP_DSS_CHANNEL_LCD2: 278 case OMAP_DSS_CHANNEL_LCD2:
261 return 0x03BC; 279 return 0x03BC;
262 default: 280 default:
263 BUG(); 281 BUG();
282 return 0;
264 } 283 }
265} 284}
266 285
@@ -271,10 +290,12 @@ static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
271 return 0x0224; 290 return 0x0224;
272 case OMAP_DSS_CHANNEL_DIGIT: 291 case OMAP_DSS_CHANNEL_DIGIT:
273 BUG(); 292 BUG();
293 return 0;
274 case OMAP_DSS_CHANNEL_LCD2: 294 case OMAP_DSS_CHANNEL_LCD2:
275 return 0x03B8; 295 return 0x03B8;
276 default: 296 default:
277 BUG(); 297 BUG();
298 return 0;
278 } 299 }
279} 300}
280 301
@@ -285,10 +306,12 @@ static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
285 return 0x0228; 306 return 0x0228;
286 case OMAP_DSS_CHANNEL_DIGIT: 307 case OMAP_DSS_CHANNEL_DIGIT:
287 BUG(); 308 BUG();
309 return 0;
288 case OMAP_DSS_CHANNEL_LCD2: 310 case OMAP_DSS_CHANNEL_LCD2:
289 return 0x03B4; 311 return 0x03B4;
290 default: 312 default:
291 BUG(); 313 BUG();
314 return 0;
292 } 315 }
293} 316}
294 317
@@ -306,6 +329,7 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
306 return 0x0300; 329 return 0x0300;
307 default: 330 default:
308 BUG(); 331 BUG();
332 return 0;
309 } 333 }
310} 334}
311 335
@@ -321,6 +345,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
321 return 0x0008; 345 return 0x0008;
322 default: 346 default:
323 BUG(); 347 BUG();
348 return 0;
324 } 349 }
325} 350}
326 351
@@ -335,6 +360,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
335 return 0x000C; 360 return 0x000C;
336 default: 361 default:
337 BUG(); 362 BUG();
363 return 0;
338 } 364 }
339} 365}
340 366
@@ -343,6 +369,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
343 switch (plane) { 369 switch (plane) {
344 case OMAP_DSS_GFX: 370 case OMAP_DSS_GFX:
345 BUG(); 371 BUG();
372 return 0;
346 case OMAP_DSS_VIDEO1: 373 case OMAP_DSS_VIDEO1:
347 return 0x0544; 374 return 0x0544;
348 case OMAP_DSS_VIDEO2: 375 case OMAP_DSS_VIDEO2:
@@ -351,6 +378,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
351 return 0x0310; 378 return 0x0310;
352 default: 379 default:
353 BUG(); 380 BUG();
381 return 0;
354 } 382 }
355} 383}
356 384
@@ -359,6 +387,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
359 switch (plane) { 387 switch (plane) {
360 case OMAP_DSS_GFX: 388 case OMAP_DSS_GFX:
361 BUG(); 389 BUG();
390 return 0;
362 case OMAP_DSS_VIDEO1: 391 case OMAP_DSS_VIDEO1:
363 return 0x0548; 392 return 0x0548;
364 case OMAP_DSS_VIDEO2: 393 case OMAP_DSS_VIDEO2:
@@ -367,6 +396,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
367 return 0x0314; 396 return 0x0314;
368 default: 397 default:
369 BUG(); 398 BUG();
399 return 0;
370 } 400 }
371} 401}
372 402
@@ -381,6 +411,7 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
381 return 0x009C; 411 return 0x009C;
382 default: 412 default:
383 BUG(); 413 BUG();
414 return 0;
384 } 415 }
385} 416}
386 417
@@ -395,6 +426,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
395 return 0x00A8; 426 return 0x00A8;
396 default: 427 default:
397 BUG(); 428 BUG();
429 return 0;
398 } 430 }
399} 431}
400 432
@@ -410,6 +442,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
410 return 0x0070; 442 return 0x0070;
411 default: 443 default:
412 BUG(); 444 BUG();
445 return 0;
413 } 446 }
414} 447}
415 448
@@ -418,6 +451,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
418 switch (plane) { 451 switch (plane) {
419 case OMAP_DSS_GFX: 452 case OMAP_DSS_GFX:
420 BUG(); 453 BUG();
454 return 0;
421 case OMAP_DSS_VIDEO1: 455 case OMAP_DSS_VIDEO1:
422 return 0x0568; 456 return 0x0568;
423 case OMAP_DSS_VIDEO2: 457 case OMAP_DSS_VIDEO2:
@@ -426,6 +460,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
426 return 0x032C; 460 return 0x032C;
427 default: 461 default:
428 BUG(); 462 BUG();
463 return 0;
429 } 464 }
430} 465}
431 466
@@ -441,6 +476,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
441 return 0x008C; 476 return 0x008C;
442 default: 477 default:
443 BUG(); 478 BUG();
479 return 0;
444 } 480 }
445} 481}
446 482
@@ -456,6 +492,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
456 return 0x0088; 492 return 0x0088;
457 default: 493 default:
458 BUG(); 494 BUG();
495 return 0;
459 } 496 }
460} 497}
461 498
@@ -471,6 +508,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
471 return 0x00A4; 508 return 0x00A4;
472 default: 509 default:
473 BUG(); 510 BUG();
511 return 0;
474 } 512 }
475} 513}
476 514
@@ -486,6 +524,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
486 return 0x0098; 524 return 0x0098;
487 default: 525 default:
488 BUG(); 526 BUG();
527 return 0;
489 } 528 }
490} 529}
491 530
@@ -498,8 +537,10 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
498 case OMAP_DSS_VIDEO2: 537 case OMAP_DSS_VIDEO2:
499 case OMAP_DSS_VIDEO3: 538 case OMAP_DSS_VIDEO3:
500 BUG(); 539 BUG();
540 return 0;
501 default: 541 default:
502 BUG(); 542 BUG();
543 return 0;
503 } 544 }
504} 545}
505 546
@@ -512,8 +553,10 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
512 case OMAP_DSS_VIDEO2: 553 case OMAP_DSS_VIDEO2:
513 case OMAP_DSS_VIDEO3: 554 case OMAP_DSS_VIDEO3:
514 BUG(); 555 BUG();
556 return 0;
515 default: 557 default:
516 BUG(); 558 BUG();
559 return 0;
517 } 560 }
518} 561}
519 562
@@ -522,6 +565,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
522 switch (plane) { 565 switch (plane) {
523 case OMAP_DSS_GFX: 566 case OMAP_DSS_GFX:
524 BUG(); 567 BUG();
568 return 0;
525 case OMAP_DSS_VIDEO1: 569 case OMAP_DSS_VIDEO1:
526 case OMAP_DSS_VIDEO2: 570 case OMAP_DSS_VIDEO2:
527 return 0x0024; 571 return 0x0024;
@@ -529,6 +573,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
529 return 0x0090; 573 return 0x0090;
530 default: 574 default:
531 BUG(); 575 BUG();
576 return 0;
532 } 577 }
533} 578}
534 579
@@ -537,6 +582,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
537 switch (plane) { 582 switch (plane) {
538 case OMAP_DSS_GFX: 583 case OMAP_DSS_GFX:
539 BUG(); 584 BUG();
585 return 0;
540 case OMAP_DSS_VIDEO1: 586 case OMAP_DSS_VIDEO1:
541 return 0x0580; 587 return 0x0580;
542 case OMAP_DSS_VIDEO2: 588 case OMAP_DSS_VIDEO2:
@@ -545,6 +591,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
545 return 0x0424; 591 return 0x0424;
546 default: 592 default:
547 BUG(); 593 BUG();
594 return 0;
548 } 595 }
549} 596}
550 597
@@ -553,6 +600,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
553 switch (plane) { 600 switch (plane) {
554 case OMAP_DSS_GFX: 601 case OMAP_DSS_GFX:
555 BUG(); 602 BUG();
603 return 0;
556 case OMAP_DSS_VIDEO1: 604 case OMAP_DSS_VIDEO1:
557 case OMAP_DSS_VIDEO2: 605 case OMAP_DSS_VIDEO2:
558 return 0x0028; 606 return 0x0028;
@@ -560,6 +608,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
560 return 0x0094; 608 return 0x0094;
561 default: 609 default:
562 BUG(); 610 BUG();
611 return 0;
563 } 612 }
564} 613}
565 614
@@ -569,6 +618,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
569 switch (plane) { 618 switch (plane) {
570 case OMAP_DSS_GFX: 619 case OMAP_DSS_GFX:
571 BUG(); 620 BUG();
621 return 0;
572 case OMAP_DSS_VIDEO1: 622 case OMAP_DSS_VIDEO1:
573 case OMAP_DSS_VIDEO2: 623 case OMAP_DSS_VIDEO2:
574 return 0x002C; 624 return 0x002C;
@@ -576,6 +626,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
576 return 0x0000; 626 return 0x0000;
577 default: 627 default:
578 BUG(); 628 BUG();
629 return 0;
579 } 630 }
580} 631}
581 632
@@ -584,6 +635,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
584 switch (plane) { 635 switch (plane) {
585 case OMAP_DSS_GFX: 636 case OMAP_DSS_GFX:
586 BUG(); 637 BUG();
638 return 0;
587 case OMAP_DSS_VIDEO1: 639 case OMAP_DSS_VIDEO1:
588 return 0x0584; 640 return 0x0584;
589 case OMAP_DSS_VIDEO2: 641 case OMAP_DSS_VIDEO2:
@@ -592,6 +644,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
592 return 0x0428; 644 return 0x0428;
593 default: 645 default:
594 BUG(); 646 BUG();
647 return 0;
595 } 648 }
596} 649}
597 650
@@ -600,6 +653,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
600 switch (plane) { 653 switch (plane) {
601 case OMAP_DSS_GFX: 654 case OMAP_DSS_GFX:
602 BUG(); 655 BUG();
656 return 0;
603 case OMAP_DSS_VIDEO1: 657 case OMAP_DSS_VIDEO1:
604 case OMAP_DSS_VIDEO2: 658 case OMAP_DSS_VIDEO2:
605 return 0x0030; 659 return 0x0030;
@@ -607,6 +661,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
607 return 0x0004; 661 return 0x0004;
608 default: 662 default:
609 BUG(); 663 BUG();
664 return 0;
610 } 665 }
611} 666}
612 667
@@ -615,6 +670,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
615 switch (plane) { 670 switch (plane) {
616 case OMAP_DSS_GFX: 671 case OMAP_DSS_GFX:
617 BUG(); 672 BUG();
673 return 0;
618 case OMAP_DSS_VIDEO1: 674 case OMAP_DSS_VIDEO1:
619 return 0x0588; 675 return 0x0588;
620 case OMAP_DSS_VIDEO2: 676 case OMAP_DSS_VIDEO2:
@@ -623,6 +679,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
623 return 0x042C; 679 return 0x042C;
624 default: 680 default:
625 BUG(); 681 BUG();
682 return 0;
626 } 683 }
627} 684}
628 685
@@ -632,6 +689,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
632 switch (plane) { 689 switch (plane) {
633 case OMAP_DSS_GFX: 690 case OMAP_DSS_GFX:
634 BUG(); 691 BUG();
692 return 0;
635 case OMAP_DSS_VIDEO1: 693 case OMAP_DSS_VIDEO1:
636 case OMAP_DSS_VIDEO2: 694 case OMAP_DSS_VIDEO2:
637 return 0x0034 + i * 0x8; 695 return 0x0034 + i * 0x8;
@@ -639,6 +697,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
639 return 0x0010 + i * 0x8; 697 return 0x0010 + i * 0x8;
640 default: 698 default:
641 BUG(); 699 BUG();
700 return 0;
642 } 701 }
643} 702}
644 703
@@ -648,6 +707,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
648 switch (plane) { 707 switch (plane) {
649 case OMAP_DSS_GFX: 708 case OMAP_DSS_GFX:
650 BUG(); 709 BUG();
710 return 0;
651 case OMAP_DSS_VIDEO1: 711 case OMAP_DSS_VIDEO1:
652 return 0x058C + i * 0x8; 712 return 0x058C + i * 0x8;
653 case OMAP_DSS_VIDEO2: 713 case OMAP_DSS_VIDEO2:
@@ -656,6 +716,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
656 return 0x0430 + i * 0x8; 716 return 0x0430 + i * 0x8;
657 default: 717 default:
658 BUG(); 718 BUG();
719 return 0;
659 } 720 }
660} 721}
661 722
@@ -665,6 +726,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
665 switch (plane) { 726 switch (plane) {
666 case OMAP_DSS_GFX: 727 case OMAP_DSS_GFX:
667 BUG(); 728 BUG();
729 return 0;
668 case OMAP_DSS_VIDEO1: 730 case OMAP_DSS_VIDEO1:
669 case OMAP_DSS_VIDEO2: 731 case OMAP_DSS_VIDEO2:
670 return 0x0038 + i * 0x8; 732 return 0x0038 + i * 0x8;
@@ -672,6 +734,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
672 return 0x0014 + i * 0x8; 734 return 0x0014 + i * 0x8;
673 default: 735 default:
674 BUG(); 736 BUG();
737 return 0;
675 } 738 }
676} 739}
677 740
@@ -681,6 +744,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
681 switch (plane) { 744 switch (plane) {
682 case OMAP_DSS_GFX: 745 case OMAP_DSS_GFX:
683 BUG(); 746 BUG();
747 return 0;
684 case OMAP_DSS_VIDEO1: 748 case OMAP_DSS_VIDEO1:
685 return 0x0590 + i * 8; 749 return 0x0590 + i * 8;
686 case OMAP_DSS_VIDEO2: 750 case OMAP_DSS_VIDEO2:
@@ -689,6 +753,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
689 return 0x0434 + i * 0x8; 753 return 0x0434 + i * 0x8;
690 default: 754 default:
691 BUG(); 755 BUG();
756 return 0;
692 } 757 }
693} 758}
694 759
@@ -698,12 +763,14 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
698 switch (plane) { 763 switch (plane) {
699 case OMAP_DSS_GFX: 764 case OMAP_DSS_GFX:
700 BUG(); 765 BUG();
766 return 0;
701 case OMAP_DSS_VIDEO1: 767 case OMAP_DSS_VIDEO1:
702 case OMAP_DSS_VIDEO2: 768 case OMAP_DSS_VIDEO2:
703 case OMAP_DSS_VIDEO3: 769 case OMAP_DSS_VIDEO3:
704 return 0x0074 + i * 0x4; 770 return 0x0074 + i * 0x4;
705 default: 771 default:
706 BUG(); 772 BUG();
773 return 0;
707 } 774 }
708} 775}
709 776
@@ -713,6 +780,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
713 switch (plane) { 780 switch (plane) {
714 case OMAP_DSS_GFX: 781 case OMAP_DSS_GFX:
715 BUG(); 782 BUG();
783 return 0;
716 case OMAP_DSS_VIDEO1: 784 case OMAP_DSS_VIDEO1:
717 return 0x0124 + i * 0x4; 785 return 0x0124 + i * 0x4;
718 case OMAP_DSS_VIDEO2: 786 case OMAP_DSS_VIDEO2:
@@ -721,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
721 return 0x0050 + i * 0x4; 789 return 0x0050 + i * 0x4;
722 default: 790 default:
723 BUG(); 791 BUG();
792 return 0;
724 } 793 }
725} 794}
726 795
@@ -730,6 +799,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
730 switch (plane) { 799 switch (plane) {
731 case OMAP_DSS_GFX: 800 case OMAP_DSS_GFX:
732 BUG(); 801 BUG();
802 return 0;
733 case OMAP_DSS_VIDEO1: 803 case OMAP_DSS_VIDEO1:
734 return 0x05CC + i * 0x4; 804 return 0x05CC + i * 0x4;
735 case OMAP_DSS_VIDEO2: 805 case OMAP_DSS_VIDEO2:
@@ -738,6 +808,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
738 return 0x0470 + i * 0x4; 808 return 0x0470 + i * 0x4;
739 default: 809 default:
740 BUG(); 810 BUG();
811 return 0;
741 } 812 }
742} 813}
743 814
@@ -754,6 +825,7 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
754 return 0x00A0; 825 return 0x00A0;
755 default: 826 default:
756 BUG(); 827 BUG();
828 return 0;
757 } 829 }
758} 830}
759#endif 831#endif
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c
index 4424c198dbcd..249010630370 100644
--- a/drivers/video/omap2/dss/display.c
+++ b/drivers/video/omap2/dss/display.c
@@ -304,10 +304,18 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
304 return 24; 304 return 24;
305 default: 305 default:
306 BUG(); 306 BUG();
307 return 0;
307 } 308 }
308} 309}
309EXPORT_SYMBOL(omapdss_default_get_recommended_bpp); 310EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
310 311
312void omapdss_default_get_timings(struct omap_dss_device *dssdev,
313 struct omap_video_timings *timings)
314{
315 *timings = dssdev->panel.timings;
316}
317EXPORT_SYMBOL(omapdss_default_get_timings);
318
311/* Checks if replication logic should be used. Only use for active matrix, 319/* Checks if replication logic should be used. Only use for active matrix,
312 * when overlay is in RGB12U or RGB16 mode, and LCD interface is 320 * when overlay is in RGB12U or RGB16 mode, and LCD interface is
313 * 18bpp or 24bpp */ 321 * 18bpp or 24bpp */
@@ -340,6 +348,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
340 break; 348 break;
341 default: 349 default:
342 BUG(); 350 BUG();
351 return false;
343 } 352 }
344 353
345 return bpp > 16; 354 return bpp > 16;
@@ -352,46 +361,6 @@ void dss_init_device(struct platform_device *pdev,
352 int i; 361 int i;
353 int r; 362 int r;
354 363
355 switch (dssdev->type) {
356#ifdef CONFIG_OMAP2_DSS_DPI
357 case OMAP_DISPLAY_TYPE_DPI:
358 r = dpi_init_display(dssdev);
359 break;
360#endif
361#ifdef CONFIG_OMAP2_DSS_RFBI
362 case OMAP_DISPLAY_TYPE_DBI:
363 r = rfbi_init_display(dssdev);
364 break;
365#endif
366#ifdef CONFIG_OMAP2_DSS_VENC
367 case OMAP_DISPLAY_TYPE_VENC:
368 r = venc_init_display(dssdev);
369 break;
370#endif
371#ifdef CONFIG_OMAP2_DSS_SDI
372 case OMAP_DISPLAY_TYPE_SDI:
373 r = sdi_init_display(dssdev);
374 break;
375#endif
376#ifdef CONFIG_OMAP2_DSS_DSI
377 case OMAP_DISPLAY_TYPE_DSI:
378 r = dsi_init_display(dssdev);
379 break;
380#endif
381 case OMAP_DISPLAY_TYPE_HDMI:
382 r = hdmi_init_display(dssdev);
383 break;
384 default:
385 DSSERR("Support for display '%s' not compiled in.\n",
386 dssdev->name);
387 return;
388 }
389
390 if (r) {
391 DSSERR("failed to init display %s\n", dssdev->name);
392 return;
393 }
394
395 /* create device sysfs files */ 364 /* create device sysfs files */
396 i = 0; 365 i = 0;
397 while ((attr = display_sysfs_attrs[i++]) != NULL) { 366 while ((attr = display_sysfs_attrs[i++]) != NULL) {
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index faaf305fda27..8c2056c9537b 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -156,7 +156,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
156 t->pixel_clock = pck; 156 t->pixel_clock = pck;
157 } 157 }
158 158
159 dispc_mgr_set_lcd_timings(dssdev->manager->id, t); 159 dss_mgr_set_timings(dssdev->manager, t);
160 160
161 return 0; 161 return 0;
162} 162}
@@ -202,10 +202,6 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
202 goto err_reg_enable; 202 goto err_reg_enable;
203 } 203 }
204 204
205 r = dss_runtime_get();
206 if (r)
207 goto err_get_dss;
208
209 r = dispc_runtime_get(); 205 r = dispc_runtime_get();
210 if (r) 206 if (r)
211 goto err_get_dispc; 207 goto err_get_dispc;
@@ -244,8 +240,6 @@ err_dsi_pll_init:
244err_get_dsi: 240err_get_dsi:
245 dispc_runtime_put(); 241 dispc_runtime_put();
246err_get_dispc: 242err_get_dispc:
247 dss_runtime_put();
248err_get_dss:
249 if (cpu_is_omap34xx()) 243 if (cpu_is_omap34xx())
250 regulator_disable(dpi.vdds_dsi_reg); 244 regulator_disable(dpi.vdds_dsi_reg);
251err_reg_enable: 245err_reg_enable:
@@ -266,7 +260,6 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
266 } 260 }
267 261
268 dispc_runtime_put(); 262 dispc_runtime_put();
269 dss_runtime_put();
270 263
271 if (cpu_is_omap34xx()) 264 if (cpu_is_omap34xx())
272 regulator_disable(dpi.vdds_dsi_reg); 265 regulator_disable(dpi.vdds_dsi_reg);
@@ -283,21 +276,15 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
283 DSSDBG("dpi_set_timings\n"); 276 DSSDBG("dpi_set_timings\n");
284 dssdev->panel.timings = *timings; 277 dssdev->panel.timings = *timings;
285 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { 278 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
286 r = dss_runtime_get();
287 if (r)
288 return;
289
290 r = dispc_runtime_get(); 279 r = dispc_runtime_get();
291 if (r) { 280 if (r)
292 dss_runtime_put();
293 return; 281 return;
294 }
295 282
296 dpi_set_mode(dssdev); 283 dpi_set_mode(dssdev);
297 dispc_mgr_go(dssdev->manager->id);
298 284
299 dispc_runtime_put(); 285 dispc_runtime_put();
300 dss_runtime_put(); 286 } else {
287 dss_mgr_set_timings(dssdev->manager, timings);
301 } 288 }
302} 289}
303EXPORT_SYMBOL(dpi_set_timings); 290EXPORT_SYMBOL(dpi_set_timings);
@@ -312,7 +299,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
312 unsigned long pck; 299 unsigned long pck;
313 struct dispc_clock_info dispc_cinfo; 300 struct dispc_clock_info dispc_cinfo;
314 301
315 if (!dispc_lcd_timings_ok(timings)) 302 if (dss_mgr_check_timings(dssdev->manager, timings))
316 return -EINVAL; 303 return -EINVAL;
317 304
318 if (timings->pixel_clock == 0) 305 if (timings->pixel_clock == 0)
@@ -352,7 +339,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
352} 339}
353EXPORT_SYMBOL(dpi_check_timings); 340EXPORT_SYMBOL(dpi_check_timings);
354 341
355int dpi_init_display(struct omap_dss_device *dssdev) 342static int __init dpi_init_display(struct omap_dss_device *dssdev)
356{ 343{
357 DSSDBG("init_display\n"); 344 DSSDBG("init_display\n");
358 345
@@ -378,12 +365,58 @@ int dpi_init_display(struct omap_dss_device *dssdev)
378 return 0; 365 return 0;
379} 366}
380 367
381int dpi_init(void) 368static void __init dpi_probe_pdata(struct platform_device *pdev)
382{ 369{
370 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
371 int i, r;
372
373 for (i = 0; i < pdata->num_devices; ++i) {
374 struct omap_dss_device *dssdev = pdata->devices[i];
375
376 if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
377 continue;
378
379 r = dpi_init_display(dssdev);
380 if (r) {
381 DSSERR("device %s init failed: %d\n", dssdev->name, r);
382 continue;
383 }
384
385 r = omap_dss_register_device(dssdev, &pdev->dev, i);
386 if (r)
387 DSSERR("device %s register failed: %d\n",
388 dssdev->name, r);
389 }
390}
391
392static int __init omap_dpi_probe(struct platform_device *pdev)
393{
394 dpi_probe_pdata(pdev);
395
396 return 0;
397}
398
399static int __exit omap_dpi_remove(struct platform_device *pdev)
400{
401 omap_dss_unregister_child_devices(&pdev->dev);
402
383 return 0; 403 return 0;
384} 404}
385 405
386void dpi_exit(void) 406static struct platform_driver omap_dpi_driver = {
407 .remove = __exit_p(omap_dpi_remove),
408 .driver = {
409 .name = "omapdss_dpi",
410 .owner = THIS_MODULE,
411 },
412};
413
414int __init dpi_init_platform_driver(void)
387{ 415{
416 return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe);
388} 417}
389 418
419void __exit dpi_uninit_platform_driver(void)
420{
421 platform_driver_unregister(&omap_dpi_driver);
422}
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 662d14f8c2c3..ec363d8390ed 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -256,14 +256,13 @@ struct dsi_data {
256 struct platform_device *pdev; 256 struct platform_device *pdev;
257 void __iomem *base; 257 void __iomem *base;
258 258
259 int module_id;
260
259 int irq; 261 int irq;
260 262
261 struct clk *dss_clk; 263 struct clk *dss_clk;
262 struct clk *sys_clk; 264 struct clk *sys_clk;
263 265
264 int (*enable_pads)(int dsi_id, unsigned lane_mask);
265 void (*disable_pads)(int dsi_id, unsigned lane_mask);
266
267 struct dsi_clock_info current_cinfo; 266 struct dsi_clock_info current_cinfo;
268 267
269 bool vdds_dsi_enabled; 268 bool vdds_dsi_enabled;
@@ -361,11 +360,6 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
361 return dsi_pdev_map[module]; 360 return dsi_pdev_map[module];
362} 361}
363 362
364static inline int dsi_get_dsidev_id(struct platform_device *dsidev)
365{
366 return dsidev->id;
367}
368
369static inline void dsi_write_reg(struct platform_device *dsidev, 363static inline void dsi_write_reg(struct platform_device *dsidev,
370 const struct dsi_reg idx, u32 val) 364 const struct dsi_reg idx, u32 val)
371{ 365{
@@ -452,6 +446,7 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
452 return 16; 446 return 16;
453 default: 447 default:
454 BUG(); 448 BUG();
449 return 0;
455 } 450 }
456} 451}
457 452
@@ -1184,10 +1179,9 @@ static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
1184static unsigned long dsi_fclk_rate(struct platform_device *dsidev) 1179static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1185{ 1180{
1186 unsigned long r; 1181 unsigned long r;
1187 int dsi_module = dsi_get_dsidev_id(dsidev);
1188 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1182 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1189 1183
1190 if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) { 1184 if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {
1191 /* DSI FCLK source is DSS_CLK_FCK */ 1185 /* DSI FCLK source is DSS_CLK_FCK */
1192 r = clk_get_rate(dsi->dss_clk); 1186 r = clk_get_rate(dsi->dss_clk);
1193 } else { 1187 } else {
@@ -1279,10 +1273,9 @@ static int dsi_pll_power(struct platform_device *dsidev,
1279} 1273}
1280 1274
1281/* calculate clock rates using dividers in cinfo */ 1275/* calculate clock rates using dividers in cinfo */
1282static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, 1276static int dsi_calc_clock_rates(struct platform_device *dsidev,
1283 struct dsi_clock_info *cinfo) 1277 struct dsi_clock_info *cinfo)
1284{ 1278{
1285 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
1286 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1279 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1287 1280
1288 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max) 1281 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
@@ -1297,21 +1290,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
1297 if (cinfo->regm_dsi > dsi->regm_dsi_max) 1290 if (cinfo->regm_dsi > dsi->regm_dsi_max)
1298 return -EINVAL; 1291 return -EINVAL;
1299 1292
1300 if (cinfo->use_sys_clk) { 1293 cinfo->clkin = clk_get_rate(dsi->sys_clk);
1301 cinfo->clkin = clk_get_rate(dsi->sys_clk); 1294 cinfo->fint = cinfo->clkin / cinfo->regn;
1302 /* XXX it is unclear if highfreq should be used
1303 * with DSS_SYS_CLK source also */
1304 cinfo->highfreq = 0;
1305 } else {
1306 cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);
1307
1308 if (cinfo->clkin < 32000000)
1309 cinfo->highfreq = 0;
1310 else
1311 cinfo->highfreq = 1;
1312 }
1313
1314 cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
1315 1295
1316 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min) 1296 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
1317 return -EINVAL; 1297 return -EINVAL;
@@ -1378,27 +1358,21 @@ retry:
1378 1358
1379 memset(&cur, 0, sizeof(cur)); 1359 memset(&cur, 0, sizeof(cur));
1380 cur.clkin = dss_sys_clk; 1360 cur.clkin = dss_sys_clk;
1381 cur.use_sys_clk = 1;
1382 cur.highfreq = 0;
1383 1361
1384 /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ 1362 /* 0.75MHz < Fint = clkin / regn < 2.1MHz */
1385 /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
1386 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ 1363 /* To reduce PLL lock time, keep Fint high (around 2 MHz) */
1387 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { 1364 for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
1388 if (cur.highfreq == 0) 1365 cur.fint = cur.clkin / cur.regn;
1389 cur.fint = cur.clkin / cur.regn;
1390 else
1391 cur.fint = cur.clkin / (2 * cur.regn);
1392 1366
1393 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) 1367 if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
1394 continue; 1368 continue;
1395 1369
1396 /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ 1370 /* DSIPHY(MHz) = (2 * regm / regn) * clkin */
1397 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { 1371 for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
1398 unsigned long a, b; 1372 unsigned long a, b;
1399 1373
1400 a = 2 * cur.regm * (cur.clkin/1000); 1374 a = 2 * cur.regm * (cur.clkin/1000);
1401 b = cur.regn * (cur.highfreq + 1); 1375 b = cur.regn;
1402 cur.clkin4ddr = a / b * 1000; 1376 cur.clkin4ddr = a / b * 1000;
1403 1377
1404 if (cur.clkin4ddr > 1800 * 1000 * 1000) 1378 if (cur.clkin4ddr > 1800 * 1000 * 1000)
@@ -1486,9 +1460,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1486 1460
1487 DSSDBGF(); 1461 DSSDBGF();
1488 1462
1489 dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk; 1463 dsi->current_cinfo.clkin = cinfo->clkin;
1490 dsi->current_cinfo.highfreq = cinfo->highfreq;
1491
1492 dsi->current_cinfo.fint = cinfo->fint; 1464 dsi->current_cinfo.fint = cinfo->fint;
1493 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr; 1465 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
1494 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk = 1466 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
@@ -1503,17 +1475,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1503 1475
1504 DSSDBG("DSI Fint %ld\n", cinfo->fint); 1476 DSSDBG("DSI Fint %ld\n", cinfo->fint);
1505 1477
1506 DSSDBG("clkin (%s) rate %ld, highfreq %d\n", 1478 DSSDBG("clkin rate %ld\n", cinfo->clkin);
1507 cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree",
1508 cinfo->clkin,
1509 cinfo->highfreq);
1510 1479
1511 /* DSIPHY == CLKIN4DDR */ 1480 /* DSIPHY == CLKIN4DDR */
1512 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n", 1481 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
1513 cinfo->regm, 1482 cinfo->regm,
1514 cinfo->regn, 1483 cinfo->regn,
1515 cinfo->clkin, 1484 cinfo->clkin,
1516 cinfo->highfreq + 1,
1517 cinfo->clkin4ddr); 1485 cinfo->clkin4ddr);
1518 1486
1519 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n", 1487 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
@@ -1568,10 +1536,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
1568 1536
1569 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) 1537 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
1570 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ 1538 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1571 l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
1572 11, 11); /* DSI_PLL_CLKSEL */
1573 l = FLD_MOD(l, cinfo->highfreq,
1574 12, 12); /* DSI_PLL_HIGHFREQ */
1575 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */ 1539 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1576 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */ 1540 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1577 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */ 1541 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
@@ -1716,7 +1680,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1716 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1680 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1717 struct dsi_clock_info *cinfo = &dsi->current_cinfo; 1681 struct dsi_clock_info *cinfo = &dsi->current_cinfo;
1718 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; 1682 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
1719 int dsi_module = dsi_get_dsidev_id(dsidev); 1683 int dsi_module = dsi->module_id;
1720 1684
1721 dispc_clk_src = dss_get_dispc_clk_source(); 1685 dispc_clk_src = dss_get_dispc_clk_source();
1722 dsi_clk_src = dss_get_dsi_clk_source(dsi_module); 1686 dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
@@ -1726,8 +1690,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1726 1690
1727 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); 1691 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
1728 1692
1729 seq_printf(s, "dsi pll source = %s\n", 1693 seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin);
1730 cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree");
1731 1694
1732 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); 1695 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
1733 1696
@@ -1789,7 +1752,6 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
1789 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1752 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1790 unsigned long flags; 1753 unsigned long flags;
1791 struct dsi_irq_stats stats; 1754 struct dsi_irq_stats stats;
1792 int dsi_module = dsi_get_dsidev_id(dsidev);
1793 1755
1794 spin_lock_irqsave(&dsi->irq_stats_lock, flags); 1756 spin_lock_irqsave(&dsi->irq_stats_lock, flags);
1795 1757
@@ -1806,7 +1768,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
1806#define PIS(x) \ 1768#define PIS(x) \
1807 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]); 1769 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
1808 1770
1809 seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1); 1771 seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);
1810 PIS(VC0); 1772 PIS(VC0);
1811 PIS(VC1); 1773 PIS(VC1);
1812 PIS(VC2); 1774 PIS(VC2);
@@ -1886,22 +1848,6 @@ static void dsi2_dump_irqs(struct seq_file *s)
1886 1848
1887 dsi_dump_dsidev_irqs(dsidev, s); 1849 dsi_dump_dsidev_irqs(dsidev, s);
1888} 1850}
1889
1890void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
1891 const struct file_operations *debug_fops)
1892{
1893 struct platform_device *dsidev;
1894
1895 dsidev = dsi_get_dsidev_from_id(0);
1896 if (dsidev)
1897 debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir,
1898 &dsi1_dump_irqs, debug_fops);
1899
1900 dsidev = dsi_get_dsidev_from_id(1);
1901 if (dsidev)
1902 debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir,
1903 &dsi2_dump_irqs, debug_fops);
1904}
1905#endif 1851#endif
1906 1852
1907static void dsi_dump_dsidev_regs(struct platform_device *dsidev, 1853static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
@@ -2002,21 +1948,6 @@ static void dsi2_dump_regs(struct seq_file *s)
2002 dsi_dump_dsidev_regs(dsidev, s); 1948 dsi_dump_dsidev_regs(dsidev, s);
2003} 1949}
2004 1950
2005void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
2006 const struct file_operations *debug_fops)
2007{
2008 struct platform_device *dsidev;
2009
2010 dsidev = dsi_get_dsidev_from_id(0);
2011 if (dsidev)
2012 debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir,
2013 &dsi1_dump_regs, debug_fops);
2014
2015 dsidev = dsi_get_dsidev_from_id(1);
2016 if (dsidev)
2017 debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir,
2018 &dsi2_dump_regs, debug_fops);
2019}
2020enum dsi_cio_power_state { 1951enum dsi_cio_power_state {
2021 DSI_COMPLEXIO_POWER_OFF = 0x0, 1952 DSI_COMPLEXIO_POWER_OFF = 0x0,
2022 DSI_COMPLEXIO_POWER_ON = 0x1, 1953 DSI_COMPLEXIO_POWER_ON = 0x1,
@@ -2073,68 +2004,10 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2073 return 1365 * 3; /* 1365x24 bits */ 2004 return 1365 * 3; /* 1365x24 bits */
2074 default: 2005 default:
2075 BUG(); 2006 BUG();
2007 return 0;
2076 } 2008 }
2077} 2009}
2078 2010
2079static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
2080{
2081 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2082 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2083 u8 lanes[DSI_MAX_NR_LANES];
2084 u8 polarities[DSI_MAX_NR_LANES];
2085 int num_lanes, i;
2086
2087 static const enum dsi_lane_function functions[] = {
2088 DSI_LANE_CLK,
2089 DSI_LANE_DATA1,
2090 DSI_LANE_DATA2,
2091 DSI_LANE_DATA3,
2092 DSI_LANE_DATA4,
2093 };
2094
2095 lanes[0] = dssdev->phy.dsi.clk_lane;
2096 lanes[1] = dssdev->phy.dsi.data1_lane;
2097 lanes[2] = dssdev->phy.dsi.data2_lane;
2098 lanes[3] = dssdev->phy.dsi.data3_lane;
2099 lanes[4] = dssdev->phy.dsi.data4_lane;
2100 polarities[0] = dssdev->phy.dsi.clk_pol;
2101 polarities[1] = dssdev->phy.dsi.data1_pol;
2102 polarities[2] = dssdev->phy.dsi.data2_pol;
2103 polarities[3] = dssdev->phy.dsi.data3_pol;
2104 polarities[4] = dssdev->phy.dsi.data4_pol;
2105
2106 num_lanes = 0;
2107
2108 for (i = 0; i < dsi->num_lanes_supported; ++i)
2109 dsi->lanes[i].function = DSI_LANE_UNUSED;
2110
2111 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2112 int num;
2113
2114 if (lanes[i] == DSI_LANE_UNUSED)
2115 break;
2116
2117 num = lanes[i] - 1;
2118
2119 if (num >= dsi->num_lanes_supported)
2120 return -EINVAL;
2121
2122 if (dsi->lanes[num].function != DSI_LANE_UNUSED)
2123 return -EINVAL;
2124
2125 dsi->lanes[num].function = functions[i];
2126 dsi->lanes[num].polarity = polarities[i];
2127 num_lanes++;
2128 }
2129
2130 if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported)
2131 return -EINVAL;
2132
2133 dsi->num_lanes_used = num_lanes;
2134
2135 return 0;
2136}
2137
2138static int dsi_set_lane_config(struct omap_dss_device *dssdev) 2011static int dsi_set_lane_config(struct omap_dss_device *dssdev)
2139{ 2012{
2140 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2013 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -2396,7 +2269,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2396 2269
2397 DSSDBGF(); 2270 DSSDBGF();
2398 2271
2399 r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); 2272 r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
2400 if (r) 2273 if (r)
2401 return r; 2274 return r;
2402 2275
@@ -2506,7 +2379,7 @@ err_cio_pwr:
2506 dsi_cio_disable_lane_override(dsidev); 2379 dsi_cio_disable_lane_override(dsidev);
2507err_scp_clk_dom: 2380err_scp_clk_dom:
2508 dsi_disable_scp_clk(dsidev); 2381 dsi_disable_scp_clk(dsidev);
2509 dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); 2382 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
2510 return r; 2383 return r;
2511} 2384}
2512 2385
@@ -2520,7 +2393,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)
2520 2393
2521 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF); 2394 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
2522 dsi_disable_scp_clk(dsidev); 2395 dsi_disable_scp_clk(dsidev);
2523 dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev)); 2396 dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
2524} 2397}
2525 2398
2526static void dsi_config_tx_fifo(struct platform_device *dsidev, 2399static void dsi_config_tx_fifo(struct platform_device *dsidev,
@@ -2544,6 +2417,7 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev,
2544 if (add + size > 4) { 2417 if (add + size > 4) {
2545 DSSERR("Illegal FIFO configuration\n"); 2418 DSSERR("Illegal FIFO configuration\n");
2546 BUG(); 2419 BUG();
2420 return;
2547 } 2421 }
2548 2422
2549 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); 2423 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
@@ -2576,6 +2450,7 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev,
2576 if (add + size > 4) { 2450 if (add + size > 4) {
2577 DSSERR("Illegal FIFO configuration\n"); 2451 DSSERR("Illegal FIFO configuration\n");
2578 BUG(); 2452 BUG();
2453 return;
2579 } 2454 }
2580 2455
2581 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4); 2456 v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
@@ -2717,6 +2592,7 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)
2717 return dsi_sync_vc_l4(dsidev, channel); 2592 return dsi_sync_vc_l4(dsidev, channel);
2718 default: 2593 default:
2719 BUG(); 2594 BUG();
2595 return -EINVAL;
2720 } 2596 }
2721} 2597}
2722 2598
@@ -3285,6 +3161,7 @@ static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,
3285 data = reqdata[0] | (reqdata[1] << 8); 3161 data = reqdata[0] | (reqdata[1] << 8);
3286 } else { 3162 } else {
3287 BUG(); 3163 BUG();
3164 return -EINVAL;
3288 } 3165 }
3289 3166
3290 r = dsi_vc_send_short(dsidev, channel, data_type, data, 0); 3167 r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
@@ -3399,7 +3276,6 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
3399 goto err; 3276 goto err;
3400 } 3277 }
3401 3278
3402 BUG();
3403err: 3279err:
3404 DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel, 3280 DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
3405 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS"); 3281 type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
@@ -3794,6 +3670,186 @@ static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
3794 dsi_write_reg(dsidev, DSI_CTRL, r); 3670 dsi_write_reg(dsidev, DSI_CTRL, r);
3795} 3671}
3796 3672
3673/*
3674 * According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
3675 * results in maximum transition time for data and clock lanes to enter and
3676 * exit HS mode. Hence, this is the scenario where the least amount of command
3677 * mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
3678 * clock cycles that can be used to interleave command mode data in HS so that
3679 * all scenarios are satisfied.
3680 */
3681static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
3682 int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
3683{
3684 int transition;
3685
3686 /*
3687 * If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
3688 * time of data lanes only, if it isn't set, we need to consider HS
3689 * transition time of both data and clock lanes. HS transition time
3690 * of Scenario 3 is considered.
3691 */
3692 if (ddr_alwon) {
3693 transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
3694 } else {
3695 int trans1, trans2;
3696 trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
3697 trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
3698 enter_hs + 1;
3699 transition = max(trans1, trans2);
3700 }
3701
3702 return blank > transition ? blank - transition : 0;
3703}
3704
3705/*
3706 * According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
3707 * results in maximum transition time for data lanes to enter and exit LP mode.
3708 * Hence, this is the scenario where the least amount of command mode data can
3709 * be interleaved. We program the minimum amount of bytes that can be
3710 * interleaved in LP so that all scenarios are satisfied.
3711 */
3712static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
3713 int lp_clk_div, int tdsi_fclk)
3714{
3715 int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */
3716 int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */
3717 int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */
3718 int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */
3719 int lp_inter; /* cmd mode data that can be interleaved, in bytes */
3720
3721 /* maximum LP transition time according to Scenario 1 */
3722 trans_lp = exit_hs + max(enter_hs, 2) + 1;
3723
3724 /* CLKIN4DDR = 16 * TXBYTECLKHS */
3725 tlp_avail = thsbyte_clk * (blank - trans_lp);
3726
3727 ttxclkesc = tdsi_fclk / lp_clk_div;
3728
3729 lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
3730 26) / 16;
3731
3732 return max(lp_inter, 0);
3733}
3734
3735static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
3736{
3737 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3738 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3739 int blanking_mode;
3740 int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
3741 int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
3742 int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
3743 int tclk_trail, ths_exit, exiths_clk;
3744 bool ddr_alwon;
3745 struct omap_video_timings *timings = &dssdev->panel.timings;
3746 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
3747 int ndl = dsi->num_lanes_used - 1;
3748 int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
3749 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
3750 int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
3751 int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
3752 int bl_interleave_hs = 0, bl_interleave_lp = 0;
3753 u32 r;
3754
3755 r = dsi_read_reg(dsidev, DSI_CTRL);
3756 blanking_mode = FLD_GET(r, 20, 20);
3757 hfp_blanking_mode = FLD_GET(r, 21, 21);
3758 hbp_blanking_mode = FLD_GET(r, 22, 22);
3759 hsa_blanking_mode = FLD_GET(r, 23, 23);
3760
3761 r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
3762 hbp = FLD_GET(r, 11, 0);
3763 hfp = FLD_GET(r, 23, 12);
3764 hsa = FLD_GET(r, 31, 24);
3765
3766 r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
3767 ddr_clk_post = FLD_GET(r, 7, 0);
3768 ddr_clk_pre = FLD_GET(r, 15, 8);
3769
3770 r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
3771 exit_hs_mode_lat = FLD_GET(r, 15, 0);
3772 enter_hs_mode_lat = FLD_GET(r, 31, 16);
3773
3774 r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
3775 lp_clk_div = FLD_GET(r, 12, 0);
3776 ddr_alwon = FLD_GET(r, 13, 13);
3777
3778 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
3779 ths_exit = FLD_GET(r, 7, 0);
3780
3781 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
3782 tclk_trail = FLD_GET(r, 15, 8);
3783
3784 exiths_clk = ths_exit + tclk_trail;
3785
3786 width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
3787 bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
3788
3789 if (!hsa_blanking_mode) {
3790 hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
3791 enter_hs_mode_lat, exit_hs_mode_lat,
3792 exiths_clk, ddr_clk_pre, ddr_clk_post);
3793 hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
3794 enter_hs_mode_lat, exit_hs_mode_lat,
3795 lp_clk_div, dsi_fclk_hsdiv);
3796 }
3797
3798 if (!hfp_blanking_mode) {
3799 hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
3800 enter_hs_mode_lat, exit_hs_mode_lat,
3801 exiths_clk, ddr_clk_pre, ddr_clk_post);
3802 hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
3803 enter_hs_mode_lat, exit_hs_mode_lat,
3804 lp_clk_div, dsi_fclk_hsdiv);
3805 }
3806
3807 if (!hbp_blanking_mode) {
3808 hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
3809 enter_hs_mode_lat, exit_hs_mode_lat,
3810 exiths_clk, ddr_clk_pre, ddr_clk_post);
3811
3812 hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
3813 enter_hs_mode_lat, exit_hs_mode_lat,
3814 lp_clk_div, dsi_fclk_hsdiv);
3815 }
3816
3817 if (!blanking_mode) {
3818 bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
3819 enter_hs_mode_lat, exit_hs_mode_lat,
3820 exiths_clk, ddr_clk_pre, ddr_clk_post);
3821
3822 bl_interleave_lp = dsi_compute_interleave_lp(bllp,
3823 enter_hs_mode_lat, exit_hs_mode_lat,
3824 lp_clk_div, dsi_fclk_hsdiv);
3825 }
3826
3827 DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3828 hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
3829 bl_interleave_hs);
3830
3831 DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
3832 hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
3833 bl_interleave_lp);
3834
3835 r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
3836 r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
3837 r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
3838 r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
3839 dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
3840
3841 r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
3842 r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
3843 r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
3844 r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
3845 dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
3846
3847 r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
3848 r = FLD_MOD(r, bl_interleave_hs, 31, 15);
3849 r = FLD_MOD(r, bl_interleave_lp, 16, 0);
3850 dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
3851}
3852
3797static int dsi_proto_config(struct omap_dss_device *dssdev) 3853static int dsi_proto_config(struct omap_dss_device *dssdev)
3798{ 3854{
3799 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3855 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3828,6 +3884,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3828 break; 3884 break;
3829 default: 3885 default:
3830 BUG(); 3886 BUG();
3887 return -EINVAL;
3831 } 3888 }
3832 3889
3833 r = dsi_read_reg(dsidev, DSI_CTRL); 3890 r = dsi_read_reg(dsidev, DSI_CTRL);
@@ -3852,6 +3909,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3852 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3909 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3853 dsi_config_vp_sync_events(dssdev); 3910 dsi_config_vp_sync_events(dssdev);
3854 dsi_config_blanking_modes(dssdev); 3911 dsi_config_blanking_modes(dssdev);
3912 dsi_config_cmd_mode_interleaving(dssdev);
3855 } 3913 }
3856 3914
3857 dsi_vc_initial_config(dsidev, 0); 3915 dsi_vc_initial_config(dsidev, 0);
@@ -3975,6 +4033,74 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3975 } 4033 }
3976} 4034}
3977 4035
4036int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev,
4037 const struct omap_dsi_pin_config *pin_cfg)
4038{
4039 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4040 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4041 int num_pins;
4042 const int *pins;
4043 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
4044 int num_lanes;
4045 int i;
4046
4047 static const enum dsi_lane_function functions[] = {
4048 DSI_LANE_CLK,
4049 DSI_LANE_DATA1,
4050 DSI_LANE_DATA2,
4051 DSI_LANE_DATA3,
4052 DSI_LANE_DATA4,
4053 };
4054
4055 num_pins = pin_cfg->num_pins;
4056 pins = pin_cfg->pins;
4057
4058 if (num_pins < 4 || num_pins > dsi->num_lanes_supported * 2
4059 || num_pins % 2 != 0)
4060 return -EINVAL;
4061
4062 for (i = 0; i < DSI_MAX_NR_LANES; ++i)
4063 lanes[i].function = DSI_LANE_UNUSED;
4064
4065 num_lanes = 0;
4066
4067 for (i = 0; i < num_pins; i += 2) {
4068 u8 lane, pol;
4069 int dx, dy;
4070
4071 dx = pins[i];
4072 dy = pins[i + 1];
4073
4074 if (dx < 0 || dx >= dsi->num_lanes_supported * 2)
4075 return -EINVAL;
4076
4077 if (dy < 0 || dy >= dsi->num_lanes_supported * 2)
4078 return -EINVAL;
4079
4080 if (dx & 1) {
4081 if (dy != dx - 1)
4082 return -EINVAL;
4083 pol = 1;
4084 } else {
4085 if (dy != dx + 1)
4086 return -EINVAL;
4087 pol = 0;
4088 }
4089
4090 lane = dx / 2;
4091
4092 lanes[lane].function = functions[i / 2];
4093 lanes[lane].polarity = pol;
4094 num_lanes++;
4095 }
4096
4097 memcpy(dsi->lanes, lanes, sizeof(dsi->lanes));
4098 dsi->num_lanes_used = num_lanes;
4099
4100 return 0;
4101}
4102EXPORT_SYMBOL(omapdss_dsi_configure_pins);
4103
3978int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 4104int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
3979{ 4105{
3980 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4106 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
@@ -3999,6 +4125,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
3999 break; 4125 break;
4000 default: 4126 default:
4001 BUG(); 4127 BUG();
4128 return -EINVAL;
4002 }; 4129 };
4003 4130
4004 dsi_if_enable(dsidev, false); 4131 dsi_if_enable(dsidev, false);
@@ -4183,10 +4310,6 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
4183 __cancel_delayed_work(&dsi->framedone_timeout_work); 4310 __cancel_delayed_work(&dsi->framedone_timeout_work);
4184 4311
4185 dsi_handle_framedone(dsidev, 0); 4312 dsi_handle_framedone(dsidev, 0);
4186
4187#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
4188 dispc_fake_vsync_irq();
4189#endif
4190} 4313}
4191 4314
4192int omap_dsi_update(struct omap_dss_device *dssdev, int channel, 4315int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
@@ -4250,13 +4373,12 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4250 dispc_mgr_enable_stallmode(dssdev->manager->id, true); 4373 dispc_mgr_enable_stallmode(dssdev->manager->id, true);
4251 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1); 4374 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1);
4252 4375
4253 dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings); 4376 dss_mgr_set_timings(dssdev->manager, &timings);
4254 } else { 4377 } else {
4255 dispc_mgr_enable_stallmode(dssdev->manager->id, false); 4378 dispc_mgr_enable_stallmode(dssdev->manager->id, false);
4256 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0); 4379 dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0);
4257 4380
4258 dispc_mgr_set_lcd_timings(dssdev->manager->id, 4381 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
4259 &dssdev->panel.timings);
4260 } 4382 }
4261 4383
4262 dispc_mgr_set_lcd_display_type(dssdev->manager->id, 4384 dispc_mgr_set_lcd_display_type(dssdev->manager->id,
@@ -4285,13 +4407,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
4285 struct dsi_clock_info cinfo; 4407 struct dsi_clock_info cinfo;
4286 int r; 4408 int r;
4287 4409
4288 /* we always use DSS_CLK_SYSCK as input clock */
4289 cinfo.use_sys_clk = true;
4290 cinfo.regn = dssdev->clocks.dsi.regn; 4410 cinfo.regn = dssdev->clocks.dsi.regn;
4291 cinfo.regm = dssdev->clocks.dsi.regm; 4411 cinfo.regm = dssdev->clocks.dsi.regm;
4292 cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; 4412 cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
4293 cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; 4413 cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
4294 r = dsi_calc_clock_rates(dssdev, &cinfo); 4414 r = dsi_calc_clock_rates(dsidev, &cinfo);
4295 if (r) { 4415 if (r) {
4296 DSSERR("Failed to calc dsi clocks\n"); 4416 DSSERR("Failed to calc dsi clocks\n");
4297 return r; 4417 return r;
@@ -4336,15 +4456,9 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
4336static int dsi_display_init_dsi(struct omap_dss_device *dssdev) 4456static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4337{ 4457{
4338 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4458 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4339 int dsi_module = dsi_get_dsidev_id(dsidev); 4459 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4340 int r; 4460 int r;
4341 4461
4342 r = dsi_parse_lane_config(dssdev);
4343 if (r) {
4344 DSSERR("illegal lane config");
4345 goto err0;
4346 }
4347
4348 r = dsi_pll_init(dsidev, true, true); 4462 r = dsi_pll_init(dsidev, true, true);
4349 if (r) 4463 if (r)
4350 goto err0; 4464 goto err0;
@@ -4354,7 +4468,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4354 goto err1; 4468 goto err1;
4355 4469
4356 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); 4470 dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
4357 dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src); 4471 dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
4358 dss_select_lcd_clk_source(dssdev->manager->id, 4472 dss_select_lcd_clk_source(dssdev->manager->id,
4359 dssdev->clocks.dispc.channel.lcd_clk_src); 4473 dssdev->clocks.dispc.channel.lcd_clk_src);
4360 4474
@@ -4393,7 +4507,7 @@ err3:
4393 dsi_cio_uninit(dssdev); 4507 dsi_cio_uninit(dssdev);
4394err2: 4508err2:
4395 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4509 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4396 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); 4510 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4397 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4511 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
4398 4512
4399err1: 4513err1:
@@ -4407,7 +4521,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4407{ 4521{
4408 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4522 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4409 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4523 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4410 int dsi_module = dsi_get_dsidev_id(dsidev);
4411 4524
4412 if (enter_ulps && !dsi->ulps_enabled) 4525 if (enter_ulps && !dsi->ulps_enabled)
4413 dsi_enter_ulps(dsidev); 4526 dsi_enter_ulps(dsidev);
@@ -4420,7 +4533,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
4420 dsi_vc_enable(dsidev, 3, 0); 4533 dsi_vc_enable(dsidev, 3, 0);
4421 4534
4422 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 4535 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
4423 dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK); 4536 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4424 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK); 4537 dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
4425 dsi_cio_uninit(dssdev); 4538 dsi_cio_uninit(dssdev);
4426 dsi_pll_uninit(dsidev, disconnect_lanes); 4539 dsi_pll_uninit(dsidev, disconnect_lanes);
@@ -4524,7 +4637,7 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
4524} 4637}
4525EXPORT_SYMBOL(omapdss_dsi_enable_te); 4638EXPORT_SYMBOL(omapdss_dsi_enable_te);
4526 4639
4527int dsi_init_display(struct omap_dss_device *dssdev) 4640static int __init dsi_init_display(struct omap_dss_device *dssdev)
4528{ 4641{
4529 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4642 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4530 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4643 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4677,13 +4790,39 @@ static void dsi_put_clocks(struct platform_device *dsidev)
4677 clk_put(dsi->sys_clk); 4790 clk_put(dsi->sys_clk);
4678} 4791}
4679 4792
4793static void __init dsi_probe_pdata(struct platform_device *dsidev)
4794{
4795 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4796 struct omap_dss_board_info *pdata = dsidev->dev.platform_data;
4797 int i, r;
4798
4799 for (i = 0; i < pdata->num_devices; ++i) {
4800 struct omap_dss_device *dssdev = pdata->devices[i];
4801
4802 if (dssdev->type != OMAP_DISPLAY_TYPE_DSI)
4803 continue;
4804
4805 if (dssdev->phy.dsi.module != dsi->module_id)
4806 continue;
4807
4808 r = dsi_init_display(dssdev);
4809 if (r) {
4810 DSSERR("device %s init failed: %d\n", dssdev->name, r);
4811 continue;
4812 }
4813
4814 r = omap_dss_register_device(dssdev, &dsidev->dev, i);
4815 if (r)
4816 DSSERR("device %s register failed: %d\n",
4817 dssdev->name, r);
4818 }
4819}
4820
4680/* DSI1 HW IP initialisation */ 4821/* DSI1 HW IP initialisation */
4681static int omap_dsihw_probe(struct platform_device *dsidev) 4822static int __init omap_dsihw_probe(struct platform_device *dsidev)
4682{ 4823{
4683 struct omap_display_platform_data *dss_plat_data;
4684 struct omap_dss_board_info *board_info;
4685 u32 rev; 4824 u32 rev;
4686 int r, i, dsi_module = dsi_get_dsidev_id(dsidev); 4825 int r, i;
4687 struct resource *dsi_mem; 4826 struct resource *dsi_mem;
4688 struct dsi_data *dsi; 4827 struct dsi_data *dsi;
4689 4828
@@ -4691,15 +4830,11 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4691 if (!dsi) 4830 if (!dsi)
4692 return -ENOMEM; 4831 return -ENOMEM;
4693 4832
4833 dsi->module_id = dsidev->id;
4694 dsi->pdev = dsidev; 4834 dsi->pdev = dsidev;
4695 dsi_pdev_map[dsi_module] = dsidev; 4835 dsi_pdev_map[dsi->module_id] = dsidev;
4696 dev_set_drvdata(&dsidev->dev, dsi); 4836 dev_set_drvdata(&dsidev->dev, dsi);
4697 4837
4698 dss_plat_data = dsidev->dev.platform_data;
4699 board_info = dss_plat_data->board_data;
4700 dsi->enable_pads = board_info->dsi_enable_pads;
4701 dsi->disable_pads = board_info->dsi_disable_pads;
4702
4703 spin_lock_init(&dsi->irq_lock); 4838 spin_lock_init(&dsi->irq_lock);
4704 spin_lock_init(&dsi->errors_lock); 4839 spin_lock_init(&dsi->errors_lock);
4705 dsi->errors = 0; 4840 dsi->errors = 0;
@@ -4777,8 +4912,21 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4777 else 4912 else
4778 dsi->num_lanes_supported = 3; 4913 dsi->num_lanes_supported = 3;
4779 4914
4915 dsi_probe_pdata(dsidev);
4916
4780 dsi_runtime_put(dsidev); 4917 dsi_runtime_put(dsidev);
4781 4918
4919 if (dsi->module_id == 0)
4920 dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs);
4921 else if (dsi->module_id == 1)
4922 dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs);
4923
4924#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
4925 if (dsi->module_id == 0)
4926 dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs);
4927 else if (dsi->module_id == 1)
4928 dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs);
4929#endif
4782 return 0; 4930 return 0;
4783 4931
4784err_runtime_get: 4932err_runtime_get:
@@ -4787,12 +4935,14 @@ err_runtime_get:
4787 return r; 4935 return r;
4788} 4936}
4789 4937
4790static int omap_dsihw_remove(struct platform_device *dsidev) 4938static int __exit omap_dsihw_remove(struct platform_device *dsidev)
4791{ 4939{
4792 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4940 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4793 4941
4794 WARN_ON(dsi->scp_clk_refcount > 0); 4942 WARN_ON(dsi->scp_clk_refcount > 0);
4795 4943
4944 omap_dss_unregister_child_devices(&dsidev->dev);
4945
4796 pm_runtime_disable(&dsidev->dev); 4946 pm_runtime_disable(&dsidev->dev);
4797 4947
4798 dsi_put_clocks(dsidev); 4948 dsi_put_clocks(dsidev);
@@ -4813,7 +4963,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev)
4813static int dsi_runtime_suspend(struct device *dev) 4963static int dsi_runtime_suspend(struct device *dev)
4814{ 4964{
4815 dispc_runtime_put(); 4965 dispc_runtime_put();
4816 dss_runtime_put();
4817 4966
4818 return 0; 4967 return 0;
4819} 4968}
@@ -4822,20 +4971,11 @@ static int dsi_runtime_resume(struct device *dev)
4822{ 4971{
4823 int r; 4972 int r;
4824 4973
4825 r = dss_runtime_get();
4826 if (r)
4827 goto err_get_dss;
4828
4829 r = dispc_runtime_get(); 4974 r = dispc_runtime_get();
4830 if (r) 4975 if (r)
4831 goto err_get_dispc; 4976 return r;
4832 4977
4833 return 0; 4978 return 0;
4834
4835err_get_dispc:
4836 dss_runtime_put();
4837err_get_dss:
4838 return r;
4839} 4979}
4840 4980
4841static const struct dev_pm_ops dsi_pm_ops = { 4981static const struct dev_pm_ops dsi_pm_ops = {
@@ -4844,8 +4984,7 @@ static const struct dev_pm_ops dsi_pm_ops = {
4844}; 4984};
4845 4985
4846static struct platform_driver omap_dsihw_driver = { 4986static struct platform_driver omap_dsihw_driver = {
4847 .probe = omap_dsihw_probe, 4987 .remove = __exit_p(omap_dsihw_remove),
4848 .remove = omap_dsihw_remove,
4849 .driver = { 4988 .driver = {
4850 .name = "omapdss_dsi", 4989 .name = "omapdss_dsi",
4851 .owner = THIS_MODULE, 4990 .owner = THIS_MODULE,
@@ -4853,12 +4992,12 @@ static struct platform_driver omap_dsihw_driver = {
4853 }, 4992 },
4854}; 4993};
4855 4994
4856int dsi_init_platform_driver(void) 4995int __init dsi_init_platform_driver(void)
4857{ 4996{
4858 return platform_driver_register(&omap_dsihw_driver); 4997 return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe);
4859} 4998}
4860 4999
4861void dsi_uninit_platform_driver(void) 5000void __exit dsi_uninit_platform_driver(void)
4862{ 5001{
4863 return platform_driver_unregister(&omap_dsihw_driver); 5002 platform_driver_unregister(&omap_dsihw_driver);
4864} 5003}
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index bd2d5e159463..6ea1ff149f6f 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -62,6 +62,9 @@ struct dss_reg {
62#define REG_FLD_MOD(idx, val, start, end) \ 62#define REG_FLD_MOD(idx, val, start, end) \
63 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) 63 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
64 64
65static int dss_runtime_get(void);
66static void dss_runtime_put(void);
67
65static struct { 68static struct {
66 struct platform_device *pdev; 69 struct platform_device *pdev;
67 void __iomem *base; 70 void __iomem *base;
@@ -277,7 +280,7 @@ void dss_dump_clocks(struct seq_file *s)
277 dss_runtime_put(); 280 dss_runtime_put();
278} 281}
279 282
280void dss_dump_regs(struct seq_file *s) 283static void dss_dump_regs(struct seq_file *s)
281{ 284{
282#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) 285#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
283 286
@@ -322,6 +325,7 @@ void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
322 break; 325 break;
323 default: 326 default:
324 BUG(); 327 BUG();
328 return;
325 } 329 }
326 330
327 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); 331 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
@@ -335,7 +339,7 @@ void dss_select_dsi_clk_source(int dsi_module,
335 enum omap_dss_clk_source clk_src) 339 enum omap_dss_clk_source clk_src)
336{ 340{
337 struct platform_device *dsidev; 341 struct platform_device *dsidev;
338 int b; 342 int b, pos;
339 343
340 switch (clk_src) { 344 switch (clk_src) {
341 case OMAP_DSS_CLK_SRC_FCK: 345 case OMAP_DSS_CLK_SRC_FCK:
@@ -355,9 +359,11 @@ void dss_select_dsi_clk_source(int dsi_module,
355 break; 359 break;
356 default: 360 default:
357 BUG(); 361 BUG();
362 return;
358 } 363 }
359 364
360 REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ 365 pos = dsi_module == 0 ? 1 : 10;
366 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */
361 367
362 dss.dsi_clk_source[dsi_module] = clk_src; 368 dss.dsi_clk_source[dsi_module] = clk_src;
363} 369}
@@ -389,6 +395,7 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
389 break; 395 break;
390 default: 396 default:
391 BUG(); 397 BUG();
398 return;
392 } 399 }
393 400
394 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; 401 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
@@ -706,7 +713,7 @@ static void dss_put_clocks(void)
706 clk_put(dss.dss_clk); 713 clk_put(dss.dss_clk);
707} 714}
708 715
709int dss_runtime_get(void) 716static int dss_runtime_get(void)
710{ 717{
711 int r; 718 int r;
712 719
@@ -717,7 +724,7 @@ int dss_runtime_get(void)
717 return r < 0 ? r : 0; 724 return r < 0 ? r : 0;
718} 725}
719 726
720void dss_runtime_put(void) 727static void dss_runtime_put(void)
721{ 728{
722 int r; 729 int r;
723 730
@@ -740,7 +747,7 @@ void dss_debug_dump_clocks(struct seq_file *s)
740#endif 747#endif
741 748
742/* DSS HW IP initialisation */ 749/* DSS HW IP initialisation */
743static int omap_dsshw_probe(struct platform_device *pdev) 750static int __init omap_dsshw_probe(struct platform_device *pdev)
744{ 751{
745 struct resource *dss_mem; 752 struct resource *dss_mem;
746 u32 rev; 753 u32 rev;
@@ -785,40 +792,24 @@ static int omap_dsshw_probe(struct platform_device *pdev)
785 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 792 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
786 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 793 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
787 794
788 r = dpi_init();
789 if (r) {
790 DSSERR("Failed to initialize DPI\n");
791 goto err_dpi;
792 }
793
794 r = sdi_init();
795 if (r) {
796 DSSERR("Failed to initialize SDI\n");
797 goto err_sdi;
798 }
799
800 rev = dss_read_reg(DSS_REVISION); 795 rev = dss_read_reg(DSS_REVISION);
801 printk(KERN_INFO "OMAP DSS rev %d.%d\n", 796 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
802 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 797 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
803 798
804 dss_runtime_put(); 799 dss_runtime_put();
805 800
801 dss_debugfs_create_file("dss", dss_dump_regs);
802
806 return 0; 803 return 0;
807err_sdi: 804
808 dpi_exit();
809err_dpi:
810 dss_runtime_put();
811err_runtime_get: 805err_runtime_get:
812 pm_runtime_disable(&pdev->dev); 806 pm_runtime_disable(&pdev->dev);
813 dss_put_clocks(); 807 dss_put_clocks();
814 return r; 808 return r;
815} 809}
816 810
817static int omap_dsshw_remove(struct platform_device *pdev) 811static int __exit omap_dsshw_remove(struct platform_device *pdev)
818{ 812{
819 dpi_exit();
820 sdi_exit();
821
822 pm_runtime_disable(&pdev->dev); 813 pm_runtime_disable(&pdev->dev);
823 814
824 dss_put_clocks(); 815 dss_put_clocks();
@@ -829,11 +820,24 @@ static int omap_dsshw_remove(struct platform_device *pdev)
829static int dss_runtime_suspend(struct device *dev) 820static int dss_runtime_suspend(struct device *dev)
830{ 821{
831 dss_save_context(); 822 dss_save_context();
823 dss_set_min_bus_tput(dev, 0);
832 return 0; 824 return 0;
833} 825}
834 826
835static int dss_runtime_resume(struct device *dev) 827static int dss_runtime_resume(struct device *dev)
836{ 828{
829 int r;
830 /*
831 * Set an arbitrarily high tput request to ensure OPP100.
832 * What we should really do is to make a request to stay in OPP100,
833 * without any tput requirements, but that is not currently possible
834 * via the PM layer.
835 */
836
837 r = dss_set_min_bus_tput(dev, 1000000000);
838 if (r)
839 return r;
840
837 dss_restore_context(); 841 dss_restore_context();
838 return 0; 842 return 0;
839} 843}
@@ -844,8 +848,7 @@ static const struct dev_pm_ops dss_pm_ops = {
844}; 848};
845 849
846static struct platform_driver omap_dsshw_driver = { 850static struct platform_driver omap_dsshw_driver = {
847 .probe = omap_dsshw_probe, 851 .remove = __exit_p(omap_dsshw_remove),
848 .remove = omap_dsshw_remove,
849 .driver = { 852 .driver = {
850 .name = "omapdss_dss", 853 .name = "omapdss_dss",
851 .owner = THIS_MODULE, 854 .owner = THIS_MODULE,
@@ -853,12 +856,12 @@ static struct platform_driver omap_dsshw_driver = {
853 }, 856 },
854}; 857};
855 858
856int dss_init_platform_driver(void) 859int __init dss_init_platform_driver(void)
857{ 860{
858 return platform_driver_register(&omap_dsshw_driver); 861 return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
859} 862}
860 863
861void dss_uninit_platform_driver(void) 864void dss_uninit_platform_driver(void)
862{ 865{
863 return platform_driver_unregister(&omap_dsshw_driver); 866 platform_driver_unregister(&omap_dsshw_driver);
864} 867}
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index d4b3dff2ead3..dd1092ceaeef 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -150,9 +150,6 @@ struct dsi_clock_info {
150 u16 regm_dsi; /* OMAP3: REGM4 150 u16 regm_dsi; /* OMAP3: REGM4
151 * OMAP4: REGM5 */ 151 * OMAP4: REGM5 */
152 u16 lp_clk_div; 152 u16 lp_clk_div;
153
154 u8 highfreq;
155 bool use_sys_clk;
156}; 153};
157 154
158struct seq_file; 155struct seq_file;
@@ -162,6 +159,16 @@ struct platform_device;
162struct bus_type *dss_get_bus(void); 159struct bus_type *dss_get_bus(void);
163struct regulator *dss_get_vdds_dsi(void); 160struct regulator *dss_get_vdds_dsi(void);
164struct regulator *dss_get_vdds_sdi(void); 161struct regulator *dss_get_vdds_sdi(void);
162int dss_get_ctx_loss_count(struct device *dev);
163int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
164void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
165int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
166int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
167
168int omap_dss_register_device(struct omap_dss_device *dssdev,
169 struct device *parent, int disp_num);
170void omap_dss_unregister_device(struct omap_dss_device *dssdev);
171void omap_dss_unregister_child_devices(struct device *parent);
165 172
166/* apply */ 173/* apply */
167void dss_apply_init(void); 174void dss_apply_init(void);
@@ -179,6 +186,9 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
179int dss_mgr_set_device(struct omap_overlay_manager *mgr, 186int dss_mgr_set_device(struct omap_overlay_manager *mgr,
180 struct omap_dss_device *dssdev); 187 struct omap_dss_device *dssdev);
181int dss_mgr_unset_device(struct omap_overlay_manager *mgr); 188int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
189void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
190 struct omap_video_timings *timings);
191const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
182 192
183bool dss_ovl_is_enabled(struct omap_overlay *ovl); 193bool dss_ovl_is_enabled(struct omap_overlay *ovl);
184int dss_ovl_enable(struct omap_overlay *ovl); 194int dss_ovl_enable(struct omap_overlay *ovl);
@@ -208,9 +218,11 @@ int dss_init_overlay_managers(struct platform_device *pdev);
208void dss_uninit_overlay_managers(struct platform_device *pdev); 218void dss_uninit_overlay_managers(struct platform_device *pdev);
209int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 219int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
210 const struct omap_overlay_manager_info *info); 220 const struct omap_overlay_manager_info *info);
221int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
222 const struct omap_video_timings *timings);
211int dss_mgr_check(struct omap_overlay_manager *mgr, 223int dss_mgr_check(struct omap_overlay_manager *mgr,
212 struct omap_dss_device *dssdev,
213 struct omap_overlay_manager_info *info, 224 struct omap_overlay_manager_info *info,
225 const struct omap_video_timings *mgr_timings,
214 struct omap_overlay_info **overlay_infos); 226 struct omap_overlay_info **overlay_infos);
215 227
216/* overlay */ 228/* overlay */
@@ -220,22 +232,18 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
220void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); 232void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
221int dss_ovl_simple_check(struct omap_overlay *ovl, 233int dss_ovl_simple_check(struct omap_overlay *ovl,
222 const struct omap_overlay_info *info); 234 const struct omap_overlay_info *info);
223int dss_ovl_check(struct omap_overlay *ovl, 235int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
224 struct omap_overlay_info *info, struct omap_dss_device *dssdev); 236 const struct omap_video_timings *mgr_timings);
225 237
226/* DSS */ 238/* DSS */
227int dss_init_platform_driver(void); 239int dss_init_platform_driver(void) __init;
228void dss_uninit_platform_driver(void); 240void dss_uninit_platform_driver(void);
229 241
230int dss_runtime_get(void);
231void dss_runtime_put(void);
232
233void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 242void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
234enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 243enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
235const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 244const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
236void dss_dump_clocks(struct seq_file *s); 245void dss_dump_clocks(struct seq_file *s);
237 246
238void dss_dump_regs(struct seq_file *s);
239#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) 247#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
240void dss_debug_dump_clocks(struct seq_file *s); 248void dss_debug_dump_clocks(struct seq_file *s);
241#endif 249#endif
@@ -265,19 +273,8 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
265 struct dispc_clock_info *dispc_cinfo); 273 struct dispc_clock_info *dispc_cinfo);
266 274
267/* SDI */ 275/* SDI */
268#ifdef CONFIG_OMAP2_DSS_SDI 276int sdi_init_platform_driver(void) __init;
269int sdi_init(void); 277void sdi_uninit_platform_driver(void) __exit;
270void sdi_exit(void);
271int sdi_init_display(struct omap_dss_device *display);
272#else
273static inline int sdi_init(void)
274{
275 return 0;
276}
277static inline void sdi_exit(void)
278{
279}
280#endif
281 278
282/* DSI */ 279/* DSI */
283#ifdef CONFIG_OMAP2_DSS_DSI 280#ifdef CONFIG_OMAP2_DSS_DSI
@@ -285,19 +282,14 @@ static inline void sdi_exit(void)
285struct dentry; 282struct dentry;
286struct file_operations; 283struct file_operations;
287 284
288int dsi_init_platform_driver(void); 285int dsi_init_platform_driver(void) __init;
289void dsi_uninit_platform_driver(void); 286void dsi_uninit_platform_driver(void) __exit;
290 287
291int dsi_runtime_get(struct platform_device *dsidev); 288int dsi_runtime_get(struct platform_device *dsidev);
292void dsi_runtime_put(struct platform_device *dsidev); 289void dsi_runtime_put(struct platform_device *dsidev);
293 290
294void dsi_dump_clocks(struct seq_file *s); 291void dsi_dump_clocks(struct seq_file *s);
295void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
296 const struct file_operations *debug_fops);
297void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
298 const struct file_operations *debug_fops);
299 292
300int dsi_init_display(struct omap_dss_device *display);
301void dsi_irq_handler(void); 293void dsi_irq_handler(void);
302u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); 294u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
303 295
@@ -314,13 +306,6 @@ void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
314void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); 306void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
315struct platform_device *dsi_get_dsidev_from_id(int module); 307struct platform_device *dsi_get_dsidev_from_id(int module);
316#else 308#else
317static inline int dsi_init_platform_driver(void)
318{
319 return 0;
320}
321static inline void dsi_uninit_platform_driver(void)
322{
323}
324static inline int dsi_runtime_get(struct platform_device *dsidev) 309static inline int dsi_runtime_get(struct platform_device *dsidev)
325{ 310{
326 return 0; 311 return 0;
@@ -377,28 +362,14 @@ static inline struct platform_device *dsi_get_dsidev_from_id(int module)
377#endif 362#endif
378 363
379/* DPI */ 364/* DPI */
380#ifdef CONFIG_OMAP2_DSS_DPI 365int dpi_init_platform_driver(void) __init;
381int dpi_init(void); 366void dpi_uninit_platform_driver(void) __exit;
382void dpi_exit(void);
383int dpi_init_display(struct omap_dss_device *dssdev);
384#else
385static inline int dpi_init(void)
386{
387 return 0;
388}
389static inline void dpi_exit(void)
390{
391}
392#endif
393 367
394/* DISPC */ 368/* DISPC */
395int dispc_init_platform_driver(void); 369int dispc_init_platform_driver(void) __init;
396void dispc_uninit_platform_driver(void); 370void dispc_uninit_platform_driver(void) __exit;
397void dispc_dump_clocks(struct seq_file *s); 371void dispc_dump_clocks(struct seq_file *s);
398void dispc_dump_irqs(struct seq_file *s);
399void dispc_dump_regs(struct seq_file *s);
400void dispc_irq_handler(void); 372void dispc_irq_handler(void);
401void dispc_fake_vsync_irq(void);
402 373
403int dispc_runtime_get(void); 374int dispc_runtime_get(void);
404void dispc_runtime_put(void); 375void dispc_runtime_put(void);
@@ -409,12 +380,12 @@ void dispc_disable_sidle(void);
409void dispc_lcd_enable_signal_polarity(bool act_high); 380void dispc_lcd_enable_signal_polarity(bool act_high);
410void dispc_lcd_enable_signal(bool enable); 381void dispc_lcd_enable_signal(bool enable);
411void dispc_pck_free_enable(bool enable); 382void dispc_pck_free_enable(bool enable);
412void dispc_set_digit_size(u16 width, u16 height);
413void dispc_enable_fifomerge(bool enable); 383void dispc_enable_fifomerge(bool enable);
414void dispc_enable_gamma_table(bool enable); 384void dispc_enable_gamma_table(bool enable);
415void dispc_set_loadmode(enum omap_dss_load_mode mode); 385void dispc_set_loadmode(enum omap_dss_load_mode mode);
416 386
417bool dispc_lcd_timings_ok(struct omap_video_timings *timings); 387bool dispc_mgr_timings_ok(enum omap_channel channel,
388 const struct omap_video_timings *timings);
418unsigned long dispc_fclk_rate(void); 389unsigned long dispc_fclk_rate(void);
419void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, 390void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
420 struct dispc_clock_info *cinfo); 391 struct dispc_clock_info *cinfo);
@@ -424,15 +395,16 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
424 395
425void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); 396void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
426void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, 397void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
427 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge); 398 u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
399 bool manual_update);
428int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 400int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
429 bool ilace, bool replication); 401 bool ilace, bool replication,
402 const struct omap_video_timings *mgr_timings);
430int dispc_ovl_enable(enum omap_plane plane, bool enable); 403int dispc_ovl_enable(enum omap_plane plane, bool enable);
431void dispc_ovl_set_channel_out(enum omap_plane plane, 404void dispc_ovl_set_channel_out(enum omap_plane plane,
432 enum omap_channel channel); 405 enum omap_channel channel);
433 406
434void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); 407void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
435void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
436u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); 408u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
437u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); 409u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
438bool dispc_mgr_go_busy(enum omap_channel channel); 410bool dispc_mgr_go_busy(enum omap_channel channel);
@@ -445,12 +417,13 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
445void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); 417void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
446void dispc_mgr_set_lcd_display_type(enum omap_channel channel, 418void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
447 enum omap_lcd_display_type type); 419 enum omap_lcd_display_type type);
448void dispc_mgr_set_lcd_timings(enum omap_channel channel, 420void dispc_mgr_set_timings(enum omap_channel channel,
449 struct omap_video_timings *timings); 421 struct omap_video_timings *timings);
450void dispc_mgr_set_pol_freq(enum omap_channel channel, 422void dispc_mgr_set_pol_freq(enum omap_channel channel,
451 enum omap_panel_config config, u8 acbi, u8 acb); 423 enum omap_panel_config config, u8 acbi, u8 acb);
452unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); 424unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
453unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); 425unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
426unsigned long dispc_core_clk_rate(void);
454int dispc_mgr_set_clock_div(enum omap_channel channel, 427int dispc_mgr_set_clock_div(enum omap_channel channel,
455 struct dispc_clock_info *cinfo); 428 struct dispc_clock_info *cinfo);
456int dispc_mgr_get_clock_div(enum omap_channel channel, 429int dispc_mgr_get_clock_div(enum omap_channel channel,
@@ -460,19 +433,10 @@ void dispc_mgr_setup(enum omap_channel channel,
460 433
461/* VENC */ 434/* VENC */
462#ifdef CONFIG_OMAP2_DSS_VENC 435#ifdef CONFIG_OMAP2_DSS_VENC
463int venc_init_platform_driver(void); 436int venc_init_platform_driver(void) __init;
464void venc_uninit_platform_driver(void); 437void venc_uninit_platform_driver(void) __exit;
465void venc_dump_regs(struct seq_file *s);
466int venc_init_display(struct omap_dss_device *display);
467unsigned long venc_get_pixel_clock(void); 438unsigned long venc_get_pixel_clock(void);
468#else 439#else
469static inline int venc_init_platform_driver(void)
470{
471 return 0;
472}
473static inline void venc_uninit_platform_driver(void)
474{
475}
476static inline unsigned long venc_get_pixel_clock(void) 440static inline unsigned long venc_get_pixel_clock(void)
477{ 441{
478 WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__); 442 WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
@@ -482,23 +446,10 @@ static inline unsigned long venc_get_pixel_clock(void)
482 446
483/* HDMI */ 447/* HDMI */
484#ifdef CONFIG_OMAP4_DSS_HDMI 448#ifdef CONFIG_OMAP4_DSS_HDMI
485int hdmi_init_platform_driver(void); 449int hdmi_init_platform_driver(void) __init;
486void hdmi_uninit_platform_driver(void); 450void hdmi_uninit_platform_driver(void) __exit;
487int hdmi_init_display(struct omap_dss_device *dssdev);
488unsigned long hdmi_get_pixel_clock(void); 451unsigned long hdmi_get_pixel_clock(void);
489void hdmi_dump_regs(struct seq_file *s);
490#else 452#else
491static inline int hdmi_init_display(struct omap_dss_device *dssdev)
492{
493 return 0;
494}
495static inline int hdmi_init_platform_driver(void)
496{
497 return 0;
498}
499static inline void hdmi_uninit_platform_driver(void)
500{
501}
502static inline unsigned long hdmi_get_pixel_clock(void) 453static inline unsigned long hdmi_get_pixel_clock(void)
503{ 454{
504 WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__); 455 WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
@@ -514,22 +465,18 @@ int omapdss_hdmi_read_edid(u8 *buf, int len);
514bool omapdss_hdmi_detect(void); 465bool omapdss_hdmi_detect(void);
515int hdmi_panel_init(void); 466int hdmi_panel_init(void);
516void hdmi_panel_exit(void); 467void hdmi_panel_exit(void);
468#ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO
469int hdmi_audio_enable(void);
470void hdmi_audio_disable(void);
471int hdmi_audio_start(void);
472void hdmi_audio_stop(void);
473bool hdmi_mode_has_audio(void);
474int hdmi_audio_config(struct omap_dss_audio *audio);
475#endif
517 476
518/* RFBI */ 477/* RFBI */
519#ifdef CONFIG_OMAP2_DSS_RFBI 478int rfbi_init_platform_driver(void) __init;
520int rfbi_init_platform_driver(void); 479void rfbi_uninit_platform_driver(void) __exit;
521void rfbi_uninit_platform_driver(void);
522void rfbi_dump_regs(struct seq_file *s);
523int rfbi_init_display(struct omap_dss_device *display);
524#else
525static inline int rfbi_init_platform_driver(void)
526{
527 return 0;
528}
529static inline void rfbi_uninit_platform_driver(void)
530{
531}
532#endif
533 480
534 481
535#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 482#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 ce14aa6dd672..938709724f0c 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -52,6 +52,8 @@ struct omap_dss_features {
52 const char * const *clksrc_names; 52 const char * const *clksrc_names;
53 const struct dss_param_range *dss_params; 53 const struct dss_param_range *dss_params;
54 54
55 const enum omap_dss_rotation_type supported_rotation_types;
56
55 const u32 buffer_size_unit; 57 const u32 buffer_size_unit;
56 const u32 burst_size_unit; 58 const u32 burst_size_unit;
57}; 59};
@@ -311,6 +313,8 @@ static const struct dss_param_range omap2_dss_param_range[] = {
311 * scaler cannot scale a image with width more than 768. 313 * scaler cannot scale a image with width more than 768.
312 */ 314 */
313 [FEAT_PARAM_LINEWIDTH] = { 1, 768 }, 315 [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
316 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
317 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
314}; 318};
315 319
316static const struct dss_param_range omap3_dss_param_range[] = { 320static const struct dss_param_range omap3_dss_param_range[] = {
@@ -324,6 +328,8 @@ static const struct dss_param_range omap3_dss_param_range[] = {
324 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 328 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
325 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 329 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
326 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 330 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
331 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
332 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
327}; 333};
328 334
329static const struct dss_param_range omap4_dss_param_range[] = { 335static const struct dss_param_range omap4_dss_param_range[] = {
@@ -337,6 +343,8 @@ static const struct dss_param_range omap4_dss_param_range[] = {
337 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 343 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
338 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 344 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
339 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 345 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
346 [FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
347 [FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
340}; 348};
341 349
342static const enum dss_feat_id omap2_dss_feat_list[] = { 350static const enum dss_feat_id omap2_dss_feat_list[] = {
@@ -399,6 +407,7 @@ static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
399 FEAT_FIR_COEF_V, 407 FEAT_FIR_COEF_V,
400 FEAT_ALPHA_FREE_ZORDER, 408 FEAT_ALPHA_FREE_ZORDER,
401 FEAT_FIFO_MERGE, 409 FEAT_FIFO_MERGE,
410 FEAT_BURST_2D,
402}; 411};
403 412
404static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = { 413static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
@@ -416,6 +425,7 @@ static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
416 FEAT_FIR_COEF_V, 425 FEAT_FIR_COEF_V,
417 FEAT_ALPHA_FREE_ZORDER, 426 FEAT_ALPHA_FREE_ZORDER,
418 FEAT_FIFO_MERGE, 427 FEAT_FIFO_MERGE,
428 FEAT_BURST_2D,
419}; 429};
420 430
421static const enum dss_feat_id omap4_dss_feat_list[] = { 431static const enum dss_feat_id omap4_dss_feat_list[] = {
@@ -434,6 +444,7 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
434 FEAT_FIR_COEF_V, 444 FEAT_FIR_COEF_V,
435 FEAT_ALPHA_FREE_ZORDER, 445 FEAT_ALPHA_FREE_ZORDER,
436 FEAT_FIFO_MERGE, 446 FEAT_FIFO_MERGE,
447 FEAT_BURST_2D,
437}; 448};
438 449
439/* OMAP2 DSS Features */ 450/* OMAP2 DSS Features */
@@ -451,6 +462,7 @@ static const struct omap_dss_features omap2_dss_features = {
451 .overlay_caps = omap2_dss_overlay_caps, 462 .overlay_caps = omap2_dss_overlay_caps,
452 .clksrc_names = omap2_dss_clk_source_names, 463 .clksrc_names = omap2_dss_clk_source_names,
453 .dss_params = omap2_dss_param_range, 464 .dss_params = omap2_dss_param_range,
465 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
454 .buffer_size_unit = 1, 466 .buffer_size_unit = 1,
455 .burst_size_unit = 8, 467 .burst_size_unit = 8,
456}; 468};
@@ -470,6 +482,7 @@ static const struct omap_dss_features omap3430_dss_features = {
470 .overlay_caps = omap3430_dss_overlay_caps, 482 .overlay_caps = omap3430_dss_overlay_caps,
471 .clksrc_names = omap3_dss_clk_source_names, 483 .clksrc_names = omap3_dss_clk_source_names,
472 .dss_params = omap3_dss_param_range, 484 .dss_params = omap3_dss_param_range,
485 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
473 .buffer_size_unit = 1, 486 .buffer_size_unit = 1,
474 .burst_size_unit = 8, 487 .burst_size_unit = 8,
475}; 488};
@@ -488,6 +501,7 @@ static const struct omap_dss_features omap3630_dss_features = {
488 .overlay_caps = omap3630_dss_overlay_caps, 501 .overlay_caps = omap3630_dss_overlay_caps,
489 .clksrc_names = omap3_dss_clk_source_names, 502 .clksrc_names = omap3_dss_clk_source_names,
490 .dss_params = omap3_dss_param_range, 503 .dss_params = omap3_dss_param_range,
504 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
491 .buffer_size_unit = 1, 505 .buffer_size_unit = 1,
492 .burst_size_unit = 8, 506 .burst_size_unit = 8,
493}; 507};
@@ -508,6 +522,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
508 .overlay_caps = omap4_dss_overlay_caps, 522 .overlay_caps = omap4_dss_overlay_caps,
509 .clksrc_names = omap4_dss_clk_source_names, 523 .clksrc_names = omap4_dss_clk_source_names,
510 .dss_params = omap4_dss_param_range, 524 .dss_params = omap4_dss_param_range,
525 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
511 .buffer_size_unit = 16, 526 .buffer_size_unit = 16,
512 .burst_size_unit = 16, 527 .burst_size_unit = 16,
513}; 528};
@@ -527,6 +542,7 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
527 .overlay_caps = omap4_dss_overlay_caps, 542 .overlay_caps = omap4_dss_overlay_caps,
528 .clksrc_names = omap4_dss_clk_source_names, 543 .clksrc_names = omap4_dss_clk_source_names,
529 .dss_params = omap4_dss_param_range, 544 .dss_params = omap4_dss_param_range,
545 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
530 .buffer_size_unit = 16, 546 .buffer_size_unit = 16,
531 .burst_size_unit = 16, 547 .burst_size_unit = 16,
532}; 548};
@@ -546,6 +562,7 @@ static const struct omap_dss_features omap4_dss_features = {
546 .overlay_caps = omap4_dss_overlay_caps, 562 .overlay_caps = omap4_dss_overlay_caps,
547 .clksrc_names = omap4_dss_clk_source_names, 563 .clksrc_names = omap4_dss_clk_source_names,
548 .dss_params = omap4_dss_param_range, 564 .dss_params = omap4_dss_param_range,
565 .supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
549 .buffer_size_unit = 16, 566 .buffer_size_unit = 16,
550 .burst_size_unit = 16, 567 .burst_size_unit = 16,
551}; 568};
@@ -562,13 +579,17 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
562 .pll_enable = ti_hdmi_4xxx_pll_enable, 579 .pll_enable = ti_hdmi_4xxx_pll_enable,
563 .pll_disable = ti_hdmi_4xxx_pll_disable, 580 .pll_disable = ti_hdmi_4xxx_pll_disable,
564 .video_enable = ti_hdmi_4xxx_wp_video_start, 581 .video_enable = ti_hdmi_4xxx_wp_video_start,
582 .video_disable = ti_hdmi_4xxx_wp_video_stop,
565 .dump_wrapper = ti_hdmi_4xxx_wp_dump, 583 .dump_wrapper = ti_hdmi_4xxx_wp_dump,
566 .dump_core = ti_hdmi_4xxx_core_dump, 584 .dump_core = ti_hdmi_4xxx_core_dump,
567 .dump_pll = ti_hdmi_4xxx_pll_dump, 585 .dump_pll = ti_hdmi_4xxx_pll_dump,
568 .dump_phy = ti_hdmi_4xxx_phy_dump, 586 .dump_phy = ti_hdmi_4xxx_phy_dump,
569#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 587#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
570 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
571 .audio_enable = ti_hdmi_4xxx_wp_audio_enable, 588 .audio_enable = ti_hdmi_4xxx_wp_audio_enable,
589 .audio_disable = ti_hdmi_4xxx_wp_audio_disable,
590 .audio_start = ti_hdmi_4xxx_audio_start,
591 .audio_stop = ti_hdmi_4xxx_audio_stop,
592 .audio_config = ti_hdmi_4xxx_audio_config,
572#endif 593#endif
573 594
574}; 595};
@@ -662,6 +683,11 @@ void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
662 *end = omap_current_dss_features->reg_fields[id].end; 683 *end = omap_current_dss_features->reg_fields[id].end;
663} 684}
664 685
686bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
687{
688 return omap_current_dss_features->supported_rotation_types & rot_type;
689}
690
665void dss_features_init(void) 691void dss_features_init(void)
666{ 692{
667 if (cpu_is_omap24xx()) 693 if (cpu_is_omap24xx())
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index c332e7ddfce1..bdf469f080e7 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -62,6 +62,7 @@ enum dss_feat_id {
62 FEAT_FIFO_MERGE, 62 FEAT_FIFO_MERGE,
63 /* An unknown HW bug causing the normal FIFO thresholds not to work */ 63 /* An unknown HW bug causing the normal FIFO thresholds not to work */
64 FEAT_OMAP3_DSI_FIFO_BUG, 64 FEAT_OMAP3_DSI_FIFO_BUG,
65 FEAT_BURST_2D,
65}; 66};
66 67
67/* DSS register field id */ 68/* DSS register field id */
@@ -91,6 +92,8 @@ enum dss_range_param {
91 FEAT_PARAM_DSIPLL_LPDIV, 92 FEAT_PARAM_DSIPLL_LPDIV,
92 FEAT_PARAM_DOWNSCALE, 93 FEAT_PARAM_DOWNSCALE,
93 FEAT_PARAM_LINEWIDTH, 94 FEAT_PARAM_LINEWIDTH,
95 FEAT_PARAM_MGR_WIDTH,
96 FEAT_PARAM_MGR_HEIGHT,
94}; 97};
95 98
96/* DSS Feature Functions */ 99/* DSS Feature Functions */
@@ -108,6 +111,8 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
108u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ 111u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
109u32 dss_feat_get_burst_size_unit(void); /* in bytes */ 112u32 dss_feat_get_burst_size_unit(void); /* in bytes */
110 113
114bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
115
111bool dss_has_feature(enum dss_feat_id id); 116bool dss_has_feature(enum dss_feat_id id);
112void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); 117void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
113void dss_features_init(void); 118void dss_features_init(void);
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index c4b4f6950a92..8195c7166d20 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -33,12 +33,6 @@
33#include <linux/pm_runtime.h> 33#include <linux/pm_runtime.h>
34#include <linux/clk.h> 34#include <linux/clk.h>
35#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#include "ti_hdmi_4xxx_ip.h"
41#endif
42 36
43#include "ti_hdmi.h" 37#include "ti_hdmi.h"
44#include "dss.h" 38#include "dss.h"
@@ -63,7 +57,6 @@
63 57
64static struct { 58static struct {
65 struct mutex lock; 59 struct mutex lock;
66 struct omap_display_platform_data *pdata;
67 struct platform_device *pdev; 60 struct platform_device *pdev;
68 struct hdmi_ip_data ip_data; 61 struct hdmi_ip_data ip_data;
69 62
@@ -130,25 +123,12 @@ static int hdmi_runtime_get(void)
130 123
131 DSSDBG("hdmi_runtime_get\n"); 124 DSSDBG("hdmi_runtime_get\n");
132 125
133 /*
134 * HACK: Add dss_runtime_get() to ensure DSS clock domain is enabled.
135 * This should be removed later.
136 */
137 r = dss_runtime_get();
138 if (r < 0)
139 goto err_get_dss;
140
141 r = pm_runtime_get_sync(&hdmi.pdev->dev); 126 r = pm_runtime_get_sync(&hdmi.pdev->dev);
142 WARN_ON(r < 0); 127 WARN_ON(r < 0);
143 if (r < 0) 128 if (r < 0)
144 goto err_get_hdmi; 129 return r;
145 130
146 return 0; 131 return 0;
147
148err_get_hdmi:
149 dss_runtime_put();
150err_get_dss:
151 return r;
152} 132}
153 133
154static void hdmi_runtime_put(void) 134static void hdmi_runtime_put(void)
@@ -159,15 +139,9 @@ static void hdmi_runtime_put(void)
159 139
160 r = pm_runtime_put_sync(&hdmi.pdev->dev); 140 r = pm_runtime_put_sync(&hdmi.pdev->dev);
161 WARN_ON(r < 0); 141 WARN_ON(r < 0);
162
163 /*
164 * HACK: This is added to complement the dss_runtime_get() call in
165 * hdmi_runtime_get(). This should be removed later.
166 */
167 dss_runtime_put();
168} 142}
169 143
170int hdmi_init_display(struct omap_dss_device *dssdev) 144static int __init hdmi_init_display(struct omap_dss_device *dssdev)
171{ 145{
172 DSSDBG("init_display\n"); 146 DSSDBG("init_display\n");
173 147
@@ -344,7 +318,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
344 318
345 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data); 319 hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
346 320
347 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 321 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
348 322
349 /* config the PLL and PHY hdmi_set_pll_pwrfirst */ 323 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
350 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data); 324 r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
@@ -376,10 +350,11 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
376 dispc_enable_gamma_table(0); 350 dispc_enable_gamma_table(0);
377 351
378 /* tv size */ 352 /* tv size */
379 dispc_set_digit_size(dssdev->panel.timings.x_res, 353 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
380 dssdev->panel.timings.y_res);
381 354
382 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); 355 r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
356 if (r)
357 goto err_vid_enable;
383 358
384 r = dss_mgr_enable(dssdev->manager); 359 r = dss_mgr_enable(dssdev->manager);
385 if (r) 360 if (r)
@@ -388,7 +363,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
388 return 0; 363 return 0;
389 364
390err_mgr_enable: 365err_mgr_enable:
391 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 366 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
367err_vid_enable:
392 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 368 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
393 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 369 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
394err: 370err:
@@ -400,7 +376,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
400{ 376{
401 dss_mgr_disable(dssdev->manager); 377 dss_mgr_disable(dssdev->manager);
402 378
403 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 379 hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
404 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 380 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
405 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data); 381 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
406 hdmi_runtime_put(); 382 hdmi_runtime_put();
@@ -436,10 +412,12 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
436 r = hdmi_power_on(dssdev); 412 r = hdmi_power_on(dssdev);
437 if (r) 413 if (r)
438 DSSERR("failed to power on device\n"); 414 DSSERR("failed to power on device\n");
415 } else {
416 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
439 } 417 }
440} 418}
441 419
442void hdmi_dump_regs(struct seq_file *s) 420static void hdmi_dump_regs(struct seq_file *s)
443{ 421{
444 mutex_lock(&hdmi.lock); 422 mutex_lock(&hdmi.lock);
445 423
@@ -555,248 +533,201 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
555 mutex_unlock(&hdmi.lock); 533 mutex_unlock(&hdmi.lock);
556} 534}
557 535
558#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 536static int hdmi_get_clocks(struct platform_device *pdev)
559 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
560
561static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
562 struct snd_soc_dai *dai)
563{ 537{
564 struct snd_soc_pcm_runtime *rtd = substream->private_data; 538 struct clk *clk;
565 struct snd_soc_codec *codec = rtd->codec;
566 struct platform_device *pdev = to_platform_device(codec->dev);
567 struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
568 int err = 0;
569 539
570 if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) { 540 clk = clk_get(&pdev->dev, "sys_clk");
571 dev_err(&pdev->dev, "Cannot enable/disable audio\n"); 541 if (IS_ERR(clk)) {
572 return -ENODEV; 542 DSSERR("can't get sys_clk\n");
543 return PTR_ERR(clk);
573 } 544 }
574 545
575 switch (cmd) { 546 hdmi.sys_clk = clk;
576 case SNDRV_PCM_TRIGGER_START: 547
577 case SNDRV_PCM_TRIGGER_RESUME: 548 return 0;
578 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 549}
579 ip_data->ops->audio_enable(ip_data, true); 550
580 break; 551static void hdmi_put_clocks(void)
581 case SNDRV_PCM_TRIGGER_STOP: 552{
582 case SNDRV_PCM_TRIGGER_SUSPEND: 553 if (hdmi.sys_clk)
583 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 554 clk_put(hdmi.sys_clk);
584 ip_data->ops->audio_enable(ip_data, false); 555}
585 break; 556
586 default: 557#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
587 err = -EINVAL; 558int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
588 } 559{
589 return err; 560 u32 deep_color;
590} 561 bool deep_color_correct = false;
591 562 u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
592static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, 563
593 struct snd_pcm_hw_params *params, 564 if (n == NULL || cts == NULL)
594 struct snd_soc_dai *dai)
595{
596 struct snd_soc_pcm_runtime *rtd = substream->private_data;
597 struct snd_soc_codec *codec = rtd->codec;
598 struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
599 struct hdmi_audio_format audio_format;
600 struct hdmi_audio_dma audio_dma;
601 struct hdmi_core_audio_config core_cfg;
602 struct hdmi_core_infoframe_audio aud_if_cfg;
603 int err, n, cts;
604 enum hdmi_core_audio_sample_freq sample_freq;
605
606 switch (params_format(params)) {
607 case SNDRV_PCM_FORMAT_S16_LE:
608 core_cfg.i2s_cfg.word_max_length =
609 HDMI_AUDIO_I2S_MAX_WORD_20BITS;
610 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
611 core_cfg.i2s_cfg.in_length_bits =
612 HDMI_AUDIO_I2S_INPUT_LENGTH_16;
613 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
614 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
615 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
616 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
617 audio_dma.transfer_size = 0x10;
618 break;
619 case SNDRV_PCM_FORMAT_S24_LE:
620 core_cfg.i2s_cfg.word_max_length =
621 HDMI_AUDIO_I2S_MAX_WORD_24BITS;
622 core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
623 core_cfg.i2s_cfg.in_length_bits =
624 HDMI_AUDIO_I2S_INPUT_LENGTH_24;
625 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
626 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
627 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
628 core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
629 audio_dma.transfer_size = 0x20;
630 break;
631 default:
632 return -EINVAL; 565 return -EINVAL;
633 }
634 566
635 switch (params_rate(params)) { 567 /* TODO: When implemented, query deep color mode here. */
568 deep_color = 100;
569
570 /*
571 * When using deep color, the default N value (as in the HDMI
572 * specification) yields to an non-integer CTS. Hence, we
573 * modify it while keeping the restrictions described in
574 * section 7.2.1 of the HDMI 1.4a specification.
575 */
576 switch (sample_freq) {
636 case 32000: 577 case 32000:
637 sample_freq = HDMI_AUDIO_FS_32000; 578 case 48000:
579 case 96000:
580 case 192000:
581 if (deep_color == 125)
582 if (pclk == 27027 || pclk == 74250)
583 deep_color_correct = true;
584 if (deep_color == 150)
585 if (pclk == 27027)
586 deep_color_correct = true;
638 break; 587 break;
639 case 44100: 588 case 44100:
640 sample_freq = HDMI_AUDIO_FS_44100; 589 case 88200:
641 break; 590 case 176400:
642 case 48000: 591 if (deep_color == 125)
643 sample_freq = HDMI_AUDIO_FS_48000; 592 if (pclk == 27027)
593 deep_color_correct = true;
644 break; 594 break;
645 default: 595 default:
646 return -EINVAL; 596 return -EINVAL;
647 } 597 }
648 598
649 err = hdmi_config_audio_acr(ip_data, params_rate(params), &n, &cts); 599 if (deep_color_correct) {
650 if (err < 0) 600 switch (sample_freq) {
651 return err; 601 case 32000:
652 602 *n = 8192;
653 /* Audio wrapper config */ 603 break;
654 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL; 604 case 44100:
655 audio_format.active_chnnls_msk = 0x03; 605 *n = 12544;
656 audio_format.type = HDMI_AUDIO_TYPE_LPCM; 606 break;
657 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST; 607 case 48000:
658 /* Disable start/stop signals of IEC 60958 blocks */ 608 *n = 8192;
659 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF; 609 break;
610 case 88200:
611 *n = 25088;
612 break;
613 case 96000:
614 *n = 16384;
615 break;
616 case 176400:
617 *n = 50176;
618 break;
619 case 192000:
620 *n = 32768;
621 break;
622 default:
623 return -EINVAL;
624 }
625 } else {
626 switch (sample_freq) {
627 case 32000:
628 *n = 4096;
629 break;
630 case 44100:
631 *n = 6272;
632 break;
633 case 48000:
634 *n = 6144;
635 break;
636 case 88200:
637 *n = 12544;
638 break;
639 case 96000:
640 *n = 12288;
641 break;
642 case 176400:
643 *n = 25088;
644 break;
645 case 192000:
646 *n = 24576;
647 break;
648 default:
649 return -EINVAL;
650 }
651 }
652 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
653 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
660 654
661 audio_dma.block_size = 0xC0; 655 return 0;
662 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA; 656}
663 audio_dma.fifo_threshold = 0x20; /* in number of samples */
664 657
665 hdmi_wp_audio_config_dma(ip_data, &audio_dma); 658int hdmi_audio_enable(void)
666 hdmi_wp_audio_config_format(ip_data, &audio_format); 659{
660 DSSDBG("audio_enable\n");
667 661
668 /* 662 return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
669 * I2S config 663}
670 */
671 core_cfg.i2s_cfg.en_high_bitrate_aud = false;
672 /* Only used with high bitrate audio */
673 core_cfg.i2s_cfg.cbit_order = false;
674 /* Serial data and word select should change on sck rising edge */
675 core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
676 core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
677 /* Set I2S word select polarity */
678 core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
679 core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
680 /* Set serial data to word select shift. See Phillips spec. */
681 core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
682 /* Enable one of the four available serial data channels */
683 core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
684
685 /* Core audio config */
686 core_cfg.freq_sample = sample_freq;
687 core_cfg.n = n;
688 core_cfg.cts = cts;
689 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
690 core_cfg.aud_par_busclk = 0;
691 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
692 core_cfg.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
693 } else {
694 core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
695 core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
696 core_cfg.use_mclk = true;
697 }
698 664
699 if (core_cfg.use_mclk) 665void hdmi_audio_disable(void)
700 core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS; 666{
701 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH; 667 DSSDBG("audio_disable\n");
702 core_cfg.en_spdif = false;
703 /* Use sample frequency from channel status word */
704 core_cfg.fs_override = true;
705 /* Enable ACR packets */
706 core_cfg.en_acr_pkt = true;
707 /* Disable direct streaming digital audio */
708 core_cfg.en_dsd_audio = false;
709 /* Use parallel audio interface */
710 core_cfg.en_parallel_aud_input = true;
711
712 hdmi_core_audio_config(ip_data, &core_cfg);
713 668
714 /* 669 hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
715 * Configure packet
716 * info frame audio see doc CEA861-D page 74
717 */
718 aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
719 aud_if_cfg.db1_channel_count = 2;
720 aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
721 aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
722 aud_if_cfg.db4_channel_alloc = 0x00;
723 aud_if_cfg.db5_downmix_inh = false;
724 aud_if_cfg.db5_lsv = 0;
725
726 hdmi_core_audio_infoframe_config(ip_data, &aud_if_cfg);
727 return 0;
728} 670}
729 671
730static int hdmi_audio_startup(struct snd_pcm_substream *substream, 672int hdmi_audio_start(void)
731 struct snd_soc_dai *dai)
732{ 673{
733 if (!hdmi.ip_data.cfg.cm.mode) { 674 DSSDBG("audio_start\n");
734 pr_err("Current video settings do not support audio.\n"); 675
735 return -EIO; 676 return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
736 }
737 return 0;
738} 677}
739 678
740static int hdmi_audio_codec_probe(struct snd_soc_codec *codec) 679void hdmi_audio_stop(void)
741{ 680{
742 struct hdmi_ip_data *priv = &hdmi.ip_data; 681 DSSDBG("audio_stop\n");
743 682
744 snd_soc_codec_set_drvdata(codec, priv); 683 hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
745 return 0;
746} 684}
747 685
748static struct snd_soc_codec_driver hdmi_audio_codec_drv = { 686bool hdmi_mode_has_audio(void)
749 .probe = hdmi_audio_codec_probe, 687{
750}; 688 if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
689 return true;
690 else
691 return false;
692}
751 693
752static struct snd_soc_dai_ops hdmi_audio_codec_ops = { 694int hdmi_audio_config(struct omap_dss_audio *audio)
753 .hw_params = hdmi_audio_hw_params, 695{
754 .trigger = hdmi_audio_trigger, 696 return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
755 .startup = hdmi_audio_startup, 697}
756};
757 698
758static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
759 .name = "hdmi-audio-codec",
760 .playback = {
761 .channels_min = 2,
762 .channels_max = 2,
763 .rates = SNDRV_PCM_RATE_32000 |
764 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
765 .formats = SNDRV_PCM_FMTBIT_S16_LE |
766 SNDRV_PCM_FMTBIT_S24_LE,
767 },
768 .ops = &hdmi_audio_codec_ops,
769};
770#endif 699#endif
771 700
772static int hdmi_get_clocks(struct platform_device *pdev) 701static void __init hdmi_probe_pdata(struct platform_device *pdev)
773{ 702{
774 struct clk *clk; 703 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
704 int r, i;
775 705
776 clk = clk_get(&pdev->dev, "sys_clk"); 706 for (i = 0; i < pdata->num_devices; ++i) {
777 if (IS_ERR(clk)) { 707 struct omap_dss_device *dssdev = pdata->devices[i];
778 DSSERR("can't get sys_clk\n");
779 return PTR_ERR(clk);
780 }
781 708
782 hdmi.sys_clk = clk; 709 if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
710 continue;
783 711
784 return 0; 712 r = hdmi_init_display(dssdev);
785} 713 if (r) {
714 DSSERR("device %s init failed: %d\n", dssdev->name, r);
715 continue;
716 }
786 717
787static void hdmi_put_clocks(void) 718 r = omap_dss_register_device(dssdev, &pdev->dev, i);
788{ 719 if (r)
789 if (hdmi.sys_clk) 720 DSSERR("device %s register failed: %d\n",
790 clk_put(hdmi.sys_clk); 721 dssdev->name, r);
722 }
791} 723}
792 724
793/* HDMI HW IP initialisation */ 725/* HDMI HW IP initialisation */
794static int omapdss_hdmihw_probe(struct platform_device *pdev) 726static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
795{ 727{
796 struct resource *hdmi_mem; 728 struct resource *hdmi_mem;
797 int r; 729 int r;
798 730
799 hdmi.pdata = pdev->dev.platform_data;
800 hdmi.pdev = pdev; 731 hdmi.pdev = pdev;
801 732
802 mutex_init(&hdmi.lock); 733 mutex_init(&hdmi.lock);
@@ -830,28 +761,18 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
830 761
831 hdmi_panel_init(); 762 hdmi_panel_init();
832 763
833#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 764 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
834 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 765
766 hdmi_probe_pdata(pdev);
835 767
836 /* Register ASoC codec DAI */
837 r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
838 &hdmi_codec_dai_drv, 1);
839 if (r) {
840 DSSERR("can't register ASoC HDMI audio codec\n");
841 return r;
842 }
843#endif
844 return 0; 768 return 0;
845} 769}
846 770
847static int omapdss_hdmihw_remove(struct platform_device *pdev) 771static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
848{ 772{
849 hdmi_panel_exit(); 773 omap_dss_unregister_child_devices(&pdev->dev);
850 774
851#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 775 hdmi_panel_exit();
852 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
853 snd_soc_unregister_codec(&pdev->dev);
854#endif
855 776
856 pm_runtime_disable(&pdev->dev); 777 pm_runtime_disable(&pdev->dev);
857 778
@@ -867,7 +788,6 @@ static int hdmi_runtime_suspend(struct device *dev)
867 clk_disable(hdmi.sys_clk); 788 clk_disable(hdmi.sys_clk);
868 789
869 dispc_runtime_put(); 790 dispc_runtime_put();
870 dss_runtime_put();
871 791
872 return 0; 792 return 0;
873} 793}
@@ -876,23 +796,13 @@ static int hdmi_runtime_resume(struct device *dev)
876{ 796{
877 int r; 797 int r;
878 798
879 r = dss_runtime_get();
880 if (r < 0)
881 goto err_get_dss;
882
883 r = dispc_runtime_get(); 799 r = dispc_runtime_get();
884 if (r < 0) 800 if (r < 0)
885 goto err_get_dispc; 801 return r;
886
887 802
888 clk_enable(hdmi.sys_clk); 803 clk_enable(hdmi.sys_clk);
889 804
890 return 0; 805 return 0;
891
892err_get_dispc:
893 dss_runtime_put();
894err_get_dss:
895 return r;
896} 806}
897 807
898static const struct dev_pm_ops hdmi_pm_ops = { 808static const struct dev_pm_ops hdmi_pm_ops = {
@@ -901,8 +811,7 @@ static const struct dev_pm_ops hdmi_pm_ops = {
901}; 811};
902 812
903static struct platform_driver omapdss_hdmihw_driver = { 813static struct platform_driver omapdss_hdmihw_driver = {
904 .probe = omapdss_hdmihw_probe, 814 .remove = __exit_p(omapdss_hdmihw_remove),
905 .remove = omapdss_hdmihw_remove,
906 .driver = { 815 .driver = {
907 .name = "omapdss_hdmi", 816 .name = "omapdss_hdmi",
908 .owner = THIS_MODULE, 817 .owner = THIS_MODULE,
@@ -910,12 +819,12 @@ static struct platform_driver omapdss_hdmihw_driver = {
910 }, 819 },
911}; 820};
912 821
913int hdmi_init_platform_driver(void) 822int __init hdmi_init_platform_driver(void)
914{ 823{
915 return platform_driver_register(&omapdss_hdmihw_driver); 824 return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe);
916} 825}
917 826
918void hdmi_uninit_platform_driver(void) 827void __exit hdmi_uninit_platform_driver(void)
919{ 828{
920 return platform_driver_unregister(&omapdss_hdmihw_driver); 829 platform_driver_unregister(&omapdss_hdmihw_driver);
921} 830}
diff --git a/drivers/video/omap2/dss/hdmi_panel.c b/drivers/video/omap2/dss/hdmi_panel.c
index 533d5dc634d2..1179e3c4b1c7 100644
--- a/drivers/video/omap2/dss/hdmi_panel.c
+++ b/drivers/video/omap2/dss/hdmi_panel.c
@@ -30,7 +30,12 @@
30#include "dss.h" 30#include "dss.h"
31 31
32static struct { 32static struct {
33 struct mutex hdmi_lock; 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
34} hdmi; 39} hdmi;
35 40
36 41
@@ -54,12 +59,168 @@ static void hdmi_panel_remove(struct omap_dss_device *dssdev)
54 59
55} 60}
56 61
62#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
63static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
64{
65 unsigned long flags;
66 int r;
67
68 mutex_lock(&hdmi.lock);
69 spin_lock_irqsave(&hdmi.audio_lock, flags);
70
71 /* enable audio only if the display is active and supports audio */
72 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
73 !hdmi_mode_has_audio()) {
74 DSSERR("audio not supported or display is off\n");
75 r = -EPERM;
76 goto err;
77 }
78
79 r = hdmi_audio_enable();
80
81 if (!r)
82 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
83
84err:
85 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
86 mutex_unlock(&hdmi.lock);
87 return r;
88}
89
90static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
91{
92 unsigned long flags;
93
94 spin_lock_irqsave(&hdmi.audio_lock, flags);
95
96 hdmi_audio_disable();
97
98 dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
99
100 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
101}
102
103static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
104{
105 unsigned long flags;
106 int r;
107
108 spin_lock_irqsave(&hdmi.audio_lock, flags);
109 /*
110 * No need to check the panel state. It was checked when trasitioning
111 * to AUDIO_ENABLED.
112 */
113 if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) {
114 DSSERR("audio start from invalid state\n");
115 r = -EPERM;
116 goto err;
117 }
118
119 r = hdmi_audio_start();
120
121 if (!r)
122 dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
123
124err:
125 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
126 return r;
127}
128
129static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
130{
131 unsigned long flags;
132
133 spin_lock_irqsave(&hdmi.audio_lock, flags);
134
135 hdmi_audio_stop();
136 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
137
138 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
139}
140
141static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
142{
143 bool r = false;
144
145 mutex_lock(&hdmi.lock);
146
147 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
148 goto err;
149
150 if (!hdmi_mode_has_audio())
151 goto err;
152
153 r = true;
154err:
155 mutex_unlock(&hdmi.lock);
156 return r;
157}
158
159static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
160 struct omap_dss_audio *audio)
161{
162 unsigned long flags;
163 int r;
164
165 mutex_lock(&hdmi.lock);
166 spin_lock_irqsave(&hdmi.audio_lock, flags);
167
168 /* config audio only if the display is active and supports audio */
169 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
170 !hdmi_mode_has_audio()) {
171 DSSERR("audio not supported or display is off\n");
172 r = -EPERM;
173 goto err;
174 }
175
176 r = hdmi_audio_config(audio);
177
178 if (!r)
179 dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
180
181err:
182 spin_unlock_irqrestore(&hdmi.audio_lock, flags);
183 mutex_unlock(&hdmi.lock);
184 return r;
185}
186
187#else
188static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
189{
190 return -EPERM;
191}
192
193static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
194{
195}
196
197static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
198{
199 return -EPERM;
200}
201
202static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
203{
204}
205
206static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
207{
208 return false;
209}
210
211static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
212 struct omap_dss_audio *audio)
213{
214 return -EPERM;
215}
216#endif
217
57static int hdmi_panel_enable(struct omap_dss_device *dssdev) 218static int hdmi_panel_enable(struct omap_dss_device *dssdev)
58{ 219{
59 int r = 0; 220 int r = 0;
60 DSSDBG("ENTER hdmi_panel_enable\n"); 221 DSSDBG("ENTER hdmi_panel_enable\n");
61 222
62 mutex_lock(&hdmi.hdmi_lock); 223 mutex_lock(&hdmi.lock);
63 224
64 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { 225 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
65 r = -EINVAL; 226 r = -EINVAL;
@@ -75,40 +236,52 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
75 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 236 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
76 237
77err: 238err:
78 mutex_unlock(&hdmi.hdmi_lock); 239 mutex_unlock(&hdmi.lock);
79 240
80 return r; 241 return r;
81} 242}
82 243
83static void hdmi_panel_disable(struct omap_dss_device *dssdev) 244static void hdmi_panel_disable(struct omap_dss_device *dssdev)
84{ 245{
85 mutex_lock(&hdmi.hdmi_lock); 246 mutex_lock(&hdmi.lock);
86 247
87 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) 248 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
249 /*
250 * TODO: notify audio users that the display was disabled. For
251 * now, disable audio locally to not break our audio state
252 * machine.
253 */
254 hdmi_panel_audio_disable(dssdev);
88 omapdss_hdmi_display_disable(dssdev); 255 omapdss_hdmi_display_disable(dssdev);
256 }
89 257
90 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 258 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
91 259
92 mutex_unlock(&hdmi.hdmi_lock); 260 mutex_unlock(&hdmi.lock);
93} 261}
94 262
95static int hdmi_panel_suspend(struct omap_dss_device *dssdev) 263static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
96{ 264{
97 int r = 0; 265 int r = 0;
98 266
99 mutex_lock(&hdmi.hdmi_lock); 267 mutex_lock(&hdmi.lock);
100 268
101 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 269 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
102 r = -EINVAL; 270 r = -EINVAL;
103 goto err; 271 goto err;
104 } 272 }
105 273
106 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; 274 /*
275 * TODO: notify audio users that the display was suspended. For now,
276 * disable audio locally to not break our audio state machine.
277 */
278 hdmi_panel_audio_disable(dssdev);
107 279
280 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
108 omapdss_hdmi_display_disable(dssdev); 281 omapdss_hdmi_display_disable(dssdev);
109 282
110err: 283err:
111 mutex_unlock(&hdmi.hdmi_lock); 284 mutex_unlock(&hdmi.lock);
112 285
113 return r; 286 return r;
114} 287}
@@ -117,7 +290,7 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
117{ 290{
118 int r = 0; 291 int r = 0;
119 292
120 mutex_lock(&hdmi.hdmi_lock); 293 mutex_lock(&hdmi.lock);
121 294
122 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { 295 if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
123 r = -EINVAL; 296 r = -EINVAL;
@@ -129,11 +302,12 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
129 DSSERR("failed to power on\n"); 302 DSSERR("failed to power on\n");
130 goto err; 303 goto err;
131 } 304 }
305 /* TODO: notify audio users that the panel resumed. */
132 306
133 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 307 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
134 308
135err: 309err:
136 mutex_unlock(&hdmi.hdmi_lock); 310 mutex_unlock(&hdmi.lock);
137 311
138 return r; 312 return r;
139} 313}
@@ -141,11 +315,11 @@ err:
141static void hdmi_get_timings(struct omap_dss_device *dssdev, 315static void hdmi_get_timings(struct omap_dss_device *dssdev,
142 struct omap_video_timings *timings) 316 struct omap_video_timings *timings)
143{ 317{
144 mutex_lock(&hdmi.hdmi_lock); 318 mutex_lock(&hdmi.lock);
145 319
146 *timings = dssdev->panel.timings; 320 *timings = dssdev->panel.timings;
147 321
148 mutex_unlock(&hdmi.hdmi_lock); 322 mutex_unlock(&hdmi.lock);
149} 323}
150 324
151static void hdmi_set_timings(struct omap_dss_device *dssdev, 325static void hdmi_set_timings(struct omap_dss_device *dssdev,
@@ -153,12 +327,18 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
153{ 327{
154 DSSDBG("hdmi_set_timings\n"); 328 DSSDBG("hdmi_set_timings\n");
155 329
156 mutex_lock(&hdmi.hdmi_lock); 330 mutex_lock(&hdmi.lock);
331
332 /*
333 * TODO: notify audio users that there was a timings change. For
334 * now, disable audio locally to not break our audio state machine.
335 */
336 hdmi_panel_audio_disable(dssdev);
157 337
158 dssdev->panel.timings = *timings; 338 dssdev->panel.timings = *timings;
159 omapdss_hdmi_display_set_timing(dssdev); 339 omapdss_hdmi_display_set_timing(dssdev);
160 340
161 mutex_unlock(&hdmi.hdmi_lock); 341 mutex_unlock(&hdmi.lock);
162} 342}
163 343
164static int hdmi_check_timings(struct omap_dss_device *dssdev, 344static int hdmi_check_timings(struct omap_dss_device *dssdev,
@@ -168,11 +348,11 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
168 348
169 DSSDBG("hdmi_check_timings\n"); 349 DSSDBG("hdmi_check_timings\n");
170 350
171 mutex_lock(&hdmi.hdmi_lock); 351 mutex_lock(&hdmi.lock);
172 352
173 r = omapdss_hdmi_display_check_timing(dssdev, timings); 353 r = omapdss_hdmi_display_check_timing(dssdev, timings);
174 354
175 mutex_unlock(&hdmi.hdmi_lock); 355 mutex_unlock(&hdmi.lock);
176 return r; 356 return r;
177} 357}
178 358
@@ -180,7 +360,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
180{ 360{
181 int r; 361 int r;
182 362
183 mutex_lock(&hdmi.hdmi_lock); 363 mutex_lock(&hdmi.lock);
184 364
185 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 365 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
186 r = omapdss_hdmi_display_enable(dssdev); 366 r = omapdss_hdmi_display_enable(dssdev);
@@ -194,7 +374,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
194 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) 374 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
195 omapdss_hdmi_display_disable(dssdev); 375 omapdss_hdmi_display_disable(dssdev);
196err: 376err:
197 mutex_unlock(&hdmi.hdmi_lock); 377 mutex_unlock(&hdmi.lock);
198 378
199 return r; 379 return r;
200} 380}
@@ -203,7 +383,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
203{ 383{
204 int r; 384 int r;
205 385
206 mutex_lock(&hdmi.hdmi_lock); 386 mutex_lock(&hdmi.lock);
207 387
208 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { 388 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
209 r = omapdss_hdmi_display_enable(dssdev); 389 r = omapdss_hdmi_display_enable(dssdev);
@@ -217,7 +397,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
217 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED) 397 dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
218 omapdss_hdmi_display_disable(dssdev); 398 omapdss_hdmi_display_disable(dssdev);
219err: 399err:
220 mutex_unlock(&hdmi.hdmi_lock); 400 mutex_unlock(&hdmi.lock);
221 401
222 return r; 402 return r;
223} 403}
@@ -234,6 +414,12 @@ static struct omap_dss_driver hdmi_driver = {
234 .check_timings = hdmi_check_timings, 414 .check_timings = hdmi_check_timings,
235 .read_edid = hdmi_read_edid, 415 .read_edid = hdmi_read_edid,
236 .detect = hdmi_detect, 416 .detect = hdmi_detect,
417 .audio_enable = hdmi_panel_audio_enable,
418 .audio_disable = hdmi_panel_audio_disable,
419 .audio_start = hdmi_panel_audio_start,
420 .audio_stop = hdmi_panel_audio_stop,
421 .audio_supported = hdmi_panel_audio_supported,
422 .audio_config = hdmi_panel_audio_config,
237 .driver = { 423 .driver = {
238 .name = "hdmi_panel", 424 .name = "hdmi_panel",
239 .owner = THIS_MODULE, 425 .owner = THIS_MODULE,
@@ -242,7 +428,11 @@ static struct omap_dss_driver hdmi_driver = {
242 428
243int hdmi_panel_init(void) 429int hdmi_panel_init(void)
244{ 430{
245 mutex_init(&hdmi.hdmi_lock); 431 mutex_init(&hdmi.lock);
432
433#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
434 spin_lock_init(&hdmi.audio_lock);
435#endif
246 436
247 omap_dss_register_driver(&hdmi_driver); 437 omap_dss_register_driver(&hdmi_driver);
248 438
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index e7364603f6a1..0cbcde4c688a 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -654,9 +654,20 @@ static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
654 return 0; 654 return 0;
655} 655}
656 656
657int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
658 const struct omap_video_timings *timings)
659{
660 if (!dispc_mgr_timings_ok(mgr->id, timings)) {
661 DSSERR("check_manager: invalid timings\n");
662 return -EINVAL;
663 }
664
665 return 0;
666}
667
657int dss_mgr_check(struct omap_overlay_manager *mgr, 668int dss_mgr_check(struct omap_overlay_manager *mgr,
658 struct omap_dss_device *dssdev,
659 struct omap_overlay_manager_info *info, 669 struct omap_overlay_manager_info *info,
670 const struct omap_video_timings *mgr_timings,
660 struct omap_overlay_info **overlay_infos) 671 struct omap_overlay_info **overlay_infos)
661{ 672{
662 struct omap_overlay *ovl; 673 struct omap_overlay *ovl;
@@ -668,6 +679,10 @@ int dss_mgr_check(struct omap_overlay_manager *mgr,
668 return r; 679 return r;
669 } 680 }
670 681
682 r = dss_mgr_check_timings(mgr, mgr_timings);
683 if (r)
684 return r;
685
671 list_for_each_entry(ovl, &mgr->overlays, list) { 686 list_for_each_entry(ovl, &mgr->overlays, list) {
672 struct omap_overlay_info *oi; 687 struct omap_overlay_info *oi;
673 int r; 688 int r;
@@ -677,7 +692,7 @@ int dss_mgr_check(struct omap_overlay_manager *mgr,
677 if (oi == NULL) 692 if (oi == NULL)
678 continue; 693 continue;
679 694
680 r = dss_ovl_check(ovl, oi, dssdev); 695 r = dss_ovl_check(ovl, oi, mgr_timings);
681 if (r) 696 if (r)
682 return r; 697 return r;
683 } 698 }
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 6e821810deec..b0ba60f88dd2 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -628,19 +628,23 @@ int dss_ovl_simple_check(struct omap_overlay *ovl,
628 return -EINVAL; 628 return -EINVAL;
629 } 629 }
630 630
631 if (dss_feat_rotation_type_supported(info->rotation_type) == 0) {
632 DSSERR("check_overlay: rotation type %d not supported\n",
633 info->rotation_type);
634 return -EINVAL;
635 }
636
631 return 0; 637 return 0;
632} 638}
633 639
634int dss_ovl_check(struct omap_overlay *ovl, 640int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
635 struct omap_overlay_info *info, struct omap_dss_device *dssdev) 641 const struct omap_video_timings *mgr_timings)
636{ 642{
637 u16 outw, outh; 643 u16 outw, outh;
638 u16 dw, dh; 644 u16 dw, dh;
639 645
640 if (dssdev == NULL) 646 dw = mgr_timings->x_res;
641 return 0; 647 dh = mgr_timings->y_res;
642
643 dssdev->driver->get_resolution(dssdev, &dw, &dh);
644 648
645 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 649 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
646 outw = info->width; 650 outw = info->width;
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 788a0ef6323a..3d8c206e90e5 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -304,13 +304,23 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
304 u16 height, void (*callback)(void *data), void *data) 304 u16 height, void (*callback)(void *data), void *data)
305{ 305{
306 u32 l; 306 u32 l;
307 struct omap_video_timings timings = {
308 .hsw = 1,
309 .hfp = 1,
310 .hbp = 1,
311 .vsw = 1,
312 .vfp = 0,
313 .vbp = 0,
314 .x_res = width,
315 .y_res = height,
316 };
307 317
308 /*BUG_ON(callback == 0);*/ 318 /*BUG_ON(callback == 0);*/
309 BUG_ON(rfbi.framedone_callback != NULL); 319 BUG_ON(rfbi.framedone_callback != NULL);
310 320
311 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 321 DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
312 322
313 dispc_mgr_set_lcd_size(dssdev->manager->id, width, height); 323 dss_mgr_set_timings(dssdev->manager, &timings);
314 324
315 dispc_mgr_enable(dssdev->manager->id, true); 325 dispc_mgr_enable(dssdev->manager->id, true);
316 326
@@ -766,6 +776,16 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
766 u16 *x, u16 *y, u16 *w, u16 *h) 776 u16 *x, u16 *y, u16 *w, u16 *h)
767{ 777{
768 u16 dw, dh; 778 u16 dw, dh;
779 struct omap_video_timings timings = {
780 .hsw = 1,
781 .hfp = 1,
782 .hbp = 1,
783 .vsw = 1,
784 .vfp = 0,
785 .vbp = 0,
786 .x_res = *w,
787 .y_res = *h,
788 };
769 789
770 dssdev->driver->get_resolution(dssdev, &dw, &dh); 790 dssdev->driver->get_resolution(dssdev, &dw, &dh);
771 791
@@ -784,7 +804,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
784 if (*w == 0 || *h == 0) 804 if (*w == 0 || *h == 0)
785 return -EINVAL; 805 return -EINVAL;
786 806
787 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); 807 dss_mgr_set_timings(dssdev->manager, &timings);
788 808
789 return 0; 809 return 0;
790} 810}
@@ -799,7 +819,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
799} 819}
800EXPORT_SYMBOL(omap_rfbi_update); 820EXPORT_SYMBOL(omap_rfbi_update);
801 821
802void rfbi_dump_regs(struct seq_file *s) 822static void rfbi_dump_regs(struct seq_file *s)
803{ 823{
804#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) 824#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
805 825
@@ -900,15 +920,39 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
900} 920}
901EXPORT_SYMBOL(omapdss_rfbi_display_disable); 921EXPORT_SYMBOL(omapdss_rfbi_display_disable);
902 922
903int rfbi_init_display(struct omap_dss_device *dssdev) 923static int __init rfbi_init_display(struct omap_dss_device *dssdev)
904{ 924{
905 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 925 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
906 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 926 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
907 return 0; 927 return 0;
908} 928}
909 929
930static void __init rfbi_probe_pdata(struct platform_device *pdev)
931{
932 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
933 int i, r;
934
935 for (i = 0; i < pdata->num_devices; ++i) {
936 struct omap_dss_device *dssdev = pdata->devices[i];
937
938 if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
939 continue;
940
941 r = rfbi_init_display(dssdev);
942 if (r) {
943 DSSERR("device %s init failed: %d\n", dssdev->name, r);
944 continue;
945 }
946
947 r = omap_dss_register_device(dssdev, &pdev->dev, i);
948 if (r)
949 DSSERR("device %s register failed: %d\n",
950 dssdev->name, r);
951 }
952}
953
910/* RFBI HW IP initialisation */ 954/* RFBI HW IP initialisation */
911static int omap_rfbihw_probe(struct platform_device *pdev) 955static int __init omap_rfbihw_probe(struct platform_device *pdev)
912{ 956{
913 u32 rev; 957 u32 rev;
914 struct resource *rfbi_mem; 958 struct resource *rfbi_mem;
@@ -956,6 +1000,10 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
956 1000
957 rfbi_runtime_put(); 1001 rfbi_runtime_put();
958 1002
1003 dss_debugfs_create_file("rfbi", rfbi_dump_regs);
1004
1005 rfbi_probe_pdata(pdev);
1006
959 return 0; 1007 return 0;
960 1008
961err_runtime_get: 1009err_runtime_get:
@@ -963,8 +1011,9 @@ err_runtime_get:
963 return r; 1011 return r;
964} 1012}
965 1013
966static int omap_rfbihw_remove(struct platform_device *pdev) 1014static int __exit omap_rfbihw_remove(struct platform_device *pdev)
967{ 1015{
1016 omap_dss_unregister_child_devices(&pdev->dev);
968 pm_runtime_disable(&pdev->dev); 1017 pm_runtime_disable(&pdev->dev);
969 return 0; 1018 return 0;
970} 1019}
@@ -972,7 +1021,6 @@ static int omap_rfbihw_remove(struct platform_device *pdev)
972static int rfbi_runtime_suspend(struct device *dev) 1021static int rfbi_runtime_suspend(struct device *dev)
973{ 1022{
974 dispc_runtime_put(); 1023 dispc_runtime_put();
975 dss_runtime_put();
976 1024
977 return 0; 1025 return 0;
978} 1026}
@@ -981,20 +1029,11 @@ static int rfbi_runtime_resume(struct device *dev)
981{ 1029{
982 int r; 1030 int r;
983 1031
984 r = dss_runtime_get();
985 if (r < 0)
986 goto err_get_dss;
987
988 r = dispc_runtime_get(); 1032 r = dispc_runtime_get();
989 if (r < 0) 1033 if (r < 0)
990 goto err_get_dispc; 1034 return r;
991 1035
992 return 0; 1036 return 0;
993
994err_get_dispc:
995 dss_runtime_put();
996err_get_dss:
997 return r;
998} 1037}
999 1038
1000static const struct dev_pm_ops rfbi_pm_ops = { 1039static const struct dev_pm_ops rfbi_pm_ops = {
@@ -1003,8 +1042,7 @@ static const struct dev_pm_ops rfbi_pm_ops = {
1003}; 1042};
1004 1043
1005static struct platform_driver omap_rfbihw_driver = { 1044static struct platform_driver omap_rfbihw_driver = {
1006 .probe = omap_rfbihw_probe, 1045 .remove = __exit_p(omap_rfbihw_remove),
1007 .remove = omap_rfbihw_remove,
1008 .driver = { 1046 .driver = {
1009 .name = "omapdss_rfbi", 1047 .name = "omapdss_rfbi",
1010 .owner = THIS_MODULE, 1048 .owner = THIS_MODULE,
@@ -1012,12 +1050,12 @@ static struct platform_driver omap_rfbihw_driver = {
1012 }, 1050 },
1013}; 1051};
1014 1052
1015int rfbi_init_platform_driver(void) 1053int __init rfbi_init_platform_driver(void)
1016{ 1054{
1017 return platform_driver_register(&omap_rfbihw_driver); 1055 return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe);
1018} 1056}
1019 1057
1020void rfbi_uninit_platform_driver(void) 1058void __exit rfbi_uninit_platform_driver(void)
1021{ 1059{
1022 return platform_driver_unregister(&omap_rfbihw_driver); 1060 platform_driver_unregister(&omap_rfbihw_driver);
1023} 1061}
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 8266ca0d666b..3a43dc2a9b46 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -24,6 +24,7 @@
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/regulator/consumer.h> 25#include <linux/regulator/consumer.h>
26#include <linux/export.h> 26#include <linux/export.h>
27#include <linux/platform_device.h>
27 28
28#include <video/omapdss.h> 29#include <video/omapdss.h>
29#include "dss.h" 30#include "dss.h"
@@ -71,10 +72,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
71 if (r) 72 if (r)
72 goto err_reg_enable; 73 goto err_reg_enable;
73 74
74 r = dss_runtime_get();
75 if (r)
76 goto err_get_dss;
77
78 r = dispc_runtime_get(); 75 r = dispc_runtime_get();
79 if (r) 76 if (r)
80 goto err_get_dispc; 77 goto err_get_dispc;
@@ -107,7 +104,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
107 } 104 }
108 105
109 106
110 dispc_mgr_set_lcd_timings(dssdev->manager->id, t); 107 dss_mgr_set_timings(dssdev->manager, t);
111 108
112 r = dss_set_clock_div(&dss_cinfo); 109 r = dss_set_clock_div(&dss_cinfo);
113 if (r) 110 if (r)
@@ -137,8 +134,6 @@ err_set_dss_clock_div:
137err_calc_clock_div: 134err_calc_clock_div:
138 dispc_runtime_put(); 135 dispc_runtime_put();
139err_get_dispc: 136err_get_dispc:
140 dss_runtime_put();
141err_get_dss:
142 regulator_disable(sdi.vdds_sdi_reg); 137 regulator_disable(sdi.vdds_sdi_reg);
143err_reg_enable: 138err_reg_enable:
144 omap_dss_stop_device(dssdev); 139 omap_dss_stop_device(dssdev);
@@ -154,7 +149,6 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
154 dss_sdi_disable(); 149 dss_sdi_disable();
155 150
156 dispc_runtime_put(); 151 dispc_runtime_put();
157 dss_runtime_put();
158 152
159 regulator_disable(sdi.vdds_sdi_reg); 153 regulator_disable(sdi.vdds_sdi_reg);
160 154
@@ -162,7 +156,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
162} 156}
163EXPORT_SYMBOL(omapdss_sdi_display_disable); 157EXPORT_SYMBOL(omapdss_sdi_display_disable);
164 158
165int sdi_init_display(struct omap_dss_device *dssdev) 159static int __init sdi_init_display(struct omap_dss_device *dssdev)
166{ 160{
167 DSSDBG("SDI init\n"); 161 DSSDBG("SDI init\n");
168 162
@@ -182,11 +176,58 @@ int sdi_init_display(struct omap_dss_device *dssdev)
182 return 0; 176 return 0;
183} 177}
184 178
185int sdi_init(void) 179static void __init sdi_probe_pdata(struct platform_device *pdev)
180{
181 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
182 int i, r;
183
184 for (i = 0; i < pdata->num_devices; ++i) {
185 struct omap_dss_device *dssdev = pdata->devices[i];
186
187 if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
188 continue;
189
190 r = sdi_init_display(dssdev);
191 if (r) {
192 DSSERR("device %s init failed: %d\n", dssdev->name, r);
193 continue;
194 }
195
196 r = omap_dss_register_device(dssdev, &pdev->dev, i);
197 if (r)
198 DSSERR("device %s register failed: %d\n",
199 dssdev->name, r);
200 }
201}
202
203static int __init omap_sdi_probe(struct platform_device *pdev)
186{ 204{
205 sdi_probe_pdata(pdev);
206
207 return 0;
208}
209
210static int __exit omap_sdi_remove(struct platform_device *pdev)
211{
212 omap_dss_unregister_child_devices(&pdev->dev);
213
187 return 0; 214 return 0;
188} 215}
189 216
190void sdi_exit(void) 217static struct platform_driver omap_sdi_driver = {
218 .remove = __exit_p(omap_sdi_remove),
219 .driver = {
220 .name = "omapdss_sdi",
221 .owner = THIS_MODULE,
222 },
223};
224
225int __init sdi_init_platform_driver(void)
226{
227 return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe);
228}
229
230void __exit sdi_uninit_platform_driver(void)
191{ 231{
232 platform_driver_unregister(&omap_sdi_driver);
192} 233}
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 1f58b84d6901..e734cb444bc7 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -96,7 +96,9 @@ struct ti_hdmi_ip_ops {
96 96
97 void (*pll_disable)(struct hdmi_ip_data *ip_data); 97 void (*pll_disable)(struct hdmi_ip_data *ip_data);
98 98
99 void (*video_enable)(struct hdmi_ip_data *ip_data, bool start); 99 int (*video_enable)(struct hdmi_ip_data *ip_data);
100
101 void (*video_disable)(struct hdmi_ip_data *ip_data);
100 102
101 void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s); 103 void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
102 104
@@ -106,9 +108,17 @@ struct ti_hdmi_ip_ops {
106 108
107 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); 109 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
108 110
109#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 111#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
110 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 112 int (*audio_enable)(struct hdmi_ip_data *ip_data);
111 void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start); 113
114 void (*audio_disable)(struct hdmi_ip_data *ip_data);
115
116 int (*audio_start)(struct hdmi_ip_data *ip_data);
117
118 void (*audio_stop)(struct hdmi_ip_data *ip_data);
119
120 int (*audio_config)(struct hdmi_ip_data *ip_data,
121 struct omap_dss_audio *audio);
112#endif 122#endif
113 123
114}; 124};
@@ -173,7 +183,8 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
173void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data); 183void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
174int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len); 184int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
175bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data); 185bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
176void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start); 186int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data);
187void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data);
177int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data); 188int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
178void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data); 189void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
179void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data); 190void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
@@ -181,8 +192,13 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
181void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 192void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
182void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 193void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
183void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 194void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
184#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 195#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
185 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 196int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts);
186void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable); 197int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data);
198void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data);
199int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
200void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
201int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
202 struct omap_dss_audio *audio);
187#endif 203#endif
188#endif 204#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index bfe6fe65c8be..4dae1b291079 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -29,9 +29,14 @@
29#include <linux/string.h> 29#include <linux/string.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/gpio.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
32 36
33#include "ti_hdmi_4xxx_ip.h" 37#include "ti_hdmi_4xxx_ip.h"
34#include "dss.h" 38#include "dss.h"
39#include "dss_features.h"
35 40
36static inline void hdmi_write_reg(void __iomem *base_addr, 41static inline void hdmi_write_reg(void __iomem *base_addr,
37 const u16 idx, u32 val) 42 const u16 idx, u32 val)
@@ -298,9 +303,9 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
298 REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); 303 REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
299 304
300 r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio), 305 r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
301 NULL, hpd_irq_handler, 306 NULL, hpd_irq_handler,
302 IRQF_DISABLED | IRQF_TRIGGER_RISING | 307 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
303 IRQF_TRIGGER_FALLING, "hpd", ip_data); 308 IRQF_ONESHOT, "hpd", ip_data);
304 if (r) { 309 if (r) {
305 DSSERR("HPD IRQ request failed\n"); 310 DSSERR("HPD IRQ request failed\n");
306 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF); 311 hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
@@ -699,9 +704,15 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
699 704
700} 705}
701 706
702void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start) 707int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data)
708{
709 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31);
710 return 0;
711}
712
713void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data)
703{ 714{
704 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31); 715 REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31);
705} 716}
706 717
707static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, 718static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
@@ -886,10 +897,12 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
886 897
887#define CORE_REG(i, name) name(i) 898#define CORE_REG(i, name) name(i)
888#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\ 899#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
889 hdmi_read_reg(hdmi_pll_base(ip_data), r)) 900 hdmi_read_reg(hdmi_core_sys_base(ip_data), r))
890#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \ 901#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
902 hdmi_read_reg(hdmi_av_base(ip_data), r))
903#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
891 (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \ 904 (i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
892 hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r))) 905 hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
893 906
894 DUMPCORE(HDMI_CORE_SYS_VND_IDL); 907 DUMPCORE(HDMI_CORE_SYS_VND_IDL);
895 DUMPCORE(HDMI_CORE_SYS_DEV_IDL); 908 DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
@@ -898,6 +911,13 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
898 DUMPCORE(HDMI_CORE_SYS_SRST); 911 DUMPCORE(HDMI_CORE_SYS_SRST);
899 DUMPCORE(HDMI_CORE_CTRL1); 912 DUMPCORE(HDMI_CORE_CTRL1);
900 DUMPCORE(HDMI_CORE_SYS_SYS_STAT); 913 DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
914 DUMPCORE(HDMI_CORE_SYS_DE_DLY);
915 DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
916 DUMPCORE(HDMI_CORE_SYS_DE_TOP);
917 DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
918 DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
919 DUMPCORE(HDMI_CORE_SYS_DE_LINL);
920 DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
901 DUMPCORE(HDMI_CORE_SYS_VID_ACEN); 921 DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
902 DUMPCORE(HDMI_CORE_SYS_VID_MODE); 922 DUMPCORE(HDMI_CORE_SYS_VID_MODE);
903 DUMPCORE(HDMI_CORE_SYS_INTR_STATE); 923 DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
@@ -907,102 +927,91 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
907 DUMPCORE(HDMI_CORE_SYS_INTR4); 927 DUMPCORE(HDMI_CORE_SYS_INTR4);
908 DUMPCORE(HDMI_CORE_SYS_UMASK1); 928 DUMPCORE(HDMI_CORE_SYS_UMASK1);
909 DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL); 929 DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
910 DUMPCORE(HDMI_CORE_SYS_DE_DLY);
911 DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
912 DUMPCORE(HDMI_CORE_SYS_DE_TOP);
913 DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
914 DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
915 DUMPCORE(HDMI_CORE_SYS_DE_LINL);
916 DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
917 930
918 DUMPCORE(HDMI_CORE_DDC_CMD);
919 DUMPCORE(HDMI_CORE_DDC_STATUS);
920 DUMPCORE(HDMI_CORE_DDC_ADDR); 931 DUMPCORE(HDMI_CORE_DDC_ADDR);
932 DUMPCORE(HDMI_CORE_DDC_SEGM);
921 DUMPCORE(HDMI_CORE_DDC_OFFSET); 933 DUMPCORE(HDMI_CORE_DDC_OFFSET);
922 DUMPCORE(HDMI_CORE_DDC_COUNT1); 934 DUMPCORE(HDMI_CORE_DDC_COUNT1);
923 DUMPCORE(HDMI_CORE_DDC_COUNT2); 935 DUMPCORE(HDMI_CORE_DDC_COUNT2);
936 DUMPCORE(HDMI_CORE_DDC_STATUS);
937 DUMPCORE(HDMI_CORE_DDC_CMD);
924 DUMPCORE(HDMI_CORE_DDC_DATA); 938 DUMPCORE(HDMI_CORE_DDC_DATA);
925 DUMPCORE(HDMI_CORE_DDC_SEGM);
926 939
927 DUMPCORE(HDMI_CORE_AV_HDMI_CTRL); 940 DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL);
928 DUMPCORE(HDMI_CORE_AV_DPD); 941 DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL);
929 DUMPCORE(HDMI_CORE_AV_PB_CTRL1); 942 DUMPCOREAV(HDMI_CORE_AV_N_SVAL1);
930 DUMPCORE(HDMI_CORE_AV_PB_CTRL2); 943 DUMPCOREAV(HDMI_CORE_AV_N_SVAL2);
931 DUMPCORE(HDMI_CORE_AV_AVI_TYPE); 944 DUMPCOREAV(HDMI_CORE_AV_N_SVAL3);
932 DUMPCORE(HDMI_CORE_AV_AVI_VERS); 945 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1);
933 DUMPCORE(HDMI_CORE_AV_AVI_LEN); 946 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2);
934 DUMPCORE(HDMI_CORE_AV_AVI_CHSUM); 947 DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3);
948 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1);
949 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2);
950 DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3);
951 DUMPCOREAV(HDMI_CORE_AV_AUD_MODE);
952 DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL);
953 DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS);
954 DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S);
955 DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH);
956 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP);
957 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL);
958 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0);
959 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1);
960 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2);
961 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4);
962 DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5);
963 DUMPCOREAV(HDMI_CORE_AV_ASRC);
964 DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN);
965 DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL);
966 DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT);
967 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
968 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
969 DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
970 DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL);
971 DUMPCOREAV(HDMI_CORE_AV_DPD);
972 DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1);
973 DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2);
974 DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE);
975 DUMPCOREAV(HDMI_CORE_AV_AVI_VERS);
976 DUMPCOREAV(HDMI_CORE_AV_AVI_LEN);
977 DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM);
935 978
936 for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++) 979 for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
937 DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE); 980 DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE);
981
982 DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE);
983 DUMPCOREAV(HDMI_CORE_AV_SPD_VERS);
984 DUMPCOREAV(HDMI_CORE_AV_SPD_LEN);
985 DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM);
938 986
939 for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++) 987 for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
940 DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE); 988 DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE);
989
990 DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE);
991 DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS);
992 DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN);
993 DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM);
941 994
942 for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++) 995 for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
943 DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE); 996 DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE);
997
998 DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE);
999 DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS);
1000 DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN);
1001 DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM);
944 1002
945 for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++) 1003 for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
946 DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE); 1004 DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE);
947 1005
948 for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++) 1006 for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
949 DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE); 1007 DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE);
1008
1009 DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1);
950 1010
951 for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++) 1011 for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
952 DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE); 1012 DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE);
953 1013
954 DUMPCORE(HDMI_CORE_AV_ACR_CTRL); 1014 DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
955 DUMPCORE(HDMI_CORE_AV_FREQ_SVAL);
956 DUMPCORE(HDMI_CORE_AV_N_SVAL1);
957 DUMPCORE(HDMI_CORE_AV_N_SVAL2);
958 DUMPCORE(HDMI_CORE_AV_N_SVAL3);
959 DUMPCORE(HDMI_CORE_AV_CTS_SVAL1);
960 DUMPCORE(HDMI_CORE_AV_CTS_SVAL2);
961 DUMPCORE(HDMI_CORE_AV_CTS_SVAL3);
962 DUMPCORE(HDMI_CORE_AV_CTS_HVAL1);
963 DUMPCORE(HDMI_CORE_AV_CTS_HVAL2);
964 DUMPCORE(HDMI_CORE_AV_CTS_HVAL3);
965 DUMPCORE(HDMI_CORE_AV_AUD_MODE);
966 DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL);
967 DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS);
968 DUMPCORE(HDMI_CORE_AV_SWAP_I2S);
969 DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH);
970 DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP);
971 DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL);
972 DUMPCORE(HDMI_CORE_AV_I2S_CHST0);
973 DUMPCORE(HDMI_CORE_AV_I2S_CHST1);
974 DUMPCORE(HDMI_CORE_AV_I2S_CHST2);
975 DUMPCORE(HDMI_CORE_AV_I2S_CHST4);
976 DUMPCORE(HDMI_CORE_AV_I2S_CHST5);
977 DUMPCORE(HDMI_CORE_AV_ASRC);
978 DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN);
979 DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
980 DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT);
981 DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
982 DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
983 DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
984 DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL);
985 DUMPCORE(HDMI_CORE_AV_DPD);
986 DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
987 DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
988 DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
989 DUMPCORE(HDMI_CORE_AV_AVI_VERS);
990 DUMPCORE(HDMI_CORE_AV_AVI_LEN);
991 DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
992 DUMPCORE(HDMI_CORE_AV_SPD_TYPE);
993 DUMPCORE(HDMI_CORE_AV_SPD_VERS);
994 DUMPCORE(HDMI_CORE_AV_SPD_LEN);
995 DUMPCORE(HDMI_CORE_AV_SPD_CHSUM);
996 DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE);
997 DUMPCORE(HDMI_CORE_AV_AUDIO_VERS);
998 DUMPCORE(HDMI_CORE_AV_AUDIO_LEN);
999 DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM);
1000 DUMPCORE(HDMI_CORE_AV_MPEG_TYPE);
1001 DUMPCORE(HDMI_CORE_AV_MPEG_VERS);
1002 DUMPCORE(HDMI_CORE_AV_MPEG_LEN);
1003 DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM);
1004 DUMPCORE(HDMI_CORE_AV_CP_BYTE1);
1005 DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID);
1006} 1015}
1007 1016
1008void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s) 1017void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
@@ -1016,9 +1025,8 @@ void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
1016 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); 1025 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
1017} 1026}
1018 1027
1019#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 1028#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
1020 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 1029static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1021void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1022 struct hdmi_audio_format *aud_fmt) 1030 struct hdmi_audio_format *aud_fmt)
1023{ 1031{
1024 u32 r; 1032 u32 r;
@@ -1037,7 +1045,7 @@ void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
1037 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r); 1045 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
1038} 1046}
1039 1047
1040void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data, 1048static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
1041 struct hdmi_audio_dma *aud_dma) 1049 struct hdmi_audio_dma *aud_dma)
1042{ 1050{
1043 u32 r; 1051 u32 r;
@@ -1055,7 +1063,7 @@ void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
1055 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r); 1063 hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
1056} 1064}
1057 1065
1058void hdmi_core_audio_config(struct hdmi_ip_data *ip_data, 1066static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data,
1059 struct hdmi_core_audio_config *cfg) 1067 struct hdmi_core_audio_config *cfg)
1060{ 1068{
1061 u32 r; 1069 u32 r;
@@ -1106,27 +1114,33 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1106 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL, 1114 REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
1107 cfg->fs_override, 1, 1); 1115 cfg->fs_override, 1, 1);
1108 1116
1109 /* I2S parameters */ 1117 /*
1110 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4, 1118 * Set IEC-60958-3 channel status word. It is passed to the IP
1111 cfg->freq_sample, 3, 0); 1119 * just as it is received. The user of the driver is responsible
1112 1120 * for its contents.
1121 */
1122 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
1123 cfg->iec60958_cfg->status[0]);
1124 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
1125 cfg->iec60958_cfg->status[1]);
1126 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
1127 cfg->iec60958_cfg->status[2]);
1128 /* yes, this is correct: status[3] goes to CHST4 register */
1129 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
1130 cfg->iec60958_cfg->status[3]);
1131 /* yes, this is correct: status[4] goes to CHST5 register */
1132 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
1133 cfg->iec60958_cfg->status[4]);
1134
1135 /* set I2S parameters */
1113 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL); 1136 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL);
1114 r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
1115 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6); 1137 r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
1116 r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
1117 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4); 1138 r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
1118 r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
1119 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2); 1139 r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
1120 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1); 1140 r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
1121 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0); 1141 r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
1122 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r); 1142 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
1123 1143
1124 r = hdmi_read_reg(av_base, HDMI_CORE_AV_I2S_CHST5);
1125 r = FLD_MOD(r, cfg->freq_sample, 7, 4);
1126 r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
1127 r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
1128 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5, r);
1129
1130 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN, 1144 REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
1131 cfg->i2s_cfg.in_length_bits, 3, 0); 1145 cfg->i2s_cfg.in_length_bits, 3, 0);
1132 1146
@@ -1138,12 +1152,19 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
1138 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2); 1152 r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
1139 r = FLD_MOD(r, cfg->en_spdif, 1, 1); 1153 r = FLD_MOD(r, cfg->en_spdif, 1, 1);
1140 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r); 1154 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
1155
1156 /* Audio channel mappings */
1157 /* TODO: Make channel mapping dynamic. For now, map channels
1158 * in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
1159 * HDMI speaker order is different. See CEA-861 Section 6.6.2.
1160 */
1161 hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
1162 REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
1141} 1163}
1142 1164
1143void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, 1165static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data,
1144 struct hdmi_core_infoframe_audio *info_aud) 1166 struct snd_cea_861_aud_if *info_aud)
1145{ 1167{
1146 u8 val;
1147 u8 sum = 0, checksum = 0; 1168 u8 sum = 0, checksum = 0;
1148 void __iomem *av_base = hdmi_av_base(ip_data); 1169 void __iomem *av_base = hdmi_av_base(ip_data);
1149 1170
@@ -1157,24 +1178,23 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
1157 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a); 1178 hdmi_write_reg(av_base, HDMI_CORE_AV_AUDIO_LEN, 0x0a);
1158 sum += 0x84 + 0x001 + 0x00a; 1179 sum += 0x84 + 0x001 + 0x00a;
1159 1180
1160 val = (info_aud->db1_coding_type << 4) 1181 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
1161 | (info_aud->db1_channel_count - 1); 1182 info_aud->db1_ct_cc);
1162 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val); 1183 sum += info_aud->db1_ct_cc;
1163 sum += val;
1164 1184
1165 val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size; 1185 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
1166 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val); 1186 info_aud->db2_sf_ss);
1167 sum += val; 1187 sum += info_aud->db2_sf_ss;
1168 1188
1169 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00); 1189 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
1190 sum += info_aud->db3;
1170 1191
1171 val = info_aud->db4_channel_alloc; 1192 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
1172 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val); 1193 sum += info_aud->db4_ca;
1173 sum += val;
1174 1194
1175 val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3); 1195 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
1176 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val); 1196 info_aud->db5_dminh_lsv);
1177 sum += val; 1197 sum += info_aud->db5_dminh_lsv;
1178 1198
1179 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00); 1199 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
1180 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00); 1200 hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
@@ -1192,70 +1212,212 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
1192 */ 1212 */
1193} 1213}
1194 1214
1195int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, 1215int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
1196 u32 sample_freq, u32 *n, u32 *cts) 1216 struct omap_dss_audio *audio)
1197{ 1217{
1198 u32 r; 1218 struct hdmi_audio_format audio_format;
1199 u32 deep_color = 0; 1219 struct hdmi_audio_dma audio_dma;
1200 u32 pclk = ip_data->cfg.timings.pixel_clock; 1220 struct hdmi_core_audio_config core;
1201 1221 int err, n, cts, channel_count;
1202 if (n == NULL || cts == NULL) 1222 unsigned int fs_nr;
1223 bool word_length_16b = false;
1224
1225 if (!audio || !audio->iec || !audio->cea || !ip_data)
1203 return -EINVAL; 1226 return -EINVAL;
1227
1228 core.iec60958_cfg = audio->iec;
1204 /* 1229 /*
1205 * Obtain current deep color configuration. This needed 1230 * In the IEC-60958 status word, check if the audio sample word length
1206 * to calculate the TMDS clock based on the pixel clock. 1231 * is 16-bit as several optimizations can be performed in such case.
1207 */ 1232 */
1208 r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0); 1233 if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
1209 switch (r) { 1234 if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
1210 case 1: /* No deep color selected */ 1235 word_length_16b = true;
1211 deep_color = 100; 1236
1237 /* I2S configuration. See Phillips' specification */
1238 if (word_length_16b)
1239 core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1240 else
1241 core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1242 /*
1243 * The I2S input word length is twice the lenght given in the IEC-60958
1244 * status word. If the word size is greater than
1245 * 20 bits, increment by one.
1246 */
1247 core.i2s_cfg.in_length_bits = audio->iec->status[4]
1248 & IEC958_AES4_CON_WORDLEN;
1249 if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
1250 core.i2s_cfg.in_length_bits++;
1251 core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
1252 core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
1253 core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
1254 core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
1255
1256 /* convert sample frequency to a number */
1257 switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
1258 case IEC958_AES3_CON_FS_32000:
1259 fs_nr = 32000;
1260 break;
1261 case IEC958_AES3_CON_FS_44100:
1262 fs_nr = 44100;
1263 break;
1264 case IEC958_AES3_CON_FS_48000:
1265 fs_nr = 48000;
1212 break; 1266 break;
1213 case 2: /* 10-bit deep color selected */ 1267 case IEC958_AES3_CON_FS_88200:
1214 deep_color = 125; 1268 fs_nr = 88200;
1215 break; 1269 break;
1216 case 3: /* 12-bit deep color selected */ 1270 case IEC958_AES3_CON_FS_96000:
1217 deep_color = 150; 1271 fs_nr = 96000;
1272 break;
1273 case IEC958_AES3_CON_FS_176400:
1274 fs_nr = 176400;
1275 break;
1276 case IEC958_AES3_CON_FS_192000:
1277 fs_nr = 192000;
1218 break; 1278 break;
1219 default: 1279 default:
1220 return -EINVAL; 1280 return -EINVAL;
1221 } 1281 }
1222 1282
1223 switch (sample_freq) { 1283 err = hdmi_compute_acr(fs_nr, &n, &cts);
1224 case 32000: 1284
1225 if ((deep_color == 125) && ((pclk == 54054) 1285 /* Audio clock regeneration settings */
1226 || (pclk == 74250))) 1286 core.n = n;
1227 *n = 8192; 1287 core.cts = cts;
1228 else 1288 if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
1229 *n = 4096; 1289 core.aud_par_busclk = 0;
1290 core.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
1291 core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
1292 } else {
1293 core.aud_par_busclk = (((128 * 31) - 1) << 8);
1294 core.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
1295 core.use_mclk = true;
1296 }
1297
1298 if (core.use_mclk)
1299 core.mclk_mode = HDMI_AUDIO_MCLK_128FS;
1300
1301 /* Audio channels settings */
1302 channel_count = (audio->cea->db1_ct_cc &
1303 CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
1304
1305 switch (channel_count) {
1306 case 2:
1307 audio_format.active_chnnls_msk = 0x03;
1308 break;
1309 case 3:
1310 audio_format.active_chnnls_msk = 0x07;
1311 break;
1312 case 4:
1313 audio_format.active_chnnls_msk = 0x0f;
1314 break;
1315 case 5:
1316 audio_format.active_chnnls_msk = 0x1f;
1230 break; 1317 break;
1231 case 44100: 1318 case 6:
1232 *n = 6272; 1319 audio_format.active_chnnls_msk = 0x3f;
1233 break; 1320 break;
1234 case 48000: 1321 case 7:
1235 if ((deep_color == 125) && ((pclk == 54054) 1322 audio_format.active_chnnls_msk = 0x7f;
1236 || (pclk == 74250))) 1323 break;
1237 *n = 8192; 1324 case 8:
1238 else 1325 audio_format.active_chnnls_msk = 0xff;
1239 *n = 6144;
1240 break; 1326 break;
1241 default: 1327 default:
1242 *n = 0;
1243 return -EINVAL; 1328 return -EINVAL;
1244 } 1329 }
1245 1330
1246 /* Calculate CTS. See HDMI 1.3a or 1.4a specifications */ 1331 /*
1247 *cts = pclk * (*n / 128) * deep_color / (sample_freq / 10); 1332 * the HDMI IP needs to enable four stereo channels when transmitting
1333 * more than 2 audio channels
1334 */
1335 if (channel_count == 2) {
1336 audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
1337 core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
1338 core.layout = HDMI_AUDIO_LAYOUT_2CH;
1339 } else {
1340 audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
1341 core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
1342 HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
1343 HDMI_AUDIO_I2S_SD3_EN;
1344 core.layout = HDMI_AUDIO_LAYOUT_8CH;
1345 }
1346
1347 core.en_spdif = false;
1348 /* use sample frequency from channel status word */
1349 core.fs_override = true;
1350 /* enable ACR packets */
1351 core.en_acr_pkt = true;
1352 /* disable direct streaming digital audio */
1353 core.en_dsd_audio = false;
1354 /* use parallel audio interface */
1355 core.en_parallel_aud_input = true;
1356
1357 /* DMA settings */
1358 if (word_length_16b)
1359 audio_dma.transfer_size = 0x10;
1360 else
1361 audio_dma.transfer_size = 0x20;
1362 audio_dma.block_size = 0xC0;
1363 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
1364 audio_dma.fifo_threshold = 0x20; /* in number of samples */
1365
1366 /* audio FIFO format settings */
1367 if (word_length_16b) {
1368 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
1369 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
1370 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
1371 } else {
1372 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
1373 audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
1374 audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
1375 }
1376 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
1377 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
1378 /* disable start/stop signals of IEC 60958 blocks */
1379 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
1380
1381 /* configure DMA and audio FIFO format*/
1382 ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma);
1383 ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format);
1384
1385 /* configure the core*/
1386 ti_hdmi_4xxx_core_audio_config(ip_data, &core);
1387
1388 /* configure CEA 861 audio infoframe*/
1389 ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea);
1248 1390
1249 return 0; 1391 return 0;
1250} 1392}
1251 1393
1252void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable) 1394int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data)
1395{
1396 REG_FLD_MOD(hdmi_wp_base(ip_data),
1397 HDMI_WP_AUDIO_CTRL, true, 31, 31);
1398 return 0;
1399}
1400
1401void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data)
1402{
1403 REG_FLD_MOD(hdmi_wp_base(ip_data),
1404 HDMI_WP_AUDIO_CTRL, false, 31, 31);
1405}
1406
1407int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data)
1253{ 1408{
1254 REG_FLD_MOD(hdmi_av_base(ip_data), 1409 REG_FLD_MOD(hdmi_av_base(ip_data),
1255 HDMI_CORE_AV_AUD_MODE, enable, 0, 0); 1410 HDMI_CORE_AV_AUD_MODE, true, 0, 0);
1256 REG_FLD_MOD(hdmi_wp_base(ip_data), 1411 REG_FLD_MOD(hdmi_wp_base(ip_data),
1257 HDMI_WP_AUDIO_CTRL, enable, 31, 31); 1412 HDMI_WP_AUDIO_CTRL, true, 30, 30);
1413 return 0;
1414}
1415
1416void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
1417{
1418 REG_FLD_MOD(hdmi_av_base(ip_data),
1419 HDMI_CORE_AV_AUD_MODE, false, 0, 0);
1258 REG_FLD_MOD(hdmi_wp_base(ip_data), 1420 REG_FLD_MOD(hdmi_wp_base(ip_data),
1259 HDMI_WP_AUDIO_CTRL, enable, 30, 30); 1421 HDMI_WP_AUDIO_CTRL, false, 30, 30);
1260} 1422}
1261#endif 1423#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index a14d1a0e6e41..8366ae19e82e 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -24,11 +24,6 @@
24#include <linux/string.h> 24#include <linux/string.h>
25#include <video/omapdss.h> 25#include <video/omapdss.h>
26#include "ti_hdmi.h" 26#include "ti_hdmi.h"
27#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
28 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
29#include <sound/soc.h>
30#include <sound/pcm_params.h>
31#endif
32 27
33/* HDMI Wrapper */ 28/* HDMI Wrapper */
34 29
@@ -57,6 +52,13 @@
57#define HDMI_CORE_SYS_SRST 0x14 52#define HDMI_CORE_SYS_SRST 0x14
58#define HDMI_CORE_CTRL1 0x20 53#define HDMI_CORE_CTRL1 0x20
59#define HDMI_CORE_SYS_SYS_STAT 0x24 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
60#define HDMI_CORE_SYS_VID_ACEN 0x124 62#define HDMI_CORE_SYS_VID_ACEN 0x124
61#define HDMI_CORE_SYS_VID_MODE 0x128 63#define HDMI_CORE_SYS_VID_MODE 0x128
62#define HDMI_CORE_SYS_INTR_STATE 0x1C0 64#define HDMI_CORE_SYS_INTR_STATE 0x1C0
@@ -66,50 +68,24 @@
66#define HDMI_CORE_SYS_INTR4 0x1D0 68#define HDMI_CORE_SYS_INTR4 0x1D0
67#define HDMI_CORE_SYS_UMASK1 0x1D4 69#define HDMI_CORE_SYS_UMASK1 0x1D4
68#define HDMI_CORE_SYS_TMDS_CTRL 0x208 70#define HDMI_CORE_SYS_TMDS_CTRL 0x208
69#define HDMI_CORE_SYS_DE_DLY 0xC8 71
70#define HDMI_CORE_SYS_DE_CTRL 0xCC
71#define HDMI_CORE_SYS_DE_TOP 0xD0
72#define HDMI_CORE_SYS_DE_CNTL 0xD8
73#define HDMI_CORE_SYS_DE_CNTH 0xDC
74#define HDMI_CORE_SYS_DE_LINL 0xE0
75#define HDMI_CORE_SYS_DE_LINH_1 0xE4
76#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 72#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
77#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 73#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
78#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 74#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
79#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 75#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
80 76
81/* HDMI DDC E-DID */ 77/* HDMI DDC E-DID */
82#define HDMI_CORE_DDC_CMD 0x3CC
83#define HDMI_CORE_DDC_STATUS 0x3C8
84#define HDMI_CORE_DDC_ADDR 0x3B4 78#define HDMI_CORE_DDC_ADDR 0x3B4
79#define HDMI_CORE_DDC_SEGM 0x3B8
85#define HDMI_CORE_DDC_OFFSET 0x3BC 80#define HDMI_CORE_DDC_OFFSET 0x3BC
86#define HDMI_CORE_DDC_COUNT1 0x3C0 81#define HDMI_CORE_DDC_COUNT1 0x3C0
87#define HDMI_CORE_DDC_COUNT2 0x3C4 82#define HDMI_CORE_DDC_COUNT2 0x3C4
83#define HDMI_CORE_DDC_STATUS 0x3C8
84#define HDMI_CORE_DDC_CMD 0x3CC
88#define HDMI_CORE_DDC_DATA 0x3D0 85#define HDMI_CORE_DDC_DATA 0x3D0
89#define HDMI_CORE_DDC_SEGM 0x3B8
90 86
91/* HDMI IP Core Audio Video */ 87/* HDMI IP Core Audio Video */
92 88
93#define HDMI_CORE_AV_HDMI_CTRL 0xBC
94#define HDMI_CORE_AV_DPD 0xF4
95#define HDMI_CORE_AV_PB_CTRL1 0xF8
96#define HDMI_CORE_AV_PB_CTRL2 0xFC
97#define HDMI_CORE_AV_AVI_TYPE 0x100
98#define HDMI_CORE_AV_AVI_VERS 0x104
99#define HDMI_CORE_AV_AVI_LEN 0x108
100#define HDMI_CORE_AV_AVI_CHSUM 0x10C
101#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
102#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
103#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
104#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
105#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
106#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
107#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
108#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
109#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
110#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
111#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
112#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
113#define HDMI_CORE_AV_ACR_CTRL 0x4 89#define HDMI_CORE_AV_ACR_CTRL 0x4
114#define HDMI_CORE_AV_FREQ_SVAL 0x8 90#define HDMI_CORE_AV_FREQ_SVAL 0x8
115#define HDMI_CORE_AV_N_SVAL1 0xC 91#define HDMI_CORE_AV_N_SVAL1 0xC
@@ -148,25 +124,39 @@
148#define HDMI_CORE_AV_AVI_VERS 0x104 124#define HDMI_CORE_AV_AVI_VERS 0x104
149#define HDMI_CORE_AV_AVI_LEN 0x108 125#define HDMI_CORE_AV_AVI_LEN 0x108
150#define HDMI_CORE_AV_AVI_CHSUM 0x10C 126#define HDMI_CORE_AV_AVI_CHSUM 0x10C
127#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
151#define HDMI_CORE_AV_SPD_TYPE 0x180 128#define HDMI_CORE_AV_SPD_TYPE 0x180
152#define HDMI_CORE_AV_SPD_VERS 0x184 129#define HDMI_CORE_AV_SPD_VERS 0x184
153#define HDMI_CORE_AV_SPD_LEN 0x188 130#define HDMI_CORE_AV_SPD_LEN 0x188
154#define HDMI_CORE_AV_SPD_CHSUM 0x18C 131#define HDMI_CORE_AV_SPD_CHSUM 0x18C
132#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
155#define HDMI_CORE_AV_AUDIO_TYPE 0x200 133#define HDMI_CORE_AV_AUDIO_TYPE 0x200
156#define HDMI_CORE_AV_AUDIO_VERS 0x204 134#define HDMI_CORE_AV_AUDIO_VERS 0x204
157#define HDMI_CORE_AV_AUDIO_LEN 0x208 135#define HDMI_CORE_AV_AUDIO_LEN 0x208
158#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C 136#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
137#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
159#define HDMI_CORE_AV_MPEG_TYPE 0x280 138#define HDMI_CORE_AV_MPEG_TYPE 0x280
160#define HDMI_CORE_AV_MPEG_VERS 0x284 139#define HDMI_CORE_AV_MPEG_VERS 0x284
161#define HDMI_CORE_AV_MPEG_LEN 0x288 140#define HDMI_CORE_AV_MPEG_LEN 0x288
162#define HDMI_CORE_AV_MPEG_CHSUM 0x28C 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)
163#define HDMI_CORE_AV_CP_BYTE1 0x37C 144#define HDMI_CORE_AV_CP_BYTE1 0x37C
145#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
164#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC 146#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC
147
165#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 148#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
166#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 149#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
167#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 150#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
168#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 151#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
169 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
170/* PLL */ 160/* PLL */
171 161
172#define PLLCTRL_PLL_CONTROL 0x0 162#define PLLCTRL_PLL_CONTROL 0x0
@@ -284,35 +274,6 @@ enum hdmi_core_infoframe {
284 HDMI_INFOFRAME_AVI_DB5PR_8 = 7, 274 HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
285 HDMI_INFOFRAME_AVI_DB5PR_9 = 8, 275 HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
286 HDMI_INFOFRAME_AVI_DB5PR_10 = 9, 276 HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
287 HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0,
288 HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1,
289 HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2,
290 HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3,
291 HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4,
292 HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5,
293 HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6,
294 HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7,
295 HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8,
296 HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9,
297 HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10,
298 HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11,
299 HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12,
300 HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13,
301 HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14,
302 HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0,
303 HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1,
304 HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2,
305 HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3,
306 HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4,
307 HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5,
308 HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6,
309 HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7,
310 HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0,
311 HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1,
312 HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2,
313 HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3,
314 HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0,
315 HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1
316}; 277};
317 278
318enum hdmi_packing_mode { 279enum hdmi_packing_mode {
@@ -322,17 +283,6 @@ enum hdmi_packing_mode {
322 HDMI_PACK_ALREADYPACKED = 7 283 HDMI_PACK_ALREADYPACKED = 7
323}; 284};
324 285
325enum hdmi_core_audio_sample_freq {
326 HDMI_AUDIO_FS_32000 = 0x3,
327 HDMI_AUDIO_FS_44100 = 0x0,
328 HDMI_AUDIO_FS_48000 = 0x2,
329 HDMI_AUDIO_FS_88200 = 0x8,
330 HDMI_AUDIO_FS_96000 = 0xA,
331 HDMI_AUDIO_FS_176400 = 0xC,
332 HDMI_AUDIO_FS_192000 = 0xE,
333 HDMI_AUDIO_FS_NOT_INDICATED = 0x1
334};
335
336enum hdmi_core_audio_layout { 286enum hdmi_core_audio_layout {
337 HDMI_AUDIO_LAYOUT_2CH = 0, 287 HDMI_AUDIO_LAYOUT_2CH = 0,
338 HDMI_AUDIO_LAYOUT_8CH = 1 288 HDMI_AUDIO_LAYOUT_8CH = 1
@@ -387,37 +337,12 @@ enum hdmi_audio_blk_strt_end_sig {
387}; 337};
388 338
389enum hdmi_audio_i2s_config { 339enum hdmi_audio_i2s_config {
390 HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0,
391 HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1,
392 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0, 340 HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
393 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1, 341 HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
394 HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0,
395 HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1,
396 HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0,
397 HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1,
398 HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6,
399 HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2,
400 HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4,
401 HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5,
402 HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1,
403 HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6,
404 HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2,
405 HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4,
406 HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5,
407 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0, 342 HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
408 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1, 343 HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
409 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0, 344 HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
410 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1, 345 HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
411 HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0,
412 HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2,
413 HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12,
414 HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4,
415 HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8,
416 HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10,
417 HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13,
418 HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5,
419 HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9,
420 HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11,
421 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0, 346 HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
422 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1, 347 HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
423 HDMI_AUDIO_I2S_SD0_EN = 1, 348 HDMI_AUDIO_I2S_SD0_EN = 1,
@@ -446,20 +371,6 @@ struct hdmi_core_video_config {
446 enum hdmi_core_tclkselclkmult tclk_sel_clkmult; 371 enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
447}; 372};
448 373
449/*
450 * Refer to section 8.2 in HDMI 1.3 specification for
451 * details about infoframe databytes
452 */
453struct hdmi_core_infoframe_audio {
454 u8 db1_coding_type;
455 u8 db1_channel_count;
456 u8 db2_sample_freq;
457 u8 db2_sample_size;
458 u8 db4_channel_alloc;
459 bool db5_downmix_inh;
460 u8 db5_lsv; /* Level shift values for downmix */
461};
462
463struct hdmi_core_packet_enable_repeat { 374struct hdmi_core_packet_enable_repeat {
464 u32 audio_pkt; 375 u32 audio_pkt;
465 u32 audio_pkt_repeat; 376 u32 audio_pkt_repeat;
@@ -496,15 +407,10 @@ struct hdmi_audio_dma {
496}; 407};
497 408
498struct hdmi_core_audio_i2s_config { 409struct hdmi_core_audio_i2s_config {
499 u8 word_max_length;
500 u8 word_length;
501 u8 in_length_bits; 410 u8 in_length_bits;
502 u8 justification; 411 u8 justification;
503 u8 en_high_bitrate_aud;
504 u8 sck_edge_mode; 412 u8 sck_edge_mode;
505 u8 cbit_order;
506 u8 vbit; 413 u8 vbit;
507 u8 ws_polarity;
508 u8 direction; 414 u8 direction;
509 u8 shift; 415 u8 shift;
510 u8 active_sds; 416 u8 active_sds;
@@ -512,7 +418,7 @@ struct hdmi_core_audio_i2s_config {
512 418
513struct hdmi_core_audio_config { 419struct hdmi_core_audio_config {
514 struct hdmi_core_audio_i2s_config i2s_cfg; 420 struct hdmi_core_audio_i2s_config i2s_cfg;
515 enum hdmi_core_audio_sample_freq freq_sample; 421 struct snd_aes_iec958 *iec60958_cfg;
516 bool fs_override; 422 bool fs_override;
517 u32 n; 423 u32 n;
518 u32 cts; 424 u32 cts;
@@ -527,17 +433,4 @@ struct hdmi_core_audio_config {
527 bool en_spdif; 433 bool en_spdif;
528}; 434};
529 435
530#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
531 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
532int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
533 u32 sample_freq, u32 *n, u32 *cts);
534void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
535 struct hdmi_core_infoframe_audio *info_aud);
536void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
537 struct hdmi_core_audio_config *cfg);
538void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
539 struct hdmi_audio_dma *aud_dma);
540void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
541 struct hdmi_audio_format *aud_fmt);
542#endif
543#endif 436#endif
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 9c3daf71750c..2b8973931ff4 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -415,6 +415,7 @@ static const struct venc_config *venc_timings_to_config(
415 return &venc_config_ntsc_trm; 415 return &venc_config_ntsc_trm;
416 416
417 BUG(); 417 BUG();
418 return NULL;
418} 419}
419 420
420static int venc_power_on(struct omap_dss_device *dssdev) 421static int venc_power_on(struct omap_dss_device *dssdev)
@@ -440,10 +441,11 @@ static int venc_power_on(struct omap_dss_device *dssdev)
440 441
441 venc_write_reg(VENC_OUTPUT_CONTROL, l); 442 venc_write_reg(VENC_OUTPUT_CONTROL, l);
442 443
443 dispc_set_digit_size(dssdev->panel.timings.x_res, 444 dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
444 dssdev->panel.timings.y_res/2);
445 445
446 regulator_enable(venc.vdda_dac_reg); 446 r = regulator_enable(venc.vdda_dac_reg);
447 if (r)
448 goto err;
447 449
448 if (dssdev->platform_enable) 450 if (dssdev->platform_enable)
449 dssdev->platform_enable(dssdev); 451 dssdev->platform_enable(dssdev);
@@ -485,16 +487,68 @@ unsigned long venc_get_pixel_clock(void)
485 return 13500000; 487 return 13500000;
486} 488}
487 489
490static ssize_t display_output_type_show(struct device *dev,
491 struct device_attribute *attr, char *buf)
492{
493 struct omap_dss_device *dssdev = to_dss_device(dev);
494 const char *ret;
495
496 switch (dssdev->phy.venc.type) {
497 case OMAP_DSS_VENC_TYPE_COMPOSITE:
498 ret = "composite";
499 break;
500 case OMAP_DSS_VENC_TYPE_SVIDEO:
501 ret = "svideo";
502 break;
503 default:
504 return -EINVAL;
505 }
506
507 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
508}
509
510static ssize_t display_output_type_store(struct device *dev,
511 struct device_attribute *attr, const char *buf, size_t size)
512{
513 struct omap_dss_device *dssdev = to_dss_device(dev);
514 enum omap_dss_venc_type new_type;
515
516 if (sysfs_streq("composite", buf))
517 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
518 else if (sysfs_streq("svideo", buf))
519 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
520 else
521 return -EINVAL;
522
523 mutex_lock(&venc.venc_lock);
524
525 if (dssdev->phy.venc.type != new_type) {
526 dssdev->phy.venc.type = new_type;
527 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
528 venc_power_off(dssdev);
529 venc_power_on(dssdev);
530 }
531 }
532
533 mutex_unlock(&venc.venc_lock);
534
535 return size;
536}
537
538static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
539 display_output_type_show, display_output_type_store);
540
488/* driver */ 541/* driver */
489static int venc_panel_probe(struct omap_dss_device *dssdev) 542static int venc_panel_probe(struct omap_dss_device *dssdev)
490{ 543{
491 dssdev->panel.timings = omap_dss_pal_timings; 544 dssdev->panel.timings = omap_dss_pal_timings;
492 545
493 return 0; 546 return device_create_file(&dssdev->dev, &dev_attr_output_type);
494} 547}
495 548
496static void venc_panel_remove(struct omap_dss_device *dssdev) 549static void venc_panel_remove(struct omap_dss_device *dssdev)
497{ 550{
551 device_remove_file(&dssdev->dev, &dev_attr_output_type);
498} 552}
499 553
500static int venc_panel_enable(struct omap_dss_device *dssdev) 554static int venc_panel_enable(struct omap_dss_device *dssdev)
@@ -577,12 +631,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
577 return venc_panel_enable(dssdev); 631 return venc_panel_enable(dssdev);
578} 632}
579 633
580static void venc_get_timings(struct omap_dss_device *dssdev,
581 struct omap_video_timings *timings)
582{
583 *timings = dssdev->panel.timings;
584}
585
586static void venc_set_timings(struct omap_dss_device *dssdev, 634static void venc_set_timings(struct omap_dss_device *dssdev,
587 struct omap_video_timings *timings) 635 struct omap_video_timings *timings)
588{ 636{
@@ -597,6 +645,8 @@ static void venc_set_timings(struct omap_dss_device *dssdev,
597 /* turn the venc off and on to get new timings to use */ 645 /* turn the venc off and on to get new timings to use */
598 venc_panel_disable(dssdev); 646 venc_panel_disable(dssdev);
599 venc_panel_enable(dssdev); 647 venc_panel_enable(dssdev);
648 } else {
649 dss_mgr_set_timings(dssdev->manager, timings);
600 } 650 }
601} 651}
602 652
@@ -661,7 +711,6 @@ static struct omap_dss_driver venc_driver = {
661 .get_resolution = omapdss_default_get_resolution, 711 .get_resolution = omapdss_default_get_resolution,
662 .get_recommended_bpp = omapdss_default_get_recommended_bpp, 712 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
663 713
664 .get_timings = venc_get_timings,
665 .set_timings = venc_set_timings, 714 .set_timings = venc_set_timings,
666 .check_timings = venc_check_timings, 715 .check_timings = venc_check_timings,
667 716
@@ -675,7 +724,7 @@ static struct omap_dss_driver venc_driver = {
675}; 724};
676/* driver end */ 725/* driver end */
677 726
678int venc_init_display(struct omap_dss_device *dssdev) 727static int __init venc_init_display(struct omap_dss_device *dssdev)
679{ 728{
680 DSSDBG("init_display\n"); 729 DSSDBG("init_display\n");
681 730
@@ -695,7 +744,7 @@ int venc_init_display(struct omap_dss_device *dssdev)
695 return 0; 744 return 0;
696} 745}
697 746
698void venc_dump_regs(struct seq_file *s) 747static void venc_dump_regs(struct seq_file *s)
699{ 748{
700#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r)) 749#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
701 750
@@ -779,8 +828,32 @@ static void venc_put_clocks(void)
779 clk_put(venc.tv_dac_clk); 828 clk_put(venc.tv_dac_clk);
780} 829}
781 830
831static void __init venc_probe_pdata(struct platform_device *pdev)
832{
833 struct omap_dss_board_info *pdata = pdev->dev.platform_data;
834 int r, i;
835
836 for (i = 0; i < pdata->num_devices; ++i) {
837 struct omap_dss_device *dssdev = pdata->devices[i];
838
839 if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
840 continue;
841
842 r = venc_init_display(dssdev);
843 if (r) {
844 DSSERR("device %s init failed: %d\n", dssdev->name, r);
845 continue;
846 }
847
848 r = omap_dss_register_device(dssdev, &pdev->dev, i);
849 if (r)
850 DSSERR("device %s register failed: %d\n",
851 dssdev->name, r);
852 }
853}
854
782/* VENC HW IP initialisation */ 855/* VENC HW IP initialisation */
783static int omap_venchw_probe(struct platform_device *pdev) 856static int __init omap_venchw_probe(struct platform_device *pdev)
784{ 857{
785 u8 rev_id; 858 u8 rev_id;
786 struct resource *venc_mem; 859 struct resource *venc_mem;
@@ -824,6 +897,10 @@ static int omap_venchw_probe(struct platform_device *pdev)
824 if (r) 897 if (r)
825 goto err_reg_panel_driver; 898 goto err_reg_panel_driver;
826 899
900 dss_debugfs_create_file("venc", venc_dump_regs);
901
902 venc_probe_pdata(pdev);
903
827 return 0; 904 return 0;
828 905
829err_reg_panel_driver: 906err_reg_panel_driver:
@@ -833,12 +910,15 @@ err_runtime_get:
833 return r; 910 return r;
834} 911}
835 912
836static int omap_venchw_remove(struct platform_device *pdev) 913static int __exit omap_venchw_remove(struct platform_device *pdev)
837{ 914{
915 omap_dss_unregister_child_devices(&pdev->dev);
916
838 if (venc.vdda_dac_reg != NULL) { 917 if (venc.vdda_dac_reg != NULL) {
839 regulator_put(venc.vdda_dac_reg); 918 regulator_put(venc.vdda_dac_reg);
840 venc.vdda_dac_reg = NULL; 919 venc.vdda_dac_reg = NULL;
841 } 920 }
921
842 omap_dss_unregister_driver(&venc_driver); 922 omap_dss_unregister_driver(&venc_driver);
843 923
844 pm_runtime_disable(&pdev->dev); 924 pm_runtime_disable(&pdev->dev);
@@ -853,7 +933,6 @@ static int venc_runtime_suspend(struct device *dev)
853 clk_disable(venc.tv_dac_clk); 933 clk_disable(venc.tv_dac_clk);
854 934
855 dispc_runtime_put(); 935 dispc_runtime_put();
856 dss_runtime_put();
857 936
858 return 0; 937 return 0;
859} 938}
@@ -862,23 +941,14 @@ static int venc_runtime_resume(struct device *dev)
862{ 941{
863 int r; 942 int r;
864 943
865 r = dss_runtime_get();
866 if (r < 0)
867 goto err_get_dss;
868
869 r = dispc_runtime_get(); 944 r = dispc_runtime_get();
870 if (r < 0) 945 if (r < 0)
871 goto err_get_dispc; 946 return r;
872 947
873 if (venc.tv_dac_clk) 948 if (venc.tv_dac_clk)
874 clk_enable(venc.tv_dac_clk); 949 clk_enable(venc.tv_dac_clk);
875 950
876 return 0; 951 return 0;
877
878err_get_dispc:
879 dss_runtime_put();
880err_get_dss:
881 return r;
882} 952}
883 953
884static const struct dev_pm_ops venc_pm_ops = { 954static const struct dev_pm_ops venc_pm_ops = {
@@ -887,8 +957,7 @@ static const struct dev_pm_ops venc_pm_ops = {
887}; 957};
888 958
889static struct platform_driver omap_venchw_driver = { 959static struct platform_driver omap_venchw_driver = {
890 .probe = omap_venchw_probe, 960 .remove = __exit_p(omap_venchw_remove),
891 .remove = omap_venchw_remove,
892 .driver = { 961 .driver = {
893 .name = "omapdss_venc", 962 .name = "omapdss_venc",
894 .owner = THIS_MODULE, 963 .owner = THIS_MODULE,
@@ -896,18 +965,18 @@ static struct platform_driver omap_venchw_driver = {
896 }, 965 },
897}; 966};
898 967
899int venc_init_platform_driver(void) 968int __init venc_init_platform_driver(void)
900{ 969{
901 if (cpu_is_omap44xx()) 970 if (cpu_is_omap44xx())
902 return 0; 971 return 0;
903 972
904 return platform_driver_register(&omap_venchw_driver); 973 return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
905} 974}
906 975
907void venc_uninit_platform_driver(void) 976void __exit venc_uninit_platform_driver(void)
908{ 977{
909 if (cpu_is_omap44xx()) 978 if (cpu_is_omap44xx())
910 return; 979 return;
911 980
912 return platform_driver_unregister(&omap_venchw_driver); 981 platform_driver_unregister(&omap_venchw_driver);
913} 982}
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 6a09ef87e14f..c6cf372d22c5 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -70,7 +70,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
70 70
71 DBG("omapfb_setup_plane\n"); 71 DBG("omapfb_setup_plane\n");
72 72
73 if (ofbi->num_overlays != 1) { 73 if (ofbi->num_overlays == 0) {
74 r = -EINVAL; 74 r = -EINVAL;
75 goto out; 75 goto out;
76 } 76 }
@@ -185,7 +185,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
185{ 185{
186 struct omapfb_info *ofbi = FB2OFB(fbi); 186 struct omapfb_info *ofbi = FB2OFB(fbi);
187 187
188 if (ofbi->num_overlays != 1) { 188 if (ofbi->num_overlays == 0) {
189 memset(pi, 0, sizeof(*pi)); 189 memset(pi, 0, sizeof(*pi));
190 } else { 190 } else {
191 struct omap_overlay *ovl; 191 struct omap_overlay *ovl;
@@ -225,6 +225,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
225 down_write_nested(&rg->lock, rg->id); 225 down_write_nested(&rg->lock, rg->id);
226 atomic_inc(&rg->lock_count); 226 atomic_inc(&rg->lock_count);
227 227
228 if (rg->size == size && rg->type == mi->type)
229 goto out;
230
228 if (atomic_read(&rg->map_count)) { 231 if (atomic_read(&rg->map_count)) {
229 r = -EBUSY; 232 r = -EBUSY;
230 goto out; 233 goto out;
@@ -247,12 +250,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
247 } 250 }
248 } 251 }
249 252
250 if (rg->size != size || rg->type != mi->type) { 253 r = omapfb_realloc_fbmem(fbi, size, mi->type);
251 r = omapfb_realloc_fbmem(fbi, size, mi->type); 254 if (r) {
252 if (r) { 255 dev_err(fbdev->dev, "realloc fbmem failed\n");
253 dev_err(fbdev->dev, "realloc fbmem failed\n"); 256 goto out;
254 goto out;
255 }
256 } 257 }
257 258
258 out: 259 out:
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index b00db4068d21..3450ea0966c9 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -179,6 +179,7 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
179 break; 179 break;
180 default: 180 default:
181 BUG(); 181 BUG();
182 return 0;
182 } 183 }
183 184
184 offset *= vrfb->bytespp; 185 offset *= vrfb->bytespp;
@@ -1502,7 +1503,7 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
1502 1503
1503 fbnum = simple_strtoul(p, &p, 10); 1504 fbnum = simple_strtoul(p, &p, 10);
1504 1505
1505 if (p == param) 1506 if (p == start)
1506 return -EINVAL; 1507 return -EINVAL;
1507 1508
1508 if (*p != ':') 1509 if (*p != ':')
@@ -2307,7 +2308,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
2307 return 0; 2308 return 0;
2308} 2309}
2309 2310
2310static int omapfb_probe(struct platform_device *pdev) 2311static int __init omapfb_probe(struct platform_device *pdev)
2311{ 2312{
2312 struct omapfb2_device *fbdev = NULL; 2313 struct omapfb2_device *fbdev = NULL;
2313 int r = 0; 2314 int r = 0;
@@ -2448,7 +2449,7 @@ err0:
2448 return r; 2449 return r;
2449} 2450}
2450 2451
2451static int omapfb_remove(struct platform_device *pdev) 2452static int __exit omapfb_remove(struct platform_device *pdev)
2452{ 2453{
2453 struct omapfb2_device *fbdev = platform_get_drvdata(pdev); 2454 struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
2454 2455
@@ -2462,8 +2463,7 @@ static int omapfb_remove(struct platform_device *pdev)
2462} 2463}
2463 2464
2464static struct platform_driver omapfb_driver = { 2465static struct platform_driver omapfb_driver = {
2465 .probe = omapfb_probe, 2466 .remove = __exit_p(omapfb_remove),
2466 .remove = omapfb_remove,
2467 .driver = { 2467 .driver = {
2468 .name = "omapfb", 2468 .name = "omapfb",
2469 .owner = THIS_MODULE, 2469 .owner = THIS_MODULE,
@@ -2474,7 +2474,7 @@ static int __init omapfb_init(void)
2474{ 2474{
2475 DBG("omapfb_init\n"); 2475 DBG("omapfb_init\n");
2476 2476
2477 if (platform_driver_register(&omapfb_driver)) { 2477 if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
2478 printk(KERN_ERR "failed to register omapfb driver\n"); 2478 printk(KERN_ERR "failed to register omapfb driver\n");
2479 return -ENODEV; 2479 return -ENODEV;
2480 } 2480 }
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index c0bdc9b54ecf..30361a09aecd 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -166,6 +166,7 @@ static inline struct omapfb_display_data *get_display_data(
166 166
167 /* This should never happen */ 167 /* This should never happen */
168 BUG(); 168 BUG();
169 return NULL;
169} 170}
170 171
171static inline void omapfb_lock(struct omapfb2_device *fbdev) 172static inline void omapfb_lock(struct omapfb2_device *fbdev)
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 4e5b960c32c8..7e990220ad2a 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -179,8 +179,10 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
179 pixel_size_exp = 2; 179 pixel_size_exp = 2;
180 else if (bytespp == 2) 180 else if (bytespp == 2)
181 pixel_size_exp = 1; 181 pixel_size_exp = 1;
182 else 182 else {
183 BUG(); 183 BUG();
184 return;
185 }
184 186
185 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp; 187 vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
186 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT); 188 vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);