vdac: optimize the vdac controlling [1/1]
authorEvoke Zhang <evoke.zhang@amlogic.com>
Mon, 22 Jul 2019 10:27:14 +0000 (18:27 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Thu, 17 Oct 2019 02:29:23 +0000 (19:29 -0700)
PD#SWPL-8385

Problem:
no cvbsout on ab311

Solution:
1.optimize the vdac controlling
2.enable cvbsout in ab311 dts

Verify:
ab311

Change-Id: Ib046e760eca1c9ad3ae30749c546aff538504b33
Signed-off-by: Evoke Zhang <evoke.zhang@amlogic.com>
25 files changed:
MAINTAINERS
arch/arm/boot/dts/amlogic/tm2_t962e2_ab311.dts
arch/arm/boot/dts/amlogic/txlx_t962e_r321.dts
arch/arm64/boot/dts/amlogic/tm2_t962e2_ab311.dts
arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts
drivers/amlogic/atv_demod/atv_demod_ops.c
drivers/amlogic/media/dtv_demod/amlfrontend.c
drivers/amlogic/media/dtv_demod/include/amlfrontend.h
drivers/amlogic/media/dtv_demod/include/depend.h
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h
drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe.h
drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c
drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h
drivers/amlogic/media/vout/cvbs/cvbs_out.c
drivers/amlogic/media/vout/cvbs/cvbs_out_reg.h
drivers/amlogic/media/vout/cvbs/enc_clk_config.c
drivers/amlogic/media/vout/vdac/Makefile
drivers/amlogic/media/vout/vdac/vdac_config.c [new file with mode: 0644]
drivers/amlogic/media/vout/vdac/vdac_dev.c
drivers/amlogic/media/vout/vdac/vdac_dev.h [new file with mode: 0644]
include/linux/amlogic/media/vout/vdac_dev.h

index a3b5855..db338ff 100644 (file)
@@ -15103,6 +15103,11 @@ F:     arch/arm64/configs/meson64_a64_defconfig
 F:     arch/arm/boot/dts/amlogic/Makefile
 F:     arch/arm64/boot/dts/amlogic/Makefile
 
+AMLOGIC VDAC
+M:      Evoke Zhang <evoke.zhang@amlogic.com>
+F:      drivers/amlogic/media/vout/vdac/vdac_dev.h
+F:     drivers/amlogic/media/vout/vdac/vdac_config.c
+
 AMLOGIC DRM
 M:     Dezhi Kong <dezhi.kong@amlogic.com>
 F:     arch/arm/boot/dts/amlogic/mesonsm1_drm.dtsi
index 2428ec7..09c5711 100644 (file)
 
        cvbsout {
                compatible = "amlogic, cvbsout-tm2";
-               status = "disabled";
+               status = "okay";
                clocks = <&clkc CLKID_VCLK2_ENCI
                        &clkc CLKID_VCLK2_VENCI0
                        &clkc CLKID_VCLK2_VENCI1
index 9603ac4..a8b1a98 100644 (file)
        cvbsout {
                compatible = "amlogic, cvbsout-txlx";
                dev_name = "cvbsout";
-               status = "disabled";
+               status = "okay";
                clocks = <&clkc CLKID_VCLK2_ENCI
                        &clkc CLKID_VCLK2_VENCI0
                        &clkc CLKID_VCLK2_VENCI1
index 6d16810..38a4e0e 100644 (file)
 
        cvbsout {
                compatible = "amlogic, cvbsout-tm2";
-               status = "disabled";
+               status = "okay";
                clocks = <&clkc CLKID_VCLK2_ENCI
                        &clkc CLKID_VCLK2_VENCI0
                        &clkc CLKID_VCLK2_VENCI1
index 2f16a18..78d6437 100644 (file)
        cvbsout {
                compatible = "amlogic, cvbsout-txlx";
                dev_name = "cvbsout";
-               status = "disabled";
+               status = "okay";
                clocks = <&clkc CLKID_VCLK2_ENCI
                        &clkc CLKID_VCLK2_VENCI0
                        &clkc CLKID_VCLK2_VENCI1
index 27175cd..2b566f7 100644 (file)
@@ -20,6 +20,7 @@
 #include <uapi/linux/dvb/frontend.h>
 
 #include <linux/amlogic/aml_atvdemod.h>
+#include <linux/amlogic/media/vout/vdac_dev.h>
 
 #include "drivers/media/tuners/tuner-i2c.h"
 #include "drivers/media/dvb-core/dvb_frontend.h"
@@ -149,7 +150,7 @@ int atv_demod_enter_mode(struct dvb_frontend *fe)
        }
 
        err_code = adc_set_pll_cntl(1, ADC_EN_ATV_DEMOD, NULL);
-       vdac_enable(1, 1);
+       vdac_enable(1, VDAC_MODULE_AVOUT_ATV);
        usleep_range(2000, 2100);
        atvdemod_clk_init();
        /* err_code = atvdemod_init(); */
@@ -201,7 +202,7 @@ int atv_demod_leave_mode(struct dvb_frontend *fe)
                amlatvdemod_devp->agc_pin = NULL;
        }
 
-       vdac_enable(0, 1);
+       vdac_enable(0, VDAC_MODULE_AVOUT_ATV);
        adc_set_pll_cntl(0, ADC_EN_ATV_DEMOD, NULL);
        if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || is_meson_tl1_cpu()
                        || is_meson_tm2_cpu())
index 6a279a6..c24cbf1 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/dma-contiguous.h>
 
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
+#include <linux/amlogic/media/vout/vdac_dev.h>
 
 
 MODULE_PARM_DESC(debug_aml, "\n\t\t Enable frontend debug information");
@@ -2998,7 +2999,7 @@ static bool enter_mode(enum aml_fe_n_mode_t mode)
 
        /*-------------------*/
        /* must enable the adc ref signal for demod, */
-       /*vdac_enable(1, 0x2);*/
+       /*vdac_enable(1, VDAC_MODULE_DTV_DEMOD);*/
        dtvdemod_vdac_enable(1);/*on*/
        dtvdd_devp->en_detect = 0;/**/
        dtvdd_devp->n_mode = mode;
@@ -3115,7 +3116,7 @@ static int leave_mode(enum aml_fe_n_mode_t mode)
        adc_set_pll_cntl(0, 0x8, NULL);
        demod_mode_para = UNKNOWN;
        /* should disable the adc ref signal for demod */
-       /*vdac_enable(0, 0x2);*/
+       /*vdac_enable(0, VDAC_MODULE_DTV_DEMOD);*/
        dtvdemod_vdac_enable(0);/*off*/
        dtvdemod_set_agc_pinmux(0);
        msleep(200);
@@ -3630,10 +3631,10 @@ static void dtvdemod_vdac_enable(bool on)
 {
        if (on) {
                vdac_clk_gate_ctrl(1);
-               vdac_enable(1, 0x02);
+               vdac_enable(1, VDAC_MODULE_DTV_DEMOD);
        } else {
                vdac_clk_gate_ctrl(0);
-               vdac_enable(0, 0x02);
+               vdac_enable(0, VDAC_MODULE_DTV_DEMOD);
        }
 }
 
index 3970aad..701532d 100644 (file)
@@ -285,7 +285,6 @@ extern struct amldtvdemod_device_s *dtvdd_devp;     /**/
 
 /*int M6_Demod_Dtmb_Init(struct aml_fe_dev *dev);*/
 int convert_snr(int in_snr);
-extern int vdac_enable_check_dtv(void);
 
 
 extern unsigned  int ats_thread_flg;
index c664860..038f2f2 100644 (file)
@@ -21,8 +21,6 @@
 #include <linux/device.h>      /**/
 
 
-extern void vdac_enable(bool on, unsigned int module_sel);
-
 /*dma_alloc_from_contiguous*/
 struct page *aml_dma_alloc_contiguous(struct device *dev, int count,
                                                unsigned int order);
index af5f20f..814f704 100644 (file)
@@ -50,6 +50,7 @@
 /*#include <linux/amlogic/amports/vframe_provider.h>*/
 /*#include <linux/amlogic/amports/vframe_receiver.h>*/
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
+#include <linux/amlogic/media/vout/vdac_dev.h>
 /*#include <linux/amlogic/amports/vframe.h>*/
 #include <linux/of_gpio.h>
 #ifdef CONFIG_AMLOGIC_LEGACY_EARLY_SUSPEND
@@ -312,7 +313,7 @@ int hdmirx_dec_open(struct tvin_frontend_s *fe, enum tvin_port_e port)
        devp->param.port = port;
 
        /* should enable the adc ref signal for audio pll */
-       /* vdac_enable(1, 0x10); */
+       /* vdac_enable(1, VDAC_MODULE_AUDIO_OUT); */
        hdmirx_open_port(port);
        rx.open_fg = 1;
        rx_pr("%s port:%x ok nosignal:%d\n", __func__, port, rx.no_signal);
@@ -371,7 +372,7 @@ void hdmirx_dec_close(struct tvin_frontend_s *fe)
         */
        /* For txl,also need to keep bandgap always on:SWPL-1224 */
        /* if (rx.chip_id == CHIP_ID_TXL) */
-               /* vdac_enable(0, 0x10); */
+               /* vdac_enable(0, VDAC_MODULE_AUDIO_OUT); */
        /* open_flage = 0; */
        rx.open_fg = 0;
        devp = container_of(fe, struct hdmirx_dev_s, frontend);
index 7d26172..148e4d8 100644 (file)
@@ -562,7 +562,6 @@ extern unsigned int *pd_fifo_buf;
 
 /* for other modules */
 extern int External_Mute(int mute_flag);
-extern void vdac_enable(bool on, unsigned int module_sel);
 extern int rx_is_hdcp22_support(void);
 extern int hdmirx_get_connect_info(void);
 #endif
index 3c6320a..f48b2fb 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
+#include <linux/amlogic/media/vout/vdac_dev.h>
 #include <linux/arm-smccc.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
@@ -2583,9 +2584,6 @@ void rx_aud_pll_ctl(bool en)
        if (rx.chip_id >= CHIP_ID_TL1) {
                if (en) {
                        /* AUD_CLK=N/CTS*TMDS_CLK */
-                       /* bandgap enable */
-                       wr_reg_hhi(HHI_VDAC_CNTL0, 0x906001);
-                       wr_reg_hhi(HHI_VDAC_CNTL1, 0x0);
                        wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x40001540);
                        #if 1
                        /* use mpll */
index d821e25..c4ce0c2 100644 (file)
@@ -148,6 +148,8 @@ static struct tvafe_user_param_s tvafe_user_param = {
 
        /*4 is the test result@20171101 on fluke-54200 and DVD*/
        .skip_vf_num = 4,
+
+       .avout_en = 1,
 };
 
 struct tvafe_user_param_s *tvafe_get_user_param(void)
index 466aa0f..452f687 100644 (file)
@@ -81,6 +81,7 @@ struct tvafe_user_param_s {
        unsigned int nostd_stable_cnt;
        unsigned int nostd_dmd_clp_step;
        unsigned int skip_vf_num;
+       unsigned int avout_en;
 };
 
 /* tvafe device structure */
index 57b29d7..f963af9 100644 (file)
@@ -209,6 +209,7 @@ static void tvafe_state(struct tvafe_dev_s *devp)
        tvafe_pr_info("skip_vf_num:%d\n", user_param->skip_vf_num);
        tvafe_pr_info("try_fmt_max_atv:%d\n", try_fmt_max_atv);
        tvafe_pr_info("try_fmt_max_av:%d\n", try_fmt_max_av);
+       tvafe_pr_info("avout_en:%d\n", user_param->avout_en);
        tvafe_pr_info("tvafe version :  %s\n", TVAFE_VER);
 }
 
@@ -462,6 +463,13 @@ static ssize_t tvafe_store(struct device *dev,
                        goto tvafe_store_err;
                pr_info("[tvafe..]%s: set try_fmt_max_av = %d\n",
                        __func__, try_fmt_max_av);
+       } else if (!strncmp(buff, "avout_en", strlen("avout_en"))) {
+               if (parm[1]) {
+                       if (kstrtouint(parm[1], 16, &user_param->avout_en) < 0)
+                               goto tvafe_store_err;
+               }
+               pr_info("[tvafe..]%s: avout_en = 0x%x\n",
+                       __func__, user_param->avout_en);
        } else if (!strncmp(buff, "dbg_print", strlen("dbg_print"))) {
                if (parm[1]) {
                        if (kstrtouint(parm[1], 16, &tvafe_dbg_print) < 0)
@@ -514,6 +522,8 @@ static const char *tvafe_debug_usage_str = {
 "\n"
 "    echo skip_vf_num val(d) > /sys/class/tvafe/tvafe0/debug;set skip_vf_num for vdin\n"
 "\n"
+"    echo avout_en val(d) > /sys/class/tvafe/tvafe0/debug;set avout\n"
+"\n"
 "    echo print val(h) > /sys/class/tvafe/tvafe0/debug;enable debug print\n"
 "    bit[0]: normal debug info\n"
 "    bit[4]: vsync isr debug info\n"
index deefc5f..61a48c0 100644 (file)
@@ -23,6 +23,7 @@
 /*#include <mach/am_regs.h>*/
 
 #include <linux/amlogic/media/frame_provider/tvin/tvin.h>
+#include <linux/amlogic/media/vout/vdac_dev.h>
 #include "../tvin_global.h"
 #include "../tvin_format_table.h"
 #include "tvafe.h"
@@ -554,7 +555,10 @@ void tvafe_set_ddemod_default(void)
                W_HIU_REG(HHI_DADC_CNTL3, 0x00082183);
 
                /*W_HIU_REG(HHI_VDAC_CNTL0, 0x00000200);*/
-               W_HIU_BIT(HHI_VDAC_CNTL0, 1, 9, 1);
+               /*W_HIU_BIT(HHI_VDAC_CNTL0, 1, 9, 1);*/
+               /* remove vdac reg write, make sure it write in vdac driver,
+                * because multi module use it
+                */
 
        } else if (tvafe_cpu_type() >= CPU_TYPE_TL1) {
                W_APB_REG(TVFE_VAFE_CTRL0, 0x000d0710);
@@ -566,7 +570,10 @@ void tvafe_set_ddemod_default(void)
                W_HIU_REG(HHI_DADC_CNTL3, 0x08300b83);
 
                //HHI_VDAC_CNTL1
-               W_HIU_REG(0xbc, 0x0);
+               /*W_HIU_REG(0xbc, 0x0);*/
+               /* remove vdac reg write, make sure it write in vdac driver,
+                * because multi module use it
+                */
        }
 
 }
@@ -580,23 +587,16 @@ void tvafe_enable_avout(enum tvin_port_e port, bool enable)
                if (enable) {
                        tvafe_clk_gate_ctrl(1);
                        if (port == TVIN_PORT_CVBS3) {
-                               vdac_enable(1, 0x1);
-                               /* clock delay control */
-                               W_HIU_BIT(HHI_VIID_CLK_DIV, 1, 19, 1);
-                               /* vdac_clock_mux form atv demod */
-                               W_HIU_BIT(HHI_VID_CLK_CNTL2, 1, 8, 1);
-                               W_HIU_BIT(HHI_VID_CLK_CNTL2, 1, 4, 1);
-                               /* vdac_clk gated clock control */
-                               W_VCBUS_BIT(VENC_VDAC_DACSEL0, 1, 5, 1);
+                               vdac_enable(1, VDAC_MODULE_AVOUT_ATV);
                        } else {
                                W_APB_REG(TVFE_ATV_DMD_CLP_CTRL, 0);
-                               vdac_enable(1, 0x4);
+                               vdac_enable(1, VDAC_MODULE_AVOUT_AV);
                        }
                } else {
                        if (port == TVIN_PORT_CVBS3)
-                               vdac_enable(0, 0x1);
+                               vdac_enable(0, VDAC_MODULE_AVOUT_ATV);
                        else
-                               vdac_enable(0, 0x4);
+                               vdac_enable(0, VDAC_MODULE_AVOUT_AV);
                        tvafe_clk_gate_ctrl(0);
                }
        }
@@ -967,14 +967,12 @@ EXPORT_SYMBOL(tvafe_adc_get_pll_flag);
 /*
  * tvafe init the whole module
  */
-static bool enableavout = true;
-module_param(enableavout, bool, 0644);
-MODULE_PARM_DESC(enableavout, "disable av out when load adc reg");
 void tvafe_init_reg(struct tvafe_cvd2_s *cvd2,
        struct tvafe_cvd2_mem_s *mem, enum tvin_port_e port,
        struct tvafe_pin_mux_s *pinmux)
 {
        unsigned int module_sel = ADC_EN_TVAFE;
+       struct tvafe_user_param_s *user_param = tvafe_get_user_param();
 
        if (port == TVIN_PORT_CVBS3)
                module_sel = ADC_EN_ATV_DEMOD;
@@ -1002,7 +1000,7 @@ void tvafe_init_reg(struct tvafe_cvd2_s *cvd2,
 
                tvafe_set_cvbs_default(cvd2, mem, port, pinmux);
                /*turn on/off av out*/
-               tvafe_enable_avout(port, enableavout);
+               tvafe_enable_avout(port, user_param->avout_en);
                /* CDAC_CTRL_RESV2<1>=0 */
        }
 
index 4110b2b..2b4111a 100644 (file)
@@ -195,9 +195,6 @@ extern void tvafe_set_apb_bus_err_ctrl(void);
 extern void tvafe_enable_module(bool enable);
 extern void tvafe_enable_avout(enum tvin_port_e port, bool enable);
 
-/* vdac ctrl,adc/dac ref signal,cvbs out signal*/
-/* module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8*/
-void vdac_enable(bool on, unsigned int module_sel);
 extern void adc_set_pll_reset(void);
 extern int tvafe_adc_get_pll_flag(void);
 extern int tvafe_cpu_type(void);
index 23c1454..4c5e3de 100644 (file)
@@ -249,7 +249,7 @@ static void cvbs_cntl_output(unsigned int open)
                vdac_set_ctrl0_ctrl1(cntl0, cntl1);
 
                /* must enable adc bandgap, the adc ref signal for demod */
-               vdac_enable(0, 0x8);
+               vdac_enable(0, VDAC_MODULE_CVBS_OUT);
        } else if (open == 1) { /* open */
 
                cntl0 = info->cvbs_data->cntl0_val;
@@ -259,7 +259,7 @@ static void cvbs_cntl_output(unsigned int open)
                vdac_set_ctrl0_ctrl1(cntl0, cntl1);
 
                /*vdac ctrl for cvbsout/rf signal,adc bandgap*/
-               vdac_enable(1, 0x8);
+               vdac_enable(1, VDAC_MODULE_CVBS_OUT);
        }
 }
 
index 268d7dc..d4ec568 100644 (file)
 #define HHI_DIF_CSI_PHY_CNTL5                      0xdd
 #define HHI_LVDS_TX_PHY_CNTL0                      0xde
 #define HHI_LVDS_TX_PHY_CNTL1                      0xdf
+#define HHI_LVDS_TX_PHY_CNTL0_TL1                  0x9a
+#define HHI_LVDS_TX_PHY_CNTL1_TL1                  0x9b
 #define HHI_VID2_PLL_CNTL                          0xe0
 #define HHI_VID2_PLL_CNTL2                         0xe1
 #define HHI_VID2_PLL_CNTL3                         0xe2
index 1f1a029..615fb63 100644 (file)
@@ -105,6 +105,9 @@ static void cvbs_set_vid1_clk(unsigned int src_pll)
        /* vclk: 27M */
        /* [31:28]=0 enci_clk_sel, select vclk_div1 */
        cvbs_out_hiu_setb(HHI_VID_CLK_DIV, 0, 28, 4);
+       /* [31:28]=0 vdac_clk_sel, select vclk_div1 */
+       /* [19]=0 disable atv_demod clk for vdac */
+       cvbs_out_hiu_setb(HHI_VIID_CLK_DIV, 0, 19, 1);
        cvbs_out_hiu_setb(HHI_VIID_CLK_DIV, 0, 28, 4);
        /* release vclk_div_reset and enable vclk_div */
        cvbs_out_hiu_setb(HHI_VID_CLK_DIV, 1, VCLK_XD_EN, 2);
@@ -150,6 +153,9 @@ static void cvbs_set_vid2_clk(unsigned int src_pll)
        /* vclk: 27M */
        /* [31:28]=8 enci_clk_sel, select vclk2_div1 */
        cvbs_out_hiu_setb(HHI_VID_CLK_DIV, 8, 28, 4);
+       /* [31:28]=8 vdac_clk_sel, select vclk2_div1 */
+       /* [19]=0 disable atv_demod clk for vdac */
+       cvbs_out_hiu_setb(HHI_VIID_CLK_DIV, 0, 19, 1);
        cvbs_out_hiu_setb(HHI_VIID_CLK_DIV, 8, 28, 4);
        /* release vclk2_div_reset and enable vclk2_div */
        cvbs_out_hiu_setb(HHI_VIID_CLK_DIV, 1, VCLK2_XD_EN, 2);
@@ -214,8 +220,28 @@ void set_vmode_clk(void)
                }
                if (ret)
                        pr_info("[error]:hdmi_pll lock failed\n");
