diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c index 0dc5f7ba6d0b..e44405593e66 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.c +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.c @@ -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; diff --git a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h index 9a01bb43ea00..4de842e6abce 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_clk_config.h +++ b/drivers/amlogic/media/vout/lcd/lcd_clk_config.h @@ -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); diff --git a/drivers/amlogic/media/vout/lcd/lcd_common.h b/drivers/amlogic/media/vout/lcd/lcd_common.h index fbf1140fcde1..f024c3c5b19a 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_common.h +++ b/drivers/amlogic/media/vout/lcd/lcd_common.h @@ -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) diff --git a/drivers/amlogic/media/vout/lcd/lcd_debug.c b/drivers/amlogic/media/vout/lcd/lcd_debug.c index 5c7142d3f0b7..e2212ac1911e 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_debug.c +++ b/drivers/amlogic/media/vout/lcd/lcd_debug.c @@ -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, diff --git a/drivers/amlogic/media/vout/lcd/lcd_reg.h b/drivers/amlogic/media/vout/lcd/lcd_reg.h index 0936f01d3e07..cf1612e847c3 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_reg.h +++ b/drivers/amlogic/media/vout/lcd/lcd_reg.h @@ -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 diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c index f516cfc9758f..be574e3ab28b 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/lcd_tablet.c @@ -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; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c index 0b5f5c40422a..520bf3df62bf 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tablet/mipi_dsi_util.c @@ -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); } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c index e01bf71c4763..aaeda21e61c5 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c +++ b/drivers/amlogic/media/vout/lcd/lcd_tv/lcd_tv.c @@ -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; } } diff --git a/drivers/amlogic/media/vout/lcd/lcd_vout.c b/drivers/amlogic/media/vout/lcd/lcd_vout.c index d6f3bd536066..4ea46dfb62de 100644 --- a/drivers/amlogic/media/vout/lcd/lcd_vout.c +++ b/drivers/amlogic/media/vout/lcd/lcd_vout.c @@ -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; } diff --git a/include/linux/amlogic/media/vout/lcd/lcd_vout.h b/include/linux/amlogic/media/vout/lcd/lcd_vout.h index 7520be140d74..8fb5e88662b7 100644 --- a/include/linux/amlogic/media/vout/lcd/lcd_vout.h +++ b/include/linux/amlogic/media/vout/lcd/lcd_vout.h @@ -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 */