HDMI: modify rk3288 hdmi phy config and add 4kx2k timing
authorzwl <zwl@rock-chips.com>
Mon, 17 Mar 2014 13:17:00 +0000 (21:17 +0800)
committerzwl <zwl@rock-chips.com>
Mon, 17 Mar 2014 13:17:00 +0000 (21:17 +0800)
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi.c
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.c
drivers/video/rockchip/hdmi/chips/rk3288/rk3288_hdmi_hw.h
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c

index 9c1e64a9f25b8cd3339975256a398fbc03a982c5..fef837d6546b04baabbfb9cb95dfb3e43c6a0b3d 100644 (file)
@@ -144,8 +144,11 @@ struct hdmi* rk3288_hdmi_register_hdcp_callbacks(
 static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv)
 {
        int ret = 0;
+       struct rk_screen screen;
        //struct rk_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk_hdmi_device, driver);
 
+       rk_fb_get_prmry_screen(&screen);
+       hdmi_dev->lcdc_id = (screen.lcdc_id == 1) ? 0 : 1;      //hdmi is extend as default,TODO modify if hdmi is primary
         grf_writel(HDMI_SEL_LCDC(hdmi_dev->lcdc_id), RK3288_GRF_SOC_CON6);     //lcdc source select
        if(hdmi_dev->lcdc_id == 0)
                hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
@@ -177,8 +180,8 @@ static int rk3288_hdmi_parse_dt(struct rk3288_hdmi_device *hdmi_dev)
        int val = 0;
        struct device_node *np = hdmi_dev->dev->of_node;
 
-       if(!of_property_read_u32(np, "rockchips,hdmi_lcdc_source", &val))
-               hdmi_dev->lcdc_id = val;
+       //if(!of_property_read_u32(np, "rockchips,hdmi_lcdc_source", &val))
+       //      hdmi_dev->lcdc_id = val;
 
        if(!of_property_read_u32(np, "rockchips,hdmi_audio_source", &val))
                hdmi_dev->driver.audio.type = val;
index 4850df939c00030dac32a9a88e6d80f8f9d164b7..e6bcb01e4e6fe05cb0a2f908181cb2e24b8d0271 100644 (file)
@@ -360,6 +360,44 @@ int rk3288_hdmi_video_sampler(struct hdmi *hdmi_drv, struct hdmi_video_para *vpa
        return 0;
 }
 
+static int rk3288_hdmi_read_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_addr, int *val)
+{
+       int trytime = 2, i = 0, op_status = 0;
+
+       mutex_lock(&hdmi_dev->int_mutex);
+       hdmi_dev->phy_i2cm_int = 0;
+       mutex_unlock(&hdmi_dev->int_mutex);
+
+       while(trytime--) {
+               hdmi_writel(hdmi_dev, PHY_I2CM_ADDRESS, reg_addr);
+               hdmi_writel(hdmi_dev, PHY_I2CM_OPERATION, m_PHY_I2CM_READ);
+
+               i = 100;
+               while(i--) {
+                       mutex_lock(&hdmi_dev->int_mutex);
+                       //op_status = hdmi_readl(hdmi_dev, PHY_I2CM_INT);
+                       op_status = hdmi_dev->phy_i2cm_int;
+                       hdmi_dev->phy_i2cm_int = 0;
+                       mutex_unlock(&hdmi_dev->int_mutex);
+                       if(op_status & (m_I2CMPHY_DONE | m_I2CMPHY_ERR)) {
+                               break;
+                       }
+                       msleep(10);
+               }
+
+               if(op_status & m_I2CMPHY_DONE) {
+                       *val = (hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_1) >> 8) & 0xff;
+                       *val += (hdmi_readl(hdmi_dev, PHY_I2CM_DATAI_0) & 0xff);
+                       return 0;
+               }
+               else {
+                       hdmi_err(hdmi_dev->dev, "[%s] operation error,trytime=%d\n", __FUNCTION__,trytime);
+               }
+               msleep(100);
+       }
+
+       return -1;
+}
 
 static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_addr, int val)
 {
@@ -400,38 +438,70 @@ static int rk3288_hdmi_write_phy(struct rk3288_hdmi_device *hdmi_dev, int reg_ad
        return -1;
 }
 
-static void rk3288_hdmi_config_phy(struct hdmi *hdmi_drv)
+static int rk3288_hdmi_config_phy(struct hdmi *hdmi_drv)
 {
-       int stat = 0;
-       char color_depth = COLOR_DEPTH_24BIT_DEFAULT;
+       int stat = 0, i = 0;
+       //char color_depth = COLOR_DEPTH_24BIT;//COLOR_DEPTH_24BIT_DEFAULT;
        char pix_repet = NO_PIXEL_REPET;
        const struct phy_mpll_config_tab *phy_mpll = NULL;
        struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
 
-       hdmi_writel(hdmi_dev, PHY_CONF0, 0x32);
+       //get phy_type,if PHY_GEN2==1 config phy register
+       //phy_type = hdmi_readl(hdmi_dev, CONFIG2_ID);
+       //if(phy_type != HDMI_3D_TX_WITH_HEAC_PHY && phy_type != HDMI_3D_TX_PHY) {
+       //      printk("%s: PHY_GEN2 = 0,No need to config phy", __FUNCTION__);
+       //      return;
+       //}
+
+       //hdmi_writel(hdmi_dev, PHY_CONF0, 0x32);
+       hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG, v_PDDQ_SIG(1) | v_TXPWRON_SIG(0));
        hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(1));
        //the resolution that we used is no pixel repet,refer to the CEA-861 specification.
