summaryrefslogtreecommitdiff
authorEvoke 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)
commit036f8451c0614265d3511965d1867584c3627647 (patch)
tree106229c9c9c670a0e9ef93eb87b90aaa4be90df1
parent52f85f097210274b43056b25f92329797d86d2ba (diff)
downloadcommon-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>
Diffstat
-rw-r--r--drivers/amlogic/media/vout/cvbs/cvbs_out.c160
-rw-r--r--drivers/amlogic/media/vout/cvbs/cvbs_out.h3
-rw-r--r--drivers/amlogic/media/vout/vdac/vdac_config.c10
-rw-r--r--drivers/amlogic/media/vout/vdac/vdac_dev.c80
-rw-r--r--include/linux/amlogic/media/vout/vdac_dev.h2
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