-       } else if (cvbs_cpu_type() == CVBS_CPU_TYPE_TL1 ||
-               cvbs_cpu_type() == CVBS_CPU_TYPE_TM2) {
+       } else if (cvbs_cpu_type() == CVBS_CPU_TYPE_TL1) {
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL0,  0x202f04f7);
+               udelay(100);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL0,  0x302f04f7);
+               udelay(100);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL1,  0x10110000);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL2,  0x00001108);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL3,  0x10051400);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL4,  0x010100c0);
+               udelay(100);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL4,  0x038300c0);
+               udelay(100);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL0,  0x342f04f7);
+               udelay(100);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL0,  0x142f04f7);
+               udelay(100);
+               cvbs_out_hiu_write(HHI_TCON_PLL_CNTL2,  0x00003008);
+               udelay(100);
+               ret = pll_wait_lock(HHI_TCON_PLL_CNTL0, 31);
+               if (ret)
+                       pr_info("[error]:tl1 tcon_pll lock failed\n");
+       } else if (cvbs_cpu_type() == CVBS_CPU_TYPE_TM2) {
                cvbs_out_hiu_write(HHI_TCON_PLL_CNTL0,  0x202f04f7);
                udelay(100);
                cvbs_out_hiu_write(HHI_TCON_PLL_CNTL0,  0x302f04f7);
@@ -236,6 +262,8 @@ void set_vmode_clk(void)
                ret = pll_wait_lock(HHI_TCON_PLL_CNTL0, 31);
                if (ret)
                        pr_info("[error]:tl1 tcon_pll lock failed\n");
+               /* mux tcon pll */
+               cvbs_out_hiu_setb(HHI_LVDS_TX_PHY_CNTL1_TL1, 0, 29, 1);
        } else {
                pr_info("config eqafter gxl hdmi pll\n");
                cvbs_out_hiu_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
index 752cf7f..438445c 100644 (file)
@@ -1,3 +1,3 @@
-obj-$(CONFIG_AMLOGIC_VDAC) += vdac_dev.o
+obj-$(CONFIG_AMLOGIC_VDAC) += vdac_dev.o vdac_config.o
 
 ccflags-y += -Idrivers/amlogic/display/
\ No newline at end of file
diff --git a/drivers/amlogic/media/vout/vdac/vdac_config.c b/drivers/amlogic/media/vout/vdac/vdac_config.c
new file mode 100644 (file)
index 0000000..be3a7e5
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * drivers/amlogic/media/vout/vdac/vdac_config.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include "vdac_dev.h"
+
+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_CNTL1, 0, 3, 1},
+       {VDAC_REG_MAX, 0, 0, 0},
+};
+
+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_CNTL1, 1, 3, 1},
+       {VDAC_REG_MAX, 0, 0, 0},
+};
+
+static struct meson_vdac_ctrl_s vdac_ctrl_enable_txlx[] = {
+       {HHI_VDAC_CNTL0, 1, 9, 1},
+       {HHI_VDAC_CNTL0, 1, 10, 1},
+       {HHI_VDAC_CNTL0, 1, 0, 1},
+       {HHI_VDAC_CNTL0, 0, 13, 1}, /* bandgap */
+       {HHI_VDAC_CNTL1, 1, 3, 1},
+       {VDAC_REG_MAX, 0, 0, 0},
+};
+
+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_CNTL1_G12A, 0, 3, 1},
+       {VDAC_REG_MAX, 0, 0, 0},
+};
+
+static struct meson_vdac_ctrl_s vdac_ctrl_enable_tl1[] = {
+       {HHI_VDAC_CNTL0_G12A, 0, 9, 1},
+       {HHI_VDAC_CNTL0_G12A, 1, 0, 1},
+       {HHI_VDAC_CNTL1_G12A, 0, 3, 1},
+       {HHI_VDAC_CNTL1_G12A, 0, 7, 1}, /* bandgap */
+       {HHI_VDAC_CNTL1_G12A, 1, 6, 1}, /* bypass avout */
+       {HHI_VDAC_CNTL1_G12A, 1, 8, 1}, /* bypass avout */
+       {VDAC_REG_MAX, 0, 0, 0},
+};
+
+/* ********************************************************* */
+static struct meson_vdac_data meson_gx_l_m_vdac_data = {
+       .cpu_id = VDAC_CPU_GX_L_M,
+       .name = "meson-gx_l_m-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0,
+       .reg_cntl1 = HHI_VDAC_CNTL1,
+       .ctrl_table = vdac_ctrl_enable_gxl,
+};
+
+static struct meson_vdac_data meson_txl_vdac_data = {
+       .cpu_id = VDAC_CPU_TXL,
+       .name = "meson-txl-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0,
+       .reg_cntl1 = HHI_VDAC_CNTL1,
+       .ctrl_table = vdac_ctrl_enable_txl,
+};
+
+static struct meson_vdac_data meson_txlx_vdac_data = {
+       .cpu_id = VDAC_CPU_TXLX,
+       .name = "meson-txlx-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0,
+       .reg_cntl1 = HHI_VDAC_CNTL1,
+       .ctrl_table = vdac_ctrl_enable_txlx,
+};
+
+static struct meson_vdac_data meson_gxlx_vdac_data = {
+       .cpu_id = VDAC_CPU_GXLX,
+       .name = "meson-gxlx-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0,
+       .reg_cntl1 = HHI_VDAC_CNTL1,
+       .ctrl_table = vdac_ctrl_enable_txl,
+};
+
+static struct meson_vdac_data meson_g12ab_vdac_data = {
+       .cpu_id = VDAC_CPU_G12AB,
+       .name = "meson-g12ab-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0_G12A,
+       .reg_cntl1 = HHI_VDAC_CNTL1_G12A,
+       .ctrl_table = vdac_ctrl_enable_g12ab,
+};
+
+static struct meson_vdac_data meson_tl1_vdac_data = {
+       .cpu_id = VDAC_CPU_TL1,
+       .name = "meson-tl1-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0_G12A,
+       .reg_cntl1 = HHI_VDAC_CNTL1_G12A,
+       .ctrl_table = vdac_ctrl_enable_tl1,
+};
+
+static struct meson_vdac_data meson_sm1_vdac_data = {
+       .cpu_id = VDAC_CPU_SM1,
+       .name = "meson-sm1-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0_G12A,
+       .reg_cntl1 = HHI_VDAC_CNTL1_G12A,
+       .ctrl_table = vdac_ctrl_enable_g12ab,
+};
+
+static struct meson_vdac_data meson_tm2_vdac_data = {
+       .cpu_id = VDAC_CPU_TM2,
+       .name = "meson-tm2-vdac",
+
+       .reg_cntl0 = HHI_VDAC_CNTL0_G12A,
+       .reg_cntl1 = HHI_VDAC_CNTL1_G12A,
+       .ctrl_table = vdac_ctrl_enable_tl1,
+};
+
+const struct of_device_id meson_vdac_dt_match[] = {
+       {
+               .compatible = "amlogic, vdac-gxl",
+               .data           = &meson_gx_l_m_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-gxm",
+               .data           = &meson_gx_l_m_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-txl",
+               .data           = &meson_txl_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-txlx",
+               .data           = &meson_txlx_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-gxlx",
+               .data           = &meson_gxlx_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-g12a",
+               .data           = &meson_g12ab_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-g12b",
+               .data           = &meson_g12ab_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-tl1",
+               .data           = &meson_tl1_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-sm1",
+               .data           = &meson_sm1_vdac_data,
+       }, {
+               .compatible = "amlogic, vdac-tm2",
+               .data           = &meson_tm2_vdac_data,
+       },
+       {}
+};
+
+struct meson_vdac_data *aml_vdac_config_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct meson_vdac_data *data;
+
+       match = of_match_device(meson_vdac_dt_match, &pdev->dev);
+       if (match == NULL) {
+               pr_err("%s, no matched table\n", __func__);
+               return NULL;
+       }
+       data = (struct meson_vdac_data *)match->data;
+       if (data) {
+               pr_info("%s: cpu_id:%d, name:%s\n", __func__,
+                       data->cpu_id, data->name);
+       }
+
+       return data;
+}
index 2c605bf..4b5b07a 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/amlogic/iomap.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include "vdac_dev.h"
 
 #define AMVDAC_NAME               "amvdac"
 #define AMVDAC_DRIVER_NAME        "amvdac"
