rk3036/3128 hdmi:
authorZheng Yang <zhengyang@rock-chips.com>
Mon, 17 Nov 2014 06:30:09 +0000 (14:30 +0800)
committerZheng Yang <zhengyang@rock-chips.com>
Mon, 17 Nov 2014 06:30:09 +0000 (14:30 +0800)
Take following sequence to avoid picture flash when swiching resolution:
1. Send AV_MUTE GCP packet.
2. Power off hdmi phy.
3. Sleep 2 second to wait TV process no TMDS signal.
4. Configure video and audio registers.
5. Power on HDMI phy.
6. Send CLEAR_MUTE GCP packet.

drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi.c
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk3036/rk3036_hdmi_hw.h
drivers/video/rockchip/hdmi/rk_hdmi_task.c

index f6d1888637e3e3c698094601be6989e88e7b11b6..8c48563e0dae334d555184e07f58293315b38333 100755 (executable)
@@ -513,6 +513,8 @@ static void rk3036_hdmi_shutdown(struct platform_device *pdev)
                if (hdmi_drv->irq)
                        disable_irq(hdmi_drv->irq);
                mutex_unlock(&hdmi_drv->enable_mutex);
+               if (hdmi_drv->hotplug == HDMI_HPD_ACTIVED)
+                       rk3036_hdmi_control_output(hdmi_drv, 0);
        }
        hdmi_dbg(hdmi_drv->dev, "rk3036 hdmi shut down.\n");
 }
index b3419b930148859368a52853bdde62cc4c9dbd61..7c7b2770468bd1a4142025657f3754548c8ad4ea 100755 (executable)
@@ -51,9 +51,16 @@ static void rk3036_hdmi_av_mute(struct hdmi *hdmi_drv, bool enable)
        struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv,
                                                       struct rk_hdmi_device,
                                                       driver);
-
-       hdmi_writel(hdmi_dev, AV_MUTE,
-                   v_AUDIO_MUTE(enable) | v_VIDEO_MUTE(enable));
+       if (enable) {
+               hdmi_msk_reg(hdmi_dev, AV_MUTE,
+                            m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
+                            v_AVMUTE_CLEAR(0) | v_AVMUTE_ENABLE(1));
+       } else {
+               hdmi_msk_reg(hdmi_dev, AV_MUTE,
+                            m_AVMUTE_CLEAR | m_AVMUTE_ENABLE,
+                            v_AVMUTE_CLEAR(1) | v_AVMUTE_ENABLE(0));
+       }
+       hdmi_writel(hdmi_dev, PACKET_SEND_AUTO, m_PACKET_GCP_EN);
 }
 
 static void rk3036_hdmi_sys_power(struct hdmi *hdmi_drv, bool enable)
@@ -100,14 +107,12 @@ static void rk3036_hdmi_set_pwr_mode(struct hdmi *hdmi_drv, int mode)
                hdmi_writel(hdmi_dev, PHY_CHG_PWR, 0x0f);
                hdmi_writel(hdmi_dev, 0xce, 0x00);
                hdmi_writel(hdmi_dev, 0xce, 0x01);
-               rk3036_hdmi_av_mute(hdmi_drv, 1);
                rk3036_hdmi_sys_power(hdmi_drv, true);
                break;
        case LOWER_PWR:
                hdmi_dbg(hdmi_drv->dev,
                         "%s change pwr_mode LOWER_PWR pwr_mode = %d, mode = %d\n",
                         __func__, hdmi_drv->pwr_mode, mode);
-               rk3036_hdmi_av_mute(hdmi_drv, 0);
                rk3036_hdmi_sys_power(hdmi_drv, false);
                hdmi_writel(hdmi_dev, PHY_DRIVER, 0x00);
                hdmi_writel(hdmi_dev, PHY_PRE_EMPHASIS, 0x00);
@@ -526,11 +531,13 @@ static int rk3036_hdmi_config_video(struct hdmi *hdmi_drv,
                        vpara->output_color = VIDEO_OUTPUT_RGB444;*/
        }
 
-       if (hdmi_drv->pwr_mode == LOWER_PWR)
+/*     if (hdmi_drv->pwr_mode == LOWER_PWR)
                rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-
+*/
        /* Disable video and audio output */
