MLK-19252-2 drm/bridge: adv7511: realize mode_fixup for lanes fixup
authorFancy Fang <chen.fang@nxp.com>
Wed, 15 Aug 2018 02:45:27 +0000 (10:45 +0800)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
In the current implementation, the data lanes fixup is done in
the Bridge's mode_set() function which is too late to give the
upper layer Bridge a chance to check this change to be supported
or not and a chance to refuse this commit if it does not support
the requested data lanes number.

Signed-off-by: Fancy Fang <chen.fang@nxp.com>
(cherry picked from commit c97f9febd7e42d7865921e2bb56648ebb13c0761)
(cherry picked from commit 36f25495a5c30e66e033cfd3d46d4693f50fc8f7)
(cherry picked from commit de7e9c83c7503255c512b5c78165ba7924c7269e)

drivers/gpu/drm/bridge/adv7511/adv7511.h
drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
drivers/gpu/drm/bridge/adv7511/adv7533.c

index c2433b0..4340f06 100644 (file)
@@ -404,6 +404,8 @@ static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
 #ifdef CONFIG_DRM_I2C_ADV7533
 void adv7533_dsi_power_on(struct adv7511 *adv);
 void adv7533_dsi_power_off(struct adv7511 *adv);
+void adv7533_mode_set(struct adv7511 *adv, struct drm_display_mode *mode);
+bool adv7533_mode_fixup(struct adv7511 *adv, struct drm_display_mode *mode);
 int adv7533_patch_registers(struct adv7511 *adv);
 int adv7533_patch_cec_registers(struct adv7511 *adv);
 int adv7533_attach_dsi(struct adv7511 *adv);
@@ -423,6 +425,12 @@ static inline void adv7533_mode_set(struct adv7511 *adv,
 {
 }
 
+static inline bool adv7533_mode_fixup(struct adv7511 *adv,
+                                     struct drm_display_mode *mode)
+{
+       return true;
+}
+
 static inline int adv7533_patch_registers(struct adv7511 *adv)
 {
        return -ENODEV;
index 9b72622..433e525 100644 (file)
@@ -862,6 +862,18 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,
        adv7511_mode_set(adv, mode, adj_mode);
 }
 
+static bool adv7511_bridge_mode_fixup(struct drm_bridge *bridge,
+                                     const struct drm_display_mode *mode,
+                                     struct drm_display_mode *adjusted_mode)
+{
+       struct adv7511 *adv = bridge_to_adv7511(bridge);
+
+       if (adv->type == ADV7533 || adv->type == ADV7535)
+               return adv7533_mode_fixup(adv, adjusted_mode);
+
+       return true;
+}
+
 static int adv7511_bridge_attach(struct drm_bridge *bridge)
 {
        struct adv7511 *adv = bridge_to_adv7511(bridge);
@@ -903,6 +915,7 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = {
        .enable = adv7511_bridge_enable,
        .disable = adv7511_bridge_disable,
        .mode_set = adv7511_bridge_mode_set,
+       .mode_fixup = adv7511_bridge_mode_fixup,
        .attach = adv7511_bridge_attach,
 };
 
index 610113f..ea6a04e 100644 (file)
@@ -138,6 +138,38 @@ void adv7533_dsi_power_off(struct adv7511 *adv)
        regmap_write(adv->regmap_cec, 0x27, 0x0b);
 }
 
+void adv7533_mode_set(struct adv7511 *adv, struct drm_display_mode *mode)
+{
+}
+
+bool adv7533_mode_fixup(struct adv7511 *adv,
+                       struct drm_display_mode *mode)
+{
+       struct mipi_dsi_device *dsi = adv->dsi;
+       int lanes, ret;
+
+       if (adv->num_dsi_lanes != 4)
+               return true;
+
+       if (mode->clock > 80000)
+               lanes = 4;
+       else
+               lanes = 3;
+
+       if (lanes != dsi->lanes) {
+               mipi_dsi_detach(dsi);
+               swap(dsi->lanes, lanes);
+               ret = mipi_dsi_attach(dsi);
+               if (ret) {
+                       dev_err(&dsi->dev, "failed to change host lanes\n");
+                       swap(dsi->lanes, lanes);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 int adv7533_patch_registers(struct adv7511 *adv)
 {
        return regmap_register_patch(adv->regmap,