author | Evoke Zhang <evoke.zhang@amlogic.com> | 2020-05-11 10:50:02 (GMT) |
---|---|---|
committer | Shen Liu <shen.liu@amlogic.com> | 2020-05-27 06:07:12 (GMT) |
commit | 036f8451c0614265d3511965d1867584c3627647 (patch) | |
tree | 106229c9c9c670a0e9ef93eb87b90aaa4be90df1 | |
parent | 52f85f097210274b43056b25f92329797d86d2ba (diff) | |
download | common-036f8451c0614265d3511965d1867584c3627647.zip common-036f8451c0614265d3511965d1867584c3627647.tar.gz common-036f8451c0614265d3511965d1867584c3627647.tar.bz2 |
vdac: optimize vdac control for cvbsout [2/2]
PD#SWPL-25744
Problem:
vdac control logic for cvbs is not very clear
Solution:
optimize vdac control for cvbsout
Verify:
ab311, ac232
Change-Id: Id4ed83986ed81142dc6cc33879019068cc745947
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
-rw-r--r-- | drivers/amlogic/media/vout/cvbs/cvbs_out.c | 160 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/cvbs/cvbs_out.h | 3 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/vdac/vdac_config.c | 10 | ||||
-rw-r--r-- | drivers/amlogic/media/vout/vdac/vdac_dev.c | 80 | ||||
-rw-r--r-- | include/linux/amlogic/media/vout/vdac_dev.h | 2 |
5 files changed, 181 insertions, 74 deletions
diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.c b/drivers/amlogic/media/vout/cvbs/cvbs_out.c index 068a170..d10c56b 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.c +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.c @@ -138,8 +138,7 @@ unsigned int cvbs_clk_path; static struct cvbs_drv_s *cvbs_drv; static enum cvbs_mode_e local_cvbs_mode; -static unsigned int vdac_cfg_valid; -static unsigned int vdac_cfg_value; +static unsigned int vdac_gsw_config; static DEFINE_MUTEX(setmode_mutex); static DEFINE_MUTEX(CC_mutex); @@ -169,9 +168,9 @@ int cvbs_cpu_type(void) } EXPORT_SYMBOL(cvbs_cpu_type); -static unsigned int cvbs_get_trimming_version(unsigned int flag) +static unsigned char cvbs_get_trimming_version(unsigned int flag) { - unsigned int version = 0xff; + unsigned char version = 0xff; if ((flag & 0xf0) == 0xa0) version = 5; @@ -184,41 +183,38 @@ static unsigned int cvbs_get_trimming_version(unsigned int flag) return version; } -static void cvbs_config_vdac(unsigned int flag, unsigned int cfg) +static unsigned int cvbs_config_vdac(unsigned int value) { unsigned char version = 0; + unsigned int cfg_valid, gsw_cfg; - vdac_cfg_value = cfg & 0x7; - version = cvbs_get_trimming_version(flag); + version = cvbs_get_trimming_version((value >> 8) & 0xff); /* flag 1/0 for validity of vdac config */ - if ((version == 1) || (version == 2) || (version == 5)) - vdac_cfg_valid = 1; - else - vdac_cfg_valid = 0; - cvbs_log_info("cvbs trimming.%d.v%d: 0x%x, 0x%x\n", - vdac_cfg_valid, version, flag, cfg); + if ((version == 1) || (version == 2) || (version == 5)) { + cfg_valid = 1; + gsw_cfg = value & 0x7; + } else { + cfg_valid = 0; + gsw_cfg = 0xffff; + } + if (cfg_valid) { + cvbs_log_info("%s: cvbs trimming 0x%x: %d.v%d, 0x%x\n", + __func__, value, cfg_valid, version, gsw_cfg); + } + + return gsw_cfg; } static void cvbs_cntl_output(unsigned int open) { - unsigned int cntl0 = 0, cntl1 = 0; - if (open == 0) { /* close */ - cntl0 = 0; - cntl1 = 8; - vdac_set_ctrl0_ctrl1(cntl0, cntl1); - - /* must enable adc bandgap, the adc ref signal for demod */ vdac_enable(0, VDAC_MODULE_CVBS_OUT); } else if (open == 1) { /* open */ - cntl0 = cvbs_drv->cvbs_data->cntl0_val; - cntl1 = (vdac_cfg_valid == 0) ? 0 : vdac_cfg_value; - vdac_set_ctrl0_ctrl1(cntl0, cntl1); - - /*vdac ctrl for cvbsout/rf signal,adc bandgap*/ + vdac_vref_adj(cvbs_drv->cvbs_data->vdac_vref_adj); + vdac_gsw_adj(cvbs_drv->cvbs_data->vdac_gsw); vdac_enable(1, VDAC_MODULE_CVBS_OUT); } - cvbs_log_info("%s: %d: 0x%x, 0x%x\n", __func__, open, cntl0, cntl1); + cvbs_log_info("%s: %d\n", __func__, open); } #ifdef CONFIG_CVBS_PERFORMANCE_COMPATIBILITY_SUPPORT @@ -963,6 +959,8 @@ enum { /*1:gp0 pll path1*/ CMD_VP_SET_PLLPATH, + CMD_VDAC, + CMD_HELP, CMD_MAX @@ -1009,34 +1007,36 @@ static void cvbs_debug_store(char *buf) argv[argc] = para; } - if (!strcmp(argv[0], "r")) + if (!strcmp(argv[0], "r")) { cmd = CMD_REG_READ; - else if (!strcmp(argv[0], "rb")) + } else if (!strcmp(argv[0], "rb")) { cmd = CMD_REG_READ_BITS; - else if (!strcmp(argv[0], "dump")) + } else if (!strcmp(argv[0], "dump")) { cmd = CMD_REG_DUMP; - else if (!strcmp(argv[0], "w")) + } else if (!strcmp(argv[0], "w")) { cmd = CMD_REG_WRITE; - else if (!strcmp(argv[0], "wb")) + } else if (!strcmp(argv[0], "wb")) { cmd = CMD_REG_WRITE_BITS; - else if (!strncmp(argv[0], "clkdump", strlen("clkdump"))) + } else if (!strncmp(argv[0], "clkdump", strlen("clkdump"))) { cmd = CMD_CLK_DUMP; - else if (!strncmp(argv[0], "clkmsr", strlen("clkmsr"))) + } else if (!strncmp(argv[0], "clkmsr", strlen("clkmsr"))) { cmd = CMD_CLK_MSR; - else if (!strncmp(argv[0], "bist", strlen("bist"))) + } else if (!strncmp(argv[0], "bist", strlen("bist"))) { cmd = CMD_BIST; - else if (!strncmp(argv[0], "vpset", strlen("vpset"))) + } else if (!strncmp(argv[0], "vpset", strlen("vpset"))) { cmd = CMD_VP_SET; - else if (!strncmp(argv[0], "vpget", strlen("vpget"))) + } else if (!strncmp(argv[0], "vpget", strlen("vpget"))) { cmd = CMD_VP_GET; - else if (!strncmp(argv[0], "vpconf", strlen("vpconf"))) + } else if (!strncmp(argv[0], "vpconf", strlen("vpconf"))) { cmd = CMD_VP_CONFIG_DUMP; - else if ((!strncmp(argv[0], "set_clkpath", strlen("set_clkpath"))) || - (!strncmp(argv[0], "clkpath", strlen("clkpath")))) + } else if ((!strncmp(argv[0], "set_clkpath", strlen("set_clkpath"))) || + (!strncmp(argv[0], "clkpath", strlen("clkpath")))) { cmd = CMD_VP_SET_PLLPATH; - else if (!strncmp(argv[0], "help", strlen("help"))) + } else if (!strncmp(argv[0], "vdac", strlen("vdac"))) { + cmd = CMD_VDAC; + } else if (!strncmp(argv[0], "help", strlen("help"))) { cmd = CMD_HELP; - else if (!strncmp(argv[0], "cvbs_ver", strlen("cvbs_ver"))) { + } else if (!strncmp(argv[0], "cvbs_ver", strlen("cvbs_ver"))) { pr_info("cvbsout version : %s\n", CVBSOUT_VER); goto DEBUG_END; } else { @@ -1212,6 +1212,20 @@ static void cvbs_debug_store(char *buf) pr_info("bit[1]: 0=vid2_clk, 1=vid1_clk\n"); break; + case CMD_VDAC: + if (argc != 2) { + pr_info("[%s] vdac state: %d\n", + __func__, + (cvbs_drv->flag & CVBS_FLAG_EN_VDAC) ? 1 : 0); + goto DEBUG_END; + } + ret = kstrtoul(argv[1], 10, &value); + if (value) + cvbs_cntl_output(1); + else + cvbs_cntl_output(0); + + break; case CMD_HELP: pr_info("command format:\n" "\tr c/h/v address_hex\n" @@ -1300,6 +1314,30 @@ static void cvbsout_get_config(struct device *dev) struct reg_s *s = NULL; const char *str; + /*clk path*/ + /*bit[0]: 0=vid_pll, 1=gp0_pll*/ + /*bit[1]: 0=vid2_clk, 1=vid_clk*/ + ret = of_property_read_u32(dev->of_node, "clk_path", &val); + if (!ret) { + if (val > 0x3) { + cvbs_log_err("error: invalid clk_path\n"); + } else { + cvbs_clk_path = val; + cvbs_log_info("clk path:0x%x\n", cvbs_clk_path); + } + } + + /* vdac config */ + ret = of_property_read_u32(dev->of_node, "vdac_config", + &vdac_gsw_config); + if (cvbs_drv->cvbs_data) { + if (vdac_gsw_config) { + val = cvbs_config_vdac(vdac_gsw_config); + if (val < 0xff) + cvbs_drv->cvbs_data->vdac_gsw = val; + } + } + /* performance: PAL */ cvbs_drv->perf_conf_pal.reg_cnt = 0; cvbs_drv->perf_conf_pal.reg_table = NULL; @@ -1394,27 +1432,6 @@ static void cvbsout_get_config(struct device *dev) i++; } } - - /*clk path*/ - /*bit[0]: 0=vid_pll, 1=gp0_pll*/ - /*bit[1]: 0=vid2_clk, 1=vid_clk*/ - ret = of_property_read_u32(dev->of_node, "clk_path", &val); - if (!ret) { - if (val > 0x3) { - cvbs_log_err("error: invalid clk_path\n"); - } else { - cvbs_clk_path = val; - cvbs_log_info("clk path:0x%x\n", cvbs_clk_path); - } - } - - /* vdac config */ - ret = of_property_read_u32(dev->of_node, "vdac_config", &val); - if (!ret) { - cvbs_config_vdac((val & 0xff00) >> 8, val & 0xff); - cvbs_log_info("find vdac_config: 0x%x\n", val); - } - } static void cvbsout_clktree_probe(struct device *dev) @@ -1451,31 +1468,36 @@ static void cvbsout_clktree_remove(struct device *dev) #ifdef CONFIG_OF struct meson_cvbsout_data meson_gxl_cvbsout_data = { - .cntl0_val = 0xb0001, + .vdac_vref_adj = 0xb, + .vdac_gsw = 0x0, .cpu_id = CVBS_CPU_TYPE_GXL, .name = "meson-gxl-cvbsout", }; struct meson_cvbsout_data meson_gxm_cvbsout_data = { - .cntl0_val = 0xb0001, + .vdac_vref_adj = 0xb, + .vdac_gsw = 0x0, .cpu_id = CVBS_CPU_TYPE_GXM, .name = "meson-gxm-cvbsout", }; struct meson_cvbsout_data meson_txlx_cvbsout_data = { - .cntl0_val = 0x620001, + .vdac_vref_adj = 0x2, + .vdac_gsw = 0x0, .cpu_id = CVBS_CPU_TYPE_TXLX, .name = "meson-txlx-cvbsout", }; struct meson_cvbsout_data meson_g12a_cvbsout_data = { - .cntl0_val = 0x906001, + .vdac_vref_adj = 0x10, + .vdac_gsw = 0x0, .cpu_id = CVBS_CPU_TYPE_G12A, .name = "meson-g12a-cvbsout", }; struct meson_cvbsout_data meson_g12b_cvbsout_data = { - .cntl0_val = 0x8f6001, + .vdac_vref_adj = 0xf, + .vdac_gsw = 0x0, .cpu_id = CVBS_CPU_TYPE_G12B, .name = "meson-g12b-cvbsout", }; @@ -1612,12 +1634,10 @@ static __exit void cvbs_exit_module(void) static int __init vdac_config_bootargs_setup(char *line) { - unsigned long cfg = 0x0; int ret = 0; cvbs_log_info("cvbs trimming line = %s\n", line); - ret = kstrtoul(line, 16, (unsigned long *)&cfg); - cvbs_config_vdac((cfg & 0xff00) >> 8, cfg & 0xff); + ret = kstrtouint(line, 16, &vdac_gsw_config); return 1; } diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.h b/drivers/amlogic/media/vout/cvbs/cvbs_out.h index d62179e..34dafeb 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.h +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.h @@ -52,7 +52,8 @@ enum cvbs_cpu_type { }; struct meson_cvbsout_data { - unsigned int cntl0_val; + unsigned int vdac_vref_adj; + unsigned int vdac_gsw; enum cvbs_cpu_type cpu_id; const char *name; }; diff --git a/drivers/amlogic/media/vout/vdac/vdac_config.c b/drivers/amlogic/media/vout/vdac/vdac_config.c index 76b254c..4abdea6 100644 --- a/drivers/amlogic/media/vout/vdac/vdac_config.c +++ b/drivers/amlogic/media/vout/vdac/vdac_config.c @@ -23,6 +23,8 @@ static struct meson_vdac_ctrl_s vdac_ctrl_enable_gxl[] = { {HHI_VDAC_CNTL0, 0, 9, 1}, {HHI_VDAC_CNTL0, 1, 10, 1}, {HHI_VDAC_CNTL0, 1, 0, 1}, + {HHI_VDAC_CNTL0, 0, 16, 5}, /* vref adj */ + {HHI_VDAC_CNTL1, 0, 0, 3}, /*gsw */ {HHI_VDAC_CNTL1, 0, 3, 1}, {VDAC_REG_MAX, 0, 0, 0}, }; @@ -31,6 +33,8 @@ static struct meson_vdac_ctrl_s vdac_ctrl_enable_txl[] = { {HHI_VDAC_CNTL0, 1, 9, 1}, {HHI_VDAC_CNTL0, 1, 10, 1}, {HHI_VDAC_CNTL0, 1, 0, 1}, + {HHI_VDAC_CNTL0, 0, 16, 5}, /* vref adj */ + {HHI_VDAC_CNTL1, 0, 0, 3}, /*gsw */ {HHI_VDAC_CNTL1, 1, 3, 1}, {VDAC_REG_MAX, 0, 0, 0}, }; @@ -40,6 +44,8 @@ static struct meson_vdac_ctrl_s vdac_ctrl_enable_txlx[] = { {HHI_VDAC_CNTL0, 1, 10, 1}, {HHI_VDAC_CNTL0, 1, 0, 1}, {HHI_VDAC_CNTL0, 0, 13, 1}, /* bandgap */ + {HHI_VDAC_CNTL0, 0, 16, 5}, /* vref adj */ + {HHI_VDAC_CNTL1, 0, 0, 3}, /*gsw */ {HHI_VDAC_CNTL1, 1, 3, 1}, {VDAC_REG_MAX, 0, 0, 0}, }; @@ -47,6 +53,8 @@ static struct meson_vdac_ctrl_s vdac_ctrl_enable_txlx[] = { static struct meson_vdac_ctrl_s vdac_ctrl_enable_g12ab[] = { {HHI_VDAC_CNTL0_G12A, 0, 9, 1}, {HHI_VDAC_CNTL0_G12A, 1, 0, 1}, + {HHI_VDAC_CNTL0_G12A, 0, 16, 5}, /* vref adj */ + {HHI_VDAC_CNTL1_G12A, 0, 0, 3}, /*gsw */ {HHI_VDAC_CNTL1_G12A, 0, 3, 1}, {VDAC_REG_MAX, 0, 0, 0}, }; @@ -56,6 +64,8 @@ static struct meson_vdac_ctrl_s vdac_ctrl_enable_tl1[] = { {HHI_VDAC_CNTL0_G12A, 1, 0, 1}, {HHI_VDAC_CNTL1_G12A, 0, 3, 1}, {HHI_VDAC_CNTL1_G12A, 0, 7, 1}, /* bandgap */ + {HHI_VDAC_CNTL0_G12A, 0, 16, 5}, /* vref adj */ + {HHI_VDAC_CNTL1_G12A, 0, 0, 3}, /*gsw */ {HHI_VDAC_CNTL1_G12A, 1, 6, 1}, /* bypass avout */ {HHI_VDAC_CNTL1_G12A, 1, 8, 1}, /* bypass avout */ {VDAC_REG_MAX, 0, 0, 0}, diff --git a/drivers/amlogic/media/vout/vdac/vdac_dev.c b/drivers/amlogic/media/vout/vdac/vdac_dev.c index 7523556..613c500 100644 --- a/drivers/amlogic/media/vout/vdac/vdac_dev.c +++ b/drivers/amlogic/media/vout/vdac/vdac_dev.c @@ -276,6 +276,10 @@ static void vdac_enable_cvbs_out(bool on) unsigned int reg_cntl1 = s_vdac_data->reg_cntl1; if (on) { + if (s_vdac_data->cpu_id <= VDAC_CPU_GXLX) + vdac_hiu_reg_setb(reg_cntl0, 0, 12, 4); + else + vdac_hiu_reg_setb(reg_cntl0, 0x6, 12, 4); vdac_ctrl_config(1, reg_cntl1, 3); vdac_ctrl_config(1, reg_cntl0, 0); vdac_ctrl_config(1, reg_cntl0, 9); @@ -420,8 +424,8 @@ void vdac_enable(bool on, unsigned int module_sel) } break; default: - pr_err("%s:module_sel: 0x%x wrong module index !! " - , __func__, module_sel); + pr_err("%s:module_sel: 0x%x wrong module index !! ", + __func__, module_sel); break; } @@ -440,7 +444,7 @@ void vdac_enable(bool on, unsigned int module_sel) } EXPORT_SYMBOL(vdac_enable); -void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1) +static void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1) { unsigned int reg_cntl0; unsigned int reg_cntl1; @@ -463,6 +467,76 @@ void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1) } } +int vdac_vref_adj(unsigned int value) +{ + struct meson_vdac_ctrl_s *table; + unsigned int reg; + unsigned int bit = 16; + int i = 0; + int ret = -1; + + if (!s_vdac_data) { + pr_err("\n%s: s_vdac_data NULL\n", __func__); + return ret; + } + + table = s_vdac_data->ctrl_table; + reg = s_vdac_data->reg_cntl0; + + while (i < VDAC_CTRL_MAX) { + if (table[i].reg == VDAC_REG_MAX) + break; + if ((table[i].reg == reg) && (table[i].bit == bit)) { + vdac_hiu_reg_setb(reg, value, bit, table[i].len); + if (vdac_debug_print) { + pr_info("vdac: %s: reg=0x%x set bit%d=0x%x, readback=0x%08x\n", + __func__, reg, bit, value, + vdac_hiu_reg_read(reg)); + } + ret = 0; + break; + } + i++; + } + + return ret; +} + +int vdac_gsw_adj(unsigned int value) +{ + struct meson_vdac_ctrl_s *table; + unsigned int reg; + unsigned int bit = 0; + int i = 0; + int ret = -1; + + if (!s_vdac_data) { + pr_err("\n%s: s_vdac_data NULL\n", __func__); + return ret; + } + + table = s_vdac_data->ctrl_table; + reg = s_vdac_data->reg_cntl1; + + while (i < VDAC_CTRL_MAX) { + if (table[i].reg == VDAC_REG_MAX) + break; + if ((table[i].reg == reg) && (table[i].bit == bit)) { + vdac_hiu_reg_setb(reg, value, bit, table[i].len); + if (vdac_debug_print) { + pr_info("vdac: %s: reg=0x%x set bit%d=0x%x, readback=0x%08x\n", + __func__, reg, bit, value, + vdac_hiu_reg_read(reg)); + } + ret = 0; + break; + } + i++; + } + + return ret; +} + unsigned int vdac_get_reg_addr(unsigned int index) { unsigned int reg; diff --git a/include/linux/amlogic/media/vout/vdac_dev.h b/include/linux/amlogic/media/vout/vdac_dev.h index f5d326b..e878371 100644 --- a/include/linux/amlogic/media/vout/vdac_dev.h +++ b/include/linux/amlogic/media/vout/vdac_dev.h @@ -29,6 +29,8 @@ void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1); void vdac_enable(bool on, unsigned int module_sel); int vdac_enable_check_dtv(void); int vdac_enable_check_cvbs(void); +int vdac_vref_adj(unsigned int value); +int vdac_gsw_adj(unsigned int value); unsigned int vdac_get_reg_addr(unsigned int index); #endif |