path: root/drivers/gpu/drm/msm/dsi
diff options
authorArchit Taneja <>2016-12-05 15:24:53 +0530
committerRob Clark <>2017-02-06 11:28:43 -0500
commit9c9f6f8d472cc9e11f2c0b370685ce78ab7eb2fa (patch)
tree75818433a58d6597e4210bfb48ab539970867191 /drivers/gpu/drm/msm/dsi
parent97e00119534bf3c9f47c4eae0b7dd982ef2de92b (diff)
drm/msm: Set encoder's mode of operation using a kms func
The mdp5 kms driver currently sets up multiple encoders per interface (INTF), one for each kind of mode of operation it supports. We create 2 drm_encoders for DSI, one for Video Mode and the other for Command Mode operation. The reason behind this approach could have been that we aren't aware of the DSI device's mode of operation when we create the encoders. This makes things a bit complicated, since these encoders have to be further attached to the same DSI bridge. The easier way out is to create a single encoder, and make the DSI driver set its mode of operation when we know what the DSI device's mode flags are. Start with providing a way to set the mdp5_intf_mode using a kms func that sets the encoder's mode of operation. When constructing a DSI encoder, we set the mode of operation to Video Mode as default. When the DSI device is attached to the host, we probe the DSI mode flags and set the corresponding mode of operation. Signed-off-by: Archit Taneja <> Signed-off-by: Rob Clark <>
Diffstat (limited to 'drivers/gpu/drm/msm/dsi')
3 files changed, 40 insertions, 0 deletions
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index ddcda8cec9a7..81971b3caf3b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -90,6 +90,7 @@ int msm_dsi_manager_phy_enable(int id,
void msm_dsi_manager_phy_disable(int id);
int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
+void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 3819fdefcae2..eb0903d37e5c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1482,6 +1482,8 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
msm_host->format = dsi->format;
msm_host->mode_flags = dsi->mode_flags;
+ msm_dsi_manager_attach_dsi_device(msm_host->id, dsi->mode_flags);
/* Some gpios defined in panel DT need to be controlled by host */
ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev);
if (ret)
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 19da23d8a0b1..bd4ba00d2524 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -168,6 +168,16 @@ static enum drm_connector_status dsi_mgr_connector_detect(
msm_dsi->panel = msm_dsi_host_get_panel(
other_dsi->host, NULL);
+ if (msm_dsi->panel && kms->funcs->set_encoder_mode) {
+ bool cmd_mode = !(msm_dsi->device_flags &
+ struct drm_encoder *encoder =
+ msm_dsi_get_encoder(msm_dsi);
+ kms->funcs->set_encoder_mode(kms, encoder, cmd_mode);
+ }
if (msm_dsi->panel && IS_DUAL_DSI())
connector->dev->mode_config.tile_property, 0);
@@ -773,6 +783,33 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
return true;
+void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags)
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+ struct drm_device *dev = msm_dsi->dev;
+ struct msm_drm_private *priv;
+ struct msm_kms *kms;
+ struct drm_encoder *encoder;
+ /*
+ * drm_device pointer is assigned to msm_dsi only in the modeset_init
+ * path. If mipi_dsi_attach() happens in DSI driver's probe path
+ * (generally the case when we're connected to a drm_panel of the type
+ * mipi_dsi_device), this would be NULL. In such cases, try to set the
+ * encoder mode in the DSI connector's detect() op.
+ */
+ if (!dev)
+ return;
+ priv = dev->dev_private;
+ kms = priv->kms;
+ encoder = msm_dsi_get_encoder(msm_dsi);
+ if (encoder && kms->funcs->set_encoder_mode)
+ if (!(device_flags & MIPI_DSI_MODE_VIDEO))
+ kms->funcs->set_encoder_mode(kms, encoder, true);
int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;