-       hdmi_writel(hdmi_dev, AV_MUTE, v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+       hdmi_msk_reg(hdmi_dev, AV_MUTE,
+                    m_AUDIO_MUTE | m_VIDEO_BLACK,
+                    v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
 
        /* Input video mode is SDR RGB24bit, Data enable signal from external */
        hdmi_writel(hdmi_dev, VIDEO_CONTRL1,
@@ -601,7 +608,6 @@ static int rk3036_hdmi_config_video(struct hdmi *hdmi_drv,
        value = mode->vsync_len;
        hdmi_writel(hdmi_dev, VIDEO_EXT_VDURATION, value & 0xFF);
 #endif
-
        if (vpara->output_mode == OUTPUT_HDMI) {
                rk3036_hdmi_config_avi(hdmi_drv, vpara->vic,
                                        vpara->output_color);
@@ -740,11 +746,7 @@ void rk3036_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
        if (enable) {
                if (hdmi_drv->pwr_mode == LOWER_PWR)
                        rk3036_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
-               hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
-               if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
-                       hdmi_writel(hdmi_dev, AV_MUTE,
-                                   v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
-               }
+
                rk3036_hdmi_sys_power(hdmi_drv, true);
                rk3036_hdmi_sys_power(hdmi_drv, false);
                delay100us();
@@ -752,9 +754,21 @@ void rk3036_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
                hdmi_writel(hdmi_dev, 0xce, 0x00);
                delay100us();
                hdmi_writel(hdmi_dev, 0xce, 0x01);
+
+               hdmi_readl(hdmi_dev, AV_MUTE, &mutestatus);
+               if (mutestatus && (m_AUDIO_MUTE | m_VIDEO_BLACK)) {
+                       hdmi_msk_reg(hdmi_dev, AV_MUTE,
+                                    m_AUDIO_MUTE | m_VIDEO_BLACK,
+                                    v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
+               }
+               rk3036_hdmi_av_mute(hdmi_drv, 0);
        } else {
-               hdmi_writel(hdmi_dev, AV_MUTE,
-                           v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+               hdmi_msk_reg(hdmi_dev, AV_MUTE,
+                            m_AUDIO_MUTE | m_VIDEO_BLACK,
+                            v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
+               rk3036_hdmi_av_mute(hdmi_drv, 1);
+               msleep(100);
+               rk3036_hdmi_set_pwr_mode(hdmi_drv, LOWER_PWR);
        }
 }
 
index 7f70adbb11044c9d57a7d31da8be1cbb887e4c9c..20b326653e6c44589209d0ff92d26275a72137fe 100755 (executable)
@@ -124,6 +124,8 @@ enum {
 #define m_AVMUTE_ENABLE                (1 << 6)
 #define m_AUDIO_MUTE           (1 << 1)
 #define m_VIDEO_BLACK          (1 << 0)
+#define v_AVMUTE_CLEAR(n)      (n << 7)
+#define v_AVMUTE_ENABLE(n)     (n << 6)
 #define v_AUDIO_MUTE(n)                (n << 1)
 #define v_VIDEO_MUTE(n)                (n << 0)
 
@@ -230,6 +232,10 @@ enum {
 #define EDID_FIFO_OFFSET               0x4f
 #define EDID_FIFO_ADDR                 0x50
 
+
+#define PACKET_SEND_MANUAL             0x9c
+#define PACKET_SEND_AUTO               0x9d
+       #define m_PACKET_GCP_EN         (1 << 7)
 /* CONTROL_PACKET_BUF_INDEX */
 #define CONTROL_PACKET_BUF_INDEX       0x9f
 enum {
index eb3c7db97adfaa8b5beab92534570653b7f35785..1f68cc909bb85ab242a926ba49660b602beb119a 100755 (executable)
@@ -130,6 +130,7 @@ static int hdmi_process_command(struct hdmi *hdmi)
                        if (!hdmi->enable || hdmi->suspend) {
                                if (hdmi->hotplug != HDMI_HPD_REMOVED) {
                                        hdmi->hotplug = HDMI_HPD_REMOVED;
+                                       hdmi->control_output(hdmi, HDMI_DISABLE);
                                        hdmi_sys_remove(hdmi);
                                }
                                hdmi->state = HDMI_SLEEP;
@@ -158,6 +159,8 @@ static int hdmi_process_command(struct hdmi *hdmi)
                default:
                        if (state > SYSTEM_CONFIG) {
                                state = SYSTEM_CONFIG;
+                               hdmi->control_output(hdmi, HDMI_DISABLE);
+                               msleep(2000);
                        } else {
                                if (hdmi->wait == 1) {
                                        complete(&hdmi->complete);
@@ -222,7 +225,7 @@ void hdmi_work(struct work_struct *work)
                hdmi->hotplug = hotplug;
        } else if (hotplug == HDMI_HPD_REMOVED) {
                hdmi_sys_sleep(hdmi);
-       }else if (hotplug == HDMI_HPD_ACTIVED) {
+       } else if (hotplug == HDMI_HPD_ACTIVED) {
                if (hdmi->uboot_logo) {
                        if (hdmi->insert)
                                hdmi->insert(hdmi);