mfd:rk616:modify some operation for vif
authoryxj <yxj@rock-chips.com>
Sun, 19 May 2013 07:43:41 +0000 (15:43 +0800)
committeryxj <yxj@rock-chips.com>
Sun, 19 May 2013 07:43:41 +0000 (15:43 +0800)
drivers/mfd/rk616-core.c
drivers/mfd/rk616-vif.c
drivers/video/display/transmitter/rk616_lvds.c
drivers/video/rockchip/hdmi/rk_hdmi_lcdc.c
drivers/video/rockchip/hdmi/rk_hdmi_task.c
include/linux/mfd/rk616.h

index bdcce422588a6e8ecf5f7704a103f182595f1236..40b8d02144101c972fdd5943d18ed769801ae10d 100644 (file)
@@ -91,7 +91,6 @@ static int rk616_i2c_write_reg(struct mfd_rk616 *rk616, u16 reg,u32 *pval)
        ret = i2c_transfer(adap, &msg, 1);
        kfree(tx_buf);
        
-       
        return (ret == 1) ? 4 : ret;
 }
 
@@ -260,6 +259,31 @@ static  int  rk616_pll_wait_lock(struct mfd_rk616 *rk616,int id)
 }
 
 
+
+int rk616_pll_pwr_down(struct mfd_rk616 *rk616,int id)
+{
+       u32 val = 0;
+       int ret;
+       int offset;
+       if(id == 0)  //PLL0
+       {
+               offset = 0;
+       }
+       else // PLL1
+       {
+               offset = 0x0c;
+       }
+
+
+       val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
+       ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
+
+       return 0;
+       
+}
+
+
+
 int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac)
 {
        u32 val = 0;
@@ -273,19 +297,39 @@ int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac)
        u32 postdiv2 = (con1 >> 6) & 0x7;
        u8 mode = !frac;
        
-       
        if(id == 0)  //PLL0
        {
+               if(((rk616->pll0_rate >> 32) == cfg_val) && 
+                       ((rk616->pll0_rate & 0xffffffff) == frac))
+               {
+                       //return 0;
+               }
+               rk616->pll0_rate = ((u64)cfg_val << 32) | frac;
                offset = 0;
        }
        else // PLL1
        {
+               if(((rk616->pll1_rate >> 32) == cfg_val) && 
+                       ((rk616->pll1_rate & 0xffffffff) == frac))
+               {
+                       // return 0;
+               }
+               rk616->pll1_rate = ((u64)cfg_val << 32) | frac;
                offset = 0x0c;
        }
 
 
        val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
        ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
+       
+
+       ret = rk616->read_dev(rk616,CRU_PLL0_CON2 + offset,&val);
+       val &= 0xff000000;
+       if(frac)
+               val |= PLL0_FRAC(frac);
+       else
+               val |= 0x800000; //default value
+       ret = rk616->write_dev(rk616,CRU_PLL0_CON2 + offset,&val);
 
        val = PLL0_POSTDIV1(postdiv1) | PLL0_FBDIV(fbdiv) | PLL0_POSTDIV1_MASK | 
                PLL0_FBDIV_MASK | (PLL0_BYPASS << 16);
@@ -294,14 +338,14 @@ int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac)
        val = PLL0_DIV_MODE(mode) | PLL0_POSTDIV2(postdiv2) | PLL0_REFDIV(refdiv) |
                (PLL0_DIV_MODE_MASK) | PLL0_POSTDIV2_MASK | PLL0_REFDIV_MASK;
        ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
-
-       val = PLL0_FRAC(frac);
-       ret = rk616->write_dev(rk616,CRU_PLL0_CON2 + offset,&val);
        
        val = (PLL0_PWR_DN << 16);
        ret = rk616->write_dev(rk616,CRU_PLL0_CON1 + offset,&val);
+       
        rk616_pll_wait_lock(rk616,id);
 
