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 ddcda8cec9a7e98011d1a7fb52b2c9373bebac3f..81971b3caf3b61721e6ab1ca9b7f1d99a35e48c6 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 3819fdefcae2192206097cd41aaf99bbf40b6e85..eb0903d37e5c535c9c5c62b88e5a978ae5aa6a84 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 19da23d8a0b117068e4b0c57ad820d6fb18bb427..bd4ba00d2524975ec015bcdfeb86eafce2e01b4b 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 fe0c22230883281f260db69a58d3637071979364..1e7c99125fdd539e3d2196797f426b9b1df900c2 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 5bad72c9e253e7c4710e273bdf466c81b9bbf1fa..f73d467569121ae9e44c840fffb0da54d9c30593 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 cdfc63d90c7b4bf4b7f1f116b410c347560663ef..3e0baed0a8a77f87e0c377611a6949077813ede2 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 e470f4cf8f765d8ca3e7fae4292e9b00950912f2..117635d2b8c54bedd883db4bafdbf362433ecc7a 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