diff mbox series

[RFCv1,32/42] drm/omap: dsi: convert to drm_panel

Message ID 20191117024028.2233-33-sebastian.reichel@collabora.com (mailing list archive)
State New, archived
Headers show
Series drm/omap: Convert DSI code to use drm_mipi_dsi and drm_panel | expand

Commit Message

Sebastian Reichel Nov. 17, 2019, 2:40 a.m. UTC
This converts the DSI module to expect common drm_panel display
drivers instead of dssdev based ones.

This commit is WIP. We somehow need to know the panels resolution
in omap_dsi_host_attach(), so that we can properly configure the
DSI bus clock before enabling the bus. The control bus must be
enabled at this point, so that the panel can use it.

Other drivers run drm_panel_attach() in their dsi host attach,
which makes it possible to call drm_panel_get_modes() afterwards
and the get the correct mode from the connector.

Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
 .../gpu/drm/omapdrm/displays/panel-dsi-cm.c   | 217 +++++++-----------
 drivers/gpu/drm/omapdrm/dss/dsi.c             | 141 ++++++++++--
 .../gpu/drm/omapdrm/dss/omapdss-boot-init.c   |   1 -
 drivers/gpu/drm/omapdrm/dss/omapdss.h         |  22 +-
 drivers/gpu/drm/omapdrm/omap_crtc.c           |  17 +-
 5 files changed, 205 insertions(+), 193 deletions(-)

Comments

H. Nikolaus Schaller Nov. 17, 2019, 7:23 p.m. UTC | #1
Hi,

