aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/video/hdmi-connector.txt1
-rw-r--r--Documentation/devicetree/bindings/video/lgphilips,lb035q02.txt33
-rw-r--r--Documentation/devicetree/bindings/video/panel-dpi.txt45
-rw-r--r--Documentation/devicetree/bindings/video/sharp,ls037v7dw01.txt43
-rw-r--r--Documentation/devicetree/bindings/video/ti,omap4-dss.txt4
-rw-r--r--Documentation/devicetree/bindings/video/ti,omap5-dss.txt96
-rw-r--r--Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt30
-rw-r--r--Documentation/devicetree/bindings/video/tpo,td043mtea1.txt33
-rw-r--r--arch/arm/mach-omap2/display.c62
-rw-r--r--drivers/video/fbdev/omap2/Makefile2
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-hdmi.c25
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-dpi.c95
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c77
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c45
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c210
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c33
-rw-r--r--drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c42
-rw-r--r--drivers/video/fbdev/omap2/dss/Kconfig26
-rw-r--r--drivers/video/fbdev/omap2/dss/Makefile7
-rw-r--r--drivers/video/fbdev/omap2/dss/core.c6
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.c22
-rw-r--r--drivers/video/fbdev/omap2/dss/dpi.c4
-rw-r--r--drivers/video/fbdev/omap2/dss/dsi.c18
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.c20
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.h3
-rw-r--r--drivers/video/fbdev/omap2/dss/dss_features.c70
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi.h17
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4.c113
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.c28
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5.c829
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5_core.c922
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5_core.h306
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_common.c41
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_phy.c265
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_pll.c107
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_wp.c29
-rw-r--r--drivers/video/fbdev/omap2/dss/omapdss-boot-init.c229
-rw-r--r--drivers/video/fbdev/omap2/dss/venc_panel.c232
-rw-r--r--include/video/omapdss.h8
39 files changed, 3604 insertions, 574 deletions
diff --git a/Documentation/devicetree/bindings/video/hdmi-connector.txt b/Documentation/devicetree/bindings/video/hdmi-connector.txt
index ccccc19e2573..acd5668b1ce1 100644
--- a/Documentation/devicetree/bindings/video/hdmi-connector.txt
+++ b/Documentation/devicetree/bindings/video/hdmi-connector.txt
@@ -7,6 +7,7 @@ Required properties:
7 7
8Optional properties: 8Optional properties:
9- label: a symbolic name for the connector 9- label: a symbolic name for the connector
10- hpd-gpios: HPD GPIO number
10 11
11Required nodes: 12Required nodes:
12- Video port for HDMI input 13- Video port for HDMI input
diff --git a/Documentation/devicetree/bindings/video/lgphilips,lb035q02.txt b/Documentation/devicetree/bindings/video/lgphilips,lb035q02.txt
new file mode 100644
index 000000000000..1a1e653e5407
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/lgphilips,lb035q02.txt
@@ -0,0 +1,33 @@
1LG.Philips LB035Q02 Panel
2=========================
3
4Required properties:
5- compatible: "lgphilips,lb035q02"
6- enable-gpios: panel enable gpio
7
8Optional properties:
9- label: a symbolic name for the panel
10
11Required nodes:
12- Video port for DPI input
13
14Example
15-------
16
17lcd-panel: panel@0 {
18 compatible = "lgphilips,lb035q02";
19 reg = <0>;
20 spi-max-frequency = <100000>;
21 spi-cpol;
22 spi-cpha;
23
24 label = "lcd";
25
26 enable-gpios = <&gpio7 7 0>;
27
28 port {
29 lcd_in: endpoint {
30 remote-endpoint = <&dpi_out>;
31 };
32 };
33};
diff --git a/Documentation/devicetree/bindings/video/panel-dpi.txt b/Documentation/devicetree/bindings/video/panel-dpi.txt
new file mode 100644
index 000000000000..a40180b05bab
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/panel-dpi.txt
@@ -0,0 +1,45 @@
1Generic MIPI DPI Panel
2======================
3
4Required properties:
5- compatible: "panel-dpi"
6
7Optional properties:
8- label: a symbolic name for the panel
9- enable-gpios: panel enable gpio
10
11Required nodes:
12- "panel-timing" containing video timings
13 (Documentation/devicetree/bindings/video/display-timing.txt)
14- Video port for DPI input
15
16Example
17-------
18
19lcd0: display@0 {
20 compatible = "samsung,lte430wq-f0c", "panel-dpi";
21 label = "lcd";
22
23 port {
24 lcd_in: endpoint {
25 remote-endpoint = <&dpi_out>;
26 };
27 };
28
29 panel-timing {
30 clock-frequency = <9200000>;
31 hactive = <480>;
32 vactive = <272>;
33 hfront-porch = <8>;
34 hback-porch = <4>;
35 hsync-len = <41>;
36 vback-porch = <2>;
37 vfront-porch = <4>;
38 vsync-len = <10>;
39
40 hsync-active = <0>;
41 vsync-active = <0>;
42 de-active = <1>;
43 pixelclk-active = <1>;
44 };
45};
diff --git a/Documentation/devicetree/bindings/video/sharp,ls037v7dw01.txt b/Documentation/devicetree/bindings/video/sharp,ls037v7dw01.txt
new file mode 100644
index 000000000000..0cc8981e9d49
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/sharp,ls037v7dw01.txt
@@ -0,0 +1,43 @@
1SHARP LS037V7DW01 TFT-LCD panel
2===================================
3
4Required properties:
5- compatible: "sharp,ls037v7dw01"
6
7Optional properties:
8- label: a symbolic name for the panel
9- enable-gpios: a GPIO spec for the optional enable pin.
10 This pin is the INI pin as specified in the LS037V7DW01.pdf file.
11- reset-gpios: a GPIO spec for the optional reset pin.
12 This pin is the RESB pin as specified in the LS037V7DW01.pdf file.
13- mode-gpios: a GPIO
14 ordered MO, LR, and UD as specified in the LS037V7DW01.pdf file.
15
16Required nodes:
17- Video port for DPI input
18
19This panel can have zero to five GPIOs to configure to change configuration
20between QVGA and VGA mode and the scan direction. As these pins can be also
21configured with external pulls, all the GPIOs are considered optional with holes
22in the array.
23
24Example
25-------
26
27Example when connected to a omap2+ based device:
28
29lcd0: display {
30 compatible = "sharp,ls037v7dw01";
31 power-supply = <&lcd_3v3>;
32 enable-gpios = <&gpio5 24 GPIO_ACTIVE_HIGH>; /* gpio152, lcd INI */
33 reset-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>; /* gpio155, lcd RESB */
34 mode-gpios = <&gpio5 26 GPIO_ACTIVE_HIGH /* gpio154, lcd MO */
35 &gpio1 2 GPIO_ACTIVE_HIGH /* gpio2, lcd LR */
36 &gpio1 3 GPIO_ACTIVE_HIGH>; /* gpio3, lcd UD */
37
38 port {
39 lcd_in: endpoint {
40 remote-endpoint = <&dpi_out>;
41 };
42 };
43};
diff --git a/Documentation/devicetree/bindings/video/ti,omap4-dss.txt b/Documentation/devicetree/bindings/video/ti,omap4-dss.txt
index f85d6fcfa705..b8c29fbd1fbb 100644
--- a/Documentation/devicetree/bindings/video/ti,omap4-dss.txt
+++ b/Documentation/devicetree/bindings/video/ti,omap4-dss.txt
@@ -109,3 +109,7 @@ Required properties:
109 109
110Optional nodes: 110Optional nodes:
111- Video port for HDMI output 111- Video port for HDMI output
112
113HDMI Endpoint optional properties:
114- lanes: list of 8 pin numbers for the HDMI lanes: CLK+, CLK-, D0+, D0-,
115 D1+, D1-, D2+, D2-. (default: 0,1,2,3,4,5,6,7)
diff --git a/Documentation/devicetree/bindings/video/ti,omap5-dss.txt b/Documentation/devicetree/bindings/video/ti,omap5-dss.txt
new file mode 100644
index 000000000000..38ffc8fcd816
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/ti,omap5-dss.txt
@@ -0,0 +1,96 @@
1Texas Instruments OMAP5 Display Subsystem
2=========================================
3
4See Documentation/devicetree/bindings/video/ti,omap-dss.txt for generic
5description about OMAP Display Subsystem bindings.
6
7DSS Core
8--------
9
10Required properties:
11- compatible: "ti,omap5-dss"
12- reg: address and length of the register space
13- ti,hwmods: "dss_core"
14- clocks: handle to fclk
15- clock-names: "fck"
16
17Required nodes:
18- DISPC
19
20Optional nodes:
21- DSS Submodules: RFBI, DSI, HDMI
22- Video port for DPI output
23
24DPI Endpoint required properties:
25- data-lines: number of lines used
26
27
28DISPC
29-----
30
31Required properties:
32- compatible: "ti,omap5-dispc"
33- reg: address and length of the register space
34- ti,hwmods: "dss_dispc"
35- interrupts: the DISPC interrupt
36- clocks: handle to fclk
37- clock-names: "fck"
38
39
40RFBI
41----
42
43Required properties:
44- compatible: "ti,omap5-rfbi"
45- reg: address and length of the register space
46- ti,hwmods: "dss_rfbi"
47- clocks: handles to fclk and iclk
48- clock-names: "fck", "ick"
49
50Optional nodes:
51- Video port for RFBI output
52- RFBI controlled peripherals
53
54
55DSI
56---
57
58Required properties:
59- compatible: "ti,omap5-dsi"
60- reg: addresses and lengths of the register spaces for 'proto', 'phy' and 'pll'
61- reg-names: "proto", "phy", "pll"
62- interrupts: the DSI interrupt line
63- ti,hwmods: "dss_dsi1" or "dss_dsi2"
64- vdd-supply: power supply for DSI
65- clocks: handles to fclk and pll clock
66- clock-names: "fck", "sys_clk"
67
68Optional nodes:
69- Video port for DSI output
70- DSI controlled peripherals
71
72DSI Endpoint required properties:
73- lanes: list of pin numbers for the DSI lanes: CLK+, CLK-, DATA0+, DATA0-,
74 DATA1+, DATA1-, ...
75
76
77HDMI
78----
79
80Required properties:
81- compatible: "ti,omap5-hdmi"
82- reg: addresses and lengths of the register spaces for 'wp', 'pll', 'phy',
83 'core'
84- reg-names: "wp", "pll", "phy", "core"
85- interrupts: the HDMI interrupt line
86- ti,hwmods: "dss_hdmi"
87- vdda-supply: vdda power supply
88- clocks: handles to fclk and pll clock
89- clock-names: "fck", "sys_clk"
90
91Optional nodes:
92- Video port for HDMI output
93
94HDMI Endpoint optional properties:
95- lanes: list of 8 pin numbers for the HDMI lanes: CLK+, CLK-, D0+, D0-,
96 D1+, D1-, D2+, D2-. (default: 0,1,2,3,4,5,6,7)
diff --git a/Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt b/Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt
new file mode 100644
index 000000000000..7175dc3740ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/toppoly,td028ttec1.txt
@@ -0,0 +1,30 @@
1Toppoly TD028TTEC1 Panel
2========================
3
4Required properties:
5- compatible: "toppoly,td028ttec1"
6
7Optional properties:
8- label: a symbolic name for the panel
9
10Required nodes:
11- Video port for DPI input
12
13Example
14-------
15
16lcd-panel: td028ttec1@0 {
17 compatible = "toppoly,td028ttec1";
18 reg = <0>;
19 spi-max-frequency = <100000>;
20 spi-cpol;
21 spi-cpha;
22
23 label = "lcd";
24 port {
25 lcd_in: endpoint {
26 remote-endpoint = <&dpi_out>;
27 };
28 };
29};
30
diff --git a/Documentation/devicetree/bindings/video/tpo,td043mtea1.txt b/Documentation/devicetree/bindings/video/tpo,td043mtea1.txt
new file mode 100644
index 000000000000..ec6d62975162
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/tpo,td043mtea1.txt
@@ -0,0 +1,33 @@
1TPO TD043MTEA1 Panel
2====================
3
4Required properties:
5- compatible: "tpo,td043mtea1"
6- reset-gpios: panel reset gpio
7
8Optional properties:
9- label: a symbolic name for the panel
10
11Required nodes:
12- Video port for DPI input
13
14Example
15-------
16
17lcd-panel: panel@0 {
18 compatible = "tpo,td043mtea1";
19 reg = <0>;
20 spi-max-frequency = <100000>;
21 spi-cpol;
22 spi-cpha;
23
24 label = "lcd";
25
26 reset-gpios = <&gpio7 7 0>;
27
28 port {
29 lcd_in: endpoint {
30 remote-endpoint = <&dpi_out>;
31 };
32 };
33};
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index 16d33d831287..bf852d7ae951 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -279,6 +279,8 @@ static enum omapdss_version __init omap_display_get_version(void)
279 return OMAPDSS_VER_OMAP4; 279 return OMAPDSS_VER_OMAP4;
280 else if (soc_is_omap54xx()) 280 else if (soc_is_omap54xx())
281 return OMAPDSS_VER_OMAP5; 281 return OMAPDSS_VER_OMAP5;
282 else if (soc_is_am43xx())
283 return OMAPDSS_VER_AM43xx;
282 else 284 else
283 return OMAPDSS_VER_UNKNOWN; 285 return OMAPDSS_VER_UNKNOWN;
284} 286}
@@ -555,65 +557,9 @@ int omap_dss_reset(struct omap_hwmod *oh)
555 return r; 557 return r;
556} 558}
557 559
558/* list of 'compatible' nodes to convert to omapdss specific */
559static const char * const dss_compat_conv_list[] __initconst = {
560 "composite-connector",
561 "dvi-connector",
562 "hdmi-connector",
563 "panel-dpi",
564 "panel-dsi-cm",
565 "sony,acx565akm",
566 "svideo-connector",
567 "ti,tfp410",
568 "ti,tpd12s015",
569};
570
571/* prepend compatible string with "omapdss," */
572static __init void omapdss_omapify_node(struct device_node *node,
573 const char *compat)
574{
575 char *new_compat;
576 struct property *prop;
577
578 new_compat = kasprintf(GFP_KERNEL, "omapdss,%s", compat);
579
580 prop = kzalloc(sizeof(*prop), GFP_KERNEL);
581
582 if (!prop) {
583 pr_err("omapdss_omapify_node: kzalloc failed\n");
584 return;
585 }
586
587 prop->name = "compatible";
588 prop->value = new_compat;
589 prop->length = strlen(new_compat) + 1;
590
591 of_update_property(node, prop);
592}
593
594/*
595 * As omapdss panel drivers are omapdss specific, but we want to define the
596 * DT-data in generic manner, we convert the compatible strings of the panel
597 * nodes from "panel-foo" to "omapdss,panel-foo". This way we can have both
598 * correct DT data and omapdss specific drivers.
599 *
600 * When we get generic panel drivers to the kernel, this will be removed.
601 */
602void __init omapdss_early_init_of(void) 560void __init omapdss_early_init_of(void)
603{ 561{
604 int i;
605
606 for (i = 0; i < ARRAY_SIZE(dss_compat_conv_list); ++i) {
607 const char *compat = dss_compat_conv_list[i];
608 struct device_node *node = NULL;
609
610 while ((node = of_find_compatible_node(node, NULL, compat))) {
611 if (!of_device_is_available(node))
612 continue;
613 562
614 omapdss_omapify_node(node, compat);
615 }
616 }
617} 563}
618 564
619struct device_node * __init omapdss_find_dss_of_node(void) 565struct device_node * __init omapdss_find_dss_of_node(void)
@@ -632,6 +578,10 @@ struct device_node * __init omapdss_find_dss_of_node(void)
632 if (node) 578 if (node)
633 return node; 579 return node;
634 580
581 node = of_find_compatible_node(NULL, NULL, "ti,omap5-dss");
582 if (node)
583 return node;
584
635 return NULL; 585 return NULL;
636} 586}
637 587
diff --git a/drivers/video/fbdev/omap2/Makefile b/drivers/video/fbdev/omap2/Makefile
index bf8127df8c71..f8745ec369cc 100644
--- a/drivers/video/fbdev/omap2/Makefile
+++ b/drivers/video/fbdev/omap2/Makefile
@@ -1,5 +1,5 @@
1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o 1obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
2 2
3obj-$(CONFIG_OMAP2_DSS) += dss/ 3obj-y += dss/
4obj-y += displays-new/ 4obj-y += displays-new/
5obj-$(CONFIG_FB_OMAP2) += omapfb/ 5obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
index 29ed21b9dce5..4420ccb69aa9 100644
--- a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
+++ b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
@@ -13,6 +13,7 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_gpio.h>
16 17
17#include <drm/drm_edid.h> 18#include <drm/drm_edid.h>
18 19
@@ -43,6 +44,8 @@ struct panel_drv_data {
43 struct device *dev; 44 struct device *dev;
44 45
45 struct omap_video_timings timings; 46 struct omap_video_timings timings;
47
48 int hpd_gpio;
46}; 49};
47 50
48#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) 51#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -161,7 +164,10 @@ static bool hdmic_detect(struct omap_dss_device *dssdev)
161 struct panel_drv_data *ddata = to_panel_data(dssdev); 164 struct panel_drv_data *ddata = to_panel_data(dssdev);
162 struct omap_dss_device *in = ddata->in; 165 struct omap_dss_device *in = ddata->in;
163 166
164 return in->ops.hdmi->detect(in); 167 if (gpio_is_valid(ddata->hpd_gpio))
168 return gpio_get_value_cansleep(ddata->hpd_gpio);
169 else
170 return in->ops.hdmi->detect(in);
165} 171}
166 172
167static int hdmic_audio_enable(struct omap_dss_device *dssdev) 173static int hdmic_audio_enable(struct omap_dss_device *dssdev)
@@ -288,6 +294,8 @@ static int hdmic_probe_pdata(struct platform_device *pdev)
288 294
289 pdata = dev_get_platdata(&pdev->dev); 295 pdata = dev_get_platdata(&pdev->dev);
290 296
297 ddata->hpd_gpio = -ENODEV;
298
291 in = omap_dss_find_output(pdata->source); 299 in = omap_dss_find_output(pdata->source);
292 if (in == NULL) { 300 if (in == NULL) {
293 dev_err(&pdev->dev, "Failed to find video source\n"); 301 dev_err(&pdev->dev, "Failed to find video source\n");
@@ -307,6 +315,14 @@ static int hdmic_probe_of(struct platform_device *pdev)
307 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 315 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
308 struct device_node *node = pdev->dev.of_node; 316 struct device_node *node = pdev->dev.of_node;
309 struct omap_dss_device *in; 317 struct omap_dss_device *in;
318 int gpio;
319
320 /* HPD GPIO */
321 gpio = of_get_named_gpio(node, "hpd-gpios", 0);
322 if (gpio_is_valid(gpio))
323 ddata->hpd_gpio = gpio;
324 else
325 ddata->hpd_gpio = -ENODEV;
310 326
311 in = omapdss_of_find_source_for_first_ep(node); 327 in = omapdss_of_find_source_for_first_ep(node);
312 if (IS_ERR(in)) { 328 if (IS_ERR(in)) {
@@ -344,6 +360,13 @@ static int hdmic_probe(struct platform_device *pdev)
344 return -ENODEV; 360 return -ENODEV;
345 } 361 }
346 362
363 if (gpio_is_valid(ddata->hpd_gpio)) {
364 r = devm_gpio_request_one(&pdev->dev, ddata->hpd_gpio,
365 GPIOF_DIR_IN, "hdmi_hpd");
366 if (r)
367 goto err_reg;
368 }
369
347 ddata->timings = hdmic_default_timings; 370 ddata->timings = hdmic_default_timings;
348 371
349 dssdev = &ddata->dssdev; 372 dssdev = &ddata->dssdev;
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
index 5f8f7e7c81ef..3636b61dc9b4 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c
@@ -13,9 +13,12 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/of.h>
17#include <linux/of_gpio.h>
16 18
17#include <video/omapdss.h> 19#include <video/omapdss.h>
18#include <video/omap-panel-data.h> 20#include <video/omap-panel-data.h>
21#include <video/of_display_timing.h>
19 22
20struct panel_drv_data { 23struct panel_drv_data {
21 struct omap_dss_device dssdev; 24 struct omap_dss_device dssdev;
@@ -25,8 +28,10 @@ struct panel_drv_data {
25 28
26 struct omap_video_timings videomode; 29 struct omap_video_timings videomode;
27 30
31 /* used for non-DT boot, to be removed */
28 int backlight_gpio; 32 int backlight_gpio;
29 int enable_gpio; 33
34 struct gpio_desc *enable_gpio;
30}; 35};
31 36
32#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) 37#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -70,15 +75,16 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev)
70 if (omapdss_device_is_enabled(dssdev)) 75 if (omapdss_device_is_enabled(dssdev))
71 return 0; 76 return 0;
72 77
73 in->ops.dpi->set_data_lines(in, ddata->data_lines); 78 if (ddata->data_lines)
79 in->ops.dpi->set_data_lines(in, ddata->data_lines);
74 in->ops.dpi->set_timings(in, &ddata->videomode); 80 in->ops.dpi->set_timings(in, &ddata->videomode);
75 81
76 r = in->ops.dpi->enable(in); 82 r = in->ops.dpi->enable(in);
77 if (r) 83 if (r)
78 return r; 84 return r;
79 85
80 if (gpio_is_valid(ddata->enable_gpio)) 86 if (ddata->enable_gpio)
81 gpio_set_value_cansleep(ddata->enable_gpio, 1); 87 gpiod_set_value_cansleep(ddata->enable_gpio, 1);
82 88
83 if (gpio_is_valid(ddata->backlight_gpio)) 89 if (gpio_is_valid(ddata->backlight_gpio))
84 gpio_set_value_cansleep(ddata->backlight_gpio, 1); 90 gpio_set_value_cansleep(ddata->backlight_gpio, 1);
@@ -96,8 +102,8 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev)
96 if (!omapdss_device_is_enabled(dssdev)) 102 if (!omapdss_device_is_enabled(dssdev))
97 return; 103 return;
98 104
99 if (gpio_is_valid(ddata->enable_gpio)) 105 if (ddata->enable_gpio)
100 gpio_set_value_cansleep(ddata->enable_gpio, 0); 106 gpiod_set_value_cansleep(ddata->enable_gpio, 0);
101 107
102 if (gpio_is_valid(ddata->backlight_gpio)) 108 if (gpio_is_valid(ddata->backlight_gpio))
103 gpio_set_value_cansleep(ddata->backlight_gpio, 0); 109 gpio_set_value_cansleep(ddata->backlight_gpio, 0);
@@ -156,6 +162,7 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev)
156 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 162 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
157 struct omap_dss_device *dssdev, *in; 163 struct omap_dss_device *dssdev, *in;
158 struct videomode vm; 164 struct videomode vm;
165 int r;
159 166
160 pdata = dev_get_platdata(&pdev->dev); 167 pdata = dev_get_platdata(&pdev->dev);
161 168
@@ -176,10 +183,65 @@ static int panel_dpi_probe_pdata(struct platform_device *pdev)
176 dssdev = &ddata->dssdev; 183 dssdev = &ddata->dssdev;
177 dssdev->name = pdata->name; 184 dssdev->name = pdata->name;
178 185
179 ddata->enable_gpio = pdata->enable_gpio; 186 r = devm_gpio_request_one(&pdev->dev, pdata->enable_gpio,
187 GPIOF_OUT_INIT_LOW, "panel enable");
188 if (r)
189 goto err_gpio;
190
191 ddata->enable_gpio = gpio_to_desc(pdata->enable_gpio);
192
180 ddata->backlight_gpio = pdata->backlight_gpio; 193 ddata->backlight_gpio = pdata->backlight_gpio;
181 194
182 return 0; 195 return 0;
196
197err_gpio:
198 omap_dss_put_device(ddata->in);
199 return r;
200}
201
202static int panel_dpi_probe_of(struct platform_device *pdev)
203{
204 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
205 struct device_node *node = pdev->dev.of_node;
206 struct omap_dss_device *in;
207 int r;
208 struct display_timing timing;
209 struct videomode vm;
210 struct gpio_desc *gpio;
211
212 gpio = devm_gpiod_get(&pdev->dev, "enable");
213
214 if (IS_ERR(gpio)) {
215 if (PTR_ERR(gpio) != -ENOENT)
216 return PTR_ERR(gpio);
217 else
218 gpio = NULL;
219 } else {
220 gpiod_direction_output(gpio, 0);
221 }
222
223 ddata->enable_gpio = gpio;
224
225 ddata->backlight_gpio = -ENOENT;
226
227 r = of_get_display_timing(node, "panel-timing", &timing);
228 if (r) {
229 dev_err(&pdev->dev, "failed to get video timing\n");
230 return r;
231 }
232
233 videomode_from_timing(&timing, &vm);
234 videomode_to_omap_video_timings(&vm, &ddata->videomode);
235
236 in = omapdss_of_find_source_for_first_ep(node);
237 if (IS_ERR(in)) {
238 dev_err(&pdev->dev, "failed to find video source\n");
239 return PTR_ERR(in);
240 }
241
242 ddata->in = in;
243
244 return 0;
183} 245}
184 246
185static int panel_dpi_probe(struct platform_device *pdev) 247static int panel_dpi_probe(struct platform_device *pdev)
@@ -198,17 +260,14 @@ static int panel_dpi_probe(struct platform_device *pdev)
198 r = panel_dpi_probe_pdata(pdev); 260 r = panel_dpi_probe_pdata(pdev);
199 if (r) 261 if (r)
200 return r; 262 return r;
263 } else if (pdev->dev.of_node) {
264 r = panel_dpi_probe_of(pdev);
265 if (r)
266 return r;
201 } else { 267 } else {
202 return -ENODEV; 268 return -ENODEV;
203 } 269 }
204 270
205 if (gpio_is_valid(ddata->enable_gpio)) {
206 r = devm_gpio_request_one(&pdev->dev, ddata->enable_gpio,
207 GPIOF_OUT_INIT_LOW, "panel enable");
208 if (r)
209 goto err_gpio;
210 }
211
212 if (gpio_is_valid(ddata->backlight_gpio)) { 271 if (gpio_is_valid(ddata->backlight_gpio)) {
213 r = devm_gpio_request_one(&pdev->dev, ddata->backlight_gpio, 272 r = devm_gpio_request_one(&pdev->dev, ddata->backlight_gpio,
214 GPIOF_OUT_INIT_LOW, "panel backlight"); 273 GPIOF_OUT_INIT_LOW, "panel backlight");
@@ -254,12 +313,20 @@ static int __exit panel_dpi_remove(struct platform_device *pdev)
254 return 0; 313 return 0;
255} 314}
256 315
316static const struct of_device_id panel_dpi_of_match[] = {
317 { .compatible = "omapdss,panel-dpi", },
318 {},
319};
320
321MODULE_DEVICE_TABLE(of, panel_dpi_of_match);
322
257static struct platform_driver panel_dpi_driver = { 323static struct platform_driver panel_dpi_driver = {
258 .probe = panel_dpi_probe, 324 .probe = panel_dpi_probe,
259 .remove = __exit_p(panel_dpi_remove), 325 .remove = __exit_p(panel_dpi_remove),
260 .driver = { 326 .driver = {
261 .name = "panel-dpi", 327 .name = "panel-dpi",
262 .owner = THIS_MODULE, 328 .owner = THIS_MODULE,
329 .of_match_table = panel_dpi_of_match,
263 }, 330 },
264}; 331};
265 332
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
index 2e6b513222d9..cc5b5124e0b4 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c
@@ -50,9 +50,10 @@ struct panel_drv_data {
50 50
51 struct omap_video_timings videomode; 51 struct omap_video_timings videomode;
52 52
53 int reset_gpio; 53 /* used for non-DT boot, to be removed */
54 int backlight_gpio; 54 int backlight_gpio;
55 int enable_gpio; 55
56 struct gpio_desc *enable_gpio;
56}; 57};
57 58
58#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev) 59#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -158,15 +159,16 @@ static int lb035q02_enable(struct omap_dss_device *dssdev)
158 if (omapdss_device_is_enabled(dssdev)) 159 if (omapdss_device_is_enabled(dssdev))
159 return 0; 160 return 0;
160 161
161 in->ops.dpi->set_data_lines(in, ddata->data_lines); 162 if (ddata->data_lines)
163 in->ops.dpi->set_data_lines(in, ddata->data_lines);
162 in->ops.dpi->set_timings(in, &ddata->videomode); 164 in->ops.dpi->set_timings(in, &ddata->videomode);
163 165
164 r = in->ops.dpi->enable(in); 166 r = in->ops.dpi->enable(in);
165 if (r) 167 if (r)
166 return r; 168 return r;
167 169
168 if (gpio_is_valid(ddata->enable_gpio)) 170 if (ddata->enable_gpio)
169 gpio_set_value_cansleep(ddata->enable_gpio, 1); 171 gpiod_set_value_cansleep(ddata->enable_gpio, 1);
170 172
171 if (gpio_is_valid(ddata->backlight_gpio)) 173 if (gpio_is_valid(ddata->backlight_gpio))
172 gpio_set_value_cansleep(ddata->backlight_gpio, 1); 174 gpio_set_value_cansleep(ddata->backlight_gpio, 1);
@@ -184,8 +186,8 @@ static void lb035q02_disable(struct omap_dss_device *dssdev)
184 if (!omapdss_device_is_enabled(dssdev)) 186 if (!omapdss_device_is_enabled(dssdev))
185 return; 187 return;
186 188
187 if (gpio_is_valid(ddata->enable_gpio)) 189 if (ddata->enable_gpio)
188 gpio_set_value_cansleep(ddata->enable_gpio, 0); 190 gpiod_set_value_cansleep(ddata->enable_gpio, 0);
189 191
190 if (gpio_is_valid(ddata->backlight_gpio)) 192 if (gpio_is_valid(ddata->backlight_gpio))
191 gpio_set_value_cansleep(ddata->backlight_gpio, 0); 193 gpio_set_value_cansleep(ddata->backlight_gpio, 0);
@@ -243,6 +245,7 @@ static int lb035q02_probe_pdata(struct spi_device *spi)
243 const struct panel_lb035q02_platform_data *pdata; 245 const struct panel_lb035q02_platform_data *pdata;
244 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); 246 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
245 struct omap_dss_device *dssdev, *in; 247 struct omap_dss_device *dssdev, *in;
248 int r;
246 249
247 pdata = dev_get_platdata(&spi->dev); 250 pdata = dev_get_platdata(&spi->dev);
248 251
@@ -260,10 +263,48 @@ static int lb035q02_probe_pdata(struct spi_device *spi)
260 dssdev = &ddata->dssdev; 263 dssdev = &ddata->dssdev;
261 dssdev->name = pdata->name; 264 dssdev->name = pdata->name;
262 265
263 ddata->enable_gpio = pdata->enable_gpio; 266 r = devm_gpio_request_one(&spi->dev, pdata->enable_gpio,
267 GPIOF_OUT_INIT_LOW, "panel enable");
268 if (r)
269 goto err_gpio;
270
271 ddata->enable_gpio = gpio_to_desc(pdata->enable_gpio);
272
264 ddata->backlight_gpio = pdata->backlight_gpio; 273 ddata->backlight_gpio = pdata->backlight_gpio;
265 274
266 return 0; 275 return 0;
276err_gpio:
277 omap_dss_put_device(ddata->in);
278 return r;
279}
280
281static int lb035q02_probe_of(struct spi_device *spi)
282{
283 struct device_node *node = spi->dev.of_node;
284 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
285 struct omap_dss_device *in;
286 struct gpio_desc *gpio;
287
288 gpio = devm_gpiod_get(&spi->dev, "enable");
289 if (IS_ERR(gpio)) {
290 dev_err(&spi->dev, "failed to parse enable gpio\n");
291 return PTR_ERR(gpio);
292 } else {
293 gpiod_direction_output(gpio, 0);
294 ddata->enable_gpio = gpio;
295 }
296
297 ddata->backlight_gpio = -ENOENT;
298
299 in = omapdss_of_find_source_for_first_ep(node);
300 if (IS_ERR(in)) {
301 dev_err(&spi->dev, "failed to find video source\n");
302 return PTR_ERR(in);
303 }
304
305 ddata->in = in;
306
307 return 0;
267} 308}
268 309
269static int lb035q02_panel_spi_probe(struct spi_device *spi) 310static int lb035q02_panel_spi_probe(struct spi_device *spi)
@@ -284,17 +325,14 @@ static int lb035q02_panel_spi_probe(struct spi_device *spi)
284 r = lb035q02_probe_pdata(spi); 325 r = lb035q02_probe_pdata(spi);
285 if (r) 326 if (r)
286 return r; 327 return r;
328 } else if (spi->dev.of_node) {
329 r = lb035q02_probe_of(spi);
330 if (r)
331 return r;
287 } else { 332 } else {
288 return -ENODEV; 333 return -ENODEV;
289 } 334 }
290 335
291 if (gpio_is_valid(ddata->enable_gpio)) {
292 r = devm_gpio_request_one(&spi->dev, ddata->enable_gpio,
293 GPIOF_OUT_INIT_LOW, "panel enable");
294 if (r)
295 goto err_gpio;
296 }
297
298 if (gpio_is_valid(ddata->backlight_gpio)) { 336 if (gpio_is_valid(ddata->backlight_gpio)) {
299 r = devm_gpio_request_one(&spi->dev, ddata->backlight_gpio, 337 r = devm_gpio_request_one(&spi->dev, ddata->backlight_gpio,
300 GPIOF_OUT_INIT_LOW, "panel backlight"); 338 GPIOF_OUT_INIT_LOW, "panel backlight");
@@ -342,17 +380,26 @@ static int lb035q02_panel_spi_remove(struct spi_device *spi)
342 return 0; 380 return 0;
343} 381}
344 382
383static const struct of_device_id lb035q02_of_match[] = {
384 { .compatible = "omapdss,lgphilips,lb035q02", },
385 {},
386};
387
388MODULE_DEVICE_TABLE(of, lb035q02_of_match);
389
345static struct spi_driver lb035q02_spi_driver = { 390static struct spi_driver lb035q02_spi_driver = {
346 .probe = lb035q02_panel_spi_probe, 391 .probe = lb035q02_panel_spi_probe,
347 .remove = lb035q02_panel_spi_remove, 392 .remove = lb035q02_panel_spi_remove,
348 .driver = { 393 .driver = {
349 .name = "panel_lgphilips_lb035q02", 394 .name = "panel_lgphilips_lb035q02",
350 .owner = THIS_MODULE, 395 .owner = THIS_MODULE,
396 .of_match_table = lb035q02_of_match,
351 }, 397 },
352}; 398};
353 399
354module_spi_driver(lb035q02_spi_driver); 400module_spi_driver(lb035q02_spi_driver);
355 401
402MODULE_ALIAS("spi:lgphilips,lb035q02");
356MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); 403MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
357MODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver"); 404MODULE_DESCRIPTION("LG.Philips LB035Q02 LCD Panel driver");
358MODULE_LICENSE("GPL"); 405MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
index 996fa004b48c..3595f111aa35 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c
@@ -16,6 +16,7 @@
16#include <linux/spi/spi.h> 16#include <linux/spi/spi.h>
17#include <linux/fb.h> 17#include <linux/fb.h>
18#include <linux/gpio.h> 18#include <linux/gpio.h>
19#include <linux/of_gpio.h>
19 20
20#include <video/omapdss.h> 21#include <video/omapdss.h>
21#include <video/omap-panel-data.h> 22#include <video/omap-panel-data.h>
@@ -156,7 +157,8 @@ static int nec_8048_enable(struct omap_dss_device *dssdev)
156 if (omapdss_device_is_enabled(dssdev)) 157 if (omapdss_device_is_enabled(dssdev))
157 return 0; 158 return 0;
158 159
159 in->ops.dpi->set_data_lines(in, ddata->data_lines); 160 if (ddata->data_lines)
161 in->ops.dpi->set_data_lines(in, ddata->data_lines);
160 in->ops.dpi->set_timings(in, &ddata->videomode); 162 in->ops.dpi->set_timings(in, &ddata->videomode);
161 163
162 r = in->ops.dpi->enable(in); 164 r = in->ops.dpi->enable(in);
@@ -258,6 +260,34 @@ static int nec_8048_probe_pdata(struct spi_device *spi)
258 return 0; 260 return 0;
259} 261}
260 262
263static int nec_8048_probe_of(struct spi_device *spi)
264{
265 struct device_node *node = spi->dev.of_node;
266 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
267 struct omap_dss_device *in;
268 int gpio;
269
270 gpio = of_get_named_gpio(node, "reset-gpios", 0);
271 if (!gpio_is_valid(gpio)) {
272 dev_err(&spi->dev, "failed to parse enable gpio\n");
273 return gpio;
274 }
275 ddata->res_gpio = gpio;
276
277 /* XXX the panel spec doesn't mention any QVGA pin?? */
278 ddata->qvga_gpio = -ENOENT;
279
280 in = omapdss_of_find_source_for_first_ep(node);
281 if (IS_ERR(in)) {
282 dev_err(&spi->dev, "failed to find video source\n");
283 return PTR_ERR(in);
284 }
285
286 ddata->in = in;
287
288 return 0;
289}
290
261static int nec_8048_probe(struct spi_device *spi) 291static int nec_8048_probe(struct spi_device *spi)
262{ 292{
263 struct panel_drv_data *ddata; 293 struct panel_drv_data *ddata;
@@ -289,6 +319,10 @@ static int nec_8048_probe(struct spi_device *spi)
289 r = nec_8048_probe_pdata(spi); 319 r = nec_8048_probe_pdata(spi);
290 if (r) 320 if (r)
291 return r; 321 return r;
322 } else if (spi->dev.of_node) {
323 r = nec_8048_probe_of(spi);
324 if (r)
325 return r;
292 } else { 326 } else {
293 return -ENODEV; 327 return -ENODEV;
294 } 328 }
@@ -377,11 +411,19 @@ static SIMPLE_DEV_PM_OPS(nec_8048_pm_ops, nec_8048_suspend,
377#define NEC_8048_PM_OPS NULL 411#define NEC_8048_PM_OPS NULL
378#endif 412#endif
379 413
414static const struct of_device_id nec_8048_of_match[] = {
415 { .compatible = "omapdss,nec,nl8048hl11", },
416 {},
417};
418
419MODULE_DEVICE_TABLE(of, nec_8048_of_match);
420
380static struct spi_driver nec_8048_driver = { 421static struct spi_driver nec_8048_driver = {
381 .driver = { 422 .driver = {
382 .name = "panel-nec-nl8048hl11", 423 .name = "panel-nec-nl8048hl11",
383 .owner = THIS_MODULE, 424 .owner = THIS_MODULE,
384 .pm = NEC_8048_PM_OPS, 425 .pm = NEC_8048_PM_OPS,
426 .of_match_table = nec_8048_of_match,
385 }, 427 },
386 .probe = nec_8048_probe, 428 .probe = nec_8048_probe,
387 .remove = nec_8048_remove, 429 .remove = nec_8048_remove,
@@ -389,6 +431,7 @@ static struct spi_driver nec_8048_driver = {
389 431
390module_spi_driver(nec_8048_driver); 432module_spi_driver(nec_8048_driver);
391 433
434MODULE_ALIAS("spi:nec,nl8048hl11");
392MODULE_AUTHOR("Erik Gilling <konkers@android.com>"); 435MODULE_AUTHOR("Erik Gilling <konkers@android.com>");
393MODULE_DESCRIPTION("NEC-NL8048HL11 Driver"); 436MODULE_DESCRIPTION("NEC-NL8048HL11 Driver");
394MODULE_LICENSE("GPL"); 437MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
index b2f710be565d..f1f72ce50a17 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c
@@ -12,25 +12,28 @@
12#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/gpio.h> 13#include <linux/gpio.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/of_gpio.h>
15#include <linux/platform_device.h> 17#include <linux/platform_device.h>
16#include <linux/slab.h> 18#include <linux/slab.h>
17 19#include <linux/regulator/consumer.h>
18#include <video/omapdss.h> 20#include <video/omapdss.h>
19#include <video/omap-panel-data.h> 21#include <video/omap-panel-data.h>
20 22
21struct panel_drv_data { 23struct panel_drv_data {
22 struct omap_dss_device dssdev; 24 struct omap_dss_device dssdev;
23 struct omap_dss_device *in; 25 struct omap_dss_device *in;
26 struct regulator *vcc;
24 27
25 int data_lines; 28 int data_lines;
26 29
27 struct omap_video_timings videomode; 30 struct omap_video_timings videomode;
28 31
29 int resb_gpio; 32 struct gpio_desc *resb_gpio; /* low = reset active min 20 us */
30 int ini_gpio; 33 struct gpio_desc *ini_gpio; /* high = power on */
31 int mo_gpio; 34 struct gpio_desc *mo_gpio; /* low = 480x640, high = 240x320 */
32 int lr_gpio; 35 struct gpio_desc *lr_gpio; /* high = conventional horizontal scanning */
33 int ud_gpio; 36 struct gpio_desc *ud_gpio; /* high = conventional vertical scanning */
34}; 37};
35 38
36static const struct omap_video_timings sharp_ls_timings = { 39static const struct omap_video_timings sharp_ls_timings = {
@@ -95,21 +98,30 @@ static int sharp_ls_enable(struct omap_dss_device *dssdev)
95 if (omapdss_device_is_enabled(dssdev)) 98 if (omapdss_device_is_enabled(dssdev))
96 return 0; 99 return 0;
97 100
98 in->ops.dpi->set_data_lines(in, ddata->data_lines); 101 if (ddata->data_lines)
102 in->ops.dpi->set_data_lines(in, ddata->data_lines);
99 in->ops.dpi->set_timings(in, &ddata->videomode); 103 in->ops.dpi->set_timings(in, &ddata->videomode);
100 104
105 if (ddata->vcc) {
106 r = regulator_enable(ddata->vcc);
107 if (r != 0)
108 return r;
109 }
110
101 r = in->ops.dpi->enable(in); 111 r = in->ops.dpi->enable(in);
102 if (r) 112 if (r) {
113 regulator_disable(ddata->vcc);
103 return r; 114 return r;
115 }
104 116
105 /* wait couple of vsyncs until enabling the LCD */ 117 /* wait couple of vsyncs until enabling the LCD */
106 msleep(50); 118 msleep(50);
107 119
108 if (gpio_is_valid(ddata->resb_gpio)) 120 if (ddata->resb_gpio)
109 gpio_set_value_cansleep(ddata->resb_gpio, 1); 121 gpiod_set_value_cansleep(ddata->resb_gpio, 1);
110 122
111 if (gpio_is_valid(ddata->ini_gpio)) 123 if (ddata->ini_gpio)
112 gpio_set_value_cansleep(ddata->ini_gpio, 1); 124 gpiod_set_value_cansleep(ddata->ini_gpio, 1);
113 125
114 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; 126 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
115 127
@@ -124,11 +136,11 @@ static void sharp_ls_disable(struct omap_dss_device *dssdev)
124 if (!omapdss_device_is_enabled(dssdev)) 136 if (!omapdss_device_is_enabled(dssdev))
125 return; 137 return;
126 138
127 if (gpio_is_valid(ddata->ini_gpio)) 139 if (ddata->ini_gpio)
128 gpio_set_value_cansleep(ddata->ini_gpio, 0); 140 gpiod_set_value_cansleep(ddata->ini_gpio, 0);
129 141
130 if (gpio_is_valid(ddata->resb_gpio)) 142 if (ddata->resb_gpio)
131 gpio_set_value_cansleep(ddata->resb_gpio, 0); 143 gpiod_set_value_cansleep(ddata->resb_gpio, 0);
132 144
133 /* wait at least 5 vsyncs after disabling the LCD */ 145 /* wait at least 5 vsyncs after disabling the LCD */
134 146
@@ -136,6 +148,9 @@ static void sharp_ls_disable(struct omap_dss_device *dssdev)
136 148
137 in->ops.dpi->disable(in); 149 in->ops.dpi->disable(in);
138 150
151 if (ddata->vcc)
152 regulator_disable(ddata->vcc);
153
139 dssdev->state = OMAP_DSS_DISPLAY_DISABLED; 154 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
140} 155}
141 156
@@ -182,11 +197,32 @@ static struct omap_dss_driver sharp_ls_ops = {
182 .get_resolution = omapdss_default_get_resolution, 197 .get_resolution = omapdss_default_get_resolution,
183}; 198};
184 199
200static int sharp_ls_get_gpio(struct device *dev, int gpio, unsigned long flags,
201 char *desc, struct gpio_desc **gpiod)
202{
203 struct gpio_desc *gd;
204 int r;
205
206 *gpiod = NULL;
207
208 r = devm_gpio_request_one(dev, gpio, flags, desc);
209 if (r)
210 return r == -ENOENT ? 0 : r;
211
212 gd = gpio_to_desc(gpio);
213 if (IS_ERR(gd))
214 return PTR_ERR(gd) == -ENOENT ? 0 : PTR_ERR(gd);
215
216 *gpiod = gd;
217 return 0;
218}
219
185static int sharp_ls_probe_pdata(struct platform_device *pdev) 220static int sharp_ls_probe_pdata(struct platform_device *pdev)
186{ 221{
187 const struct panel_sharp_ls037v7dw01_platform_data *pdata; 222 const struct panel_sharp_ls037v7dw01_platform_data *pdata;
188 struct panel_drv_data *ddata = platform_get_drvdata(pdev); 223 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
189 struct omap_dss_device *dssdev, *in; 224 struct omap_dss_device *dssdev, *in;
225 int r;
190 226
191 pdata = dev_get_platdata(&pdev->dev); 227 pdata = dev_get_platdata(&pdev->dev);
192 228
@@ -204,11 +240,95 @@ static int sharp_ls_probe_pdata(struct platform_device *pdev)
204 dssdev = &ddata->dssdev; 240 dssdev = &ddata->dssdev;
205 dssdev->name = pdata->name; 241 dssdev->name = pdata->name;
206 242
207 ddata->resb_gpio = pdata->resb_gpio; 243 r = sharp_ls_get_gpio(&pdev->dev, pdata->mo_gpio, GPIOF_OUT_INIT_LOW,
208 ddata->ini_gpio = pdata->ini_gpio; 244 "lcd MO", &ddata->mo_gpio);
209 ddata->mo_gpio = pdata->mo_gpio; 245 if (r)
210 ddata->lr_gpio = pdata->lr_gpio; 246 return r;
211 ddata->ud_gpio = pdata->ud_gpio; 247 r = sharp_ls_get_gpio(&pdev->dev, pdata->lr_gpio, GPIOF_OUT_INIT_HIGH,
248 "lcd LR", &ddata->lr_gpio);
249 if (r)
250 return r;
251 r = sharp_ls_get_gpio(&pdev->dev, pdata->ud_gpio, GPIOF_OUT_INIT_HIGH,
252 "lcd UD", &ddata->ud_gpio);
253 if (r)
254 return r;
255 r = sharp_ls_get_gpio(&pdev->dev, pdata->resb_gpio, GPIOF_OUT_INIT_LOW,
256 "lcd RESB", &ddata->resb_gpio);
257 if (r)
258 return r;
259 r = sharp_ls_get_gpio(&pdev->dev, pdata->ini_gpio, GPIOF_OUT_INIT_LOW,
260 "lcd INI", &ddata->ini_gpio);
261 if (r)
262 return r;
263
264 return 0;
265}
266
267static int sharp_ls_get_gpio_of(struct device *dev, int index, int val,
268 const char *desc, struct gpio_desc **gpiod)
269{
270 struct gpio_desc *gd;
271 int r;
272
273 *gpiod = NULL;
274
275 gd = devm_gpiod_get_index(dev, desc, index);
276 if (IS_ERR(gd))
277 return PTR_ERR(gd) == -ENOENT ? 0 : PTR_ERR(gd);
278
279 r = gpiod_direction_output(gd, val);
280 if (r)
281 return r;
282
283 *gpiod = gd;
284 return 0;
285}
286
287static int sharp_ls_probe_of(struct platform_device *pdev)
288{
289 struct panel_drv_data *ddata = platform_get_drvdata(pdev);
290 struct device_node *node = pdev->dev.of_node;
291 struct omap_dss_device *in;
292 int r;
293
294 ddata->vcc = devm_regulator_get(&pdev->dev, "envdd");
295 if (IS_ERR(ddata->vcc)) {
296 dev_err(&pdev->dev, "failed to get regulator\n");
297 return PTR_ERR(ddata->vcc);
298 }
299
300 /* lcd INI */
301 r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "enable", &ddata->ini_gpio);
302 if (r)
303 return r;
304
305 /* lcd RESB */
306 r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "reset", &ddata->resb_gpio);
307 if (r)
308 return r;
309
310 /* lcd MO */
311 r = sharp_ls_get_gpio_of(&pdev->dev, 0, 0, "mode", &ddata->mo_gpio);
312 if (r)
313 return r;
314
315 /* lcd LR */
316 r = sharp_ls_get_gpio_of(&pdev->dev, 1, 1, "mode", &ddata->lr_gpio);
317 if (r)
318 return r;
319
320 /* lcd UD */
321 r = sharp_ls_get_gpio_of(&pdev->dev, 2, 1, "mode", &ddata->ud_gpio);
322 if (r)
323 return r;
324
325 in = omapdss_of_find_source_for_first_ep(node);
326 if (IS_ERR(in)) {
327 dev_err(&pdev->dev, "failed to find video source\n");
328 return PTR_ERR(in);
329 }
330
331 ddata->in = in;
212 332
213 return 0; 333 return 0;
214} 334}
@@ -229,45 +349,14 @@ static int sharp_ls_probe(struct platform_device *pdev)
229 r = sharp_ls_probe_pdata(pdev); 349 r = sharp_ls_probe_pdata(pdev);
230 if (r) 350 if (r)
231 return r; 351 return r;
352 } else if (pdev->dev.of_node) {
353 r = sharp_ls_probe_of(pdev);
354 if (r)
355 return r;
232 } else { 356 } else {
233 return -ENODEV; 357 return -ENODEV;
234 } 358 }
235 359
236 if (gpio_is_valid(ddata->mo_gpio)) {
237 r = devm_gpio_request_one(&pdev->dev, ddata->mo_gpio,
238 GPIOF_OUT_INIT_LOW, "lcd MO");
239 if (r)
240 goto err_gpio;
241 }
242
243 if (gpio_is_valid(ddata->lr_gpio)) {
244 r = devm_gpio_request_one(&pdev->dev, ddata->lr_gpio,
245 GPIOF_OUT_INIT_HIGH, "lcd LR");
246 if (r)
247 goto err_gpio;
248 }
249
250 if (gpio_is_valid(ddata->ud_gpio)) {
251 r = devm_gpio_request_one(&pdev->dev, ddata->ud_gpio,
252 GPIOF_OUT_INIT_HIGH, "lcd UD");
253 if (r)
254 goto err_gpio;
255 }
256
257 if (gpio_is_valid(ddata->resb_gpio)) {
258 r = devm_gpio_request_one(&pdev->dev, ddata->resb_gpio,
259 GPIOF_OUT_INIT_LOW, "lcd RESB");
260 if (r)
261 goto err_gpio;
262 }
263
264 if (gpio_is_valid(ddata->ini_gpio)) {
265 r = devm_gpio_request_one(&pdev->dev, ddata->ini_gpio,
266 GPIOF_OUT_INIT_LOW, "lcd INI");
267 if (r)
268 goto err_gpio;
269 }
270
271 ddata->videomode = sharp_ls_timings; 360 ddata->videomode = sharp_ls_timings;
272 361
273 dssdev = &ddata->dssdev; 362 dssdev = &ddata->dssdev;
@@ -287,7 +376,6 @@ static int sharp_ls_probe(struct platform_device *pdev)
287 return 0; 376 return 0;
288 377
289err_reg: 378err_reg:
290err_gpio:
291 omap_dss_put_device(ddata->in); 379 omap_dss_put_device(ddata->in);
292 return r; 380 return r;
293} 381}
@@ -308,12 +396,20 @@ static int __exit sharp_ls_remove(struct platform_device *pdev)
308 return 0; 396 return 0;
309} 397}
310 398
399static const struct of_device_id sharp_ls_of_match[] = {
400 { .compatible = "omapdss,sharp,ls037v7dw01", },
401 {},
402};
403
404MODULE_DEVICE_TABLE(of, sharp_ls_of_match);
405
311static struct platform_driver sharp_ls_driver = { 406static struct platform_driver sharp_ls_driver = {
312 .probe = sharp_ls_probe, 407 .probe = sharp_ls_probe,
313 .remove = __exit_p(sharp_ls_remove), 408 .remove = __exit_p(sharp_ls_remove),
314 .driver = { 409 .driver = {
315 .name = "panel-sharp-ls037v7dw01", 410 .name = "panel-sharp-ls037v7dw01",
316 .owner = THIS_MODULE, 411 .owner = THIS_MODULE,
412 .of_match_table = sharp_ls_of_match,
317 }, 413 },
318}; 414};
319 415
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
index fae6adc005a7..728808bcceeb 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c
@@ -206,7 +206,8 @@ static int td028ttec1_panel_enable(struct omap_dss_device *dssdev)
206 if (omapdss_device_is_enabled(dssdev)) 206 if (omapdss_device_is_enabled(dssdev))
207 return 0; 207 return 0;
208 208
209 in->ops.dpi->set_data_lines(in, ddata->data_lines); 209 if (ddata->data_lines)
210 in->ops.dpi->set_data_lines(in, ddata->data_lines);
210 in->ops.dpi->set_timings(in, &ddata->videomode); 211 in->ops.dpi->set_timings(in, &ddata->videomode);
211 212
212 r = in->ops.dpi->enable(in); 213 r = in->ops.dpi->enable(in);
@@ -389,6 +390,23 @@ static int td028ttec1_panel_probe_pdata(struct spi_device *spi)
389 return 0; 390 return 0;
390} 391}
391 392
393static int td028ttec1_probe_of(struct spi_device *spi)
394{
395 struct device_node *node = spi->dev.of_node;
396 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
397 struct omap_dss_device *in;
398
399 in = omapdss_of_find_source_for_first_ep(node);
400 if (IS_ERR(in)) {
401 dev_err(&spi->dev, "failed to find video source\n");
402 return PTR_ERR(in);
403 }
404
405 ddata->in = in;
406
407 return 0;
408}
409
392static int td028ttec1_panel_probe(struct spi_device *spi) 410static int td028ttec1_panel_probe(struct spi_device *spi)
393{ 411{
394 struct panel_drv_data *ddata; 412 struct panel_drv_data *ddata;
@@ -418,6 +436,10 @@ static int td028ttec1_panel_probe(struct spi_device *spi)
418 r = td028ttec1_panel_probe_pdata(spi); 436 r = td028ttec1_panel_probe_pdata(spi);
419 if (r) 437 if (r)
420 return r; 438 return r;
439 } else if (spi->dev.of_node) {
440 r = td028ttec1_probe_of(spi);
441 if (r)
442 return r;
421 } else { 443 } else {
422 return -ENODEV; 444 return -ENODEV;
423 } 445 }
@@ -463,6 +485,13 @@ static int td028ttec1_panel_remove(struct spi_device *spi)
463 return 0; 485 return 0;
464} 486}
465 487
488static const struct of_device_id td028ttec1_of_match[] = {
489 { .compatible = "omapdss,toppoly,td028ttec1", },
490 {},
491};
492
493MODULE_DEVICE_TABLE(of, td028ttec1_of_match);
494
466static struct spi_driver td028ttec1_spi_driver = { 495static struct spi_driver td028ttec1_spi_driver = {
467 .probe = td028ttec1_panel_probe, 496 .probe = td028ttec1_panel_probe,
468 .remove = td028ttec1_panel_remove, 497 .remove = td028ttec1_panel_remove,
@@ -470,11 +499,13 @@ static struct spi_driver td028ttec1_spi_driver = {
470 .driver = { 499 .driver = {
471 .name = "panel-tpo-td028ttec1", 500 .name = "panel-tpo-td028ttec1",
472 .owner = THIS_MODULE, 501 .owner = THIS_MODULE,
502 .of_match_table = td028ttec1_of_match,
473 }, 503 },
474}; 504};
475 505
476module_spi_driver(td028ttec1_spi_driver); 506module_spi_driver(td028ttec1_spi_driver);
477 507
508MODULE_ALIAS("spi:toppoly,td028ttec1");
478MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>"); 509MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
479MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver"); 510MODULE_DESCRIPTION("Toppoly TD028TTEC1 panel driver");
480MODULE_LICENSE("GPL"); 511MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
index 875b40263b33..de78ab0caaa8 100644
--- a/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
+++ b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c
@@ -17,6 +17,7 @@
17#include <linux/gpio.h> 17#include <linux/gpio.h>
18#include <linux/err.h> 18#include <linux/err.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/of_gpio.h>
20 21
21#include <video/omapdss.h> 22#include <video/omapdss.h>
22#include <video/omap-panel-data.h> 23#include <video/omap-panel-data.h>
@@ -376,7 +377,8 @@ static int tpo_td043_enable(struct omap_dss_device *dssdev)
376 if (omapdss_device_is_enabled(dssdev)) 377 if (omapdss_device_is_enabled(dssdev))
377 return 0; 378 return 0;
378 379
379 in->ops.dpi->set_data_lines(in, ddata->data_lines); 380 if (ddata->data_lines)
381 in->ops.dpi->set_data_lines(in, ddata->data_lines);
380 in->ops.dpi->set_timings(in, &ddata->videomode); 382 in->ops.dpi->set_timings(in, &ddata->videomode);
381 383
382 r = in->ops.dpi->enable(in); 384 r = in->ops.dpi->enable(in);
@@ -489,6 +491,31 @@ static int tpo_td043_probe_pdata(struct spi_device *spi)
489 return 0; 491 return 0;
490} 492}
491 493
494static int tpo_td043_probe_of(struct spi_device *spi)
495{
496 struct device_node *node = spi->dev.of_node;
497 struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
498 struct omap_dss_device *in;
499 int gpio;
500
501 gpio = of_get_named_gpio(node, "reset-gpios", 0);
502 if (!gpio_is_valid(gpio)) {
503 dev_err(&spi->dev, "failed to parse enable gpio\n");
504 return gpio;
505 }
506 ddata->nreset_gpio = gpio;
507
508 in = omapdss_of_find_source_for_first_ep(node);
509 if (IS_ERR(in)) {
510 dev_err(&spi->dev, "failed to find video source\n");
511 return PTR_ERR(in);
512 }
513
514 ddata->in = in;
515
516 return 0;
517}
518
492static int tpo_td043_probe(struct spi_device *spi) 519static int tpo_td043_probe(struct spi_device *spi)
493{ 520{
494 struct panel_drv_data *ddata; 521 struct panel_drv_data *ddata;
@@ -518,6 +545,10 @@ static int tpo_td043_probe(struct spi_device *spi)
518 r = tpo_td043_probe_pdata(spi); 545 r = tpo_td043_probe_pdata(spi);
519 if (r) 546 if (r)
520 return r; 547 return r;
548 } else if (spi->dev.of_node) {
549 r = tpo_td043_probe_of(spi);
550 if (r)
551 return r;
521 } else { 552 } else {
522 return -ENODEV; 553 return -ENODEV;
523 } 554 }
@@ -629,11 +660,19 @@ static int tpo_td043_spi_resume(struct device *dev)
629static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm, 660static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
630 tpo_td043_spi_suspend, tpo_td043_spi_resume); 661 tpo_td043_spi_suspend, tpo_td043_spi_resume);
631 662
663static const struct of_device_id tpo_td043_of_match[] = {
664 { .compatible = "omapdss,tpo,td043mtea1", },
665 {},
666};
667
668MODULE_DEVICE_TABLE(of, tpo_td043_of_match);
669
632static struct spi_driver tpo_td043_spi_driver = { 670static struct spi_driver tpo_td043_spi_driver = {
633 .driver = { 671 .driver = {
634 .name = "panel-tpo-td043mtea1", 672 .name = "panel-tpo-td043mtea1",
635 .owner = THIS_MODULE, 673 .owner = THIS_MODULE,
636 .pm = &tpo_td043_spi_pm, 674 .pm = &tpo_td043_spi_pm,
675 .of_match_table = tpo_td043_of_match,
637 }, 676 },
638 .probe = tpo_td043_probe, 677 .probe = tpo_td043_probe,
639 .remove = tpo_td043_remove, 678 .remove = tpo_td043_remove,
@@ -641,6 +680,7 @@ static struct spi_driver tpo_td043_spi_driver = {
641 680
642module_spi_driver(tpo_td043_spi_driver); 681module_spi_driver(tpo_td043_spi_driver);
643 682
683MODULE_ALIAS("spi:tpo,td043mtea1");
644MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>"); 684MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
645MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver"); 685MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
646MODULE_LICENSE("GPL"); 686MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/dss/Kconfig
index dde4281663b1..285bcd103dce 100644
--- a/drivers/video/fbdev/omap2/dss/Kconfig
+++ b/drivers/video/fbdev/omap2/dss/Kconfig
@@ -1,6 +1,10 @@
1config OMAP2_DSS_INIT
2 bool
3
1menuconfig OMAP2_DSS 4menuconfig OMAP2_DSS
2 tristate "OMAP2+ Display Subsystem support" 5 tristate "OMAP2+ Display Subsystem support"
3 select VIDEOMODE_HELPERS 6 select VIDEOMODE_HELPERS
7 select OMAP2_DSS_INIT
4 help 8 help
5 OMAP2+ Display Subsystem support. 9 OMAP2+ Display Subsystem support.
6 10
@@ -59,16 +63,32 @@ config OMAP2_DSS_VENC
59 help 63 help
60 OMAP Video Encoder support for S-Video and composite TV-out. 64 OMAP Video Encoder support for S-Video and composite TV-out.
61 65
66config OMAP2_DSS_HDMI_COMMON
67 bool
68
62config OMAP4_DSS_HDMI 69config OMAP4_DSS_HDMI
63 bool "HDMI support" 70 bool "HDMI support for OMAP4"
64 default y 71 default y
72 select OMAP2_DSS_HDMI_COMMON
65 help 73 help
66 HDMI Interface. This adds the High Definition Multimedia Interface. 74 HDMI support for OMAP4 based SoCs.
67 See http://www.hdmi.org/ for HDMI specification.
68 75
69config OMAP4_DSS_HDMI_AUDIO 76config OMAP4_DSS_HDMI_AUDIO
70 bool 77 bool
71 78
79config OMAP5_DSS_HDMI
80 bool "HDMI support for OMAP5"
81 default n
82 select OMAP2_DSS_HDMI_COMMON
83 help
84 HDMI Interface for OMAP5 and similar cores. This adds the High
85 Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
86 specification.
87
88config OMAP5_DSS_HDMI_AUDIO
89 depends on OMAP5_DSS_HDMI
90 bool
91
72config OMAP2_DSS_SDI 92config OMAP2_DSS_SDI
73 bool "SDI support" 93 bool "SDI support"
74 default n 94 default n
diff --git a/drivers/video/fbdev/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile
index 8aec8bda27cc..245f933060ee 100644
--- a/drivers/video/fbdev/omap2/dss/Makefile
+++ b/drivers/video/fbdev/omap2/dss/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 2obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2# Core DSS files 3# Core DSS files
3omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 4omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
@@ -10,6 +11,8 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
10omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 11omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
11omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o 12omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
12omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o 13omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
13omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi_common.o hdmi_wp.o hdmi_pll.o \ 14omapdss-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \
14 hdmi_phy.o hdmi4_core.o 15 hdmi_phy.o
16omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o
17omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o
15ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG 18ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
diff --git a/drivers/video/fbdev/omap2/dss/core.c b/drivers/video/fbdev/omap2/dss/core.c
index ffa45c894cd4..6b74f73fb524 100644
--- a/drivers/video/fbdev/omap2/dss/core.c
+++ b/drivers/video/fbdev/omap2/dss/core.c
@@ -268,6 +268,9 @@ static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
268#ifdef CONFIG_OMAP4_DSS_HDMI 268#ifdef CONFIG_OMAP4_DSS_HDMI
269 hdmi4_init_platform_driver, 269 hdmi4_init_platform_driver,
270#endif 270#endif
271#ifdef CONFIG_OMAP5_DSS_HDMI
272 hdmi5_init_platform_driver,
273#endif
271}; 274};
272 275
273static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = { 276static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
@@ -289,6 +292,9 @@ static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
289#ifdef CONFIG_OMAP4_DSS_HDMI 292#ifdef CONFIG_OMAP4_DSS_HDMI
290 hdmi4_uninit_platform_driver, 293 hdmi4_uninit_platform_driver,
291#endif 294#endif
295#ifdef CONFIG_OMAP5_DSS_HDMI
296 hdmi5_uninit_platform_driver,
297#endif
292}; 298};
293 299
294static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)]; 300static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c
index f18397c33e8f..7aa33b0f4a1f 100644
--- a/drivers/video/fbdev/omap2/dss/dispc.c
+++ b/drivers/video/fbdev/omap2/dss/dispc.c
@@ -2577,9 +2577,9 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
2577 2577
2578 channel = dispc_ovl_get_channel_out(plane); 2578 channel = dispc_ovl_get_channel_out(plane);
2579 2579
2580 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " 2580 DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->"
2581 "%dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n", 2581 " %dx%d, cmode %x, rot %d, mir %d, chan %d repl %d\n",
2582 plane, oi->paddr, oi->p_uv_addr, oi->screen_width, oi->pos_x, 2582 plane, &oi->paddr, &oi->p_uv_addr, oi->screen_width, oi->pos_x,
2583 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height, 2583 oi->pos_y, oi->width, oi->height, oi->out_width, oi->out_height,
2584 oi->color_mode, oi->rotation, oi->mirror, channel, replication); 2584 oi->color_mode, oi->rotation, oi->mirror, channel, replication);
2585 2585
@@ -2945,13 +2945,13 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
2945 BUG(); 2945 BUG();
2946 } 2946 }
2947 2947
2948 l = dispc_read_reg(DISPC_POL_FREQ(channel)); 2948 l = FLD_VAL(onoff, 17, 17) |
2949 l |= FLD_VAL(onoff, 17, 17); 2949 FLD_VAL(rf, 16, 16) |
2950 l |= FLD_VAL(rf, 16, 16); 2950 FLD_VAL(de_level, 15, 15) |
2951 l |= FLD_VAL(de_level, 15, 15); 2951 FLD_VAL(ipc, 14, 14) |
2952 l |= FLD_VAL(ipc, 14, 14); 2952 FLD_VAL(hsync_level, 13, 13) |
2953 l |= FLD_VAL(hsync_level, 13, 13); 2953 FLD_VAL(vsync_level, 12, 12);
2954 l |= FLD_VAL(vsync_level, 12, 12); 2954
2955 dispc_write_reg(DISPC_POL_FREQ(channel), l); 2955 dispc_write_reg(DISPC_POL_FREQ(channel), l);
2956} 2956}
2957 2957
@@ -3656,6 +3656,7 @@ static int __init dispc_init_features(struct platform_device *pdev)
3656 case OMAPDSS_VER_OMAP34xx_ES3: 3656 case OMAPDSS_VER_OMAP34xx_ES3:
3657 case OMAPDSS_VER_OMAP3630: 3657 case OMAPDSS_VER_OMAP3630:
3658 case OMAPDSS_VER_AM35xx: 3658 case OMAPDSS_VER_AM35xx:
3659 case OMAPDSS_VER_AM43xx:
3659 src = &omap34xx_rev3_0_dispc_feats; 3660 src = &omap34xx_rev3_0_dispc_feats;
3660 break; 3661 break;
3661 3662
@@ -3829,6 +3830,7 @@ static const struct of_device_id dispc_of_match[] = {
3829 { .compatible = "ti,omap2-dispc", }, 3830 { .compatible = "ti,omap2-dispc", },
3830 { .compatible = "ti,omap3-dispc", }, 3831 { .compatible = "ti,omap3-dispc", },
3831 { .compatible = "ti,omap4-dispc", }, 3832 { .compatible = "ti,omap4-dispc", },
3833 { .compatible = "ti,omap5-dispc", },
3832 {}, 3834 {},
3833}; 3835};
3834 3836
diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index 157921db447a..9368972d6962 100644
--- a/drivers/video/fbdev/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -67,6 +67,7 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
67 case OMAPDSS_VER_OMAP34xx_ES3: 67 case OMAPDSS_VER_OMAP34xx_ES3:
68 case OMAPDSS_VER_OMAP3630: 68 case OMAPDSS_VER_OMAP3630:
69 case OMAPDSS_VER_AM35xx: 69 case OMAPDSS_VER_AM35xx:
70 case OMAPDSS_VER_AM43xx:
70 return NULL; 71 return NULL;
71 72
72 case OMAPDSS_VER_OMAP4430_ES1: 73 case OMAPDSS_VER_OMAP4430_ES1:
@@ -103,6 +104,8 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
103 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC; 104 return OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC;
104 case OMAP_DSS_CHANNEL_LCD2: 105 case OMAP_DSS_CHANNEL_LCD2:
105 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; 106 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
107 case OMAP_DSS_CHANNEL_LCD3:
108 return OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC;
106 default: 109 default:
107 /* this shouldn't happen */ 110 /* this shouldn't happen */
108 WARN_ON(1); 111 WARN_ON(1);
@@ -595,6 +598,7 @@ static enum omap_channel dpi_get_channel(void)
595 case OMAPDSS_VER_OMAP34xx_ES3: 598 case OMAPDSS_VER_OMAP34xx_ES3:
596 case OMAPDSS_VER_OMAP3630: 599 case OMAPDSS_VER_OMAP3630:
597 case OMAPDSS_VER_AM35xx: 600 case OMAPDSS_VER_AM35xx:
601 case OMAPDSS_VER_AM43xx:
598 return OMAP_DSS_CHANNEL_LCD; 602 return OMAP_DSS_CHANNEL_LCD;
599 603
600 case OMAPDSS_VER_OMAP4430_ES1: 604 case OMAPDSS_VER_OMAP4430_ES1:
diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c
index 8be9b04d8849..4755a34a5422 100644
--- a/drivers/video/fbdev/omap2/dss/dsi.c
+++ b/drivers/video/fbdev/omap2/dss/dsi.c
@@ -1161,6 +1161,7 @@ static int dsi_regulator_init(struct platform_device *dsidev)
1161{ 1161{
1162 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1162 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1163 struct regulator *vdds_dsi; 1163 struct regulator *vdds_dsi;
1164 int r;
1164 1165
1165 if (dsi->vdds_dsi_reg != NULL) 1166 if (dsi->vdds_dsi_reg != NULL)
1166 return 0; 1167 return 0;
@@ -1173,6 +1174,15 @@ static int dsi_regulator_init(struct platform_device *dsidev)
1173 return PTR_ERR(vdds_dsi); 1174 return PTR_ERR(vdds_dsi);
1174 } 1175 }
1175 1176
1177 if (regulator_can_change_voltage(vdds_dsi)) {
1178 r = regulator_set_voltage(vdds_dsi, 1800000, 1800000);
1179 if (r) {
1180 devm_regulator_put(vdds_dsi);
1181 DSSERR("can't set the DSI regulator voltage\n");
1182 return r;
1183 }
1184 }
1185
1176 dsi->vdds_dsi_reg = vdds_dsi; 1186 dsi->vdds_dsi_reg = vdds_dsi;
1177 1187
1178 return 0; 1188 return 0;
@@ -5122,6 +5132,7 @@ static enum omap_channel dsi_get_channel(int module_id)
5122{ 5132{
5123 switch (omapdss_get_version()) { 5133 switch (omapdss_get_version()) {
5124 case OMAPDSS_VER_OMAP24xx: 5134 case OMAPDSS_VER_OMAP24xx:
5135 case OMAPDSS_VER_AM43xx:
5125 DSSWARN("DSI not supported\n"); 5136 DSSWARN("DSI not supported\n");
5126 return OMAP_DSS_CHANNEL_LCD; 5137 return OMAP_DSS_CHANNEL_LCD;
5127 5138
@@ -5723,9 +5734,16 @@ static const struct dsi_module_id_data dsi_of_data_omap4[] = {
5723 { }, 5734 { },
5724}; 5735};
5725 5736
5737static const struct dsi_module_id_data dsi_of_data_omap5[] = {
5738 { .address = 0x58004000, .id = 0, },
5739 { .address = 0x58009000, .id = 1, },
5740 { },
5741};
5742
5726static const struct of_device_id dsi_of_match[] = { 5743static const struct of_device_id dsi_of_match[] = {
5727 { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, }, 5744 { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, },
5728 { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, }, 5745 { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, },
5746 { .compatible = "ti,omap5-dsi", .data = dsi_of_data_omap5, },
5729 {}, 5747 {},
5730}; 5748};
5731 5749
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index d55266c0e029..6daeb7ed44c6 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -728,6 +728,13 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
728 .dpi_select_source = &dss_dpi_select_source_omap5, 728 .dpi_select_source = &dss_dpi_select_source_omap5,
729}; 729};
730 730
731static const struct dss_features am43xx_dss_feats __initconst = {
732 .fck_div_max = 0,
733 .dss_fck_multiplier = 0,
734 .parent_clk_name = NULL,
735 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
736};
737
731static int __init dss_init_features(struct platform_device *pdev) 738static int __init dss_init_features(struct platform_device *pdev)
732{ 739{
733 const struct dss_features *src; 740 const struct dss_features *src;
@@ -764,6 +771,10 @@ static int __init dss_init_features(struct platform_device *pdev)
764 src = &omap54xx_dss_feats; 771 src = &omap54xx_dss_feats;
765 break; 772 break;
766 773
774 case OMAPDSS_VER_AM43xx:
775 src = &am43xx_dss_feats;
776 break;
777
767 default: 778 default:
768 return -ENODEV; 779 return -ENODEV;
769 } 780 }
@@ -784,12 +795,8 @@ static int __init dss_init_ports(struct platform_device *pdev)
784 return 0; 795 return 0;
785 796
786 port = omapdss_of_get_next_port(parent, NULL); 797 port = omapdss_of_get_next_port(parent, NULL);
787 if (!port) { 798 if (!port)
788#ifdef CONFIG_OMAP2_DSS_DPI
789 dpi_init_port(pdev, parent);
790#endif
791 return 0; 799 return 0;
792 }
793 800
794 do { 801 do {
795 u32 reg; 802 u32 reg;
@@ -813,7 +820,7 @@ static int __init dss_init_ports(struct platform_device *pdev)
813 return 0; 820 return 0;
814} 821}
815 822
816static void dss_uninit_ports(void) 823static void __exit dss_uninit_ports(void)
817{ 824{
818#ifdef CONFIG_OMAP2_DSS_DPI 825#ifdef CONFIG_OMAP2_DSS_DPI
819 dpi_uninit_port(); 826 dpi_uninit_port();
@@ -946,6 +953,7 @@ static const struct of_device_id dss_of_match[] = {
946 { .compatible = "ti,omap2-dss", }, 953 { .compatible = "ti,omap2-dss", },
947 { .compatible = "ti,omap3-dss", }, 954 { .compatible = "ti,omap3-dss", },
948 { .compatible = "ti,omap4-dss", }, 955 { .compatible = "ti,omap4-dss", },
956 { .compatible = "ti,omap5-dss", },
949 {}, 957 {},
950}; 958};
951 959
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
index 560078fcb198..8ff22c134c62 100644
--- a/drivers/video/fbdev/omap2/dss/dss.h
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -419,6 +419,9 @@ void venc_uninit_platform_driver(void) __exit;
419int hdmi4_init_platform_driver(void) __init; 419int hdmi4_init_platform_driver(void) __init;
420void hdmi4_uninit_platform_driver(void) __exit; 420void hdmi4_uninit_platform_driver(void) __exit;
421 421
422int hdmi5_init_platform_driver(void) __init;
423void hdmi5_uninit_platform_driver(void) __exit;
424
422/* RFBI */ 425/* RFBI */
423int rfbi_init_platform_driver(void) __init; 426int rfbi_init_platform_driver(void) __init;
424void rfbi_uninit_platform_driver(void) __exit; 427void rfbi_uninit_platform_driver(void) __exit;
diff --git a/drivers/video/fbdev/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c
index 7f8969191dc6..15088df7bd16 100644
--- a/drivers/video/fbdev/omap2/dss/dss_features.c
+++ b/drivers/video/fbdev/omap2/dss/dss_features.c
@@ -93,6 +93,17 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = {
93 [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, 93 [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 },
94}; 94};
95 95
96static const struct dss_reg_field am43xx_dss_reg_fields[] = {
97 [FEAT_REG_FIRHINC] = { 12, 0 },
98 [FEAT_REG_FIRVINC] = { 28, 16 },
99 [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 },
100 [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 },
101 [FEAT_REG_FIFOSIZE] = { 10, 0 },
102 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
103 [FEAT_REG_VERTICALACCU] = { 25, 16 },
104 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
105};
106
96static const struct dss_reg_field omap4_dss_reg_fields[] = { 107static const struct dss_reg_field omap4_dss_reg_fields[] = {
97 [FEAT_REG_FIRHINC] = { 12, 0 }, 108 [FEAT_REG_FIRHINC] = { 12, 0 },
98 [FEAT_REG_FIRVINC] = { 28, 16 }, 109 [FEAT_REG_FIRVINC] = { 28, 16 },
@@ -149,6 +160,11 @@ static const enum omap_display_type omap3630_dss_supported_displays[] = {
149 OMAP_DISPLAY_TYPE_VENC, 160 OMAP_DISPLAY_TYPE_VENC,
150}; 161};
151 162
163static const enum omap_display_type am43xx_dss_supported_displays[] = {
164 /* OMAP_DSS_CHANNEL_LCD */
165 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI,
166};
167
152static const enum omap_display_type omap4_dss_supported_displays[] = { 168static const enum omap_display_type omap4_dss_supported_displays[] = {
153 /* OMAP_DSS_CHANNEL_LCD */ 169 /* OMAP_DSS_CHANNEL_LCD */
154 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, 170 OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI,
@@ -200,6 +216,11 @@ static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
200 OMAP_DSS_OUTPUT_VENC, 216 OMAP_DSS_OUTPUT_VENC,
201}; 217};
202 218
219static const enum omap_dss_output_id am43xx_dss_supported_outputs[] = {
220 /* OMAP_DSS_CHANNEL_LCD */
221 OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI,
222};
223
203static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { 224static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
204 /* OMAP_DSS_CHANNEL_LCD */ 225 /* OMAP_DSS_CHANNEL_LCD */
205 OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1, 226 OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
@@ -444,6 +465,13 @@ static const struct dss_param_range omap3_dss_param_range[] = {
444 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 465 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
445}; 466};
446 467
468static const struct dss_param_range am43xx_dss_param_range[] = {
469 [FEAT_PARAM_DSS_FCK] = { 0, 200000000 },
470 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
471 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
472 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
473};
474
447static const struct dss_param_range omap4_dss_param_range[] = { 475static const struct dss_param_range omap4_dss_param_range[] = {
448 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, 476 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
449 [FEAT_PARAM_DSS_PCD] = { 1, 255 }, 477 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
@@ -520,6 +548,21 @@ static const enum dss_feat_id am35xx_dss_feat_list[] = {
520 FEAT_OMAP3_DSI_FIFO_BUG, 548 FEAT_OMAP3_DSI_FIFO_BUG,
521}; 549};
522 550
551static const enum dss_feat_id am43xx_dss_feat_list[] = {
552 FEAT_LCDENABLEPOL,
553 FEAT_LCDENABLESIGNAL,
554 FEAT_PCKFREEENABLE,
555 FEAT_FUNCGATED,
556 FEAT_LINEBUFFERSPLIT,
557 FEAT_ROWREPEATENABLE,
558 FEAT_RESIZECONF,
559 FEAT_CPR,
560 FEAT_PRELOAD,
561 FEAT_FIR_COEF_V,
562 FEAT_ALPHA_FIXED_ZORDER,
563 FEAT_FIFO_MERGE,
564};
565
523static const enum dss_feat_id omap3630_dss_feat_list[] = { 566static const enum dss_feat_id omap3630_dss_feat_list[] = {
524 FEAT_LCDENABLEPOL, 567 FEAT_LCDENABLEPOL,
525 FEAT_LCDENABLESIGNAL, 568 FEAT_LCDENABLESIGNAL,
@@ -595,6 +638,7 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
595 638
596static const enum dss_feat_id omap5_dss_feat_list[] = { 639static const enum dss_feat_id omap5_dss_feat_list[] = {
597 FEAT_MGR_LCD2, 640 FEAT_MGR_LCD2,
641 FEAT_MGR_LCD3,
598 FEAT_CORE_CLK_DIV, 642 FEAT_CORE_CLK_DIV,
599 FEAT_LCD_CLK_SRC, 643 FEAT_LCD_CLK_SRC,
600 FEAT_DSI_DCS_CMD_CONFIG_VC, 644 FEAT_DSI_DCS_CMD_CONFIG_VC,
@@ -682,6 +726,26 @@ static const struct omap_dss_features am35xx_dss_features = {
682 .burst_size_unit = 8, 726 .burst_size_unit = 8,
683}; 727};
684 728
729static const struct omap_dss_features am43xx_dss_features = {
730 .reg_fields = am43xx_dss_reg_fields,
731 .num_reg_fields = ARRAY_SIZE(am43xx_dss_reg_fields),
732
733 .features = am43xx_dss_feat_list,
734 .num_features = ARRAY_SIZE(am43xx_dss_feat_list),
735
736 .num_mgrs = 1,
737 .num_ovls = 3,
738 .supported_displays = am43xx_dss_supported_displays,
739 .supported_outputs = am43xx_dss_supported_outputs,
740 .supported_color_modes = omap3_dss_supported_color_modes,
741 .overlay_caps = omap3430_dss_overlay_caps,
742 .clksrc_names = omap2_dss_clk_source_names,
743 .dss_params = am43xx_dss_param_range,
744 .supported_rotation_types = OMAP_DSS_ROT_DMA,
745 .buffer_size_unit = 1,
746 .burst_size_unit = 8,
747};
748
685static const struct omap_dss_features omap3630_dss_features = { 749static const struct omap_dss_features omap3630_dss_features = {
686 .reg_fields = omap3_dss_reg_fields, 750 .reg_fields = omap3_dss_reg_fields,
687 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), 751 .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
@@ -777,7 +841,7 @@ static const struct omap_dss_features omap5_dss_features = {
777 .features = omap5_dss_feat_list, 841 .features = omap5_dss_feat_list,
778 .num_features = ARRAY_SIZE(omap5_dss_feat_list), 842 .num_features = ARRAY_SIZE(omap5_dss_feat_list),
779 843
780 .num_mgrs = 3, 844 .num_mgrs = 4,
781 .num_ovls = 4, 845 .num_ovls = 4,
782 .supported_displays = omap5_dss_supported_displays, 846 .supported_displays = omap5_dss_supported_displays,
783 .supported_outputs = omap5_dss_supported_outputs, 847 .supported_outputs = omap5_dss_supported_outputs,
@@ -928,6 +992,10 @@ void dss_features_init(enum omapdss_version version)
928 omap_current_dss_features = &am35xx_dss_features; 992 omap_current_dss_features = &am35xx_dss_features;
929 break; 993 break;
930 994
995 case OMAPDSS_VER_AM43xx:
996 omap_current_dss_features = &am43xx_dss_features;
997 break;
998
931 default: 999 default:
932 DSSWARN("Unsupported OMAP version"); 1000 DSSWARN("Unsupported OMAP version");
933 break; 1001 break;
diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h
index e25681ff5a70..fbee07816337 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi.h
@@ -80,6 +80,7 @@
80#define HDMI_TXPHY_DIGITAL_CTRL 0x4 80#define HDMI_TXPHY_DIGITAL_CTRL 0x4
81#define HDMI_TXPHY_POWER_CTRL 0x8 81#define HDMI_TXPHY_POWER_CTRL 0x8
82#define HDMI_TXPHY_PAD_CFG_CTRL 0xC 82#define HDMI_TXPHY_PAD_CFG_CTRL 0xC
83#define HDMI_TXPHY_BIST_CONTROL 0x1C
83 84
84enum hdmi_pll_pwr { 85enum hdmi_pll_pwr {
85 HDMI_PLLPWRCMD_ALLOFF = 0, 86 HDMI_PLLPWRCMD_ALLOFF = 0,
@@ -351,7 +352,8 @@ struct hdmi_pll_data {
351struct hdmi_phy_data { 352struct hdmi_phy_data {
352 void __iomem *base; 353 void __iomem *base;
353 354
354 int irq; 355 u8 lane_function[4];
356 u8 lane_polarity[4];
355}; 357};
356 358
357struct hdmi_core_data { 359struct hdmi_core_data {
@@ -360,13 +362,13 @@ struct hdmi_core_data {
360 struct hdmi_core_infoframe_avi avi_cfg; 362 struct hdmi_core_infoframe_avi avi_cfg;
361}; 363};
362 364
363static inline void hdmi_write_reg(void __iomem *base_addr, const u16 idx, 365static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx,
364 u32 val) 366 u32 val)
365{ 367{
366 __raw_writel(val, base_addr + idx); 368 __raw_writel(val, base_addr + idx);
367} 369}
368 370
369static inline u32 hdmi_read_reg(void __iomem *base_addr, const u16 idx) 371static inline u32 hdmi_read_reg(void __iomem *base_addr, const u32 idx)
370{ 372{
371 return __raw_readl(base_addr + idx); 373 return __raw_readl(base_addr + idx);
372} 374}
@@ -417,18 +419,19 @@ void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy);
417int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); 419int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll);
418 420
419/* HDMI PHY funcs */ 421/* HDMI PHY funcs */
420int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, 422int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg);
421 struct hdmi_config *cfg);
422void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp);
423void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); 423void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
424int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); 424int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
425int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
425 426
426/* HDMI common funcs */ 427/* HDMI common funcs */
427const struct hdmi_config *hdmi_default_timing(void); 428const struct hdmi_config *hdmi_default_timing(void);
428const struct hdmi_config *hdmi_get_timings(int mode, int code); 429const struct hdmi_config *hdmi_get_timings(int mode, int code);
429struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing); 430struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
431int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
432 struct hdmi_phy_data *phy);
430 433
431#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 434#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
432int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts); 435int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
433int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); 436int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
434int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable); 437int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c
index f5f7944a1fd1..626aad2bef46 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
@@ -81,8 +81,40 @@ static void hdmi_runtime_put(void)
81 WARN_ON(r < 0 && r != -ENOSYS); 81 WARN_ON(r < 0 && r != -ENOSYS);
82} 82}
83 83
84static irqreturn_t hdmi_irq_handler(int irq, void *data)
85{
86 struct hdmi_wp_data *wp = data;
87 u32 irqstatus;
88
89 irqstatus = hdmi_wp_get_irqstatus(wp);
90 hdmi_wp_set_irqstatus(wp, irqstatus);
91
92 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
93 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
94 /*
95 * If we get both connect and disconnect interrupts at the same
96 * time, turn off the PHY, clear interrupts, and restart, which
97 * raises connect interrupt if a cable is connected, or nothing
98 * if cable is not connected.
99 */
100 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
101
102 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
103 HDMI_IRQ_LINK_DISCONNECT);
104
105 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
106 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
107 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
108 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
109 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
110 }
111
112 return IRQ_HANDLED;
113}
114
84static int hdmi_init_regulator(void) 115static int hdmi_init_regulator(void)
85{ 116{
117 int r;
86 struct regulator *reg; 118 struct regulator *reg;
87 119
88 if (hdmi.vdda_hdmi_dac_reg != NULL) 120 if (hdmi.vdda_hdmi_dac_reg != NULL)
@@ -96,6 +128,15 @@ static int hdmi_init_regulator(void)
96 return PTR_ERR(reg); 128 return PTR_ERR(reg);
97 } 129 }
98 130
131 if (regulator_can_change_voltage(reg)) {
132 r = regulator_set_voltage(reg, 1800000, 1800000);
133 if (r) {
134 devm_regulator_put(reg);
135 DSSWARN("can't set the regulator voltage\n");
136 return r;
137 }
138 }
139
99 hdmi.vdda_hdmi_dac_reg = reg; 140 hdmi.vdda_hdmi_dac_reg = reg;
100 141
101 return 0; 142 return 0;
@@ -140,11 +181,16 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
140 struct omap_video_timings *p; 181 struct omap_video_timings *p;
141 struct omap_overlay_manager *mgr = hdmi.output.manager; 182 struct omap_overlay_manager *mgr = hdmi.output.manager;
142 unsigned long phy; 183 unsigned long phy;
184 struct hdmi_wp_data *wp = &hdmi.wp;
143 185
144 r = hdmi_power_on_core(dssdev); 186 r = hdmi_power_on_core(dssdev);
145 if (r) 187 if (r)
146 return r; 188 return r;
147 189
190 /* disable and clear irqs */
191 hdmi_wp_clear_irqenable(wp, 0xffffffff);
192 hdmi_wp_set_irqstatus(wp, 0xffffffff);
193
148 p = &hdmi.cfg.timings; 194 p = &hdmi.cfg.timings;
149 195
150 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); 196 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
@@ -161,12 +207,16 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
161 goto err_pll_enable; 207 goto err_pll_enable;
162 } 208 }
163 209
164 r = hdmi_phy_enable(&hdmi.phy, &hdmi.wp, &hdmi.cfg); 210 r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
165 if (r) { 211 if (r) {
166 DSSDBG("Failed to start PHY\n"); 212 DSSDBG("Failed to configure PHY\n");
167 goto err_phy_enable; 213 goto err_phy_cfg;
168 } 214 }
169 215
216 r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
217 if (r)
218 goto err_phy_pwr;
219
170 hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg); 220 hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
171 221
172 /* bypass TV gamma table */ 222 /* bypass TV gamma table */
@@ -183,13 +233,17 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
183 if (r) 233 if (r)
184 goto err_mgr_enable; 234 goto err_mgr_enable;
185 235
236 hdmi_wp_set_irqenable(wp,
237 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
238
186 return 0; 239 return 0;
187 240
188err_mgr_enable: 241err_mgr_enable:
189 hdmi_wp_video_stop(&hdmi.wp); 242 hdmi_wp_video_stop(&hdmi.wp);
190err_vid_enable: 243err_vid_enable:
191 hdmi_phy_disable(&hdmi.phy, &hdmi.wp); 244err_phy_cfg:
192err_phy_enable: 245 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
246err_phy_pwr:
193 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 247 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
194err_pll_enable: 248err_pll_enable:
195 hdmi_power_off_core(dssdev); 249 hdmi_power_off_core(dssdev);
@@ -200,10 +254,14 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
200{ 254{
201 struct omap_overlay_manager *mgr = hdmi.output.manager; 255 struct omap_overlay_manager *mgr = hdmi.output.manager;
202 256
257 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
258
203 dss_mgr_disable(mgr); 259 dss_mgr_disable(mgr);
204 260
205 hdmi_wp_video_stop(&hdmi.wp); 261 hdmi_wp_video_stop(&hdmi.wp);
206 hdmi_phy_disable(&hdmi.phy, &hdmi.wp); 262
263 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
264
207 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 265 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
208 266
209 hdmi_power_off_core(dssdev); 267 hdmi_power_off_core(dssdev);
@@ -600,15 +658,44 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev)
600 omapdss_unregister_output(out); 658 omapdss_unregister_output(out);
601} 659}
602 660
661static int hdmi_probe_of(struct platform_device *pdev)
662{
663 struct device_node *node = pdev->dev.of_node;
664 struct device_node *ep;
665 int r;
666
667 ep = omapdss_of_get_first_endpoint(node);
668 if (!ep)
669 return 0;
670
671 r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy);
672 if (r)
673 goto err;
674
675 of_node_put(ep);
676 return 0;
677
678err:
679 of_node_put(ep);
680 return r;
681}
682
603/* HDMI HW IP initialisation */ 683/* HDMI HW IP initialisation */
604static int omapdss_hdmihw_probe(struct platform_device *pdev) 684static int omapdss_hdmihw_probe(struct platform_device *pdev)
605{ 685{
606 int r; 686 int r;
687 int irq;
607 688
608 hdmi.pdev = pdev; 689 hdmi.pdev = pdev;
609 690
610 mutex_init(&hdmi.lock); 691 mutex_init(&hdmi.lock);
611 692
693 if (pdev->dev.of_node) {
694 r = hdmi_probe_of(pdev);
695 if (r)
696 return r;
697 }
698
612 r = hdmi_wp_init(pdev, &hdmi.wp); 699 r = hdmi_wp_init(pdev, &hdmi.wp);
613 if (r) 700 if (r)
614 return r; 701 return r;
@@ -631,6 +718,20 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
631 return r; 718 return r;
632 } 719 }
633 720
721 irq = platform_get_irq(pdev, 0);
722 if (irq < 0) {
723 DSSERR("platform_get_irq failed\n");
724 return -ENODEV;
725 }
726
727 r = devm_request_threaded_irq(&pdev->dev, irq,
728 NULL, hdmi_irq_handler,
729 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
730 if (r) {
731 DSSERR("HDMI IRQ request failed\n");
732 return r;
733 }
734
634 pm_runtime_enable(&pdev->dev); 735 pm_runtime_enable(&pdev->dev);
635 736
636 hdmi_init_output(pdev); 737 hdmi_init_output(pdev);
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
index 2eb04dcf807c..8bde7b7e95ff 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4_core.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
@@ -998,38 +998,20 @@ int hdmi4_audio_get_dma_port(u32 *offset, u32 *size)
998 998
999#endif 999#endif
1000 1000
1001#define CORE_OFFSET 0x400
1002#define CORE_SIZE 0xc00
1003
1004int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) 1001int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
1005{ 1002{
1006 struct resource *res; 1003 struct resource *res;
1007 struct resource temp_res;
1008 1004
1009 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core"); 1005 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
1010 if (!res) { 1006 if (!res) {
1011 DSSDBG("can't get CORE mem resource by name\n"); 1007 DSSERR("can't get CORE mem resource\n");
1012 /* 1008 return -EINVAL;
1013 * if hwmod/DT doesn't have the memory resource information
1014 * split into HDMI sub blocks by name, we try again by getting
1015 * the platform's first resource. this code will be removed when
1016 * the driver can get the mem resources by name
1017 */
1018 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1019 if (!res) {
1020 DSSERR("can't get CORE mem resource\n");
1021 return -EINVAL;
1022 }
1023
1024 temp_res.start = res->start + CORE_OFFSET;
1025 temp_res.end = temp_res.start + CORE_SIZE - 1;
1026 res = &temp_res;
1027 } 1009 }
1028 1010
1029 core->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 1011 core->base = devm_ioremap_resource(&pdev->dev, res);
1030 if (!core->base) { 1012 if (IS_ERR(core->base)) {
1031 DSSERR("can't ioremap CORE\n"); 1013 DSSERR("can't ioremap CORE\n");
1032 return -ENOMEM; 1014 return PTR_ERR(core->base);
1033 } 1015 }
1034 1016
1035 return 0; 1017 return 0;
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c
new file mode 100644
index 000000000000..c468b9e1f295
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi5.c
@@ -0,0 +1,829 @@
1/*
2 * HDMI driver for OMAP5
3 *
4 * Copyright (C) 2014 Texas Instruments Incorporated
5 *
6 * Authors:
7 * Yong Zhi
8 * Mythri pk
9 * Archit Taneja <archit@ti.com>
10 * Tomi Valkeinen <tomi.valkeinen@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25#define DSS_SUBSYS_NAME "HDMI"
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/err.h>
30#include <linux/io.h>
31#include <linux/interrupt.h>
32#include <linux/mutex.h>
33#include <linux/delay.h>
34#include <linux/string.h>
35#include <linux/platform_device.h>
36#include <linux/pm_runtime.h>
37#include <linux/clk.h>
38#include <linux/gpio.h>
39#include <linux/regulator/consumer.h>
40#include <video/omapdss.h>
41
42#include "hdmi5_core.h"
43#include "dss.h"
44#include "dss_features.h"
45
46static struct {
47 struct mutex lock;
48 struct platform_device *pdev;
49
50 struct hdmi_wp_data wp;
51 struct hdmi_pll_data pll;
52 struct hdmi_phy_data phy;
53 struct hdmi_core_data core;
54
55 struct hdmi_config cfg;
56
57 struct clk *sys_clk;
58 struct regulator *vdda_reg;
59
60 bool core_enabled;
61
62 struct omap_dss_device output;
63} hdmi;
64
65static int hdmi_runtime_get(void)
66{
67 int r;
68
69 DSSDBG("hdmi_runtime_get\n");
70
71 r = pm_runtime_get_sync(&hdmi.pdev->dev);
72 WARN_ON(r < 0);
73 if (r < 0)
74 return r;
75
76 return 0;
77}
78
79static void hdmi_runtime_put(void)
80{
81 int r;
82
83 DSSDBG("hdmi_runtime_put\n");
84
85 r = pm_runtime_put_sync(&hdmi.pdev->dev);
86 WARN_ON(r < 0 && r != -ENOSYS);
87}
88
89static irqreturn_t hdmi_irq_handler(int irq, void *data)
90{
91 struct hdmi_wp_data *wp = data;
92 u32 irqstatus;
93
94 irqstatus = hdmi_wp_get_irqstatus(wp);
95 hdmi_wp_set_irqstatus(wp, irqstatus);
96
97 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) &&
98 irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
99 u32 v;
100 /*
101 * If we get both connect and disconnect interrupts at the same
102 * time, turn off the PHY, clear interrupts, and restart, which
103 * raises connect interrupt if a cable is connected, or nothing
104 * if cable is not connected.
105 */
106
107 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
108
109 /*
110 * We always get bogus CONNECT & DISCONNECT interrupts when
111 * setting the PHY to LDOON. To ignore those, we force the RXDET
112 * line to 0 until the PHY power state has been changed.
113 */
114 v = hdmi_read_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL);
115 v = FLD_MOD(v, 1, 15, 15); /* FORCE_RXDET_HIGH */
116 v = FLD_MOD(v, 0, 14, 7); /* RXDET_LINE */
117 hdmi_write_reg(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, v);
118
119 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT |
120 HDMI_IRQ_LINK_DISCONNECT);
121
122 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
123
124 REG_FLD_MOD(hdmi.phy.base, HDMI_TXPHY_PAD_CFG_CTRL, 0, 15, 15);
125
126 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) {
127 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON);
128 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) {
129 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON);
130 }
131
132 return IRQ_HANDLED;
133}
134
135static int hdmi_init_regulator(void)
136{
137 int r;
138 struct regulator *reg;
139
140 if (hdmi.vdda_reg != NULL)
141 return 0;
142
143 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
144 if (IS_ERR(reg)) {
145 DSSERR("can't get VDDA regulator\n");
146 return PTR_ERR(reg);
147 }
148
149 if (regulator_can_change_voltage(reg)) {
150 r = regulator_set_voltage(reg, 1800000, 1800000);
151 if (r) {
152 devm_regulator_put(reg);
153 DSSWARN("can't set the regulator voltage\n");
154 return r;
155 }
156 }
157
158 hdmi.vdda_reg = reg;
159
160 return 0;
161}
162
163static int hdmi_power_on_core(struct omap_dss_device *dssdev)
164{
165 int r;
166
167 r = regulator_enable(hdmi.vdda_reg);
168 if (r)
169 return r;
170
171 r = hdmi_runtime_get();
172 if (r)
173 goto err_runtime_get;
174
175 /* Make selection of HDMI in DSS */
176 dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK);
177
178 hdmi.core_enabled = true;
179
180 return 0;
181
182err_runtime_get:
183 regulator_disable(hdmi.vdda_reg);
184
185 return r;
186}
187
188static void hdmi_power_off_core(struct omap_dss_device *dssdev)
189{
190 hdmi.core_enabled = false;
191
192 hdmi_runtime_put();
193 regulator_disable(hdmi.vdda_reg);
194}
195
196static int hdmi_power_on_full(struct omap_dss_device *dssdev)
197{
198 int r;
199 struct omap_video_timings *p;
200 struct omap_overlay_manager *mgr = hdmi.output.manager;
201 unsigned long phy;
202
203 r = hdmi_power_on_core(dssdev);
204 if (r)
205 return r;
206
207 p = &hdmi.cfg.timings;
208
209 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
210
211 /* the functions below use kHz pixel clock. TODO: change to Hz */
212 phy = p->pixelclock / 1000;
213
214 hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
215
216 /* disable and clear irqs */
217 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
218 hdmi_wp_set_irqstatus(&hdmi.wp,
219 hdmi_wp_get_irqstatus(&hdmi.wp));
220
221 /* config the PLL and PHY hdmi_set_pll_pwrfirst */
222 r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
223 if (r) {
224 DSSDBG("Failed to lock PLL\n");
225 goto err_pll_enable;
226 }
227
228 r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg);
229 if (r) {
230 DSSDBG("Failed to start PHY\n");
231 goto err_phy_cfg;
232 }
233
234 r = hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_LDOON);
235 if (r)
236 goto err_phy_pwr;
237
238 hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
239
240 /* bypass TV gamma table */
241 dispc_enable_gamma_table(0);
242
243 /* tv size */
244 dss_mgr_set_timings(mgr, p);
245
246 r = hdmi_wp_video_start(&hdmi.wp);
247 if (r)
248 goto err_vid_enable;
249
250 r = dss_mgr_enable(mgr);
251 if (r)
252 goto err_mgr_enable;
253
254 hdmi_wp_set_irqenable(&hdmi.wp,
255 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
256
257 return 0;
258
259err_mgr_enable:
260 hdmi_wp_video_stop(&hdmi.wp);
261err_vid_enable:
262 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
263err_phy_pwr:
264err_phy_cfg:
265 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
266err_pll_enable:
267 hdmi_power_off_core(dssdev);
268 return -EIO;
269}
270
271static void hdmi_power_off_full(struct omap_dss_device *dssdev)
272{
273 struct omap_overlay_manager *mgr = hdmi.output.manager;
274
275 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
276
277 dss_mgr_disable(mgr);
278
279 hdmi_wp_video_stop(&hdmi.wp);
280
281 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
282
283 hdmi_pll_disable(&hdmi.pll, &hdmi.wp);
284
285 hdmi_power_off_core(dssdev);
286}
287
288static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
289 struct omap_video_timings *timings)
290{
291 struct omap_dss_device *out = &hdmi.output;
292
293 if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
294 return -EINVAL;
295
296 return 0;
297}
298
299static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
300 struct omap_video_timings *timings)
301{
302 struct hdmi_cm cm;
303 const struct hdmi_config *t;
304
305 mutex_lock(&hdmi.lock);
306
307 cm = hdmi_get_code(timings);
308 hdmi.cfg.cm = cm;
309
310 t = hdmi_get_timings(cm.mode, cm.code);
311 if (t != NULL) {
312 hdmi.cfg = *t;
313
314 dispc_set_tv_pclk(t->timings.pixelclock);
315 } else {
316 hdmi.cfg.timings = *timings;
317 hdmi.cfg.cm.code = 0;
318 hdmi.cfg.cm.mode = HDMI_DVI;
319
320 dispc_set_tv_pclk(timings->pixelclock);
321 }
322
323 DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
324 "DVI" : "HDMI", hdmi.cfg.cm.code);
325
326 mutex_unlock(&hdmi.lock);
327}
328
329static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
330 struct omap_video_timings *timings)
331{
332 const struct hdmi_config *cfg;
333 struct hdmi_cm cm = hdmi.cfg.cm;
334
335 cfg = hdmi_get_timings(cm.mode, cm.code);
336 if (cfg == NULL)
337 cfg = hdmi_default_timing();
338
339 memcpy(timings, &cfg->timings, sizeof(cfg->timings));
340}
341
342static void hdmi_dump_regs(struct seq_file *s)
343{
344 mutex_lock(&hdmi.lock);
345
346 if (hdmi_runtime_get()) {
347 mutex_unlock(&hdmi.lock);
348 return;
349 }
350
351 hdmi_wp_dump(&hdmi.wp, s);
352 hdmi_pll_dump(&hdmi.pll, s);
353 hdmi_phy_dump(&hdmi.phy, s);
354 hdmi5_core_dump(&hdmi.core, s);
355
356 hdmi_runtime_put();
357 mutex_unlock(&hdmi.lock);
358}
359
360static int read_edid(u8 *buf, int len)
361{
362 int r;
363 int idlemode;
364
365 mutex_lock(&hdmi.lock);
366
367 r = hdmi_runtime_get();
368 BUG_ON(r);
369
370 idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
371 /* No-idle mode */
372 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
373
374 r = hdmi5_read_edid(&hdmi.core, buf, len);
375
376 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, idlemode, 3, 2);
377
378 hdmi_runtime_put();
379 mutex_unlock(&hdmi.lock);
380
381 return r;
382}
383
384static int hdmi_display_enable(struct omap_dss_device *dssdev)
385{
386 struct omap_dss_device *out = &hdmi.output;
387 int r = 0;
388
389 DSSDBG("ENTER hdmi_display_enable\n");
390
391 mutex_lock(&hdmi.lock);
392
393 if (out == NULL || out->manager == NULL) {
394 DSSERR("failed to enable display: no output/manager\n");
395 r = -ENODEV;
396 goto err0;
397 }
398
399 r = hdmi_power_on_full(dssdev);
400 if (r) {
401 DSSERR("failed to power on device\n");
402 goto err0;
403 }
404
405 mutex_unlock(&hdmi.lock);
406 return 0;
407
408err0:
409 mutex_unlock(&hdmi.lock);
410 return r;
411}
412
413static void hdmi_display_disable(struct omap_dss_device *dssdev)
414{
415 DSSDBG("Enter hdmi_display_disable\n");
416
417 mutex_lock(&hdmi.lock);
418
419 hdmi_power_off_full(dssdev);
420
421 mutex_unlock(&hdmi.lock);
422}
423
424static int hdmi_core_enable(struct omap_dss_device *dssdev)
425{
426 int r = 0;
427
428 DSSDBG("ENTER omapdss_hdmi_core_enable\n");
429
430 mutex_lock(&hdmi.lock);
431
432 r = hdmi_power_on_core(dssdev);
433 if (r) {
434 DSSERR("failed to power on device\n");
435 goto err0;
436 }
437
438 mutex_unlock(&hdmi.lock);
439 return 0;
440
441err0:
442 mutex_unlock(&hdmi.lock);
443 return r;
444}
445
446static void hdmi_core_disable(struct omap_dss_device *dssdev)
447{
448 DSSDBG("Enter omapdss_hdmi_core_disable\n");
449
450 mutex_lock(&hdmi.lock);
451
452 hdmi_power_off_core(dssdev);
453
454 mutex_unlock(&hdmi.lock);
455}
456
457static int hdmi_get_clocks(struct platform_device *pdev)
458{
459 struct clk *clk;
460
461 clk = devm_clk_get(&pdev->dev, "sys_clk");
462 if (IS_ERR(clk)) {
463 DSSERR("can't get sys_clk\n");
464 return PTR_ERR(clk);
465 }
466
467 hdmi.sys_clk = clk;
468
469 return 0;
470}
471
472static int hdmi_connect(struct omap_dss_device *dssdev,
473 struct omap_dss_device *dst)
474{
475 struct omap_overlay_manager *mgr;
476 int r;
477
478 r = hdmi_init_regulator();
479 if (r)
480 return r;
481
482 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
483 if (!mgr)
484 return -ENODEV;
485
486 r = dss_mgr_connect(mgr, dssdev);
487 if (r)
488 return r;
489
490 r = omapdss_output_set_device(dssdev, dst);
491 if (r) {
492 DSSERR("failed to connect output to new device: %s\n",
493 dst->name);
494 dss_mgr_disconnect(mgr, dssdev);
495 return r;
496 }
497
498 return 0;
499}
500
501static void hdmi_disconnect(struct omap_dss_device *dssdev,
502 struct omap_dss_device *dst)
503{
504 WARN_ON(dst != dssdev->dst);
505
506 if (dst != dssdev->dst)
507 return;
508
509 omapdss_output_unset_device(dssdev);
510
511 if (dssdev->manager)
512 dss_mgr_disconnect(dssdev->manager, dssdev);
513}
514
515static int hdmi_read_edid(struct omap_dss_device *dssdev,
516 u8 *edid, int len)
517{
518 bool need_enable;
519 int r;
520
521 need_enable = hdmi.core_enabled == false;
522
523 if (need_enable) {
524 r = hdmi_core_enable(dssdev);
525 if (r)
526 return r;
527 }
528
529 r = read_edid(edid, len);
530
531 if (need_enable)
532 hdmi_core_disable(dssdev);
533
534 return r;
535}
536
537#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
538static int hdmi_audio_enable(struct omap_dss_device *dssdev)
539{
540 int r;
541
542 mutex_lock(&hdmi.lock);
543
544 if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
545 r = -EPERM;
546 goto err;
547 }
548
549 r = hdmi_wp_audio_enable(&hdmi.wp, true);
550 if (r)
551 goto err;
552
553 mutex_unlock(&hdmi.lock);
554 return 0;
555
556err:
557 mutex_unlock(&hdmi.lock);
558 return r;
559}
560
561static void hdmi_audio_disable(struct omap_dss_device *dssdev)
562{
563 hdmi_wp_audio_enable(&hdmi.wp, false);
564}
565
566static int hdmi_audio_start(struct omap_dss_device *dssdev)
567{
568 return hdmi_wp_audio_core_req_enable(&hdmi.wp, true);
569}
570
571static void hdmi_audio_stop(struct omap_dss_device *dssdev)
572{
573 hdmi_wp_audio_core_req_enable(&hdmi.wp, false);
574}
575
576static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
577{
578 bool r;
579
580 mutex_lock(&hdmi.lock);
581
582 r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
583
584 mutex_unlock(&hdmi.lock);
585 return r;
586}
587
588static int hdmi_audio_config(struct omap_dss_device *dssdev,
589 struct omap_dss_audio *audio)
590{
591 int r;
592 u32 pclk = hdmi.cfg.timings.pixelclock;
593
594 mutex_lock(&hdmi.lock);
595
596 if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
597 r = -EPERM;
598 goto err;
599 }
600
601 r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
602 if (r)
603 goto err;
604
605 mutex_unlock(&hdmi.lock);
606 return 0;
607
608err:
609 mutex_unlock(&hdmi.lock);
610 return r;
611}
612#else
613static int hdmi_audio_enable(struct omap_dss_device *dssdev)
614{
615 return -EPERM;
616}
617
618static void hdmi_audio_disable(struct omap_dss_device *dssdev)
619{
620}
621
622static int hdmi_audio_start(struct omap_dss_device *dssdev)
623{
624 return -EPERM;
625}
626
627static void hdmi_audio_stop(struct omap_dss_device *dssdev)
628{
629}
630
631static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
632{
633 return false;
634}
635
636static int hdmi_audio_config(struct omap_dss_device *dssdev,
637 struct omap_dss_audio *audio)
638{
639 return -EPERM;
640}
641#endif
642
643static const struct omapdss_hdmi_ops hdmi_ops = {
644 .connect = hdmi_connect,
645 .disconnect = hdmi_disconnect,
646
647 .enable = hdmi_display_enable,
648 .disable = hdmi_display_disable,
649
650 .check_timings = hdmi_display_check_timing,
651 .set_timings = hdmi_display_set_timing,
652 .get_timings = hdmi_display_get_timings,
653
654 .read_edid = hdmi_read_edid,
655
656 .audio_enable = hdmi_audio_enable,
657 .audio_disable = hdmi_audio_disable,
658 .audio_start = hdmi_audio_start,
659 .audio_stop = hdmi_audio_stop,
660 .audio_supported = hdmi_audio_supported,
661 .audio_config = hdmi_audio_config,
662};
663
664static void hdmi_init_output(struct platform_device *pdev)
665{
666 struct omap_dss_device *out = &hdmi.output;
667
668 out->dev = &pdev->dev;
669 out->id = OMAP_DSS_OUTPUT_HDMI;
670 out->output_type = OMAP_DISPLAY_TYPE_HDMI;
671 out->name = "hdmi.0";
672 out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
673 out->ops.hdmi = &hdmi_ops;
674 out->owner = THIS_MODULE;
675
676 omapdss_register_output(out);
677}
678
679static void __exit hdmi_uninit_output(struct platform_device *pdev)
680{
681 struct omap_dss_device *out = &hdmi.output;
682
683 omapdss_unregister_output(out);
684}
685
686static int hdmi_probe_of(struct platform_device *pdev)
687{
688 struct device_node *node = pdev->dev.of_node;
689 struct device_node *ep;
690 int r;
691
692 ep = omapdss_of_get_first_endpoint(node);
693 if (!ep)
694 return 0;
695
696 r = hdmi_parse_lanes_of(pdev, ep, &hdmi.phy);
697 if (r)
698 goto err;
699
700 of_node_put(ep);
701 return 0;
702
703err:
704 of_node_put(ep);
705 return r;
706}
707
708/* HDMI HW IP initialisation */
709static int omapdss_hdmihw_probe(struct platform_device *pdev)
710{
711 int r;
712 int irq;
713
714 hdmi.pdev = pdev;
715
716 mutex_init(&hdmi.lock);
717
718 if (pdev->dev.of_node) {
719 r = hdmi_probe_of(pdev);
720 if (r)
721 return r;
722 }
723
724 r = hdmi_wp_init(pdev, &hdmi.wp);
725 if (r)
726 return r;
727
728 r = hdmi_pll_init(pdev, &hdmi.pll);
729 if (r)
730 return r;
731
732 r = hdmi_phy_init(pdev, &hdmi.phy);
733 if (r)
734 return r;
735
736 r = hdmi5_core_init(pdev, &hdmi.core);
737 if (r)
738 return r;
739
740 r = hdmi_get_clocks(pdev);
741 if (r) {
742 DSSERR("can't get clocks\n");
743 return r;
744 }
745
746 irq = platform_get_irq(pdev, 0);
747 if (irq < 0) {
748 DSSERR("platform_get_irq failed\n");
749 return -ENODEV;
750 }
751
752 r = devm_request_threaded_irq(&pdev->dev, irq,
753 NULL, hdmi_irq_handler,
754 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
755 if (r) {
756 DSSERR("HDMI IRQ request failed\n");
757 return r;
758 }
759
760 pm_runtime_enable(&pdev->dev);
761
762 hdmi_init_output(pdev);
763
764 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
765
766 return 0;
767}
768
769static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
770{
771 hdmi_uninit_output(pdev);
772
773 pm_runtime_disable(&pdev->dev);
774
775 return 0;
776}
777
778static int hdmi_runtime_suspend(struct device *dev)
779{
780 clk_disable_unprepare(hdmi.sys_clk);
781
782 dispc_runtime_put();
783
784 return 0;
785}
786
787static int hdmi_runtime_resume(struct device *dev)
788{
789 int r;
790
791 r = dispc_runtime_get();
792 if (r < 0)
793 return r;
794
795 clk_prepare_enable(hdmi.sys_clk);
796
797 return 0;
798}
799
800static const struct dev_pm_ops hdmi_pm_ops = {
801 .runtime_suspend = hdmi_runtime_suspend,
802 .runtime_resume = hdmi_runtime_resume,
803};
804
805static const struct of_device_id hdmi_of_match[] = {
806 { .compatible = "ti,omap5-hdmi", },
807 {},
808};
809
810static struct platform_driver omapdss_hdmihw_driver = {
811 .probe = omapdss_hdmihw_probe,
812 .remove = __exit_p(omapdss_hdmihw_remove),
813 .driver = {
814 .name = "omapdss_hdmi5",
815 .owner = THIS_MODULE,
816 .pm = &hdmi_pm_ops,
817 .of_match_table = hdmi_of_match,
818 },
819};
820
821int __init hdmi5_init_platform_driver(void)
822{
823 return platform_driver_register(&omapdss_hdmihw_driver);
824}
825
826void __exit hdmi5_uninit_platform_driver(void)
827{
828 platform_driver_unregister(&omapdss_hdmihw_driver);
829}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.c b/drivers/video/fbdev/omap2/dss/hdmi5_core.c
new file mode 100644
index 000000000000..7528c7a42aa5
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi5_core.c
@@ -0,0 +1,922 @@
1/*
2 * OMAP5 HDMI CORE IP driver library
3 *
4 * Copyright (C) 2014 Texas Instruments Incorporated
5 *
6 * Authors:
7 * Yong Zhi
8 * Mythri pk
9 * Archit Taneja <archit@ti.com>
10 * Tomi Valkeinen <tomi.valkeinen@ti.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published by
14 * the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/err.h>
28#include <linux/io.h>
29#include <linux/delay.h>
30#include <linux/string.h>
31#include <linux/seq_file.h>
32#include <drm/drm_edid.h>
33#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
34#include <sound/asound.h>
35#include <sound/asoundef.h>
36#endif
37
38#include "hdmi5_core.h"
39
40/* only 24 bit color depth used for now */
41static const struct csc_table csc_table_deepcolor[] = {
42 /* HDMI_DEEP_COLOR_24BIT */
43 [0] = { 7036, 0, 0, 32, 0, 7036, 0, 32, 0, 0, 7036, 32, },
44 /* HDMI_DEEP_COLOR_30BIT */
45 [1] = { 7015, 0, 0, 128, 0, 7015, 0, 128, 0, 0, 7015, 128, },
46 /* HDMI_DEEP_COLOR_36BIT */
47 [2] = { 7010, 0, 0, 512, 0, 7010, 0, 512, 0, 0, 7010, 512, },
48 /* FULL RANGE */
49 [3] = { 8192, 0, 0, 0, 0, 8192, 0, 0, 0, 0, 8192, 0, },
50};
51
52static void hdmi_core_ddc_init(struct hdmi_core_data *core)
53{
54 void __iomem *base = core->base;
55 const unsigned long long iclk = 266000000; /* DSS L3 ICLK */
56 const unsigned ss_scl_high = 4000; /* ns */
57 const unsigned ss_scl_low = 4700; /* ns */
58 const unsigned fs_scl_high = 600; /* ns */
59 const unsigned fs_scl_low = 1300; /* ns */
60 const unsigned sda_hold = 300; /* ns */
61 const unsigned sfr_div = 10;
62 unsigned long long sfr;
63 unsigned v;
64
65 sfr = iclk / sfr_div; /* SFR_DIV */
66 sfr /= 1000; /* SFR clock in kHz */
67
68 /* Reset */
69 REG_FLD_MOD(base, HDMI_CORE_I2CM_SOFTRSTZ, 0, 0, 0);
70 if (hdmi_wait_for_bit_change(base, HDMI_CORE_I2CM_SOFTRSTZ,
71 0, 0, 1) != 1)
72 DSSERR("HDMI I2CM reset failed\n");
73
74 /* Standard (0) or Fast (1) Mode */
75 REG_FLD_MOD(base, HDMI_CORE_I2CM_DIV, 0, 3, 3);
76
77 /* Standard Mode SCL High counter */
78 v = DIV_ROUND_UP_ULL(ss_scl_high * sfr, 1000000);
79 REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR,
80 (v >> 8) & 0xff, 7, 0);
81 REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR,
82 v & 0xff, 7, 0);
83
84 /* Standard Mode SCL Low counter */
85 v = DIV_ROUND_UP_ULL(ss_scl_low * sfr, 1000000);
86 REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR,
87 (v >> 8) & 0xff, 7, 0);
88 REG_FLD_MOD(base, HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR,
89 v & 0xff, 7, 0);
90
91 /* Fast Mode SCL High Counter */
92 v = DIV_ROUND_UP_ULL(fs_scl_high * sfr, 1000000);
93 REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR,
94 (v >> 8) & 0xff, 7, 0);
95 REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR,
96 v & 0xff, 7, 0);
97
98 /* Fast Mode SCL Low Counter */
99 v = DIV_ROUND_UP_ULL(fs_scl_low * sfr, 1000000);
100 REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR,
101 (v >> 8) & 0xff, 7, 0);
102 REG_FLD_MOD(base, HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR,
103 v & 0xff, 7, 0);
104
105 /* SDA Hold Time */
106 v = DIV_ROUND_UP_ULL(sda_hold * sfr, 1000000);
107 REG_FLD_MOD(base, HDMI_CORE_I2CM_SDA_HOLD_ADDR, v & 0xff, 7, 0);
108
109 REG_FLD_MOD(base, HDMI_CORE_I2CM_SLAVE, 0x50, 6, 0);
110 REG_FLD_MOD(base, HDMI_CORE_I2CM_SEGADDR, 0x30, 6, 0);
111
112 /* NACK_POL to high */
113 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 7, 7);
114
115 /* NACK_MASK to unmasked */
116 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x0, 6, 6);
117
118 /* ARBITRATION_POL to high */
119 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 3, 3);
120
121 /* ARBITRATION_MASK to unmasked */
122 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x0, 2, 2);
123
124 /* DONE_POL to high */
125 REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 3, 3);
126
127 /* DONE_MASK to unmasked */
128 REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x0, 2, 2);
129}
130
131static void hdmi_core_ddc_uninit(struct hdmi_core_data *core)
132{
133 void __iomem *base = core->base;
134
135 /* Mask I2C interrupts */
136 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 6, 6);
137 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 2, 2);
138 REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 2, 2);
139}
140
141static int hdmi_core_ddc_edid(struct hdmi_core_data *core, u8 *pedid, u8 ext)
142{
143 void __iomem *base = core->base;
144 u8 cur_addr;
145 char checksum = 0;
146 const int retries = 1000;
147 u8 seg_ptr = ext / 2;
148 u8 edidbase = ((ext % 2) * 0x80);
149
150 REG_FLD_MOD(base, HDMI_CORE_I2CM_SEGPTR, seg_ptr, 7, 0);
151
152 /*
153 * TODO: We use polling here, although we probably should use proper
154 * interrupts.
155 */
156 for (cur_addr = 0; cur_addr < 128; ++cur_addr) {
157 int i;
158
159 /* clear ERROR and DONE */
160 REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0x3, 1, 0);
161
162 REG_FLD_MOD(base, HDMI_CORE_I2CM_ADDRESS,
163 edidbase + cur_addr, 7, 0);
164
165 if (seg_ptr)
166 REG_FLD_MOD(base, HDMI_CORE_I2CM_OPERATION, 1, 1, 1);
167 else
168 REG_FLD_MOD(base, HDMI_CORE_I2CM_OPERATION, 1, 0, 0);
169
170 for (i = 0; i < retries; ++i) {
171 u32 stat;
172
173 stat = REG_GET(base, HDMI_CORE_IH_I2CM_STAT0, 1, 0);
174
175 /* I2CM_ERROR */
176 if (stat & 1) {
177 DSSERR("HDMI I2C Master Error\n");
178 return -EIO;
179 }
180
181 /* I2CM_DONE */
182 if (stat & (1 << 1))
183 break;
184
185 usleep_range(250, 1000);
186 }
187
188 if (i == retries) {
189 DSSERR("HDMI I2C timeout reading EDID\n");
190 return -EIO;
191 }
192
193 pedid[cur_addr] = REG_GET(base, HDMI_CORE_I2CM_DATAI, 7, 0);
194 checksum += pedid[cur_addr];
195 }
196
197 return 0;
198
199}
200
201int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
202{
203 int r, n, i;
204 int max_ext_blocks = (len / 128) - 1;
205
206 if (len < 128)
207 return -EINVAL;
208
209 hdmi_core_ddc_init(core);
210
211 r = hdmi_core_ddc_edid(core, edid, 0);
212 if (r)
213 goto out;
214
215 n = edid[0x7e];
216
217 if (n > max_ext_blocks)
218 n = max_ext_blocks;
219
220 for (i = 1; i <= n; i++) {
221 r = hdmi_core_ddc_edid(core, edid + i * EDID_LENGTH, i);
222 if (r)
223 goto out;
224 }
225
226out:
227 hdmi_core_ddc_uninit(core);
228
229 return r ? r : len;
230}
231
232void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s)
233{
234
235#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
236 hdmi_read_reg(core->base, r))
237
238 DUMPCORE(HDMI_CORE_FC_INVIDCONF);
239 DUMPCORE(HDMI_CORE_FC_INHACTIV0);
240 DUMPCORE(HDMI_CORE_FC_INHACTIV1);
241 DUMPCORE(HDMI_CORE_FC_INHBLANK0);
242 DUMPCORE(HDMI_CORE_FC_INHBLANK1);
243 DUMPCORE(HDMI_CORE_FC_INVACTIV0);
244 DUMPCORE(HDMI_CORE_FC_INVACTIV1);
245 DUMPCORE(HDMI_CORE_FC_INVBLANK);
246 DUMPCORE(HDMI_CORE_FC_HSYNCINDELAY0);
247 DUMPCORE(HDMI_CORE_FC_HSYNCINDELAY1);
248 DUMPCORE(HDMI_CORE_FC_HSYNCINWIDTH0);
249 DUMPCORE(HDMI_CORE_FC_HSYNCINWIDTH1);
250 DUMPCORE(HDMI_CORE_FC_VSYNCINDELAY);
251 DUMPCORE(HDMI_CORE_FC_VSYNCINWIDTH);
252 DUMPCORE(HDMI_CORE_FC_CTRLDUR);
253 DUMPCORE(HDMI_CORE_FC_EXCTRLDUR);
254 DUMPCORE(HDMI_CORE_FC_EXCTRLSPAC);
255 DUMPCORE(HDMI_CORE_FC_CH0PREAM);
256 DUMPCORE(HDMI_CORE_FC_CH1PREAM);
257 DUMPCORE(HDMI_CORE_FC_CH2PREAM);
258 DUMPCORE(HDMI_CORE_FC_AVICONF0);
259 DUMPCORE(HDMI_CORE_FC_AVICONF1);
260 DUMPCORE(HDMI_CORE_FC_AVICONF2);
261 DUMPCORE(HDMI_CORE_FC_AVIVID);
262 DUMPCORE(HDMI_CORE_FC_PRCONF);
263
264 DUMPCORE(HDMI_CORE_MC_CLKDIS);
265 DUMPCORE(HDMI_CORE_MC_SWRSTZREQ);
266 DUMPCORE(HDMI_CORE_MC_FLOWCTRL);
267 DUMPCORE(HDMI_CORE_MC_PHYRSTZ);
268 DUMPCORE(HDMI_CORE_MC_LOCKONCLOCK);
269
270 DUMPCORE(HDMI_CORE_I2CM_SLAVE);
271 DUMPCORE(HDMI_CORE_I2CM_ADDRESS);
272 DUMPCORE(HDMI_CORE_I2CM_DATAO);
273 DUMPCORE(HDMI_CORE_I2CM_DATAI);
274 DUMPCORE(HDMI_CORE_I2CM_OPERATION);
275 DUMPCORE(HDMI_CORE_I2CM_INT);
276 DUMPCORE(HDMI_CORE_I2CM_CTLINT);
277 DUMPCORE(HDMI_CORE_I2CM_DIV);
278 DUMPCORE(HDMI_CORE_I2CM_SEGADDR);
279 DUMPCORE(HDMI_CORE_I2CM_SOFTRSTZ);
280 DUMPCORE(HDMI_CORE_I2CM_SEGPTR);
281 DUMPCORE(HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR);
282 DUMPCORE(HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR);
283 DUMPCORE(HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR);
284 DUMPCORE(HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR);
285 DUMPCORE(HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR);
286 DUMPCORE(HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR);
287 DUMPCORE(HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR);
288 DUMPCORE(HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR);
289 DUMPCORE(HDMI_CORE_I2CM_SDA_HOLD_ADDR);
290}
291
292static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
293 struct hdmi_core_infoframe_avi *avi_cfg,
294 struct hdmi_config *cfg)
295{
296 DSSDBG("hdmi_core_init\n");
297
298 /* video core */
299 video_cfg->data_enable_pol = 1; /* It is always 1*/
300 video_cfg->v_fc_config.timings.hsync_level = cfg->timings.hsync_level;
301 video_cfg->v_fc_config.timings.x_res = cfg->timings.x_res;
302 video_cfg->v_fc_config.timings.hsw = cfg->timings.hsw - 1;
303 video_cfg->v_fc_config.timings.hbp = cfg->timings.hbp;
304 video_cfg->v_fc_config.timings.hfp = cfg->timings.hfp;
305 video_cfg->hblank = cfg->timings.hfp +
306 cfg->timings.hbp + cfg->timings.hsw - 1;
307 video_cfg->v_fc_config.timings.vsync_level = cfg->timings.vsync_level;
308 video_cfg->v_fc_config.timings.y_res = cfg->timings.y_res;
309 video_cfg->v_fc_config.timings.vsw = cfg->timings.vsw;
310 video_cfg->v_fc_config.timings.vfp = cfg->timings.vfp;
311 video_cfg->v_fc_config.timings.vbp = cfg->timings.vbp;
312 video_cfg->vblank_osc = 0; /* Always 0 - need to confirm */
313 video_cfg->vblank = cfg->timings.vsw +
314 cfg->timings.vfp + cfg->timings.vbp;
315 video_cfg->v_fc_config.cm.mode = cfg->cm.mode;
316 video_cfg->v_fc_config.timings.interlace = cfg->timings.interlace;
317
318 /* info frame */
319 avi_cfg->db1_format = 0;
320 avi_cfg->db1_active_info = 0;
321 avi_cfg->db1_bar_info_dv = 0;
322 avi_cfg->db1_scan_info = 0;
323 avi_cfg->db2_colorimetry = 0;
324 avi_cfg->db2_aspect_ratio = 0;
325 avi_cfg->db2_active_fmt_ar = 0;
326 avi_cfg->db3_itc = 0;
327 avi_cfg->db3_ec = 0;
328 avi_cfg->db3_q_range = 0;
329 avi_cfg->db3_nup_scaling = 0;
330 avi_cfg->db4_videocode = 0;
331 avi_cfg->db5_pixel_repeat = 0;
332 avi_cfg->db6_7_line_eoftop = 0;
333 avi_cfg->db8_9_line_sofbottom = 0;
334 avi_cfg->db10_11_pixel_eofleft = 0;
335 avi_cfg->db12_13_pixel_sofright = 0;
336}
337
338/* DSS_HDMI_CORE_VIDEO_CONFIG */
339static void hdmi_core_video_config(struct hdmi_core_data *core,
340 struct hdmi_core_vid_config *cfg)
341{
342 void __iomem *base = core->base;
343 unsigned char r = 0;
344 bool vsync_pol, hsync_pol;
345
346 vsync_pol =
347 cfg->v_fc_config.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
348 hsync_pol =
349 cfg->v_fc_config.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
350
351 /* Set hsync, vsync and data-enable polarity */
352 r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF);
353 r = FLD_MOD(r, vsync_pol, 6, 6);
354 r = FLD_MOD(r, hsync_pol, 5, 5);
355 r = FLD_MOD(r, cfg->data_enable_pol, 4, 4);
356 r = FLD_MOD(r, cfg->vblank_osc, 1, 1);
357 r = FLD_MOD(r, cfg->v_fc_config.timings.interlace, 0, 0);
358 hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r);
359
360 /* set x resolution */
361 REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1,
362 cfg->v_fc_config.timings.x_res >> 8, 4, 0);
363 REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0,
364 cfg->v_fc_config.timings.x_res & 0xFF, 7, 0);
365
366 /* set y resolution */
367 REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1,
368 cfg->v_fc_config.timings.y_res >> 8, 4, 0);
369 REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0,
370 cfg->v_fc_config.timings.y_res & 0xFF, 7, 0);
371
372 /* set horizontal blanking pixels */
373 REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0);
374 REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK0, cfg->hblank & 0xFF, 7, 0);
375
376 /* set vertial blanking pixels */
377 REG_FLD_MOD(base, HDMI_CORE_FC_INVBLANK, cfg->vblank, 7, 0);
378
379 /* set horizontal sync offset */
380 REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1,
381 cfg->v_fc_config.timings.hfp >> 8, 4, 0);
382 REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0,
383 cfg->v_fc_config.timings.hfp & 0xFF, 7, 0);
384
385 /* set vertical sync offset */
386 REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY,
387 cfg->v_fc_config.timings.vfp, 7, 0);
388
389 /* set horizontal sync pulse width */
390 REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1,
391 (cfg->v_fc_config.timings.hsw >> 8), 1, 0);
392 REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0,
393 cfg->v_fc_config.timings.hsw & 0xFF, 7, 0);
394
395 /* set vertical sync pulse width */
396 REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH,
397 cfg->v_fc_config.timings.vsw, 5, 0);
398
399 /* select DVI mode */
400 REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF,
401 cfg->v_fc_config.cm.mode, 3, 3);
402}
403
404static void hdmi_core_config_video_packetizer(struct hdmi_core_data *core)
405{
406 void __iomem *base = core->base;
407 int clr_depth = 0; /* 24 bit color depth */
408
409 /* COLOR_DEPTH */
410 REG_FLD_MOD(base, HDMI_CORE_VP_PR_CD, clr_depth, 7, 4);
411 /* BYPASS_EN */
412 REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 0 : 1, 6, 6);
413 /* PP_EN */
414 REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 1 : 0, 5, 5);
415 /* YCC422_EN */
416 REG_FLD_MOD(base, HDMI_CORE_VP_CONF, 0, 3, 3);
417 /* PP_STUFFING */
418 REG_FLD_MOD(base, HDMI_CORE_VP_STUFF, clr_depth ? 1 : 0, 1, 1);
419 /* YCC422_STUFFING */
420 REG_FLD_MOD(base, HDMI_CORE_VP_STUFF, 1, 2, 2);
421 /* OUTPUT_SELECTOR */
422 REG_FLD_MOD(base, HDMI_CORE_VP_CONF, clr_depth ? 0 : 2, 1, 0);
423}
424
425static void hdmi_core_config_csc(struct hdmi_core_data *core)
426{
427 int clr_depth = 0; /* 24 bit color depth */
428
429 /* CSC_COLORDEPTH */
430 REG_FLD_MOD(core->base, HDMI_CORE_CSC_SCALE, clr_depth, 7, 4);
431}
432
433static void hdmi_core_config_video_sampler(struct hdmi_core_data *core)
434{
435 int video_mapping = 1; /* for 24 bit color depth */
436
437 /* VIDEO_MAPPING */
438 REG_FLD_MOD(core->base, HDMI_CORE_TX_INVID0, video_mapping, 4, 0);
439}
440
441static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core)
442{
443 void __iomem *base = core->base;
444 struct hdmi_core_infoframe_avi avi = core->avi_cfg;
445
446 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_format, 1, 0);
447 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_active_info, 6, 6);
448 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_bar_info_dv, 3, 2);
449 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_scan_info, 5, 4);
450 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_colorimetry, 7, 6);
451 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_aspect_ratio, 5, 4);
452 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_active_fmt_ar, 3, 0);
453 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_itc, 7, 7);
454 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_ec, 6, 4);
455 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_q_range, 3, 2);
456 REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_nup_scaling, 1, 0);
457 REG_FLD_MOD(base, HDMI_CORE_FC_AVIVID, avi.db4_videocode, 6, 0);
458 REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, avi.db5_pixel_repeat, 3, 0);
459}
460
461static void hdmi_core_csc_config(struct hdmi_core_data *core,
462 struct csc_table csc_coeff)
463{
464 void __iomem *base = core->base;
465
466 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_MSB, csc_coeff.a1 >> 8 , 6, 0);
467 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A1_LSB, csc_coeff.a1, 7, 0);
468 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_MSB, csc_coeff.a2 >> 8, 6, 0);
469 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A2_LSB, csc_coeff.a2, 7, 0);
470 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_MSB, csc_coeff.a3 >> 8, 6, 0);
471 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A3_LSB, csc_coeff.a3, 7, 0);
472 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_MSB, csc_coeff.a4 >> 8, 6, 0);
473 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_A4_LSB, csc_coeff.a4, 7, 0);
474 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_MSB, csc_coeff.b1 >> 8, 6, 0);
475 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B1_LSB, csc_coeff.b1, 7, 0);
476 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_MSB, csc_coeff.b2 >> 8, 6, 0);
477 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B2_LSB, csc_coeff.b2, 7, 0);
478 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_MSB, csc_coeff.b3 >> 8, 6, 0);
479 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B3_LSB, csc_coeff.b3, 7, 0);
480 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_MSB, csc_coeff.b4 >> 8, 6, 0);
481 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_B4_LSB, csc_coeff.b4, 7, 0);
482 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_MSB, csc_coeff.c1 >> 8, 6, 0);
483 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C1_LSB, csc_coeff.c1, 7, 0);
484 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_MSB, csc_coeff.c2 >> 8, 6, 0);
485 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C2_LSB, csc_coeff.c2, 7, 0);
486 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_MSB, csc_coeff.c3 >> 8, 6, 0);
487 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C3_LSB, csc_coeff.c3, 7, 0);
488 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_MSB, csc_coeff.c4 >> 8, 6, 0);
489 REG_FLD_MOD(base, HDMI_CORE_CSC_COEF_C4_LSB, csc_coeff.c4, 7, 0);
490
491 REG_FLD_MOD(base, HDMI_CORE_MC_FLOWCTRL, 0x1, 0, 0);
492}
493
494static void hdmi_core_configure_range(struct hdmi_core_data *core)
495{
496 struct csc_table csc_coeff = { 0 };
497
498 /* support limited range with 24 bit color depth for now */
499 csc_coeff = csc_table_deepcolor[0];
500 core->avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_LR;
501
502 hdmi_core_csc_config(core, csc_coeff);
503 hdmi_core_aux_infoframe_avi_config(core);
504}
505
506static void hdmi_core_enable_video_path(struct hdmi_core_data *core)
507{
508 void __iomem *base = core->base;
509
510 DSSDBG("hdmi_core_enable_video_path\n");
511
512 REG_FLD_MOD(base, HDMI_CORE_FC_CTRLDUR, 0x0C, 7, 0);
513 REG_FLD_MOD(base, HDMI_CORE_FC_EXCTRLDUR, 0x20, 7, 0);
514 REG_FLD_MOD(base, HDMI_CORE_FC_EXCTRLSPAC, 0x01, 7, 0);
515 REG_FLD_MOD(base, HDMI_CORE_FC_CH0PREAM, 0x0B, 7, 0);
516 REG_FLD_MOD(base, HDMI_CORE_FC_CH1PREAM, 0x16, 5, 0);
517 REG_FLD_MOD(base, HDMI_CORE_FC_CH2PREAM, 0x21, 5, 0);
518 REG_FLD_MOD(base, HDMI_CORE_MC_CLKDIS, 0x00, 0, 0);
519 REG_FLD_MOD(base, HDMI_CORE_MC_CLKDIS, 0x00, 1, 1);
520}
521
522static void hdmi_core_mask_interrupts(struct hdmi_core_data *core)
523{
524 void __iomem *base = core->base;
525
526 /* Master IRQ mask */
527 REG_FLD_MOD(base, HDMI_CORE_IH_MUTE, 0x3, 1, 0);
528
529 /* Mask all the interrupts in HDMI core */
530
531 REG_FLD_MOD(base, HDMI_CORE_VP_MASK, 0xff, 7, 0);
532 REG_FLD_MOD(base, HDMI_CORE_FC_MASK0, 0xe7, 7, 0);
533 REG_FLD_MOD(base, HDMI_CORE_FC_MASK1, 0xfb, 7, 0);
534 REG_FLD_MOD(base, HDMI_CORE_FC_MASK2, 0x3, 1, 0);
535
536 REG_FLD_MOD(base, HDMI_CORE_AUD_INT, 0x3, 3, 2);
537 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_MASK, 0x3, 1, 0);
538
539 REG_FLD_MOD(base, HDMI_CORE_CEC_MASK, 0x7f, 6, 0);
540
541 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 6, 6);
542 REG_FLD_MOD(base, HDMI_CORE_I2CM_CTLINT, 0x1, 2, 2);
543 REG_FLD_MOD(base, HDMI_CORE_I2CM_INT, 0x1, 2, 2);
544
545 REG_FLD_MOD(base, HDMI_CORE_PHY_MASK0, 0xf3, 7, 0);
546
547 REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0);
548
549 /* Clear all the current interrupt bits */
550
551 REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0);
552 REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xe7, 7, 0);
553 REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xfb, 7, 0);
554 REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0x3, 1, 0);
555
556 REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0x7, 2, 0);
557
558 REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0x7f, 6, 0);
559
560 REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0x3, 1, 0);
561
562 REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0);
563}
564
565static void hdmi_core_enable_interrupts(struct hdmi_core_data *core)
566{
567 /* Unmute interrupts */
568 REG_FLD_MOD(core->base, HDMI_CORE_IH_MUTE, 0x0, 1, 0);
569}
570
571int hdmi5_core_handle_irqs(struct hdmi_core_data *core)
572{
573 void __iomem *base = core->base;
574
575 REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xff, 7, 0);
576 REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xff, 7, 0);
577 REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0xff, 7, 0);
578 REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0xff, 7, 0);
579 REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0);
580 REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0xff, 7, 0);
581 REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0xff, 7, 0);
582 REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0);
583 REG_FLD_MOD(base, HDMI_CORE_IH_I2CMPHY_STAT0, 0xff, 7, 0);
584
585 return 0;
586}
587
588void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
589 struct hdmi_config *cfg)
590{
591 struct omap_video_timings video_timing;
592 struct hdmi_video_format video_format;
593 struct hdmi_core_vid_config v_core_cfg;
594 struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg;
595
596 hdmi_core_mask_interrupts(core);
597
598 hdmi_core_init(&v_core_cfg, avi_cfg, cfg);
599
600 hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
601
602 hdmi_wp_video_config_timing(wp, &video_timing);
603
604 /* video config */
605 video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
606
607 hdmi_wp_video_config_format(wp, &video_format);
608
609 hdmi_wp_video_config_interface(wp, &video_timing);
610
611 hdmi_core_configure_range(core);
612
613 /*
614 * configure core video part, set software reset in the core
615 */
616 v_core_cfg.packet_mode = HDMI_PACKETMODE24BITPERPIXEL;
617
618 hdmi_core_video_config(core, &v_core_cfg);
619
620 hdmi_core_config_video_packetizer(core);
621 hdmi_core_config_csc(core);
622 hdmi_core_config_video_sampler(core);
623
624 /*
625 * configure packet info frame video see doc CEA861-D page 65
626 */
627 avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
628 avi_cfg->db1_active_info =
629 HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
630 avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
631 avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
632 avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
633 avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
634 avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
635 avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
636 avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
637 avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
638 avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
639 avi_cfg->db4_videocode = cfg->cm.code;
640 avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
641 avi_cfg->db6_7_line_eoftop = 0;
642 avi_cfg->db8_9_line_sofbottom = 0;
643 avi_cfg->db10_11_pixel_eofleft = 0;
644 avi_cfg->db12_13_pixel_sofright = 0;
645
646 hdmi_core_aux_infoframe_avi_config(core);
647
648 hdmi_core_enable_video_path(core);
649
650 hdmi_core_enable_interrupts(core);
651}
652
653
654#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
655
656static void hdmi5_core_audio_config(struct hdmi_core_data *core,
657 struct hdmi_core_audio_config *cfg)
658{
659 void __iomem *base = core->base;
660 u8 val;
661
662 /* Mute audio before configuring */
663 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 0xf, 7, 4);
664
665 /* Set the N parameter */
666 REG_FLD_MOD(base, HDMI_CORE_AUD_N1, cfg->n, 7, 0);
667 REG_FLD_MOD(base, HDMI_CORE_AUD_N2, cfg->n >> 8, 7, 0);
668 REG_FLD_MOD(base, HDMI_CORE_AUD_N3, cfg->n >> 16, 3, 0);
669
670 /*
671 * CTS manual mode. Automatic mode is not supported when using audio
672 * parallel interface.
673 */
674 REG_FLD_MOD(base, HDMI_CORE_AUD_CTS3, 1, 4, 4);
675 REG_FLD_MOD(base, HDMI_CORE_AUD_CTS1, cfg->cts, 7, 0);
676 REG_FLD_MOD(base, HDMI_CORE_AUD_CTS2, cfg->cts >> 8, 7, 0);
677 REG_FLD_MOD(base, HDMI_CORE_AUD_CTS3, cfg->cts >> 16, 3, 0);
678
679 /* Layout of Audio Sample Packets: 2-channel or multichannels */
680 if (cfg->layout == HDMI_AUDIO_LAYOUT_2CH)
681 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 0, 0, 0);
682 else
683 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 1, 0, 0);
684
685 /* Configure IEC-609580 Validity bits */
686 /* Channel 0 is valid */
687 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, 0, 0, 0);
688 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, 0, 4, 4);
689
690 if (cfg->layout == HDMI_AUDIO_LAYOUT_2CH)
691 val = 1;
692 else
693 val = 0;
694
695 /* Channels 1, 2 setting */
696 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 1, 1);
697 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 5, 5);
698 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 2, 2);
699 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 6, 6);
700 /* Channel 3 setting */
701 if (cfg->layout == HDMI_AUDIO_LAYOUT_6CH)
702 val = 1;
703 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 3, 3);
704 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSV, val, 7, 7);
705
706 /* Configure IEC-60958 User bits */
707 /* TODO: should be set by user. */
708 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSU, 0, 7, 0);
709
710 /* Configure IEC-60958 Channel Status word */
711 /* CGMSA */
712 val = cfg->iec60958_cfg->status[5] & IEC958_AES5_CON_CGMSA;
713 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(0), val, 5, 4);
714
715 /* Copyright */
716 val = (cfg->iec60958_cfg->status[0] &
717 IEC958_AES0_CON_NOT_COPYRIGHT) >> 2;
718 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(0), val, 0, 0);
719
720 /* Category */
721 hdmi_write_reg(base, HDMI_CORE_FC_AUDSCHNLS(1),
722 cfg->iec60958_cfg->status[1]);
723
724 /* PCM audio mode */
725 val = (cfg->iec60958_cfg->status[0] & IEC958_AES0_CON_MODE) >> 6;
726 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 6, 4);
727
728 /* Source number */
729 val = cfg->iec60958_cfg->status[2] & IEC958_AES2_CON_SOURCE;
730 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 3, 4);
731
732 /* Channel number right 0 */
733 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 2, 3, 0);
734 /* Channel number right 1*/
735 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 4, 7, 4);
736 /* Channel number right 2 */
737 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(4), 6, 3, 0);
738 /* Channel number right 3*/
739 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(4), 8, 7, 4);
740 /* Channel number left 0 */
741 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(5), 1, 3, 0);
742 /* Channel number left 1*/
743 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(5), 3, 7, 4);
744 /* Channel number left 2 */
745 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(6), 5, 3, 0);
746 /* Channel number left 3*/
747 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(6), 7, 7, 4);
748
749 /* Clock accuracy and sample rate */
750 hdmi_write_reg(base, HDMI_CORE_FC_AUDSCHNLS(7),
751 cfg->iec60958_cfg->status[3]);
752
753 /* Original sample rate and word length */
754 hdmi_write_reg(base, HDMI_CORE_FC_AUDSCHNLS(8),
755 cfg->iec60958_cfg->status[4]);
756
757 /* Enable FIFO empty and full interrupts */
758 REG_FLD_MOD(base, HDMI_CORE_AUD_INT, 3, 3, 2);
759
760 /* Configure GPA */
761 /* select HBR/SPDIF interfaces */
762 if (cfg->layout == HDMI_AUDIO_LAYOUT_2CH) {
763 /* select HBR/SPDIF interfaces */
764 REG_FLD_MOD(base, HDMI_CORE_AUD_CONF0, 0, 5, 5);
765 /* enable two channels in GPA */
766 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF1, 3, 7, 0);
767 } else if (cfg->layout == HDMI_AUDIO_LAYOUT_6CH) {
768 /* select HBR/SPDIF interfaces */
769 REG_FLD_MOD(base, HDMI_CORE_AUD_CONF0, 0, 5, 5);
770 /* enable six channels in GPA */
771 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF1, 0x3F, 7, 0);
772 } else {
773 /* select HBR/SPDIF interfaces */
774 REG_FLD_MOD(base, HDMI_CORE_AUD_CONF0, 0, 5, 5);
775 /* enable eight channels in GPA */
776 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF1, 0xFF, 7, 0);
777 }
778
779 /* disable HBR */
780 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF2, 0, 0, 0);
781 /* enable PCUV */
782 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_CONF2, 1, 1, 1);
783 /* enable GPA FIFO full and empty mask */
784 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_MASK, 3, 1, 0);
785 /* set polarity of GPA FIFO empty interrupts */
786 REG_FLD_MOD(base, HDMI_CORE_AUD_GP_POL, 1, 0, 0);
787
788 /* unmute audio */
789 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCONF, 0, 7, 4);
790}
791
792static void hdmi5_core_audio_infoframe_cfg(struct hdmi_core_data *core,
793 struct snd_cea_861_aud_if *info_aud)
794{
795 void __iomem *base = core->base;
796
797 /* channel count and coding type fields in AUDICONF0 are swapped */
798 hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF0,
799 (info_aud->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CC) << 4 |
800 (info_aud->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CT) >> 4);
801
802 hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF1, info_aud->db2_sf_ss);
803 hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF2, info_aud->db4_ca);
804 hdmi_write_reg(base, HDMI_CORE_FC_AUDICONF3, info_aud->db5_dminh_lsv);
805}
806
807int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
808 struct omap_dss_audio *audio, u32 pclk)
809{
810 struct hdmi_audio_format audio_format;
811 struct hdmi_audio_dma audio_dma;
812 struct hdmi_core_audio_config core_cfg;
813 int err, n, cts, channel_count;
814 unsigned int fs_nr;
815 bool word_length_16b = false;
816
817 if (!audio || !audio->iec || !audio->cea || !core)
818 return -EINVAL;
819
820 core_cfg.iec60958_cfg = audio->iec;
821
822 if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24) &&
823 (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16))
824 word_length_16b = true;
825
826 /* only 16-bit word length supported atm */
827 if (!word_length_16b)
828 return -EINVAL;
829
830 switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
831 case IEC958_AES3_CON_FS_32000:
832 fs_nr = 32000;
833 break;
834 case IEC958_AES3_CON_FS_44100:
835 fs_nr = 44100;
836 break;
837 case IEC958_AES3_CON_FS_48000:
838 fs_nr = 48000;
839 break;
840 case IEC958_AES3_CON_FS_88200:
841 fs_nr = 88200;
842 break;
843 case IEC958_AES3_CON_FS_96000:
844 fs_nr = 96000;
845 break;
846 case IEC958_AES3_CON_FS_176400:
847 fs_nr = 176400;
848 break;
849 case IEC958_AES3_CON_FS_192000:
850 fs_nr = 192000;
851 break;
852 default:
853 return -EINVAL;
854 }
855
856 err = hdmi_compute_acr(pclk, fs_nr, &n, &cts);
857 core_cfg.n = n;
858 core_cfg.cts = cts;
859
860 /* Audio channels settings */
861 channel_count = (audio->cea->db1_ct_cc & CEA861_AUDIO_INFOFRAME_DB1CC)
862 + 1;
863
864 if (channel_count == 2)
865 core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
866 else if (channel_count == 6)
867 core_cfg.layout = HDMI_AUDIO_LAYOUT_6CH;
868 else
869 core_cfg.layout = HDMI_AUDIO_LAYOUT_8CH;
870
871 /* DMA settings */
872 if (word_length_16b)
873 audio_dma.transfer_size = 0x10;
874 else
875 audio_dma.transfer_size = 0x20;
876 audio_dma.block_size = 0xC0;
877 audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
878 audio_dma.fifo_threshold = 0x20; /* in number of samples */
879
880 /* audio FIFO format settings for 16-bit samples*/
881 audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
882 audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
883 audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
884
885 /* only LPCM atm */
886 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
887
888 /* disable start/stop signals of IEC 60958 blocks */
889 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
890
891 /* configure DMA and audio FIFO format*/
892 hdmi_wp_audio_config_dma(wp, &audio_dma);
893 hdmi_wp_audio_config_format(wp, &audio_format);
894
895 /* configure the core */
896 hdmi5_core_audio_config(core, &core_cfg);
897
898 /* configure CEA 861 audio infoframe */
899 hdmi5_core_audio_infoframe_cfg(core, audio->cea);
900
901 return 0;
902}
903#endif
904
905int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
906{
907 struct resource *res;
908
909 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "core");
910 if (!res) {
911 DSSERR("can't get CORE IORESOURCE_MEM HDMI\n");
912 return -EINVAL;
913 }
914
915 core->base = devm_ioremap_resource(&pdev->dev, res);
916 if (IS_ERR(core->base)) {
917 DSSERR("can't ioremap HDMI core\n");
918 return PTR_ERR(core->base);
919 }
920
921 return 0;
922}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.h b/drivers/video/fbdev/omap2/dss/hdmi5_core.h
new file mode 100644
index 000000000000..ce7e9f376f04
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/hdmi5_core.h
@@ -0,0 +1,306 @@
1/*
2 * HDMI driver definition for TI OMAP5 processors.
3 *
4 * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef _HDMI5_CORE_H_
20#define _HDMI5_CORE_H_
21
22#include "hdmi.h"
23
24/* HDMI IP Core System */
25
26/* HDMI Identification */
27#define HDMI_CORE_DESIGN_ID 0x00000
28#define HDMI_CORE_REVISION_ID 0x00004
29#define HDMI_CORE_PRODUCT_ID0 0x00008
30#define HDMI_CORE_PRODUCT_ID1 0x0000C
31#define HDMI_CORE_CONFIG0_ID 0x00010
32#define HDMI_CORE_CONFIG1_ID 0x00014
33#define HDMI_CORE_CONFIG2_ID 0x00018
34#define HDMI_CORE_CONFIG3_ID 0x0001C
35
36/* HDMI Interrupt */
37#define HDMI_CORE_IH_FC_STAT0 0x00400
38#define HDMI_CORE_IH_FC_STAT1 0x00404
39#define HDMI_CORE_IH_FC_STAT2 0x00408
40#define HDMI_CORE_IH_AS_STAT0 0x0040C
41#define HDMI_CORE_IH_PHY_STAT0 0x00410
42#define HDMI_CORE_IH_I2CM_STAT0 0x00414
43#define HDMI_CORE_IH_CEC_STAT0 0x00418
44#define HDMI_CORE_IH_VP_STAT0 0x0041C
45#define HDMI_CORE_IH_I2CMPHY_STAT0 0x00420
46#define HDMI_CORE_IH_MUTE 0x007FC
47
48/* HDMI Video Sampler */
49#define HDMI_CORE_TX_INVID0 0x00800
50#define HDMI_CORE_TX_INSTUFFING 0x00804
51#define HDMI_CORE_TX_RGYDATA0 0x00808
52#define HDMI_CORE_TX_RGYDATA1 0x0080C
53#define HDMI_CORE_TX_RCRDATA0 0x00810
54#define HDMI_CORE_TX_RCRDATA1 0x00814
55#define HDMI_CORE_TX_BCBDATA0 0x00818
56#define HDMI_CORE_TX_BCBDATA1 0x0081C
57
58/* HDMI Video Packetizer */
59#define HDMI_CORE_VP_STATUS 0x02000
60#define HDMI_CORE_VP_PR_CD 0x02004
61#define HDMI_CORE_VP_STUFF 0x02008
62#define HDMI_CORE_VP_REMAP 0x0200C
63#define HDMI_CORE_VP_CONF 0x02010
64#define HDMI_CORE_VP_STAT 0x02014
65#define HDMI_CORE_VP_INT 0x02018
66#define HDMI_CORE_VP_MASK 0x0201C
67#define HDMI_CORE_VP_POL 0x02020
68
69/* Frame Composer */
70#define HDMI_CORE_FC_INVIDCONF 0x04000
71#define HDMI_CORE_FC_INHACTIV0 0x04004
72#define HDMI_CORE_FC_INHACTIV1 0x04008
73#define HDMI_CORE_FC_INHBLANK0 0x0400C
74#define HDMI_CORE_FC_INHBLANK1 0x04010
75#define HDMI_CORE_FC_INVACTIV0 0x04014
76#define HDMI_CORE_FC_INVACTIV1 0x04018
77#define HDMI_CORE_FC_INVBLANK 0x0401C
78#define HDMI_CORE_FC_HSYNCINDELAY0 0x04020
79#define HDMI_CORE_FC_HSYNCINDELAY1 0x04024
80#define HDMI_CORE_FC_HSYNCINWIDTH0 0x04028
81#define HDMI_CORE_FC_HSYNCINWIDTH1 0x0402C
82#define HDMI_CORE_FC_VSYNCINDELAY 0x04030
83#define HDMI_CORE_FC_VSYNCINWIDTH 0x04034
84#define HDMI_CORE_FC_INFREQ0 0x04038
85#define HDMI_CORE_FC_INFREQ1 0x0403C
86#define HDMI_CORE_FC_INFREQ2 0x04040
87#define HDMI_CORE_FC_CTRLDUR 0x04044
88#define HDMI_CORE_FC_EXCTRLDUR 0x04048
89#define HDMI_CORE_FC_EXCTRLSPAC 0x0404C
90#define HDMI_CORE_FC_CH0PREAM 0x04050
91#define HDMI_CORE_FC_CH1PREAM 0x04054
92#define HDMI_CORE_FC_CH2PREAM 0x04058
93#define HDMI_CORE_FC_AVICONF3 0x0405C
94#define HDMI_CORE_FC_GCP 0x04060
95#define HDMI_CORE_FC_AVICONF0 0x04064
96#define HDMI_CORE_FC_AVICONF1 0x04068
97#define HDMI_CORE_FC_AVICONF2 0x0406C
98#define HDMI_CORE_FC_AVIVID 0x04070
99#define HDMI_CORE_FC_AVIETB0 0x04074
100#define HDMI_CORE_FC_AVIETB1 0x04078
101#define HDMI_CORE_FC_AVISBB0 0x0407C
102#define HDMI_CORE_FC_AVISBB1 0x04080
103#define HDMI_CORE_FC_AVIELB0 0x04084
104#define HDMI_CORE_FC_AVIELB1 0x04088
105#define HDMI_CORE_FC_AVISRB0 0x0408C
106#define HDMI_CORE_FC_AVISRB1 0x04090
107#define HDMI_CORE_FC_AUDICONF0 0x04094
108#define HDMI_CORE_FC_AUDICONF1 0x04098
109#define HDMI_CORE_FC_AUDICONF2 0x0409C
110#define HDMI_CORE_FC_AUDICONF3 0x040A0
111#define HDMI_CORE_FC_VSDIEEEID0 0x040A4
112#define HDMI_CORE_FC_VSDSIZE 0x040A8
113#define HDMI_CORE_FC_VSDIEEEID1 0x040C0
114#define HDMI_CORE_FC_VSDIEEEID2 0x040C4
115#define HDMI_CORE_FC_VSDPAYLOAD(n) (n * 4 + 0x040C8)
116#define HDMI_CORE_FC_SPDVENDORNAME(n) (n * 4 + 0x04128)
117#define HDMI_CORE_FC_SPDPRODUCTNAME(n) (n * 4 + 0x04148)
118#define HDMI_CORE_FC_SPDDEVICEINF 0x04188
119#define HDMI_CORE_FC_AUDSCONF 0x0418C
120#define HDMI_CORE_FC_AUDSSTAT 0x04190
121#define HDMI_CORE_FC_AUDSV 0x04194
122#define HDMI_CORE_FC_AUDSU 0x04198
123#define HDMI_CORE_FC_AUDSCHNLS(n) (n * 4 + 0x0419C)
124#define HDMI_CORE_FC_CTRLQHIGH 0x041CC
125#define HDMI_CORE_FC_CTRLQLOW 0x041D0
126#define HDMI_CORE_FC_ACP0 0x041D4
127#define HDMI_CORE_FC_ACP(n) ((16-n) * 4 + 0x04208)
128#define HDMI_CORE_FC_ISCR1_0 0x04248
129#define HDMI_CORE_FC_ISCR1(n) ((16-n) * 4 + 0x0424C)
130#define HDMI_CORE_FC_ISCR2(n) ((15-n) * 4 + 0x0428C)
131#define HDMI_CORE_FC_DATAUTO0 0x042CC
132#define HDMI_CORE_FC_DATAUTO1 0x042D0
133#define HDMI_CORE_FC_DATAUTO2 0x042D4
134#define HDMI_CORE_FC_DATMAN 0x042D8
135#define HDMI_CORE_FC_DATAUTO3 0x042DC
136#define HDMI_CORE_FC_RDRB(n) (n * 4 + 0x042E0)
137#define HDMI_CORE_FC_STAT0 0x04340
138#define HDMI_CORE_FC_INT0 0x04344
139#define HDMI_CORE_FC_MASK0 0x04348
140#define HDMI_CORE_FC_POL0 0x0434C
141#define HDMI_CORE_FC_STAT1 0x04350
142#define HDMI_CORE_FC_INT1 0x04354
143#define HDMI_CORE_FC_MASK1 0x04358
144#define HDMI_CORE_FC_POL1 0x0435C
145#define HDMI_CORE_FC_STAT2 0x04360
146#define HDMI_CORE_FC_INT2 0x04364
147#define HDMI_CORE_FC_MASK2 0x04368
148#define HDMI_CORE_FC_POL2 0x0436C
149#define HDMI_CORE_FC_PRCONF 0x04380
150#define HDMI_CORE_FC_GMD_STAT 0x04400
151#define HDMI_CORE_FC_GMD_EN 0x04404
152#define HDMI_CORE_FC_GMD_UP 0x04408
153#define HDMI_CORE_FC_GMD_CONF 0x0440C
154#define HDMI_CORE_FC_GMD_HB 0x04410
155#define HDMI_CORE_FC_GMD_PB(n) (n * 4 + 0x04414)
156#define HDMI_CORE_FC_DBGFORCE 0x04800
157#define HDMI_CORE_FC_DBGAUD0CH0 0x04804
158#define HDMI_CORE_FC_DBGAUD1CH0 0x04808
159#define HDMI_CORE_FC_DBGAUD2CH0 0x0480C
160#define HDMI_CORE_FC_DBGAUD0CH1 0x04810
161#define HDMI_CORE_FC_DBGAUD1CH1 0x04814
162#define HDMI_CORE_FC_DBGAUD2CH1 0x04818
163#define HDMI_CORE_FC_DBGAUD0CH2 0x0481C
164#define HDMI_CORE_FC_DBGAUD1CH2 0x04820
165#define HDMI_CORE_FC_DBGAUD2CH2 0x04824
166#define HDMI_CORE_FC_DBGAUD0CH3 0x04828
167#define HDMI_CORE_FC_DBGAUD1CH3 0x0482C
168#define HDMI_CORE_FC_DBGAUD2CH3 0x04830
169#define HDMI_CORE_FC_DBGAUD0CH4 0x04834
170#define HDMI_CORE_FC_DBGAUD1CH4 0x04838
171#define HDMI_CORE_FC_DBGAUD2CH4 0x0483C
172#define HDMI_CORE_FC_DBGAUD0CH5 0x04840
173#define HDMI_CORE_FC_DBGAUD1CH5 0x04844
174#define HDMI_CORE_FC_DBGAUD2CH5 0x04848
175#define HDMI_CORE_FC_DBGAUD0CH6 0x0484C
176#define HDMI_CORE_FC_DBGAUD1CH6 0x04850
177#define HDMI_CORE_FC_DBGAUD2CH6 0x04854
178#define HDMI_CORE_FC_DBGAUD0CH7 0x04858
179#define HDMI_CORE_FC_DBGAUD1CH7 0x0485C
180#define HDMI_CORE_FC_DBGAUD2CH7 0x04860
181#define HDMI_CORE_FC_DBGTMDS0 0x04864
182#define HDMI_CORE_FC_DBGTMDS1 0x04868
183#define HDMI_CORE_FC_DBGTMDS2 0x0486C
184#define HDMI_CORE_PHY_MASK0 0x0C018
185#define HDMI_CORE_PHY_I2CM_INT_ADDR 0x0C09C
186#define HDMI_CORE_PHY_I2CM_CTLINT_ADDR 0x0C0A0
187
188/* HDMI Audio */
189#define HDMI_CORE_AUD_CONF0 0x0C400
190#define HDMI_CORE_AUD_CONF1 0x0C404
191#define HDMI_CORE_AUD_INT 0x0C408
192#define HDMI_CORE_AUD_N1 0x0C800
193#define HDMI_CORE_AUD_N2 0x0C804
194#define HDMI_CORE_AUD_N3 0x0C808
195#define HDMI_CORE_AUD_CTS1 0x0C80C
196#define HDMI_CORE_AUD_CTS2 0x0C810
197#define HDMI_CORE_AUD_CTS3 0x0C814
198#define HDMI_CORE_AUD_INCLKFS 0x0C818
199#define HDMI_CORE_AUD_CC08 0x0CC08
200#define HDMI_CORE_AUD_GP_CONF0 0x0D400
201#define HDMI_CORE_AUD_GP_CONF1 0x0D404
202#define HDMI_CORE_AUD_GP_CONF2 0x0D408
203#define HDMI_CORE_AUD_D010 0x0D010
204#define HDMI_CORE_AUD_GP_STAT 0x0D40C
205#define HDMI_CORE_AUD_GP_INT 0x0D410
206#define HDMI_CORE_AUD_GP_POL 0x0D414
207#define HDMI_CORE_AUD_GP_MASK 0x0D418
208
209/* HDMI Main Controller */
210#define HDMI_CORE_MC_CLKDIS 0x10004
211#define HDMI_CORE_MC_SWRSTZREQ 0x10008
212#define HDMI_CORE_MC_FLOWCTRL 0x10010
213#define HDMI_CORE_MC_PHYRSTZ 0x10014
214#define HDMI_CORE_MC_LOCKONCLOCK 0x10018
215
216/* HDMI COLOR SPACE CONVERTER */
217#define HDMI_CORE_CSC_CFG 0x10400
218#define HDMI_CORE_CSC_SCALE 0x10404
219#define HDMI_CORE_CSC_COEF_A1_MSB 0x10408
220#define HDMI_CORE_CSC_COEF_A1_LSB 0x1040C
221#define HDMI_CORE_CSC_COEF_A2_MSB 0x10410
222#define HDMI_CORE_CSC_COEF_A2_LSB 0x10414
223#define HDMI_CORE_CSC_COEF_A3_MSB 0x10418
224#define HDMI_CORE_CSC_COEF_A3_LSB 0x1041C
225#define HDMI_CORE_CSC_COEF_A4_MSB 0x10420
226#define HDMI_CORE_CSC_COEF_A4_LSB 0x10424
227#define HDMI_CORE_CSC_COEF_B1_MSB 0x10428
228#define HDMI_CORE_CSC_COEF_B1_LSB 0x1042C
229#define HDMI_CORE_CSC_COEF_B2_MSB 0x10430
230#define HDMI_CORE_CSC_COEF_B2_LSB 0x10434
231#define HDMI_CORE_CSC_COEF_B3_MSB 0x10438
232#define HDMI_CORE_CSC_COEF_B3_LSB 0x1043C
233#define HDMI_CORE_CSC_COEF_B4_MSB 0x10440
234#define HDMI_CORE_CSC_COEF_B4_LSB 0x10444
235#define HDMI_CORE_CSC_COEF_C1_MSB 0x10448
236#define HDMI_CORE_CSC_COEF_C1_LSB 0x1044C
237#define HDMI_CORE_CSC_COEF_C2_MSB 0x10450
238#define HDMI_CORE_CSC_COEF_C2_LSB 0x10454
239#define HDMI_CORE_CSC_COEF_C3_MSB 0x10458
240#define HDMI_CORE_CSC_COEF_C3_LSB 0x1045C
241#define HDMI_CORE_CSC_COEF_C4_MSB 0x10460
242#define HDMI_CORE_CSC_COEF_C4_LSB 0x10464
243
244/* HDMI HDCP */
245#define HDMI_CORE_HDCP_MASK 0x14020
246
247/* HDMI CEC */
248#define HDMI_CORE_CEC_MASK 0x17408
249
250/* HDMI I2C Master */
251#define HDMI_CORE_I2CM_SLAVE 0x157C8
252#define HDMI_CORE_I2CM_ADDRESS 0x157CC
253#define HDMI_CORE_I2CM_DATAO 0x157D0
254#define HDMI_CORE_I2CM_DATAI 0X157D4
255#define HDMI_CORE_I2CM_OPERATION 0x157D8
256#define HDMI_CORE_I2CM_INT 0x157DC
257#define HDMI_CORE_I2CM_CTLINT 0x157E0
258#define HDMI_CORE_I2CM_DIV 0x157E4
259#define HDMI_CORE_I2CM_SEGADDR 0x157E8
260#define HDMI_CORE_I2CM_SOFTRSTZ 0x157EC
261#define HDMI_CORE_I2CM_SEGPTR 0x157F0
262#define HDMI_CORE_I2CM_SS_SCL_HCNT_1_ADDR 0x157F4
263#define HDMI_CORE_I2CM_SS_SCL_HCNT_0_ADDR 0x157F8
264#define HDMI_CORE_I2CM_SS_SCL_LCNT_1_ADDR 0x157FC
265#define HDMI_CORE_I2CM_SS_SCL_LCNT_0_ADDR 0x15800
266#define HDMI_CORE_I2CM_FS_SCL_HCNT_1_ADDR 0x15804
267#define HDMI_CORE_I2CM_FS_SCL_HCNT_0_ADDR 0x15808
268#define HDMI_CORE_I2CM_FS_SCL_LCNT_1_ADDR 0x1580C
269#define HDMI_CORE_I2CM_FS_SCL_LCNT_0_ADDR 0x15810
270#define HDMI_CORE_I2CM_SDA_HOLD_ADDR 0x15814
271
272enum hdmi_core_packet_mode {
273 HDMI_PACKETMODERESERVEDVALUE = 0,
274 HDMI_PACKETMODE24BITPERPIXEL = 4,
275 HDMI_PACKETMODE30BITPERPIXEL = 5,
276 HDMI_PACKETMODE36BITPERPIXEL = 6,
277 HDMI_PACKETMODE48BITPERPIXEL = 7,
278};
279
280struct hdmi_core_vid_config {
281 struct hdmi_config v_fc_config;
282 enum hdmi_core_packet_mode packet_mode;
283 int data_enable_pol;
284 int vblank_osc;
285 int hblank;
286 int vblank;
287};
288
289struct csc_table {
290 u16 a1, a2, a3, a4;
291 u16 b1, b2, b3, b4;
292 u16 c1, c2, c3, c4;
293};
294
295int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len);
296void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s);
297int hdmi5_core_handle_irqs(struct hdmi_core_data *core);
298void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
299 struct hdmi_config *cfg);
300int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
301
302#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
303int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
304 struct omap_dss_audio *audio, u32 pclk);
305#endif
306#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_common.c b/drivers/video/fbdev/omap2/dss/hdmi_common.c
index 0b12a3f62fe1..9a2c39cf297f 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_common.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_common.c
@@ -17,6 +17,7 @@
17 17
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/err.h> 19#include <linux/err.h>
20#include <linux/of.h>
20#include <video/omapdss.h> 21#include <video/omapdss.h>
21 22
22#include "hdmi.h" 23#include "hdmi.h"
@@ -323,6 +324,46 @@ end:
323 return cm; 324 return cm;
324} 325}
325 326
327int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
328 struct hdmi_phy_data *phy)
329{
330 struct property *prop;
331 int r, len;
332
333 prop = of_find_property(ep, "lanes", &len);
334 if (prop) {
335 u32 lanes[8];
336
337 if (len / sizeof(u32) != ARRAY_SIZE(lanes)) {
338 dev_err(&pdev->dev, "bad number of lanes\n");
339 return -EINVAL;
340 }
341
342 r = of_property_read_u32_array(ep, "lanes", lanes,
343 ARRAY_SIZE(lanes));
344 if (r) {
345 dev_err(&pdev->dev, "failed to read lane data\n");
346 return r;
347 }
348
349 r = hdmi_phy_parse_lanes(phy, lanes);
350 if (r) {
351 dev_err(&pdev->dev, "failed to parse lane data\n");
352 return r;
353 }
354 } else {
355 static const u32 default_lanes[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
356
357 r = hdmi_phy_parse_lanes(phy, default_lanes);
358 if (WARN_ON(r)) {
359 dev_err(&pdev->dev, "failed to parse lane data\n");
360 return r;
361 }
362 }
363
364 return 0;
365}
366
326#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 367#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
327int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) 368int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
328{ 369{
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
index dd376ce8da01..e007ac892d79 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_phy.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
@@ -12,11 +12,22 @@
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/slab.h>
15#include <video/omapdss.h> 16#include <video/omapdss.h>
16 17
17#include "dss.h" 18#include "dss.h"
18#include "hdmi.h" 19#include "hdmi.h"
19 20
21struct hdmi_phy_features {
22 bool bist_ctrl;
23 bool calc_freqout;
24 bool ldo_voltage;
25 unsigned long dcofreq_min;
26 unsigned long max_phy;
27};
28
29static const struct hdmi_phy_features *phy_feat;
30
20void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s) 31void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
21{ 32{
22#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\ 33#define DUMPPHY(r) seq_printf(s, "%-35s %08x\n", #r,\
@@ -26,53 +37,104 @@ void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s)
26 DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL); 37 DUMPPHY(HDMI_TXPHY_DIGITAL_CTRL);
27 DUMPPHY(HDMI_TXPHY_POWER_CTRL); 38 DUMPPHY(HDMI_TXPHY_POWER_CTRL);
28 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL); 39 DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
40 if (phy_feat->bist_ctrl)
41 DUMPPHY(HDMI_TXPHY_BIST_CONTROL);
29} 42}
30 43
31static irqreturn_t hdmi_irq_handler(int irq, void *data) 44int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes)
32{ 45{
33 struct hdmi_wp_data *wp = data; 46 int i;
34 u32 irqstatus; 47
35 48 for (i = 0; i < 8; i += 2) {
36 irqstatus = hdmi_wp_get_irqstatus(wp); 49 u8 lane, pol;
37 hdmi_wp_set_irqstatus(wp, irqstatus); 50 int dx, dy;
38 51
39 if ((irqstatus & HDMI_IRQ_LINK_CONNECT) && 52 dx = lanes[i];
40 irqstatus & HDMI_IRQ_LINK_DISCONNECT) { 53 dy = lanes[i + 1];
41 /* 54
42 * If we get both connect and disconnect interrupts at the same 55 if (dx < 0 || dx >= 8)
43 * time, turn off the PHY, clear interrupts, and restart, which 56 return -EINVAL;
44 * raises connect interrupt if a cable is connected, or nothing 57
45 * if cable is not connected. 58 if (dy < 0 || dy >= 8)
46 */ 59 return -EINVAL;
47 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); 60
48 61 if (dx & 1) {
49 hdmi_wp_set_irqstatus(wp, HDMI_IRQ_LINK_CONNECT | 62 if (dy != dx - 1)
50 HDMI_IRQ_LINK_DISCONNECT); 63 return -EINVAL;
51 64 pol = 1;
52 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 65 } else {
53 } else if (irqstatus & HDMI_IRQ_LINK_CONNECT) { 66 if (dy != dx + 1)
54 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_TXON); 67 return -EINVAL;
55 } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { 68 pol = 0;
56 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 69 }
70
71 lane = dx / 2;
72
73 phy->lane_function[lane] = i / 2;
74 phy->lane_polarity[lane] = pol;
57 } 75 }
58 76
59 return IRQ_HANDLED; 77 return 0;
60} 78}
61 79
62int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp, 80static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
63 struct hdmi_config *cfg)
64{ 81{
65 u16 r = 0; 82 static const u16 pad_cfg_list[] = {
66 u32 irqstatus; 83 0x0123,
67 84 0x0132,
68 hdmi_wp_clear_irqenable(wp, 0xffffffff); 85 0x0312,
69 86 0x0321,
70 irqstatus = hdmi_wp_get_irqstatus(wp); 87 0x0231,
71 hdmi_wp_set_irqstatus(wp, irqstatus); 88 0x0213,
89 0x1023,
90 0x1032,
91 0x3012,
92 0x3021,
93 0x2031,
94 0x2013,
95 0x1203,
96 0x1302,
97 0x3102,
98 0x3201,
99 0x2301,
100 0x2103,
101 0x1230,
102 0x1320,
103 0x3120,
104 0x3210,
105 0x2310,
106 0x2130,
107 };
108
109 u16 lane_cfg = 0;
110 int i;
111 unsigned lane_cfg_val;
112 u16 pol_val = 0;
113
114 for (i = 0; i < 4; ++i)
115 lane_cfg |= phy->lane_function[i] << ((3 - i) * 4);
116
117 pol_val |= phy->lane_polarity[0] << 0;
118 pol_val |= phy->lane_polarity[1] << 3;
119 pol_val |= phy->lane_polarity[2] << 2;
120 pol_val |= phy->lane_polarity[3] << 1;
121
122 for (i = 0; i < ARRAY_SIZE(pad_cfg_list); ++i)
123 if (pad_cfg_list[i] == lane_cfg)
124 break;
125
126 if (WARN_ON(i == ARRAY_SIZE(pad_cfg_list)))
127 i = 0;
128
129 lane_cfg_val = i;
130
131 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, lane_cfg_val, 26, 22);
132 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27);
133}
72 134
73 r = hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); 135int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
74 if (r) 136{
75 return r; 137 u8 freqout;
76 138
77 /* 139 /*
78 * Read address 0 in order to get the SCP reset done completed 140 * Read address 0 in order to get the SCP reset done completed
@@ -81,79 +143,112 @@ int hdmi_phy_enable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp,
81 hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL); 143 hdmi_read_reg(phy->base, HDMI_TXPHY_TX_CTRL);
82 144
83 /* 145 /*
146 * In OMAP5+, the HFBITCLK must be divided by 2 before issuing the
147 * HDMI_PHYPWRCMD_LDOON command.
148 */
149 if (phy_feat->bist_ctrl)
150 REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11);
151
152 if (phy_feat->calc_freqout) {
153 /* DCOCLK/10 is pixel clock, compare pclk with DCOCLK_MIN/10 */
154 u32 dco_min = phy_feat->dcofreq_min / 10;
155 u32 pclk = cfg->timings.pixelclock;
156
157 if (pclk < dco_min)
158 freqout = 0;
159 else if ((pclk >= dco_min) && (pclk < phy_feat->max_phy))
160 freqout = 1;
161 else
162 freqout = 2;
163 } else {
164 freqout = 1;
165 }
166
167 /*
84 * Write to phy address 0 to configure the clock 168 * Write to phy address 0 to configure the clock
85 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field 169 * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field
86 */ 170 */
87 REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); 171 REG_FLD_MOD(phy->base, HDMI_TXPHY_TX_CTRL, freqout, 31, 30);
88 172
89 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ 173 /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */
90 hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); 174 hdmi_write_reg(phy->base, HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000);
91 175
92 /* Setup max LDO voltage */ 176 /* Setup max LDO voltage */
93 REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); 177 if (phy_feat->ldo_voltage)
178 REG_FLD_MOD(phy->base, HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0);
94 179
95 /* Write to phy address 3 to change the polarity control */ 180 hdmi_phy_configure_lanes(phy);
96 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
97
98 r = request_threaded_irq(phy->irq, NULL, hdmi_irq_handler,
99 IRQF_ONESHOT, "OMAP HDMI", wp);
100 if (r) {
101 DSSERR("HDMI IRQ request failed\n");
102 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF);
103 return r;
104 }
105
106 hdmi_wp_set_irqenable(wp,
107 HDMI_IRQ_LINK_CONNECT | HDMI_IRQ_LINK_DISCONNECT);
108 181
109 return 0; 182 return 0;
110} 183}
111 184
112void hdmi_phy_disable(struct hdmi_phy_data *phy, struct hdmi_wp_data *wp) 185static const struct hdmi_phy_features omap44xx_phy_feats = {
186 .bist_ctrl = false,
187 .calc_freqout = false,
188 .ldo_voltage = true,
189 .dcofreq_min = 500000000,
190 .max_phy = 185675000,
191};
192
193static const struct hdmi_phy_features omap54xx_phy_feats = {
194 .bist_ctrl = true,
195 .calc_freqout = true,
196 .ldo_voltage = false,
197 .dcofreq_min = 750000000,
198 .max_phy = 186000000,
199};
200
201static int hdmi_phy_init_features(struct platform_device *pdev)
113{ 202{
114 free_irq(phy->irq, wp); 203 struct hdmi_phy_features *dst;
204 const struct hdmi_phy_features *src;
115 205
116 hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_OFF); 206 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
117} 207 if (!dst) {
208 dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n");
209 return -ENOMEM;
210 }
211
212 switch (omapdss_get_version()) {
213 case OMAPDSS_VER_OMAP4430_ES1:
214 case OMAPDSS_VER_OMAP4430_ES2:
215 case OMAPDSS_VER_OMAP4:
216 src = &omap44xx_phy_feats;
217 break;
118 218
119#define PHY_OFFSET 0x300 219 case OMAPDSS_VER_OMAP5:
120#define PHY_SIZE 0x100 220 src = &omap54xx_phy_feats;
221 break;
222
223 default:
224 return -ENODEV;
225 }
226
227 memcpy(dst, src, sizeof(*dst));
228 phy_feat = dst;
229
230 return 0;
231}
121 232
122int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy) 233int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy)
123{ 234{
235 int r;
124 struct resource *res; 236 struct resource *res;
125 struct resource temp_res; 237
238 r = hdmi_phy_init_features(pdev);
239 if (r)
240 return r;
126 241
127 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); 242 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
128 if (!res) { 243 if (!res) {
129 DSSDBG("can't get PHY mem resource by name\n"); 244 DSSERR("can't get PHY mem resource\n");
130 /* 245 return -EINVAL;
131 * if hwmod/DT doesn't have the memory resource information
132 * split into HDMI sub blocks by name, we try again by getting
133 * the platform's first resource. this code will be removed when
134 * the driver can get the mem resources by name
135 */
136 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
137 if (!res) {
138 DSSERR("can't get PHY mem resource\n");
139 return -EINVAL;
140 }
141
142 temp_res.start = res->start + PHY_OFFSET;
143 temp_res.end = temp_res.start + PHY_SIZE - 1;
144 res = &temp_res;
145 } 246 }
146 247
147 phy->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 248 phy->base = devm_ioremap_resource(&pdev->dev, res);
148 if (!phy->base) { 249 if (IS_ERR(phy->base)) {
149 DSSERR("can't ioremap TX PHY\n"); 250 DSSERR("can't ioremap TX PHY\n");
150 return -ENOMEM; 251 return PTR_ERR(phy->base);
151 }
152
153 phy->irq = platform_get_irq(pdev, 0);
154 if (phy->irq < 0) {
155 DSSERR("platform_get_irq failed\n");
156 return -ENODEV;
157 } 252 }
158 253
159 return 0; 254 return 0;
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
index 5fc71215c303..54df12a8d744 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
@@ -23,6 +23,18 @@
23#define HDMI_DEFAULT_REGN 16 23#define HDMI_DEFAULT_REGN 16
24#define HDMI_DEFAULT_REGM2 1 24#define HDMI_DEFAULT_REGM2 1
25 25
26struct hdmi_pll_features {
27 bool sys_reset;
28 /* this is a hack, need to replace it with a better computation of M2 */
29 bool bound_dcofreq;
30 unsigned long fint_min, fint_max;
31 u16 regm_max;
32 unsigned long dcofreq_low_min, dcofreq_low_max;
33 unsigned long dcofreq_high_min, dcofreq_high_max;
34};
35
36static const struct hdmi_pll_features *pll_feat;
37
26void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) 38void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
27{ 39{
28#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ 40#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
@@ -57,7 +69,11 @@ void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy)
57 69
58 refclk = clkin / pi->regn; 70 refclk = clkin / pi->regn;
59 71
60 pi->regm2 = HDMI_DEFAULT_REGM2; 72 /* temorary hack to make sure DCO freq isn't calculated too low */
73 if (pll_feat->bound_dcofreq && phy <= 65000)
74 pi->regm2 = 3;
75 else
76 pi->regm2 = HDMI_DEFAULT_REGM2;
61 77
62 /* 78 /*
63 * multiplier is pixel_clk/ref_clk 79 * multiplier is pixel_clk/ref_clk
@@ -154,7 +170,7 @@ static int hdmi_pll_config(struct hdmi_pll_data *pll)
154static int hdmi_pll_reset(struct hdmi_pll_data *pll) 170static int hdmi_pll_reset(struct hdmi_pll_data *pll)
155{ 171{
156 /* SYSRESET controlled by power FSM */ 172 /* SYSRESET controlled by power FSM */
157 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 3, 3); 173 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, pll_feat->sys_reset, 3, 3);
158 174
159 /* READ 0x0 reset is in progress */ 175 /* READ 0x0 reset is in progress */
160 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1) 176 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
@@ -194,38 +210,81 @@ void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
194 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); 210 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
195} 211}
196 212
197#define PLL_OFFSET 0x200 213static const struct hdmi_pll_features omap44xx_pll_feats = {
198#define PLL_SIZE 0x100 214 .sys_reset = false,
215 .bound_dcofreq = false,
216 .fint_min = 500000,
217 .fint_max = 2500000,
218 .regm_max = 4095,
219 .dcofreq_low_min = 500000000,
220 .dcofreq_low_max = 1000000000,
221 .dcofreq_high_min = 1000000000,
222 .dcofreq_high_max = 2000000000,
223};
224
225static const struct hdmi_pll_features omap54xx_pll_feats = {
226 .sys_reset = true,
227 .bound_dcofreq = true,
228 .fint_min = 620000,
229 .fint_max = 2500000,
230 .regm_max = 2046,
231 .dcofreq_low_min = 750000000,
232 .dcofreq_low_max = 1500000000,
233 .dcofreq_high_min = 1250000000,
234 .dcofreq_high_max = 2500000000UL,
235};
236
237static int hdmi_pll_init_features(struct platform_device *pdev)
238{
239 struct hdmi_pll_features *dst;
240 const struct hdmi_pll_features *src;
241
242 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
243 if (!dst) {
244 dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n");
245 return -ENOMEM;
246 }
247
248 switch (omapdss_get_version()) {
249 case OMAPDSS_VER_OMAP4430_ES1:
250 case OMAPDSS_VER_OMAP4430_ES2:
251 case OMAPDSS_VER_OMAP4:
252 src = &omap44xx_pll_feats;
253 break;
254
255 case OMAPDSS_VER_OMAP5:
256 src = &omap54xx_pll_feats;
257 break;
258
259 default:
260 return -ENODEV;
261 }
262
263 memcpy(dst, src, sizeof(*dst));
264 pll_feat = dst;
265
266 return 0;
267}
199 268
200int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) 269int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
201{ 270{
271 int r;
202 struct resource *res; 272 struct resource *res;
203 struct resource temp_res; 273
274 r = hdmi_pll_init_features(pdev);
275 if (r)
276 return r;
204 277
205 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); 278 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
206 if (!res) { 279 if (!res) {
207 DSSDBG("can't get PLL mem resource by name\n"); 280 DSSERR("can't get PLL mem resource\n");
208 /* 281 return -EINVAL;
209 * if hwmod/DT doesn't have the memory resource information
210 * split into HDMI sub blocks by name, we try again by getting
211 * the platform's first resource. this code will be removed when
212 * the driver can get the mem resources by name
213 */
214 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
215 if (!res) {
216 DSSERR("can't get PLL mem resource\n");
217 return -EINVAL;
218 }
219
220 temp_res.start = res->start + PLL_OFFSET;
221 temp_res.end = temp_res.start + PLL_SIZE - 1;
222 res = &temp_res;
223 } 282 }
224 283
225 pll->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 284 pll->base = devm_ioremap_resource(&pdev->dev, res);
226 if (!pll->base) { 285 if (IS_ERR(pll->base)) {
227 DSSERR("can't ioremap PLLCTRL\n"); 286 DSSERR("can't ioremap PLLCTRL\n");
228 return -ENOMEM; 287 return PTR_ERR(pll->base);
229 } 288 }
230 289
231 return 0; 290 return 0;
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
index f5f4ccf50d90..496327e2b21b 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_wp.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
@@ -185,7 +185,7 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
185 timings->interlace = param->timings.interlace; 185 timings->interlace = param->timings.interlace;
186} 186}
187 187
188#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) 188#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
189void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, 189void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
190 struct hdmi_audio_format *aud_fmt) 190 struct hdmi_audio_format *aud_fmt)
191{ 191{
@@ -238,37 +238,20 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
238} 238}
239#endif 239#endif
240 240
241#define WP_SIZE 0x200
242
243int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) 241int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
244{ 242{
245 struct resource *res; 243 struct resource *res;
246 struct resource temp_res;
247 244
248 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp"); 245 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wp");
249 if (!res) { 246 if (!res) {
250 DSSDBG("can't get WP mem resource by name\n"); 247 DSSERR("can't get WP mem resource\n");
251 /* 248 return -EINVAL;
252 * if hwmod/DT doesn't have the memory resource information
253 * split into HDMI sub blocks by name, we try again by getting
254 * the platform's first resource. this code will be removed when
255 * the driver can get the mem resources by name
256 */
257 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
258 if (!res) {
259 DSSERR("can't get WP mem resource\n");
260 return -EINVAL;
261 }
262
263 temp_res.start = res->start;
264 temp_res.end = temp_res.start + WP_SIZE - 1;
265 res = &temp_res;
266 } 249 }
267 250
268 wp->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 251 wp->base = devm_ioremap_resource(&pdev->dev, res);
269 if (!wp->base) { 252 if (IS_ERR(wp->base)) {
270 DSSERR("can't ioremap HDMI WP\n"); 253 DSSERR("can't ioremap HDMI WP\n");
271 return -ENOMEM; 254 return PTR_ERR(wp->base);
272 } 255 }
273 256
274 return 0; 257 return 0;
diff --git a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
new file mode 100644
index 000000000000..99af9e88b2d8
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c
@@ -0,0 +1,229 @@
1/*
2 * Copyright (C) 2014 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * As omapdss panel drivers are omapdss specific, but we want to define the
20 * DT-data in generic manner, we convert the compatible strings of the panel and
21 * encoder nodes from "panel-foo" to "omapdss,panel-foo". This way we can have
22 * both correct DT data and omapdss specific drivers.
23 *
24 * When we get generic panel drivers to the kernel, this file will be removed.
25 */
26
27#include <linux/kernel.h>
28#include <linux/of.h>
29#include <linux/of_graph.h>
30#include <linux/slab.h>
31#include <linux/list.h>
32
33static struct list_head dss_conv_list __initdata;
34
35static const char prefix[] __initconst = "omapdss,";
36
37struct dss_conv_node {
38 struct list_head list;
39 struct device_node *node;
40 bool root;
41};
42
43static int __init omapdss_count_strings(const struct property *prop)
44{
45 const char *p = prop->value;
46 int l = 0, total = 0;
47 int i;
48
49 for (i = 0; total < prop->length; total += l, p += l, i++)
50 l = strlen(p) + 1;
51
52 return i;
53}
54
55static void __init omapdss_update_prop(struct device_node *node, char *compat,
56 int len)
57{
58 struct property *prop;
59
60 prop = kzalloc(sizeof(*prop), GFP_KERNEL);
61 if (!prop)
62 return;
63
64 prop->name = "compatible";
65 prop->value = compat;
66 prop->length = len;
67
68 of_update_property(node, prop);
69}
70
71static void __init omapdss_prefix_strcpy(char *dst, int dst_len,
72 const char *src, int src_len)
73{
74 size_t total = 0;
75
76 while (total < src_len) {
77 size_t l = strlen(src) + 1;
78
79 strcpy(dst, prefix);
80 dst += strlen(prefix);
81
82 strcpy(dst, src);
83 dst += l;
84
85 src += l;
86 total += l;
87 }
88}
89
90/* prepend compatible property strings with "omapdss," */
91static void __init omapdss_omapify_node(struct device_node *node)
92{
93 struct property *prop;
94 char *new_compat;
95 int num_strs;
96 int new_len;
97
98 prop = of_find_property(node, "compatible", NULL);
99
100 if (!prop || !prop->value)
101 return;
102
103 if (strnlen(prop->value, prop->length) >= prop->length)
104 return;
105
106 /* is it already prefixed? */
107 if (strncmp(prefix, prop->value, strlen(prefix)) == 0)
108 return;
109
110 num_strs = omapdss_count_strings(prop);
111
112 new_len = prop->length + strlen(prefix) * num_strs;
113 new_compat = kmalloc(new_len, GFP_KERNEL);
114
115 omapdss_prefix_strcpy(new_compat, new_len, prop->value, prop->length);
116
117 omapdss_update_prop(node, new_compat, new_len);
118}
119
120static void __init omapdss_add_to_list(struct device_node *node, bool root)
121{
122 struct dss_conv_node *n = kmalloc(sizeof(struct dss_conv_node),
123 GFP_KERNEL);
124 n->node = node;
125 n->root = root;
126 list_add(&n->list, &dss_conv_list);
127}
128
129static bool __init omapdss_list_contains(const struct device_node *node)
130{
131 struct dss_conv_node *n;
132
133 list_for_each_entry(n, &dss_conv_list, list) {
134 if (n->node == node)
135 return true;
136 }
137
138 return false;
139}
140
141static void __init omapdss_walk_device(struct device_node *node, bool root)
142{
143 struct device_node *n;
144
145 omapdss_add_to_list(node, root);
146
147 /*
148 * of_graph_get_remote_port_parent() prints an error if there is no
149 * port/ports node. To avoid that, check first that there's the node.
150 */
151 n = of_get_child_by_name(node, "ports");
152 if (!n)
153 n = of_get_child_by_name(node, "port");
154 if (!n)
155 return;
156
157 of_node_put(n);
158
159 n = NULL;
160 while ((n = of_graph_get_next_endpoint(node, n)) != NULL) {
161 struct device_node *pn;
162
163 pn = of_graph_get_remote_port_parent(n);
164
165 if (!pn) {
166 of_node_put(n);
167 continue;
168 }
169
170 if (!of_device_is_available(pn) || omapdss_list_contains(pn)) {
171 of_node_put(pn);
172 of_node_put(n);
173 continue;
174 }
175
176 omapdss_walk_device(pn, false);
177
178 of_node_put(n);
179 }
180}
181
182static const struct of_device_id omapdss_of_match[] __initconst = {
183 { .compatible = "ti,omap2-dss", },
184 { .compatible = "ti,omap3-dss", },
185 { .compatible = "ti,omap4-dss", },
186 { .compatible = "ti,omap5-dss", },
187 {},
188};
189
190static int __init omapdss_boot_init(void)
191{
192 struct device_node *dss, *child;
193
194 INIT_LIST_HEAD(&dss_conv_list);
195
196 dss = of_find_matching_node(NULL, omapdss_of_match);
197
198 if (dss == NULL || !of_device_is_available(dss))
199 return 0;
200
201 omapdss_walk_device(dss, true);
202
203 for_each_available_child_of_node(dss, child) {
204 if (!of_find_property(child, "compatible", NULL)) {
205 of_node_put(child);
206 continue;
207 }
208
209 omapdss_walk_device(child, true);
210 }
211
212 while (!list_empty(&dss_conv_list)) {
213 struct dss_conv_node *n;
214
215 n = list_first_entry(&dss_conv_list, struct dss_conv_node,
216 list);
217
218 if (!n->root)
219 omapdss_omapify_node(n->node);
220
221 list_del(&n->list);
222 of_node_put(n->node);
223 kfree(n);
224 }
225
226 return 0;
227}
228
229subsys_initcall(omapdss_boot_init);
diff --git a/drivers/video/fbdev/omap2/dss/venc_panel.c b/drivers/video/fbdev/omap2/dss/venc_panel.c
deleted file mode 100644
index af68cd444d7e..000000000000
--- a/drivers/video/fbdev/omap2/dss/venc_panel.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * VENC panel driver
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <linux/err.h>
22#include <linux/io.h>
23#include <linux/mutex.h>
24#include <linux/module.h>
25
26#include <video/omapdss.h>
27
28#include "dss.h"
29
30static struct {
31 struct mutex lock;
32} venc_panel;
33
34static ssize_t display_output_type_show(struct device *dev,
35 struct device_attribute *attr, char *buf)
36{
37 struct omap_dss_device *dssdev = to_dss_device(dev);
38 const char *ret;
39
40 switch (dssdev->phy.venc.type) {
41 case OMAP_DSS_VENC_TYPE_COMPOSITE:
42 ret = "composite";
43 break;
44 case OMAP_DSS_VENC_TYPE_SVIDEO:
45 ret = "svideo";
46 break;
47 default:
48 return -EINVAL;
49 }
50
51 return snprintf(buf, PAGE_SIZE, "%s\n", ret);
52}
53
54static ssize_t display_output_type_store(struct device *dev,
55 struct device_attribute *attr, const char *buf, size_t size)
56{
57 struct omap_dss_device *dssdev = to_dss_device(dev);
58 enum omap_dss_venc_type new_type;
59
60 if (sysfs_streq("composite", buf))
61 new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
62 else if (sysfs_streq("svideo", buf))
63 new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
64 else
65 return -EINVAL;
66
67 mutex_lock(&venc_panel.lock);
68
69 if (dssdev->phy.venc.type != new_type) {
70 dssdev->phy.venc.type = new_type;
71 omapdss_venc_set_type(dssdev, new_type);
72 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
73 omapdss_venc_display_disable(dssdev);
74 omapdss_venc_display_enable(dssdev);
75 }
76 }
77
78 mutex_unlock(&venc_panel.lock);
79
80 return size;
81}
82
83static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
84 display_output_type_show, display_output_type_store);
85
86static int venc_panel_probe(struct omap_dss_device *dssdev)
87{
88 /* set default timings to PAL */
89 const struct omap_video_timings default_timings = {
90 .x_res = 720,
91 .y_res = 574,
92 .pixelclock = 13500000,
93 .hsw = 64,
94 .hfp = 12,
95 .hbp = 68,
96 .vsw = 5,
97 .vfp = 5,
98 .vbp = 41,
99
100 .vsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
101 .hsync_level = OMAPDSS_SIG_ACTIVE_HIGH,
102
103 .interlace = true,
104 };
105
106 mutex_init(&venc_panel.lock);
107
108 dssdev->panel.timings = default_timings;
109
110 return device_create_file(dssdev->dev, &dev_attr_output_type);
111}
112
113static void venc_panel_remove(struct omap_dss_device *dssdev)
114{
115 device_remove_file(dssdev->dev, &dev_attr_output_type);
116}
117
118static int venc_panel_enable(struct omap_dss_device *dssdev)
119{
120 int r;
121
122 dev_dbg(dssdev->dev, "venc_panel_enable\n");
123
124 mutex_lock(&venc_panel.lock);
125
126 if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
127 r = -EINVAL;
128 goto err;
129 }
130
131 omapdss_venc_set_timings(dssdev, &dssdev->panel.timings);
132 omapdss_venc_set_type(dssdev, dssdev->phy.venc.type);
133 omapdss_venc_invert_vid_out_polarity(dssdev,
134 dssdev->phy.venc.invert_polarity);
135
136 r = omapdss_venc_display_enable(dssdev);
137 if (r)
138 goto err;
139
140 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
141
142 mutex_unlock(&venc_panel.lock);
143
144 return 0;
145err:
146 mutex_unlock(&venc_panel.lock);
147
148 return r;
149}
150
151static void venc_panel_disable(struct omap_dss_device *dssdev)
152{
153 dev_dbg(dssdev->dev, "venc_panel_disable\n");
154
155 mutex_lock(&venc_panel.lock);
156
157 if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
158 goto end;
159
160 omapdss_venc_display_disable(dssdev);
161
162 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
163end:
164 mutex_unlock(&venc_panel.lock);
165}
166
167static void venc_panel_set_timings(struct omap_dss_device *dssdev,
168 struct omap_video_timings *timings)
169{
170 dev_dbg(dssdev->dev, "venc_panel_set_timings\n");
171
172 mutex_lock(&venc_panel.lock);
173
174 omapdss_venc_set_timings(dssdev, timings);
175 dssdev->panel.timings = *timings;
176
177 mutex_unlock(&venc_panel.lock);
178}
179
180static int venc_panel_check_timings(struct omap_dss_device *dssdev,
181 struct omap_video_timings *timings)
182{
183 dev_dbg(dssdev->dev, "venc_panel_check_timings\n");
184
185 return omapdss_venc_check_timings(dssdev, timings);
186}
187
188static u32 venc_panel_get_wss(struct omap_dss_device *dssdev)
189{
190 dev_dbg(dssdev->dev, "venc_panel_get_wss\n");
191
192 return omapdss_venc_get_wss(dssdev);
193}
194
195static int venc_panel_set_wss(struct omap_dss_device *dssdev, u32 wss)
196{
197 dev_dbg(dssdev->dev, "venc_panel_set_wss\n");
198
199 return omapdss_venc_set_wss(dssdev, wss);
200}
201
202static struct omap_dss_driver venc_driver = {
203 .probe = venc_panel_probe,
204 .remove = venc_panel_remove,
205
206 .enable = venc_panel_enable,
207 .disable = venc_panel_disable,
208
209 .get_resolution = omapdss_default_get_resolution,
210 .get_recommended_bpp = omapdss_default_get_recommended_bpp,
211
212 .set_timings = venc_panel_set_timings,
213 .check_timings = venc_panel_check_timings,
214
215 .get_wss = venc_panel_get_wss,
216 .set_wss = venc_panel_set_wss,
217
218 .driver = {
219 .name = "venc",
220 .owner = THIS_MODULE,
221 },
222};
223
224int venc_panel_init(void)
225{
226 return omap_dss_register_driver(&venc_driver);
227}
228
229void venc_panel_exit(void)
230{
231 omap_dss_unregister_driver(&venc_driver);
232}
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 6adb44534606..fc06c5b5f12a 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -319,6 +319,7 @@ enum omapdss_version {
319 OMAPDSS_VER_OMAP4430_ES2, /* OMAP4430 ES2.0, 2.1, 2.2 */ 319 OMAPDSS_VER_OMAP4430_ES2, /* OMAP4430 ES2.0, 2.1, 2.2 */
320 OMAPDSS_VER_OMAP4, /* All other OMAP4s */ 320 OMAPDSS_VER_OMAP4, /* All other OMAP4s */
321 OMAPDSS_VER_OMAP5, 321 OMAPDSS_VER_OMAP5,
322 OMAPDSS_VER_AM43xx,
322}; 323};
323 324
324/* Board specific data */ 325/* Board specific data */
@@ -388,8 +389,8 @@ struct omap_dss_cpr_coefs {
388}; 389};
389 390
390struct omap_overlay_info { 391struct omap_overlay_info {
391 u32 paddr; 392 dma_addr_t paddr;
392 u32 p_uv_addr; /* for NV12 format */ 393 dma_addr_t p_uv_addr; /* for NV12 format */
393 u16 screen_width; 394 u16 screen_width;
394 u16 width; 395 u16 width;
395 u16 height; 396 u16 height;
@@ -964,9 +965,6 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
964 bool replication, const struct omap_video_timings *mgr_timings, 965 bool replication, const struct omap_video_timings *mgr_timings,
965 bool mem_to_mem); 966 bool mem_to_mem);
966 967
967#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
968#define to_dss_device(x) container_of((x), struct omap_dss_device, old_dev)
969
970int omapdss_compat_init(void); 968int omapdss_compat_init(void);
971void omapdss_compat_uninit(void); 969void omapdss_compat_uninit(void);
972 970