lcd: support two clk_path for g12a

PD#156734: lcd: support two clk_path for g12a
clk_path=0, use hpll, default setting;
clk_path=1, use gp0_pll.
clk_path is configured in dts, and can be changed by sysfs node:
echo path <n> >/sys/class/lcd/clk

Change-Id: I30d29ca8eefb2b3e8f4f7f37e4e0e639b23c06bb
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
This commit is contained in:
Evoke Zhang
2018-02-26 14:49:01 +08:00
committed by Jianxin Pan
parent fc3de90be4
commit dfac15acb6
10 changed files with 444 additions and 317 deletions

View File

@@ -102,11 +102,7 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */
.pll_od3_sel = 0,
.pll_level = 0,
.ss_level = 0,
.edp_div0 = 0,
.edp_div1 = 0,
.div_pre = 0, /* m6, m8, m8b */
.div_post = 0, /* m6, m8, m8b */
.div_sel = 0, /* g9tv, g9bb, gxtvbb */
.div_sel = 0,
.xd = 0,
.pll_fout = 0,
@@ -118,9 +114,7 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */
.pll_frac_range = 0,
.pll_od_sel_max = 0,
.ss_level_max = 0,
.div_pre_sel_max = 0, /* m6, m8, m8b */
.div_post_sel_max = 0, /* m6, m8, m8b */
.div_sel_max = 0, /* g9tv, g9bb, gxtvbb */
.div_sel_max = 0,
.xd_max = 0,
.pll_ref_fmax = 0,
.pll_ref_fmin = 0,
@@ -128,9 +122,8 @@ static struct lcd_clk_config_s clk_conf = { /* unit: kHz */
.pll_vco_fmin = 0,
.pll_out_fmax = 0,
.pll_out_fmin = 0,
.div_post_out_fmax = 0, /* m6, m8, m8b */
.div_in_fmax = 0, /* g9tv, g9bb, gxtvbb */
.div_out_fmax = 0, /* g9tv, g9bb, gxtvbb */
.div_in_fmax = 0,
.div_out_fmax = 0,
.xd_out_fmax = 0,
};
@@ -206,8 +199,25 @@ void lcd_clk_config_print(void)
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_AXG:
case LCD_CHIP_G12A:
LCDPR("lcd clk config:\n"
"clk_path %d\n"
"pll_m: %d\n"
"pll_n: %d\n"
"pll_frac: 0x%03x\n"
"pll_fvco: %dkHz\n"
"pll_od: %d\n"
"pll_out: %dkHz\n"
"xd: %d\n"
"fout: %dkHz\n"
"ss_level: %d\n\n",
lcd_drv->lcd_clk_path,
clk_conf.pll_m, clk_conf.pll_n,
clk_conf.pll_frac, clk_conf.pll_fvco,
clk_conf.pll_od1_sel, clk_conf.pll_fout,
clk_conf.xd, clk_conf.fout, clk_conf.ss_level);
break;
case LCD_CHIP_AXG:
LCDPR("lcd clk config:\n"
"pll_m: %d\n"
"pll_n: %d\n"
@@ -349,26 +359,34 @@ static void lcd_clk_config_chip_init(void)
cConf->pll_out_fmax = CRT_VID_CLK_IN_MAX_AXG;
cConf->pll_out_fmin = cConf->pll_vco_fmin /
od_table[cConf->pll_od_sel_max - 1];
cConf->div_post_out_fmax = CRT_VID_CLK_IN_MAX_AXG;
cConf->div_out_fmax = CRT_VID_CLK_IN_MAX_AXG;
cConf->xd_out_fmax = ENCL_CLK_IN_MAX_AXG;
break;
case LCD_CHIP_G12A:
cConf->od_fb = PLL_FRAC_OD_FB_G12A;
cConf->ss_level_max = SS_LEVEL_MAX_G12A;
if (lcd_drv->lcd_clk_path) {
cConf->od_fb = PLL_FRAC_OD_FB_GP0_G12A;
cConf->ss_level_max = SS_LEVEL_MAX_GP0_G12A;
cConf->pll_frac_range = PLL_FRAC_RANGE_GP0_G12A;
cConf->pll_od_sel_max = PLL_OD_SEL_MAX_GP0_G12A;
cConf->pll_vco_fmax = PLL_VCO_MAX_GP0_G12A;
cConf->pll_vco_fmin = PLL_VCO_MIN_GP0_G12A;
} else {
cConf->od_fb = PLL_FRAC_OD_FB_HPLL_G12A;
cConf->ss_level_max = SS_LEVEL_MAX_HPLL_G12A;
cConf->pll_frac_range = PLL_FRAC_RANGE_HPLL_G12A;
cConf->pll_od_sel_max = PLL_OD_SEL_MAX_HPLL_G12A;
cConf->pll_vco_fmax = PLL_VCO_MAX_HPLL_G12A;
cConf->pll_vco_fmin = PLL_VCO_MIN_HPLL_G12A;
}
cConf->pll_m_max = PLL_M_MAX_G12A;
cConf->pll_m_min = PLL_M_MIN_G12A;
cConf->pll_n_max = PLL_N_MAX_G12A;
cConf->pll_n_min = PLL_N_MIN_G12A;
cConf->pll_frac_range = PLL_FRAC_RANGE_G12A;
cConf->pll_od_sel_max = PLL_OD_SEL_MAX_G12A;
cConf->pll_ref_fmax = PLL_FREF_MAX_G12A;
cConf->pll_ref_fmin = PLL_FREF_MIN_G12A;
cConf->pll_vco_fmax = PLL_VCO_MAX_G12A;
cConf->pll_vco_fmin = PLL_VCO_MIN_G12A;
cConf->pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A;
cConf->pll_out_fmin = cConf->pll_vco_fmin /
od_table[cConf->pll_od_sel_max - 1];
cConf->div_post_out_fmax = CRT_VID_CLK_IN_MAX_G12A;
cConf->pll_out_fmin = cConf->pll_vco_fmin / 16;
cConf->div_out_fmax = CRT_VID_CLK_IN_MAX_G12A;
cConf->xd_out_fmax = ENCL_CLK_IN_MAX_G12A;
break;
default:
@@ -379,6 +397,45 @@ static void lcd_clk_config_chip_init(void)
lcd_clk_config_init_print();
}
int lcd_clk_path_change(int sel)
{
struct lcd_clk_config_s *cConf = get_lcd_clk_config();
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
int ret = 0;
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_G12A:
if (sel) {
lcd_drv->lcd_clk_path = 1;
cConf->od_fb = PLL_FRAC_OD_FB_GP0_G12A;
cConf->ss_level_max = SS_LEVEL_MAX_GP0_G12A;
cConf->pll_frac_range = PLL_FRAC_RANGE_GP0_G12A;
cConf->pll_od_sel_max = PLL_OD_SEL_MAX_GP0_G12A;
cConf->pll_vco_fmax = PLL_VCO_MAX_GP0_G12A;
cConf->pll_vco_fmin = PLL_VCO_MIN_GP0_G12A;
} else {
lcd_drv->lcd_clk_path = 0;
cConf->od_fb = PLL_FRAC_OD_FB_HPLL_G12A;
cConf->ss_level_max = SS_LEVEL_MAX_HPLL_G12A;
cConf->pll_frac_range = PLL_FRAC_RANGE_HPLL_G12A;
cConf->pll_od_sel_max = PLL_OD_SEL_MAX_HPLL_G12A;
cConf->pll_vco_fmax = PLL_VCO_MAX_HPLL_G12A;
cConf->pll_vco_fmin = PLL_VCO_MIN_HPLL_G12A;
}
cConf->pll_out_fmax = CRT_VID_CLK_IN_MAX_G12A;
cConf->pll_out_fmin = cConf->pll_vco_fmin / 16;
break;
default:
ret = -1;
LCDPR("%s: current chip not support\n", __func__);
break;
}
if (lcd_debug_print_flag > 0)
lcd_clk_config_init_print();
return ret;
}
/* lcd controller operation */
static int lcd_pll_wait_lock(unsigned int reg, unsigned int lock_bit)
{
@@ -761,14 +818,14 @@ static void lcd_update_pll_frac_axg(struct lcd_clk_config_s *cConf)
lcd_hiu_setb(HHI_GP0_PLL_CNTL1_AXG, cConf->pll_frac, 0, 12);
}
static void lcd_pll_reset_g12a(void)
static void lcd_gp0_pll_reset_g12a(void)
{
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 1, LCD_PLL_RST_G12A, 1);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 1, LCD_PLL_RST_GP0_G12A, 1);
udelay(10);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 0, LCD_PLL_RST_G12A, 1);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 0, LCD_PLL_RST_GP0_G12A, 1);
}
static void lcd_set_pll_g12a(struct lcd_clk_config_s *cConf)
static void lcd_set_gp0_pll_g12a(struct lcd_clk_config_s *cConf)
{
unsigned int pll_ctrl, pll_ctrl1, pll_ctrl3, pll_ctrl4, pll_ctrl6;
int ret;
@@ -776,10 +833,10 @@ static void lcd_set_pll_g12a(struct lcd_clk_config_s *cConf)
if (lcd_debug_print_flag == 2)
LCDPR("%s\n", __func__);
pll_ctrl = ((1 << LCD_PLL_EN_G12A) |
(cConf->pll_n << LCD_PLL_N_G12A) |
(cConf->pll_m << LCD_PLL_M_G12A) |
(cConf->pll_od1_sel << LCD_PLL_OD_G12A));
pll_ctrl = ((1 << LCD_PLL_EN_GP0_G12A) |
(cConf->pll_n << LCD_PLL_N_GP0_G12A) |
(cConf->pll_m << LCD_PLL_M_GP0_G12A) |
(cConf->pll_od1_sel << LCD_PLL_OD_GP0_G12A));
pll_ctrl1 = (cConf->pll_frac << 0);
if (cConf->pll_frac) {
pll_ctrl |= (1 << 27);
@@ -799,17 +856,17 @@ static void lcd_set_pll_g12a(struct lcd_clk_config_s *cConf)
lcd_hiu_write(HHI_GP0_PLL_CNTL4_G12A, pll_ctrl4);
lcd_hiu_write(HHI_GP0_PLL_CNTL5_G12A, 0x39272000);
lcd_hiu_write(HHI_GP0_PLL_CNTL6_G12A, pll_ctrl6);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 1, LCD_PLL_RST_G12A, 1);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 1, LCD_PLL_RST_GP0_G12A, 1);
udelay(100);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 0, LCD_PLL_RST_G12A, 1);
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 0, LCD_PLL_RST_GP0_G12A, 1);
ret = lcd_pll_wait_lock(HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_LOCK_G12A);
ret = lcd_pll_wait_lock(HHI_GP0_PLL_CNTL0_G12A, LCD_PLL_LOCK_GP0_G12A);
if (ret)
LCDERR("gp0_pll lock failed\n");
}
static void lcd_update_pll_frac_g12a(struct lcd_clk_config_s *cConf)
static void lcd_update_gp0_pll_frac_g12a(struct lcd_clk_config_s *cConf)
{
if (lcd_debug_print_flag == 2)
LCDPR("%s\n", __func__);
@@ -817,6 +874,65 @@ static void lcd_update_pll_frac_g12a(struct lcd_clk_config_s *cConf)
lcd_hiu_setb(HHI_GP0_PLL_CNTL1_G12A, cConf->pll_frac, 0, 19);
}
static void lcd_hpll_reset_g12a(void)
{
lcd_hiu_setb(HHI_HDMI_PLL_CNTL, 1, LCD_PLL_RST_HPLL_G12A, 1);
udelay(10);
lcd_hiu_setb(HHI_HDMI_PLL_CNTL, 0, LCD_PLL_RST_HPLL_G12A, 1);
}
static void lcd_set_hpll_g12a(struct lcd_clk_config_s *cConf)
{
unsigned int pll_ctrl, pll_ctrl2, pll_ctrl4, pll_ctrl5, pll_ctrl7;
int ret;
if (lcd_debug_print_flag == 2)
LCDPR("%s\n", __func__);
pll_ctrl = ((1 << LCD_PLL_EN_HPLL_G12A) |
(1 << 25) | /* clk out gate */
(cConf->pll_n << LCD_PLL_N_HPLL_G12A) |
(cConf->pll_m << LCD_PLL_M_HPLL_G12A) |
(cConf->pll_od1_sel << LCD_PLL_OD1_HPLL_G12A) |
(cConf->pll_od2_sel << LCD_PLL_OD2_HPLL_G12A) |
(cConf->pll_od3_sel << LCD_PLL_OD3_HPLL_G12A));
pll_ctrl2 = (cConf->pll_frac << 0);
if (cConf->pll_frac) {
pll_ctrl |= (1 << 27);
pll_ctrl4 = 0x6a29dc00;
pll_ctrl5 = 0x65771290;
pll_ctrl7 = 0x54540000;
} else {
pll_ctrl4 = 0x0a691c00;
pll_ctrl5 = 0x33771290;
pll_ctrl7 = 0x50540000;
}
lcd_hiu_write(HHI_HDMI_PLL_CNTL, pll_ctrl);
lcd_hiu_write(HHI_HDMI_PLL_CNTL2, pll_ctrl2);
lcd_hiu_write(HHI_HDMI_PLL_CNTL3, 0x00);
lcd_hiu_write(HHI_HDMI_PLL_CNTL4, pll_ctrl4);
lcd_hiu_write(HHI_HDMI_PLL_CNTL5, pll_ctrl5);
lcd_hiu_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
lcd_hiu_write(HHI_HDMI_PLL_CNTL7, pll_ctrl7);
lcd_hiu_setb(HHI_HDMI_PLL_CNTL, 1, LCD_PLL_RST_HPLL_G12A, 1);
udelay(100);
lcd_hiu_setb(HHI_HDMI_PLL_CNTL, 0, LCD_PLL_RST_HPLL_G12A, 1);
ret = lcd_pll_wait_lock(HHI_HDMI_PLL_CNTL, LCD_PLL_LOCK_HPLL_G12A);
if (ret)
LCDERR("hpll lock failed\n");
}
static void lcd_update_hpll_frac_g12a(struct lcd_clk_config_s *cConf)
{
if (lcd_debug_print_flag == 2)
LCDPR("%s\n", __func__);
lcd_hiu_setb(HHI_HDMI_PLL_CNTL2, cConf->pll_frac, 0, 19);
}
static unsigned int lcd_clk_div_g9_gxtvbb[][3] = {
/* divider, shift_val, shift_sel */
{CLK_DIV_SEL_1, 0xffff, 0,},
@@ -837,7 +953,7 @@ static unsigned int lcd_clk_div_g9_gxtvbb[][3] = {
{CLK_DIV_SEL_MAX, 0xffff, 0,},
};
static void lcd_set_clk_div_g9_gxtvbb(struct lcd_clk_config_s *cConf)
static void lcd_set_vid_pll_div(struct lcd_clk_config_s *cConf)
{
unsigned int shift_val, shift_sel;
int i;
@@ -893,7 +1009,10 @@ static void lcd_set_vclk_crt(int lcd_type, struct lcd_clk_config_s *cConf)
/* select vid_pll_clk */
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_G12A:
lcd_hiu_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_CLK_IN_SEL, 3);
if (lcd_drv->lcd_clk_path)
lcd_hiu_setb(HHI_VIID_CLK_CNTL, 1, VCLK2_CLK_IN_SEL, 3);
else
lcd_hiu_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_CLK_IN_SEL, 3);
break;
default:
lcd_hiu_setb(HHI_VIID_CLK_CNTL, 0, VCLK2_CLK_IN_SEL, 3);
@@ -918,19 +1037,17 @@ static void lcd_set_vclk_crt(int lcd_type, struct lcd_clk_config_s *cConf)
lcd_hiu_setb(HHI_VID_CLK_CNTL2, 1, ENCL_GATE_VCLK, 1);
}
static void dsi_phy_clk_set(void)
static void lcd_set_dsi_phy_clk(int sel)
{
if (lcd_debug_print_flag == 2)
LCDPR("%s\n", __func__);
lcd_hiu_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 0, 14, 1);
lcd_hiu_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 0, 13, 1);
lcd_hiu_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 1, 12, 1);
lcd_hiu_setb(HHI_MIPIDSI_PHY_CLK_CNTL, sel, 12, 3);
lcd_hiu_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 1, 8, 1);
lcd_hiu_setb(HHI_MIPIDSI_PHY_CLK_CNTL, 0, 0, 7);
}
static unsigned int clk_div_calc_g9_gxtvbb(unsigned int clk,
static unsigned int clk_vid_pll_div_calc(unsigned int clk,
unsigned int div_sel, int dir)
{
unsigned int clk_ret;
@@ -1032,7 +1149,7 @@ static unsigned int clk_div_calc_g9_gxtvbb(unsigned int clk,
return clk_ret;
}
static unsigned int clk_div_get_g9_gxtvbb(unsigned int clk_div)
static unsigned int clk_vid_pll_div_get(unsigned int clk_div)
{
unsigned int div_sel;
@@ -1057,7 +1174,7 @@ static unsigned int clk_div_get_g9_gxtvbb(unsigned int clk_div)
return div_sel;
}
static int check_pll_g9_gxtvbb(struct lcd_clk_config_s *cConf,
static int check_pll_gxtvbb(struct lcd_clk_config_s *cConf,
unsigned int pll_fout)
{
unsigned int m, n;
@@ -1105,7 +1222,7 @@ static int check_pll_g9_gxtvbb(struct lcd_clk_config_s *cConf,
cConf->pll_n = n;
cConf->pll_frac = pll_frac;
if (lcd_debug_print_flag == 2) {
LCDPR("m=%d, n=%d, frac=%d\n",
LCDPR("m=%d, n=%d, frac=0x%x\n",
m, n, pll_frac);
}
done = 1;
@@ -1116,7 +1233,7 @@ static int check_pll_g9_gxtvbb(struct lcd_clk_config_s *cConf,
return done;
}
static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
static void lcd_clk_generate_gxtvbb(struct lcd_config_s *pconf)
{
unsigned int pll_fout;
unsigned int clk_div_in, clk_div_out;
@@ -1132,7 +1249,7 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
if (cConf->fout > cConf->xd_out_fmax) {
LCDERR("%s: wrong lcd_clk value %dkHz\n",
__func__, cConf->fout);
goto generate_clk_done_g9_gxtvbb;
goto generate_clk_done_gxtvbb;
}
switch (pconf->lcd_basic.lcd_type) {
@@ -1147,7 +1264,7 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
LCDPR("fout=%d, xd=%d, clk_div_out=%d\n",
cConf->fout, xd, clk_div_out);
}
clk_div_in = clk_div_calc_g9_gxtvbb(clk_div_out,
clk_div_in = clk_vid_pll_div_calc(clk_div_out,
clk_div_sel, CLK_DIV_O2I);
if (clk_div_in > cConf->div_in_fmax)
continue;
@@ -1159,9 +1276,9 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
lcd_clk_div_sel_table[clk_div_sel],
clk_div_sel, pll_fout);
}
done = check_pll_g9_gxtvbb(cConf, pll_fout);
done = check_pll_gxtvbb(cConf, pll_fout);
if (done)
goto generate_clk_done_g9_gxtvbb;
goto generate_clk_done_gxtvbb;
}
break;
case LCD_LVDS:
@@ -1169,15 +1286,15 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
xd = 1;
clk_div_out = cConf->fout * xd;
if (clk_div_out > cConf->div_out_fmax)
goto generate_clk_done_g9_gxtvbb;
goto generate_clk_done_gxtvbb;
if (lcd_debug_print_flag == 2) {
LCDPR("fout=%d, xd=%d, clk_div_out=%d\n",
cConf->fout, xd, clk_div_out);
}
clk_div_in = clk_div_calc_g9_gxtvbb(clk_div_out,
clk_div_in = clk_vid_pll_div_calc(clk_div_out,
clk_div_sel, CLK_DIV_O2I);
if (clk_div_in > cConf->div_in_fmax)
goto generate_clk_done_g9_gxtvbb;
goto generate_clk_done_gxtvbb;
cConf->xd = xd;
cConf->div_sel = clk_div_sel;
pll_fout = clk_div_in;
@@ -1186,9 +1303,9 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
lcd_clk_div_sel_table[clk_div_sel],
clk_div_sel, pll_fout);
}
done = check_pll_g9_gxtvbb(cConf, pll_fout);
done = check_pll_gxtvbb(cConf, pll_fout);
if (done)
goto generate_clk_done_g9_gxtvbb;
goto generate_clk_done_gxtvbb;
break;
case LCD_VBYONE:
cConf->div_sel_max = CLK_DIV_SEL_MAX;
@@ -1196,7 +1313,7 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
pll_fout = pconf->lcd_control.vbyone_config->bit_rate / 1000;
clk_div_in = pll_fout;
if (clk_div_in > cConf->div_in_fmax)
goto generate_clk_done_g9_gxtvbb;
goto generate_clk_done_gxtvbb;
if (lcd_debug_print_flag == 2)
LCDPR("pll_fout=%d\n", pll_fout);
if ((clk_div_in / cConf->fout) > 15)
@@ -1210,8 +1327,8 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
clk_div_out, cConf->xd);
}
if (clk_div_out > cConf->div_out_fmax)
goto generate_clk_done_g9_gxtvbb;
clk_div_sel = clk_div_get_g9_gxtvbb(
goto generate_clk_done_gxtvbb;
clk_div_sel = clk_vid_pll_div_get(
clk_div_in * 100 / clk_div_out);
cConf->div_sel = clk_div_sel;
if (lcd_debug_print_flag == 2) {
@@ -1219,13 +1336,13 @@ static void lcd_clk_generate_g9_gxtvbb(struct lcd_config_s *pconf)
lcd_clk_div_sel_table[clk_div_sel],
cConf->div_sel);
}
done = check_pll_g9_gxtvbb(cConf, pll_fout);
done = check_pll_gxtvbb(cConf, pll_fout);
break;
default:
break;
}
generate_clk_done_g9_gxtvbb:
generate_clk_done_gxtvbb:
if (done) {
pconf->lcd_timing.pll_ctrl =
(cConf->pll_od1_sel << PLL_CTRL_OD1) |
@@ -1253,7 +1370,7 @@ generate_clk_done_g9_gxtvbb:
}
}
static void lcd_pll_frac_generate_g9_gxtvbb(struct lcd_config_s *pconf)
static void lcd_pll_frac_generate_gxtvbb(struct lcd_config_s *pconf)
{
unsigned int pll_fout;
unsigned int clk_div_in, clk_div_out, clk_div_sel;
@@ -1294,7 +1411,7 @@ static void lcd_pll_frac_generate_g9_gxtvbb(struct lcd_config_s *pconf)
}
clk_div_in =
clk_div_calc_g9_gxtvbb(clk_div_out, clk_div_sel, CLK_DIV_O2I);
clk_vid_pll_div_calc(clk_div_out, clk_div_sel, CLK_DIV_O2I);
if (clk_div_in > cConf->div_in_fmax) {
LCDERR("%s: wrong clk_div_in value %dkHz\n",
__func__, clk_div_in);
@@ -1380,8 +1497,7 @@ static int check_pll_txl(struct lcd_clk_config_s *cConf,
}
cConf->pll_fvco = pll_fvco;
n = 1;
/* update od_fb to 1 for ss width */
od_fb = cConf->od_fb; /* pll default */
od_fb = cConf->od_fb;
pll_fvco = pll_fvco / od_fb_table[od_fb];
m = pll_fvco / cConf->fin;
pll_frac = (pll_fvco % cConf->fin) *
@@ -1390,7 +1506,7 @@ static int check_pll_txl(struct lcd_clk_config_s *cConf,
cConf->pll_n = n;
cConf->pll_frac = pll_frac;
if (lcd_debug_print_flag == 2) {
LCDPR("m=%d, n=%d, frac=%d\n",
LCDPR("m=%d, n=%d, frac=0x%x\n",
m, n, pll_frac);
}
done = 1;
@@ -1437,7 +1553,7 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf)
LCDPR("fout=%d, xd=%d, clk_div_out=%d\n",
cConf->fout, xd, clk_div_out);
}
clk_div_in = clk_div_calc_g9_gxtvbb(clk_div_out,
clk_div_in = clk_vid_pll_div_calc(clk_div_out,
clk_div_sel, CLK_DIV_O2I);
if (clk_div_in > cConf->div_in_fmax)
continue;
@@ -1464,7 +1580,7 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf)
LCDPR("fout=%d, xd=%d, clk_div_out=%d\n",
cConf->fout, xd, clk_div_out);
}
clk_div_in = clk_div_calc_g9_gxtvbb(clk_div_out,
clk_div_in = clk_vid_pll_div_calc(clk_div_out,
clk_div_sel, CLK_DIV_O2I);
if (clk_div_in > cConf->div_in_fmax)
goto generate_clk_done_txl;
@@ -1501,7 +1617,7 @@ static void lcd_clk_generate_txl(struct lcd_config_s *pconf)
}
if (clk_div_out > cConf->div_out_fmax)
goto generate_clk_done_txl;
clk_div_sel = clk_div_get_g9_gxtvbb(
clk_div_sel = clk_vid_pll_div_get(
clk_div_in * 100 / clk_div_out);
cConf->div_sel = clk_div_sel;
if (lcd_debug_print_flag == 2) {
@@ -1526,8 +1642,7 @@ generate_clk_done_txl:
pconf->lcd_timing.div_ctrl =
(cConf->div_sel << DIV_CTRL_DIV_SEL) |
(cConf->xd << DIV_CTRL_XD);
pconf->lcd_timing.clk_ctrl =
(cConf->pll_frac << CLK_CTRL_FRAC);
pconf->lcd_timing.clk_ctrl = (cConf->pll_frac << CLK_CTRL_FRAC);
} else {
pconf->lcd_timing.pll_ctrl =
(1 << PLL_CTRL_OD1) |
@@ -1584,7 +1699,7 @@ static void lcd_pll_frac_generate_txl(struct lcd_config_s *pconf)
}
clk_div_in =
clk_div_calc_g9_gxtvbb(clk_div_out, clk_div_sel, CLK_DIV_O2I);
clk_vid_pll_div_calc(clk_div_out, clk_div_sel, CLK_DIV_O2I);
if (clk_div_in > cConf->div_in_fmax) {
LCDERR("%s: wrong clk_div_in value %dkHz\n",
__func__, clk_div_in);
@@ -1668,9 +1783,8 @@ static int check_pll_axg(struct lcd_clk_config_s *cConf,
cConf->pll_n = n;
cConf->pll_frac = pll_frac;
if (lcd_debug_print_flag == 2) {
LCDPR("pll_m=%d, pll_n=%d\n", m, n);
LCDPR("pll_frac=0x%03x\n",
pll_frac);
LCDPR("pll_m=%d, pll_n=%d, pll_frac=0x%x\n",
m, n, pll_frac);
}
done = 1;
break;
@@ -1733,27 +1847,19 @@ generate_clk_done_axg:
(cConf->pll_n << PLL_CTRL_N) |
(cConf->pll_m << PLL_CTRL_M);
pconf->lcd_timing.div_ctrl =
(cConf->edp_div1 << DIV_CTRL_EDP_DIV1) |
(cConf->edp_div0 << DIV_CTRL_EDP_DIV0) |
(cConf->div_post << DIV_CTRL_DIV_POST) |
(cConf->div_pre << DIV_CTRL_DIV_PRE) |
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(cConf->xd << DIV_CTRL_XD);
tmp = (pconf->lcd_timing.clk_ctrl &
~((0x7 << CLK_CTRL_LEVEL) | (0xfff << CLK_CTRL_FRAC)));
pconf->lcd_timing.clk_ctrl = (tmp |
(cConf->pll_level << CLK_CTRL_LEVEL) |
(cConf->pll_frac << CLK_CTRL_FRAC));
pconf->lcd_timing.clk_ctrl = (cConf->pll_frac << CLK_CTRL_FRAC);
} else {
pconf->lcd_timing.pll_ctrl = (1 << PLL_CTRL_OD1) |
(1 << PLL_CTRL_N) | (50 << PLL_CTRL_M);
pconf->lcd_timing.pll_ctrl =
(1 << PLL_CTRL_OD1) |
(1 << PLL_CTRL_N) |
(50 << PLL_CTRL_M);
pconf->lcd_timing.div_ctrl =
(0 << DIV_CTRL_EDP_DIV1) | (0 << DIV_CTRL_EDP_DIV0) |
(1 << DIV_CTRL_DIV_PRE) | (1 << DIV_CTRL_DIV_PRE) |
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(7 << DIV_CTRL_XD);
tmp = (pconf->lcd_timing.clk_ctrl &
~((0x7 << CLK_CTRL_LEVEL) | (0xfff << CLK_CTRL_FRAC)));
pconf->lcd_timing.clk_ctrl |= (1 << CLK_CTRL_LEVEL);
LCDERR("Out of clock range, reset to default setting!\n");
pconf->lcd_timing.clk_ctrl = (0 << CLK_CTRL_FRAC);
LCDERR("Out of clock range, reset to default setting\n");
}
}
@@ -1821,61 +1927,17 @@ static void lcd_pll_frac_generate_axg(struct lcd_config_s *pconf)
if (lcd_debug_print_flag)
LCDPR("lcd_pll_frac_generate: frac=0x%x\n", frac);
}
#if 0
static int check_pll_g12a(struct lcd_clk_config_s *cConf,
unsigned int pll_fout)
{
unsigned int m, n, od_sel, od;
unsigned int pll_fvco;
unsigned int pll_frac;
int done = 0;
if ((pll_fout > cConf->pll_out_fmax) ||
(pll_fout < cConf->pll_out_fmin)) {
return done;
}
for (od_sel = cConf->pll_od_sel_max; od_sel > 0; od_sel--) {
od = od_table[od_sel - 1];
pll_fvco = pll_fout * od;
if ((pll_fvco < cConf->pll_vco_fmin) ||
(pll_fvco > cConf->pll_vco_fmax)) {
continue;
}
cConf->pll_od1_sel = od_sel - 1;
cConf->pll_fout = pll_fout;
if (lcd_debug_print_flag == 2) {
LCDPR("od_sel=%d, pll_fvco=%d\n",
(od_sel - 1), pll_fvco);
}
cConf->pll_fvco = pll_fvco;
n = 1;
m = pll_fvco / cConf->fin;
pll_frac = (pll_fvco % cConf->fin) *
cConf->pll_frac_range / cConf->fin;
cConf->pll_m = m;
cConf->pll_n = n;
cConf->pll_frac = pll_frac;
if (lcd_debug_print_flag == 2) {
LCDPR("pll_m=%d, pll_n=%d\n", m, n);
LCDPR("pll_frac=0x%03x\n",
pll_frac);
}
done = 1;
break;
}
return done;
}
static void lcd_clk_generate_g12a(struct lcd_config_s *pconf)
static void lcd_clk_generate_hpll_g12a(struct lcd_config_s *pconf)
{
unsigned int pll_fout;
unsigned int xd;
unsigned int clk_div_sel, xd;
unsigned int dsi_bit_rate_max = 0, dsi_bit_rate_min = 0;
unsigned int tmp;
struct lcd_clk_config_s *cConf;
struct lcd_clk_config_s *cConf = get_lcd_clk_config();
int done;
cConf = get_lcd_clk_config();
done = 0;
cConf->fout = pconf->lcd_timing.lcd_clk / 1000; /* kHz */
cConf->err_fmin = MAX_ERROR;
@@ -1891,6 +1953,7 @@ static void lcd_clk_generate_g12a(struct lcd_config_s *pconf)
dsi_bit_rate_max = tmp * 1000; /* change to kHz */
dsi_bit_rate_min = dsi_bit_rate_max - cConf->fout;
clk_div_sel = CLK_DIV_SEL_1;
for (xd = 1; xd <= cConf->xd_max; xd++) {
pll_fout = cConf->fout * xd;
if ((pll_fout > dsi_bit_rate_max) ||
@@ -1904,84 +1967,50 @@ static void lcd_clk_generate_g12a(struct lcd_config_s *pconf)
pll_fout * 1000;
pconf->lcd_control.mipi_config->clk_factor = xd;
cConf->xd = xd;
check_pll_g12a(cConf, pll_fout);
cConf->div_sel = clk_div_sel;
done = check_pll_txl(cConf, pll_fout);
if (done)
goto generate_clk_done_g12a;
}
break;
default:
break;
}
}
static void lcd_pll_frac_generate_g12a(struct lcd_config_s *pconf)
{
unsigned int pll_fout;
unsigned int od, pll_fvco;
unsigned int m, n, frac, offset, temp;
struct lcd_clk_config_s *cConf;
cConf = get_lcd_clk_config();
cConf->fout = pconf->lcd_timing.lcd_clk / 1000; /* kHz */
od = od_table[cConf->pll_od1_sel];
m = cConf->pll_m;
n = cConf->pll_n;
if (lcd_debug_print_flag == 2) {
LCDPR("m=%d, n=%d, od=%d, xd=%d\n",
m, n, cConf->pll_od1_sel, cConf->xd);
}
if (cConf->fout > cConf->xd_out_fmax) {
LCDERR("%s: wrong lcd_clk value %dkHz\n",
__func__, cConf->fout);
return;
}
if (lcd_debug_print_flag == 2)
LCDPR("%s pclk=%d\n", __func__, cConf->fout);
pll_fout = cConf->fout * cConf->xd;
if ((pll_fout > cConf->pll_out_fmax) ||
(pll_fout < cConf->pll_out_fmin)) {
LCDERR("%s: wrong pll_fout value %dkHz\n", __func__, pll_fout);
return;
}
if (lcd_debug_print_flag == 2)
LCDPR("%s pll_fout=%d\n", __func__, pll_fout);
pll_fvco = pll_fout * od;
if ((pll_fvco < cConf->pll_vco_fmin) ||
(pll_fvco > cConf->pll_vco_fmax)) {
LCDERR("%s: wrong pll_fvco value %dkHz\n", __func__, pll_fvco);
return;
}
if (lcd_debug_print_flag == 2)
LCDPR("%s pll_fvco=%d\n", __func__, pll_fvco);
cConf->pll_fvco = pll_fvco;
temp = cConf->fin * m / n;
if (pll_fvco >= temp) {
temp = pll_fvco - temp;
offset = 0;
generate_clk_done_g12a:
if (done) {
pconf->lcd_timing.pll_ctrl =
(cConf->pll_od1_sel << PLL_CTRL_OD1) |
(cConf->pll_od2_sel << PLL_CTRL_OD2) |
(cConf->pll_od3_sel << PLL_CTRL_OD3) |
(cConf->pll_n << PLL_CTRL_N) |
(cConf->pll_m << PLL_CTRL_M);
pconf->lcd_timing.div_ctrl =
(cConf->div_sel << DIV_CTRL_DIV_SEL) |
(cConf->xd << DIV_CTRL_XD);
pconf->lcd_timing.clk_ctrl = (cConf->pll_frac << CLK_CTRL_FRAC);
} else {
temp = temp - pll_fvco;
offset = 1;
pconf->lcd_timing.pll_ctrl =
(1 << PLL_CTRL_OD1) |
(1 << PLL_CTRL_OD2) |
(1 << PLL_CTRL_OD3) |
(1 << PLL_CTRL_N) |
(50 << PLL_CTRL_M);
pconf->lcd_timing.div_ctrl =
(CLK_DIV_SEL_1 << DIV_CTRL_DIV_SEL) |
(7 << DIV_CTRL_XD);
pconf->lcd_timing.clk_ctrl = (0 << CLK_CTRL_FRAC);
LCDERR("Out of clock range, reset to default setting\n");
}
if (temp >= (2 * cConf->fin)) {
LCDERR("%s: pll changing %dkHz is too much\n",
__func__, temp);
return;
}
frac = temp * cConf->pll_frac_range * n / cConf->fin;
cConf->pll_frac = frac | (offset << 11);
if (lcd_debug_print_flag)
LCDPR("lcd_pll_frac_generate: frac=0x%x\n", frac);
}
#endif
void lcd_clk_generate_parameter(struct lcd_config_s *pconf)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_GXTVBB:
lcd_clk_generate_g9_gxtvbb(pconf);
lcd_clk_generate_gxtvbb(pconf);
break;
case LCD_CHIP_GXL:
case LCD_CHIP_GXM:
@@ -1989,12 +2018,14 @@ void lcd_clk_generate_parameter(struct lcd_config_s *pconf)
lcd_clk_generate_txl(pconf);
break;
case LCD_CHIP_AXG:
case LCD_CHIP_G12A:
lcd_clk_generate_axg(pconf);
break;
// case LCD_CHIP_G12A:
// lcd_clk_generate_g12a(pconf);
// break;
case LCD_CHIP_G12A:
if (lcd_drv->lcd_clk_path)
lcd_clk_generate_axg(pconf);
else
lcd_clk_generate_hpll_g12a(pconf);
break;
default:
break;
}
@@ -2081,7 +2112,10 @@ void lcd_pll_reset(void)
lcd_pll_reset_axg();
break;
case LCD_CHIP_G12A:
lcd_pll_reset_g12a();
if (lcd_drv->lcd_clk_path)
lcd_gp0_pll_reset_g12a();
else
lcd_hpll_reset_g12a();
break;
default:
break;
@@ -2101,7 +2135,7 @@ void lcd_clk_update(struct lcd_config_s *pconf)
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_GXTVBB:
lcd_pll_frac_generate_g9_gxtvbb(pconf);
lcd_pll_frac_generate_gxtvbb(pconf);
lcd_update_pll_frac_gxtvbb(&clk_conf);
break;
case LCD_CHIP_GXL:
@@ -2115,8 +2149,13 @@ void lcd_clk_update(struct lcd_config_s *pconf)
lcd_update_pll_frac_axg(&clk_conf);
break;
case LCD_CHIP_G12A:
lcd_pll_frac_generate_axg(pconf);
lcd_update_pll_frac_g12a(&clk_conf);
if (lcd_drv->lcd_clk_path) {
lcd_pll_frac_generate_axg(pconf);
lcd_update_gp0_pll_frac_g12a(&clk_conf);
} else {
lcd_pll_frac_generate_txl(pconf);
lcd_update_hpll_frac_g12a(&clk_conf);
}
break;
default:
break;
@@ -2139,23 +2178,29 @@ void lcd_clk_set(struct lcd_config_s *pconf)
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_GXTVBB:
lcd_set_pll_gxtvbb(&clk_conf);
lcd_set_clk_div_g9_gxtvbb(&clk_conf);
lcd_set_vid_pll_div(&clk_conf);
break;
case LCD_CHIP_GXL:
case LCD_CHIP_GXM:
lcd_set_pll_txl(&clk_conf);
lcd_set_clk_div_g9_gxtvbb(&clk_conf);
lcd_set_vid_pll_div(&clk_conf);
break;
case LCD_CHIP_TXLX:
lcd_set_pll_txlx(&clk_conf);
lcd_set_clk_div_g9_gxtvbb(&clk_conf);
lcd_set_vid_pll_div(&clk_conf);
break;
case LCD_CHIP_AXG:
lcd_set_pll_axg(&clk_conf);
break;
case LCD_CHIP_G12A:
lcd_set_pll_g12a(&clk_conf);
dsi_phy_clk_set();
if (lcd_drv->lcd_clk_path) { /* gp0_pll */
lcd_set_gp0_pll_g12a(&clk_conf);
lcd_set_dsi_phy_clk(1);
} else { /* hpll */
lcd_set_hpll_g12a(&clk_conf);
lcd_set_vid_pll_div(&clk_conf);
lcd_set_dsi_phy_clk(0);
}
break;
default:
break;
@@ -2172,19 +2217,7 @@ void lcd_clk_disable(void)
if (lcd_debug_print_flag)
LCDPR("%s\n", __func__);
/* disable CTS_ENCL clk gate, new added in m8m2 */
switch (lcd_drv->data->chip_type) {
case LCD_CHIP_GXTVBB:
case LCD_CHIP_GXL:
case LCD_CHIP_GXM:
case LCD_CHIP_TXLX:
case LCD_CHIP_AXG:
case LCD_CHIP_G12A:
lcd_hiu_setb(HHI_VID_CLK_CNTL2, 0, ENCL_GATE_VCLK, 1);
break;
default:
break;
}
lcd_hiu_setb(HHI_VID_CLK_CNTL2, 0, ENCL_GATE_VCLK, 1);
/* close vclk2_div gate: 0x104b[4:0] */
lcd_hiu_setb(HHI_VIID_CLK_CNTL, 0, 0, 5);
@@ -2208,8 +2241,14 @@ void lcd_clk_disable(void)
lcd_hiu_setb(HHI_GP0_PLL_CNTL_AXG, 0, LCD_PLL_EN_AXG, 1);
break;
case LCD_CHIP_G12A:
/* disable hdmi_pll: 0x10c8[28] */
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A, 0, LCD_PLL_EN_G12A, 1);
if (lcd_drv->lcd_clk_path) {
lcd_hiu_setb(HHI_GP0_PLL_CNTL0_G12A,
0, LCD_PLL_EN_GP0_G12A, 1);
} else {
/* disable hdmi_pll: 0x10c8[28] */
lcd_hiu_setb(HHI_HDMI_PLL_CNTL,
0, LCD_PLL_EN_HPLL_G12A, 1);
}
break;
default:
break;

