diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 21:47:51 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-07 21:47:51 +0400 |
commit | 0af9fb63915cf5ebb47b5c9ff16526b47545baf5 (patch) | |
tree | 2e05c80a4b3ef074e7535c0222e37150cdec09e7 /drivers/video | |
parent | e5744abb2fa3629aa5a94e21ca1eae32ff2fe00b (diff) | |
parent | 0f5d9d2e7d234acb26bc98dd820cc8dd178774d6 (diff) | |
download | linux-0af9fb63915cf5ebb47b5c9ff16526b47545baf5.tar.xz |
Merge tag 'fbdev-omap-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux
Pull OMAP fbdev changes from Tomi Valkeinen:
"This is based on the already pulled fbdev-main changes, and this also
merges .dts branch from Tony Lindgren (which has also been pulled), so
that I was able to add the display related .dts changes.
This contains OMAP related fbdev changes for 3.15. The bulk of the
patches are for adding Device Tree support for OMAP Display Subsystem:
- SoCs: OMAP2/3/4
- Boards: OMAP4 Panda, OMAP4 SDP, OMAP3 Beagle, OMAP3 Beagle-xM,
OMAP3 IGEP0020, OMAP3 N900
- Devices: TFP410 Encoder, tpd12s015 HDMI companion chip, Sony
acx565akm panel, MIPI DSI Command mode panel and HDMI, DVI and
Analog TV connectors"
* tag 'fbdev-omap-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (45 commits)
OMAPDSS: HDMI: fix interlace output
OMAPDSS: add missing __init for dss_init_ports
ARM: OMAP2+: remove pdata quirks for displays
OMAPDSS: remove DT hacks for regulators
Doc/DT: Add DT binding documentation for tpd12s015 encoder
Doc/DT: Add DT binding documentation for TFP410 encoder
Doc/DT: Add DT binding documentation for Sony acx565akm panel
Doc/DT: Add DT binding documentation for MIPI DSI CM Panel
Doc/DT: Add DT binding documentation for HDMI Connector
Doc/DT: Add DT binding documentation for DVI Connector
Doc/DT: Add DT binding documentation for Analog TV Connector
ARM: omap3-n900.dts: add display information
ARM: omap3-igep0020.dts: add display information
ARM: omap3-beagle-xm.dts: add display information
ARM: omap3-beagle.dts: add display information
ARM: omap4-sdp.dts: add display information
Doc/DT: Add DT binding documentation for OMAP DSS
OMAPDSS: acx565akm: Add DT support
OMAPDSS: connector-analog-tv: Add DT support
OMAPDSS: hdmi-connector: Add DT support
...
Diffstat (limited to 'drivers/video')
20 files changed, 923 insertions, 42 deletions
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 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <video/omapdss.h> #include <video/omap-panel-data.h> @@ -42,6 +43,12 @@ static const struct omap_video_timings tvc_pal_timings = { .interlace = true, }; +static const struct of_device_id tvc_of_match[]; + +struct tvc_of_data { + enum omap_dss_venc_type connector_type; +}; + #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) static int tvc_connect(struct omap_dss_device *dssdev) @@ -91,8 +98,12 @@ static int tvc_enable(struct omap_dss_device *dssdev) in->ops.atv->set_timings(in, &ddata->timings); - in->ops.atv->set_type(in, ddata->connector_type); - in->ops.atv->invert_vid_out_polarity(in, ddata->invert_polarity); + if (!ddata->dev->of_node) { + in->ops.atv->set_type(in, ddata->connector_type); + + in->ops.atv->invert_vid_out_polarity(in, + ddata->invert_polarity); + } r = in->ops.atv->enable(in); if (r) @@ -205,6 +216,23 @@ static int tvc_probe_pdata(struct platform_device *pdev) return 0; } +static int tvc_probe_of(struct platform_device *pdev) +{ + struct panel_drv_data *ddata = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + struct omap_dss_device *in; + + in = omapdss_of_find_source_for_first_ep(node); + if (IS_ERR(in)) { + dev_err(&pdev->dev, "failed to find video source\n"); + return PTR_ERR(in); + } + + ddata->in = in; + + return 0; +} + static int tvc_probe(struct platform_device *pdev) { struct panel_drv_data *ddata; @@ -222,6 +250,10 @@ static int tvc_probe(struct platform_device *pdev) r = tvc_probe_pdata(pdev); if (r) return r; + } else if (pdev->dev.of_node) { + r = tvc_probe_of(pdev); + if (r) + return r; } else { return -ENODEV; } @@ -263,12 +295,19 @@ static int __exit tvc_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id tvc_of_match[] = { + { .compatible = "omapdss,svideo-connector", }, + { .compatible = "omapdss,composite-video-connector", }, + {}, +}; + static struct platform_driver tvc_connector_driver = { .probe = tvc_probe, .remove = __exit_p(tvc_remove), .driver = { .name = "connector-analog-tv", .owner = THIS_MODULE, + .of_match_table = tvc_of_match, }, }; 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) return 0; } +static int dvic_probe_of(struct platform_device *pdev) +{ + struct panel_drv_data *ddata = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + struct omap_dss_device *in; + struct device_node *adapter_node; + struct i2c_adapter *adapter; + + in = omapdss_of_find_source_for_first_ep(node); + if (IS_ERR(in)) { + dev_err(&pdev->dev, "failed to find video source\n"); + return PTR_ERR(in); + } + + ddata->in = in; + + adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0); + if (adapter_node) { + adapter = of_find_i2c_adapter_by_node(adapter_node); + if (adapter == NULL) { + dev_err(&pdev->dev, "failed to parse ddc-i2c-bus\n"); + omap_dss_put_device(ddata->in); + return -EPROBE_DEFER; + } + + ddata->i2c_adapter = adapter; + } + + return 0; +} + static int dvic_probe(struct platform_device *pdev) { struct panel_drv_data *ddata; @@ -293,6 +324,10 @@ static int dvic_probe(struct platform_device *pdev) r = dvic_probe_pdata(pdev); if (r) return r; + } else if (pdev->dev.of_node) { + r = dvic_probe_of(pdev); + if (r) + return r; } else { return -ENODEV; } @@ -342,12 +377,20 @@ static int __exit dvic_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id dvic_of_match[] = { + { .compatible = "omapdss,dvi-connector", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, dvic_of_match); + static struct platform_driver dvi_connector_driver = { .probe = dvic_probe, .remove = __exit_p(dvic_remove), .driver = { .name = "connector-dvi", .owner = THIS_MODULE, + .of_match_table = dvic_of_match, }, }; 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 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <drm/drm_edid.h> @@ -301,6 +302,23 @@ static int hdmic_probe_pdata(struct platform_device *pdev) return 0; } +static int hdmic_probe_of(struct platform_device *pdev) +{ + struct panel_drv_data *ddata = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + struct omap_dss_device *in; + + in = omapdss_of_find_source_for_first_ep(node); + if (IS_ERR(in)) { + dev_err(&pdev->dev, "failed to find video source\n"); + return PTR_ERR(in); + } + + ddata->in = in; + + return 0; +} + static int hdmic_probe(struct platform_device *pdev) { struct panel_drv_data *ddata; @@ -318,6 +336,10 @@ static int hdmic_probe(struct platform_device *pdev) r = hdmic_probe_pdata(pdev); if (r) return r; + } else if (pdev->dev.of_node) { + r = hdmic_probe_of(pdev); + if (r) + return r; } else { return -ENODEV; } @@ -359,12 +381,20 @@ static int __exit hdmic_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id hdmic_of_match[] = { + { .compatible = "omapdss,hdmi-connector", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, hdmic_of_match); + static struct platform_driver hdmi_connector_driver = { .probe = hdmic_probe, .remove = __exit_p(hdmic_remove), .driver = { .name = "connector-hdmi", .owner = THIS_MODULE, + .of_match_table = hdmic_of_match, }, }; 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 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/of_gpio.h> #include <video/omapdss.h> #include <video/omap-panel-data.h> @@ -82,7 +83,8 @@ static int tfp410_enable(struct omap_dss_device *dssdev) return 0; in->ops.dpi->set_timings(in, &ddata->timings); - in->ops.dpi->set_data_lines(in, ddata->data_lines); + if (ddata->data_lines) + in->ops.dpi->set_data_lines(in, ddata->data_lines); r = in->ops.dpi->enable(in); if (r) @@ -179,6 +181,33 @@ static int tfp410_probe_pdata(struct platform_device *pdev) return 0; } +static int tfp410_probe_of(struct platform_device *pdev) +{ + struct panel_drv_data *ddata = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + struct omap_dss_device *in; + int gpio; + + gpio = of_get_named_gpio(node, "powerdown-gpios", 0); + + if (gpio_is_valid(gpio) || gpio == -ENOENT) { + ddata->pd_gpio = gpio; + } else { + dev_err(&pdev->dev, "failed to parse PD gpio\n"); + return gpio; + } + + in = omapdss_of_find_source_for_first_ep(node); + if (IS_ERR(in)) { + dev_err(&pdev->dev, "failed to find video source\n"); + return PTR_ERR(in); + } + + ddata->in = in; + + return 0; +} + static int tfp410_probe(struct platform_device *pdev) { struct panel_drv_data *ddata; @@ -195,6 +224,10 @@ static int tfp410_probe(struct platform_device *pdev) r = tfp410_probe_pdata(pdev); if (r) return r; + } else if (pdev->dev.of_node) { + r = tfp410_probe_of(pdev); + if (r) + return r; } else { return -ENODEV; } @@ -251,12 +284,20 @@ static int __exit tfp410_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id tfp410_of_match[] = { + { .compatible = "omapdss,ti,tfp410", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, tfp410_of_match); + static struct platform_driver tfp410_driver = { .probe = tfp410_probe, .remove = __exit_p(tfp410_remove), .driver = { .name = "tfp410", .owner = THIS_MODULE, + .of_match_table = tfp410_of_match, }, }; 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 @@ #include <linux/slab.h> #include <linux/gpio.h> #include <linux/platform_device.h> +#include <linux/of_gpio.h> #include <video/omapdss.h> #include <video/omap-panel-data.h> @@ -289,6 +290,49 @@ static int tpd_probe_pdata(struct platform_device *pdev) return 0; } +static int tpd_probe_of(struct platform_device *pdev) +{ + struct panel_drv_data *ddata = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + struct omap_dss_device *in; + int gpio; + + /* CT CP HPD GPIO */ + gpio = of_get_gpio(node, 0); + if (!gpio_is_valid(gpio)) { + dev_err(&pdev->dev, "failed to parse CT CP HPD gpio\n"); + return gpio; + } + ddata->ct_cp_hpd_gpio = gpio; + + /* LS OE GPIO */ + gpio = of_get_gpio(node, 1); + if (gpio_is_valid(gpio) || gpio == -ENOENT) { + ddata->ls_oe_gpio = gpio; + } else { + dev_err(&pdev->dev, "failed to parse LS OE gpio\n"); + return gpio; + } + + /* HPD GPIO */ + gpio = of_get_gpio(node, 2); + if (!gpio_is_valid(gpio)) { + dev_err(&pdev->dev, "failed to parse HPD gpio\n"); + return gpio; + } + ddata->hpd_gpio = gpio; + + in = omapdss_of_find_source_for_first_ep(node); + if (IS_ERR(in)) { + dev_err(&pdev->dev, "failed to find video source\n"); + return PTR_ERR(in); + } + + ddata->in = in; + + return 0; +} + static int tpd_probe(struct platform_device *pdev) { struct omap_dss_device *in, *dssdev; @@ -307,6 +351,10 @@ static int tpd_probe(struct platform_device *pdev) r = tpd_probe_pdata(pdev); if (r) return r; + } else if (pdev->dev.of_node) { + r = tpd_probe_of(pdev); + if (r) + return r; } else { return -ENODEV; } @@ -379,12 +427,20 @@ static int __exit tpd_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id tpd_of_match[] = { + { .compatible = "omapdss,ti,tpd12s015", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, tpd_of_match); + static struct platform_driver tpd_driver = { .probe = tpd_probe, .remove = __exit_p(tpd_remove), .driver = { .name = "tpd12s015", .owner = THIS_MODULE, + .of_match_table = tpd_of_match, }, }; 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 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/workqueue.h> +#include <linux/of_device.h> +#include <linux/of_gpio.h> #include <video/omapdss.h> #include <video/omap-panel-data.h> @@ -595,10 +597,13 @@ static int dsicm_power_on(struct panel_drv_data *ddata) .lp_clk_max = 10000000, }; - r = in->ops.dsi->configure_pins(in, &ddata->pin_config); - if (r) { - dev_err(&ddata->pdev->dev, "failed to configure DSI pins\n"); - goto err0; + if (ddata->pin_config.num_pins > 0) { + r = in->ops.dsi->configure_pins(in, &ddata->pin_config); + if (r) { + dev_err(&ddata->pdev->dev, + "failed to configure DSI pins\n"); + goto err0; + } } r = in->ops.dsi->set_config(in, &dsi_config); @@ -1156,6 +1161,41 @@ static int dsicm_probe_pdata(struct platform_device *pdev) return 0; } +static int dsicm_probe_of(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct panel_drv_data *ddata = platform_get_drvdata(pdev); + struct omap_dss_device *in; + int gpio; + + gpio = of_get_named_gpio(node, "reset-gpios", 0); + if (!gpio_is_valid(gpio)) { + dev_err(&pdev->dev, "failed to parse reset gpio\n"); + return gpio; + } + ddata->reset_gpio = gpio; + + gpio = of_get_named_gpio(node, "te-gpios", 0); + if (gpio_is_valid(gpio) || gpio == -ENOENT) { + ddata->ext_te_gpio = gpio; + } else { + dev_err(&pdev->dev, "failed to parse TE gpio\n"); + return gpio; + } + + in = omapdss_of_find_source_for_first_ep(node); + if (IS_ERR(in)) { + dev_err(&pdev->dev, "failed to find video source\n"); + return PTR_ERR(in); + } + + ddata->in = in; + + /* TODO: ulps, backlight */ + + return 0; +} + static int dsicm_probe(struct platform_device *pdev) { struct backlight_properties props; @@ -1178,6 +1218,10 @@ static int dsicm_probe(struct platform_device *pdev) r = dsicm_probe_pdata(pdev); if (r) return r; + } else if (pdev->dev.of_node) { + r = dsicm_probe_of(pdev); + if (r) + return r; } else { return -ENODEV; } @@ -1320,12 +1364,20 @@ static int __exit dsicm_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id dsicm_of_match[] = { + { .compatible = "omapdss,panel-dsi-cm", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, dsicm_of_match); + static struct platform_driver dsicm_driver = { .probe = dsicm_probe, .remove = __exit_p(dsicm_remove), .driver = { .name = "panel-dsi-cm", .owner = THIS_MODULE, + .of_match_table = dsicm_of_match, }, }; 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 @@ #include <linux/backlight.h> #include <linux/fb.h> #include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #include <video/omapdss.h> #include <video/omap-panel-data.h> @@ -547,7 +549,9 @@ static int acx565akm_panel_power_on(struct omap_dss_device *dssdev) dev_dbg(&ddata->spi->dev, "%s\n", __func__); in->ops.sdi->set_timings(in, &ddata->videomode); - in->ops.sdi->set_datapairs(in, ddata->datapairs); + + if (ddata->datapairs > 0) + in->ops.sdi->set_datapairs(in, ddata->datapairs); r = in->ops.sdi->enable(in); if (r) { @@ -726,6 +730,22 @@ static int acx565akm_probe_pdata(struct spi_device *spi) return 0; } +static int acx565akm_probe_of(struct spi_device *spi) +{ + struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev); + struct device_node *np = spi->dev.of_node; + + ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0); + + ddata->in = omapdss_of_find_source_for_first_ep(np); + if (IS_ERR(ddata->in)) { + dev_err(&spi->dev, "failed to find video source\n"); + return PTR_ERR(ddata->in); + } + + return 0; +} + static int acx565akm_probe(struct spi_device *spi) { struct panel_drv_data *ddata; @@ -753,7 +773,12 @@ static int acx565akm_probe(struct spi_device *spi) r = acx565akm_probe_pdata(spi); if (r) return r; + } else if (spi->dev.of_node) { + r = acx565akm_probe_of(spi); + if (r) + return r; } else { + dev_err(&spi->dev, "platform data missing!\n"); return -ENODEV; } @@ -864,10 +889,16 @@ static int acx565akm_remove(struct spi_device *spi) return 0; } +static const struct of_device_id acx565akm_of_match[] = { + { .compatible = "omapdss,sony,acx565akm", }, + {}, +}; + static struct spi_driver acx565akm_driver = { .driver = { .name = "acx565akm", .owner = THIS_MODULE, + .of_match_table = acx565akm_of_match, }, .probe = acx565akm_probe, .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 @@ obj-$(CONFIG_OMAP2_DSS) += omapdss.o # Core DSS files omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ - output.o + output.o dss-of.o # DSS compat layer files omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ dispc-compat.o display-sysfs.o diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index aaecbf347748..2bbdb7ff7daf 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -3778,12 +3778,20 @@ static const struct dev_pm_ops dispc_pm_ops = { .runtime_resume = dispc_runtime_resume, }; +static const struct of_device_id dispc_of_match[] = { + { .compatible = "ti,omap2-dispc", }, + { .compatible = "ti,omap3-dispc", }, + { .compatible = "ti,omap4-dispc", }, + {}, +}; + static struct platform_driver omap_dispchw_driver = { .remove = __exit_p(omap_dispchw_remove), .driver = { .name = "omapdss_dispc", .owner = THIS_MODULE, .pm = &dispc_pm_ops, + .of_match_table = dispc_of_match, }, }; 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 @@ #include <linux/module.h> #include <linux/jiffies.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <video/omapdss.h> #include "dss.h" @@ -133,9 +134,32 @@ static int disp_num_counter; int omapdss_register_display(struct omap_dss_device *dssdev) { struct omap_dss_driver *drv = dssdev->driver; + int id; - snprintf(dssdev->alias, sizeof(dssdev->alias), - "display%d", disp_num_counter++); + /* + * Note: this presumes all the displays are either using DT or non-DT, + * which normally should be the case. This also presumes that all + * displays either have an DT alias, or none has. + */ + + if (dssdev->dev->of_node) { + id = of_alias_get_id(dssdev->dev->of_node, "display"); + + if (id < 0) + id = disp_num_counter++; + } else { + id = disp_num_counter++; + } + + snprintf(dssdev->alias, sizeof(dssdev->alias), "display%d", id); + + /* Use 'label' property for name, if it exists */ + if (dssdev->dev->of_node) + of_property_read_string(dssdev->dev->of_node, "label", + &dssdev->name); + + if (dssdev->name == NULL) + dssdev->name = dssdev->alias; if (drv && drv->get_resolution == NULL) drv->get_resolution = omapdss_default_get_resolution; diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 6c0bb099b7bf..157921db447a 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c @@ -30,6 +30,7 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/string.h> +#include <linux/of.h> #include <video/omapdss.h> @@ -49,6 +50,8 @@ static struct { int data_lines; struct omap_dss_device output; + + bool port_initialized; } dpi; static struct platform_device *dpi_get_dsidev(enum omap_channel channel) @@ -725,3 +728,47 @@ void __exit dpi_uninit_platform_driver(void) { platform_driver_unregister(&omap_dpi_driver); } + +int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) +{ + struct device_node *ep; + u32 datalines; + int r; + + ep = omapdss_of_get_next_endpoint(port, NULL); + if (!ep) + return 0; + + r = of_property_read_u32(ep, "data-lines", &datalines); + if (r) { + DSSERR("failed to parse datalines\n"); + goto err_datalines; + } + + dpi.data_lines = datalines; + + of_node_put(ep); + + dpi.pdev = pdev; + + mutex_init(&dpi.lock); + + dpi_init_output(pdev); + + dpi.port_initialized = true; + + return 0; + +err_datalines: + of_node_put(ep); + + return r; +} + +void __exit dpi_uninit_port(void) +{ + if (!dpi.port_initialized) + return; + + dpi_uninit_output(dpi.pdev); +} diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 0d82f731d2f0..121d1049d0bc 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -38,6 +38,8 @@ #include <linux/slab.h> #include <linux/debugfs.h> #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <video/omapdss.h> #include <video/mipi_display.h> @@ -386,6 +388,13 @@ struct dsi_packet_sent_handler_data { struct completion *completion; }; +struct dsi_module_id_data { + u32 address; + int id; +}; + +static const struct of_device_id dsi_of_match[]; + #ifdef DSI_PERF_MEASURE static bool dsi_perf; module_param(dsi_perf, bool, 0644); @@ -1151,15 +1160,11 @@ static int dsi_regulator_init(struct platform_device *dsidev) if (dsi->vdds_dsi_reg != NULL) return 0; - vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdds_dsi"); - - /* DT HACK: try VCXIO to make omapdss work for o4 sdp/panda */ - if (IS_ERR(vdds_dsi)) - vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "VCXIO"); + vdds_dsi = devm_regulator_get(&dsi->pdev->dev, "vdd"); if (IS_ERR(vdds_dsi)) { if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) - DSSERR("can't get VDDS_DSI regulator\n"); + DSSERR("can't get DSI VDD regulator\n"); return PTR_ERR(vdds_dsi); } @@ -5370,12 +5375,69 @@ static void dsi_uninit_output(struct platform_device *dsidev) omapdss_unregister_output(out); } +static int dsi_probe_of(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); + struct property *prop; + u32 lane_arr[10]; + int len, num_pins; + int r, i; + struct device_node *ep; + struct omap_dsi_pin_config pin_cfg; + + ep = omapdss_of_get_first_endpoint(node); + if (!ep) + return 0; + + prop = of_find_property(ep, "lanes", &len); + if (prop == NULL) { + dev_err(&pdev->dev, "failed to find lane data\n"); + r = -EINVAL; + goto err; + } + + num_pins = len / sizeof(u32); + + if (num_pins < 4 || num_pins % 2 != 0 || + num_pins > dsi->num_lanes_supported * 2) { + dev_err(&pdev->dev, "bad number of lanes\n"); + r = -EINVAL; + goto err; + } + + r = of_property_read_u32_array(ep, "lanes", lane_arr, num_pins); + if (r) { + dev_err(&pdev->dev, "failed to read lane data\n"); + goto err; + } + + pin_cfg.num_pins = num_pins; + for (i = 0; i < num_pins; ++i) + pin_cfg.pins[i] = (int)lane_arr[i]; + + r = dsi_configure_pins(&dsi->output, &pin_cfg); + if (r) { + dev_err(&pdev->dev, "failed to configure pins"); + goto err; + } + + of_node_put(ep); + + return 0; + +err: + of_node_put(ep); + return r; +} + /* DSI1 HW IP initialisation */ static int omap_dsihw_probe(struct platform_device *dsidev) { u32 rev; int r, i; struct dsi_data *dsi; + struct resource *dsi_mem; struct resource *res; struct resource temp_res; @@ -5383,7 +5445,6 @@ static int omap_dsihw_probe(struct platform_device *dsidev) if (!dsi) return -ENOMEM; - dsi->module_id = dsidev->id; dsi->pdev = dsidev; dev_set_drvdata(&dsidev->dev, dsi); @@ -5421,6 +5482,8 @@ static int omap_dsihw_probe(struct platform_device *dsidev) res = &temp_res; } + dsi_mem = res; + dsi->proto_base = devm_ioremap(&dsidev->dev, res->start, resource_size(res)); if (!dsi->proto_base) { @@ -5481,6 +5544,31 @@ static int omap_dsihw_probe(struct platform_device *dsidev) return r; } + if (dsidev->dev.of_node) { + const struct of_device_id *match; + const struct dsi_module_id_data *d; + + match = of_match_node(dsi_of_match, dsidev->dev.of_node); + if (!match) { + DSSERR("unsupported DSI module\n"); + return -ENODEV; + } + + d = match->data; + + while (d->address != 0 && d->address != dsi_mem->start) + d++; + + if (d->address == 0) { + DSSERR("unsupported DSI module\n"); + return -ENODEV; + } + + dsi->module_id = d->id; + } else { + dsi->module_id = dsidev->id; + } + /* DSI VCs initialization */ for (i = 0; i < ARRAY_SIZE(dsi->vc); i++) { dsi->vc[i].source = DSI_VC_SOURCE_L4; @@ -5516,6 +5604,19 @@ static int omap_dsihw_probe(struct platform_device *dsidev) dsi_init_output(dsidev); + if (dsidev->dev.of_node) { + r = dsi_probe_of(dsidev); + if (r) { + DSSERR("Invalid DSI DT data\n"); + goto err_probe_of; + } + + r = of_platform_populate(dsidev->dev.of_node, NULL, NULL, + &dsidev->dev); + if (r) + DSSERR("Failed to populate DSI child devices: %d\n", r); + } + dsi_runtime_put(dsidev); if (dsi->module_id == 0) @@ -5529,17 +5630,31 @@ static int omap_dsihw_probe(struct platform_device *dsidev) else if (dsi->module_id == 1) dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs); #endif + return 0; +err_probe_of: + dsi_uninit_output(dsidev); + dsi_runtime_put(dsidev); + err_runtime_get: pm_runtime_disable(&dsidev->dev); return r; } +static int dsi_unregister_child(struct device *dev, void *data) +{ + struct platform_device *pdev = to_platform_device(dev); + platform_device_unregister(pdev); + return 0; +} + static int __exit omap_dsihw_remove(struct platform_device *dsidev) { struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); + device_for_each_child(&dsidev->dev, NULL, dsi_unregister_child); + WARN_ON(dsi->scp_clk_refcount > 0); dsi_uninit_output(dsidev); @@ -5577,6 +5692,23 @@ static const struct dev_pm_ops dsi_pm_ops = { .runtime_resume = dsi_runtime_resume, }; +static const struct dsi_module_id_data dsi_of_data_omap3[] = { + { .address = 0x4804fc00, .id = 0, }, + { }, +}; + +static const struct dsi_module_id_data dsi_of_data_omap4[] = { + { .address = 0x58004000, .id = 0, }, + { .address = 0x58005000, .id = 1, }, + { }, +}; + +static const struct of_device_id dsi_of_match[] = { + { .compatible = "ti,omap3-dsi", .data = dsi_of_data_omap3, }, + { .compatible = "ti,omap4-dsi", .data = dsi_of_data_omap4, }, + {}, +}; + static struct platform_driver omap_dsihw_driver = { .probe = omap_dsihw_probe, .remove = __exit_p(omap_dsihw_remove), @@ -5584,6 +5716,7 @@ static struct platform_driver omap_dsihw_driver = { .name = "omapdss_dsi", .owner = THIS_MODULE, .pm = &dsi_pm_ops, + .of_match_table = dsi_of_match, }, }; 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 @@ +/* + * Copyright (C) 2013 Texas Instruments + * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/seq_file.h> + +#include <video/omapdss.h> + +struct device_node * +omapdss_of_get_next_port(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *port = NULL; + + if (!parent) + return NULL; + + if (!prev) { + struct device_node *ports; + /* + * It's the first call, we have to find a port subnode + * within this node or within an optional 'ports' node. + */ + ports = of_get_child_by_name(parent, "ports"); + if (ports) + parent = ports; + + port = of_get_child_by_name(parent, "port"); + + /* release the 'ports' node */ + of_node_put(ports); + } else { + struct device_node *ports; + + ports = of_get_parent(prev); + if (!ports) + return NULL; + + do { + port = of_get_next_child(ports, prev); + if (!port) { + of_node_put(ports); + return NULL; + } + prev = port; + } while (of_node_cmp(port->name, "port") != 0); + } + + return port; +} +EXPORT_SYMBOL_GPL(omapdss_of_get_next_port); + +struct device_node * +omapdss_of_get_next_endpoint(const struct device_node *parent, + struct device_node *prev) +{ + struct device_node *ep = NULL; + + if (!parent) + return NULL; + + do { + ep = of_get_next_child(parent, prev); + if (!ep) + return NULL; + prev = ep; + } while (of_node_cmp(ep->name, "endpoint") != 0); + + return ep; +} +EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); + +static struct device_node * +omapdss_of_get_remote_device_node(const struct device_node *node) +{ + struct device_node *np; + int i; + + np = of_parse_phandle(node, "remote-endpoint", 0); + + if (!np) + return NULL; + + np = of_get_next_parent(np); + + for (i = 0; i < 3 && np; ++i) { + struct property *prop; + + prop = of_find_property(np, "compatible", NULL); + + if (prop) + return np; + + np = of_get_next_parent(np); + } + + return NULL; +} + +struct device_node * +omapdss_of_get_first_endpoint(const struct device_node *parent) +{ + struct device_node *port, *ep; + + port = omapdss_of_get_next_port(parent, NULL); + + if (!port) + return NULL; + + ep = omapdss_of_get_next_endpoint(port, NULL); + + of_node_put(port); + + return ep; +} +EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint); + +struct omap_dss_device * +omapdss_of_find_source_for_first_ep(struct device_node *node) +{ + struct device_node *ep; + struct device_node *src_node; + struct omap_dss_device *src; + + ep = omapdss_of_get_first_endpoint(node); + if (!ep) + return ERR_PTR(-EINVAL); + + src_node = omapdss_of_get_remote_device_node(ep); + + of_node_put(ep); + + if (!src_node) + return ERR_PTR(-EINVAL); + + src = omap_dss_find_output_by_node(src_node); + + of_node_put(src_node); + + if (!src) + return ERR_PTR(-EPROBE_DEFER); + + return src; +} +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..825c019ddee7 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -23,6 +23,7 @@ #define DSS_SUBSYS_NAME "DSS" #include <linux/kernel.h> +#include <linux/module.h> #include <linux/io.h> #include <linux/export.h> #include <linux/err.h> @@ -33,6 +34,7 @@ #include <linux/pm_runtime.h> #include <linux/gfp.h> #include <linux/sizes.h> +#include <linux/of.h> #include <video/omapdss.h> @@ -772,6 +774,56 @@ static int __init dss_init_features(struct platform_device *pdev) return 0; } +static int __init dss_init_ports(struct platform_device *pdev) +{ + struct device_node *parent = pdev->dev.of_node; + struct device_node *port; + int r; + + if (parent == NULL) + return 0; + + port = omapdss_of_get_next_port(parent, NULL); + if (!port) { +#ifdef CONFIG_OMAP2_DSS_DPI + dpi_init_port(pdev, parent); +#endif + return 0; + } + + do { + u32 reg; + + r = of_property_read_u32(port, "reg", ®); + if (r) + reg = 0; + +#ifdef CONFIG_OMAP2_DSS_DPI + if (reg == 0) + dpi_init_port(pdev, port); +#endif + +#ifdef CONFIG_OMAP2_DSS_SDI + if (reg == 1) + sdi_init_port(pdev, port); +#endif + + } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); + + return 0; +} + +static void dss_uninit_ports(void) +{ +#ifdef CONFIG_OMAP2_DSS_DPI + dpi_uninit_port(); +#endif + +#ifdef CONFIG_OMAP2_DSS_SDI + sdi_uninit_port(); +#endif +} + /* DSS HW IP initialisation */ static int __init omap_dsshw_probe(struct platform_device *pdev) { @@ -830,6 +882,8 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; + dss_init_ports(pdev); + rev = dss_read_reg(DSS_REVISION); printk(KERN_INFO "OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); @@ -849,6 +903,8 @@ err_setup_clocks: static int __exit omap_dsshw_remove(struct platform_device *pdev) { + dss_uninit_ports(); + pm_runtime_disable(&pdev->dev); dss_put_clocks(); @@ -886,12 +942,22 @@ static const struct dev_pm_ops dss_pm_ops = { .runtime_resume = dss_runtime_resume, }; +static const struct of_device_id dss_of_match[] = { + { .compatible = "ti,omap2-dss", }, + { .compatible = "ti,omap3-dss", }, + { .compatible = "ti,omap4-dss", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, dss_of_match); + static struct platform_driver omap_dsshw_driver = { .remove = __exit_p(omap_dsshw_remove), .driver = { .name = "omapdss_dss", .owner = THIS_MODULE, .pm = &dss_pm_ops, + .of_match_table = dss_of_match, }, }; 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, int sdi_init_platform_driver(void) __init; void sdi_uninit_platform_driver(void) __exit; +int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init; +void sdi_uninit_port(void) __exit; + /* DSI */ 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, int dpi_init_platform_driver(void) __init; void dpi_uninit_platform_driver(void) __exit; +int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; +void dpi_uninit_port(void) __exit; + /* DISPC */ int dispc_init_platform_driver(void) __init; 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..f5f7944a1fd1 100644 --- a/drivers/video/omap2/dss/hdmi4.c +++ b/drivers/video/omap2/dss/hdmi4.c @@ -88,15 +88,11 @@ static int hdmi_init_regulator(void) if (hdmi.vdda_hdmi_dac_reg != NULL) return 0; - reg = devm_regulator_get(&hdmi.pdev->dev, "vdda_hdmi_dac"); - - /* DT HACK: try VDAC to make omapdss work for o4 sdp/panda */ - if (IS_ERR(reg)) - reg = devm_regulator_get(&hdmi.pdev->dev, "VDAC"); + reg = devm_regulator_get(&hdmi.pdev->dev, "vdda"); if (IS_ERR(reg)) { if (PTR_ERR(reg) != -EPROBE_DEFER) - DSSERR("can't get VDDA_HDMI_DAC regulator\n"); + DSSERR("can't get VDDA regulator\n"); return PTR_ERR(reg); } @@ -680,6 +676,11 @@ static const struct dev_pm_ops hdmi_pm_ops = { .runtime_resume = hdmi_runtime_resume, }; +static const struct of_device_id hdmi_of_match[] = { + { .compatible = "ti,omap4-hdmi", }, + {}, +}; + static struct platform_driver omapdss_hdmihw_driver = { .probe = omapdss_hdmihw_probe, .remove = __exit_p(omapdss_hdmihw_remove), @@ -687,6 +688,7 @@ static struct platform_driver omapdss_hdmihw_driver = { .name = "omapdss_hdmi", .owner = THIS_MODULE, .pm = &hdmi_pm_ops, + .of_match_table = hdmi_of_match, }, }; diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/omap2/dss/hdmi_wp.c index cd620c6e43a0..f5f4ccf50d90 100644 --- a/drivers/video/omap2/dss/hdmi_wp.c +++ b/drivers/video/omap2/dss/hdmi_wp.c @@ -171,6 +171,8 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; video_fmt->y_res = param->timings.y_res; video_fmt->x_res = param->timings.x_res; + if (param->timings.interlace) + video_fmt->y_res /= 2; timings->hbp = param->timings.hbp; timings->hfp = param->timings.hfp; diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index b679e33adf2d..911dcc9173a6 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c @@ -26,6 +26,7 @@ #include <linux/export.h> #include <linux/platform_device.h> #include <linux/string.h> +#include <linux/of.h> #include <video/omapdss.h> #include "dss.h" @@ -41,6 +42,8 @@ static struct { int datapairs; struct omap_dss_device output; + + bool port_initialized; } sdi; struct sdi_clk_calc_ctx { @@ -386,3 +389,45 @@ void __exit sdi_uninit_platform_driver(void) { platform_driver_unregister(&omap_sdi_driver); } + +int __init sdi_init_port(struct platform_device *pdev, struct device_node *port) +{ + struct device_node *ep; + u32 datapairs; + int r; + + ep = omapdss_of_get_next_endpoint(port, NULL); + if (!ep) + return 0; + + r = of_property_read_u32(ep, "datapairs", &datapairs); + if (r) { + DSSERR("failed to parse datapairs\n"); + goto err_datapairs; + } + + sdi.datapairs = datapairs; + + of_node_put(ep); + + sdi.pdev = pdev; + + sdi_init_output(pdev); + + sdi.port_initialized = true; + + return 0; + +err_datapairs: + of_node_put(ep); + + return r; +} + +void __exit sdi_uninit_port(void) +{ + if (!sdi.port_initialized) + return; + + sdi_uninit_output(sdi.pdev); +} 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 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> +#include <linux/of.h> #include <video/omapdss.h> @@ -636,7 +637,10 @@ static int venc_init_regulator(void) if (venc.vdda_dac_reg != NULL) return 0; - vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac"); + if (venc.pdev->dev.of_node) + vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda"); + else + vdda_dac = devm_regulator_get(&venc.pdev->dev, "vdda_dac"); if (IS_ERR(vdda_dac)) { if (PTR_ERR(vdda_dac) != -EPROBE_DEFER) @@ -805,6 +809,48 @@ static void __exit venc_uninit_output(struct platform_device *pdev) omapdss_unregister_output(out); } +static int venc_probe_of(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct device_node *ep; + u32 channels; + int r; + + ep = omapdss_of_get_first_endpoint(node); + if (!ep) + return 0; + + venc.invert_polarity = of_property_read_bool(ep, "ti,invert-polarity"); + + r = of_property_read_u32(ep, "ti,channels", &channels); + if (r) { + dev_err(&pdev->dev, + "failed to read property 'ti,channels': %d\n", r); + goto err; + } + + switch (channels) { + case 1: + venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE; + break; + case 2: + venc.type = OMAP_DSS_VENC_TYPE_SVIDEO; + break; + default: + dev_err(&pdev->dev, "bad channel propert '%d'\n", channels); + r = -EINVAL; + goto err; + } + + of_node_put(ep); + + return 0; +err: + of_node_put(ep); + + return 0; +} + /* VENC HW IP initialisation */ static int omap_venchw_probe(struct platform_device *pdev) { @@ -846,12 +892,21 @@ static int omap_venchw_probe(struct platform_device *pdev) venc_runtime_put(); + if (pdev->dev.of_node) { + r = venc_probe_of(pdev); + if (r) { + DSSERR("Invalid DT data\n"); + goto err_probe_of; + } + } + dss_debugfs_create_file("venc", venc_dump_regs); venc_init_output(pdev); return 0; +err_probe_of: err_runtime_get: pm_runtime_disable(&pdev->dev); return r; @@ -895,6 +950,14 @@ static const struct dev_pm_ops venc_pm_ops = { .runtime_resume = venc_runtime_resume, }; + +static const struct of_device_id venc_of_match[] = { + { .compatible = "ti,omap2-venc", }, + { .compatible = "ti,omap3-venc", }, + { .compatible = "ti,omap4-venc", }, + {}, +}; + static struct platform_driver omap_venchw_driver = { .probe = omap_venchw_probe, .remove = __exit_p(omap_venchw_remove), @@ -902,6 +965,7 @@ static struct platform_driver omap_venchw_driver = { .name = "omapdss_venc", .owner = THIS_MODULE, .pm = &venc_pm_ops, + .of_match_table = venc_of_match, }, }; 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, return 0; } +static struct omap_dss_device * +omapfb_find_default_display(struct omapfb2_device *fbdev) +{ + const char *def_name; + int i; + + /* + * Search with the display name from the user or the board file, + * comparing to display names and aliases + */ + + def_name = omapdss_get_default_display_name(); + + if (def_name) { + for (i = 0; i < fbdev->num_displays; ++i) { + struct omap_dss_device *dssdev; + + dssdev = fbdev->displays[i].dssdev; + + if (dssdev->name && strcmp(def_name, dssdev->name) == 0) + return dssdev; + + if (strcmp(def_name, dssdev->alias) == 0) + return dssdev; + } + + /* def_name given but not found */ + return NULL; + } + + /* then look for DT alias display0 */ + for (i = 0; i < fbdev->num_displays; ++i) { + struct omap_dss_device *dssdev; + int id; + + dssdev = fbdev->displays[i].dssdev; + + if (dssdev->dev->of_node == NULL) + continue; + + id = of_alias_get_id(dssdev->dev->of_node, "display"); + if (id == 0) + return dssdev; + } + + /* return the first display we have in the list */ + return fbdev->displays[0].dssdev; +} + static int omapfb_probe(struct platform_device *pdev) { struct omapfb2_device *fbdev = NULL; @@ -2494,23 +2543,7 @@ static int omapfb_probe(struct platform_device *pdev) for (i = 0; i < fbdev->num_managers; i++) fbdev->managers[i] = omap_dss_get_overlay_manager(i); - def_display = NULL; - - for (i = 0; i < fbdev->num_displays; ++i) { - struct omap_dss_device *dssdev; - const char *def_name; - - def_name = omapdss_get_default_display_name(); - - dssdev = fbdev->displays[i].dssdev; - - if (def_name == NULL || - (dssdev->name && strcmp(def_name, dssdev->name) == 0)) { - def_display = dssdev; - break; - } - } - + def_display = omapfb_find_default_display(fbdev); if (def_display == NULL) { dev_err(fbdev->dev, "failed to find default display\n"); r = -EPROBE_DEFER; |