aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 12:07:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 12:07:08 -0400
commit15b588303155b22edd559672905db8e59a44ef9a (patch)
tree5413973ea42014d71ac6d8ce36dbf05058a45646 /drivers/video
parentd55696af8d91e8f21dacd74a236e6dcc4f6d78c4 (diff)
parentf2dd36ac9974cc2353bcbb8e6b643fb96030564c (diff)
Merge tag 'fbdev-omap-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into next
Pull omap fbdev changes from Tomi Valkeinen: - DT support for the panel drivers that were still missing it - TI AM43xx support - TI OMAP5 support * tag 'fbdev-omap-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (46 commits) OMAPDSS: move 'compatible' converter to omapdss driver OMAPDSS: HDMI: fix devm_ioremap_resource error checks OMAPDSS: HDMI: remove unused defines OMAPDSS: HDMI: cleanup WP ioremaps OMAPDSS: panel NEC-NL8048HL11 DT support Doc/DT: Add DT binding documentation for TPO td043mtea1 panel OMAPDSS: Panel TPO-TD043MTEA1 DT support Doc/DT: Add DT binding documentation for SHARP LS037V7DW01 OMAPDSS: panel sharp-ls037v7dw01 DT support OMAPDSS: panel-sharp-ls037v7dw01: update to use gpiod Doc/DT: Add binding doc for lgphilips,lb035q02.txt OMAPDSS: panel-lgphilips-lb035q02: Add DT support OMAPDSS: panel-lgphilips-lb035q02: use gpiod for enable gpio OMAPDSS: hdmi5_core: Fix compilation with OMAP5_DSS_HDMI_AUDIO OMAPDSS: panel-dpi: enable-gpio OMAPDSS: Fix writes to DISPC_POL_FREQ Doc/DT: Add OMAP5 DSS DT bindings OMAPDSS: HDMI: cleanup ioremaps OMAPDSS: HDMI: Add OMAP5 HDMI support OMAPDSS: HDMI: PLL changes for OMAP5 ...
Diffstat (limited to 'drivers/video')
-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
29 files changed, 3310 insertions, 513 deletions
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}