View File

@@ -31,6 +31,7 @@ struct lcd_clk_config_s { /* unit: kHz */
unsigned int fout;
/* pll parameters */
unsigned int pll_mode;
unsigned int od_fb;
unsigned int pll_m;
unsigned int pll_n;
@@ -42,11 +43,9 @@ struct lcd_clk_config_s { /* unit: kHz */
unsigned int pll_frac;
unsigned int pll_fout;
unsigned int ss_level;
unsigned int edp_div0;
unsigned int edp_div1;
unsigned int div_pre; /* m6, m8, m8b */
unsigned int div_post; /* m6, m8, m8b */
unsigned int div_sel; /* g9tv, g9bb, gxbb */
/*unsigned int edp_div0;*/
/*unsigned int edp_div1;*/
unsigned int div_sel;
unsigned int xd;
/* clk path node parameters */
@@ -57,9 +56,7 @@ struct lcd_clk_config_s { /* unit: kHz */
unsigned int pll_n_min;
unsigned int pll_frac_range;
unsigned int pll_od_sel_max;
unsigned int div_pre_sel_max; /* m6, m8, m8b */
unsigned int div_post_sel_max; /* m6, m8, m8b */
unsigned int div_sel_max; /* g9tv, g9bb, gxbb */
unsigned int div_sel_max;
unsigned int xd_max;
unsigned int pll_ref_fmax;
unsigned int pll_ref_fmin;
@@ -67,12 +64,10 @@ struct lcd_clk_config_s { /* unit: kHz */
unsigned int pll_vco_fmin;
unsigned int pll_out_fmax;
unsigned int pll_out_fmin;
unsigned int div_post_out_fmax; /* m6, m8, m8b */
unsigned int div_in_fmax; /* g9tv, g9bb, gxbb */
unsigned int div_out_fmax; /* g9tv, g9bb, gxbb */
unsigned int div_in_fmax;
unsigned int div_out_fmax;
unsigned int xd_out_fmax;
unsigned int err_fmin;
unsigned int pll_mode;
};
/* **********************************
@@ -134,7 +129,6 @@ enum div_sel_e {
#define LCD_PLL_OD1_GXTVBB 16
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_GXTVBB 0
#define SS_LEVEL_MAX_GXTVBB 5
#define PLL_M_MIN_GXTVBB 2
@@ -170,7 +164,6 @@ enum div_sel_e {
#define LCD_PLL_OD1_GXL 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_GXL 1
#define SS_LEVEL_MAX_GXL 5
#define PLL_M_MIN_GXL 2
@@ -206,7 +199,6 @@ enum div_sel_e {
#define LCD_PLL_OD1_GXM 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_GXM 1
#define SS_LEVEL_MAX_GXM 5
#define PLL_M_MIN_GXM 2
@@ -242,8 +234,7 @@ enum div_sel_e {
#define LCD_PLL_OD1_TXL 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_TXL 1
#define PLL_FRAC_OD_FB_TXL 1 /* update od_fb to 1 for ss width */
#define SS_LEVEL_MAX_TXL 5
#define PLL_M_MIN_TXL 2
#define PLL_M_MAX_TXL 511
@@ -278,7 +269,6 @@ enum div_sel_e {
#define LCD_PLL_OD1_TXLX 21
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_TXLX 0
#define SS_LEVEL_MAX_TXLX 6
#define PLL_M_MIN_TXLX 2
@@ -311,7 +301,6 @@ enum div_sel_e {
#define LCD_PLL_M_AXG 0
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_AXG 0
#define SS_LEVEL_MAX_AXG 5
#define PLL_M_MIN_AXG 2
@@ -331,35 +320,56 @@ enum div_sel_e {
/* G12A */
/* ******** register bit ******** */
/* PLL_CNTL */
#define LCD_PLL_LOCK_G12A 31
#define LCD_PLL_EN_G12A 28
#define LCD_PLL_RST_G12A 29
#define LCD_PLL_OD_G12A 16
#define LCD_PLL_N_G12A 10
#define LCD_PLL_M_G12A 0
/* PLL_CNTL bit: GP0 */
#define LCD_PLL_LOCK_GP0_G12A 31
#define LCD_PLL_EN_GP0_G12A 28
#define LCD_PLL_RST_GP0_G12A 29
#define LCD_PLL_OD_GP0_G12A 16
#define LCD_PLL_N_GP0_G12A 10
#define LCD_PLL_M_GP0_G12A 0
/* ******** frequency limit (unit: kHz) ******** */
/* pll */
#define PLL_FRAC_OD_FB_G12A 0
#define SS_LEVEL_MAX_G12A 5
#define PLL_M_MIN_G12A 2
#define PLL_M_MAX_G12A 511
#define PLL_N_MIN_G12A 1
#define PLL_N_MAX_G12A 1
#define PLL_FRAC_RANGE_G12A (1 << 17)
#define PLL_OD_SEL_MAX_G12A 5
#define PLL_FREF_MIN_G12A (5 * 1000)
#define PLL_FREF_MAX_G12A (25 * 1000)
#define PLL_VCO_MIN_G12A (3000 * 1000)
#define PLL_VCO_MAX_G12A (6000 * 1000)
#define PLL_FRAC_OD_FB_GP0_G12A 0
#define SS_LEVEL_MAX_GP0_G12A 1
#define PLL_FRAC_RANGE_GP0_G12A (1 << 17)
#define PLL_OD_SEL_MAX_GP0_G12A 5
#define PLL_VCO_MIN_GP0_G12A (3000 * 1000)
#define PLL_VCO_MAX_GP0_G12A (6000 * 1000)
/* PLL_CNTL bit: hpll */
#define LCD_PLL_LOCK_HPLL_G12A 31
#define LCD_PLL_EN_HPLL_G12A 28
#define LCD_PLL_RST_HPLL_G12A 29
#define LCD_PLL_N_HPLL_G12A 10
#define LCD_PLL_M_HPLL_G12A 0
#define LCD_PLL_OD3_HPLL_G12A 20
#define LCD_PLL_OD2_HPLL_G12A 18
#define LCD_PLL_OD1_HPLL_G12A 16
/* ******** frequency limit (unit: kHz) ******** */
#define PLL_FRAC_OD_FB_HPLL_G12A 0
#define SS_LEVEL_MAX_HPLL_G12A 1
#define PLL_FRAC_RANGE_HPLL_G12A (1 << 17)
#define PLL_OD_SEL_MAX_HPLL_G12A 3
#define PLL_VCO_MIN_HPLL_G12A (3000 * 1000)
#define PLL_VCO_MAX_HPLL_G12A (6000 * 1000)
/* video */
#define CRT_VID_CLK_IN_MAX_G12A (6000 * 1000)
#define ENCL_CLK_IN_MAX_G12A (200 * 1000)
#define PLL_M_MIN_G12A 2
#define PLL_M_MAX_G12A 511
#define PLL_N_MIN_G12A 1
#define PLL_N_MAX_G12A 1
#define PLL_FREF_MIN_G12A (5 * 1000)
#define PLL_FREF_MAX_G12A (25 * 1000)
#define CRT_VID_CLK_IN_MAX_G12A (6000 * 1000)
#define ENCL_CLK_IN_MAX_G12A (200 * 1000)
/* ******** api ******** */
extern int meson_clk_measure(unsigned int clk_mux);
extern struct lcd_clk_config_s *get_lcd_clk_config(void);
extern int lcd_clk_path_change(int sel);
extern void lcd_clk_config_print(void);
extern int lcd_encl_clk_msr(void);
extern void lcd_pll_reset(void);

View File

@@ -25,7 +25,8 @@
/* 20170505: add a113 support to linux4.9 */
/* 20170905: fix coverity errors */
/* 20180122: support txlx, optimize lcd noitfier event */
#define LCD_DRV_VERSION "20180122"
/* 20180226: g12a support */
#define LCD_DRV_VERSION "20180226"
#define VPP_OUT_SATURATE (1 << 0)

View File

@@ -462,13 +462,12 @@ static unsigned int lcd_reg_dump_clk_axg[] = {
HHI_GP0_PLL_CNTL4_AXG,
HHI_GP0_PLL_CNTL5_AXG,
HHI_GP0_PLL_CNTL1_AXG,
HHI_VID_PLL_CLK_DIV,
HHI_VIID_CLK_DIV,
HHI_VIID_CLK_CNTL,
HHI_VID_CLK_CNTL2,
};
static unsigned int lcd_reg_dump_clk_g12a[] = {
static unsigned int lcd_reg_dump_clk_gp0_g12a[] = {
HHI_GP0_PLL_CNTL0_G12A,
HHI_GP0_PLL_CNTL1_G12A,
HHI_GP0_PLL_CNTL2_G12A,
@@ -476,10 +475,25 @@ static unsigned int lcd_reg_dump_clk_g12a[] = {
HHI_GP0_PLL_CNTL4_G12A,
HHI_GP0_PLL_CNTL5_G12A,
HHI_GP0_PLL_CNTL6_G12A,
HHI_VIID_CLK_DIV,
HHI_VIID_CLK_CNTL,
HHI_VID_CLK_CNTL2,
HHI_MIPIDSI_PHY_CLK_CNTL,
};
static unsigned int lcd_reg_dump_clk_hpll_g12a[] = {
HHI_HDMI_PLL_CNTL,
HHI_HDMI_PLL_CNTL2,
HHI_HDMI_PLL_CNTL3,
HHI_HDMI_PLL_CNTL4,
HHI_HDMI_PLL_CNTL5,
HHI_HDMI_PLL_CNTL6,
HHI_HDMI_PLL_CNTL7,
HHI_VID_PLL_CLK_DIV,
HHI_VIID_CLK_DIV,
HHI_VIID_CLK_CNTL,
HHI_VID_CLK_CNTL2,
HHI_MIPIDSI_PHY_CLK_CNTL,
};
static unsigned int lcd_reg_dump_encl[] = {
@@ -822,19 +836,33 @@ static int lcd_reg_print(char *buf, int offset)
}
break;
case LCD_CHIP_G12A:
for (i = 0; i < ARRAY_SIZE(lcd_reg_dump_clk_g12a); i++) {
n = lcd_debug_info_len(len + offset);
len += snprintf((buf+len), n,
"hiu [0x%04x] = 0x%08x\n",
lcd_reg_dump_clk_g12a[i],
lcd_hiu_read(lcd_reg_dump_clk_g12a[i]));
if (lcd_drv->lcd_clk_path) {
for (i = 0; i < ARRAY_SIZE(lcd_reg_dump_clk_gp0_g12a);
i++) {
n = lcd_debug_info_len(len + offset);
len += snprintf((buf+len), n,
"hiu [0x%04x] = 0x%08x\n",
lcd_reg_dump_clk_gp0_g12a[i],
lcd_hiu_read(
lcd_reg_dump_clk_gp0_g12a[i]));
}
} else {
for (i = 0; i < ARRAY_SIZE(lcd_reg_dump_clk_hpll_g12a);
i++) {
n = lcd_debug_info_len(len + offset);
len += snprintf((buf+len), n,
"hiu [0x%04x] = 0x%08x\n",
lcd_reg_dump_clk_hpll_g12a[i],
lcd_hiu_read(
lcd_reg_dump_clk_hpll_g12a[i]));
}
}
break;
default:
for (i = 0; i < ARRAY_SIZE(lcd_reg_dump_clk); i++) {
n = lcd_debug_info_len(len + offset);
len += snprintf((buf+len), n,
"hiu [0x%04x] = 0x%08x\n",
"hiu [0x%04x] = 0x%08x\n",
lcd_reg_dump_clk[i],
lcd_hiu_read(lcd_reg_dump_clk[i]));
}
@@ -1717,6 +1745,45 @@ static ssize_t lcd_debug_clk_show(struct class *class,
return sprintf(buf, "\n");
}
static ssize_t lcd_debug_clk_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
int ret = 0;
unsigned int temp = 0;
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
switch (buf[0]) {
case 'p':
ret = sscanf(buf, "path %d", &temp);
if (ret == 1) {
ret = lcd_clk_path_change(temp);
if (ret) {
pr_info("change clk_path error\n");
} else {
lcd_clk_generate_parameter(lcd_drv->lcd_config);
pr_info("change clk_path: %d\n", temp);
}
} else {
pr_info("invalid data\n");
return -EINVAL;
}
break;
default:
pr_info("wrong command\n");
break;
}
return count;
}
static ssize_t lcd_debug_test_show(struct class *class,
struct class_attribute *attr, char *buf)
{
struct aml_lcd_drv_s *lcd_drv = aml_lcd_get_driver();
return sprintf(buf, "test pattern: %d\n", lcd_drv->lcd_test_flag);
}
static ssize_t lcd_debug_test_store(struct class *class,
struct class_attribute *attr, const char *buf, size_t count)
{
@@ -2202,8 +2269,8 @@ static struct class_attribute lcd_debug_class_attrs[] = {
__ATTR(fr_policy, 0644,
lcd_debug_fr_policy_show, lcd_debug_fr_policy_store),
__ATTR(ss, 0644, lcd_debug_ss_show, lcd_debug_ss_store),
__ATTR(clk, 0444, lcd_debug_clk_show, NULL),
__ATTR(test, 0200, NULL, lcd_debug_test_store),
__ATTR(clk, 0644, lcd_debug_clk_show, lcd_debug_clk_store),
__ATTR(test, 0644, lcd_debug_test_show, lcd_debug_test_store),
__ATTR(mute, 0644, lcd_debug_mute_show, lcd_debug_mute_store),
__ATTR(reg, 0200, NULL, lcd_debug_reg_store),
__ATTR(dither, 0644,

View File

@@ -133,6 +133,8 @@
#define HHI_HDMI_PLL_CNTL4 0xcb
#define HHI_HDMI_PLL_CNTL5 0xcc
#define HHI_HDMI_PLL_CNTL6 0xcd
/*G12A*/
#define HHI_HDMI_PLL_CNTL7 0xce
#define HHI_DSI_LVDS_EDP_CNTL0 0xd1
#define HHI_DSI_LVDS_EDP_CNTL1 0xd2

View File

@@ -427,8 +427,6 @@ static void lcd_tablet_vinfo_update(void)
vinfo->video_clk = pconf->lcd_timing.lcd_clk;
vinfo->htotal = pconf->lcd_basic.h_period;
vinfo->vtotal = pconf->lcd_basic.v_period;
vinfo->viu_color_fmt = COLOR_FMT_RGB444;
vinfo->viu_mux = VIU_MUX_ENCL;
lcd_hdr_vinfo_update();
}
@@ -468,8 +466,6 @@ static void lcd_tablet_vinfo_update_default(void)
vinfo->video_clk = 0;
vinfo->htotal = h_total;
vinfo->vtotal = v_total;
vinfo->viu_color_fmt = COLOR_FMT_RGB444;
vinfo->viu_mux = VIU_MUX_ENCL;
}
}

View File

@@ -411,13 +411,30 @@ static void mipi_dcs_set(int trans_type, int req_ack, int tear_en)
* Check the status of the dphy: phylock and stopstateclklane,
* to decide if the DPHY is ready
*/
#define DPHY_TIMEOUT 200000
static void check_phy_status(void)
{
while (dsi_host_getb(MIPI_DSI_DWC_PHY_STATUS_OS, BIT_PHY_LOCK, 1) == 0)
int i = 0;
while (dsi_host_getb(MIPI_DSI_DWC_PHY_STATUS_OS,
BIT_PHY_LOCK, 1) == 0) {
if (i++ >= DPHY_TIMEOUT) {
LCDERR("%s: phy_lock timeout\n", __func__);
break;
}
udelay(6);
}
i = 0;
udelay(10);
while (dsi_host_getb(MIPI_DSI_DWC_PHY_STATUS_OS,
BIT_PHY_STOPSTATECLKLANE, 1) == 0) {
LCDPR(" Waiting STOP STATE LANE\n");
if (i == 0)
LCDPR(" Waiting STOP STATE LANE\n");
if (i++ >= DPHY_TIMEOUT) {
LCDERR("%s: lane_state timeout\n", __func__);
break;
}
udelay(6);
}
}

View File

@@ -639,8 +639,6 @@ static void lcd_vinfo_update_default(void)
vinfo->video_clk = 0;
vinfo->htotal = h_total;
vinfo->vtotal = v_total;
vinfo->viu_color_fmt = COLOR_FMT_RGB444;
vinfo->viu_mux = VIU_MUX_ENCL;
}
}

View File

@@ -200,6 +200,7 @@ static struct vinfo_s lcd_vinfo = {
.name = "panel",
.mode = VMODE_LCD,
.viu_color_fmt = COLOR_FMT_RGB444,
.viu_mux = VIU_MUX_ENCL,
.vout_device = NULL,
};
@@ -751,18 +752,20 @@ static int lcd_mode_probe(struct device *dev)
return 0;
}
static int lcd_mode_remove(struct device *dev)
static int lcd_config_remove(struct device *dev)
{
lcd_notifier_unregister();
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
lcd_tv_vout_server_remove();
lcd_tv_remove(dev);
break;
#endif
#ifdef CONFIG_AMLOGIC_LCD_TABLET
case LCD_MODE_TABLET:
lcd_tablet_vout_server_remove();
lcd_tablet_remove(dev);
break;
#endif
@@ -770,6 +773,9 @@ static int lcd_mode_remove(struct device *dev)
LCDPR("invalid lcd mode\n");
break;
}
lcd_clk_config_remove();
return 0;
}
@@ -856,6 +862,16 @@ static int lcd_config_probe(struct platform_device *pdev)
LCDPR("detect mode: %s, fr_auto_policy: %d, key_valid: %d\n",
str, lcd_driver->fr_auto_policy, lcd_driver->lcd_key_valid);
ret = of_property_read_u32(lcd_driver->dev->of_node, "clk_path", &val);
if (ret) {
if (lcd_debug_print_flag)
LCDPR("failed to get clk_path\n");
lcd_driver->lcd_clk_path = 0;
} else {
lcd_driver->lcd_clk_path = (unsigned char)val;
LCDPR("detect lcd_clk_path: %d\n", lcd_driver->lcd_clk_path);
}
lcd_driver->lcd_info = &lcd_vinfo;
lcd_driver->lcd_config = &lcd_config_dft;
lcd_driver->lcd_test_flag = 0;
@@ -866,6 +882,7 @@ static int lcd_config_probe(struct platform_device *pdev)
IORESOURCE_IRQ, 0);
lcd_driver->res_vx1_irq = platform_get_resource(pdev,
IORESOURCE_IRQ, 1);
lcd_clk_config_probe();
lcd_config_default();
lcd_init_vout();
@@ -1004,7 +1021,6 @@ static int lcd_probe(struct platform_device *pdev)
INIT_WORK(&(lcd_driver->lcd_resume_work), lcd_resume_work);
lcd_ioremap(pdev);
lcd_clk_config_probe();
ret = lcd_config_probe(pdev);
LCDPR("%s %s\n", __func__, (ret ? "failed" : "ok"));
@@ -1013,33 +1029,15 @@ static int lcd_probe(struct platform_device *pdev)
static int lcd_remove(struct platform_device *pdev)
{
int ret;
ret = cancel_delayed_work(&lcd_driver->lcd_probe_delayed_work);
cancel_delayed_work(&lcd_driver->lcd_probe_delayed_work);
if (lcd_driver->workqueue)
destroy_workqueue(lcd_driver->workqueue);
if (lcd_driver) {
switch (lcd_driver->lcd_mode) {
#ifdef CONFIG_AMLOGIC_LCD_TV
case LCD_MODE_TV:
lcd_tv_vout_server_remove();
break;
#endif
#ifdef CONFIG_AMLOGIC_LCD_TABLET
case LCD_MODE_TABLET:
lcd_tablet_vout_server_remove();
break;
#endif
default:
break;
}
lcd_fops_remove();
lcd_class_remove();
lcd_clk_config_remove();
lcd_config_remove(lcd_driver->dev);
lcd_mode_remove(lcd_driver->dev);
kfree(lcd_driver);
lcd_driver = NULL;
}

View File

@@ -49,14 +49,12 @@ extern unsigned char lcd_debug_print_flag;
/* ******** div_ctrl ******** */
#define DIV_CTRL_EDP_DIV1 24 /* [26:24] */
#define DIV_CTRL_EDP_DIV0 20 /* [23:20] */
#define DIV_CTRL_DIV_POST 12 /* [14:12] */
#define DIV_CTRL_DIV_PRE 8 /* [10:8] */
#define DIV_CTRL_DIV_SEL 8 /* [15:8] */
#define DIV_CTRL_XD 0 /* [7:0] */
/* ******** clk_ctrl ******** */
#define CLK_CTRL_LEVEL 12 /* [14:12] */
#define CLK_CTRL_FRAC 0 /* [11:0] */
#define CLK_CTRL_LEVEL 28 /* [30:28] */
#define CLK_CTRL_FRAC 0 /* [18:0] */
/* **********************************
* VENC to TCON sync delay
@@ -394,6 +392,7 @@ struct aml_lcd_drv_s {
unsigned char lcd_mode;
unsigned char lcd_status;
unsigned char lcd_key_valid;
unsigned char lcd_clk_path; /* 0=hpll, 1=gp0_pll */
unsigned char lcd_config_load;
unsigned char lcd_test_flag;
unsigned char lcd_resume_type; /* 0=directly, 1=workqueue */