-       hdmi_writel(hdmi_dev, VP_PR_CD, v_COLOR_DEPTH(color_depth) | v_DESIRED_PR_FACTOR(pix_repet));
-       msleep(5);
+       //hdmi_writel(hdmi_dev, VP_PR_CD, v_COLOR_DEPTH(color_depth) | v_DESIRED_PR_FACTOR(pix_repet));
+       //msleep(5);
        hdmi_writel(hdmi_dev, MC_PHYRSTZ, v_PHY_RSTZ(0));
 
        //Set slave address as PHY GEN2 address
-       hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_GEN2_ADDR);
+       hdmi_writel(hdmi_dev, PHY_I2CM_SLAVE, PHY_I2C_SLAVE_ADDR);
+
+       rk3288_hdmi_write_phy(hdmi_dev, 0x13, 0x0000); /* PLLPHBYCTRL */
+       rk3288_hdmi_write_phy(hdmi_dev, 0x17, 0x0006);
+       /* RESISTANCE TERM 133Ohm Cfg  */
+       rk3288_hdmi_write_phy(hdmi_dev, 0x19, 0x0005); /* TXTERM */     //TODO Daisen wait to modify
+       /* REMOVE CLK TERM */
+       rk3288_hdmi_write_phy(hdmi_dev, 0x05, 0x8000); /* CKCALCTRL */
 
        //config the required PHY I2C register
-       phy_mpll = get_phy_mpll_tab(hdmi_drv->tmdsclk, pix_repet, color_depth);
-       rk3288_hdmi_write_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG, v_PREP_DIV(phy_mpll->prep_div) | v_TMDS_CNTRL(phy_mpll->tmdsmhl_cntrl) | v_OPMODE(phy_mpll->opmode) |
-               v_FBDIV2_CNTRL(phy_mpll->fbdiv2_cntrl) | v_FBDIV1_CNTRL(phy_mpll->fbdiv1_cntrl) | v_REF_CNTRL(phy_mpll->ref_cntrl) | v_MPLL_N_CNTRL(phy_mpll->n_cntrl));
-       rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLCURRCTRL, v_MPLL_PROP_CNTRL(phy_mpll->prop_cntrl) | v_MPLL_INT_CNTRL(phy_mpll->int_cntrl));
-       rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLGMPCTRL, v_MPLL_GMP_CNTRL(phy_mpll->gmp_cntrl));
+       phy_mpll = get_phy_mpll_tab(hdmi_drv->tmdsclk, pix_repet, 8);
+       if(phy_mpll) {
+               rk3288_hdmi_write_phy(hdmi_dev, PHYTX_OPMODE_PLLCFG, v_PREP_DIV(phy_mpll->prep_div) | v_TMDS_CNTRL(phy_mpll->tmdsmhl_cntrl) | v_OPMODE(phy_mpll->opmode) |
+                       v_FBDIV2_CNTRL(phy_mpll->fbdiv2_cntrl) | v_FBDIV1_CNTRL(phy_mpll->fbdiv1_cntrl) | v_REF_CNTRL(phy_mpll->ref_cntrl) | v_MPLL_N_CNTRL(phy_mpll->n_cntrl));
+               rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLCURRCTRL, v_MPLL_PROP_CNTRL(phy_mpll->prop_cntrl) | v_MPLL_INT_CNTRL(phy_mpll->int_cntrl));
+               rk3288_hdmi_write_phy(hdmi_dev, PHYTX_PLLGMPCTRL, v_MPLL_GMP_CNTRL(phy_mpll->gmp_cntrl));
+       }
 
        //power on PHY
-       hdmi_writel(hdmi_dev, PHY_CONF0, 0x2a);
+       //hdmi_writel(hdmi_dev, PHY_CONF0, 0x2a);
+       hdmi_msk_reg(hdmi_dev, PHY_CONF0, m_PDDQ_SIG | m_TXPWRON_SIG | m_ENHPD_RXSENSE_SIG,
+               v_PDDQ_SIG(0) | v_TXPWRON_SIG(1) | v_ENHPD_RXSENSE_SIG(1));
 
        //check if the PHY PLL is locked