@@ -56,310 +57,259 @@ static struct amvdac_dev_s amvdac_dev;
 static struct meson_vdac_data *s_vdac_data;
 static struct mutex vdac_mutex;
 
-#define HHI_VDAC_CNTL0 0xbd
-#define HHI_VDAC_CNTL1 0xbe
-#define HHI_VDAC_CNTL0_G12A 0xbb
-#define HHI_VDAC_CNTL1_G12A 0xbc
-
-#define VDAC_MODULE_ATV_DEMOD 0x1
-#define VDAC_MODULE_DTV_DEMOD 0x2
-#define VDAC_MODULE_TVAFE     0x4
-#define VDAC_MODULE_CVBS_OUT  0x8
-#define VDAC_MODULE_AUDIO_OUT  0x10
-
-static bool vdac_init_succ_flag;
-
 /* priority for module,
- * module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; cvbsout:0x8
+ * #define VDAC_MODULE_ATV_DEMOD (1 << 0)
+ * #define VDAC_MODULE_DTV_DEMOD (1 << 1)
+ * #define VDAC_MODULE_TVAFE     (1 << 2)
+ * #define VDAC_MODULE_CVBS_OUT  (1 << 3)
+ * #define VDAC_MODULE_AUDIO_OUT (1 << 4)
+ * #define VDAC_MODULE_AVOUT_ATV (1 << 5)
+ * #define VDAC_MODULE_AVOUT_AV  (1 << 6)
  */
 static unsigned int pri_flag;
 