> Am 17.11.2019 um 03:40 schrieb Sebastian Reichel <sebastian.reichel@collabora.com>:
> 
> This converts the DSI module to expect common drm_panel display
> drivers instead of dssdev based ones.
> 
> This commit is WIP. We somehow need to know the panels resolution
> in omap_dsi_host_attach(), so that we can properly configure the
> DSI bus clock before enabling the bus. The control bus must be
> enabled at this point, so that the panel can use it.
> 
> Other drivers run drm_panel_attach() in their dsi host attach,
> which makes it possible to call drm_panel_get_modes() afterwards
> and the get the correct mode from the connector.
> 
> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> ---
> .../gpu/drm/omapdrm/displays/panel-dsi-cm.c   | 217 +++++++-----------
> drivers/gpu/drm/omapdrm/dss/dsi.c             | 141 ++++++++++--
> .../gpu/drm/omapdrm/dss/omapdss-boot-init.c   |   1 -
> drivers/gpu/drm/omapdrm/dss/omapdss.h         |  22 +-
> drivers/gpu/drm/omapdrm/omap_crtc.c           |  17 +-
> 5 files changed, 205 insertions(+), 193 deletions(-)
> 
> diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
> index 18020ac43a83..84b0e79c025e 100644
> --- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
> +++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
> @@ -6,8 +6,6 @@
>  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
>  */
> 
> -/* #define DEBUG */
> -
> #include <linux/backlight.h>
> #include <linux/delay.h>
> #include <linux/gpio/consumer.h>
> @@ -20,11 +18,14 @@
> #include <linux/regulator/consumer.h>
> 
> #include <drm/drm_connector.h>
> +#include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_panel.h>
> +#include <drm/drm_modes.h>
> 
> +#include <video/display_timing.h>
> #include <video/mipi_display.h>
> #include <video/of_display_timing.h>
> -
> -#include "../dss/omapdss.h"
> +#include <video/videomode.h>
> 
> #define DCS_READ_NUM_ERRORS	0x05
> #define DCS_GET_ID1		0xda
> @@ -35,11 +36,8 @@
> 
> struct panel_drv_data {
> 	struct mipi_dsi_device *dsi;
> -
> -	struct omap_dss_device dssdev;
> -	struct omap_dss_device *src;
> -
> -	struct videomode vm;
> +	struct drm_panel panel;
> +	struct drm_display_mode mode;
> 
> 	struct mutex lock;
> 
> @@ -71,7 +69,11 @@ struct panel_drv_data {
> 	bool ulps_enabled;
> };
> 
> -#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
> +
> +static inline struct panel_drv_data *panel_to_ddata(struct drm_panel *panel)
> +{
> +	return container_of(panel, struct panel_drv_data, panel);
> +}
> 
> static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
> 
> @@ -285,10 +287,15 @@ 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->src;
> 	u8 id1, id2, id3;
> 	int r;
> 
> +	r = regulator_bulk_enable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
> +	if (r) {
> +		dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
> +		return r;
> +	}
> +
> 	dsicm_hw_reset(ddata);
> 
> 	ddata->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
> @@ -322,10 +329,6 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
> 	if (r)
> 		goto err;
> 
> -	r = src->ops->dsi.enable_video_output(src, ddata->dsi->channel);
> -	if (r)
> -		goto err;
> -
> 	ddata->enabled = 1;
> 
> 	if (!ddata->intro_printed) {
> @@ -342,18 +345,17 @@ static int dsicm_power_on(struct panel_drv_data *ddata)
> 
> 	dsicm_hw_reset(ddata);
> 
> +	regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
> +
> 	return r;
> }
> 
> -static void dsicm_power_off(struct panel_drv_data *ddata)
> +static int dsicm_power_off(struct panel_drv_data *ddata)
> {
> -	struct omap_dss_device *src = ddata->src;
> 	int r;
> 
> 	ddata->enabled = 0;
> 
> -	src->ops->dsi.disable_video_output(src, ddata->dsi->channel);
> -
> 	r = mipi_dsi_dcs_set_display_off(ddata->dsi);
> 	if (!r)
> 		r = dsicm_sleep_in(ddata);
> @@ -363,52 +365,17 @@ static void dsicm_power_off(struct panel_drv_data *ddata)
> 				"error disabling panel, issuing HW reset\n");
> 		dsicm_hw_reset(ddata);
> 	}
> -}
> 
> -static int dsicm_connect(struct omap_dss_device *src,
> -			 struct omap_dss_device *dst)
> -{
> -	struct panel_drv_data *ddata = to_panel_data(dst);
> -
> -	ddata->src = src;
> -	return 0;
> -}
> -
> -static void dsicm_disconnect(struct omap_dss_device *src,
> -			     struct omap_dss_device *dst)
> -{
> -	struct panel_drv_data *ddata = to_panel_data(dst);
> -
> -	ddata->src = NULL;
> -}
> -
> -static void dsicm_pre_enable(struct omap_dss_device *dssdev)
> -{
> -	struct panel_drv_data *ddata = to_panel_data(dssdev);
> -	struct omap_dss_device *src = ddata->src;
> -	int r;
> -	struct omap_dss_dsi_config dsi_config = {
> -		.vm = &ddata->vm,
> -		.hs_clk_min = 150000000,
> -		.hs_clk_max = 300000000,
> -		.lp_clk_min = 7000000,
> -		.lp_clk_max = 10000000,
> -	};
> -
> -	r = regulator_bulk_enable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
> -	if (r) {
> -		dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
> -	}
> +	r = regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
> +	if (r)
> +		dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
> 
> -	r = src->ops->dsi.set_config(src, &dsi_config);
> -	if (r) {
> -		dev_err(&ddata->dsi->dev, "failed to configure DSI\n");
> -	}
> +	return r;
> }
> 
> -static void dsicm_enable(struct omap_dss_device *dssdev)
> +static int dsicm_prepare(struct drm_panel *panel)
> {
> -	struct panel_drv_data *ddata = to_panel_data(dssdev);
> +	struct panel_drv_data *ddata = panel_to_ddata(panel);
> 	int r;
> 
> 	mutex_lock(&ddata->lock);
> @@ -421,33 +388,27 @@ static void dsicm_enable(struct omap_dss_device *dssdev)
> 
> 	dsicm_bl_power(ddata, true);
> 
> -	return;
> +	return 0;
> err:
> -	dev_dbg(&ddata->dsi->dev, "enable failed (%d)\n", r);
> +	dev_err(&ddata->dsi->dev, "enable failed (%d)\n", r);
> 	mutex_unlock(&ddata->lock);
> +	return r;
> }
> 
> -static void dsicm_disable(struct omap_dss_device *dssdev)
> +static int dsicm_unprepare(struct drm_panel *panel)
> {
> -	struct panel_drv_data *ddata = to_panel_data(dssdev);
> +	struct panel_drv_data *ddata = panel_to_ddata(panel);
> +	int r;
> 
> 	dsicm_bl_power(ddata, false);
> 
> 	mutex_lock(&ddata->lock);
> 
> -	dsicm_power_off(ddata);
> +	r = dsicm_power_off(ddata);
> 
> 	mutex_unlock(&ddata->lock);
> -}
> -
> -static void dsicm_post_disable(struct omap_dss_device *dssdev)
> -{
> -	struct panel_drv_data *ddata = to_panel_data(dssdev);
> -	int r;
> 
> -	r = regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
> -	if (r)
> -		dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
> +	return r;
> }
> 
> static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
> @@ -466,50 +427,35 @@ static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
> 	return r;
> }
> 
> -static int dsicm_get_modes(struct omap_dss_device *dssdev,
> -			   struct drm_connector *connector)
> +static int dsicm_get_modes(struct drm_panel *panel)
> {
> -	struct panel_drv_data *ddata = to_panel_data(dssdev);
> -
> -	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 drm_display_mode *mode)
> -{
> -	struct panel_drv_data *ddata = to_panel_data(dssdev);
> -	int ret = 0;
> +	struct panel_drv_data *ddata = panel_to_ddata(panel);
> +	struct drm_connector *connector = panel->connector;
> +	struct drm_display_mode *mode;
> +
> +	mode = drm_mode_duplicate(panel->drm, &ddata->mode);
> +	if (!mode) {
> +		dev_err(&ddata->dsi->dev, "failed to add mode %ux%ux@%u\n",
> +			ddata->mode.hdisplay, ddata->mode.vdisplay,
> +			ddata->mode.vrefresh);
> +		return -ENOMEM;
> +	}
> 
> -	if (mode->hdisplay != ddata->vm.hactive)
> -		ret = -EINVAL;
> +	drm_mode_set_name(mode);
> 
> -	if (mode->vdisplay != ddata->vm.vactive)
> -		ret = -EINVAL;
> +	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
> +	drm_mode_probed_add(connector, mode);
> 
> -	if (ret) {
> -		dev_warn(dssdev->dev, "wrong resolution: %d x %d",
> -			 mode->hdisplay, mode->vdisplay);
> -		dev_warn(dssdev->dev, "panel resolution: %d x %d",
> -			 ddata->vm.hactive, ddata->vm.vactive);
> -	}
> +	connector->display_info.width_mm = ddata->width_mm;
> +	connector->display_info.height_mm = ddata->height_mm;
> 
> -	return ret;
> +	return 1;
> }
> 
> -static const struct omap_dss_device_ops dsicm_ops = {
> -	.connect	= dsicm_connect,
> -	.disconnect	= dsicm_disconnect,
> -
> -	.pre_enable	= dsicm_pre_enable,
> -	.enable		= dsicm_enable,
> -	.disable	= dsicm_disable,
> -	.post_disable	= dsicm_post_disable,
> -
> -	.get_modes	= dsicm_get_modes,
> -	.check_timings	= dsicm_check_timings,
> +static const struct drm_panel_funcs dsicm_panel_funcs = {
> +	.unprepare = dsicm_unprepare,
> +	.prepare = dsicm_prepare,
> +	.get_modes = dsicm_get_modes,
> };
> 
> static int dsicm_probe_of(struct mipi_dsi_device *dsi)
> @@ -518,8 +464,12 @@ static int dsicm_probe_of(struct mipi_dsi_device *dsi)
> 	struct device_node *backlight;
> 	struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
> 	struct display_timing timing;
> +	struct videomode vm;
> 	int err;
> 
> +	vm.hactive = 864;
> +	vm.vactive = 480;
> +
> 	ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
> 	if (IS_ERR(ddata->reset_gpio)) {
> 		err = PTR_ERR(ddata->reset_gpio);
> @@ -529,15 +479,16 @@ static int dsicm_probe_of(struct mipi_dsi_device *dsi)
> 
> 	err = of_get_display_timing(node, "panel-timing", &timing);
> 	if (!err) {
> -		videomode_from_timing(&timing, &ddata->vm);
> -		if (!ddata->vm.pixelclock)
> -			ddata->vm.pixelclock =
> -				ddata->vm.hactive * ddata->vm.vactive * 60;
> +		videomode_from_timing(&timing, &vm);
> 	} else {
> 		dev_warn(&dsi->dev,
> 			 "failed to get video timing, using defaults\n");
> 	}
> 
> +	if (!vm.pixelclock)
> +		vm.pixelclock = vm.hactive * vm.vactive * 60;
> +	drm_display_mode_from_videomode(&vm, &ddata->mode);
> +
> 	ddata->width_mm = 0;
> 	of_property_read_u32(node, "width-mm", &ddata->width_mm);
> 
> @@ -573,7 +524,6 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
> 	struct panel_drv_data *ddata;
> 	struct backlight_device *bldev = NULL;
> 	struct device *dev = &dsi->dev;
> -	struct omap_dss_device *dssdev;
> 	int r;
> 
> 	dev_dbg(dev, "probe\n");
> @@ -585,33 +535,17 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
> 	mipi_dsi_set_drvdata(dsi, ddata);
> 	ddata->dsi = dsi;
> 
> -	ddata->vm.hactive = 864;
> -	ddata->vm.vactive = 480;
> -	ddata->vm.pixelclock = 864 * 480 * 60;
> -
> 	r = dsicm_probe_of(dsi);
> 	if (r)
> 		return r;
> 
> -	dssdev = &ddata->dssdev;
> -	dssdev->dev = dev;
> -	dssdev->ops = &dsicm_ops;
> -	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;
> -
> -	omapdss_display_init(dssdev);
> -	omapdss_device_register(dssdev);
> -
> 	mutex_init(&ddata->lock);
> 
> 	dsicm_hw_reset(ddata);
> 
> +	drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
> +		       DRM_MODE_CONNECTOR_DSI);
> +

This leads to

drivers/gpu/drm/panel/panel-dsi-cm.c: In function 'dsicm_probe':
drivers/gpu/drm/panel/panel-dsi-cm.c:552:2: error: too many arguments to function 'drm_panel_init'
  drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
  ^
In file included from drivers/gpu/drm/panel/panel-dsi-cm.c:22:0:
./include/drm/drm_panel.h:150:6: note: declared here
 void drm_panel_init(struct drm_panel *panel);
      ^

(when applied to v5.4-rc7)

> 	if (ddata->use_dsi_backlight) {
> 		struct backlight_properties props = { 0 };
> 		props.max_brightness = 255;
> @@ -643,6 +577,10 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
> 	if (ddata->ulps_enabled)
> 		dsi->mode_flags |= MIPI_DSI_MODE_ULPS_IDLE;
> 
> +	r = drm_panel_add(&ddata->panel);
> +	if (r < 0)
> +		goto err_panel_add;
> +
> 	r = mipi_dsi_attach(dsi);
> 	if (r < 0)
> 		goto err_dsi_attach;
> @@ -650,6 +588,8 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
> 	return 0;
> 
> err_dsi_attach:
> +	drm_panel_remove(&ddata->panel);
> +err_panel_add:
> 	sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
> err_bl:
> 	if (ddata->extbldev)
> @@ -661,15 +601,12 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
> static int __exit dsicm_remove(struct mipi_dsi_device *dsi)
> {
> 	struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
> -	struct omap_dss_device *dssdev = &ddata->dssdev;
> 
> 	dev_dbg(&dsi->dev, "remove\n");
> 
> 	mipi_dsi_detach(dsi);
> 
> -	omapdss_device_unregister(dssdev);
> -
> -	omapdss_device_disconnect(ddata->src, dssdev);
> +	drm_panel_remove(&ddata->panel);
> 
> 	sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
> 
> @@ -683,7 +620,7 @@ static int __exit dsicm_remove(struct mipi_dsi_device *dsi)
> }
> 
> static const struct of_device_id dsicm_of_match[] = {
> -	{ .compatible = "omapdss,panel-dsi-cm", },
> +	{ .compatible = "panel-dsi-cm", },
> 	{},
> };
> 
> diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
> index 66ad7dbc66a2..754815068927 100644
> --- a/drivers/gpu/drm/omapdrm/dss/dsi.c
> +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
> @@ -37,6 +37,7 @@
> 
> #include <video/mipi_display.h>
> #include <drm/drm_mipi_dsi.h>
> +#include <drm/drm_panel.h>
> 
> #include "omapdss.h"
> #include "dss.h"
> @@ -220,6 +221,8 @@ static int dsi_vc_send_null(struct dsi_data *dsi, int channel);
> static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi,
> 				       const struct mipi_dsi_msg *msg);
> 
> +static void dsi_display_disable(struct omap_dss_device *dssdev);
> +
> /* DSI PLL HSDIV indices */
> #define HSDIV_DISPC	0
> #define HSDIV_DSI	1
> @@ -386,6 +389,7 @@ struct dsi_data {
> 	bool te_enabled;
> 	bool ulps_enabled;
> 	bool ulps_auto_idle;
> +	bool video_enabled;
> 
> 	struct delayed_work ulps_work;
> 
> @@ -426,6 +430,8 @@ struct dsi_data {
> 
> 	unsigned int scp_clk_refcount;
> 
> +	struct omap_dss_dsi_config config;
> +
> 	struct dss_lcd_mgr_config mgr_config;
> 	struct videomode vm;
> 	enum mipi_dsi_pixel_format pix_fmt;
> @@ -3629,7 +3635,7 @@ static int dsi_configure_pins(struct omap_dss_device *dssdev,
> 	return 0;
> }
> 
> -static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
> +static void dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
> {
> 	struct dsi_data *dsi = to_dsi_data(dssdev);
> 	int bpp = mipi_dsi_pixel_format_to_bpp(dsi->pix_fmt);
> @@ -3638,8 +3644,10 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
> 	int r;
> 
> 	r = dsi_display_init_dispc(dsi);
> -	if (r)
> -		return r;
> +	if (r) {
> +		dev_err(dsi->dev, "failed to init dispc!\n");
> +		return;
> +	}
> 
> 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
> 		switch (dsi->pix_fmt) {
> @@ -3679,7 +3687,7 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
> 	if (r)
> 		goto err_mgr_enable;
> 
> -	return 0;
> +	return;
> 
> err_mgr_enable:
> 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
> @@ -3688,7 +3696,8 @@ static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
> 	}
> err_pix_fmt:
> 	dsi_display_uninit_dispc(dsi);
> -	return r;
> +	dev_err(dsi->dev, "failed to enable DSI encoder!\n");
> +	return;
> }
> 
> static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
> @@ -3711,6 +3720,25 @@ static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel
> 	dsi_display_uninit_dispc(dsi);
> }
> 
> +static void dsi_disable_video_outputs(struct omap_dss_device *dssdev)
> +{
> +	struct dsi_data *dsi = to_dsi_data(dssdev);
> +	int i;
> +
> +	dsi_bus_lock(dsi);
> +	dsi->video_enabled = false;
> +
> +	for (i = 0; i < 3; i++) {
> +		if (!dsi->vc[i].dest)
> +			continue;
> +		dsi_disable_video_output(dssdev, i);
> +	}
> +
> +	dsi_display_disable(dssdev);
> +
> +	dsi_bus_unlock(dsi);
> +}
> +
> static void dsi_update_screen_dispc(struct dsi_data *dsi)
> {
> 	unsigned int bytespp;
> @@ -3904,6 +3932,11 @@ static int dsi_update_channel(struct omap_dss_device *dssdev, int channel)
> 
> 	dsi_bus_lock(dsi);
> 
> +	if (!dsi->video_enabled) {
> +		r = -EIO;
> +		goto err;
> +	}
> +
> 	if (!dsi->vc[channel].dest) {
> 		r = -ENODEV;
> 		goto err;
> @@ -3949,7 +3982,7 @@ static int dsi_update_all(struct omap_dss_device *dssdev)
> 
> 	for (i = 0; i < 4; i++) {
> 		r = dsi_update_channel(dssdev, i);
> -		if (r != -ENODEV)
> +		if (r && r != -ENODEV)
> 			return r;
> 	}
> 
> @@ -4172,8 +4205,30 @@ static void dsi_display_enable(struct omap_dss_device *dssdev)
> {
> 	struct dsi_data *dsi = to_dsi_data(dssdev);
> 	DSSDBG("dsi_display_enable\n");
> -	dsi_bus_lock(dsi);
> +	WARN_ON(!dsi_bus_is_locked(dsi));
> +
> 	dsi_display_ulps_enable(dsi);
> +}
> +
> +static void dsi_enable_video_outputs(struct omap_dss_device *dssdev)
> +{
> +	struct dsi_data *dsi = to_dsi_data(dssdev);
> +	int i;
> +
> +	dsi_bus_lock(dsi);
> +
> +	dsi_display_enable(dssdev);
> +
> +	for (i = 0; i < 3; i++) {
> +		if (!dsi->vc[i].dest)
> +			continue;
> +		dsi_enable_video_output(dssdev, i);
> +	}
> +
> +	dsi->video_enabled = true;
> +
> +	dsi_set_ulps_auto(dsi, true);
> +
> 	dsi_bus_unlock(dsi);
> }
> 
> @@ -4199,10 +4254,10 @@ static void dsi_display_ulps_disable(struct dsi_data *dsi,
> static void dsi_display_disable(struct omap_dss_device *dssdev)
> {
> 	struct dsi_data *dsi = to_dsi_data(dssdev);
> +	WARN_ON(!dsi_bus_is_locked(dsi));
> 	DSSDBG("dsi_display_disable\n");
> -	dsi_bus_lock(dsi);
> +
> 	dsi_display_ulps_disable(dsi, true, false);
> -	dsi_bus_unlock(dsi);
> }
> 
> static int dsi_enable_te(struct dsi_data *dsi, bool enable)
> @@ -4732,15 +4787,26 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
> 			dsi_vm_calc_pll_cb, ctx);
> }
> 
> +static bool dsi_is_video_mode(struct omap_dss_device *dssdev)
> +{
> +	struct dsi_data *dsi = to_dsi_data(dssdev);
> +
> +	return (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE);
> +}
> +
> static int dsi_set_config(struct omap_dss_device *dssdev,
> -		const struct omap_dss_dsi_config *config)
> +		const struct drm_display_mode *mode)
> {
> 	struct dsi_data *dsi = to_dsi_data(dssdev);
> 	struct dsi_clk_calc_ctx ctx;
> -	struct omap_dss_dsi_config cfg = *config;
> +	struct videomode vm;
> +	struct omap_dss_dsi_config cfg = dsi->config;
> 	bool ok;
> 	int r;
> 
> +	drm_display_mode_to_videomode(mode, &vm);
> +	cfg.vm = &vm;
> +
> 	mutex_lock(&dsi->lock);
> 
> 	cfg.mode = dsi->mode;
> @@ -4903,9 +4969,15 @@ static ssize_t omap_dsi_host_transfer(struct mipi_dsi_host *host,
> 	int r;
> 
> 	dsi_bus_lock(dsi);
> -	dsi_set_ulps_auto(dsi, false);
> -	r = _omap_dsi_host_transfer(dsi, msg);
> -	dsi_set_ulps_auto(dsi, true);
> +
> +	if (dsi->video_enabled) {
> +		dsi_set_ulps_auto(dsi, false);
> +		r = _omap_dsi_host_transfer(dsi, msg);
> +		dsi_set_ulps_auto(dsi, true);
> +	} else {
> +		r = -EIO;
> +	}
> +
> 	dsi_bus_unlock(dsi);
> 
> 	return r;
> @@ -4926,6 +4998,23 @@ static int dsi_get_clocks(struct dsi_data *dsi)
> 	return 0;
> }
> 
> +static void dsi_set_timings(struct omap_dss_device *dssdev,
> +			    const struct drm_display_mode *mode)
> +{
> +	DSSDBG("dsi_set_timings\n");
> +	dsi_set_config(dssdev, mode);
> +}
> +
> +static int dsi_check_timings(struct omap_dss_device *dssdev,
> +			     struct drm_display_mode *mode)
> +{
> +	DSSDBG("dsi_check_timings\n");
> +
> +	/* TODO */
> +
> +	return 0;
> +}
> +
> static int dsi_connect(struct omap_dss_device *src,
> 		       struct omap_dss_device *dst)
> {
> @@ -4941,16 +5030,15 @@ static void dsi_disconnect(struct omap_dss_device *src,
> static const struct omap_dss_device_ops dsi_ops = {
> 	.connect = dsi_connect,
> 	.disconnect = dsi_disconnect,
> -	.enable = dsi_display_enable,
> -	.disable = dsi_display_disable,
> -
> -	.dsi = {
> -		.set_config = dsi_set_config,
> +	.enable = dsi_enable_video_outputs,
> +	.disable = dsi_disable_video_outputs,
> 
> -		.enable_video_output = dsi_enable_video_output,
> -		.disable_video_output = dsi_disable_video_output,
> +	.check_timings = dsi_check_timings,
> +	.set_timings = dsi_set_timings,
> 
> +	.dsi = {
> 		.update = dsi_update_all,
> +		.is_video_mode = dsi_is_video_mode,
> 	},
> };
> 
> @@ -5038,6 +5126,7 @@ int omap_dsi_host_attach(struct mipi_dsi_host *host,
> {
> 	struct dsi_data *dsi = host_to_omap(host);
> 	unsigned int channel = client->channel;
> +	struct drm_panel *panel;
> 	int r;
> 
> 	if (channel > 3)
> @@ -5050,6 +5139,10 @@ int omap_dsi_host_attach(struct mipi_dsi_host *host,
> 
> 	dsi_bus_lock(dsi);
> 
> +	panel = of_drm_find_panel(client->dev.of_node);
> +	if (IS_ERR(panel))
> +		return PTR_ERR(panel);
> +
> 	atomic_set(&dsi->do_ext_te_update, 0);
> 
> 	if (client->mode_flags & MIPI_DSI_MODE_VIDEO) {
> @@ -5070,8 +5163,12 @@ int omap_dsi_host_attach(struct mipi_dsi_host *host,
> 	INIT_DEFERRABLE_WORK(&dsi->ulps_work,
> 			     omap_dsi_ulps_work_callback);
> 
> +	dsi->config.hs_clk_min = 150000000; // TODO: get from client?
> +	dsi->config.hs_clk_max = client->hs_rate;
> +	dsi->config.lp_clk_min = 7000000; // TODO: get from client?
> +	dsi->config.lp_clk_max = client->lp_rate;
> +
> 	dsi->ulps_auto_idle = !!(client->mode_flags & MIPI_DSI_MODE_ULPS_IDLE);
> -	dsi_set_ulps_auto(dsi, true);
> 
> 	dsi_bus_unlock(dsi);
> 	return 0;
> diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
> index 31502857f013..05ac2e1cd77e 100644
> --- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
> +++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
> @@ -176,7 +176,6 @@ static const struct of_device_id omapdss_of_match[] __initconst = {
> static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = {
> 	{ .compatible = "composite-video-connector" },
> 	{ .compatible = "hdmi-connector" },
> -	{ .compatible = "panel-dsi-cm" },
> 	{ .compatible = "svideo-connector" },
> 	{ .compatible = "ti,opa362" },
> 	{ .compatible = "ti,tpd12s015" },
> diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
> index 21601af29ee4..bfb402a88475 100644
> --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
> +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
> @@ -122,11 +122,6 @@ enum omap_dss_dsi_mode {
> 	OMAP_DSS_DSI_VIDEO_MODE,
> };
> 
> -enum omap_display_caps {
> -	OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE	= 1 << 0,
> -	OMAP_DSS_DISPLAY_CAP_TEAR_ELIM		= 1 << 1,
> -};
> -
> enum omap_dss_display_state {
> 	OMAP_DSS_DISPLAY_DISABLED = 0,
> 	OMAP_DSS_DISPLAY_ACTIVE,
> @@ -288,14 +283,7 @@ struct omapdss_hdmi_ops {
> 
> struct omapdss_dsi_ops {
> 	int (*update)(struct omap_dss_device *dssdev);
> -
> -	/* legacy API used by omapdss panels */
> -	int (*set_config)(struct omap_dss_device *dssdev,
> -			const struct omap_dss_dsi_config *cfg);
> -
> -	int (*enable_video_output)(struct omap_dss_device *dssdev, int channel);
> -	void (*disable_video_output)(struct omap_dss_device *dssdev,
> -			int channel);
> +	bool (*is_video_mode)(struct omap_dss_device *dssdev);
> };
> 
> struct omap_dss_device_ops {
> @@ -374,13 +362,10 @@ struct omap_dss_device {
> 
> 	const char *name;
> 
> -	const struct omap_dss_driver *driver;
> 	const struct omap_dss_device_ops *ops;
> 	unsigned long ops_flags;
> 	u32 bus_flags;
> 
> -	enum omap_display_caps caps;
> -
> 	enum omap_dss_display_state state;
> 
> 	/* OMAP DSS output specific fields */
> @@ -395,11 +380,6 @@ struct omap_dss_device {
> 	unsigned int of_ports;
> };
> 
> -struct omap_dss_driver {
> -	int (*update)(struct omap_dss_device *dssdev,
> -			       u16 x, u16 y, u16 w, u16 h);
> -};
> -
> struct dss_device *omapdss_get_dss(void);
> void omapdss_set_dss(struct dss_device *dss);
> static inline bool omapdss_is_initialized(void)
> diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
> index a8d0543d1296..80ed1b15ba49 100644
> --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> @@ -495,8 +495,7 @@ static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
> 	 * valid DISPC mode. DSI will calculate and configure the
> 	 * proper DISPC mode later.
> 	 */
> -	if (omap_crtc->pipe->output->next == NULL ||
> -	    omap_crtc->pipe->output->next->type != OMAP_DISPLAY_TYPE_DSI) {
> +	if (omap_crtc->pipe->output->type != OMAP_DISPLAY_TYPE_DSI) {
> 		r = priv->dispc_ops->mgr_check_timings(priv->dispc,
> 						       omap_crtc->channel,
> 						       &vm);
> @@ -548,17 +547,17 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
> static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
> {
> 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
> -	struct omap_dss_device *display = omap_crtc->pipe->output->next;
> +	struct omap_dss_device *dssdev = omap_crtc->pipe->output;
> 
> -	if (!display)
> +	if (dssdev->type != OMAP_DISPLAY_TYPE_DSI ||
> +	    !dssdev->ops->dsi.is_video_mode)
> 		return false;
> 
> -	if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
> -		DBG("detected manually updated display!");
> -		return true;
> -	}
> +	if (dssdev->ops->dsi.is_video_mode(dssdev))
> +		return false;
> 
> -	return false;
> +	DBG("detected manually updated display!");
> +	return true;
> }
> 
> static int omap_crtc_atomic_check(struct drm_crtc *crtc,
> -- 
> 2.24.0
> 

Otherwise the patches compile fine and my work-in progress
DSI panel driver is probing, but not initializing.

BR,
Nikolaus
Sebastian Reichel Nov. 18, 2019, 2:45 p.m. UTC | #2
Hi,

On Sun, Nov 17, 2019 at 08:23:05PM +0100, H. Nikolaus Schaller wrote:
> > [...]
>
> > +	drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
> > +		       DRM_MODE_CONNECTOR_DSI);
> > +
> 
> This leads to
> 
> drivers/gpu/drm/panel/panel-dsi-cm.c: In function 'dsicm_probe':
> drivers/gpu/drm/panel/panel-dsi-cm.c:552:2: error: too many arguments to function 'drm_panel_init'
>   drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
>   ^
> In file included from drivers/gpu/drm/panel/panel-dsi-cm.c:22:0:
> ./include/drm/drm_panel.h:150:6: note: declared here
>  void drm_panel_init(struct drm_panel *panel);
>       ^
> 
> (when applied to v5.4-rc7)

The patchset is based on drm-next from
https://anongit.freedesktop.org/git/drm/drm.git

For v5.4-rc7 it needs to look like this:

+	drm_panel_init(&ddata->panel);
+	ddata->panel.dev = dev;
+	ddata->panel.funcs = &dsicm_panel_funcs;

> > [...] 
> 
> Otherwise the patches compile fine and my work-in progress
> DSI panel driver is probing, but not initializing.

Ok, I tried not to break video mode support, but I do not have any
hardware. Make sure to set the MIPI_DSI_MODE_VIDEO flag in the panel
driver.

-- Sebastian
H. Nikolaus Schaller Nov. 18, 2019, 2:51 p.m. UTC | #3
> Am 18.11.2019 um 15:45 schrieb Sebastian Reichel <sebastian.reichel@collabora.com>:
> 
> Hi,
> 
> On Sun, Nov 17, 2019 at 08:23:05PM +0100, H. Nikolaus Schaller wrote:
>>> [...]
>> 
>>> +	drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
>>> +		       DRM_MODE_CONNECTOR_DSI);
>>> +
>> 
>> This leads to
>> 
>> drivers/gpu/drm/panel/panel-dsi-cm.c: In function 'dsicm_probe':
>> drivers/gpu/drm/panel/panel-dsi-cm.c:552:2: error: too many arguments to function 'drm_panel_init'
>>  drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
>>  ^
>> In file included from drivers/gpu/drm/panel/panel-dsi-cm.c:22:0:
>> ./include/drm/drm_panel.h:150:6: note: declared here
>> void drm_panel_init(struct drm_panel *panel);
>>      ^
>> 
>> (when applied to v5.4-rc7)
> 
> The patchset is based on drm-next from
> https://anongit.freedesktop.org/git/drm/drm.git
> 
> For v5.4-rc7 it needs to look like this:
> 
> +	drm_panel_init(&ddata->panel);
> +	ddata->panel.dev = dev;
> +	ddata->panel.funcs = &dsicm_panel_funcs;

Ah, ok. The issue with changed parameters seems
to already be fixed by two patches in linux-next
and therefore soon in v5.5-rc1.

> 
>>> [...] 
>> 
>> Otherwise the patches compile fine and my work-in progress
>> DSI panel driver is probing, but not initializing.
> 
> Ok, I tried not to break video mode support, but I do not have any
> hardware. Make sure to set the MIPI_DSI_MODE_VIDEO flag in the panel
> driver.

Indeed, this may be missing (can't look into the code at the moment)...
Or I did something wrong when refactoring the driver.
We will find out.

BR and thanks for the great work,
Nikolaus
H. Nikolaus Schaller Nov. 19, 2019, 9:42 a.m. UTC | #4
Hi Sebastian,

> Am 18.11.2019 um 15:51 schrieb H. Nikolaus Schaller <hns@goldelico.com>:
> 
>> Ok, I tried not to break video mode support, but I do not have any
>> hardware. Make sure to set the MIPI_DSI_MODE_VIDEO flag in the panel
>> driver.
> 
> Indeed, this may be missing (can't look into the code at the moment)...
> Or I did something wrong when refactoring the driver.
> We will find out.

Yes, MIPI_DSI_MODE_VIDEO was indeed missing/wrongly applied and some
more bugs. But I still wasn't able to make it work.

I also tried to fake the panel-orisetech-otm8009a.c DSI driver into
my setup. It should not properly program the panel by DCS command
but it should try to.

Result is the same: I can see it being probed and calling get_modes
but then:

[drm] Cannot find any crtc or sizes

And I don't see calls to .enable or .prepare where DCS commands would
be sent.

BR and thanks,
Nikolaus
Sebastian Reichel Nov. 19, 2019, 9:21 p.m. UTC | #5
Hi Nikolaus,

On Tue, Nov 19, 2019 at 10:42:55AM +0100, H. Nikolaus Schaller wrote:
> > Am 18.11.2019 um 15:51 schrieb H. Nikolaus Schaller <hns@goldelico.com>:
> > 
> >> Ok, I tried not to break video mode support, but I do not have any
> >> hardware. Make sure to set the MIPI_DSI_MODE_VIDEO flag in the panel
> >> driver.
> > 
> > Indeed, this may be missing (can't look into the code at the moment)...
> > Or I did something wrong when refactoring the driver.
> > We will find out.
> 
> Yes, MIPI_DSI_MODE_VIDEO was indeed missing/wrongly applied and some
> more bugs. But I still wasn't able to make it work.
> 
> I also tried to fake the panel-orisetech-otm8009a.c DSI driver into
> my setup. It should not properly program the panel by DCS command
> but it should try to.
> 
> Result is the same: I can see it being probed and calling get_modes
> but then:
> 
> [drm] Cannot find any crtc or sizes
> 
> And I don't see calls to .enable or .prepare where DCS commands would
> be sent.

You probably want to enable all kind of drm debugging to get more
information. I guess, that some timing check fails, e.g.
dsi_check_timings(). If the timing checks fail, the mode will not
be added as valid mode. When no valid mode is found, the panel
will not be enabled.

-- Sebastian
diff mbox series

Patch

diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
index 18020ac43a83..84b0e79c025e 100644
--- a/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
+++ b/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
@@ -6,8 +6,6 @@ 
  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
  */
 
-/* #define DEBUG */
-
 #include <linux/backlight.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
@@ -20,11 +18,14 @@ 
 #include <linux/regulator/consumer.h>
 
 #include <drm/drm_connector.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_modes.h>
 
+#include <video/display_timing.h>
 #include <video/mipi_display.h>
 #include <video/of_display_timing.h>
-
-#include "../dss/omapdss.h"
+#include <video/videomode.h>
 
 #define DCS_READ_NUM_ERRORS	0x05
 #define DCS_GET_ID1		0xda
@@ -35,11 +36,8 @@ 
 
 struct panel_drv_data {
 	struct mipi_dsi_device *dsi;
-
-	struct omap_dss_device dssdev;
-	struct omap_dss_device *src;
-
-	struct videomode vm;
+	struct drm_panel panel;
+	struct drm_display_mode mode;
 
 	struct mutex lock;
 
@@ -71,7 +69,11 @@  struct panel_drv_data {
 	bool ulps_enabled;
 };
 
-#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
+
+static inline struct panel_drv_data *panel_to_ddata(struct drm_panel *panel)
+{
+	return container_of(panel, struct panel_drv_data, panel);
+}
 
 static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
 
@@ -285,10 +287,15 @@  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->src;
 	u8 id1, id2, id3;
 	int r;
 
+	r = regulator_bulk_enable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
+	if (r) {
+		dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
+		return r;
+	}
+
 	dsicm_hw_reset(ddata);
 
 	ddata->dsi->mode_flags |= MIPI_DSI_MODE_LPM;
@@ -322,10 +329,6 @@  static int dsicm_power_on(struct panel_drv_data *ddata)
 	if (r)
 		goto err;
 
-	r = src->ops->dsi.enable_video_output(src, ddata->dsi->channel);
-	if (r)
-		goto err;
-
 	ddata->enabled = 1;
 
 	if (!ddata->intro_printed) {
@@ -342,18 +345,17 @@  static int dsicm_power_on(struct panel_drv_data *ddata)
 
 	dsicm_hw_reset(ddata);
 
+	regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
+
 	return r;
 }
 
-static void dsicm_power_off(struct panel_drv_data *ddata)
+static int dsicm_power_off(struct panel_drv_data *ddata)
 {
-	struct omap_dss_device *src = ddata->src;
 	int r;
 
 	ddata->enabled = 0;
 
-	src->ops->dsi.disable_video_output(src, ddata->dsi->channel);
-
 	r = mipi_dsi_dcs_set_display_off(ddata->dsi);
 	if (!r)
 		r = dsicm_sleep_in(ddata);
@@ -363,52 +365,17 @@  static void dsicm_power_off(struct panel_drv_data *ddata)
 				"error disabling panel, issuing HW reset\n");
 		dsicm_hw_reset(ddata);
 	}
-}
 
-static int dsicm_connect(struct omap_dss_device *src,
-			 struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dst);
-
-	ddata->src = src;
-	return 0;
-}
-
-static void dsicm_disconnect(struct omap_dss_device *src,
-			     struct omap_dss_device *dst)
-{
-	struct panel_drv_data *ddata = to_panel_data(dst);
-
-	ddata->src = NULL;
-}
-
-static void dsicm_pre_enable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	struct omap_dss_device *src = ddata->src;
-	int r;
-	struct omap_dss_dsi_config dsi_config = {
-		.vm = &ddata->vm,
-		.hs_clk_min = 150000000,
-		.hs_clk_max = 300000000,
-		.lp_clk_min = 7000000,
-		.lp_clk_max = 10000000,
-	};
-
-	r = regulator_bulk_enable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
-	if (r) {
-		dev_err(&ddata->dsi->dev, "failed to enable supplies: %d\n", r);
-	}
+	r = regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
+	if (r)
+		dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
 
-	r = src->ops->dsi.set_config(src, &dsi_config);
-	if (r) {
-		dev_err(&ddata->dsi->dev, "failed to configure DSI\n");
-	}
+	return r;
 }
 
-static void dsicm_enable(struct omap_dss_device *dssdev)
+static int dsicm_prepare(struct drm_panel *panel)
 {
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct panel_drv_data *ddata = panel_to_ddata(panel);
 	int r;
 
 	mutex_lock(&ddata->lock);
@@ -421,33 +388,27 @@  static void dsicm_enable(struct omap_dss_device *dssdev)
 
 	dsicm_bl_power(ddata, true);
 
-	return;
+	return 0;
 err:
-	dev_dbg(&ddata->dsi->dev, "enable failed (%d)\n", r);
+	dev_err(&ddata->dsi->dev, "enable failed (%d)\n", r);
 	mutex_unlock(&ddata->lock);
+	return r;
 }
 
-static void dsicm_disable(struct omap_dss_device *dssdev)
+static int dsicm_unprepare(struct drm_panel *panel)
 {
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
+	struct panel_drv_data *ddata = panel_to_ddata(panel);
+	int r;
 
 	dsicm_bl_power(ddata, false);
 
 	mutex_lock(&ddata->lock);
 
-	dsicm_power_off(ddata);
+	r = dsicm_power_off(ddata);
 
 	mutex_unlock(&ddata->lock);
-}
-
-static void dsicm_post_disable(struct omap_dss_device *dssdev)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	int r;
 
-	r = regulator_bulk_disable(DCS_REGULATOR_SUPPLY_NUM, ddata->supplies);
-	if (r)
-		dev_err(&ddata->dsi->dev, "failed to disable supplies: %d\n", r);
+	return r;
 }
 
 static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
@@ -466,50 +427,35 @@  static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
 	return r;
 }
 
-static int dsicm_get_modes(struct omap_dss_device *dssdev,
-			   struct drm_connector *connector)
+static int dsicm_get_modes(struct drm_panel *panel)
 {
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-
-	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 drm_display_mode *mode)
-{
-	struct panel_drv_data *ddata = to_panel_data(dssdev);
-	int ret = 0;
+	struct panel_drv_data *ddata = panel_to_ddata(panel);
+	struct drm_connector *connector = panel->connector;
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(panel->drm, &ddata->mode);
+	if (!mode) {
+		dev_err(&ddata->dsi->dev, "failed to add mode %ux%ux@%u\n",
+			ddata->mode.hdisplay, ddata->mode.vdisplay,
+			ddata->mode.vrefresh);
+		return -ENOMEM;
+	}
 
-	if (mode->hdisplay != ddata->vm.hactive)
-		ret = -EINVAL;
+	drm_mode_set_name(mode);
 
-	if (mode->vdisplay != ddata->vm.vactive)
-		ret = -EINVAL;
+	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+	drm_mode_probed_add(connector, mode);
 
-	if (ret) {
-		dev_warn(dssdev->dev, "wrong resolution: %d x %d",
-			 mode->hdisplay, mode->vdisplay);
-		dev_warn(dssdev->dev, "panel resolution: %d x %d",
-			 ddata->vm.hactive, ddata->vm.vactive);
-	}
+	connector->display_info.width_mm = ddata->width_mm;
+	connector->display_info.height_mm = ddata->height_mm;
 
-	return ret;
+	return 1;
 }
 
-static const struct omap_dss_device_ops dsicm_ops = {
-	.connect	= dsicm_connect,
-	.disconnect	= dsicm_disconnect,
-
-	.pre_enable	= dsicm_pre_enable,
-	.enable		= dsicm_enable,
-	.disable	= dsicm_disable,
-	.post_disable	= dsicm_post_disable,
-
-	.get_modes	= dsicm_get_modes,
-	.check_timings	= dsicm_check_timings,
+static const struct drm_panel_funcs dsicm_panel_funcs = {
+	.unprepare = dsicm_unprepare,
+	.prepare = dsicm_prepare,
+	.get_modes = dsicm_get_modes,
 };
 
 static int dsicm_probe_of(struct mipi_dsi_device *dsi)
@@ -518,8 +464,12 @@  static int dsicm_probe_of(struct mipi_dsi_device *dsi)
 	struct device_node *backlight;
 	struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
 	struct display_timing timing;
+	struct videomode vm;
 	int err;
 
+	vm.hactive = 864;
+	vm.vactive = 480;
+
 	ddata->reset_gpio = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(ddata->reset_gpio)) {
 		err = PTR_ERR(ddata->reset_gpio);
@@ -529,15 +479,16 @@  static int dsicm_probe_of(struct mipi_dsi_device *dsi)
 
 	err = of_get_display_timing(node, "panel-timing", &timing);
 	if (!err) {
-		videomode_from_timing(&timing, &ddata->vm);
-		if (!ddata->vm.pixelclock)
-			ddata->vm.pixelclock =
-				ddata->vm.hactive * ddata->vm.vactive * 60;
+		videomode_from_timing(&timing, &vm);
 	} else {
 		dev_warn(&dsi->dev,
 			 "failed to get video timing, using defaults\n");
 	}
 
+	if (!vm.pixelclock)
+		vm.pixelclock = vm.hactive * vm.vactive * 60;
+	drm_display_mode_from_videomode(&vm, &ddata->mode);
+
 	ddata->width_mm = 0;
 	of_property_read_u32(node, "width-mm", &ddata->width_mm);
 
@@ -573,7 +524,6 @@  static int dsicm_probe(struct mipi_dsi_device *dsi)
 	struct panel_drv_data *ddata;
 	struct backlight_device *bldev = NULL;
 	struct device *dev = &dsi->dev;
-	struct omap_dss_device *dssdev;
 	int r;
 
 	dev_dbg(dev, "probe\n");
@@ -585,33 +535,17 @@  static int dsicm_probe(struct mipi_dsi_device *dsi)
 	mipi_dsi_set_drvdata(dsi, ddata);
 	ddata->dsi = dsi;
 
-	ddata->vm.hactive = 864;
-	ddata->vm.vactive = 480;
-	ddata->vm.pixelclock = 864 * 480 * 60;
-
 	r = dsicm_probe_of(dsi);
 	if (r)
 		return r;
 
-	dssdev = &ddata->dssdev;
-	dssdev->dev = dev;
-	dssdev->ops = &dsicm_ops;
-	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;
-
-	omapdss_display_init(dssdev);
-	omapdss_device_register(dssdev);
-
 	mutex_init(&ddata->lock);
 
 	dsicm_hw_reset(ddata);
 
+	drm_panel_init(&ddata->panel, dev, &dsicm_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
+
 	if (ddata->use_dsi_backlight) {
 		struct backlight_properties props = { 0 };
 		props.max_brightness = 255;
@@ -643,6 +577,10 @@  static int dsicm_probe(struct mipi_dsi_device *dsi)
 	if (ddata->ulps_enabled)
 		dsi->mode_flags |= MIPI_DSI_MODE_ULPS_IDLE;
 
+	r = drm_panel_add(&ddata->panel);
+	if (r < 0)
+		goto err_panel_add;
+
 	r = mipi_dsi_attach(dsi);
 	if (r < 0)
 		goto err_dsi_attach;
@@ -650,6 +588,8 @@  static int dsicm_probe(struct mipi_dsi_device *dsi)
 	return 0;
 
 err_dsi_attach:
+	drm_panel_remove(&ddata->panel);
+err_panel_add:
 	sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
 err_bl:
 	if (ddata->extbldev)
@@ -661,15 +601,12 @@  static int dsicm_probe(struct mipi_dsi_device *dsi)
 static int __exit dsicm_remove(struct mipi_dsi_device *dsi)
 {
 	struct panel_drv_data *ddata = mipi_dsi_get_drvdata(dsi);
-	struct omap_dss_device *dssdev = &ddata->dssdev;
 
 	dev_dbg(&dsi->dev, "remove\n");
 
 	mipi_dsi_detach(dsi);
 
-	omapdss_device_unregister(dssdev);
-
-	omapdss_device_disconnect(ddata->src, dssdev);
+	drm_panel_remove(&ddata->panel);
 
 	sysfs_remove_group(&dsi->dev.kobj, &dsicm_attr_group);
 
@@ -683,7 +620,7 @@  static int __exit dsicm_remove(struct mipi_dsi_device *dsi)
 }
 
 static const struct of_device_id dsicm_of_match[] = {
-	{ .compatible = "omapdss,panel-dsi-cm", },
+	{ .compatible = "panel-dsi-cm", },
 	{},
 };
 
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index 66ad7dbc66a2..754815068927 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -37,6 +37,7 @@ 
 
 #include <video/mipi_display.h>
 #include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
 
 #include "omapdss.h"
 #include "dss.h"
@@ -220,6 +221,8 @@  static int dsi_vc_send_null(struct dsi_data *dsi, int channel);
 static ssize_t _omap_dsi_host_transfer(struct dsi_data *dsi,
 				       const struct mipi_dsi_msg *msg);
 
+static void dsi_display_disable(struct omap_dss_device *dssdev);
+
 /* DSI PLL HSDIV indices */
 #define HSDIV_DISPC	0
 #define HSDIV_DSI	1
@@ -386,6 +389,7 @@  struct dsi_data {
 	bool te_enabled;
 	bool ulps_enabled;
 	bool ulps_auto_idle;
+	bool video_enabled;
 
 	struct delayed_work ulps_work;
 
@@ -426,6 +430,8 @@  struct dsi_data {
 
 	unsigned int scp_clk_refcount;
 
+	struct omap_dss_dsi_config config;
+
 	struct dss_lcd_mgr_config mgr_config;
 	struct videomode vm;
 	enum mipi_dsi_pixel_format pix_fmt;
@@ -3629,7 +3635,7 @@  static int dsi_configure_pins(struct omap_dss_device *dssdev,
 	return 0;
 }
 
-static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
+static void dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 {
 	struct dsi_data *dsi = to_dsi_data(dssdev);
 	int bpp = mipi_dsi_pixel_format_to_bpp(dsi->pix_fmt);
@@ -3638,8 +3644,10 @@  static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 	int r;
 
 	r = dsi_display_init_dispc(dsi);
-	if (r)
-		return r;
+	if (r) {
+		dev_err(dsi->dev, "failed to init dispc!\n");
+		return;
+	}
 
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		switch (dsi->pix_fmt) {
@@ -3679,7 +3687,7 @@  static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 	if (r)
 		goto err_mgr_enable;
 
-	return 0;
+	return;
 
 err_mgr_enable:
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
@@ -3688,7 +3696,8 @@  static int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
 	}
 err_pix_fmt:
 	dsi_display_uninit_dispc(dsi);
-	return r;
+	dev_err(dsi->dev, "failed to enable DSI encoder!\n");
+	return;
 }
 
 static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
@@ -3711,6 +3720,25 @@  static void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel
 	dsi_display_uninit_dispc(dsi);
 }
 
+static void dsi_disable_video_outputs(struct omap_dss_device *dssdev)
+{
+	struct dsi_data *dsi = to_dsi_data(dssdev);
+	int i;
+
+	dsi_bus_lock(dsi);
+	dsi->video_enabled = false;
+
+	for (i = 0; i < 3; i++) {
+		if (!dsi->vc[i].dest)
+			continue;
+		dsi_disable_video_output(dssdev, i);
+	}
+
+	dsi_display_disable(dssdev);
+
+	dsi_bus_unlock(dsi);
+}
+
 static void dsi_update_screen_dispc(struct dsi_data *dsi)
 {
 	unsigned int bytespp;
@@ -3904,6 +3932,11 @@  static int dsi_update_channel(struct omap_dss_device *dssdev, int channel)
 
 	dsi_bus_lock(dsi);
 
+	if (!dsi->video_enabled) {
+		r = -EIO;
+		goto err;
+	}
+
 	if (!dsi->vc[channel].dest) {
 		r = -ENODEV;
 		goto err;
@@ -3949,7 +3982,7 @@  static int dsi_update_all(struct omap_dss_device *dssdev)
 
 	for (i = 0; i < 4; i++) {
 		r = dsi_update_channel(dssdev, i);
-		if (r != -ENODEV)
+		if (r && r != -ENODEV)
 			return r;
 	}
 
@@ -4172,8 +4205,30 @@  static void dsi_display_enable(struct omap_dss_device *dssdev)
 {
 	struct dsi_data *dsi = to_dsi_data(dssdev);
 	DSSDBG("dsi_display_enable\n");
-	dsi_bus_lock(dsi);
+	WARN_ON(!dsi_bus_is_locked(dsi));
+
 	dsi_display_ulps_enable(dsi);
+}
+
+static void dsi_enable_video_outputs(struct omap_dss_device *dssdev)
+{
+	struct dsi_data *dsi = to_dsi_data(dssdev);
+	int i;
+
+	dsi_bus_lock(dsi);
+
+	dsi_display_enable(dssdev);
+
+	for (i = 0; i < 3; i++) {
+		if (!dsi->vc[i].dest)
+			continue;
+		dsi_enable_video_output(dssdev, i);
+	}
+
+	dsi->video_enabled = true;
+
+	dsi_set_ulps_auto(dsi, true);
+
 	dsi_bus_unlock(dsi);
 }
 
@@ -4199,10 +4254,10 @@  static void dsi_display_ulps_disable(struct dsi_data *dsi,
 static void dsi_display_disable(struct omap_dss_device *dssdev)
 {
 	struct dsi_data *dsi = to_dsi_data(dssdev);
+	WARN_ON(!dsi_bus_is_locked(dsi));
 	DSSDBG("dsi_display_disable\n");
-	dsi_bus_lock(dsi);
+
 	dsi_display_ulps_disable(dsi, true, false);
-	dsi_bus_unlock(dsi);
 }
 
 static int dsi_enable_te(struct dsi_data *dsi, bool enable)
@@ -4732,15 +4787,26 @@  static bool dsi_vm_calc(struct dsi_data *dsi,
 			dsi_vm_calc_pll_cb, ctx);
 }
 
+static bool dsi_is_video_mode(struct omap_dss_device *dssdev)
+{
+	struct dsi_data *dsi = to_dsi_data(dssdev);
+
+	return (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE);
+}
+
 static int dsi_set_config(struct omap_dss_device *dssdev,
-		const struct omap_dss_dsi_config *config)
+		const struct drm_display_mode *mode)
 {
 	struct dsi_data *dsi = to_dsi_data(dssdev);
 	struct dsi_clk_calc_ctx ctx;
-	struct omap_dss_dsi_config cfg = *config;
+	struct videomode vm;
+	struct omap_dss_dsi_config cfg = dsi->config;
 	bool ok;
 	int r;
 
+	drm_display_mode_to_videomode(mode, &vm);
+	cfg.vm = &vm;
+
 	mutex_lock(&dsi->lock);
 
 	cfg.mode = dsi->mode;
@@ -4903,9 +4969,15 @@  static ssize_t omap_dsi_host_transfer(struct mipi_dsi_host *host,
 	int r;
 
 	dsi_bus_lock(dsi);
-	dsi_set_ulps_auto(dsi, false);
-	r = _omap_dsi_host_transfer(dsi, msg);
-	dsi_set_ulps_auto(dsi, true);
+
+	if (dsi->video_enabled) {
+		dsi_set_ulps_auto(dsi, false);
+		r = _omap_dsi_host_transfer(dsi, msg);
+		dsi_set_ulps_auto(dsi, true);
+	} else {
+		r = -EIO;
+	}
+
 	dsi_bus_unlock(dsi);
 
 	return r;
@@ -4926,6 +4998,23 @@  static int dsi_get_clocks(struct dsi_data *dsi)
 	return 0;
 }
 
+static void dsi_set_timings(struct omap_dss_device *dssdev,
+			    const struct drm_display_mode *mode)
+{
+	DSSDBG("dsi_set_timings\n");
+	dsi_set_config(dssdev, mode);
+}
+
+static int dsi_check_timings(struct omap_dss_device *dssdev,
+			     struct drm_display_mode *mode)
+{
+	DSSDBG("dsi_check_timings\n");
+
+	/* TODO */
+
+	return 0;
+}
+
 static int dsi_connect(struct omap_dss_device *src,
 		       struct omap_dss_device *dst)
 {
@@ -4941,16 +5030,15 @@  static void dsi_disconnect(struct omap_dss_device *src,
 static const struct omap_dss_device_ops dsi_ops = {
 	.connect = dsi_connect,
 	.disconnect = dsi_disconnect,
-	.enable = dsi_display_enable,
-	.disable = dsi_display_disable,
-
-	.dsi = {
-		.set_config = dsi_set_config,
+	.enable = dsi_enable_video_outputs,
+	.disable = dsi_disable_video_outputs,
 
-		.enable_video_output = dsi_enable_video_output,
-		.disable_video_output = dsi_disable_video_output,
+	.check_timings = dsi_check_timings,
+	.set_timings = dsi_set_timings,
 
+	.dsi = {
 		.update = dsi_update_all,
+		.is_video_mode = dsi_is_video_mode,
 	},
 };
 
@@ -5038,6 +5126,7 @@  int omap_dsi_host_attach(struct mipi_dsi_host *host,
 {
 	struct dsi_data *dsi = host_to_omap(host);
 	unsigned int channel = client->channel;
+	struct drm_panel *panel;
 	int r;
 
 	if (channel > 3)
@@ -5050,6 +5139,10 @@  int omap_dsi_host_attach(struct mipi_dsi_host *host,
 
 	dsi_bus_lock(dsi);
 
+	panel = of_drm_find_panel(client->dev.of_node);
+	if (IS_ERR(panel))
+		return PTR_ERR(panel);
+
 	atomic_set(&dsi->do_ext_te_update, 0);
 
 	if (client->mode_flags & MIPI_DSI_MODE_VIDEO) {
@@ -5070,8 +5163,12 @@  int omap_dsi_host_attach(struct mipi_dsi_host *host,
 	INIT_DEFERRABLE_WORK(&dsi->ulps_work,
 			     omap_dsi_ulps_work_callback);
 
+	dsi->config.hs_clk_min = 150000000; // TODO: get from client?
+	dsi->config.hs_clk_max = client->hs_rate;
+	dsi->config.lp_clk_min = 7000000; // TODO: get from client?
+	dsi->config.lp_clk_max = client->lp_rate;
+
 	dsi->ulps_auto_idle = !!(client->mode_flags & MIPI_DSI_MODE_ULPS_IDLE);
-	dsi_set_ulps_auto(dsi, true);
 
 	dsi_bus_unlock(dsi);
 	return 0;
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
index 31502857f013..05ac2e1cd77e 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
@@ -176,7 +176,6 @@  static const struct of_device_id omapdss_of_match[] __initconst = {
 static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = {
 	{ .compatible = "composite-video-connector" },
 	{ .compatible = "hdmi-connector" },
-	{ .compatible = "panel-dsi-cm" },
 	{ .compatible = "svideo-connector" },
 	{ .compatible = "ti,opa362" },
 	{ .compatible = "ti,tpd12s015" },
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h
index 21601af29ee4..bfb402a88475 100644
--- a/drivers/gpu/drm/omapdrm/dss/omapdss.h
+++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h
@@ -122,11 +122,6 @@  enum omap_dss_dsi_mode {
 	OMAP_DSS_DSI_VIDEO_MODE,
 };
 
-enum omap_display_caps {
-	OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE	= 1 << 0,
-	OMAP_DSS_DISPLAY_CAP_TEAR_ELIM		= 1 << 1,
-};
-
 enum omap_dss_display_state {
 	OMAP_DSS_DISPLAY_DISABLED = 0,
 	OMAP_DSS_DISPLAY_ACTIVE,
@@ -288,14 +283,7 @@  struct omapdss_hdmi_ops {
 
 struct omapdss_dsi_ops {
 	int (*update)(struct omap_dss_device *dssdev);
-
-	/* legacy API used by omapdss panels */
-	int (*set_config)(struct omap_dss_device *dssdev,
-			const struct omap_dss_dsi_config *cfg);
-
-	int (*enable_video_output)(struct omap_dss_device *dssdev, int channel);
-	void (*disable_video_output)(struct omap_dss_device *dssdev,
-			int channel);
+	bool (*is_video_mode)(struct omap_dss_device *dssdev);
 };
 
 struct omap_dss_device_ops {
@@ -374,13 +362,10 @@  struct omap_dss_device {
 
 	const char *name;
 
-	const struct omap_dss_driver *driver;
 	const struct omap_dss_device_ops *ops;
 	unsigned long ops_flags;
 	u32 bus_flags;
 
-	enum omap_display_caps caps;
-
 	enum omap_dss_display_state state;
 
 	/* OMAP DSS output specific fields */
@@ -395,11 +380,6 @@  struct omap_dss_device {
 	unsigned int of_ports;
 };
 
-struct omap_dss_driver {
-	int (*update)(struct omap_dss_device *dssdev,
-			       u16 x, u16 y, u16 w, u16 h);
-};
-
 struct dss_device *omapdss_get_dss(void);
 void omapdss_set_dss(struct dss_device *dss);
 static inline bool omapdss_is_initialized(void)
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index a8d0543d1296..80ed1b15ba49 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -495,8 +495,7 @@  static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
 	 * valid DISPC mode. DSI will calculate and configure the
 	 * proper DISPC mode later.
 	 */
-	if (omap_crtc->pipe->output->next == NULL ||
-	    omap_crtc->pipe->output->next->type != OMAP_DISPLAY_TYPE_DSI) {
+	if (omap_crtc->pipe->output->type != OMAP_DISPLAY_TYPE_DSI) {
 		r = priv->dispc_ops->mgr_check_timings(priv->dispc,
 						       omap_crtc->channel,
 						       &vm);
@@ -548,17 +547,17 @@  static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
 static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	struct omap_dss_device *display = omap_crtc->pipe->output->next;
+	struct omap_dss_device *dssdev = omap_crtc->pipe->output;
 
-	if (!display)
+	if (dssdev->type != OMAP_DISPLAY_TYPE_DSI ||
+	    !dssdev->ops->dsi.is_video_mode)
 		return false;
 
-	if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
-		DBG("detected manually updated display!");
-		return true;
-	}
+	if (dssdev->ops->dsi.is_video_mode(dssdev))
+		return false;
 
-	return false;
+	DBG("detected manually updated display!");
+	return true;
 }
 
 static int omap_crtc_atomic_check(struct drm_crtc *crtc,