-       stat = hdmi_readl(hdmi_dev, PHY_STAT0);
-       if(stat & m_PHY_LOCK)
-               hdmi_writel(hdmi_dev, PHY_STAT0, v_PHY_LOCK(1));
+       #define PHY_TIMEOUT     10000
+       while(i++ < PHY_TIMEOUT) {
+               if ((i % 100) == 0) {
+                       stat = hdmi_readl(hdmi_dev, PHY_STAT0);
+                       if(stat & m_PHY_LOCK) {
+                               //hdmi_writel(hdmi_dev, PHY_STAT0, v_PHY_LOCK(1));
+                               break;
+                       }
+               }
+       }
+       if((stat & m_PHY_LOCK) == 0) {
+               hdmi_err(hdmi_dev->dev, "PHY PLL not locked\n");
+               return -1;
+       }
+
+       return 0;
 }
 
 static void rk3288_hdmi_config_avi(struct hdmi *hdmi_drv, unsigned char vic, unsigned char output_color)
@@ -638,7 +708,7 @@ static void rk3288_hdmi_config_aai(struct hdmi *hdmi_drv, struct hdmi_audio *aud
 
 int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio)
 {
-       int word_length = 0, channel = 0, N = 0, mclk_fs, value;
+       int word_length = 0, channel = 0, N = 0, mclk_fs;
        struct rk3288_hdmi_device *hdmi_dev = container_of(hdmi_drv, struct rk3288_hdmi_device, driver);
 
        if(audio->channel < 3)
@@ -736,8 +806,8 @@ int rk3288_hdmi_config_audio(struct hdmi *hdmi_drv, struct hdmi_audio *audio)
        }
 
        /* more than 2 channels => layout 1 else layout 0 */
-       value = (audio->channel > 2) ? 1 : 0;   //TODO Daisen wait to modify
-       hdmi_msk_reg(hdmi_dev, FC_AUDSCONF, m_AUD_PACK_LAYOUT, v_AUD_PACK_LAYOUT(1));
+       //value = (audio->channel > 2) ? 1 : 0; //TODO Daisen wait to modify
+       //hdmi_msk_reg(hdmi_dev, FC_AUDSCONF, m_AUD_PACK_LAYOUT, v_AUD_PACK_LAYOUT(value));
 
        if(hdmi_drv->audio.type == INPUT_SPDIF) {
                hdmi_msk_reg(hdmi_dev, AUD_CONF0, m_I2S_SEL, v_I2S_SEL(AUDIO_SPDIF_GPA));
@@ -778,6 +848,8 @@ void rk3288_hdmi_control_output(struct hdmi *hdmi_drv, int enable)
        else {
                if(hdmi_drv->pwr_mode == LOWER_PWR)
                        rk3288_hdmi_set_pwr_mode(hdmi_drv, NORMAL);
+               /* disable blue screen transmission after turning on all necessary blocks*/
+               rk3288_hdmi_video_forceOutput(hdmi_drv, 0);
                rk3288_hdmi_av_mute(hdmi_drv, 0);
        }
 }
index 70c0a584a753d15524f5535b499575cf4cb6c2d1..b727f54712af38265ee816150213ee658f92a6a2 100644 (file)
@@ -635,7 +635,7 @@ enum {
 #define m_TXPWRON_SIG          (1 << 3)                //depend on PHY_GEN2=1 or PHY_EXTERNAL=1
 #define v_TXPWRON_SIG(n)       (((n)&0x01) << 3)
 #define m_ENHPD_RXSENSE_SIG    (1 << 2)                //depend on PHY_GEN2=1 or PHY_EXTERNAL=1
-#define v_ENHPD_RXSENSE_SIG    (((n)&0x01) << 2)
+#define v_ENHPD_RXSENSE_SIG(n) (((n)&0x01) << 2)
 #define m_SEL_DATAEN_POL       (1 << 1)
 #define v_SEL_DATAEN_POL(n)    (((n)&0x01) << 1)
 #define m_SEL_INTERFACE                (1 << 0)
@@ -678,6 +678,7 @@ enum {
 #define        PHY_I2CM_SLAVE                  0x3020
 #define PHY_GEN2_ADDR          0x69
 #define PHY_HEAC_ADDR          0x49
+#define PHY_I2C_SLAVE_ADDR     0x54
 
 #define        PHY_I2CM_ADDRESS                0x3021
 #define        PHY_I2CM_DATAO_1                0x3022
index c453ab644dd3238d8ce7650c91871db42c39d913..7a1a97d65ec7c24fc00349068e791203607c1893 100755 (executable)
@@ -60,7 +60,10 @@ static const struct fb_videomode hdmi_mode [] = {
 {      "720x480p@240Hz",       240,            720,    480,    108000000,      60,     16,     30,     9,      62,     6,              0,                      0,              56      },
 {      "1440x480i@240Hz",      240,            1440,   480,    108000000,      114,    38,     15,     4,      12,     3,              0,                      1,              58      },
 */
-{      "3840x2160p@30Hz",      30,             3840,   2160,   297000000,      296,    1276,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              93      },                                      
+{      "3840x2160p@24Hz",      24,             3840,   2160,   297000000,      296,    1276,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              93      },
+{      "3840x2160p@25Hz",      25,             3840,   2160,   297000000,      296,    1056,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              94      },
+{      "3840x2160p@30Hz",      30,             3840,   2160,   297000000,      296,    176,    72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              95      },
+{      "4096x2160p@24Hz",      24,             4096,   2160,   297000000,      296,    1020,   72,     8,      88,     10,     FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,                   0,              98      },
 
 };