-static unsigned int vdac_cntl0_bit9;
-module_param(vdac_cntl0_bit9, uint, 0644);
-MODULE_PARM_DESC(vdac_cntl0_bit9, "vdac_cntl0_bit9");
-
-static unsigned int vdac_cntl1_bit3;
-module_param(vdac_cntl1_bit3, uint, 0644);
-MODULE_PARM_DESC(vdac_cntl1_bit3, "vdac_cntl1_bit3");
+static unsigned int vdac_debug_print;
 
-static unsigned int vdac_cntl0_bit0;
-module_param(vdac_cntl0_bit0, uint, 0644);
-MODULE_PARM_DESC(vdac_cntl0_bit0, "vdac_cntl0_bit0");
-
-static unsigned int vdac_cntl0_bit10;
-module_param(vdac_cntl0_bit10, uint, 0644);
-MODULE_PARM_DESC(vdac_cntl0_bit10, "vdac_cntl0_bit10");
-
-static inline uint32_t vdac_hiu_reg_read(uint32_t reg)
+static inline unsigned int vdac_hiu_reg_read(unsigned int reg)
 {
        return aml_read_hiubus(reg);
 }
 
-static inline void vdac_hiu_reg_write(uint32_t reg, uint32_t val)
+static inline void vdac_hiu_reg_write(unsigned int reg, unsigned int val)
 {
-       return aml_write_hiubus(reg, val);
+       aml_write_hiubus(reg, val);
 }
 
-static inline void vdac_hiu_reg_setb(uint32_t reg,
-           const uint32_t value,
-           const uint32_t start,
-           const uint32_t len)
+static inline void vdac_hiu_reg_setb(unsigned int reg, unsigned int value,
+               unsigned int start, unsigned int len)
 {
-       aml_write_hiubus(reg, ((aml_read_hiubus(reg) &
+       vdac_hiu_reg_write(reg, ((vdac_hiu_reg_read(reg) &
                        ~(((1L << (len)) - 1) << (start))) |
                        (((value) & ((1L << (len)) - 1)) << (start))));
 }
 
-static inline uint32_t vdac_hiu_reg_getb(uint32_t reg,
-           const uint32_t start,
-           const uint32_t len)
+static inline unsigned int vdac_hiu_reg_getb(unsigned int reg,
+               unsigned int start, unsigned int len)
 {
-       uint32_t val;
+       unsigned int val;
 
        val = ((vdac_hiu_reg_read(reg) >> (start)) & ((1L << (len)) - 1));
 
        return val;
 }
 
-/* adc/dac ref signal,
- * module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8
- */
-void ana_ref_cntl0_bit9(bool on, unsigned int module_sel)
+static inline unsigned int vdac_vcbus_reg_read(unsigned int reg)
 {
-       bool enable = 0;
+       return aml_read_vcbus(reg);
+}
 
-       /*tl1:bandgap en, bc[7] default:0 opened*/
-       if (s_vdac_data->cpu_id == VDAC_CPU_TL1)
-               return;
+static inline void vdac_vcbus_reg_write(unsigned int reg, unsigned int val)
+{
+       aml_write_vcbus(reg, val);
+}
 
-       switch (module_sel & 0x1f) {
-       case VDAC_MODULE_ATV_DEMOD: /* dtv demod */
-               if (on)
-                       vdac_cntl0_bit9 |= VDAC_MODULE_ATV_DEMOD;
-               else
-                       vdac_cntl0_bit9 &= ~VDAC_MODULE_ATV_DEMOD;
-               break;
-       case VDAC_MODULE_DTV_DEMOD: /* atv demod */
-               if (on)
-                       vdac_cntl0_bit9 |= VDAC_MODULE_DTV_DEMOD;
-               else
-                       vdac_cntl0_bit9 &= ~VDAC_MODULE_DTV_DEMOD;
-               break;
-       case VDAC_MODULE_TVAFE: /* cvbs in demod */
-               if (on)
-                       vdac_cntl0_bit9 |= VDAC_MODULE_TVAFE;
-               else
-                       vdac_cntl0_bit9 &= ~VDAC_MODULE_TVAFE;
-               break;
-       case VDAC_MODULE_CVBS_OUT: /* cvbs in demod */
-               if (on)
-                       vdac_cntl0_bit9 |= VDAC_MODULE_CVBS_OUT;
-               else
-                       vdac_cntl0_bit9 &= ~VDAC_MODULE_CVBS_OUT;
-               break;
-       case VDAC_MODULE_AUDIO_OUT: /* audio out ctrl*/
-               if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
-                       s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
-                       if (on)
-                               vdac_cntl0_bit9 |= VDAC_MODULE_AUDIO_OUT;
-                       else
-                               vdac_cntl0_bit9 &= ~VDAC_MODULE_AUDIO_OUT;
-               }
-               break;
-       default:
-               pr_err("module_sel: 0x%x wrong module index !! ", module_sel);
-               break;
-       }
-       /* pr_info("\nvdac_cntl0_bit9: 0x%x\n", vdac_cntl0_bit9); */
+static inline void vdac_vcbus_reg_setb(unsigned int reg, unsigned int value,
+               unsigned int start, unsigned int len)
+{
+       vdac_vcbus_reg_write(reg, ((vdac_vcbus_reg_read(reg) &
+                       ~(((1L << (len)) - 1) << (start))) |
+                       (((value) & ((1L << (len)) - 1)) << (start))));
+}
 
-       if ((vdac_cntl0_bit9 & 0x1f) == 0)
-               enable = 0;
-       else
-               enable = 1;
+static inline unsigned int vdac_vcbus_reg_getb(unsigned int reg,
+               unsigned int start, unsigned int len)
+{
+       unsigned int val;
 
-       if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
-                       s_vdac_data->cpu_id == VDAC_CPU_TXLX)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, enable, 9, 1);
-       else if (s_vdac_data->cpu_id >= VDAC_CPU_G12AB)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL0_G12A, ~enable, 9, 1);
-       else
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, ~enable, 9, 1);
+       val = ((vdac_vcbus_reg_read(reg) >> (start)) & ((1L << (len)) - 1));
+
+       return val;
 }
-EXPORT_SYMBOL(ana_ref_cntl0_bit9);
 
-/*avin cvbsout signal,
- * module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8
- */
-void vdac_out_cntl0_bit10(bool on, unsigned int module_sel)
+static int vdac_ctrl_config(bool on, unsigned int reg, unsigned int bit)
 {
-       bool enable = 0;
-
-       /*bit10 is for bandgap startup setting in g12a*/
-       if (s_vdac_data->cpu_id >= VDAC_CPU_G12AB)
-               return;
+       struct meson_vdac_ctrl_s *table = s_vdac_data->ctrl_table;
+       unsigned int val;
+       int i = 0;
+       int ret = -1;
 
-       switch (module_sel & 0xf) {
-       case VDAC_MODULE_ATV_DEMOD: /* dtv demod */
-               if (on)
-                       vdac_cntl0_bit10 |= VDAC_MODULE_ATV_DEMOD;
-               else
-                       vdac_cntl0_bit10 &= ~VDAC_MODULE_ATV_DEMOD;
-               break;
-       case VDAC_MODULE_DTV_DEMOD: /* atv demod */
-               if (on)
-                       vdac_cntl0_bit10 |= VDAC_MODULE_DTV_DEMOD;
-               else
-                       vdac_cntl0_bit10 &= ~VDAC_MODULE_DTV_DEMOD;
-               break;
-       case VDAC_MODULE_TVAFE: /* av in demod */
-               if (on)
-                       vdac_cntl0_bit10 |= VDAC_MODULE_TVAFE;
-               else
-                       vdac_cntl0_bit10 &= ~VDAC_MODULE_TVAFE;
-               break;
-       case VDAC_MODULE_CVBS_OUT: /* cvbs out demod */
-               if (on)
-                       vdac_cntl0_bit10 |= VDAC_MODULE_CVBS_OUT;
-               else
-                       vdac_cntl0_bit10 &= ~VDAC_MODULE_CVBS_OUT;
-               break;
-       default:
-               pr_err("module_sel: 0x%x wrong module index !! ", module_sel);
-               break;
+       while (i < VDAC_CTRL_MAX) {
+               if (table[i].reg == VDAC_REG_MAX)
+                       break;
+               if ((table[i].reg == reg) && (table[i].bit == bit)) {
+                       if (on)
+                               val = table[i].val;
+                       else
+                               val = table[i].val ? 0 : 1;
+                       vdac_hiu_reg_setb(reg, val, bit, table[i].len);
+                       if (vdac_debug_print) {
+                               pr_info("vdac: reg=0x%02x set bit%d=%d, readback=0x%08x\n",
+                                       reg, bit, val, vdac_hiu_reg_read(reg));
+                       }
+                       ret = 0;
+                       break;
+               }
+               i++;
        }
-       /* pr_info("\vdac_cntl0_bit0: 0x%x\n", vdac_cntl1_bit3); */
 
-       if ((vdac_cntl0_bit10 & 0xf) == 0)
-               enable = 0;
-       else
-               enable = 1;
-
-       vdac_hiu_reg_setb(HHI_VDAC_CNTL0, enable, 10, 1);
+       return ret;
 }
-EXPORT_SYMBOL(vdac_out_cntl0_bit10);
 
-/*atv cvbsout signal,
- * module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8
- */
-void vdac_out_cntl0_bit0(bool on, unsigned int module_sel)
+static void vdac_enable_avout_atv(bool on)
 {
-       bool enable = 0;
+       unsigned int reg_cntl0 = s_vdac_data->reg_cntl0;
+       unsigned int reg_cntl1 = s_vdac_data->reg_cntl1;
+
+       if (on) {
+               /* clock delay control */
+               vdac_hiu_reg_setb(HHI_VIID_CLK_DIV, 1, 19, 1);
+               /* vdac_clock_mux form atv demod */
+               vdac_hiu_reg_setb(HHI_VID_CLK_CNTL2, 1, 8, 1);
+               vdac_hiu_reg_setb(HHI_VID_CLK_CNTL2, 1, 4, 1);
+               /* vdac_clk gated clock control */
+               vdac_vcbus_reg_setb(VENC_VDAC_DACSEL0, 1, 5, 1);
+
+               vdac_ctrl_config(1, reg_cntl0, 9);
+               /*after txlx need reset bandgap after bit9 enabled*/
+               /*bit10 reset bandgap in g12a*/
+               if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
+                       vdac_ctrl_config(0, reg_cntl0, 13);
+                       udelay(5);
+                       vdac_ctrl_config(1, reg_cntl0, 13);
+               }
 
-       switch (module_sel & 0xf) {
-       case VDAC_MODULE_ATV_DEMOD: /* dtv demod */
-               if (on)
-                       vdac_cntl0_bit0 |= VDAC_MODULE_ATV_DEMOD;
-               else
-                       vdac_cntl0_bit0 &= ~VDAC_MODULE_ATV_DEMOD;
-               break;
-       case VDAC_MODULE_DTV_DEMOD: /* atv demod */
-               if (on)
-                       vdac_cntl0_bit0 |= VDAC_MODULE_DTV_DEMOD;
-               else
-                       vdac_cntl0_bit0 &= ~VDAC_MODULE_DTV_DEMOD;
-               break;
-       case VDAC_MODULE_TVAFE: /* av in demod */
-               if (on)
-                       vdac_cntl0_bit0 |= VDAC_MODULE_TVAFE;
-               else
-                       vdac_cntl0_bit0 &= ~VDAC_MODULE_TVAFE;
-               break;
-       case VDAC_MODULE_CVBS_OUT: /* cvbs in demod */
-               if (on)
-                       vdac_cntl0_bit0 |= VDAC_MODULE_CVBS_OUT;
-               else
-                       vdac_cntl0_bit0 &= ~VDAC_MODULE_CVBS_OUT;
-               break;
-       default:
-               pr_err("module_sel: 0x%x wrong module index !! ", module_sel);
-               break;
-       }
-       /* pr_info("\vdac_cntl0_bit0: 0x%x\n", vdac_cntl1_bit3); */
+               /*Cdac pwd*/
+               vdac_ctrl_config(1, reg_cntl1, 3);
+               /* enable AFE output buffer */
+               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
+                       vdac_ctrl_config(0, reg_cntl0, 10);
+               vdac_ctrl_config(1, reg_cntl0, 0);
 
-       if ((vdac_cntl0_bit0 & 0xf) == 0)
-               enable = 0;
-       else
-               enable = 1;
 
-       if (s_vdac_data->cpu_id >= VDAC_CPU_G12AB)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL0_G12A, enable, 0, 1);
-       else
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, enable, 0, 1);
+       } else {
+               vdac_ctrl_config(0, reg_cntl0, 9);
+
+               vdac_ctrl_config(0, reg_cntl0, 0);
+               /* Disable AFE output buffer */
+               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
+                       vdac_ctrl_config(0, reg_cntl0, 10);
+               /* disable dac output */
+               vdac_ctrl_config(0, reg_cntl1, 3);
+
+               /* vdac_clk gated clock control */
+               vdac_vcbus_reg_setb(VENC_VDAC_DACSEL0, 0, 5, 1);
+               /* vdac_clock_mux form atv demod */
+               vdac_hiu_reg_setb(HHI_VID_CLK_CNTL2, 0, 4, 1);
+               vdac_hiu_reg_setb(HHI_VID_CLK_CNTL2, 0, 8, 1);
+               /* clock delay control */
+               vdac_hiu_reg_setb(HHI_VIID_CLK_DIV, 0, 19, 1);
+       }
 }
