diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c | 197 |
1 files changed, 36 insertions, 161 deletions
diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index d275bf152da5..94de55fd8884 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -21,42 +21,26 @@ struct panel_drv_data { struct omap_dss_device dssdev; - struct omap_dss_device *in; void (*hpd_cb)(void *cb_data, enum drm_connector_status status); void *hpd_cb_data; - bool hpd_enabled; struct mutex hpd_lock; struct gpio_desc *ct_cp_hpd_gpio; struct gpio_desc *ls_oe_gpio; struct gpio_desc *hpd_gpio; - - struct videomode vm; }; #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) -static int tpd_connect(struct omap_dss_device *dssdev, - struct omap_dss_device *dst) +static int tpd_connect(struct omap_dss_device *src, + struct omap_dss_device *dst) { - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in; + struct panel_drv_data *ddata = to_panel_data(dst); int r; - in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node); - if (IS_ERR(in)) { - dev_err(dssdev->dev, "failed to find video source\n"); - return PTR_ERR(in); - } - - r = in->ops.hdmi->connect(in, dssdev); - if (r) { - omap_dss_put_device(in); + r = omapdss_device_connect(dst->dss, dst, dst->next); + if (r) return r; - } - - dst->src = dssdev; - dssdev->dst = dst; gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1); @@ -64,45 +48,29 @@ static int tpd_connect(struct omap_dss_device *dssdev, /* DC-DC converter needs at max 300us to get to 90% of 5V */ udelay(300); - ddata->in = in; return 0; } -static void tpd_disconnect(struct omap_dss_device *dssdev, - struct omap_dss_device *dst) +static void tpd_disconnect(struct omap_dss_device *src, + struct omap_dss_device *dst) { - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - - WARN_ON(dst != dssdev->dst); - - if (dst != dssdev->dst) - return; + struct panel_drv_data *ddata = to_panel_data(dst); gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0); gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0); - dst->src = NULL; - dssdev->dst = NULL; - - in->ops.hdmi->disconnect(in, &ddata->dssdev); - - omap_dss_put_device(in); - ddata->in = NULL; + omapdss_device_disconnect(dst, dst->next); } static int tpd_enable(struct omap_dss_device *dssdev) { - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; + struct omap_dss_device *src = dssdev->src; int r; if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) return 0; - in->ops.hdmi->set_timings(in, &ddata->vm); - - r = in->ops.hdmi->enable(in); + r = src->ops->enable(src); if (r) return r; @@ -113,76 +81,27 @@ static int tpd_enable(struct omap_dss_device *dssdev) static void tpd_disable(struct omap_dss_device *dssdev) { - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; + struct omap_dss_device *src = dssdev->src; if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) return; - in->ops.hdmi->disable(in); + src->ops->disable(src); dssdev->state = OMAP_DSS_DISPLAY_DISABLED; } -static void tpd_set_timings(struct omap_dss_device *dssdev, - struct videomode *vm) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - - ddata->vm = *vm; - dssdev->panel.vm = *vm; - - in->ops.hdmi->set_timings(in, vm); -} - -static void tpd_get_timings(struct omap_dss_device *dssdev, - struct videomode *vm) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - - *vm = ddata->vm; -} - -static int tpd_check_timings(struct omap_dss_device *dssdev, - struct videomode *vm) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - int r; - - r = in->ops.hdmi->check_timings(in, vm); - - return r; -} - -static int tpd_read_edid(struct omap_dss_device *dssdev, - u8 *edid, int len) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - - if (!gpiod_get_value_cansleep(ddata->hpd_gpio)) - return -ENODEV; - - return in->ops.hdmi->read_edid(in, edid, len); -} - static bool tpd_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - bool connected = gpiod_get_value_cansleep(ddata->hpd_gpio); - if (!connected && in->ops.hdmi->lost_hotplug) - in->ops.hdmi->lost_hotplug(in); - return connected; + return gpiod_get_value_cansleep(ddata->hpd_gpio); } -static int tpd_register_hpd_cb(struct omap_dss_device *dssdev, - void (*cb)(void *cb_data, +static void tpd_register_hpd_cb(struct omap_dss_device *dssdev, + void (*cb)(void *cb_data, enum drm_connector_status status), - void *cb_data) + void *cb_data) { struct panel_drv_data *ddata = to_panel_data(dssdev); @@ -190,8 +109,6 @@ static int tpd_register_hpd_cb(struct omap_dss_device *dssdev, ddata->hpd_cb = cb; ddata->hpd_cb_data = cb_data; mutex_unlock(&ddata->hpd_lock); - - return 0; } static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev) @@ -204,61 +121,14 @@ static void tpd_unregister_hpd_cb(struct omap_dss_device *dssdev) mutex_unlock(&ddata->hpd_lock); } -static void tpd_enable_hpd(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - - mutex_lock(&ddata->hpd_lock); - ddata->hpd_enabled = true; - mutex_unlock(&ddata->hpd_lock); -} - -static void tpd_disable_hpd(struct omap_dss_device *dssdev) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - - mutex_lock(&ddata->hpd_lock); - ddata->hpd_enabled = false; - mutex_unlock(&ddata->hpd_lock); -} - -static int tpd_set_infoframe(struct omap_dss_device *dssdev, - const struct hdmi_avi_infoframe *avi) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - - return in->ops.hdmi->set_infoframe(in, avi); -} - -static int tpd_set_hdmi_mode(struct omap_dss_device *dssdev, - bool hdmi_mode) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *in = ddata->in; - - return in->ops.hdmi->set_hdmi_mode(in, hdmi_mode); -} - -static const struct omapdss_hdmi_ops tpd_hdmi_ops = { +static const struct omap_dss_device_ops tpd_ops = { .connect = tpd_connect, .disconnect = tpd_disconnect, - .enable = tpd_enable, .disable = tpd_disable, - - .check_timings = tpd_check_timings, - .set_timings = tpd_set_timings, - .get_timings = tpd_get_timings, - - .read_edid = tpd_read_edid, .detect = tpd_detect, .register_hpd_cb = tpd_register_hpd_cb, .unregister_hpd_cb = tpd_unregister_hpd_cb, - .enable_hpd = tpd_enable_hpd, - .disable_hpd = tpd_disable_hpd, - .set_infoframe = tpd_set_infoframe, - .set_hdmi_mode = tpd_set_hdmi_mode, }; static irqreturn_t tpd_hpd_isr(int irq, void *data) @@ -266,7 +136,7 @@ static irqreturn_t tpd_hpd_isr(int irq, void *data) struct panel_drv_data *ddata = data; mutex_lock(&ddata->hpd_lock); - if (ddata->hpd_enabled && ddata->hpd_cb) { + if (ddata->hpd_cb) { enum drm_connector_status status; if (tpd_detect(&ddata->dssdev)) @@ -283,7 +153,7 @@ static irqreturn_t tpd_hpd_isr(int irq, void *data) static int tpd_probe(struct platform_device *pdev) { - struct omap_dss_device *in, *dssdev; + struct omap_dss_device *dssdev; struct panel_drv_data *ddata; int r; struct gpio_desc *gpio; @@ -325,21 +195,24 @@ static int tpd_probe(struct platform_device *pdev) return r; dssdev = &ddata->dssdev; - dssdev->ops.hdmi = &tpd_hdmi_ops; + dssdev->ops = &tpd_ops; dssdev->dev = &pdev->dev; dssdev->type = OMAP_DISPLAY_TYPE_HDMI; dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI; dssdev->owner = THIS_MODULE; - dssdev->port_num = 1; - - in = ddata->in; - - r = omapdss_register_output(dssdev); - if (r) { - dev_err(&pdev->dev, "Failed to register output\n"); - return r; + dssdev->of_ports = BIT(1) | BIT(0); + dssdev->ops_flags = OMAP_DSS_DEVICE_OP_DETECT + | OMAP_DSS_DEVICE_OP_HPD; + + dssdev->next = omapdss_of_find_connected_device(pdev->dev.of_node, 1); + if (IS_ERR(dssdev->next)) { + if (PTR_ERR(dssdev->next) != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to find video sink\n"); + return PTR_ERR(dssdev->next); } + omapdss_device_register(dssdev); + return 0; } @@ -348,7 +221,9 @@ static int __exit tpd_remove(struct platform_device *pdev) struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct omap_dss_device *dssdev = &ddata->dssdev; - omapdss_unregister_output(&ddata->dssdev); + if (dssdev->next) + omapdss_device_put(dssdev->next); + omapdss_device_unregister(&ddata->dssdev); WARN_ON(omapdss_device_is_enabled(dssdev)); if (omapdss_device_is_enabled(dssdev)) @@ -356,7 +231,7 @@ static int __exit tpd_remove(struct platform_device *pdev) WARN_ON(omapdss_device_is_connected(dssdev)); if (omapdss_device_is_connected(dssdev)) - tpd_disconnect(dssdev, dssdev->dst); + omapdss_device_disconnect(NULL, dssdev); return 0; } |