+       msleep(5);
+
        return 0;       
        
 }
@@ -331,9 +375,12 @@ static int rk616_clk_common_init(struct mfd_rk616 *rk616)
 
        val = (PLL0_BYPASS) | (PLL0_BYPASS << 16);  //bypass pll0 
        ret = rk616->write_dev(rk616,CRU_PLL0_CON0,&val);
+       val = PLL0_PWR_DN | (PLL0_PWR_DN << 16);
+       ret = rk616->write_dev(rk616,CRU_PLL0_CON1,&val); //power down pll0
 
        val = (PLL1_BYPASS) | (PLL1_BYPASS << 16);
        ret = rk616->write_dev(rk616,CRU_PLL1_CON0,&val);
+       
 
        return 0;
 }
@@ -419,6 +466,14 @@ static int __devexit rk616_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+static void rk616_core_shutdown(struct i2c_client *client)
+{
+       struct mfd_rk616 *rk616 = i2c_get_clientdata(client);
+       if(rk616->pdata->power_deinit)
+               rk616->pdata->power_deinit();
+}
+
+
 static const struct i2c_device_id id_table[] = {
        {"rk616", 0 },
        { }
@@ -431,6 +486,7 @@ static struct i2c_driver rk616_i2c_driver  = {
        },
        .probe          = &rk616_i2c_probe,
        .remove         = &rk616_i2c_remove,
+       .shutdown       = &rk616_core_shutdown,
        .id_table       = id_table,
 };
 
index 5a5c847a169ea27a4a43a901f018224c92a639dd..877c6b761c1a3abf16c787565fe4c966615f3931 100644 (file)
@@ -6,8 +6,123 @@
 
 
 extern int rk616_pll_set_rate(struct mfd_rk616 *rk616,int id,u32 cfg_val,u32 frac);
+extern int rk616_pll_pwr_down(struct mfd_rk616 *rk616,int id);
+
 
 /*rk616 video interface config*/