-EXPORT_SYMBOL(vdac_out_cntl0_bit0);
 
-/* dac out pwd ctl,
- * module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8
- */
-void vdac_out_cntl1_bit3(bool on, unsigned int module_sel)
+static void vdac_enable_dtv_demod(bool on)
 {
-       bool enable = 0;
-
-       switch (module_sel & 0xf) {
-       case VDAC_MODULE_ATV_DEMOD: /* atv demod */
-               if (on)
-                       vdac_cntl1_bit3 |= VDAC_MODULE_ATV_DEMOD;
-               else
-                       vdac_cntl1_bit3 &= ~VDAC_MODULE_ATV_DEMOD;
-               break;
-       case VDAC_MODULE_DTV_DEMOD: /* dtv demod */
-               if (on)
-                       vdac_cntl1_bit3 |= VDAC_MODULE_DTV_DEMOD;
-               else
-                       vdac_cntl1_bit3 &= ~VDAC_MODULE_DTV_DEMOD;
-               break;
-       case VDAC_MODULE_TVAFE: /* av in demod */
-               if (on)
-                       vdac_cntl1_bit3 |= VDAC_MODULE_TVAFE;
-               else
-                       vdac_cntl1_bit3 &= ~VDAC_MODULE_TVAFE;
-               break;
-       case VDAC_MODULE_CVBS_OUT: /* cvbs in demod */
-               if (on)
-                       vdac_cntl1_bit3 |= VDAC_MODULE_CVBS_OUT;
-               else
-                       vdac_cntl1_bit3 &= ~VDAC_MODULE_CVBS_OUT;
-               break;
-       default:
-               pr_err("module_sel: 0x%x wrong module index !! ", module_sel);
-               break;
+       unsigned int reg_cntl0 = s_vdac_data->reg_cntl0;
+       unsigned int reg_cntl1 = s_vdac_data->reg_cntl1;
+
+       if (on) {
+               vdac_ctrl_config(1, reg_cntl0, 9);
+               if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
+                       vdac_ctrl_config(0, reg_cntl0, 13);
+                       udelay(5);
+                       vdac_ctrl_config(1, reg_cntl0, 13);
+               }
+               vdac_ctrl_config(1, reg_cntl1, 3);
+               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
+                       vdac_ctrl_config(0, reg_cntl0, 10);
+               vdac_ctrl_config(1, reg_cntl0, 0);
+       } else {
+               vdac_ctrl_config(0, reg_cntl0, 9);
+               vdac_ctrl_config(0, reg_cntl1, 3);
        }
-       /* pr_info("\nvdac_cntl1_bit3: 0x%x\n", vdac_cntl1_bit3); */
+}
 
-       if ((vdac_cntl1_bit3 & 0xf) == 0)
-               enable = 0;
-       else
-               enable = 1;
+static void vdac_enable_avout_av(bool on)
+{
+       unsigned int reg_cntl0 = s_vdac_data->reg_cntl0;
+       unsigned int reg_cntl1 = s_vdac_data->reg_cntl1;
+
+       if (on) {
+               vdac_ctrl_config(1, reg_cntl0, 9);
+               /*txlx need reset bandgap after bit9 enabled*/
+               if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
+                       vdac_ctrl_config(0, reg_cntl0, 13);
+                       udelay(5);
+                       vdac_ctrl_config(1, reg_cntl0, 13);
+               }
 
-       if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
-                       s_vdac_data->cpu_id == VDAC_CPU_TXLX)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL1, enable, 3, 1);
-       else if (s_vdac_data->cpu_id >= VDAC_CPU_G12AB)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, ~enable, 3, 1);
-       else
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL1, ~enable, 3, 1);
+               vdac_ctrl_config(1, reg_cntl1, 3);
+               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
+                       vdac_ctrl_config(1, reg_cntl0, 10);
+               if (s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
+                       s_vdac_data->cpu_id == VDAC_CPU_TM2) {
+                       /*[6][8]bypass buffer enable*/
+                       vdac_ctrl_config(1, reg_cntl1, 6);
+                       vdac_ctrl_config(1, reg_cntl1, 8);
+               }
+       } else {
+               vdac_ctrl_config(0, reg_cntl0, 9);
+               if (s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
+                       s_vdac_data->cpu_id == VDAC_CPU_TM2) {
+                       /*[6][8]bypass buffer disable*/
+                       vdac_ctrl_config(0, reg_cntl1, 6);
+                       vdac_ctrl_config(0, reg_cntl1, 8);
+               }
+
+               /* Disable AFE output buffer */
+               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
+                       vdac_ctrl_config(0, reg_cntl0, 10);
+               /* disable dac output */
+               vdac_ctrl_config(0, reg_cntl1, 3);
+       }
 }
-EXPORT_SYMBOL(vdac_out_cntl1_bit3);
 
-void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1)
+static void vdac_enable_cvbs_out(bool on)
 {
-       if (!s_vdac_data) {
-               pr_err("\n%s: s_vdac_data NULL\n", __func__);
-               return;
-       }
-       if (s_vdac_data->cpu_id >= VDAC_CPU_G12AB) {
-               vdac_hiu_reg_write(HHI_VDAC_CNTL0_G12A, ctrl0);
-               vdac_hiu_reg_write(HHI_VDAC_CNTL1_G12A, ctrl1);
+       unsigned int reg_cntl0 = s_vdac_data->reg_cntl0;
+       unsigned int reg_cntl1 = s_vdac_data->reg_cntl1;
+
+       if (on) {
+               vdac_ctrl_config(1, reg_cntl1, 3);
+               vdac_ctrl_config(1, reg_cntl0, 0);
+               vdac_ctrl_config(1, reg_cntl0, 9);
+               if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
+                       vdac_ctrl_config(0, reg_cntl0, 13);
+                       udelay(5);
+                       vdac_ctrl_config(1, reg_cntl0, 13);
+               }
+               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
+                       vdac_ctrl_config(0, reg_cntl0, 10);
        } else {
-               vdac_hiu_reg_write(HHI_VDAC_CNTL0, ctrl0);
-               vdac_hiu_reg_write(HHI_VDAC_CNTL1, ctrl1);
+               vdac_ctrl_config(0, reg_cntl0, 9);
+               vdac_ctrl_config(0, reg_cntl0, 0);
+               vdac_ctrl_config(0, reg_cntl1, 3);
+       }
+}
+
+static void vdac_enable_audio_out(bool on)
+{
+       unsigned int reg_cntl0 = s_vdac_data->reg_cntl0;
+
+       /*Bandgap optimization*/
+       if (s_vdac_data->cpu_id == VDAC_CPU_TXLX)
+               vdac_hiu_reg_setb(reg_cntl0, 0xe, 3, 5);
+
+       if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
+               s_vdac_data->cpu_id == VDAC_CPU_TXLX ||
+               s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
+               s_vdac_data->cpu_id == VDAC_CPU_TM2) {
+               if (on)
+                       vdac_ctrl_config(1, reg_cntl0, 9);
+               else
+                       vdac_ctrl_config(0, reg_cntl0, 9);
        }
 }
