drm/msm: Set encoder's mode of operation using a kms func
authorArchit Taneja <architt@codeaurora.org>
Mon, 5 Dec 2016 09:54:53 +0000 (15:24 +0530)
committerRob Clark <robdclark@gmail.com>
Mon, 6 Feb 2017 16:28:43 +0000 (11:28 -0500)
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 <architt@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/dsi/dsi.h
drivers/gpu/drm/msm/dsi/dsi_host.c
drivers/gpu/drm/msm/dsi/dsi_manager.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
drivers/gpu/drm/msm/msm_kms.h

index ddcda8c..81971b3 100644 (file)
@@ -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);
 
index 3819fde..eb0903d 100644 (file)
@@ -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)
index 19da23d..bd4ba00 100644 (file)
@@ -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 &
+                                         MIPI_DSI_MODE_VIDEO);
+                       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())
                        drm_object_attach_property(&connector->base,
                                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;
index fe0c222..1e7c991 100644 (file)
@@ -342,6 +342,23 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
        return 0;
 }
 
+void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode)
+{
+       struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
+       struct mdp5_interface *intf = &mdp5_encoder->intf;
+
+       /* TODO: Expand this to set writeback modes too */
+       if (cmd_mode) {
+               WARN_ON(intf->type != INTF_DSI);
+               intf->mode = MDP5_INTF_DSI_MODE_COMMAND;
+       } else {
+               if (intf->type == INTF_DSI)
+                       intf->mode = MDP5_INTF_DSI_MODE_VIDEO;
+               else
+                       intf->mode = MDP5_INTF_MODE_NONE;
+       }
+}
+
 /* initialize encoder */
 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
                        struct mdp5_interface *intf, struct mdp5_ctl *ctl)
index 5bad72c..f73d467 100644 (file)
@@ -151,6 +151,13 @@ static int mdp5_set_split_display(struct msm_kms *kms,
                return mdp5_encoder_set_split_display(encoder, slave_encoder);
 }
 
+static void mdp5_set_encoder_mode(struct msm_kms *kms,
+                                 struct drm_encoder *encoder,
+                                 bool cmd_mode)
+{
+       mdp5_encoder_set_intf_mode(encoder, cmd_mode);
+}
+
 static void mdp5_kms_destroy(struct msm_kms *kms)
 {
        struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
@@ -230,6 +237,7 @@ static const struct mdp_kms_funcs kms_funcs = {
                .get_format      = mdp_get_format,
                .round_pixclk    = mdp5_round_pixclk,
                .set_split_display = mdp5_set_split_display,
+               .set_encoder_mode = mdp5_set_encoder_mode,
                .destroy         = mdp5_kms_destroy,
 #ifdef CONFIG_DEBUG_FS
                .debugfs_init    = mdp5_kms_debugfs_init,
index cdfc63d..3e0baed 100644 (file)
@@ -246,6 +246,7 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
                struct mdp5_interface *intf, struct mdp5_ctl *ctl);
 int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
                                        struct drm_encoder *slave_encoder);
+void mdp5_encoder_set_intf_mode(struct drm_encoder *encoder, bool cmd_mode);
 int mdp5_encoder_get_linecount(struct drm_encoder *encoder);
 u32 mdp5_encoder_get_framecount(struct drm_encoder *encoder);
 
index e470f4c..117635d 100644 (file)
@@ -56,6 +56,9 @@ struct msm_kms_funcs {
                        struct drm_encoder *encoder,
                        struct drm_encoder *slave_encoder,
                        bool is_cmd_mode);
+       void (*set_encoder_mode)(struct msm_kms *kms,
+                                struct drm_encoder *encoder,
+                                bool cmd_mode);
        /* cleanup: */
        void (*destroy)(struct msm_kms *kms);
 #ifdef CONFIG_DEBUG_FS