+
+ int rk616_vif_disable(struct mfd_rk616 *rk616,int id)
+{
+       u32 val = 0;
+       int ret = 0;
+       
+       if(id == 0) //video interface 0
+       {
+                       val = (VIF0_EN << 16); //disable vif0
+                       ret = rk616->write_dev(rk616,VIF0_REG0,&val);
+               
+       }
+       else       //vide0 interface 1
+       {
+                       val = (VIF0_EN << 16); //disabl VIF1
+                       ret = rk616->write_dev(rk616,VIF1_REG0,&val);
+                       
+       }
+       
+       msleep(21);
+       
+       if(id == 0) //video interface 0
+       {
+                       val = VIF0_CLK_GATE | (VIF0_CLK_GATE << 16); //gating vif0
+                       ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
+               
+       }
+       else       //vide0 interface 1
+       {
+                       val = VIF1_CLK_GATE | (VIF1_CLK_GATE << 16); //gating vif1
+                       ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
+                       
+       }
+
+       dev_info(rk616->dev,"rk616 vif%d disable\n",id);
+       
+       return 0;
+}
+
+
+int rk616_vif_enable(struct mfd_rk616 *rk616,int id)
+{
+       u32 val = 0;
+       u32 offset = 0;
+       int ret;
+
+       
+       if(id == 0)
+       {
+               val = (VIF0_CLK_BYPASS << 16) | (VIF0_CLK_GATE << 16);
+               offset = 0;
+       }
+       else
+       {
+               val = (VIF1_CLK_BYPASS << 16) |(VIF1_CLK_GATE << 16);
+               offset = 0x18;
+       }
+
+       ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
+       
+       val = 0;
+       val |= (VIF0_DDR_CLK_EN <<16) | (VIF0_DDR_PHASEN_EN << 16) | (VIF0_DDR_MODE_EN << 16)|
+               (VIF0_EN <<16) | VIF0_EN; //disable ddr mode,enable VIF
+       ret = rk616->write_dev(rk616,VIF0_REG0 + offset,&val);
+
+       
+       dev_info(rk616->dev,"rk616 vif%d enable\n",id);
+
+       return 0;
+       
+}
+static int  rk616_vif_bypass(struct mfd_rk616 *rk616,int id)
+{
+       u32 val = 0;
+       int ret;
+
+       if(id == 0)
+       {
+               val = (VIF0_CLK_BYPASS | VIF0_CLK_BYPASS << 16);
+       }
+       else
+       {
+               val = (VIF1_CLK_BYPASS | VIF1_CLK_BYPASS << 16);
+       }
+
+       ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
+
+       dev_info(rk616->dev,"rk616 vif%d bypass\n",id);
+       return 0;
+}
+
+static bool pll_sel_mclk12m(struct mfd_rk616 *rk616,int pll_id)
+{
+       if(pll_id == 0) //pll0
+       {
+               if(rk616->route.pll0_clk_sel == PLL0_CLK_SEL(MCLK_12M))
+                       return true;
+               else
+                       return false;
+       }
+       else
+       {
+               if(rk616->route.pll1_clk_sel == PLL1_CLK_SEL(MCLK_12M))
+                       return  true;
+               else
+                       return false;   
+       }
+
+       return false;
+}
+
+
+
 int rk616_vif_cfg(struct mfd_rk616 *rk616,rk_screen *screen,int id)
 {
        int ret = 0;
@@ -20,35 +135,26 @@ int rk616_vif_cfg(struct mfd_rk616 *rk616,rk_screen *screen,int id)
        {
                if(!rk616->route.vif0_en)
                {
-                       val = (VIF0_EN << 16); //disable vif0
-                       ret = rk616->write_dev(rk616,VIF0_REG0,&val);
-                       clk_set_rate(rk616->mclk, 11289600);
+                       rk616_vif_disable(rk616,id);
                        return 0;
                }
                offset = 0;
                pll_id = rk616->route.vif0_clk_sel;
-               if(rk616->route.pll0_clk_sel == PLL0_CLK_SEL(MCLK_12M))
-                       pll_use_mclk12m = true;
-               else
-                       pll_use_mclk12m = false;
        }
        else       //vide0 interface 1
        {
                if(!rk616->route.vif1_en)
                {
-                       val = (VIF0_EN << 16); //disabl VIF1
-                       ret = rk616->write_dev(rk616,VIF1_REG0,&val);
-                       clk_set_rate(rk616->mclk, 11289600);
+                       rk616_vif_disable(rk616,id);
                        return 0;
                }
                offset = 0x18;
                pll_id = (rk616->route.vif1_clk_sel >> 6);
-               if(rk616->route.pll1_clk_sel == PLL1_CLK_SEL(MCLK_12M))
-                       pll_use_mclk12m = true;
-               else
-                       pll_use_mclk12m = false;
+               
        }
 
+       pll_use_mclk12m = pll_sel_mclk12m(rk616,pll_id);
+       
        if(pll_use_mclk12m)
        {
                clk_set_rate(rk616->mclk, 12000000);
@@ -61,37 +167,42 @@ int rk616_vif_cfg(struct mfd_rk616 *rk616,rk_screen *screen,int id)
                return -EINVAL;
        }
 
-       
-       
-       val |= (VIF0_DDR_CLK_EN <<16) | (VIF0_DDR_PHASEN_EN << 16) | (VIF0_DDR_MODE_EN << 16)|
-               (VIF0_EN <<16) | VIF0_EN; //disable ddr mode,enable VIF
-       
-       ret = rk616->write_dev(rk616,VIF0_REG0 + offset,&val);  
 
+       rk616_vif_disable(rk616,id);
        if( (screen->x_res == 1920) && (screen->y_res == 1080))
        {
                if(pll_use_mclk12m)
-                       rk616_pll_set_rate(rk616,pll_id,0xc11025,0x200000);
+                       //rk616_pll_set_rate(rk616,pll_id,0xc11025,0x200000);
+                       rk616_pll_set_rate(rk616,pll_id,0x028853de,0);
                else
                        rk616_pll_set_rate(rk616,pll_id,0x02bf5276,0);
+               
+               val = (0xc1) | (0x01 <<16);
        }
        else if((screen->x_res == 1280) && (screen->y_res == 720))
        {
                if(pll_use_mclk12m)
-                       rk616_pll_set_rate(rk616,pll_id,0x01811025,0x200000);
+                       //rk616_pll_set_rate(rk616,pll_id,0x01811025,0x200000);
+                       rk616_pll_set_rate(rk616,pll_id,0x0288418c,0);
                else
                        rk616_pll_set_rate(rk616,pll_id,0x1422014,0);
+               
+               val = (0xc1) | (0x01 <<16);
+       
        }
        else if((screen->x_res == 720))
        {
-               if(pll_use_mclk12m)
-                       rk616_pll_set_rate(rk616,pll_id,0x01413021,0xc00000);
+               if(pll_use_mclk12m )
+               {
+                       rk616_pll_set_rate(rk616,pll_id,0x0306510e,0);
+               }
                else
                        rk616_pll_set_rate(rk616,pll_id,0x1c13015,0);
+               
+               val = (0x1) | (0x01 <<16);
        }
 
-       //val = fscreen->vif_hst | (fscreen->vif_vst<<16);
-       val = (0xc1) | (0x01 <<16);
+       
        ret = rk616->write_dev(rk616,VIF0_REG1 + offset,&val);
 
        val = (screen->hsync_len << 16) | (screen->hsync_len + screen->left_margin + 
@@ -112,41 +223,13 @@ int rk616_vif_cfg(struct mfd_rk616 *rk616,rk_screen *screen,int id)
                (screen->vsync_len + screen->upper_margin);
        ret = rk616->write_dev(rk616,VIF0_REG5 + offset,&val);
 
-       dev_info(rk616->dev,"rk616 vif%d enable\n",id);
+       rk616_vif_enable(rk616,id);
        
        return ret;
        
 }
 
 
-static int rk616_vif_disable(struct mfd_rk616 *rk616,int id)
-{
-       u32 val = 0;
-       int ret = 0;
-
-       printk(KERN_INFO "rk616 vif%d disable\n",id);
-       
-       if(id == 0) //video interface 0
-       {
-               
-                       val = (VIF0_EN << 16); //disable vif0
-                       ret = rk616->write_dev(rk616,VIF0_REG0,&val);
-                       clk_set_rate(rk616->mclk, 11289600);
-                       return 0;
-               
-       }
-       else       //vide0 interface 1
-       {
-               
-                       val = (VIF0_EN << 16); //disabl VIF1
-                       ret = rk616->write_dev(rk616,VIF1_REG0,&val);
-                       clk_set_rate(rk616->mclk, 11289600);
-                       return 0;
-       }
-       
-       
-       return 0;
-}
 static int rk616_scaler_disable(struct mfd_rk616 *rk616)
 {
        u32 val = 0;
@@ -158,21 +241,18 @@ static int rk616_scaler_disable(struct mfd_rk616 *rk616)
 }
 int rk616_scaler_cfg(struct mfd_rk616 *rk616,rk_screen *screen)
 {
-       u32 val = 0;
-       int ret = 0;
        u32 scl_hor_mode,scl_ver_mode;
        u32 scl_v_factor,scl_h_factor;
        u32 scl_reg0_value,scl_reg1_value,scl_reg2_value;                //scl_con,scl_h_factor,scl_v_factor,
        u32 scl_reg3_value,scl_reg4_value,scl_reg5_value,scl_reg6_value; //dsp_frame_hst,dsp_frame_vst,dsp_timing,dsp_act_timing
        u32 scl_reg7_value,scl_reg8_value;                               //dsp_hbor ,dsp_vbor
        u32 dst_frame_hst,dst_frame_vst;                    //ʱÐò»º´æ
-       u32 dst_htotal,dst_hs_end,dst_hact_st,dst_hact_end; //ÆÁÄ»typical h²ÎÊý
-       u32 dst_vtotal,dst_vs_end,dst_vact_st,dst_vact_end; //ÆÁÄ»typical v²ÎÊý
+       u32 dst_vact_st;
 
        u32 dsp_htotal,dsp_hs_end,dsp_hact_st,dsp_hact_end; //scalerÊä³öµÄtiming²ÎÊý
        u32 dsp_vtotal,dsp_vs_end,dsp_vact_st,dsp_vact_end; 
        u32 dsp_hbor_end,dsp_hbor_st,dsp_vbor_end,dsp_vbor_st;
-       u32 src_w,src_h,src_htotal,src_vtotal,dst_w,dst_h,src_hact_st,src_vact_st;
+       u32 src_w,src_h,src_htotal,dst_w,dst_h,src_vact_st;
        u16 bor_right = 0;
        u16 bor_left = 0;
        u16 bor_up = 0;
@@ -349,7 +429,7 @@ static int rk616_dual_input_cfg(struct mfd_rk616 *rk616,rk_screen *screen,
        route->vif0_en     = 0;
        route->vif0_clk_sel = VIF0_CLKIN_SEL(VIF_CLKIN_SEL_PLL0);
        route->pll0_clk_sel = PLL0_CLK_SEL(LCD0_DCLK);
-       route->pll1_clk_sel = PLL1_CLK_SEL(MCLK_12M);
+       route->pll1_clk_sel = PLL1_CLK_SEL(LCD1_DCLK);
        route->vif1_clk_sel = VIF1_CLKIN_SEL(VIF_CLKIN_SEL_PLL1);
        route->hdmi_sel     = HDMI_IN_SEL(HDMI_CLK_SEL_VIF1);
        if(enable)  //hdmi plug in
@@ -385,11 +465,7 @@ static int rk616_dual_input_cfg(struct mfd_rk616 *rk616,rk_screen *screen,
        {
                route->lvds_en = 0;
        }
-       else
-       {
-               dev_err(rk616->dev,"un supported interface:%d\n",screen->type);
-               return -EINVAL;
-       }
+       
 
        return 0;
        
@@ -481,6 +557,9 @@ static int rk616_lcd0_input_lcd1_output_cfg(struct mfd_rk616 *rk616,rk_screen *s
        route->lcd1_input = 0; //lcd1 as out put
        route->lvds_en  = 0;
 
+       //route->scl_en      = 0;
+       //route->dither_sel  = DITHER_IN_SEL(DITHER_SEL_VIF0);
+
        return 0;
        
 }
@@ -531,11 +610,7 @@ static int rk616_lcd0_unused_lcd1_input_cfg(struct mfd_rk616 *rk616,rk_screen *s
        {
                route->lvds_en = 0;
        }
-       else
-       {
-               dev_err(rk616->dev,"un supported interface:%d\n",screen->type);
-               return -EINVAL;
-       }
+       
 
        return 0;
 }
@@ -606,7 +681,7 @@ static int rk616_router_cfg(struct mfd_rk616 *rk616)
                (VIF0_CLK_BYPASS << 16) |(route->sclin_sel) | (route->dither_sel) | 
                (route->hdmi_sel) | (route->vif1_bypass) | (route->vif0_bypass) |
                (route->vif1_clk_sel)| (route->vif0_clk_sel); 
-       ret = rk616->write_dev(rk616,CRU_CLKSE2_CON,&val);
+       ret = rk616->write_dev(rk616,CRU_CLKSEL2_CON,&val);
 
        return ret;
 }
@@ -646,6 +721,7 @@ int rk616_set_vif(struct mfd_rk616 *rk616,rk_screen *screen,bool connect)
        {
                rk616_vif_disable(rk616,0);
                rk616_vif_disable(rk616,1);
+               clk_set_rate(rk616->mclk, 11289600); 
                return 0;
        }
 #if defined(CONFIG_ONE_LCDC_DUAL_OUTPUT_INF)
index 04766b90b3e1413d2fdaf7676dff87e1e9cbe6ae..78d38eadbcd9ce03aeae7174f1a7eb09f7520bde 100644 (file)
@@ -92,6 +92,7 @@ static int rk616_dither_cfg(struct mfd_rk616 *rk616,rk_screen *screen,bool enabl
        val = FRC_DCLK_INV | (FRC_DCLK_INV << 16);
        if((screen->face != OUT_P888) && enable)  //enable frc dither if the screen is not 24bit
                val |= FRC_DITHER_EN | (FRC_DITHER_EN << 16);
+               //val |= (FRC_DITHER_EN << 16);
        else
                val |= (FRC_DITHER_EN << 16);
        ret = rk616->write_dev(rk616,FRC_REG,&val);
index 22f38f356ea77b38bcd91c85d4ddfc86c9477739..e20be70c7a7ebc4703bc3f132eebc540506e24e9 100755 (executable)
@@ -508,11 +508,12 @@ int hdmi_switch_fb(struct hdmi *hdmi, int vic)
 
        rc = hdmi_set_info(screen, hdmi->vic);
 
-       if(rc == 0) {           
-               if(hdmi->set_vif)
-                       hdmi->set_vif(screen,1);
+       if(rc == 0) {
                rk_fb_switch_screen(screen, 1, hdmi->lcdc->id);
                rk_fb_disp_scale(hdmi->xscale, hdmi->yscale, hdmi->lcdc->id);
+               if(hdmi->set_vif)
+                       hdmi->set_vif(screen,1);
+
        }
        
        kfree(screen);
index 057e32d60554f65a31403113c104e682d3e22e20..9148464f20b05aee0f7160dfafa92cfb35935777 100755 (executable)
@@ -234,6 +234,7 @@ void hdmi_work(struct work_struct *work)
                                }
                                break;
                        case SYSTEM_CONFIG:
+                               hdmi->remove();
                                if(hdmi->autoconfig)    
                                        hdmi->vic = hdmi_find_best_mode(hdmi, 0);
                                else
index c9a87995e201dc6733218fb0fd2f01f223b64614..e97057b7ce2dd5f036a34ec49982381df4f2afdf 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/i2c.h>
 #include <linux/rk_fb.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 
 #define VIF0_REG0              0x0000
 #define VIF0_DDR_CLK_EN                (1<<3)
@@ -77,7 +78,7 @@
 
 #define CRU_CODEC_DIV          0x0060
 
-#define CRU_CLKSE2_CON         0x0064
+#define CRU_CLKSEL2_CON        0x0064
 #define SCL_IN_SEL_MASK                (1<<31)
 #define DITHER_IN_SEL_MASK     (1<<30)
 #define HDMI_IN_SEL_MASK       (3<<28)
@@ -222,6 +223,7 @@ enum lvds_mode {
 };
 struct rk616_platform_data {
        int (*power_init)(void);
+       int (*power_deinit)(void);
        int scl_rate;
        enum lcd_port_func lcd0_func;
        enum lcd_port_func lcd1_func;
@@ -261,6 +263,8 @@ struct mfd_rk616 {
        struct rk616_route route;  //display path router
        struct i2c_client *client;
        struct clk *mclk;
+       u64 pll0_rate;
+       u64 pll1_rate;
        struct dentry *debugfs_dir;
        int (*read_dev)(struct mfd_rk616 *rk616,u16 reg,u32 *pval);
        int (*write_dev)(struct mfd_rk616 *rk616,u16 reg,u32 *pval);