-EXPORT_SYMBOL(vdac_set_ctrl0_ctrl1);
 
-/* dac ctl,
- * module index: atv demod:0x01; dtv demod:0x02; tvafe:0x4; dac:0x8
- */
 void vdac_enable(bool on, unsigned int module_sel)
 {
        if (!s_vdac_data) {
@@ -367,152 +317,104 @@ void vdac_enable(bool on, unsigned int module_sel)
                return;
        }
 
-       pr_info("\n%s: on:%d,module_sel:%x\n", __func__, on, module_sel);
+       pr_info("\n%s: %d, module_sel:0x%x, private_flag:0x%x\n",
+               __func__, on, module_sel, pri_flag);
 
        mutex_lock(&vdac_mutex);
        switch (module_sel) {
-       case VDAC_MODULE_ATV_DEMOD: /* atv demod */
-               if ((on && (pri_flag & VDAC_MODULE_ATV_DEMOD))
-                       || (!on && !(pri_flag & VDAC_MODULE_ATV_DEMOD))) {
-                       pr_info("%s: ATV DEMOD had done!:%d.\n", __func__, on);
-                       break;
-               }
-
+       case VDAC_MODULE_AVOUT_ATV: /* atv avout */
                if (on) {
-                       ana_ref_cntl0_bit9(1, VDAC_MODULE_ATV_DEMOD);
-                       /*after txlx need reset bandgap after bit9 enabled*/
-                       /*bit10 reset bandgap in g12a*/
-                       if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 1, 13, 1);
-                               udelay(5);
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0, 13, 1);
+                       if (pri_flag & VDAC_MODULE_AVOUT_ATV) {
+                               pr_info("%s: avout_atv is already on\n",
+                                       __func__);
+                               break;
                        }
-                       pri_flag &= ~VDAC_MODULE_TVAFE;
-                       pri_flag |= VDAC_MODULE_ATV_DEMOD;
-                       if (pri_flag & VDAC_MODULE_CVBS_OUT)
+                       pri_flag |= VDAC_MODULE_AVOUT_ATV;
+                       if (pri_flag & VDAC_MODULE_CVBS_OUT) {
+                               pr_info("%s: %d, bypass for cvbsout\n",
+                                       __func__, on);
                                break;
-                       /*Cdac pwd*/
-                       vdac_out_cntl1_bit3(1, VDAC_MODULE_ATV_DEMOD);
-                       /* enable AFE output buffer */
-                       if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0, 10, 1);
-                       vdac_out_cntl0_bit0(1, VDAC_MODULE_ATV_DEMOD);
+                       }
+                       vdac_enable_avout_atv(1);
                } else {
-                       ana_ref_cntl0_bit9(0, VDAC_MODULE_ATV_DEMOD);
-                       pri_flag &= ~VDAC_MODULE_ATV_DEMOD;
-                       if (pri_flag & VDAC_MODULE_CVBS_OUT)
+                       if (!(pri_flag & VDAC_MODULE_AVOUT_ATV)) {
+                               pr_info("%s: avout_atv is already off\n",
+                                       __func__);
+                               break;
+                       }
+                       pri_flag &= ~VDAC_MODULE_AVOUT_ATV;
+                       if (pri_flag & VDAC_MODULE_CVBS_OUT) {
+                               if (vdac_debug_print) {
+                                       pr_info("%s: %d, bypass for cvbsout\n",
+                                               __func__, on);
+                               }
                                break;
-                       vdac_out_cntl0_bit0(0, VDAC_MODULE_ATV_DEMOD);
-                       /* Disable AFE output buffer */
-                       if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0, 10, 1);
-                       /* enable dac output */
-                       vdac_out_cntl1_bit3(0, VDAC_MODULE_ATV_DEMOD);
+                       }
+                       vdac_enable_avout_atv(0);
                }
                break;
        case VDAC_MODULE_DTV_DEMOD: /* dtv demod */
                if (on) {
-                       if (s_vdac_data->cpu_id == VDAC_CPU_GXLX)
-                               vdac_out_cntl1_bit3(1, VDAC_MODULE_DTV_DEMOD);
-                       ana_ref_cntl0_bit9(1, VDAC_MODULE_DTV_DEMOD);
-                       if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 1, 13, 1);
-                               udelay(5);
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0, 13, 1);
-                       }
                        pri_flag |= VDAC_MODULE_DTV_DEMOD;
+                       vdac_enable_dtv_demod(1);
                } else {
-                       ana_ref_cntl0_bit9(0, VDAC_MODULE_DTV_DEMOD);
-                       if (s_vdac_data->cpu_id == VDAC_CPU_GXLX)
-                               vdac_out_cntl1_bit3(0, VDAC_MODULE_DTV_DEMOD);
                        pri_flag &= ~VDAC_MODULE_DTV_DEMOD;
+                       if (pri_flag & VDAC_MODULE_MASK)
+                               break;
+                       vdac_enable_dtv_demod(0);
                }
                break;
-       case VDAC_MODULE_TVAFE: /* av in demod */
+       case VDAC_MODULE_AVOUT_AV: /* avin avout */
                if (on) {
-                       ana_ref_cntl0_bit9(1, VDAC_MODULE_TVAFE);
-                       /*after txlx need reset bandgap after bit9 enabled*/
-                       if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 1, 13, 1);
-                               udelay(5);
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0, 13, 1);
-                       }
-                       pri_flag &= ~VDAC_MODULE_ATV_DEMOD;
-                       pri_flag |= VDAC_MODULE_TVAFE;
-                       if (pri_flag & VDAC_MODULE_CVBS_OUT)
+                       pri_flag |= VDAC_MODULE_AVOUT_AV;
+                       if (pri_flag & VDAC_MODULE_CVBS_OUT) {
+                               pr_info("%s: %d, bypass for cvbsout\n",
+                                       __func__, on);
                                break;
-                       vdac_out_cntl1_bit3(0, VDAC_MODULE_TVAFE);
-                       vdac_out_cntl0_bit10(1, VDAC_MODULE_TVAFE);
-                       if (s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
-                               s_vdac_data->cpu_id == VDAC_CPU_TM2) {
-                               /*[6][8]bypass buffer enable*/
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 1, 6, 1);
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 1, 8, 1);
                        }
+                       vdac_enable_avout_av(1);
                } else {
-                       ana_ref_cntl0_bit9(0, VDAC_MODULE_TVAFE);
-                       if (s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
-                               s_vdac_data->cpu_id == VDAC_CPU_TM2) {
-                               /*[6][8]bypass buffer disable*/
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 0, 6, 1);
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 0, 8, 1);
+                       pri_flag &= ~VDAC_MODULE_AVOUT_AV;
+                       if (pri_flag & VDAC_MODULE_CVBS_OUT) {
+                               if (vdac_debug_print) {
+                                       pr_info("%s: %d, bypass for cvbsout\n",
+                                               __func__, on);
+                               }
+                               break;
                        }
-                       pri_flag &= ~VDAC_MODULE_TVAFE;
-                       if (pri_flag & VDAC_MODULE_CVBS_OUT)
+                       if (pri_flag & VDAC_MODULE_MASK)
                                break;
-                       /* Disable AFE output buffer */
-                       vdac_out_cntl0_bit10(0, VDAC_MODULE_TVAFE);
-                       /* enable dac output */
-                       vdac_out_cntl1_bit3(0, VDAC_MODULE_TVAFE);
+                       vdac_enable_avout_av(0);
                }
                break;
-       case VDAC_MODULE_CVBS_OUT: /* cvbs in demod */
+       case VDAC_MODULE_CVBS_OUT:
                if (on) {
-                       vdac_out_cntl1_bit3(1, VDAC_MODULE_CVBS_OUT);
-                       vdac_out_cntl0_bit0(1, VDAC_MODULE_CVBS_OUT);
-                       ana_ref_cntl0_bit9(1, VDAC_MODULE_CVBS_OUT);
-                       if (s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 1, 13, 1);
-                               udelay(5);
-                               vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0, 13, 1);
-                       }
-                       vdac_out_cntl0_bit10(0, VDAC_MODULE_CVBS_OUT);
                        pri_flag |= VDAC_MODULE_CVBS_OUT;
