MLK-17795: drm: imx: hdp: Fix 10-bit to 8-bit color depth switch on iMX8MQ
authorLaurentiu Palcu <laurentiu.palcu@nxp.com>
Fri, 24 Aug 2018 08:17:19 +0000 (11:17 +0300)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
When switching from a 10-bit to an 8-bit color depth, the PHY pixel engine
simply stops functioning correctly 90% of the time. This results in the
HDMI sink not detecting any signal.

This patch will reset the PHY pixel engine after the pipe clocks are ON,
in the bridge enable callback. This will make the pixel engine work
correctly when BPC changes. Resetting the pixel engine before all the pipe
clocks are on, produces no results.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
(cherry picked from commit 72246ac9ccfa2074f4f575292af10d19a58c95c4)

drivers/gpu/drm/imx/hdp/imx-hdmi.c
drivers/gpu/drm/imx/hdp/imx-hdmi.h
drivers/gpu/drm/imx/hdp/imx-hdp.c
drivers/gpu/drm/imx/hdp/imx-hdp.h

index 39a575a..8089c5c 100644 (file)
@@ -279,6 +279,21 @@ int hdmi_phy_init_t28hpc(state_struct *state, struct drm_display_mode *mode, int
        return true;
 }
 
+void hdmi_phy_pix_engine_reset_t28hpc(state_struct *state)
+{
+       GENERAL_Read_Register_response regresp;
+
+       CDN_API_General_Read_Register_blocking(state, ADDR_SOURCE_CAR +
+                                              (SOURCE_HDTX_CAR << 2),
+                                              &regresp);
+       CDN_API_General_Write_Register_blocking(state, ADDR_SOURCE_CAR +
+                                               (SOURCE_HDTX_CAR << 2),
+                                               regresp.val & 0xFD);
+       CDN_API_General_Write_Register_blocking(state, ADDR_SOURCE_CAR +
+                                               (SOURCE_HDTX_CAR << 2),
+                                               regresp.val);
+}
+
 void hdmi_mode_set_vswing(state_struct *state)
 {
        GENERAL_Read_Register_response regresp[12];
index 3d53117..09d9502 100644 (file)
@@ -29,5 +29,6 @@ int hdmi_get_hpd_state(state_struct *state, u8 *hpd);
 int hdmi_write_hdr_metadata(state_struct *state,
                            union hdmi_infoframe *hdr_infoframe);
 int pixel_clock_range_t28hpc(struct drm_display_mode *mode);
+void hdmi_phy_pix_engine_reset_t28hpc(state_struct *state);
 
 #endif
index e0a2100..cf3da65 100644 (file)
@@ -597,6 +597,19 @@ static void imx_hdp_bridge_disable(struct drm_bridge *bridge)
 
 static void imx_hdp_bridge_enable(struct drm_bridge *bridge)
 {
+       struct imx_hdp *hdp = bridge->driver_private;
+
+       /*
+        * When switching from 10-bit to 8-bit color depths, iMX8MQ needs the
+        * PHY pixel engine to be reset after all clocks are ON, not before.
+        * So, we do it in the enable callback.
+        *
+        * Since the reset does not do any harm when switching from a 8-bit mode
+        * to another 8-bit mode, or from 8-bit to 10-bit, we can safely do it
+        * all the time.
+        */
+       if (cpu_is_imx8mq())
+               imx_hdp_call(hdp, pixel_engine_reset, &hdp->state);
 }
 
 static enum drm_connector_status
@@ -1010,6 +1023,7 @@ static struct hdp_ops imx8mq_ops = {
        .get_hpd_state = hdmi_get_hpd_state,
        .write_hdr_metadata = hdmi_write_hdr_metadata,
        .pixel_clock_range = pixel_clock_range_t28hpc,
+       .pixel_engine_reset = hdmi_phy_pix_engine_reset_t28hpc,
 };
 
 static struct hdp_devtype imx8mq_hdmi_devtype = {
index 17e7f49..5cfdec4 100644 (file)
@@ -99,6 +99,7 @@ struct hdp_ops {
        int (*pixel_link_init)(state_struct *state);
        void (*pixel_link_deinit)(state_struct *state);
        void (*pixel_link_mux)(state_struct *state, struct drm_display_mode *mode);
+       void (*pixel_engine_reset)(state_struct *state);
 
        int (*clock_init)(struct hdp_clks *clks);
        int (*ipg_clock_enable)(struct hdp_clks *clks);