summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/omapdrm/dss/sdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/dss/sdi.c')
-rw-r--r--drivers/gpu/drm/omapdrm/dss/sdi.c149
1 files changed, 63 insertions, 86 deletions
diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c
index 69c3b7a3d5c7..b2fe2387037a 100644
--- a/drivers/gpu/drm/omapdrm/dss/sdi.c
+++ b/drivers/gpu/drm/omapdrm/dss/sdi.c
@@ -132,10 +132,8 @@ static void sdi_config_lcd_manager(struct sdi_device *sdi)
static int sdi_display_enable(struct omap_dss_device *dssdev)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
- struct videomode *vm = &sdi->vm;
- unsigned long fck;
struct dispc_clock_info dispc_cinfo;
- unsigned long pck;
+ unsigned long fck;
int r;
if (!sdi->output.dispc_channel_connected) {
@@ -151,27 +149,12 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err_get_dispc;
- /* 15.5.9.1.2 */
- vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE;
-
- r = sdi_calc_clock_div(sdi, vm->pixelclock, &fck, &dispc_cinfo);
+ r = sdi_calc_clock_div(sdi, sdi->vm.pixelclock, &fck, &dispc_cinfo);
if (r)
goto err_calc_clock_div;
sdi->mgr_config.clock_info = dispc_cinfo;
- pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
-
- if (pck != vm->pixelclock) {
- DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
- vm->pixelclock, pck);
-
- vm->pixelclock = pck;
- }
-
-
- dss_mgr_set_timings(&sdi->output, vm);
-
r = dss_set_fck_rate(sdi->dss, fck);
if (r)
goto err_set_dss_clock_div;
@@ -230,96 +213,63 @@ static void sdi_display_disable(struct omap_dss_device *dssdev)
}
static void sdi_set_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
+ const struct videomode *vm)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
sdi->vm = *vm;
}
-static void sdi_get_timings(struct omap_dss_device *dssdev,
- struct videomode *vm)
-{
- struct sdi_device *sdi = dssdev_to_sdi(dssdev);
-
- *vm = sdi->vm;
-}
-
static int sdi_check_timings(struct omap_dss_device *dssdev,
struct videomode *vm)
{
struct sdi_device *sdi = dssdev_to_sdi(dssdev);
- enum omap_channel channel = dssdev->dispc_channel;
-
- if (!dispc_mgr_timings_ok(sdi->dss->dispc, channel, vm))
- return -EINVAL;
+ struct dispc_clock_info dispc_cinfo;
+ unsigned long fck;
+ unsigned long pck;
+ int r;
if (vm->pixelclock == 0)
return -EINVAL;
- return 0;
-}
+ r = sdi_calc_clock_div(sdi, vm->pixelclock, &fck, &dispc_cinfo);
+ if (r)
+ return r;
-static int sdi_init_regulator(struct sdi_device *sdi)
-{
- struct regulator *vdds_sdi;
+ pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
- if (sdi->vdds_sdi_reg)
- return 0;
+ if (pck != vm->pixelclock) {
+ DSSWARN("Pixel clock adjusted from %lu Hz to %lu Hz\n",
+ vm->pixelclock, pck);
- vdds_sdi = devm_regulator_get(&sdi->pdev->dev, "vdds_sdi");
- if (IS_ERR(vdds_sdi)) {
- if (PTR_ERR(vdds_sdi) != -EPROBE_DEFER)
- DSSERR("can't get VDDS_SDI regulator\n");
- return PTR_ERR(vdds_sdi);
+ vm->pixelclock = pck;
}
- sdi->vdds_sdi_reg = vdds_sdi;
-
return 0;
}
-static int sdi_connect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static int sdi_connect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct sdi_device *sdi = dssdev_to_sdi(dssdev);
int r;
- r = sdi_init_regulator(sdi);
+ r = omapdss_device_connect(dst->dss, dst, dst->next);
if (r)
return r;
- r = dss_mgr_connect(&sdi->output, dssdev);
- if (r)
- return r;
-
- r = omapdss_output_set_device(dssdev, dst);
- if (r) {
- DSSERR("failed to connect output to new device: %s\n",
- dst->name);
- dss_mgr_disconnect(&sdi->output, dssdev);
- return r;
- }
-
+ dst->dispc_channel_connected = true;
return 0;
}
-static void sdi_disconnect(struct omap_dss_device *dssdev,
- struct omap_dss_device *dst)
+static void sdi_disconnect(struct omap_dss_device *src,
+ struct omap_dss_device *dst)
{
- struct sdi_device *sdi = dssdev_to_sdi(dssdev);
+ dst->dispc_channel_connected = false;
- WARN_ON(dst != dssdev->dst);
-
- if (dst != dssdev->dst)
- return;
-
- omapdss_output_unset_device(dssdev);
-
- dss_mgr_disconnect(&sdi->output, dssdev);
+ omapdss_device_disconnect(dst, dst->next);
}
-static const struct omapdss_sdi_ops sdi_ops = {
+static const struct omap_dss_device_ops sdi_ops = {
.connect = sdi_connect,
.disconnect = sdi_disconnect,
@@ -328,12 +278,12 @@ static const struct omapdss_sdi_ops sdi_ops = {
.check_timings = sdi_check_timings,
.set_timings = sdi_set_timings,
- .get_timings = sdi_get_timings,
};
-static void sdi_init_output(struct sdi_device *sdi)
+static int sdi_init_output(struct sdi_device *sdi)
{
struct omap_dss_device *out = &sdi->output;
+ int r;
out->dev = &sdi->pdev->dev;
out->id = OMAP_DSS_OUTPUT_SDI;
@@ -341,16 +291,36 @@ static void sdi_init_output(struct sdi_device *sdi)
out->name = "sdi.0";
out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
/* We have SDI only on OMAP3, where it's on port 1 */
- out->port_num = 1;
- out->ops.sdi = &sdi_ops;
+ out->of_ports = BIT(1);
+ out->ops = &sdi_ops;
out->owner = THIS_MODULE;
+ out->bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE /* 15.5.9.1.2 */
+ | DRM_BUS_FLAG_SYNC_POSEDGE;
+
+ out->next = omapdss_of_find_connected_device(out->dev->of_node, 1);
+ if (IS_ERR(out->next)) {
+ if (PTR_ERR(out->next) != -EPROBE_DEFER)
+ dev_err(out->dev, "failed to find video sink\n");
+ return PTR_ERR(out->next);
+ }
- omapdss_register_output(out);
+ r = omapdss_output_validate(out);
+ if (r) {
+ omapdss_device_put(out->next);
+ out->next = NULL;
+ return r;
+ }
+
+ omapdss_device_register(out);
+
+ return 0;
}
static void sdi_uninit_output(struct sdi_device *sdi)
{
- omapdss_unregister_output(&sdi->output);
+ if (sdi->output.next)
+ omapdss_device_put(sdi->output.next);
+ omapdss_device_unregister(&sdi->output);
}
int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
@@ -372,25 +342,32 @@ int sdi_init_port(struct dss_device *dss, struct platform_device *pdev,
}
r = of_property_read_u32(ep, "datapairs", &datapairs);
+ of_node_put(ep);
if (r) {
DSSERR("failed to parse datapairs\n");
- goto err_datapairs;
+ goto err_free;
}
sdi->datapairs = datapairs;
sdi->dss = dss;
- of_node_put(ep);
-
sdi->pdev = pdev;
port->data = sdi;
- sdi_init_output(sdi);
+ sdi->vdds_sdi_reg = devm_regulator_get(&pdev->dev, "vdds_sdi");
+ if (IS_ERR(sdi->vdds_sdi_reg)) {
+ r = PTR_ERR(sdi->vdds_sdi_reg);
+ if (r != -EPROBE_DEFER)
+ DSSERR("can't get VDDS_SDI regulator\n");
+ goto err_free;
+ }
+
+ r = sdi_init_output(sdi);
+ if (r)
+ goto err_free;
return 0;
-err_datapairs:
- of_node_put(ep);
err_free:
kfree(sdi);