diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c | 140 |
1 files changed, 55 insertions, 85 deletions
diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c index 29692a5217c5..741a5e324767 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c @@ -24,6 +24,8 @@ #include <linux/of_device.h> #include <linux/regulator/consumer.h> +#include <drm/drm_connector.h> + #include <video/mipi_display.h> #include <video/of_display_timing.h> @@ -41,6 +43,7 @@ struct panel_drv_data { struct omap_dss_device dssdev; + struct omap_dss_device *src; struct videomode vm; @@ -141,7 +144,7 @@ static void hw_guard_wait(struct panel_drv_data *ddata) static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r; u8 buf[1]; @@ -157,14 +160,14 @@ static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data) static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; return src->ops->dsi.dcs_write(src, ddata->channel, &dcs_cmd, 1); } static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; u8 buf[2] = { dcs_cmd, param }; return src->ops->dsi.dcs_write(src, ddata->channel, buf, 2); @@ -173,7 +176,7 @@ static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param) static int dsicm_sleep_in(struct panel_drv_data *ddata) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; u8 cmd; int r; @@ -228,7 +231,7 @@ static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3) static int dsicm_set_update_window(struct panel_drv_data *ddata, u16 x, u16 y, u16 w, u16 h) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r; u16 x1 = x; u16 x2 = x + w - 1; @@ -275,7 +278,7 @@ static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata) static int dsicm_enter_ulps(struct panel_drv_data *ddata) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r; if (ddata->ulps_enabled) @@ -309,18 +312,13 @@ err: static int dsicm_exit_ulps(struct panel_drv_data *ddata) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r; if (!ddata->ulps_enabled) return 0; - r = src->ops->enable(src); - if (r) { - dev_err(&ddata->pdev->dev, "failed to enable DSI\n"); - goto err1; - } - + src->ops->enable(src); src->ops->dsi.enable_hs(src, ddata->channel, true); r = _dsicm_enable_te(ddata, true); @@ -347,7 +345,7 @@ err2: enable_irq(gpiod_to_irq(ddata->ext_te_gpio)); ddata->ulps_enabled = false; } -err1: + dsicm_queue_ulps_work(ddata); return r; @@ -366,7 +364,7 @@ static int dsicm_wake_up(struct panel_drv_data *ddata) static int dsicm_bl_update_status(struct backlight_device *dev) { struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev); - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r = 0; int level; @@ -414,7 +412,7 @@ static ssize_t dsicm_num_errors_show(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; u8 errors = 0; int r; @@ -446,7 +444,7 @@ static ssize_t dsicm_hw_revision_show(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; u8 id1, id2, id3; int r; @@ -478,7 +476,7 @@ static ssize_t dsicm_store_ulps(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; unsigned long t; int r; @@ -528,7 +526,7 @@ static ssize_t dsicm_store_ulps_timeout(struct device *dev, { struct platform_device *pdev = to_platform_device(dev); struct panel_drv_data *ddata = platform_get_drvdata(pdev); - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; unsigned long t; int r; @@ -603,7 +601,7 @@ static void dsicm_hw_reset(struct panel_drv_data *ddata) static int dsicm_power_on(struct panel_drv_data *ddata) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; u8 id1, id2, id3; int r; struct omap_dss_dsi_config dsi_config = { @@ -649,11 +647,7 @@ static int dsicm_power_on(struct panel_drv_data *ddata) goto err_vddi; } - r = src->ops->enable(src); - if (r) { - dev_err(&ddata->pdev->dev, "failed to enable DSI\n"); - goto err_vddi; - } + src->ops->enable(src); dsicm_hw_reset(ddata); @@ -722,7 +716,7 @@ err_vpnl: static void dsicm_power_off(struct panel_drv_data *ddata) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r; src->ops->dsi.disable_video_output(src, ddata->channel); @@ -776,6 +770,7 @@ static int dsicm_connect(struct omap_dss_device *src, return r; } + ddata->src = src; return 0; } @@ -785,28 +780,17 @@ static void dsicm_disconnect(struct omap_dss_device *src, struct panel_drv_data *ddata = to_panel_data(dst); src->ops->dsi.release_vc(src, ddata->channel); + ddata->src = NULL; } -static int dsicm_enable(struct omap_dss_device *dssdev) +static void dsicm_enable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; int r; - dev_dbg(&ddata->pdev->dev, "enable\n"); - mutex_lock(&ddata->lock); - if (!omapdss_device_is_connected(dssdev)) { - r = -ENODEV; - goto err; - } - - if (omapdss_device_is_enabled(dssdev)) { - r = 0; - goto err; - } - src->ops->dsi.bus_lock(src); r = dsicm_power_on(ddata); @@ -816,27 +800,22 @@ static int dsicm_enable(struct omap_dss_device *dssdev) if (r) goto err; - dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; - mutex_unlock(&ddata->lock); dsicm_bl_power(ddata, true); - return 0; + return; err: - dev_dbg(&ddata->pdev->dev, "enable failed\n"); + dev_dbg(&ddata->pdev->dev, "enable failed (%d)\n", r); mutex_unlock(&ddata->lock); - return r; } static void dsicm_disable(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; int r; - dev_dbg(&ddata->pdev->dev, "disable\n"); - dsicm_bl_power(ddata, false); mutex_lock(&ddata->lock); @@ -845,23 +824,19 @@ static void dsicm_disable(struct omap_dss_device *dssdev) src->ops->dsi.bus_lock(src); - if (omapdss_device_is_enabled(dssdev)) { - r = dsicm_wake_up(ddata); - if (!r) - dsicm_power_off(ddata); - } + r = dsicm_wake_up(ddata); + if (!r) + dsicm_power_off(ddata); src->ops->dsi.bus_unlock(src); - dssdev->state = OMAP_DSS_DISPLAY_DISABLED; - mutex_unlock(&ddata->lock); } static void dsicm_framedone_cb(int err, void *data) { struct panel_drv_data *ddata = data; - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err); src->ops->dsi.bus_unlock(src); @@ -870,7 +845,7 @@ static void dsicm_framedone_cb(int err, void *data) static irqreturn_t dsicm_te_isr(int irq, void *data) { struct panel_drv_data *ddata = data; - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int old; int r; @@ -896,7 +871,7 @@ static void dsicm_te_timeout_work_callback(struct work_struct *work) { struct panel_drv_data *ddata = container_of(work, struct panel_drv_data, te_timeout_work.work); - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n"); @@ -908,7 +883,7 @@ static int dsicm_update(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; int r; dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h); @@ -954,7 +929,7 @@ err: static int dsicm_sync(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; dev_dbg(&ddata->pdev->dev, "sync\n"); @@ -970,7 +945,7 @@ static int dsicm_sync(struct omap_dss_device *dssdev) static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable) { - struct omap_dss_device *src = ddata->dssdev.src; + struct omap_dss_device *src = ddata->src; int r; if (enable) @@ -990,7 +965,7 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable) static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; int r; mutex_lock(&ddata->lock); @@ -1041,7 +1016,7 @@ static int dsicm_memory_read(struct omap_dss_device *dssdev, u16 x, u16 y, u16 w, u16 h) { struct panel_drv_data *ddata = to_panel_data(dssdev); - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; int r; int first = 1; int plen; @@ -1123,7 +1098,7 @@ static void dsicm_ulps_work(struct work_struct *work) struct panel_drv_data *ddata = container_of(work, struct panel_drv_data, ulps_work.work); struct omap_dss_device *dssdev = &ddata->dssdev; - struct omap_dss_device *src = dssdev->src; + struct omap_dss_device *src = ddata->src; mutex_lock(&ddata->lock); @@ -1140,29 +1115,32 @@ static void dsicm_ulps_work(struct work_struct *work) mutex_unlock(&ddata->lock); } -static void dsicm_get_timings(struct omap_dss_device *dssdev, - struct videomode *vm) +static int dsicm_get_modes(struct omap_dss_device *dssdev, + struct drm_connector *connector) { struct panel_drv_data *ddata = to_panel_data(dssdev); - *vm = ddata->vm; + connector->display_info.width_mm = ddata->width_mm; + connector->display_info.height_mm = ddata->height_mm; + + return omapdss_display_get_modes(connector, &ddata->vm); } static int dsicm_check_timings(struct omap_dss_device *dssdev, - struct videomode *vm) + struct drm_display_mode *mode) { struct panel_drv_data *ddata = to_panel_data(dssdev); int ret = 0; - if (vm->hactive != ddata->vm.hactive) + if (mode->hdisplay != ddata->vm.hactive) ret = -EINVAL; - if (vm->vactive != ddata->vm.vactive) + if (mode->vdisplay != ddata->vm.vactive) ret = -EINVAL; if (ret) { dev_warn(dssdev->dev, "wrong resolution: %d x %d", - vm->hactive, vm->vactive); + mode->hdisplay, mode->vdisplay); dev_warn(dssdev->dev, "panel resolution: %d x %d", ddata->vm.hactive, ddata->vm.vactive); } @@ -1170,15 +1148,6 @@ static int dsicm_check_timings(struct omap_dss_device *dssdev, return ret; } -static void dsicm_get_size(struct omap_dss_device *dssdev, - unsigned int *width, unsigned int *height) -{ - struct panel_drv_data *ddata = to_panel_data(dssdev); - - *width = ddata->width_mm; - *height = ddata->height_mm; -} - static const struct omap_dss_device_ops dsicm_ops = { .connect = dsicm_connect, .disconnect = dsicm_disconnect, @@ -1186,7 +1155,7 @@ static const struct omap_dss_device_ops dsicm_ops = { .enable = dsicm_enable, .disable = dsicm_disable, - .get_timings = dsicm_get_timings, + .get_modes = dsicm_get_modes, .check_timings = dsicm_check_timings, }; @@ -1194,8 +1163,6 @@ static const struct omap_dss_driver dsicm_dss_driver = { .update = dsicm_update, .sync = dsicm_sync, - .get_size = dsicm_get_size, - .enable_te = dsicm_enable_te, .get_te = dsicm_get_te, @@ -1305,8 +1272,10 @@ static int dsicm_probe(struct platform_device *pdev) dssdev->ops = &dsicm_ops; dssdev->driver = &dsicm_dss_driver; dssdev->type = OMAP_DISPLAY_TYPE_DSI; + dssdev->display = true; dssdev->owner = THIS_MODULE; dssdev->of_ports = BIT(0); + dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES; dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; @@ -1385,8 +1354,9 @@ static int __exit dsicm_remove(struct platform_device *pdev) omapdss_device_unregister(dssdev); - dsicm_disable(dssdev); - omapdss_device_disconnect(dssdev->src, dssdev); + if (omapdss_device_is_enabled(dssdev)) + dsicm_disable(dssdev); + omapdss_device_disconnect(ddata->src, dssdev); sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group); |