+                       vdac_enable_cvbs_out(1);
                } else {
-                       /*vdac_out_cntl0_bit10(0, VDAC_MODULE_CVBS_OUT);*/
-                       ana_ref_cntl0_bit9(0, VDAC_MODULE_CVBS_OUT);
-                       vdac_out_cntl0_bit0(0, VDAC_MODULE_CVBS_OUT);
-                       vdac_out_cntl1_bit3(0, VDAC_MODULE_CVBS_OUT);
                        pri_flag &= ~VDAC_MODULE_CVBS_OUT;
-                       if (pri_flag & VDAC_MODULE_ATV_DEMOD) {
-                               vdac_out_cntl1_bit3(1, VDAC_MODULE_ATV_DEMOD);
-                               if (s_vdac_data->cpu_id < VDAC_CPU_G12AB)
-                                       vdac_hiu_reg_setb(HHI_VDAC_CNTL0,
-                                               0, 10, 1);
-                               vdac_out_cntl0_bit0(1, VDAC_MODULE_ATV_DEMOD);
-                       } else if (pri_flag & VDAC_MODULE_TVAFE) {
-                               vdac_out_cntl1_bit3(0, VDAC_MODULE_TVAFE);
-                               vdac_out_cntl0_bit10(1, VDAC_MODULE_TVAFE);
-                       } else if (pri_flag & VDAC_MODULE_DTV_DEMOD) {
-                               if (s_vdac_data->cpu_id == VDAC_CPU_GXLX)
-                                       vdac_out_cntl1_bit3(1,
-                                                       VDAC_MODULE_DTV_DEMOD);
-                               ana_ref_cntl0_bit9(1, VDAC_MODULE_DTV_DEMOD);
+                       if ((pri_flag & VDAC_MODULE_MASK) == 0) {
+                               vdac_enable_cvbs_out(0);
+                               break;
                        }
+
+                       if (pri_flag & VDAC_MODULE_AVOUT_ATV)
+                               vdac_enable_avout_atv(1);
+                       else if (pri_flag & VDAC_MODULE_AVOUT_AV)
+                               vdac_enable_avout_av(1);
+                       else if (pri_flag & VDAC_MODULE_DTV_DEMOD)
+                               vdac_enable_dtv_demod(1);
                }
                break;
        case VDAC_MODULE_AUDIO_OUT: /* audio demod */
-               /*Bandgap optimization*/
-               if (s_vdac_data->cpu_id == VDAC_CPU_TXHD ||
-                       s_vdac_data->cpu_id == VDAC_CPU_TXLX)
-                       vdac_hiu_reg_setb(HHI_VDAC_CNTL0, 0xe, 3, 5);
-
-               if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
-                       s_vdac_data->cpu_id == VDAC_CPU_TXLX) {
-                       if (on)
-                               ana_ref_cntl0_bit9(1, VDAC_MODULE_AUDIO_OUT);
-                       else
-                               ana_ref_cntl0_bit9(0, VDAC_MODULE_AUDIO_OUT);
+               if (on) {
+                       pri_flag |= VDAC_MODULE_AUDIO_OUT;
+                       vdac_enable_audio_out(1);
+               } else {
+                       pri_flag &= ~VDAC_MODULE_AUDIO_OUT;
+                       if (pri_flag & VDAC_MODULE_MASK)
+                               break;
+                       vdac_enable_audio_out(0);
                }
                break;
        default:
@@ -521,143 +423,222 @@ void vdac_enable(bool on, unsigned int module_sel)
                break;
        }
 
+       if (vdac_debug_print) {
+               pr_info("private_flag:             0x%02x\n"
+                       "reg_cntl0:                0x%02x=0x%08x\n"
+                       "reg_cntl1:                0x%02x=0x%08x\n",
+                       pri_flag,
+                       s_vdac_data->reg_cntl0,
+                       vdac_hiu_reg_read(s_vdac_data->reg_cntl0),
+                       s_vdac_data->reg_cntl1,
+                       vdac_hiu_reg_read(s_vdac_data->reg_cntl1));
+       }
+
        mutex_unlock(&vdac_mutex);
 }
 EXPORT_SYMBOL(vdac_enable);
 
+void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1)
+{
+       unsigned int reg_cntl0;
+       unsigned int reg_cntl1;
+
+       if (!s_vdac_data) {
+               pr_err("\n%s: s_vdac_data NULL\n", __func__);
+               return;
+       }
+
+       reg_cntl0 = s_vdac_data->reg_cntl0;
+       reg_cntl1 = s_vdac_data->reg_cntl1;
+
+       vdac_hiu_reg_write(reg_cntl0, ctrl0);
+       vdac_hiu_reg_write(reg_cntl1, ctrl1);
+       if (vdac_debug_print) {
+               pr_info("vdac: set reg 0x%02x=0x%08x, readback=0x%08x\n",
+                       reg_cntl0, ctrl0, vdac_hiu_reg_read(reg_cntl0));
+               pr_info("vdac: set reg 0x%02x=0x%08x, readback=0x%08x\n",
+                       reg_cntl1, ctrl1, vdac_hiu_reg_read(reg_cntl1));
+       }
+}
+
 int vdac_enable_check_dtv(void)
 {
-       return (pri_flag & VDAC_MODULE_DTV_DEMOD) ? 1:0;
+       return (pri_flag & VDAC_MODULE_DTV_DEMOD) ? 1 : 0;
 }
 
-static int amvdac_open(struct inode *inode, struct file *file)
+int vdac_enable_check_cvbs(void)
 {
-       struct amvdac_dev_s *devp;
-       /* Get the per-device structure that contains this cdev */
-       devp = container_of(inode->i_cdev, struct amvdac_dev_s, cdev);
-       file->private_data = devp;
-       return 0;
+       return (pri_flag & VDAC_MODULE_CVBS_OUT) ? 1 : 0;
 }
 
-static int amvdac_release(struct inode *inode, struct file *file)
+/* ********************************************************* */
+static ssize_t vdac_info_show(struct class *class,
+               struct class_attribute *attr, char *buf)
 {
-       file->private_data = NULL;
-       return 0;
+       ssize_t len = 0;
+
+       if (!s_vdac_data)
+               return sprintf(buf, "vdac data is NULL\n");
+
+       len = sprintf(buf, "vdac driver info:\n");
+       len += sprintf(buf + len,
+               "chip_type:                %s(%d)\n"
+               "private_flag:             0x%02x\n"
+               "reg_cntl0:                0x%02x=0x%08x\n"
+               "reg_cntl1:                0x%02x=0x%08x\n"
+               "debug_print:              %d\n",
+               s_vdac_data->name, s_vdac_data->cpu_id, pri_flag,
+               s_vdac_data->reg_cntl0,
+               vdac_hiu_reg_read(s_vdac_data->reg_cntl0),
+               s_vdac_data->reg_cntl1,
+               vdac_hiu_reg_read(s_vdac_data->reg_cntl1),
+               vdac_debug_print);
+
+       return len;
 }
 
