diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-03-20 02:09:19 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-03-20 02:13:50 -0400 |
commit | 17d5ca91cfc59ae91da5ff9da74ab09a9a2a17d9 (patch) | |
tree | a45f944e15a2600ec20ca4ec11b23d4641095e8e /drivers/video | |
parent | b7e4ab50418d5b34ab0dae95193dd71190e1fb50 (diff) | |
parent | c86907b59f505863ec7839471e889330982a596e (diff) |
Merge branch '3.15/dss-dt' into 3.15/fbdev
Merge OMAP DSS DT support
Diffstat (limited to 'drivers/video')
21 files changed, 938 insertions, 44 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 78e2fc7a4840..7d4e33cba6ed 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -364,7 +364,7 @@ config FB_SA1100 | |||
364 | 364 | ||
365 | config FB_IMX | 365 | config FB_IMX |
366 | tristate "Freescale i.MX1/21/25/27 LCD support" | 366 | tristate "Freescale i.MX1/21/25/27 LCD support" |
367 | depends on FB && IMX_HAVE_PLATFORM_IMX_FB | 367 | depends on FB && ARCH_MXC |
368 | select FB_CFB_FILLRECT | 368 | select FB_CFB_FILLRECT |
369 | select FB_CFB_COPYAREA | 369 | select FB_CFB_COPYAREA |
370 | select FB_CFB_IMAGEBLIT | 370 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig index 976594d578a9..eb6f2b059821 100644 --- a/drivers/video/exynos/Kconfig +++ b/drivers/video/exynos/Kconfig | |||
@@ -22,7 +22,8 @@ config EXYNOS_MIPI_DSI | |||
22 | 22 | ||
23 | config EXYNOS_LCD_S6E8AX0 | 23 | config EXYNOS_LCD_S6E8AX0 |
24 | bool "S6E8AX0 MIPI AMOLED LCD Driver" | 24 | bool "S6E8AX0 MIPI AMOLED LCD Driver" |
25 | depends on (EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE) | 25 | depends on EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE |
26 | depends on (LCD_CLASS_DEVICE = y) | ||
26 | default n | 27 | default n |
27 | help | 28 | help |
28 | If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its | 29 | If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its |
diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/omap2/displays-new/connector-analog-tv.c index 27f33ef8fca1..5ee3b5505f7f 100644 --- a/drivers/video/omap2/displays-new/connector-analog-tv.c +++ b/drivers/video/omap2/displays-new/connector-analog-tv.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
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 | 16 | ||
16 | #include <video/omapdss.h> | 17 | #include <video/omapdss.h> |
17 | #include <video/omap-panel-data.h> | 18 | #include <video/omap-panel-data.h> |
@@ -42,6 +43,12 @@ static const struct omap_video_timings tvc_pal_timings = { | |||
42 | .interlace = true, | 43 | .interlace = true, |
43 | }; | 44 | }; |
44 | 45 | ||
46 | static const struct of_device_id tvc_of_match[]; | ||
47 | |||
48 | struct tvc_of_data { | ||
49 | enum omap_dss_venc_type connector_type; | ||
50 | }; | ||
51 | |||
45 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) | 52 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) |
46 | 53 | ||
47 | static int tvc_connect(struct omap_dss_device *dssdev) | 54 | static int tvc_connect(struct omap_dss_device *dssdev) |
@@ -91,8 +98,12 @@ static int tvc_enable(struct omap_dss_device *dssdev) | |||
91 | 98 | ||
92 | in->ops.atv->set_timings(in, &ddata->timings); | 99 | in->ops.atv->set_timings(in, &ddata->timings); |
93 | 100 | ||
94 | in->ops.atv->set_type(in, ddata->connector_type); | 101 | if (!ddata->dev->of_node) { |
95 | in->ops.atv->invert_vid_out_polarity(in, ddata->invert_polarity); | 102 | in->ops.atv->set_type(in, ddata->connector_type); |
103 | |||
104 | in->ops.atv->invert_vid_out_polarity(in, | ||
105 | ddata->invert_polarity); | ||
106 | } | ||
96 | 107 | ||
97 | r = in->ops.atv->enable(in); | 108 | r = in->ops.atv->enable(in); |
98 | if (r) | 109 | if (r) |
@@ -205,6 +216,23 @@ static int tvc_probe_pdata(struct platform_device *pdev) | |||
205 | return 0; | 216 | return 0; |
206 | } | 217 | } |
207 | 218 | ||
219 | static int tvc_probe_of(struct platform_device *pdev) | ||
220 | { | ||
221 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
222 | struct device_node *node = pdev->dev.of_node; | ||
223 | struct omap_dss_device *in; | ||
224 | |||
225 | in = omapdss_of_find_source_for_first_ep(node); | ||
226 | if (IS_ERR(in)) { | ||
227 | dev_err(&pdev->dev, "failed to find video source\n"); | ||
228 | return PTR_ERR(in); | ||
229 | } | ||
230 | |||
231 | ddata->in = in; | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
208 | static int tvc_probe(struct platform_device *pdev) | 236 | static int tvc_probe(struct platform_device *pdev) |
209 | { | 237 | { |
210 | struct panel_drv_data *ddata; | 238 | struct panel_drv_data *ddata; |
@@ -222,6 +250,10 @@ static int tvc_probe(struct platform_device *pdev) | |||
222 | r = tvc_probe_pdata(pdev); | 250 | r = tvc_probe_pdata(pdev); |
223 | if (r) | 251 | if (r) |
224 | return r; | 252 | return r; |
253 | } else if (pdev->dev.of_node) { | ||
254 | r = tvc_probe_of(pdev); | ||
255 | if (r) | ||
256 | return r; | ||
225 | } else { | 257 | } else { |
226 | return -ENODEV; | 258 | return -ENODEV; |
227 | } | 259 | } |
@@ -263,12 +295,19 @@ static int __exit tvc_remove(struct platform_device *pdev) | |||
263 | return 0; | 295 | return 0; |
264 | } | 296 | } |
265 | 297 | ||
298 | static const struct of_device_id tvc_of_match[] = { | ||
299 | { .compatible = "omapdss,svideo-connector", }, | ||
300 | { .compatible = "omapdss,composite-video-connector", }, | ||
301 | {}, | ||
302 | }; | ||
303 | |||
266 | static struct platform_driver tvc_connector_driver = { | 304 | static struct platform_driver tvc_connector_driver = { |
267 | .probe = tvc_probe, | 305 | .probe = tvc_probe, |
268 | .remove = __exit_p(tvc_remove), | 306 | .remove = __exit_p(tvc_remove), |
269 | .driver = { | 307 | .driver = { |
270 | .name = "connector-analog-tv", | 308 | .name = "connector-analog-tv", |
271 | .owner = THIS_MODULE, | 309 | .owner = THIS_MODULE, |
310 | .of_match_table = tvc_of_match, | ||
272 | }, | 311 | }, |
273 | }; | 312 | }; |
274 | 313 | ||
diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/omap2/displays-new/connector-dvi.c index d18e4b8c0731..74de2bc50c4f 100644 --- a/drivers/video/omap2/displays-new/connector-dvi.c +++ b/drivers/video/omap2/displays-new/connector-dvi.c | |||
@@ -277,6 +277,37 @@ static int dvic_probe_pdata(struct platform_device *pdev) | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | static int dvic_probe_of(struct platform_device *pdev) | ||
281 | { | ||
282 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
283 | struct device_node *node = pdev->dev.of_node; | ||
284 | struct omap_dss_device *in; | ||
285 | struct device_node *adapter_node; | ||
286 | struct i2c_adapter *adapter; | ||
287 | |||
288 | in = omapdss_of_find_source_for_first_ep(node); | ||
289 | if (IS_ERR(in)) { | ||
290 | dev_err(&pdev->dev, "failed to find video source\n"); | ||
291 | return PTR_ERR(in); | ||
292 | } | ||
293 | |||
294 | ddata->in = in; | ||
295 | |||
296 | adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0); | ||
297 | if (adapter_node) { | ||
298 | adapter = of_find_i2c_adapter_by_node(adapter_node); | ||
299 | if (adapter == NULL) { | ||
300 | dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n"); | ||
301 | omap_dss_put_device(ddata->in); | ||
302 | return -EPROBE_DEFER; | ||
303 | } | ||
304 | |||
305 | ddata->i2c_adapter = adapter; | ||
306 | } | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
280 | static int dvic_probe(struct platform_device *pdev) | 311 | static int dvic_probe(struct platform_device *pdev) |
281 | { | 312 | { |
282 | struct panel_drv_data *ddata; | 313 | struct panel_drv_data *ddata; |
@@ -293,6 +324,10 @@ static int dvic_probe(struct platform_device *pdev) | |||
293 | r = dvic_probe_pdata(pdev); | 324 | r = dvic_probe_pdata(pdev); |
294 | if (r) | 325 | if (r) |
295 | return r; | 326 | return r; |
327 | } else if (pdev->dev.of_node) { | ||
328 | r = dvic_probe_of(pdev); | ||
329 | if (r) | ||
330 | return r; | ||
296 | } else { | 331 | } else { |
297 | return -ENODEV; | 332 | return -ENODEV; |
298 | } | 333 | } |
@@ -342,12 +377,20 @@ static int __exit dvic_remove(struct platform_device *pdev) | |||
342 | return 0; | 377 | return 0; |
343 | } | 378 | } |
344 | 379 | ||
380 | static const struct of_device_id dvic_of_match[] = { | ||
381 | { .compatible = "omapdss,dvi-connector", }, | ||
382 | {}, | ||
383 | }; | ||
384 | |||
385 | MODULE_DEVICE_TABLE(of, dvic_of_match); | ||
386 | |||
345 | static struct platform_driver dvi_connector_driver = { | 387 | static struct platform_driver dvi_connector_driver = { |
346 | .probe = dvic_probe, | 388 | .probe = dvic_probe, |
347 | .remove = __exit_p(dvic_remove), | 389 | .remove = __exit_p(dvic_remove), |
348 | .driver = { | 390 | .driver = { |
349 | .name = "connector-dvi", | 391 | .name = "connector-dvi", |
350 | .owner = THIS_MODULE, | 392 | .owner = THIS_MODULE, |
393 | .of_match_table = dvic_of_match, | ||
351 | }, | 394 | }, |
352 | }; | 395 | }; |
353 | 396 | ||
diff --git a/drivers/video/omap2/displays-new/connector-hdmi.c b/drivers/video/omap2/displays-new/connector-hdmi.c index 9393e2d6473d..29ed21b9dce5 100644 --- a/drivers/video/omap2/displays-new/connector-hdmi.c +++ b/drivers/video/omap2/displays-new/connector-hdmi.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
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 | 16 | ||
16 | #include <drm/drm_edid.h> | 17 | #include <drm/drm_edid.h> |
17 | 18 | ||
@@ -301,6 +302,23 @@ static int hdmic_probe_pdata(struct platform_device *pdev) | |||
301 | return 0; | 302 | return 0; |
302 | } | 303 | } |
303 | 304 | ||
305 | static int hdmic_probe_of(struct platform_device *pdev) | ||
306 | { | ||
307 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
308 | struct device_node *node = pdev->dev.of_node; | ||
309 | struct omap_dss_device *in; | ||
310 | |||
311 | in = omapdss_of_find_source_for_first_ep(node); | ||
312 | if (IS_ERR(in)) { | ||
313 | dev_err(&pdev->dev, "failed to find video source\n"); | ||
314 | return PTR_ERR(in); | ||
315 | } | ||
316 | |||
317 | ddata->in = in; | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
304 | static int hdmic_probe(struct platform_device *pdev) | 322 | static int hdmic_probe(struct platform_device *pdev) |
305 | { | 323 | { |
306 | struct panel_drv_data *ddata; | 324 | struct panel_drv_data *ddata; |
@@ -318,6 +336,10 @@ static int hdmic_probe(struct platform_device *pdev) | |||
318 | r = hdmic_probe_pdata(pdev); | 336 | r = hdmic_probe_pdata(pdev); |
319 | if (r) | 337 | if (r) |
320 | return r; | 338 | return r; |
339 | } else if (pdev->dev.of_node) { | ||
340 | r = hdmic_probe_of(pdev); | ||
341 | if (r) | ||
342 | return r; | ||
321 | } else { | 343 | } else { |
322 | return -ENODEV; | 344 | return -ENODEV; |
323 | } | 345 | } |
@@ -359,12 +381,20 @@ static int __exit hdmic_remove(struct platform_device *pdev) | |||
359 | return 0; | 381 | return 0; |
360 | } | 382 | } |
361 | 383 | ||
384 | static const struct of_device_id hdmic_of_match[] = { | ||
385 | { .compatible = "omapdss,hdmi-connector", }, | ||
386 | {}, | ||
387 | }; | ||
388 | |||
389 | MODULE_DEVICE_TABLE(of, hdmic_of_match); | ||
390 | |||
362 | static struct platform_driver hdmi_connector_driver = { | 391 | static struct platform_driver hdmi_connector_driver = { |
363 | .probe = hdmic_probe, | 392 | .probe = hdmic_probe, |
364 | .remove = __exit_p(hdmic_remove), | 393 | .remove = __exit_p(hdmic_remove), |
365 | .driver = { | 394 | .driver = { |
366 | .name = "connector-hdmi", | 395 | .name = "connector-hdmi", |
367 | .owner = THIS_MODULE, | 396 | .owner = THIS_MODULE, |
397 | .of_match_table = hdmic_of_match, | ||
368 | }, | 398 | }, |
369 | }; | 399 | }; |
370 | 400 | ||
diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/omap2/displays-new/encoder-tfp410.c index 4a291e756be9..b4e9a42a79e6 100644 --- a/drivers/video/omap2/displays-new/encoder-tfp410.c +++ b/drivers/video/omap2/displays-new/encoder-tfp410.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/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/of_gpio.h> | ||
16 | 17 | ||
17 | #include <video/omapdss.h> | 18 | #include <video/omapdss.h> |
18 | #include <video/omap-panel-data.h> | 19 | #include <video/omap-panel-data.h> |
@@ -82,7 +83,8 @@ static int tfp410_enable(struct omap_dss_device *dssdev) | |||
82 | return 0; | 83 | return 0; |
83 | 84 | ||
84 | in->ops.dpi->set_timings(in, &ddata->timings); | 85 | in->ops.dpi->set_timings(in, &ddata->timings); |
85 | in->ops.dpi->set_data_lines(in, ddata->data_lines); | 86 | if (ddata->data_lines) |
87 | in->ops.dpi->set_data_lines(in, ddata->data_lines); | ||
86 | 88 | ||
87 | r = in->ops.dpi->enable(in); | 89 | r = in->ops.dpi->enable(in); |
88 | if (r) | 90 | if (r) |
@@ -179,6 +181,33 @@ static int tfp410_probe_pdata(struct platform_device *pdev) | |||
179 | return 0; | 181 | return 0; |
180 | } | 182 | } |
181 | 183 | ||
184 | static int tfp410_probe_of(struct platform_device *pdev) | ||
185 | { | ||
186 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
187 | struct device_node *node = pdev->dev.of_node; | ||
188 | struct omap_dss_device *in; | ||
189 | int gpio; | ||
190 | |||
191 | gpio = of_get_named_gpio(node, "powerdown-gpios", 0); | ||
192 | |||
193 | if (gpio_is_valid(gpio) || gpio == -ENOENT) { | ||
194 | ddata->pd_gpio = gpio; | ||
195 | } else { | ||
196 | dev_err(&pdev->dev, "failed to parse PD gpio\n"); | ||
197 | return gpio; | ||
198 | } | ||
199 | |||
200 | in = omapdss_of_find_source_for_first_ep(node); | ||
201 | if (IS_ERR(in)) { | ||
202 | dev_err(&pdev->dev, "failed to find video source\n"); | ||
203 | return PTR_ERR(in); | ||
204 | } | ||
205 | |||
206 | ddata->in = in; | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
182 | static int tfp410_probe(struct platform_device *pdev) | 211 | static int tfp410_probe(struct platform_device *pdev) |
183 | { | 212 | { |
184 | struct panel_drv_data *ddata; | 213 | struct panel_drv_data *ddata; |
@@ -195,6 +224,10 @@ static int tfp410_probe(struct platform_device *pdev) | |||
195 | r = tfp410_probe_pdata(pdev); | 224 | r = tfp410_probe_pdata(pdev); |
196 | if (r) | 225 | if (r) |
197 | return r; | 226 | return r; |
227 | } else if (pdev->dev.of_node) { | ||
228 | r = tfp410_probe_of(pdev); | ||
229 | if (r) | ||
230 | return r; | ||
198 | } else { | 231 | } else { |
199 | return -ENODEV; | 232 | return -ENODEV; |
200 | } | 233 | } |
@@ -251,12 +284,20 @@ static int __exit tfp410_remove(struct platform_device *pdev) | |||
251 | return 0; | 284 | return 0; |
252 | } | 285 | } |
253 | 286 | ||
287 | static const struct of_device_id tfp410_of_match[] = { | ||
288 | { .compatible = "omapdss,ti,tfp410", }, | ||
289 | {}, | ||
290 | }; | ||
291 | |||
292 | MODULE_DEVICE_TABLE(of, tfp410_of_match); | ||
293 | |||
254 | static struct platform_driver tfp410_driver = { | 294 | static struct platform_driver tfp410_driver = { |
255 | .probe = tfp410_probe, | 295 | .probe = tfp410_probe, |
256 | .remove = __exit_p(tfp410_remove), | 296 | .remove = __exit_p(tfp410_remove), |
257 | .driver = { | 297 | .driver = { |
258 | .name = "tfp410", | 298 | .name = "tfp410", |
259 | .owner = THIS_MODULE, | 299 | .owner = THIS_MODULE, |
300 | .of_match_table = tfp410_of_match, | ||
260 | }, | 301 | }, |
261 | }; | 302 | }; |
262 | 303 | ||
diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/omap2/displays-new/encoder-tpd12s015.c index d5c936cb217f..7e33686171e3 100644 --- a/drivers/video/omap2/displays-new/encoder-tpd12s015.c +++ b/drivers/video/omap2/displays-new/encoder-tpd12s015.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/of_gpio.h> | ||
18 | 19 | ||
19 | #include <video/omapdss.h> | 20 | #include <video/omapdss.h> |
20 | #include <video/omap-panel-data.h> | 21 | #include <video/omap-panel-data.h> |
@@ -289,6 +290,49 @@ static int tpd_probe_pdata(struct platform_device *pdev) | |||
289 | return 0; | 290 | return 0; |
290 | } | 291 | } |
291 | 292 | ||
293 | static int tpd_probe_of(struct platform_device *pdev) | ||
294 | { | ||
295 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
296 | struct device_node *node = pdev->dev.of_node; | ||
297 | struct omap_dss_device *in; | ||
298 | int gpio; | ||
299 | |||
300 | /* CT CP HPD GPIO */ | ||
301 | gpio = of_get_gpio(node, 0); | ||
302 | if (!gpio_is_valid(gpio)) { | ||
303 | dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n"); | ||
304 | return gpio; | ||
305 | } | ||
306 | ddata->ct_cp_hpd_gpio = gpio; | ||
307 | |||
308 | /* LS OE GPIO */ | ||
309 | gpio = of_get_gpio(node, 1); | ||
310 | if (gpio_is_valid(gpio) || gpio == -ENOENT) { | ||
311 | ddata->ls_oe_gpio = gpio; | ||
312 | } else { | ||
313 | dev_err(&pdev->dev, "failed to parse LS OE gpio\n"); | ||
314 | return gpio; | ||
315 | } | ||
316 | |||
317 | /* HPD GPIO */ | ||
318 | gpio = of_get_gpio(node, 2); | ||
319 | if (!gpio_is_valid(gpio)) { | ||
320 | dev_err(&pdev->dev, "failed to parse HPD gpio\n"); | ||
321 | return gpio; | ||
322 | } | ||
323 | ddata->hpd_gpio = gpio; | ||
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; | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
292 | static int tpd_probe(struct platform_device *pdev) | 336 | static int tpd_probe(struct platform_device *pdev) |
293 | { | 337 | { |
294 | struct omap_dss_device *in, *dssdev; | 338 | struct omap_dss_device *in, *dssdev; |
@@ -307,6 +351,10 @@ static int tpd_probe(struct platform_device *pdev) | |||
307 | r = tpd_probe_pdata(pdev); | 351 | r = tpd_probe_pdata(pdev); |
308 | if (r) | 352 | if (r) |
309 | return r; | 353 | return r; |
354 | } else if (pdev->dev.of_node) { | ||
355 | r = tpd_probe_of(pdev); | ||
356 | if (r) | ||
357 | return r; | ||
310 | } else { | 358 | } else { |
311 | return -ENODEV; | 359 | return -ENODEV; |
312 | } | 360 | } |
@@ -379,12 +427,20 @@ static int __exit tpd_remove(struct platform_device *pdev) | |||
379 | return 0; | 427 | return 0; |
380 | } | 428 | } |
381 | 429 | ||
430 | static const struct of_device_id tpd_of_match[] = { | ||
431 | { .compatible = "omapdss,ti,tpd12s015", }, | ||
432 | {}, | ||
433 | }; | ||
434 | |||
435 | MODULE_DEVICE_TABLE(of, tpd_of_match); | ||
436 | |||
382 | static struct platform_driver tpd_driver = { | 437 | static struct platform_driver tpd_driver = { |
383 | .probe = tpd_probe, | 438 | .probe = tpd_probe, |
384 | .remove = __exit_p(tpd_remove), | 439 | .remove = __exit_p(tpd_remove), |
385 | .driver = { | 440 | .driver = { |
386 | .name = "tpd12s015", | 441 | .name = "tpd12s015", |
387 | .owner = THIS_MODULE, | 442 | .owner = THIS_MODULE, |
443 | .of_match_table = tpd_of_match, | ||
388 | }, | 444 | }, |
389 | }; | 445 | }; |
390 | 446 | ||
diff --git a/drivers/video/omap2/displays-new/panel-dsi-cm.c b/drivers/video/omap2/displays-new/panel-dsi-cm.c index f317c878a259..d6f14e8717e8 100644 --- a/drivers/video/omap2/displays-new/panel-dsi-cm.c +++ b/drivers/video/omap2/displays-new/panel-dsi-cm.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/of_device.h> | ||
26 | #include <linux/of_gpio.h> | ||
25 | 27 | ||
26 | #include <video/omapdss.h> | 28 | #include <video/omapdss.h> |
27 | #include <video/omap-panel-data.h> | 29 | #include <video/omap-panel-data.h> |
@@ -595,10 +597,13 @@ static int dsicm_power_on(struct panel_drv_data *ddata) | |||
595 | .lp_clk_max = 10000000, | 597 | .lp_clk_max = 10000000, |
596 | }; | 598 | }; |
597 | 599 | ||
598 | r = in->ops.dsi->configure_pins(in, &ddata->pin_config); | 600 | if (ddata->pin_config.num_pins > 0) { |
599 | if (r) { | 601 | r = in->ops.dsi->configure_pins(in, &ddata->pin_config); |
600 | dev_err(&ddata->pdev->dev, "failed to configure DSI pins\n"); | 602 | if (r) { |
601 | goto err0; | 603 | dev_err(&ddata->pdev->dev, |
604 | "failed to configure DSI pins\n"); | ||
605 | goto err0; | ||
606 | } | ||
602 | } | 607 | } |
603 | 608 | ||
604 | r = in->ops.dsi->set_config(in, &dsi_config); | 609 | r = in->ops.dsi->set_config(in, &dsi_config); |
@@ -1156,6 +1161,41 @@ static int dsicm_probe_pdata(struct platform_device *pdev) | |||
1156 | return 0; | 1161 | return 0; |
1157 | } | 1162 | } |
1158 | 1163 | ||
1164 | static int dsicm_probe_of(struct platform_device *pdev) | ||
1165 | { | ||
1166 | struct device_node *node = pdev->dev.of_node; | ||
1167 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
1168 | struct omap_dss_device *in; | ||
1169 | int gpio; | ||
1170 | |||
1171 | gpio = of_get_named_gpio(node, "reset-gpios", 0); | ||
1172 | if (!gpio_is_valid(gpio)) { | ||
1173 | dev_err(&pdev->dev, "failed to parse reset gpio\n"); | ||
1174 | return gpio; | ||
1175 | } | ||
1176 | ddata->reset_gpio = gpio; | ||
1177 | |||
1178 | gpio = of_get_named_gpio(node, "te-gpios", 0); | ||
1179 | if (gpio_is_valid(gpio) || gpio == -ENOENT) { | ||
1180 | ddata->ext_te_gpio = gpio; | ||
1181 | } else { | ||
1182 | dev_err(&pdev->dev, "failed to parse TE gpio\n"); | ||
1183 | return gpio; | ||
1184 | } | ||
1185 | |||
1186 | in = omapdss_of_find_source_for_first_ep(node); | ||
1187 | if (IS_ERR(in)) { | ||
1188 | dev_err(&pdev->dev, "failed to find video source\n"); | ||
1189 | return PTR_ERR(in); | ||
1190 | } | ||
1191 | |||
1192 | ddata->in = in; | ||
1193 | |||
1194 | /* TODO: ulps, backlight */ | ||
1195 | |||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1159 | static int dsicm_probe(struct platform_device *pdev) | 1199 | static int dsicm_probe(struct platform_device *pdev) |
1160 | { | 1200 | { |
1161 | struct backlight_properties props; | 1201 | struct backlight_properties props; |
@@ -1178,6 +1218,10 @@ static int dsicm_probe(struct platform_device *pdev) | |||
1178 | r = dsicm_probe_pdata(pdev); | 1218 | r = dsicm_probe_pdata(pdev); |
1179 | if (r) | 1219 | if (r) |
1180 | return r; | 1220 | return r; |
1221 | } else if (pdev->dev.of_node) { | ||
1222 | r = dsicm_probe_of(pdev); | ||
1223 | if (r) | ||
1224 | return r; | ||
1181 | } else { | 1225 | } else { |
1182 | return -ENODEV; | 1226 | return -ENODEV; |
1183 | } | 1227 | } |
@@ -1320,12 +1364,20 @@ static int __exit dsicm_remove(struct platform_device *pdev) | |||
1320 | return 0; | 1364 | return 0; |
1321 | } | 1365 | } |
1322 | 1366 | ||
1367 | static const struct of_device_id dsicm_of_match[] = { | ||
1368 | { .compatible = "omapdss,panel-dsi-cm", }, | ||
1369 | {}, | ||
1370 | }; | ||
1371 | |||
1372 | MODULE_DEVICE_TABLE(of, dsicm_of_match); | ||
1373 | |||
1323 | static struct platform_driver dsicm_driver = { | 1374 | static struct platform_driver dsicm_driver = { |
1324 | .probe = dsicm_probe, | 1375 | .probe = dsicm_probe, |
1325 | .remove = __exit_p(dsicm_remove), | 1376 | .remove = __exit_p(dsicm_remove), |
1326 | .driver = { | 1377 | .driver = { |
1327 | .name = "panel-dsi-cm", | 1378 | .name = "panel-dsi-cm", |
1328 | .owner = THIS_MODULE, | 1379 | .owner = THIS_MODULE, |
1380 | .of_match_table = dsicm_of_match, | ||
1329 | }, | 1381 | }, |
1330 | }; | 1382 | }; |
1331 | 1383 | ||
diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c index 27f60ad6b2ab..c7ba4d8b928a 100644 --- a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c +++ b/drivers/video/omap2/displays-new/panel-sony-acx565akm.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/backlight.h> | 30 | #include <linux/backlight.h> |
31 | #include <linux/fb.h> | 31 | #include <linux/fb.h> |
32 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
33 | #include <linux/of.h> | ||
34 | #include <linux/of_gpio.h> | ||
33 | 35 | ||
34 | #include <video/omapdss.h> | 36 | #include <video/omapdss.h> |
35 | #include <video/omap-panel-data.h> | 37 | #include <video/omap-panel-data.h> |
@@ -547,7 +549,9 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev) | |||
547 | dev_dbg(&ddata->spi->dev, "%s\n", __func__); | 549 | dev_dbg(&ddata->spi->dev, "%s\n", __func__); |
548 | 550 | ||
549 | in->ops.sdi->set_timings(in, &ddata->videomode); | 551 | in->ops.sdi->set_timings(in, &ddata->videomode); |
550 | in->ops.sdi->set_datapairs(in, ddata->datapairs); | 552 | |
553 | if (ddata->datapairs > 0) | ||
554 | in->ops.sdi->set_datapairs(in, ddata->datapairs); | ||
551 | 555 | ||
552 | r = in->ops.sdi->enable(in); | 556 | r = in->ops.sdi->enable(in); |
553 | if (r) { | 557 | if (r) { |
@@ -726,6 +730,22 @@ static int acx565akm_probe_pdata(struct spi_device *spi) | |||
726 | return 0; | 730 | return 0; |
727 | } | 731 | } |
728 | 732 | ||
733 | static int acx565akm_probe_of(struct spi_device *spi) | ||
734 | { | ||
735 | struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); | ||
736 | struct device_node *np = spi->dev.of_node; | ||
737 | |||
738 | ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); | ||
739 | |||
740 | ddata->in = omapdss_of_find_source_for_first_ep(np); | ||
741 | if (IS_ERR(ddata->in)) { | ||
742 | dev_err(&spi->dev, "failed to find video source\n"); | ||
743 | return PTR_ERR(ddata->in); | ||
744 | } | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
729 | static int acx565akm_probe(struct spi_device *spi) | 749 | static int acx565akm_probe(struct spi_device *spi) |
730 | { | 750 | { |
731 | struct panel_drv_data *ddata; | 751 | struct panel_drv_data *ddata; |
@@ -753,7 +773,12 @@ static int acx565akm_probe(struct spi_device *spi) | |||
753 | r = acx565akm_probe_pdata(spi); | 773 | r = acx565akm_probe_pdata(spi); |
754 | if (r) | 774 | if (r) |
755 | return r; | 775 | return r; |
776 | } else if (spi->dev.of_node) { | ||
777 | r = acx565akm_probe_of(spi); | ||
778 | if (r) | ||
779 | return r; | ||
756 | } else { | 780 | } else { |
781 | dev_err(&spi->dev, "platform data missing!\n"); | ||
757 | return -ENODEV; | 782 | return -ENODEV; |
758 | } | 783 | } |
759 | 784 | ||
@@ -864,10 +889,16 @@ static int acx565akm_remove(struct spi_device *spi) | |||
864 | return 0; | 889 | return 0; |
865 | } | 890 | } |
866 | 891 | ||
892 | static const struct of_device_id acx565akm_of_match[] = { | ||
893 | { .compatible = "omapdss,sony,acx565akm", }, | ||
894 | {}, | ||
895 | }; | ||
896 | |||
867 | static struct spi_driver acx565akm_driver = { | 897 | static struct spi_driver acx565akm_driver = { |
868 | .driver = { | 898 | .driver = { |
869 | .name = "acx565akm", | 899 | .name = "acx565akm", |
870 | .owner = THIS_MODULE, | 900 | .owner = THIS_MODULE, |
901 | .of_match_table = acx565akm_of_match, | ||
871 | }, | 902 | }, |
872 | .probe = acx565akm_probe, | 903 | .probe = acx565akm_probe, |
873 | .remove = acx565akm_remove, | 904 | .remove = acx565akm_remove, |
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index d3aa91bdd6a8..8aec8bda27cc 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o | 1 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o |
2 | # Core DSS files | 2 | # Core DSS files |
3 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ | 3 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ |
4 | output.o | 4 | output.o dss-of.o |
5 | # DSS compat layer files | 5 | # DSS compat layer files |
6 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ | 6 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ |
7 | dispc-compat.o display-sysfs.o | 7 | dispc-compat.o display-sysfs.o |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index b801be4660e9..2bbdb7ff7daf 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -2149,8 +2149,8 @@ static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk, | |||
2149 | *five_taps = false; | 2149 | *five_taps = false; |
2150 | 2150 | ||
2151 | do { | 2151 | do { |
2152 | in_height = DIV_ROUND_UP(height, *decim_y); | 2152 | in_height = height / *decim_y; |
2153 | in_width = DIV_ROUND_UP(width, *decim_x); | 2153 | in_width = width / *decim_x; |
2154 | *core_clk = dispc.feat->calc_core_clk(pclk, in_width, | 2154 | *core_clk = dispc.feat->calc_core_clk(pclk, in_width, |
2155 | in_height, out_width, out_height, mem_to_mem); | 2155 | in_height, out_width, out_height, mem_to_mem); |
2156 | error = (in_width > maxsinglelinewidth || !*core_clk || | 2156 | error = (in_width > maxsinglelinewidth || !*core_clk || |
@@ -2188,8 +2188,8 @@ static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk, | |||
2188 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | 2188 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); |
2189 | 2189 | ||
2190 | do { | 2190 | do { |
2191 | in_height = DIV_ROUND_UP(height, *decim_y); | 2191 | in_height = height / *decim_y; |
2192 | in_width = DIV_ROUND_UP(width, *decim_x); | 2192 | in_width = width / *decim_x; |
2193 | *five_taps = in_height > out_height; | 2193 | *five_taps = in_height > out_height; |
2194 | 2194 | ||
2195 | if (in_width > maxsinglelinewidth) | 2195 | if (in_width > maxsinglelinewidth) |
@@ -2257,7 +2257,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, | |||
2257 | { | 2257 | { |
2258 | u16 in_width, in_width_max; | 2258 | u16 in_width, in_width_max; |
2259 | int decim_x_min = *decim_x; | 2259 | int decim_x_min = *decim_x; |
2260 | u16 in_height = DIV_ROUND_UP(height, *decim_y); | 2260 | u16 in_height = height / *decim_y; |
2261 | const int maxsinglelinewidth = | 2261 | const int maxsinglelinewidth = |
2262 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); | 2262 | dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); |
2263 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); | 2263 | const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); |
@@ -2276,7 +2276,7 @@ static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk, | |||
2276 | return -EINVAL; | 2276 | return -EINVAL; |
2277 | 2277 | ||
2278 | do { | 2278 | do { |
2279 | in_width = DIV_ROUND_UP(width, *decim_x); | 2279 | in_width = width / *decim_x; |
2280 | } while (*decim_x <= *x_predecim && | 2280 | } while (*decim_x <= *x_predecim && |
2281 | in_width > maxsinglelinewidth && ++*decim_x); | 2281 | in_width > maxsinglelinewidth && ++*decim_x); |
2282 | 2282 | ||
@@ -2455,8 +2455,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
2455 | if (r) | 2455 | if (r) |
2456 | return r; | 2456 | return r; |
2457 | 2457 | ||
2458 | in_width = DIV_ROUND_UP(in_width, x_predecim); | 2458 | in_width = in_width / x_predecim; |
2459 | in_height = DIV_ROUND_UP(in_height, y_predecim); | 2459 | in_height = in_height / y_predecim; |
2460 | 2460 | ||
2461 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 2461 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
2462 | color_mode == OMAP_DSS_COLOR_UYVY || | 2462 | color_mode == OMAP_DSS_COLOR_UYVY || |
@@ -3778,12 +3778,20 @@ static const struct dev_pm_ops dispc_pm_ops = { | |||
3778 | .runtime_resume = dispc_runtime_resume, | 3778 | .runtime_resume = dispc_runtime_resume, |
3779 | }; | 3779 | }; |
3780 | 3780 | ||
3781 | static const struct of_device_id dispc_of_match[] = { | ||
3782 | { .compatible = "ti,omap2-dispc", }, | ||
3783 | { .compatible = "ti,omap3-dispc", }, | ||
3784 | { .compatible = "ti,omap4-dispc", }, | ||
3785 | {}, | ||
3786 | }; | ||
3787 | |||
3781 | static struct platform_driver omap_dispchw_driver = { | 3788 | static struct platform_driver omap_dispchw_driver = { |
3782 | .remove = __exit_p(omap_dispchw_remove), | 3789 | .remove = __exit_p(omap_dispchw_remove), |
3783 | .driver = { | 3790 | .driver = { |
3784 | .name = "omapdss_dispc", | 3791 | .name = "omapdss_dispc", |
3785 | .owner = THIS_MODULE, | 3792 | .owner = THIS_MODULE, |
3786 | .pm = &dispc_pm_ops, | 3793 | .pm = &dispc_pm_ops, |
3794 | .of_match_table = dispc_of_match, | ||
3787 | }, | 3795 | }, |
3788 | }; | 3796 | }; |
3789 | 3797 | ||
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 9f19ae22944c..2412a0dd0c13 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/of.h> | ||
29 | 30 | ||
30 | #include <video/omapdss.h> | 31 | #include <video/omapdss.h> |
31 | #include "dss.h" | 32 | #include "dss.h" |
@@ -133,9 +134,32 @@ static int disp_num_counter; | |||
133 | int omapdss_register_display(struct omap_dss_device *dssdev) | 134 | int omapdss_register_display(struct omap_dss_device *dssdev) |
134 | { | 135 | { |
135 | struct omap_dss_driver *drv = dssdev->driver; | 136 | struct omap_dss_driver *drv = dssdev->driver; |
137 | int id; | ||
136 | 138 | ||
137 | snprintf(dssdev->alias, sizeof(dssdev->alias), | 139 | /* |
138 | "display%d", disp_num_counter++); | 140 | * Note: this presumes all the displays are either using DT or non-DT, |
141 | * which normally should be the case. This also presumes that all | ||
142 | * displays either have an DT alias, or none has. | ||
143 | */ | ||
144 | |||
145 | if (dssdev->dev->of_node) { | ||
146 | id = of_alias_get_id(dssdev->dev->of_node, "display"); | ||
147 | |||
148 | if (id < 0) | ||
149 | id = disp_num_counter++; | ||
150 | } else { | ||
151 | id = disp_num_counter++; | ||
152 | } | ||
153 | |||
154 | snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id); | ||
155 | |||
156 | /* Use 'label' property for name, if it exists */ | ||
157 | if (dssdev->dev->of_node) | ||
158 | of_property_read_string(dssdev->dev->of_node, "label", | ||
159 | &dssdev->name); | ||
160 | |||
161 | if (dssdev->name == NULL) | ||
162 | dssdev->name = dssdev->alias; | ||
139 | 163 | ||
140 | if (drv && drv->get_resolution == NULL) | 164 | if (drv && drv->get_resolution == NULL) |
141 | drv->get_resolution = omapdss_default_get_resolution; | 165 | drv->get_resolution = omapdss_default_get_resolution; |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index d806fd50aa94..157921db447a 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
33 | #include <linux/of.h> | ||
33 | 34 | ||
34 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
35 | 36 | ||
@@ -49,6 +50,8 @@ static struct { | |||
49 | int data_lines; | 50 | int data_lines; |
50 | 51 | ||
51 | struct omap_dss_device output; | 52 | struct omap_dss_device output; |
53 | |||
54 | bool port_initialized; | ||
52 | } dpi; | 55 | } dpi; |
53 | 56 | ||
54 | static struct platform_device *dpi_get_dsidev(enum omap_channel channel) | 57 | static struct platform_device *dpi_get_dsidev(enum omap_channel channel) |
@@ -117,7 +120,7 @@ struct dpi_clk_calc_ctx { | |||
117 | /* outputs */ | 120 | /* outputs */ |
118 | 121 | ||
119 | struct dsi_clock_info dsi_cinfo; | 122 | struct dsi_clock_info dsi_cinfo; |
120 | unsigned long long fck; | 123 | unsigned long fck; |
121 | struct dispc_clock_info dispc_cinfo; | 124 | struct dispc_clock_info dispc_cinfo; |
122 | }; | 125 | }; |
123 | 126 | ||
@@ -725,3 +728,47 @@ void __exit dpi_uninit_platform_driver(void) | |||
725 | { | 728 | { |
726 | platform_driver_unregister(&omap_dpi_driver); | 729 | platform_driver_unregister(&omap_dpi_driver); |
727 | } | 730 | } |
731 | |||
732 | int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) | ||
733 | { | ||
734 | struct device_node *ep; | ||
735 | u32 datalines; | ||
736 | int r; | ||
737 | |||
738 | ep = omapdss_of_get_next_endpoint(port, NULL); | ||
739 | if (!ep) | ||
740 | return 0; | ||
741 | |||
742 | r = of_property_read_u32(ep, "data-lines", &datalines); | ||
743 | if (r) { | ||
744 | DSSERR("failed to parse datalines\n"); | ||
745 | goto err_datalines; | ||
746 | } | ||
747 | |||
748 | dpi.data_lines = datalines; | ||
749 | |||
750 | of_node_put(ep); | ||
751 | |||
752 | dpi.pdev = pdev; | ||
753 | |||
754 | mutex_init(&dpi.lock); | ||
755 | |||
756 | dpi_init_output(pdev); | ||
757 | |||
758 | dpi.port_initialized = true; | ||
759 | |||
760 | return 0; | ||
761 | |||
762 | err_datalines: | ||
763 | of_node_put(ep); | ||
764 | |||
765 | return r; | ||
766 | } | ||
767 | |||
768 | void __exit dpi_uninit_port(void) | ||
769 | { | ||
770 | if (!dpi.port_initialized) | ||
771 | return; | ||
772 | |||
773 | dpi_uninit_output(dpi.pdev); | ||
774 | } | ||
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 0d82f731d2f0..f3e4e468b49a 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/debugfs.h> | 39 | #include <linux/debugfs.h> |
40 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
41 | #include <linux/of.h> | ||
42 | #include <linux/of_platform.h> | ||
41 | 43 | ||
42 | #include <video/omapdss.h> | 44 | #include <video/omapdss.h> |
43 | #include <video/mipi_display.h> | 45 | #include <video/mipi_display.h> |
@@ -386,6 +388,13 @@ struct dsi_packet_sent_handler_data { | |||
386 | struct completion *completion; | 388 | struct completion *completion; |
387 | }; | 389 | }; |
388 | 390 | ||
391 | struct dsi_module_id_data { | ||
392 | u32 address; | ||
393 | int id; | ||
394 | }; | ||
395 | |||
396 | static const struct of_device_id dsi_of_match[]; | ||
397 | |||
389 | #ifdef DSI_PERF_MEASURE | 398 | #ifdef DSI_PERF_MEASURE |
390 | static bool dsi_perf; | 399 | static bool dsi_perf; |
391 | module_param(dsi_perf, bool, 0644); | 400 | module_param(dsi_perf, bool, 0644); |
@@ -1151,7 +1160,10 @@ static int dsi_regulator_init(struct platform_device *dsidev) | |||
1151 | if (dsi->vdds_dsi_reg != NULL) | 1160 | if (dsi->vdds_dsi_reg != NULL) |
1152 | return 0; | 1161 | return 0; |
1153 | 1162 | ||
1154 | vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdds_dsi"); | 1163 | if (dsi->pdev->dev.of_node) |
1164 | vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdd"); | ||
1165 | else | ||
1166 | vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdds_dsi"); | ||
1155 | 1167 | ||
1156 | /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */ | 1168 | /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */ |
1157 | if (IS_ERR(vdds_dsi)) | 1169 | if (IS_ERR(vdds_dsi)) |
@@ -5370,12 +5382,69 @@ static void dsi_uninit_output(struct platform_device *dsidev) | |||
5370 | omapdss_unregister_output(out); | 5382 | omapdss_unregister_output(out); |
5371 | } | 5383 | } |
5372 | 5384 | ||
5385 | static int dsi_probe_of(struct platform_device *pdev) | ||
5386 | { | ||
5387 | struct device_node *node = pdev->dev.of_node; | ||
5388 | struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); | ||
5389 | struct property *prop; | ||
5390 | u32 lane_arr[10]; | ||
5391 | int len, num_pins; | ||
5392 | int r, i; | ||
5393 | struct device_node *ep; | ||
5394 | struct omap_dsi_pin_config pin_cfg; | ||
5395 | |||
5396 | ep = omapdss_of_get_first_endpoint(node); | ||
5397 | if (!ep) | ||
5398 | return 0; | ||
5399 | |||
5400 | prop = of_find_property(ep, "lanes", &len); | ||
5401 | if (prop == NULL) { | ||
5402 | dev_err(&pdev->dev, "failed to find lane data\n"); | ||
5403 | r = -EINVAL; | ||
5404 | goto err; | ||
5405 | } | ||
5406 | |||
5407 | num_pins = len / sizeof(u32); | ||
5408 | |||
5409 | if (num_pins < 4 || num_pins % 2 != 0 || | ||
5410 | num_pins > dsi->num_lanes_supported * 2) { | ||
5411 | dev_err(&pdev->dev, "bad number of lanes\n"); | ||
5412 | r = -EINVAL; | ||
5413 | goto err; | ||
5414 | } | ||
5415 | |||
5416 | r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins); | ||
5417 | if (r) { | ||
5418 | dev_err(&pdev->dev, "failed to read lane data\n"); | ||
5419 | goto err; | ||
5420 | } | ||
5421 | |||
5422 | pin_cfg.num_pins = num_pins; | ||
5423 | for (i = 0; i < num_pins; ++i) | ||
5424 | pin_cfg.pins[i] = (int)lane_arr[i]; | ||
5425 | |||
5426 | r = dsi_configure_pins(&dsi->output, &pin_cfg); | ||
5427 | if (r) { | ||
5428 | dev_err(&pdev->dev, "failed to configure pins"); | ||
5429 | goto err; | ||
5430 | } | ||
5431 | |||
5432 | of_node_put(ep); | ||
5433 | |||
5434 | return 0; | ||
5435 | |||
5436 | err: | ||
5437 | of_node_put(ep); | ||
5438 | return r; | ||
5439 | } | ||
5440 | |||
5373 | /* DSI1 HW IP initialisation */ | 5441 | /* DSI1 HW IP initialisation */ |
5374 | static int omap_dsihw_probe(struct platform_device *dsidev) | 5442 | static int omap_dsihw_probe(struct platform_device *dsidev) |
5375 | { | 5443 | { |
5376 | u32 rev; | 5444 | u32 rev; |
5377 | int r, i; | 5445 | int r, i; |
5378 | struct dsi_data *dsi; | 5446 | struct dsi_data *dsi; |
5447 | struct resource *dsi_mem; | ||
5379 | struct resource *res; | 5448 | struct resource *res; |
5380 | struct resource temp_res; | 5449 | struct resource temp_res; |
5381 | 5450 | ||
@@ -5383,7 +5452,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
5383 | if (!dsi) | 5452 | if (!dsi) |
5384 | return -ENOMEM; | 5453 | return -ENOMEM; |
5385 | 5454 | ||
5386 | dsi->module_id = dsidev->id; | ||
5387 | dsi->pdev = dsidev; | 5455 | dsi->pdev = dsidev; |
5388 | dev_set_drvdata(&dsidev->dev, dsi); | 5456 | dev_set_drvdata(&dsidev->dev, dsi); |
5389 | 5457 | ||
@@ -5421,6 +5489,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
5421 | res = &temp_res; | 5489 | res = &temp_res; |
5422 | } | 5490 | } |
5423 | 5491 | ||
5492 | dsi_mem = res; | ||
5493 | |||
5424 | dsi->proto_base = devm_ioremap(&dsidev->dev, res->start, | 5494 | dsi->proto_base = devm_ioremap(&dsidev->dev, res->start, |
5425 | resource_size(res)); | 5495 | resource_size(res)); |
5426 | if (!dsi->proto_base) { | 5496 | if (!dsi->proto_base) { |
@@ -5481,6 +5551,31 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
5481 | return r; | 5551 | return r; |
5482 | } | 5552 | } |
5483 | 5553 | ||
5554 | if (dsidev->dev.of_node) { | ||
5555 | const struct of_device_id *match; | ||
5556 | const struct dsi_module_id_data *d; | ||
5557 | |||
5558 | match = of_match_node(dsi_of_match, dsidev->dev.of_node); | ||
5559 | if (!match) { | ||
5560 | DSSERR("unsupported DSI module\n"); | ||
5561 | return -ENODEV; | ||
5562 | } | ||
5563 | |||
5564 | d = match->data; | ||
5565 | |||
5566 | while (d->address != 0 && d->address != dsi_mem->start) | ||
5567 | d++; | ||
5568 | |||
5569 | if (d->address == 0) { | ||
5570 | DSSERR("unsupported DSI module\n"); | ||
5571 | return -ENODEV; | ||
5572 | } | ||
5573 | |||
5574 | dsi->module_id = d->id; | ||
5575 | } else { | ||
5576 | dsi->module_id = dsidev->id; | ||
5577 | } | ||
5578 | |||
5484 | /* DSI VCs initialization */ | 5579 | /* DSI VCs initialization */ |
5485 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { | 5580 | for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { |
5486 | dsi->vc[i].source = DSI_VC_SOURCE_L4; | 5581 | dsi->vc[i].source = DSI_VC_SOURCE_L4; |
@@ -5516,6 +5611,19 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
5516 | 5611 | ||
5517 | dsi_init_output(dsidev); | 5612 | dsi_init_output(dsidev); |
5518 | 5613 | ||
5614 | if (dsidev->dev.of_node) { | ||
5615 | r = dsi_probe_of(dsidev); | ||
5616 | if (r) { | ||
5617 | DSSERR("Invalid DSI DT data\n"); | ||
5618 | goto err_probe_of; | ||
5619 | } | ||
5620 | |||
5621 | r = of_platform_populate(dsidev->dev.of_node, NULL, NULL, | ||
5622 | &dsidev->dev); | ||
5623 | if (r) | ||
5624 | DSSERR("Failed to populate DSI child devices: %d\n", r); | ||
5625 | } | ||
5626 | |||
5519 | dsi_runtime_put(dsidev); | 5627 | dsi_runtime_put(dsidev); |
5520 | 5628 | ||
5521 | if (dsi->module_id == 0) | 5629 | if (dsi->module_id == 0) |
@@ -5529,17 +5637,31 @@ static int omap_dsihw_probe(struct platform_device *dsidev) | |||
5529 | else if (dsi->module_id == 1) | 5637 | else if (dsi->module_id == 1) |
5530 | dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); | 5638 | dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); |
5531 | #endif | 5639 | #endif |
5640 | |||
5532 | return 0; | 5641 | return 0; |
5533 | 5642 | ||
5643 | err_probe_of: | ||
5644 | dsi_uninit_output(dsidev); | ||
5645 | dsi_runtime_put(dsidev); | ||
5646 | |||
5534 | err_runtime_get: | 5647 | err_runtime_get: |
5535 | pm_runtime_disable(&dsidev->dev); | 5648 | pm_runtime_disable(&dsidev->dev); |
5536 | return r; | 5649 | return r; |
5537 | } | 5650 | } |
5538 | 5651 | ||
5652 | static int dsi_unregister_child(struct device *dev, void *data) | ||
5653 | { | ||
5654 | struct platform_device *pdev = to_platform_device(dev); | ||
5655 | platform_device_unregister(pdev); | ||
5656 | return 0; | ||
5657 | } | ||
5658 | |||
5539 | static int __exit omap_dsihw_remove(struct platform_device *dsidev) | 5659 | static int __exit omap_dsihw_remove(struct platform_device *dsidev) |
5540 | { | 5660 | { |
5541 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5661 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
5542 | 5662 | ||
5663 | device_for_each_child(&dsidev->dev, NULL, dsi_unregister_child); | ||
5664 | |||
5543 | WARN_ON(dsi->scp_clk_refcount > 0); | 5665 | WARN_ON(dsi->scp_clk_refcount > 0); |
5544 | 5666 | ||
5545 | dsi_uninit_output(dsidev); | 5667 | dsi_uninit_output(dsidev); |
@@ -5577,6 +5699,23 @@ static const struct dev_pm_ops dsi_pm_ops = { | |||
5577 | .runtime_resume = dsi_runtime_resume, | 5699 | .runtime_resume = dsi_runtime_resume, |
5578 | }; | 5700 | }; |
5579 | 5701 | ||
5702 | static const struct dsi_module_id_data dsi_of_data_omap3[] = { | ||
5703 | { .address = 0x4804fc00, .id = 0, }, | ||
5704 | { }, | ||
5705 | }; | ||
5706 | |||
5707 | static const struct dsi_module_id_data dsi_of_data_omap4[] = { | ||
5708 | { .address = 0x58004000, .id = 0, }, | ||
5709 | { .address = 0x58005000, .id = 1, }, | ||
5710 | { }, | ||
5711 | }; | ||
5712 | |||
5713 | static const struct of_device_id dsi_of_match[] = { | ||
5714 | { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, }, | ||
5715 | { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, }, | ||
5716 | {}, | ||
5717 | }; | ||
5718 | |||
5580 | static struct platform_driver omap_dsihw_driver = { | 5719 | static struct platform_driver omap_dsihw_driver = { |
5581 | .probe = omap_dsihw_probe, | 5720 | .probe = omap_dsihw_probe, |
5582 | .remove = __exit_p(omap_dsihw_remove), | 5721 | .remove = __exit_p(omap_dsihw_remove), |
@@ -5584,6 +5723,7 @@ static struct platform_driver omap_dsihw_driver = { | |||
5584 | .name = "omapdss_dsi", | 5723 | .name = "omapdss_dsi", |
5585 | .owner = THIS_MODULE, | 5724 | .owner = THIS_MODULE, |
5586 | .pm = &dsi_pm_ops, | 5725 | .pm = &dsi_pm_ops, |
5726 | .of_match_table = dsi_of_match, | ||
5587 | }, | 5727 | }, |
5588 | }; | 5728 | }; |
5589 | 5729 | ||
diff --git a/drivers/video/omap2/dss/dss-of.c b/drivers/video/omap2/dss/dss-of.c new file mode 100644 index 000000000000..a4b20aaf6142 --- /dev/null +++ b/drivers/video/omap2/dss/dss-of.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 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 | |||
15 | #include <linux/device.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | |||
21 | #include <video/omapdss.h> | ||
22 | |||
23 | struct device_node * | ||
24 | omapdss_of_get_next_port(const struct device_node *parent, | ||
25 | struct device_node *prev) | ||
26 | { | ||
27 | struct device_node *port = NULL; | ||
28 | |||
29 | if (!parent) | ||
30 | return NULL; | ||
31 | |||
32 | if (!prev) { | ||
33 | struct device_node *ports; | ||
34 | /* | ||
35 | * It's the first call, we have to find a port subnode | ||
36 | * within this node or within an optional 'ports' node. | ||
37 | */ | ||
38 | ports = of_get_child_by_name(parent, "ports"); | ||
39 | if (ports) | ||
40 | parent = ports; | ||
41 | |||
42 | port = of_get_child_by_name(parent, "port"); | ||
43 | |||
44 | /* release the 'ports' node */ | ||
45 | of_node_put(ports); | ||
46 | } else { | ||
47 | struct device_node *ports; | ||
48 | |||
49 | ports = of_get_parent(prev); | ||
50 | if (!ports) | ||
51 | return NULL; | ||
52 | |||
53 | do { | ||
54 | port = of_get_next_child(ports, prev); | ||
55 | if (!port) { | ||
56 | of_node_put(ports); | ||
57 | return NULL; | ||
58 | } | ||
59 | prev = port; | ||
60 | } while (of_node_cmp(port->name, "port") != 0); | ||
61 | } | ||
62 | |||
63 | return port; | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(omapdss_of_get_next_port); | ||
66 | |||
67 | struct device_node * | ||
68 | omapdss_of_get_next_endpoint(const struct device_node *parent, | ||
69 | struct device_node *prev) | ||
70 | { | ||
71 | struct device_node *ep = NULL; | ||
72 | |||
73 | if (!parent) | ||
74 | return NULL; | ||
75 | |||
76 | do { | ||
77 | ep = of_get_next_child(parent, prev); | ||
78 | if (!ep) | ||
79 | return NULL; | ||
80 | prev = ep; | ||
81 | } while (of_node_cmp(ep->name, "endpoint") != 0); | ||
82 | |||
83 | return ep; | ||
84 | } | ||
85 | EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); | ||
86 | |||
87 | static struct device_node * | ||
88 | omapdss_of_get_remote_device_node(const struct device_node *node) | ||
89 | { | ||
90 | struct device_node *np; | ||
91 | int i; | ||
92 | |||
93 | np = of_parse_phandle(node, "remote-endpoint", 0); | ||
94 | |||
95 | if (!np) | ||
96 | return NULL; | ||
97 | |||
98 | np = of_get_next_parent(np); | ||
99 | |||
100 | for (i = 0; i < 3 && np; ++i) { | ||
101 | struct property *prop; | ||
102 | |||
103 | prop = of_find_property(np, "compatible", NULL); | ||
104 | |||
105 | if (prop) | ||
106 | return np; | ||
107 | |||
108 | np = of_get_next_parent(np); | ||
109 | } | ||
110 | |||
111 | return NULL; | ||
112 | } | ||
113 | |||
114 | struct device_node * | ||
115 | omapdss_of_get_first_endpoint(const struct device_node *parent) | ||
116 | { | ||
117 | struct device_node *port, *ep; | ||
118 | |||
119 | port = omapdss_of_get_next_port(parent, NULL); | ||
120 | |||
121 | if (!port) | ||
122 | return NULL; | ||
123 | |||
124 | ep = omapdss_of_get_next_endpoint(port, NULL); | ||
125 | |||
126 | of_node_put(port); | ||
127 | |||
128 | return ep; | ||
129 | } | ||
130 | EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint); | ||
131 | |||
132 | struct omap_dss_device * | ||
133 | omapdss_of_find_source_for_first_ep(struct device_node *node) | ||
134 | { | ||
135 | struct device_node *ep; | ||
136 | struct device_node *src_node; | ||
137 | struct omap_dss_device *src; | ||
138 | |||
139 | ep = omapdss_of_get_first_endpoint(node); | ||
140 | if (!ep) | ||
141 | return ERR_PTR(-EINVAL); | ||
142 | |||
143 | src_node = omapdss_of_get_remote_device_node(ep); | ||
144 | |||
145 | of_node_put(ep); | ||
146 | |||
147 | if (!src_node) | ||
148 | return ERR_PTR(-EINVAL); | ||
149 | |||
150 | src = omap_dss_find_output_by_node(src_node); | ||
151 | |||
152 | of_node_put(src_node); | ||
153 | |||
154 | if (!src) | ||
155 | return ERR_PTR(-EPROBE_DEFER); | ||
156 | |||
157 | return src; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep); | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 96e400c51001..32b4ff0606ab 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #define DSS_SUBSYS_NAME "DSS" | 23 | #define DSS_SUBSYS_NAME "DSS" |
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | ||
26 | #include <linux/io.h> | 27 | #include <linux/io.h> |
27 | #include <linux/export.h> | 28 | #include <linux/export.h> |
28 | #include <linux/err.h> | 29 | #include <linux/err.h> |
@@ -33,6 +34,7 @@ | |||
33 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
34 | #include <linux/gfp.h> | 35 | #include <linux/gfp.h> |
35 | #include <linux/sizes.h> | 36 | #include <linux/sizes.h> |
37 | #include <linux/of.h> | ||
36 | 38 | ||
37 | #include <video/omapdss.h> | 39 | #include <video/omapdss.h> |
38 | 40 | ||
@@ -772,6 +774,56 @@ static int __init dss_init_features(struct platform_device *pdev) | |||
772 | return 0; | 774 | return 0; |
773 | } | 775 | } |
774 | 776 | ||
777 | static int dss_init_ports(struct platform_device *pdev) | ||
778 | { | ||
779 | struct device_node *parent = pdev->dev.of_node; | ||
780 | struct device_node *port; | ||
781 | int r; | ||
782 | |||
783 | if (parent == NULL) | ||
784 | return 0; | ||
785 | |||
786 | port = omapdss_of_get_next_port(parent, NULL); | ||
787 | if (!port) { | ||
788 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
789 | dpi_init_port(pdev, parent); | ||
790 | #endif | ||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | do { | ||
795 | u32 reg; | ||
796 | |||
797 | r = of_property_read_u32(port, "reg", ®); | ||
798 | if (r) | ||
799 | reg = 0; | ||
800 | |||
801 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
802 | if (reg == 0) | ||
803 | dpi_init_port(pdev, port); | ||
804 | #endif | ||
805 | |||
806 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
807 | if (reg == 1) | ||
808 | sdi_init_port(pdev, port); | ||
809 | #endif | ||
810 | |||
811 | } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); | ||
812 | |||
813 | return 0; | ||
814 | } | ||
815 | |||
816 | static void dss_uninit_ports(void) | ||
817 | { | ||
818 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
819 | dpi_uninit_port(); | ||
820 | #endif | ||
821 | |||
822 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
823 | sdi_uninit_port(); | ||
824 | #endif | ||
825 | } | ||
826 | |||
775 | /* DSS HW IP initialisation */ | 827 | /* DSS HW IP initialisation */ |
776 | static int __init omap_dsshw_probe(struct platform_device *pdev) | 828 | static int __init omap_dsshw_probe(struct platform_device *pdev) |
777 | { | 829 | { |
@@ -830,6 +882,8 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
830 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; | 882 | dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; |
831 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; | 883 | dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; |
832 | 884 | ||
885 | dss_init_ports(pdev); | ||
886 | |||
833 | rev = dss_read_reg(DSS_REVISION); | 887 | rev = dss_read_reg(DSS_REVISION); |
834 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", | 888 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", |
835 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 889 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
@@ -849,6 +903,8 @@ err_setup_clocks: | |||
849 | 903 | ||
850 | static int __exit omap_dsshw_remove(struct platform_device *pdev) | 904 | static int __exit omap_dsshw_remove(struct platform_device *pdev) |
851 | { | 905 | { |
906 | dss_uninit_ports(); | ||
907 | |||
852 | pm_runtime_disable(&pdev->dev); | 908 | pm_runtime_disable(&pdev->dev); |
853 | 909 | ||
854 | dss_put_clocks(); | 910 | dss_put_clocks(); |
@@ -886,12 +942,22 @@ static const struct dev_pm_ops dss_pm_ops = { | |||
886 | .runtime_resume = dss_runtime_resume, | 942 | .runtime_resume = dss_runtime_resume, |
887 | }; | 943 | }; |
888 | 944 | ||
945 | static const struct of_device_id dss_of_match[] = { | ||
946 | { .compatible = "ti,omap2-dss", }, | ||
947 | { .compatible = "ti,omap3-dss", }, | ||
948 | { .compatible = "ti,omap4-dss", }, | ||
949 | {}, | ||
950 | }; | ||
951 | |||
952 | MODULE_DEVICE_TABLE(of, dss_of_match); | ||
953 | |||
889 | static struct platform_driver omap_dsshw_driver = { | 954 | static struct platform_driver omap_dsshw_driver = { |
890 | .remove = __exit_p(omap_dsshw_remove), | 955 | .remove = __exit_p(omap_dsshw_remove), |
891 | .driver = { | 956 | .driver = { |
892 | .name = "omapdss_dss", | 957 | .name = "omapdss_dss", |
893 | .owner = THIS_MODULE, | 958 | .owner = THIS_MODULE, |
894 | .pm = &dss_pm_ops, | 959 | .pm = &dss_pm_ops, |
960 | .of_match_table = dss_of_match, | ||
895 | }, | 961 | }, |
896 | }; | 962 | }; |
897 | 963 | ||
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 570f7ed2bcbc..918fec182424 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -250,6 +250,9 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min, | |||
250 | int sdi_init_platform_driver(void) __init; | 250 | int sdi_init_platform_driver(void) __init; |
251 | void sdi_uninit_platform_driver(void) __exit; | 251 | void sdi_uninit_platform_driver(void) __exit; |
252 | 252 | ||
253 | int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init; | ||
254 | void sdi_uninit_port(void) __exit; | ||
255 | |||
253 | /* DSI */ | 256 | /* DSI */ |
254 | 257 | ||
255 | typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, | 258 | typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, |
@@ -361,6 +364,9 @@ static inline bool dsi_pll_calc(struct platform_device *dsidev, | |||
361 | int dpi_init_platform_driver(void) __init; | 364 | int dpi_init_platform_driver(void) __init; |
362 | void dpi_uninit_platform_driver(void) __exit; | 365 | void dpi_uninit_platform_driver(void) __exit; |
363 | 366 | ||
367 | int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; | ||
368 | void dpi_uninit_port(void) __exit; | ||
369 | |||
364 | /* DISPC */ | 370 | /* DISPC */ |
365 | int dispc_init_platform_driver(void) __init; | 371 | int dispc_init_platform_driver(void) __init; |
366 | void dispc_uninit_platform_driver(void) __exit; | 372 | void dispc_uninit_platform_driver(void) __exit; |
diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/omap2/dss/hdmi4.c index 895c252ae0a8..e9c3d9e6d450 100644 --- a/drivers/video/omap2/dss/hdmi4.c +++ b/drivers/video/omap2/dss/hdmi4.c | |||
@@ -88,7 +88,10 @@ static int hdmi_init_regulator(void) | |||
88 | if (hdmi.vdda_hdmi_dac_reg != NULL) | 88 | if (hdmi.vdda_hdmi_dac_reg != NULL) |
89 | return 0; | 89 | return 0; |
90 | 90 | ||
91 | reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); | 91 | if (hdmi.pdev->dev.of_node) |
92 | reg = devm_regulator_get(&hdmi.pdev->dev, "vdda"); | ||
93 | else | ||
94 | reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); | ||
92 | 95 | ||
93 | /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ | 96 | /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ |
94 | if (IS_ERR(reg)) | 97 | if (IS_ERR(reg)) |
@@ -680,6 +683,11 @@ static const struct dev_pm_ops hdmi_pm_ops = { | |||
680 | .runtime_resume = hdmi_runtime_resume, | 683 | .runtime_resume = hdmi_runtime_resume, |
681 | }; | 684 | }; |
682 | 685 | ||
686 | static const struct of_device_id hdmi_of_match[] = { | ||
687 | { .compatible = "ti,omap4-hdmi", }, | ||
688 | {}, | ||
689 | }; | ||
690 | |||
683 | static struct platform_driver omapdss_hdmihw_driver = { | 691 | static struct platform_driver omapdss_hdmihw_driver = { |
684 | .probe = omapdss_hdmihw_probe, | 692 | .probe = omapdss_hdmihw_probe, |
685 | .remove = __exit_p(omapdss_hdmihw_remove), | 693 | .remove = __exit_p(omapdss_hdmihw_remove), |
@@ -687,6 +695,7 @@ static struct platform_driver omapdss_hdmihw_driver = { | |||
687 | .name = "omapdss_hdmi", | 695 | .name = "omapdss_hdmi", |
688 | .owner = THIS_MODULE, | 696 | .owner = THIS_MODULE, |
689 | .pm = &hdmi_pm_ops, | 697 | .pm = &hdmi_pm_ops, |
698 | .of_match_table = hdmi_of_match, | ||
690 | }, | 699 | }, |
691 | }; | 700 | }; |
692 | 701 | ||
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 800b2bb4ed93..911dcc9173a6 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/of.h> | ||
29 | 30 | ||
30 | #include <video/omapdss.h> | 31 | #include <video/omapdss.h> |
31 | #include "dss.h" | 32 | #include "dss.h" |
@@ -41,12 +42,14 @@ static struct { | |||
41 | int datapairs; | 42 | int datapairs; |
42 | 43 | ||
43 | struct omap_dss_device output; | 44 | struct omap_dss_device output; |
45 | |||
46 | bool port_initialized; | ||
44 | } sdi; | 47 | } sdi; |
45 | 48 | ||
46 | struct sdi_clk_calc_ctx { | 49 | struct sdi_clk_calc_ctx { |
47 | unsigned long pck_min, pck_max; | 50 | unsigned long pck_min, pck_max; |
48 | 51 | ||
49 | unsigned long long fck; | 52 | unsigned long fck; |
50 | struct dispc_clock_info dispc_cinfo; | 53 | struct dispc_clock_info dispc_cinfo; |
51 | }; | 54 | }; |
52 | 55 | ||
@@ -386,3 +389,45 @@ void __exit sdi_uninit_platform_driver(void) | |||
386 | { | 389 | { |
387 | platform_driver_unregister(&omap_sdi_driver); | 390 | platform_driver_unregister(&omap_sdi_driver); |
388 | } | 391 | } |
392 | |||
393 | int __init sdi_init_port(struct platform_device *pdev, struct device_node *port) | ||
394 | { | ||
395 | struct device_node *ep; | ||
396 | u32 datapairs; | ||
397 | int r; | ||
398 | |||
399 | ep = omapdss_of_get_next_endpoint(port, NULL); | ||
400 | if (!ep) | ||
401 | return 0; | ||
402 | |||
403 | r = of_property_read_u32(ep, "datapairs", &datapairs); | ||
404 | if (r) { | ||
405 | DSSERR("failed to parse datapairs\n"); | ||
406 | goto err_datapairs; | ||
407 | } | ||
408 | |||
409 | sdi.datapairs = datapairs; | ||
410 | |||
411 | of_node_put(ep); | ||
412 | |||
413 | sdi.pdev = pdev; | ||
414 | |||
415 | sdi_init_output(pdev); | ||
416 | |||
417 | sdi.port_initialized = true; | ||
418 | |||
419 | return 0; | ||
420 | |||
421 | err_datapairs: | ||
422 | of_node_put(ep); | ||
423 | |||
424 | return r; | ||
425 | } | ||
426 | |||
427 | void __exit sdi_uninit_port(void) | ||
428 | { | ||
429 | if (!sdi.port_initialized) | ||
430 | return; | ||
431 | |||
432 | sdi_uninit_output(sdi.pdev); | ||
433 | } | ||
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 59ade34bd536..21d81113962b 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
35 | #include <linux/regulator/consumer.h> | 35 | #include <linux/regulator/consumer.h> |
36 | #include <linux/pm_runtime.h> | 36 | #include <linux/pm_runtime.h> |
37 | #include <linux/of.h> | ||
37 | 38 | ||
38 | #include <video/omapdss.h> | 39 | #include <video/omapdss.h> |
39 | 40 | ||
@@ -636,7 +637,10 @@ static int venc_init_regulator(void) | |||
636 | if (venc.vdda_dac_reg != NULL) | 637 | if (venc.vdda_dac_reg != NULL) |
637 | return 0; | 638 | return 0; |
638 | 639 | ||
639 | vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac"); | 640 | if (venc.pdev->dev.of_node) |
641 | vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda"); | ||
642 | else | ||
643 | vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac"); | ||
640 | 644 | ||
641 | if (IS_ERR(vdda_dac)) { | 645 | if (IS_ERR(vdda_dac)) { |
642 | if (PTR_ERR(vdda_dac) != -EPROBE_DEFER) | 646 | if (PTR_ERR(vdda_dac) != -EPROBE_DEFER) |
@@ -805,6 +809,48 @@ static void __exit venc_uninit_output(struct platform_device *pdev) | |||
805 | omapdss_unregister_output(out); | 809 | omapdss_unregister_output(out); |
806 | } | 810 | } |
807 | 811 | ||
812 | static int venc_probe_of(struct platform_device *pdev) | ||
813 | { | ||
814 | struct device_node *node = pdev->dev.of_node; | ||
815 | struct device_node *ep; | ||
816 | u32 channels; | ||
817 | int r; | ||
818 | |||
819 | ep = omapdss_of_get_first_endpoint(node); | ||
820 | if (!ep) | ||
821 | return 0; | ||
822 | |||
823 | venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity"); | ||
824 | |||
825 | r = of_property_read_u32(ep, "ti,channels", &channels); | ||
826 | if (r) { | ||
827 | dev_err(&pdev->dev, | ||
828 | "failed to read property 'ti,channels': %d\n", r); | ||
829 | goto err; | ||
830 | } | ||
831 | |||
832 | switch (channels) { | ||
833 | case 1: | ||
834 | venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE; | ||
835 | break; | ||
836 | case 2: | ||
837 | venc.type = OMAP_DSS_VENC_TYPE_SVIDEO; | ||
838 | break; | ||
839 | default: | ||
840 | dev_err(&pdev->dev, "bad channel propert '%d'\n", channels); | ||
841 | r = -EINVAL; | ||
842 | goto err; | ||
843 | } | ||
844 | |||
845 | of_node_put(ep); | ||
846 | |||
847 | return 0; | ||
848 | err: | ||
849 | of_node_put(ep); | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
808 | /* VENC HW IP initialisation */ | 854 | /* VENC HW IP initialisation */ |
809 | static int omap_venchw_probe(struct platform_device *pdev) | 855 | static int omap_venchw_probe(struct platform_device *pdev) |
810 | { | 856 | { |
@@ -846,12 +892,21 @@ static int omap_venchw_probe(struct platform_device *pdev) | |||
846 | 892 | ||
847 | venc_runtime_put(); | 893 | venc_runtime_put(); |
848 | 894 | ||
895 | if (pdev->dev.of_node) { | ||
896 | r = venc_probe_of(pdev); | ||
897 | if (r) { | ||
898 | DSSERR("Invalid DT data\n"); | ||
899 | goto err_probe_of; | ||
900 | } | ||
901 | } | ||
902 | |||
849 | dss_debugfs_create_file("venc", venc_dump_regs); | 903 | dss_debugfs_create_file("venc", venc_dump_regs); |
850 | 904 | ||
851 | venc_init_output(pdev); | 905 | venc_init_output(pdev); |
852 | 906 | ||
853 | return 0; | 907 | return 0; |
854 | 908 | ||
909 | err_probe_of: | ||
855 | err_runtime_get: | 910 | err_runtime_get: |
856 | pm_runtime_disable(&pdev->dev); | 911 | pm_runtime_disable(&pdev->dev); |
857 | return r; | 912 | return r; |
@@ -895,6 +950,14 @@ static const struct dev_pm_ops venc_pm_ops = { | |||
895 | .runtime_resume = venc_runtime_resume, | 950 | .runtime_resume = venc_runtime_resume, |
896 | }; | 951 | }; |
897 | 952 | ||
953 | |||
954 | static const struct of_device_id venc_of_match[] = { | ||
955 | { .compatible = "ti,omap2-venc", }, | ||
956 | { .compatible = "ti,omap3-venc", }, | ||
957 | { .compatible = "ti,omap4-venc", }, | ||
958 | {}, | ||
959 | }; | ||
960 | |||
898 | static struct platform_driver omap_venchw_driver = { | 961 | static struct platform_driver omap_venchw_driver = { |
899 | .probe = omap_venchw_probe, | 962 | .probe = omap_venchw_probe, |
900 | .remove = __exit_p(omap_venchw_remove), | 963 | .remove = __exit_p(omap_venchw_remove), |
@@ -902,6 +965,7 @@ static struct platform_driver omap_venchw_driver = { | |||
902 | .name = "omapdss_venc", | 965 | .name = "omapdss_venc", |
903 | .owner = THIS_MODULE, | 966 | .owner = THIS_MODULE, |
904 | .pm = &venc_pm_ops, | 967 | .pm = &venc_pm_ops, |
968 | .of_match_table = venc_of_match, | ||
905 | }, | 969 | }, |
906 | }; | 970 | }; |
907 | 971 | ||
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 8d02f164c8c6..ec2d132c782d 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -2417,6 +2417,55 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, | |||
2417 | return 0; | 2417 | return 0; |
2418 | } | 2418 | } |
2419 | 2419 | ||
2420 | static struct omap_dss_device * | ||
2421 | omapfb_find_default_display(struct omapfb2_device *fbdev) | ||
2422 | { | ||
2423 | const char *def_name; | ||
2424 | int i; | ||
2425 | |||
2426 | /* | ||
2427 | * Search with the display name from the user or the board file, | ||
2428 | * comparing to display names and aliases | ||
2429 | */ | ||
2430 | |||
2431 | def_name = omapdss_get_default_display_name(); | ||
2432 | |||
2433 | if (def_name) { | ||
2434 | for (i = 0; i < fbdev->num_displays; ++i) { | ||
2435 | struct omap_dss_device *dssdev; | ||
2436 | |||
2437 | dssdev = fbdev->displays[i].dssdev; | ||
2438 | |||
2439 | if (dssdev->name && strcmp(def_name, dssdev->name) == 0) | ||
2440 | return dssdev; | ||
2441 | |||
2442 | if (strcmp(def_name, dssdev->alias) == 0) | ||
2443 | return dssdev; | ||
2444 | } | ||
2445 | |||
2446 | /* def_name given but not found */ | ||
2447 | return NULL; | ||
2448 | } | ||
2449 | |||
2450 | /* then look for DT alias display0 */ | ||
2451 | for (i = 0; i < fbdev->num_displays; ++i) { | ||
2452 | struct omap_dss_device *dssdev; | ||
2453 | int id; | ||
2454 | |||
2455 | dssdev = fbdev->displays[i].dssdev; | ||
2456 | |||
2457 | if (dssdev->dev->of_node == NULL) | ||
2458 | continue; | ||
2459 | |||
2460 | id = of_alias_get_id(dssdev->dev->of_node, "display"); | ||
2461 | if (id == 0) | ||
2462 | return dssdev; | ||
2463 | } | ||
2464 | |||
2465 | /* return the first display we have in the list */ | ||
2466 | return fbdev->displays[0].dssdev; | ||
2467 | } | ||
2468 | |||
2420 | static int omapfb_probe(struct platform_device *pdev) | 2469 | static int omapfb_probe(struct platform_device *pdev) |
2421 | { | 2470 | { |
2422 | struct omapfb2_device *fbdev = NULL; | 2471 | struct omapfb2_device *fbdev = NULL; |
@@ -2494,23 +2543,7 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2494 | for (i = 0; i < fbdev->num_managers; i++) | 2543 | for (i = 0; i < fbdev->num_managers; i++) |
2495 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); | 2544 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); |
2496 | 2545 | ||
2497 | def_display = NULL; | 2546 | def_display = omapfb_find_default_display(fbdev); |
2498 | |||
2499 | for (i = 0; i < fbdev->num_displays; ++i) { | ||
2500 | struct omap_dss_device *dssdev; | ||
2501 | const char *def_name; | ||
2502 | |||
2503 | def_name = omapdss_get_default_display_name(); | ||
2504 | |||
2505 | dssdev = fbdev->displays[i].dssdev; | ||
2506 | |||
2507 | if (def_name == NULL || | ||
2508 | (dssdev->name && strcmp(def_name, dssdev->name) == 0)) { | ||
2509 | def_display = dssdev; | ||
2510 | break; | ||
2511 | } | ||
2512 | } | ||
2513 | |||
2514 | if (def_display == NULL) { | 2547 | if (def_display == NULL) { |
2515 | dev_err(fbdev->dev, "failed to find default display\n"); | 2548 | dev_err(fbdev->dev, "failed to find default display\n"); |
2516 | r = -EPROBE_DEFER; | 2549 | r = -EPROBE_DEFER; |