-static const struct file_operations amvdac_fops = {
-       .owner   = THIS_MODULE,
-       .open    = amvdac_open,
-       .release = amvdac_release,
+static const char *vdac_debug_usage_str = {
+"Usage:\n"
+"    cat /sys/class/amvdac/info ; print vdac information\n"
+"    echo flag > /sys/class/amvdac/debug ; vdac_private_flag config\n"
+"    echo print <val_dec> > /sys/class/amvdac/debug ; vdac_debug_print config\n"
 };
 
-struct meson_vdac_data meson_gxtvbb_vdac_data = {
-       .cpu_id = VDAC_CPU_GXTVBB,
-       .name = "meson-gxtvbb-vdac",
-};
+static ssize_t vdac_debug_show(struct class *class,
+               struct class_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", vdac_debug_usage_str);
+}
 
-struct meson_vdac_data meson_gx_l_m_vdac_data = {
-       .cpu_id = VDAC_CPU_GX_L_M,
-       .name = "meson-gx_l_m-vdac",
-};
+static void vdac_parse_param(char *buf_orig, char **parm)
+{
+       char *ps, *token;
+       char delim1[3] = " ";
+       char delim2[2] = "\n";
+       unsigned int n = 0;
+
+       ps = buf_orig;
+       strcat(delim1, delim2);
+       while (1) {
+               token = strsep(&ps, delim1);
+               if (token == NULL)
+                       break;
+               if (*token == '\0')
+                       continue;
+               parm[n++] = token;
+       }
+}
 
-struct meson_vdac_data meson_txl_vdac_data = {
-       .cpu_id = VDAC_CPU_TXL,
-       .name = "meson-txl-vdac",
-};
+static ssize_t vdac_debug_store(struct class *class,
+               struct class_attribute *attr, const char *buff, size_t count)
+{
+       char *buf_orig;
+       char *parm[3] = {NULL};
 
-struct meson_vdac_data meson_txlx_vdac_data = {
-       .cpu_id = VDAC_CPU_TXLX,
-       .name = "meson-txlx-vdac",
-};
+       if (!s_vdac_data) {
+               pr_info("vdac data is null\n");
+               return count;
+       }
 
-struct meson_vdac_data meson_gxlx_vdac_data = {
-       .cpu_id = VDAC_CPU_GXLX,
-       .name = "meson-gxlx-vdac",
-};
+       buf_orig = kstrdup(buff, GFP_KERNEL);
+       vdac_parse_param(buf_orig, (char **)&parm);
+       if (parm[0] == NULL)
+               return count;
+
+       if (!strcmp(parm[0], "flag")) {
+               pr_info("vdac_private_flag: 0x%x\n", pri_flag);
+       } else if (!strcmp(parm[0], "print")) {
+               if (parm[1]) {
+                       if (kstrtouint(parm[1], 10, &vdac_debug_print) < 0)
+                               goto vdac_store_err;
+               }
+               pr_info("vdac_debug_print:%d\n", vdac_debug_print);
+       } else {
+               pr_info("invalid cmd\n");
+       }
 
-struct meson_vdac_data meson_txhd_vdac_data = {
-       .cpu_id = VDAC_CPU_TXHD,
-       .name = "meson-txhd-vdac",
-};
+       kfree(buf_orig);
+       return count;
 
-struct meson_vdac_data meson_g12ab_vdac_data = {
-       .cpu_id = VDAC_CPU_G12AB,
-       .name = "meson-g12ab-vdac",
-};
+vdac_store_err:
+       kfree(buf_orig);
+       return -EINVAL;
+}
 
-struct meson_vdac_data meson_tl1_vdac_data = {
-       .cpu_id = VDAC_CPU_TL1,
-       .name = "meson-tl1-vdac",
+static struct class_attribute vdac_class_attrs[] = {
+       __ATTR(info, 0644, vdac_info_show, NULL),
+       __ATTR(debug, 0644, vdac_debug_show, vdac_debug_store),
 };
 
-struct meson_vdac_data meson_sm1_vdac_data = {
-       .cpu_id = VDAC_CPU_SM1,
-       .name = "meson-sm1-vdac",
-};
+static int vdac_create_class(struct amvdac_dev_s *devp)
+{
+       int i;
 
-struct meson_vdac_data meson_tm2_vdac_data = {
-       .cpu_id = VDAC_CPU_TM2,
-       .name = "meson-tm2-vdac",
-};
+       if (IS_ERR_OR_NULL(devp->clsp)) {
+               pr_err("vdac: %s debug class is null\n", __func__);
+               return -1;
+       }
 
-static const struct of_device_id meson_vdac_dt_match[] = {
-       {
-               .compatible = "amlogic, vdac-gxtvbb",
-               .data           = &meson_gxtvbb_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-gxl",
-               .data           = &meson_gx_l_m_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-gxm",
-               .data           = &meson_gx_l_m_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-txl",
-               .data           = &meson_txl_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-txlx",
-               .data           = &meson_txlx_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-gxlx",
-               .data           = &meson_gxlx_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-txhd",
-               .data           = &meson_txhd_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-g12a",
-               .data           = &meson_g12ab_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-g12b",
-               .data           = &meson_g12ab_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-tl1",
-               .data           = &meson_tl1_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-sm1",
-               .data           = &meson_sm1_vdac_data,
-       }, {
-               .compatible = "amlogic, vdac-tm2",
-               .data           = &meson_tm2_vdac_data,
-       },
-       {},
+       for (i = 0; i < ARRAY_SIZE(vdac_class_attrs); i++) {
+               if (class_create_file(devp->clsp, &vdac_class_attrs[i])) {
+                       pr_err("vdac: create debug attribute %s failed\n",
+                               vdac_class_attrs[i].attr.name);
+               }
+       }
+
+       return 0;
+}
+
+static int vdac_remove_class(struct amvdac_dev_s *devp)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(vdac_class_attrs); i++)
+               class_remove_file(devp->clsp, &vdac_class_attrs[i]);
+
+       class_destroy(devp->clsp);
+       devp->clsp = NULL;
+
+       return 0;
+}
+/* ********************************************************* */
+
+static int amvdac_open(struct inode *inode, struct file *file)
+{
+       struct amvdac_dev_s *devp;
+       /* Get the per-device structure that contains this cdev */
+       devp = container_of(inode->i_cdev, struct amvdac_dev_s, cdev);
+       file->private_data = devp;
+       return 0;
+}
+
+static int amvdac_release(struct inode *inode, struct file *file)
+{
+       file->private_data = NULL;
+       return 0;
+}
+
+static const struct file_operations amvdac_fops = {
+       .owner   = THIS_MODULE,
+       .open    = amvdac_open,
+       .release = amvdac_release,
 };
+/* ********************************************************* */
 
 static int aml_vdac_probe(struct platform_device *pdev)
 {
        int ret = 0;
-       const struct of_device_id *match;
        struct amvdac_dev_s *devp = &amvdac_dev;
 
        memset(devp, 0, (sizeof(struct amvdac_dev_s)));
 
-       match = of_match_device(meson_vdac_dt_match, &pdev->dev);
-       if (match == NULL) {
-               pr_err("%s,no matched table\n", __func__);
-               return -1;
+       s_vdac_data = aml_vdac_config_probe(pdev);
+       if (!s_vdac_data) {
+               pr_err("%s: config probe failed\n", __func__);
+               return ret;
        }
-       s_vdac_data = (struct meson_vdac_data *)match->data;
-       pr_info("%s:probe start.cpu_id:%d,name:%s\n", __func__,
-               s_vdac_data->cpu_id, s_vdac_data->name);
+
+       mutex_init(&vdac_mutex);
 
        ret = alloc_chrdev_region(&devp->devno, 0, 1, AMVDAC_NAME);
        if (ret < 0)
@@ -682,6 +663,8 @@ static int aml_vdac_probe(struct platform_device *pdev)
                goto fail_create_device;
        }
 
+       vdac_create_class(devp);
+
        pr_info("%s: ok\n", __func__);
 
        return ret;
@@ -705,11 +688,14 @@ static int __exit aml_vdac_remove(struct platform_device *pdev)
 {
        struct amvdac_dev_s *devp = &amvdac_dev;
 
+       vdac_remove_class(devp);
        device_destroy(devp->clsp, devp->devno);
        cdev_del(&devp->cdev);
        class_destroy(devp->clsp);
        unregister_chrdev_region(devp->devno, 1);
 
+       mutex_destroy(&vdac_mutex);
+
        pr_info("%s: amvdac_exit.\n", __func__);
 
        return 0;
@@ -721,10 +707,10 @@ static int amvdac_drv_suspend(struct platform_device *pdev,
 {
        if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
                s_vdac_data->cpu_id == VDAC_CPU_TXLX)
-               vdac_hiu_reg_write(HHI_VDAC_CNTL0, 0);
+               vdac_hiu_reg_write(s_vdac_data->reg_cntl0, 0);
        else if (s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
                s_vdac_data->cpu_id == VDAC_CPU_TM2)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 1, 7, 1);
+               vdac_ctrl_config(0, s_vdac_data->reg_cntl1, 7);
        pr_info("%s: suspend module\n", __func__);
        return 0;
 }
@@ -733,8 +719,9 @@ static int amvdac_drv_resume(struct platform_device *pdev)
 {
        /*0xbc[7] for bandgap enable: 0:enable,1:disable*/
        if (s_vdac_data->cpu_id == VDAC_CPU_TL1 ||
-               s_vdac_data->cpu_id == VDAC_CPU_TM2)
-               vdac_hiu_reg_setb(HHI_VDAC_CNTL1_G12A, 0, 7, 1);
+               s_vdac_data->cpu_id == VDAC_CPU_TM2) {
+               vdac_ctrl_config(1, s_vdac_data->reg_cntl1, 7);
+       }
        pr_info("%s: resume module\n", __func__);
        return 0;
 }
@@ -744,7 +731,8 @@ static void amvdac_drv_shutdown(struct platform_device *pdev)
 {
        unsigned int cntl0, cntl1;
 
-       pr_info("%s: shutdown module\n", __func__);
+       pr_info("%s: shutdown module, private_flag:0x%x\n",
+               __func__, pri_flag);
        cntl0 = 0x0;
        if (s_vdac_data->cpu_id == VDAC_CPU_TXL ||
                s_vdac_data->cpu_id == VDAC_CPU_TXLX)
@@ -768,31 +756,23 @@ static struct platform_driver aml_vdac_driver = {
        .suspend    = amvdac_drv_suspend,
        .resume     = amvdac_drv_resume,
 #endif
-       .shutdown       = amvdac_drv_shutdown,
+       .shutdown   = amvdac_drv_shutdown,
 };
 
 static int __init aml_vdac_init(void)
 {
-       pr_info("%s: module init\n", __func__);
-
-       vdac_init_succ_flag = 0;
        s_vdac_data = NULL;
 
-       mutex_init(&vdac_mutex);
-
        if (platform_driver_register(&aml_vdac_driver)) {
                pr_err("%s: failed to register vdac driver module\n", __func__);
                return -ENODEV;
        }
 
-       vdac_init_succ_flag = 1;
        return 0;
 }
 
 static void __exit aml_vdac_exit(void)
 {
-       mutex_destroy(&vdac_mutex);
-       pr_info("%s: module exit\n", __func__);
        platform_driver_unregister(&aml_vdac_driver);
 }
 
diff --git a/drivers/amlogic/media/vout/vdac/vdac_dev.h b/drivers/amlogic/media/vout/vdac/vdac_dev.h
new file mode 100644 (file)
index 0000000..695e28c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * drivers/amlogic/media/vout/vdac/vdac_dev.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _VDAC_DEV_H_
+#define _VDAC_DEV_H_
+
+#define HHI_VDAC_CNTL0        0xbd
+#define HHI_VDAC_CNTL1        0xbe
+#define HHI_VDAC_CNTL0_G12A   0xbb
+#define HHI_VDAC_CNTL1_G12A   0xbc
+
+#define HHI_VIID_CLK_DIV      0x4a
+#define HHI_VIID_CLK_CNTL     0x4b
+#define HHI_VIID_DIVIDER_CNTL 0x4c
+#define HHI_VID_CLK_CNTL2     0x65
+#define HHI_VID_DIVIDER_CNTL  0x66
+
+#define VENC_VDAC_DACSEL0     0x1b78
+
+#define VDAC_CTRL_MAX         10
+
+enum vdac_cpu_type {
+       VDAC_CPU_GX_L_M = 0,
+       VDAC_CPU_TXL  = 1,
+       VDAC_CPU_TXLX  = 2,
+       VDAC_CPU_GXLX  = 3,
+       VDAC_CPU_G12AB = 4,
+       VDAC_CPU_TL1 = 5,
+       VDAC_CPU_SM1 = 6,
+       VDAC_CPU_TM2 = 7,
+       VDAC_CPU_MAX,
+};
+
+#define VDAC_REG_MAX    0xffff
+
+struct meson_vdac_data {
+       enum vdac_cpu_type cpu_id;
+       const char *name;
+
+       unsigned int reg_cntl0;
+       unsigned int reg_cntl1;
+       struct meson_vdac_ctrl_s *ctrl_table;
+};
+
+struct meson_vdac_ctrl_s {
+       unsigned int reg;
+       unsigned int val;
+       unsigned int bit;
+       unsigned int len;
+};
+
+extern const struct of_device_id meson_vdac_dt_match[];
+struct meson_vdac_data *aml_vdac_config_probe(struct platform_device *pdev);
+
+#endif
index fe9cb85..9e278d3 100644 (file)
  *
  */
 
-#ifndef _VDAC_DEV_H_
-#define _VDAC_DEV_H_
+#ifndef _INC_VDAC_DEV_H_
+#define _INC_VDAC_DEV_H_
 
-enum vdac_cpu_type {
-       VDAC_CPU_GXTVBB = 0,
-       VDAC_CPU_GX_L_M = 1,
-       VDAC_CPU_TXL  = 2,
-       VDAC_CPU_TXLX  = 3,
-       VDAC_CPU_GXLX  = 4,
-       VDAC_CPU_TXHD = 5,
-       VDAC_CPU_G12AB = 6,
-       VDAC_CPU_TL1 = 7,
-       VDAC_CPU_SM1 = 8,
-       VDAC_CPU_TM2 = 9,
-       VDAC_CPU_MAX,
-};
-
-struct meson_vdac_data {
-       enum vdac_cpu_type cpu_id;
-       const char *name;
-};
+#define VDAC_MODULE_MASK      (0x1f)
+#define VDAC_MODULE_AVOUT_ATV (1 << 0) /*0x1*/
+#define VDAC_MODULE_DTV_DEMOD (1 << 1) /*0x2*/
+#define VDAC_MODULE_AVOUT_AV  (1 << 2) /*0x4*/
+#define VDAC_MODULE_CVBS_OUT  (1 << 3) /*0x8*/
+#define VDAC_MODULE_AUDIO_OUT (1 << 4) /*0x10*/
 
 extern void vdac_set_ctrl0_ctrl1(unsigned int ctrl0, unsigned int ctrl1);
+extern void vdac_enable(bool on, unsigned int module_sel);
+extern int vdac_enable_check_dtv(void);
+extern int vdac_enable_check_cvbs(void);
 
 #endif