diff --git a/arch/arm/boot/dts/amlogic/mesontm2.dtsi b/arch/arm/boot/dts/amlogic/mesontm2.dtsi index 0ff7ebf142ca..2d642daa61f3 100644 --- a/arch/arm/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm/boot/dts/amlogic/mesontm2.dtsi @@ -1354,7 +1354,7 @@ }; vdac { - compatible = "amlogic, vdac-tl1"; + compatible = "amlogic, vdac-tm2"; status = "okay"; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_pxp.dts b/arch/arm/boot/dts/amlogic/tl1_pxp.dts index 92a55d79cf4f..e90bb207aafb 100644 --- a/arch/arm/boot/dts/amlogic/tl1_pxp.dts +++ b/arch/arm/boot/dts/amlogic/tl1_pxp.dts @@ -96,8 +96,10 @@ vdin1_cma_reserved:linux,vdin1_cma { compatible = "shared-dma-pool"; reusable; - /* 1920x1080x2x4 =16 M */ - size = <0x1400000>; + /*keystone need 4 buffers,each has 1920*1080*3 + *for keystone, change to 0x1800000(24M) + */ + size = <0x1400000>;/*20M*/ alignment = <0x400000>; }; diff --git a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts index dc3014d9de8f..8824a5524410 100644 --- a/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts +++ b/arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts @@ -122,8 +122,10 @@ vdin1_cma_reserved:linux,vdin1_cma { compatible = "shared-dma-pool"; reusable; - /* 1920x1080x2x4 =16 M */ - size = <0x1400000>; + /*keystone need 4 buffers,each has 1920*1080*3 + *for keystone, change to 0x1800000(24M) + */ + size = <0x1400000>;/*20M*/ alignment = <0x400000>; }; diff --git a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi index 356d18193404..980cd4b0e156 100644 --- a/arch/arm64/boot/dts/amlogic/mesontm2.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesontm2.dtsi @@ -1334,7 +1334,7 @@ }; vdac { - compatible = "amlogic, vdac-tl1"; + compatible = "amlogic, vdac-tm2"; status = "okay"; }; diff --git a/drivers/amlogic/clk/tl1/tl1.h b/drivers/amlogic/clk/tl1/tl1.h index e3a7b56dbdc3..bc67643d681b 100644 --- a/drivers/amlogic/clk/tl1/tl1.h +++ b/drivers/amlogic/clk/tl1/tl1.h @@ -123,11 +123,13 @@ #define HHI_SYS_PLL_CNTL5 0x308 /* 0xc2 offset in datasheet */ #define HHI_SYS_PLL_CNTL6 0x30c /* 0xc3 offset in datasheet */ +#if 0/*tl1 no*/ #define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in datasheet */ #define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in datasheet */ #define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in datasheet */ #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in datasheet */ #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in datasheet */ +#endif #define HHI_VID_LOCK_CLK_CNTL 0x3c8 /* 0xf2 offset in datasheet1 */ #define HHI_BT656_CLK_CNTL 0x3d4 /* 0xf5 offset in datasheet1 */ #define HHI_SPICC_CLK_CNTL 0x3dc /* 0xf7 offset in datasheet1 */ diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm.c b/drivers/amlogic/media/enhancement/amvecm/amvecm.c index 078a35bf060c..4a54c83cc236 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm.c +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include /* #include */ #include /* for parse_para_pq */ #include @@ -129,7 +131,7 @@ static struct hdr_metadata_info_s vpp_hdr_metadata_s; static int vdj_mode_flg; struct am_vdj_mode_s vdj_mode_s; -void __iomem *amvecm_hiu_reg_base;/* = *ioremap(0xc883c000, 0x2000); */ +/*void __iomem *amvecm_hiu_reg_base;*//* = *ioremap(0xc883c000, 0x2000); */ static int debug_amvecm; module_param(debug_amvecm, int, 0664); @@ -722,6 +724,7 @@ static ssize_t amvecm_vlock_store(struct class *cla, sel = VLOCK_SUPPORT; } else if (!strncmp(parm[0], "enable", 6)) { vecm_latch_flag |= FLAG_VLOCK_EN; + vlock_set_en(true); } else if (!strncmp(parm[0], "disable", 7)) { vecm_latch_flag |= FLAG_VLOCK_DIS; } else if (!strncmp(parm[0], "status", 6)) { @@ -734,8 +737,36 @@ static ssize_t amvecm_vlock_store(struct class *cla, vlock_log_stop(); } else if (!strncmp(parm[0], "log_print", 9)) { vlock_log_print(); + } else if (!strncmp(parm[0], "phase", 5)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + vlock_set_phase(val); + } else if (!strncmp(parm[0], "phlock_en", 9)) { + if (kstrtol(parm[1], 10, &val) < 0) + return -EINVAL; + vlock_set_phase_en(val); } else { - pr_info("unsupport cmd!!\n"); + pr_info("----cmd list -----\n"); + pr_info("vlock_mode val\n"); + pr_info("vlock_en val\n"); + pr_info("vlock_debug val\n"); + pr_info("vlock_adapt val\n"); + pr_info("vlock_dis_cnt_limit val\n"); + pr_info("vlock_delta_limit val\n"); + pr_info("vlock_dynamic_adjust val\n"); + pr_info("vlock_line_limit val\n"); + pr_info("vlock_dis_cnt_no_vf_limit val\n"); + pr_info("vlock_line_limit val\n"); + pr_info("vlock_support val\n"); + pr_info("enable\n"); + pr_info("disable\n"); + pr_info("status\n"); + pr_info("dump_reg\n"); + pr_info("log_start\n"); + pr_info("log_stop\n"); + pr_info("log_print\n"); + pr_info("phase persent\n"); + pr_info("phlock_en val\n"); } if (sel < VLOCK_PARAM_MAX) vlock_param_set(temp_val, sel); @@ -5742,11 +5773,40 @@ static const struct file_operations amvecm_fops = { #endif .poll = amvecm_poll, }; + +static const struct vecm_match_data_s vecm_dt_xxx = { + .vlk_support = true, + .vlk_new_fsm = 0, + .vlk_hwver = vlock_hw_org, + .vlk_phlock_en = false, +}; + +static const struct vecm_match_data_s vecm_dt_tl1 = { + .vlk_support = true, + .vlk_new_fsm = 1, + .vlk_hwver = vlock_hw_ver2, + .vlk_phlock_en = true, +}; + +static const struct of_device_id aml_vecm_dt_match[] = { + { + .compatible = "amlogic, vecm", + .data = &vecm_dt_xxx, + }, + { + .compatible = "amlogic, vecm-tl1", + .data = &vecm_dt_tl1, + }, + {}, +}; + static void aml_vecm_dt_parse(struct platform_device *pdev) { struct device_node *node; unsigned int val; int ret; + const struct of_device_id *of_id; + struct vecm_match_data_s *matchdata; node = pdev->dev.of_node; /* get integer value */ @@ -5785,6 +5845,18 @@ static void aml_vecm_dt_parse(struct platform_device *pdev) pr_info("Can't find tx_op_color_primary.\n"); else tx_op_color_primary = val; + + /*get compatible matched device, to get chip related data*/ + of_id = of_match_device(aml_vecm_dt_match, &pdev->dev); + if (of_id != NULL) { + pr_info("%s", of_id->compatible); + matchdata = (struct vecm_match_data_s *)of_id->data; + } else { + matchdata = (struct vecm_match_data_s *)&vecm_dt_xxx; + pr_info("unable to get matched device\n"); + } + vlock_dt_match_init(matchdata); + /*vlock param config*/ vlock_param_config(node); } @@ -5908,16 +5980,7 @@ static int aml_vecm_probe(struct platform_device *pdev) if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) sdr_mode = 2; - /*config vlock mode*/ - /*todo:txlx & g9tv support auto pll,*/ - /*but support not good,need vlsi support optimize*/ - vlock_mode = VLOCK_MODE_MANUAL_PLL; - if (is_meson_gxtvbb_cpu() || - is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_txhd_cpu()) - vlock_en = 1; - else - vlock_en = 0; + vlock_status_init(); hdr_init(&amvecm_dev.hdr_d); aml_vecm_dt_parse(pdev); @@ -6007,13 +6070,6 @@ static void amvecm_shutdown(struct platform_device *pdev) #endif } -static const struct of_device_id aml_vecm_dt_match[] = { - { - .compatible = "amlogic, vecm", - }, - {}, -}; - static struct platform_driver aml_vecm_driver = { .driver = { .name = "aml_vecm", @@ -6032,16 +6088,19 @@ static struct platform_driver aml_vecm_driver = { static int __init aml_vecm_init(void) { - unsigned int hiu_reg_base; + /*unsigned int hiu_reg_base;*/ pr_info("%s:module init\n", __func__); + #if 0 /* remap the hiu bus */ if (is_meson_txlx_cpu() || is_meson_txhd_cpu() || - is_meson_g12a_cpu() || is_meson_g12b_cpu()) + is_meson_g12a_cpu() || is_meson_g12b_cpu() + || is_meson_tl1_cpu()) hiu_reg_base = 0xff63c000; else hiu_reg_base = 0xc883c000; amvecm_hiu_reg_base = ioremap(hiu_reg_base, 0x2000); + #endif if (platform_driver_register(&aml_vecm_driver)) { pr_err("failed to register bl driver module\n"); return -ENODEV; @@ -6053,7 +6112,7 @@ static int __init aml_vecm_init(void) static void __exit aml_vecm_exit(void) { pr_info("%s:module exit\n", __func__); - iounmap(amvecm_hiu_reg_base); + /*iounmap(amvecm_hiu_reg_base);*/ platform_driver_unregister(&aml_vecm_driver); } diff --git a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h index bdd4737d4570..292827d3c464 100644 --- a/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h +++ b/drivers/amlogic/media/enhancement/amvecm/amvecm_vlock_regmap.h @@ -30,13 +30,13 @@ static struct vlock_regs_s vlock_enc_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3000, 0xE3f50f10 }, {0x3001, 0x41E3c3c }, {0x3002, 0x6000000 }, - {0x3003, 0x20680680 }, - {0x3004, 0x280280 }, + {0x3003, 0x20709709/*0x20680680 */}, + {0x3004, 0x00709709/*0x280280 */}, {0x3005, 0x8020000 }, {0x3006, 0x0008000 }, {0x3007, 0x0000000 }, {0x3008, 0x0000000 }, - {0x3009, 0x0008000 }, + {0x3009, 0x6000000/*0x0008000 */}, {0x300a, 0x8000000 }, {0x300b, 0x000a000 }, {0x300c, 0xa000000 }, @@ -54,7 +54,7 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3001, 0x04053c32 }, {0x3002, 0x06000000 }, {0x3003, 0x20780780 }, - {0x3004, 0x00000000 }, + {0x3004, 0x00680680 }, {0x3005, 0x00080000 }, {0x3006, 0x00070000 }, {0x3007, 0x00000000 }, @@ -62,15 +62,29 @@ static struct vlock_regs_s vlock_pll_setting[VLOCK_DEFAULT_REG_SIZE] = { {0x3009, 0x00100000 }, {0x300a, 0x00600000 }, {0x300b, 0x00100000 }, - {0x300c, 0x00000000 }, + {0x300c, 0x00600000 }, {0x300d, 0x00004000 }, {0x3010, 0x20001000 }, {0x3016, 0x0003de00 }, - {0x3017, 0x00001080 }, + {0x3017, 0x00001010 }, {0x301d, 0x30501080 }, {0x301e, 0x00000007 }, {0x301f, 0x06000000 } }; +#define VLOCK_PHASE_REG_SIZE 9 +static struct vlock_regs_s vlock_pll_phase_setting[VLOCK_PHASE_REG_SIZE] = { + {0x3004, 0x00620680}, + {0x3009, 0x06000000}, + {0x300a, 0x00600000}, + {0x300b, 0x06000000}, + {0x300c, 0x00600000}, + + {0x3025, 0x00002000}, + {0x3027, 0x00022002}, + {0x3028, 0x00001000}, + {0x302a, 0x00022002}, +}; + #endif diff --git a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h index ec7f6397a9ea..37afb668a241 100644 --- a/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h +++ b/drivers/amlogic/media/enhancement/amvecm/arch/vpp_regs.h @@ -342,6 +342,7 @@ #define VPU_VLOCK_GCLK_EN 0x301e #define VPU_VLOCK_LOOP1_ACCUM_LMT 0x301f #define VPU_VLOCK_RO_M_INT_FRAC 0x3020 +#define VPU_VLOCK_RO_LCK_FRM 0x3024 #define XVYCC_VD1_RGB_CTRST 0x3170 @@ -529,11 +530,19 @@ /*ve dither*/ #define VPP_VE_DITHER_CTRL 0x3120 +/* TL1 */ +/*offset 0x1000*/ +#define HHI_TCON_PLL_CNTL0 0x20 +#define HHI_TCON_PLL_CNTL1 0x21 +#define HHI_HDMI_PLL_VLOCK_CNTL 0xd1 + /* for pll bug */ -#define HHI_HDMI_PLL_CNTL 0x10c8 -#define HHI_HDMI_PLL_CNTL2 0x10c9 -#define HHI_VID_LOCK_CLK_CNTL 0x10f2 -#define HHI_HDMI_PLL_CNTL6 0x10cd + +#define HHI_HDMI_PLL_CNTL 0xc8 +#define HHI_HDMI_PLL_CNTL2 0xc9 +#define HHI_VID_LOCK_CLK_CNTL 0xf2 +#define HHI_HDMI_PLL_CNTL6 0xcd + /* for vlock enc mode adjust begin */ #define ENCL_VIDEO_MAX_LNCNT 0x1cbb #define ENCL_VIDEO_MAX_PXCNT 0x1cb0 @@ -552,13 +561,12 @@ #define ENCT_MAX_LINE_SWITCH_POINT 0x1c88 /* for vlock enc mode adjust end */ -#define HHI_VID_LOCK_CLK_CNTL 0x10f2 - #define VDIN_MEAS_VS_COUNT_LO 0x125c +/*for vlock*/ /*after GXL new add CNTL1,same with CNTL2 on G9TV/GXTVBB*/ -#define HHI_HDMI_PLL_CNTL1 0x10c9 +#define HHI_HDMI_PLL_CNTL1 0xc9 /*after GXL CNTL5[bit3] is same with CNTL6[bit20] on G9TV/GXTVBB*/ -#define HHI_HDMI_PLL_CNTL5 0x10cd +#define HHI_HDMI_PLL_CNTL5 0xcd /* #define VI_HIST_CTRL 0x2e00 */ diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.c b/drivers/amlogic/media/enhancement/amvecm/vlock.c index 8ce8c0c088b7..752bdf4df7fe 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.c +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.c @@ -35,11 +35,13 @@ #include "amcm.h" /* video lock */ -/* 0:enc;1:pll; - * 2:manual pll; - * 3:manual_enc mode(only support lvds/vx1) +/* 0:off; + * 1:auto enc; + * 2:auto pll; + * 4:manual pll; + * 8:manual_enc mode(only support lvds/vx1) */ -unsigned int vlock_mode = VLOCK_MODE_MANUAL_PLL; +enum VLOCK_MD vlock_mode = VLOCK_MODE_MANUAL_PLL; unsigned int vlock_en = 1; /* *0:only support 50->50;60->60;24->24;30->30; @@ -65,7 +67,7 @@ static unsigned int vlock_intput_type; static signed int vlock_line_limit = 3; static unsigned int vlock_enc_adj_limit; /* 0x3009 default setting for 2 line(1080p-output) is 0x8000 */ -static unsigned int vlock_capture_limit = 0x8000; +static unsigned int vlock_capture_limit = 0x10000/*0x8000*/; static unsigned int vlock_debug; static unsigned int vlock_dynamic_adjust = 1; @@ -102,6 +104,12 @@ static unsigned int vlock_log_last_ivcnt; static unsigned int vlock_log_last_ovcnt; static unsigned int vlock_log_delta_m; static unsigned int vlock_log_delta_en; +static unsigned int hhi_pll_reg_m; +static unsigned int hhi_pll_reg_frac; + +static struct stvlock_sig_sts vlock; + +/*static unsigned int hhi_pll_reg_vlock_ctl;*/ module_param(vlock_log_size, uint, 0664); MODULE_PARM_DESC(vlock_log_size, "\n vlock_log_size\n"); module_param(vlock_log_cnt, uint, 0664); @@ -141,13 +149,17 @@ static unsigned int last_i_vsync; int amvecm_hiu_reg_read(unsigned int reg, unsigned int *val) { - *val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2)); + /**val = readl(amvecm_hiu_reg_base+((reg - 0x1000)<<2));*/ + *val = aml_read_hiubus(reg); + /*pr_info("vlock rd hiu reg:0x%x,0x%x\n", (reg - 0x1000), *val);*/ return 0; } int amvecm_hiu_reg_write(unsigned int reg, unsigned int val) { - writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2))); + /*writel(val, (amvecm_hiu_reg_base+((reg - 0x1000)<<2)));*/ + /*pr_info("vlock rd hiu reg:0x%x,0x%x\n", (reg - 0x1000), val);*/ + aml_write_hiubus(reg, val); return 0; } static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, @@ -162,6 +174,41 @@ static int amvecm_hiu_reg_write_bits(unsigned int reg, unsigned int value, return 0; } +u32 vlock_get_panel_pll_m(void) +{ + u32 val; + + amvecm_hiu_reg_read(hhi_pll_reg_m, &val); + return val; +} + +void vlock_set_panel_pll_m(u32 val) +{ + amvecm_hiu_reg_write(hhi_pll_reg_m, val); +} + +u32 vlock_get_panel_pll_frac(void) +{ + u32 val; + + amvecm_hiu_reg_read(hhi_pll_reg_frac, &val); + return val; +} + +void vlock_set_panel_pll_frac(u32 val) +{ + amvecm_hiu_reg_write(hhi_pll_reg_frac, val); +} + + +/*returen 1: use phase lock*/ +int phase_lock_check(void) +{ + unsigned int ret = 0; + + ret = READ_VPP_REG_BITS(VPU_VLOCK_RO_LCK_FRM, 17, 1); + return ret; +} static unsigned int vlock_check_input_hz(struct vframe_s *vf) { @@ -188,33 +235,41 @@ static unsigned int vlock_check_input_hz(struct vframe_s *vf) return ret_hz; } -static unsigned int vlock_check_output_hz(unsigned int sync_duration_num) +static unsigned int vlock_check_output_hz(unsigned int sync_duration_num, + unsigned int sync_duration_den) { unsigned int ret_hz = 0; + unsigned int tempHz; - switch (sync_duration_num) { - case 24: + tempHz = (sync_duration_num*100)/sync_duration_den; + + switch (tempHz) { + case 2400: ret_hz = 24; break; - case 30: + case 3000: ret_hz = 30; break; - case 50: + case 5000: ret_hz = 50; break; - case 60: + case 6000: ret_hz = 60; break; - case 100: + case 10000: ret_hz = 100; break; - case 120: + case 12000: ret_hz = 120; break; default: ret_hz = 0; break; } + + if ((ret_hz == 0) && (vlock_debug & VLOCK_DEBUG_INFO)) + pr_info("sync_duration_num:%d\n", sync_duration_num); + return ret_hz; } /*vlock is support eq_after gxbb,but which is useful only for tv chip @@ -224,10 +279,9 @@ static void vlock_enable(bool enable) { unsigned int tmp_value; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu()) { if (vlock_mode & VLOCK_MODE_MANUAL_PLL) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 20, 1); /*vlsi suggest config:don't enable load signal, *on gxtvbb this load signal will effect SSG, @@ -246,7 +300,24 @@ static void vlock_enable(bool enable) else amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL5, enable, 3, 1); + } else if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + /*reset*/ + if (!(vlock_mode & VLOCK_MODE_MANUAL_PLL)) { + /*reset*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1);*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1);*/ + } + + if (!enable) { + /*amvecm_hiu_reg_write_bits(*/ + /* HHI_HDMI_PLL_VLOCK_CNTL, 0, 0, 3);*/ + + /*WRITE_VPP_REG(VPU_VLOCK_CTRL, 0);*/ + } } + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s] (%d)\n", __func__, enable); } static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) { @@ -256,22 +327,30 @@ static void vlock_hw_reinit(struct vlock_regs_s *vlock_regs, unsigned int len) return; for (i = 0; i < len; i++) WRITE_VPP_REG(vlock_regs[i].addr, vlock_regs[i].val); + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s]\n", __func__); } static void vlock_setting(struct vframe_s *vf, unsigned int input_hz, unsigned int output_hz) { - unsigned int freq_hz = 0, hiu_reg_value_2_addr = HHI_HDMI_PLL_CNTL2; + unsigned int freq_hz = 0; unsigned int reg_value = 0, hiu_reg_value, hiu_reg_value_2; - unsigned int hiu_m_val, hiu_frac_val, temp_value; + unsigned int hiu_m_val = 0, hiu_frac_val = 0, temp_value; + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info(">>>[%s]\n", __func__); + pr_info("inputHz:%d,outputHz:%d\n", input_hz, output_hz); + pr_info("type_original:0x%x\n", vf->type_original); + } amvecm_hiu_reg_write(HHI_VID_LOCK_CLK_CNTL, 0x80); - if ((vlock_mode & (VLOCK_MODE_AUTO_ENC | - VLOCK_MODE_MANUAL_ENC | - VLOCK_MODE_MANUAL_SOFT_ENC))) { + if (IS_ENC_MODE(vlock_mode)) { /*init default config for enc mode*/ vlock_hw_reinit(vlock_enc_setting, VLOCK_DEFAULT_REG_SIZE); /*vlock line limit*/ - WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT, vlock_capture_limit); + /*WRITE_VPP_REG(VPU_VLOCK_OUTPUT0_CAPT_LMT,*/ + /* vlock_capture_limit);*/ + /* VLOCK_CNTL_EN disable */ vlock_enable(0); /* disable to adjust pll */ @@ -292,10 +371,12 @@ static void vlock_setting(struct vframe_s *vf, } /* enable to adjust enc */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 30, 1); - /*clear accum1 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); - /*clear accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) { + /*clear accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + } /*@20180314 new add*/ /* *set input & output freq @@ -303,8 +384,14 @@ static void vlock_setting(struct vframe_s *vf, *bit8~15:output freq */ if ((vf->type_original & VIDTYPE_TYPEMASK) && - !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) - input_hz = input_hz >> 1; + !(vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) { + /*tl1 fix i problem*/ + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) + input_hz = input_hz >> 1; + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 1, 28, 1); + } freq_hz = input_hz | (output_hz << 8); WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); /* @@ -317,12 +404,14 @@ static void vlock_setting(struct vframe_s *vf, WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, input_hz, 16, 8); temp_value = READ_VPP_REG(enc_max_line_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 0, 14); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, + temp_value + 1, 0, 14); temp_value = READ_VPP_REG(enc_max_pixel_addr); - WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, temp_value, 16, 14); + WRITE_VPP_REG_BITS(VPU_VLOCK_OROW_OCOL_MAX, + temp_value + 1, 16, 14); WRITE_VPP_REG_BITS(VPU_VLOCK_ADJ_EN_SYNC_CTRL, vlock_latch_en_cnt, 8, 8); - WRITE_VPP_REG_BITS(enc_video_mode_addr, 0, 15, 1); + WRITE_VPP_REG_BITS(enc_video_mode_addr, 1, 15, 1); } if ((vlock_mode & (VLOCK_MODE_AUTO_PLL | VLOCK_MODE_MANUAL_PLL))) { @@ -333,8 +422,17 @@ static void vlock_setting(struct vframe_s *vf, *bit0~7:input freq *bit8~15:output freq */ - if (vf->type_original & VIDTYPE_TYPEMASK) - input_hz = input_hz >> 1; + if (vf->type_original & VIDTYPE_TYPEMASK) { + if (get_cpu_type() < MESON_CPU_MAJOR_ID_TL1) + input_hz = input_hz >> 1; + else + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 1, 28, 1); + } else { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) + WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, + 0, 28, 1); + } freq_hz = input_hz | (output_hz << 8); WRITE_VPP_REG_BITS(VPU_VLOCK_MISC_CTRL, freq_hz, 0, 16); /* @@ -349,10 +447,23 @@ static void vlock_setting(struct vframe_s *vf, /*set PLL M_INT;PLL M_frac*/ /* WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, */ /* READ_CBUS_REG_BITS(HHI_HDMI_PLL_CNTL,0,9),12,9); */ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &hiu_reg_value); - amvecm_hiu_reg_read(hiu_reg_value_2_addr, - &hiu_reg_value_2); - if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &hiu_reg_value);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac,*/ + /* &hiu_reg_value_2);*/ + hiu_reg_value = vlock_get_panel_pll_m(); + hiu_reg_value_2 = vlock_get_panel_pll_frac(); + + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("hhi_pll_reg_m:0x%x\n", hiu_reg_value); + pr_info("hhi_pll_reg_frac:0x%x\n", hiu_reg_value_2); + } + + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + hiu_m_val = hiu_reg_value & 0xff; + /*discard low 5 bits*/ + hiu_frac_val = (hiu_reg_value_2 >> 5) & 0xfff; + reg_value = (hiu_m_val << 12) + hiu_frac_val; + } else if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) { hiu_m_val = hiu_reg_value & 0x1FF; hiu_frac_val = hiu_reg_value_2 & 0x3FF; if (hiu_reg_value_2 & 0x800) { @@ -366,6 +477,12 @@ static void vlock_setting(struct vframe_s *vf, } reg_value = (hiu_m_val << 12) + (hiu_frac_val << 2); + } else { + pr_info("err: m f value\n"); + } + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("hiu_m_val=0x%x\n", hiu_m_val); + pr_info("hiu_frac_val=0x%x\n", hiu_frac_val); } WRITE_VPP_REG_BITS(VPU_VLOCK_MX4096, reg_value, 0, 21); /*vlock_pll_adj_limit = (reg_value * 0x8000) >> 24;*/ @@ -383,6 +500,21 @@ static void vlock_setting(struct vframe_s *vf, /* enable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 29, 1); } + + /*initial phase lock setting*/ + if (vlock.dtdata->vlk_phlock_en) { + vlock_hw_reinit(vlock_pll_phase_setting, VLOCK_PHASE_REG_SIZE); + /*disable pll lock*/ + /*WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 3, 1);*/ + + /*enable pll mode and enc mode phase lock*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 3, 0, 2); + + /*reset*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + } + /* vlock module output goes to which module */ switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0:/* ENCL */ @@ -404,33 +536,40 @@ static void vlock_setting(struct vframe_s *vf, else if (vf->source_type == VFRAME_SOURCE_TYPE_HDMI) /* Input Vsync source select from hdmi-rx */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 16, 3); + + /*enable vlock*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 31, 1); } void vlock_vmode_check(void) { const struct vinfo_s *vinfo; - unsigned int t0, t1, hiu_reg_addr; + unsigned int t0, t1; if (vlock_en == 0) return; - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + vinfo = get_current_vinfo(); vlock_vmode_changed = 0; if ((vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE) || (pre_hiu_reg_m == 0)) { if (vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL)) { - amvecm_hiu_reg_read(hiu_reg_addr, &t0); - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &t1); - pre_hiu_reg_frac = t0 & 0xfff; - pre_hiu_reg_m = t1 & 0x1ff; + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &t0);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &t1);*/ + t0 = vlock_get_panel_pll_m(); + t1 = vlock_get_panel_pll_frac(); + if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) { + pre_hiu_reg_frac = (t0 >> 5) & 0xfff; + pre_hiu_reg_m = t1 & 0xff; + } else { + pre_hiu_reg_frac = t0 & 0xfff; + pre_hiu_reg_m = t1 & 0x1ff; + } } if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_AUTO_ENC | VLOCK_MODE_MANUAL_SOFT_ENC))) { + #if 0 switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0: @@ -466,6 +605,7 @@ void vlock_vmode_check(void) ENCL_MAX_LINE_SWITCH_POINT; break; } + #endif pre_enc_max_line = READ_VPP_REG(enc_max_line_addr); pre_enc_max_pixel = READ_VPP_REG(enc_max_pixel_addr); vlock_capture_limit = ((1 << 12) * vlock_line_limit) / @@ -479,7 +619,6 @@ void vlock_vmode_check(void) static void vlock_disable_step1(void) { unsigned int m_reg_value, tmp_value, enc_max_line, enc_max_pixel; - unsigned int hiu_reg_addr; /* VLOCK_CNTL_EN disable */ vlock_enable(0); @@ -487,24 +626,70 @@ static void vlock_disable_step1(void) if ((vlock_mode & (VLOCK_MODE_MANUAL_PLL | VLOCK_MODE_AUTO_PLL | VLOCK_MODE_MANUAL_SOFT_ENC))) { - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - m_reg_value = tmp_value & 0xfff; - if (m_reg_value != pre_hiu_reg_frac) { - tmp_value = (tmp_value & 0xfffff000) | - (pre_hiu_reg_frac & 0xfff); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - } - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - m_reg_value = tmp_value & 0x1ff; - if ((m_reg_value != pre_hiu_reg_m) && - (pre_hiu_reg_m != 0)) { - tmp_value = (tmp_value & 0xfffffe00) | - (pre_hiu_reg_m & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + #if 0 + amvecm_hiu_reg_read(hhi_pll_reg_frac, + &tmp_value); + m_reg_value = (tmp_value >> 5) & 0xfff; + if (m_reg_value != pre_hiu_reg_frac) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + amvecm_hiu_reg_write(hhi_pll_reg_frac, + tmp_value); + pr_info("restore f value=0x%x\n", tmp_value); + } + amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value); + m_reg_value = tmp_value & 0xff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xffffff00) | + (pre_hiu_reg_m & 0xff); + amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value); + pr_info("restore m value=0x%x\n", tmp_value); + } + #endif + + #if 1 + /*restore the orginal pll setting*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); + m_reg_value = tmp_value & 0xff; + if (m_reg_value != (vlock.val_m & 0xff)) + vlock_set_panel_pll_m(vlock.val_m); + /*amvecm_hiu_reg_write(hhi_pll_reg_m,*/ + /* vlock.val_m);*/ + + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); + m_reg_value = tmp_value & 0x1ffff; + if (m_reg_value != (vlock.val_frac & 0xfff)) + vlock_set_panel_pll_frac(vlock.val_frac); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ + /* vlock.val_frac);*/ + pr_info("restore orignal m,f value\n"); + #endif + } else { + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); + m_reg_value = tmp_value & 0xfff; + if (m_reg_value != pre_hiu_reg_frac) { + tmp_value = (tmp_value & 0xfffff000) | + (pre_hiu_reg_frac & 0xfff); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac,*/ + /* tmp_value);*/ + vlock_set_panel_pll_frac(tmp_value); + } + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); + m_reg_value = tmp_value & 0x1ff; + if ((m_reg_value != pre_hiu_reg_m) && + (pre_hiu_reg_m != 0)) { + tmp_value = (tmp_value & 0xfffffe00) | + (pre_hiu_reg_m & 0x1ff); + /*amvecm_hiu_reg_write(hhi_pll_reg_m, */ + /*tmp_value);*/ + vlock_set_panel_pll_m(tmp_value); + } } } if ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | @@ -537,15 +722,26 @@ static void vlock_disable_step1(void) } vlock_pll_stable_cnt = 0; vlock_enc_stable_flag = 0; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } -static void vlock_disable_step2(void) +static bool vlock_disable_step2(void) { unsigned int temp_val; + bool ret = false; + /* need delay to disable follow regs(vlsi suggest!!!) */ if (vlock_dis_cnt > 0) vlock_dis_cnt--; - if (vlock_dis_cnt == 0) { + else if (vlock_dis_cnt == 0) { + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x4, 0, 3); + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x0, 0, 3); + } + /* disable to adjust pll */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 29, 1); /* CFG_VID_LOCK_ADJ_EN disable */ @@ -556,10 +752,19 @@ static void vlock_disable_step2(void) /* disable vid_lock_en */ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 31, 1); vlock_state = VLOCK_STATE_DISABLE_STEP2_DONE; - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); - if (is_meson_gxtvbb_cpu() && (((temp_val >> 21) & 0x3) != 0)) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 0, 21, 2); + if (is_meson_gxtvbb_cpu()) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &temp_val); + if (((temp_val >> 21) & 0x3) != 0) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, + 0, 21, 2); + } + ret = true; + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } + + return ret; } static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, unsigned int input_hz, unsigned int output_hz) @@ -584,10 +789,13 @@ static void vlock_enable_step1(struct vframe_s *vf, struct vinfo_s *vinfo, vlock_sync_limit_flag = 0; vlock_vmode_changed = 0; vlock_dis_cnt = 0; - vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + /*vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE;*/ vlock_pll_stable_cnt = 0; vlock_log_cnt = 0; vlock_enc_stable_flag = 0; + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } void vlock_log_start(void) @@ -715,6 +923,8 @@ static void vlock_enable_step3_enc(void) vlock_reg_get(); vlock_log_cnt++; } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } static void vlock_enable_step3_soft_enc(void) @@ -840,7 +1050,10 @@ static void vlock_enable_step3_soft_enc(void) vlock_reg_get(); vlock_log_cnt++; } + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info(">>>[%s]\n", __func__); } + /*check pll adj value (0x3020),otherwise may cause blink*/ static void vlock_pll_adj_limit_check(unsigned int *pll_val) { @@ -863,15 +1076,12 @@ static void vlock_pll_adj_limit_check(unsigned int *pll_val) } } } + static void vlock_enable_step3_pll(void) { - unsigned int m_reg_value, tmp_value, abs_val, hiu_reg_addr; + unsigned int m_reg_value, tmp_value, abs_val; unsigned int ia, oa, abs_cnt; - - if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) - hiu_reg_addr = HHI_HDMI_PLL_CNTL1; - else - hiu_reg_addr = HHI_HDMI_PLL_CNTL2; + unsigned int pre_m, new_m, tar_m, org_m; /*vs_i*/ tmp_value = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); @@ -898,10 +1108,20 @@ static void vlock_enable_step3_pll(void) m_reg_value = READ_VPP_REG(VPU_VLOCK_RO_M_INT_FRAC); if (vlock_log_en && (vlock_log_cnt < vlock_log_size)) { + #if 0 vlock_log[vlock_log_cnt]->pll_frac = (vlock_pll_val_last & 0xfff) >> 2; vlock_log[vlock_log_cnt]->pll_m = (vlock_pll_val_last >> 16) & 0x1ff; + #else + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); + vlock_log[vlock_log_cnt]->pll_frac = tmp_value; + + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); + vlock_log[vlock_log_cnt]->pll_m = tmp_value; + #endif vlock_reg_get(); vlock_log_cnt++; } @@ -913,18 +1133,26 @@ static void vlock_enable_step3_pll(void) return; } /*check adjust delta limit*/ - vlock_pll_adj_limit_check(&m_reg_value); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) + vlock_pll_adj_limit_check(&m_reg_value); /*vlsi suggest config:don't enable load signal, *on gxtvbb this load signal will effect SSG, *which may result in flashes black */ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); - if (is_meson_gxtvbb_cpu() && (((tmp_value >> 21) & 0x3) != 2)) - amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 2, 21, 2); - /*add delta count check*/ - /*for interlace input need div 2*/ - if (vlock_intput_type) + if (is_meson_gxtvbb_cpu()) { + amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL6, &tmp_value); + if (((tmp_value >> 21) & 0x3) != 2) + amvecm_hiu_reg_write_bits(HHI_HDMI_PLL_CNTL6, 2, 21, 2); + } + + /* add delta count check + *for interlace input need div 2 + *0:progressive type + *1:interlace type + */ + if (vlock_intput_type && + (vlock.dtdata->vlk_hwver < vlock_hw_ver2)) ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST) / 2; else ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); @@ -936,45 +1164,101 @@ static void vlock_enable_step3_pll(void) return; } /*frac*/ - amvecm_hiu_reg_read(hiu_reg_addr, &tmp_value); - abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); - if ((abs_val >= vlock_log_delta_frac) && (vlock_log_delta_en&(1<<3))) - pr_info("vlock frac delta:%d(0x%x,0x%x)\n", - abs_val, ((m_reg_value & 0xfff) >> 2), + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_frac(); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { + abs_val = abs(((m_reg_value & 0xfff) >> 2) - (tmp_value & 0xfff)); - if ((abs_val >= vlock_delta_limit) && - (abs_cnt > vlock_delta_cnt_limit)) { - tmp_value = (tmp_value & 0xfffff000) | - ((m_reg_value & 0xfff) >> 2); - amvecm_hiu_reg_write(hiu_reg_addr, tmp_value); - vlock_pll_val_last &= 0xffff0000; - vlock_pll_val_last |= (m_reg_value & 0xfff); + if ((abs_val >= vlock_log_delta_frac) && + (vlock_log_delta_en&(1<<3))) + pr_info("vlock frac delta:%d(0x%x,0x%x)\n", + abs_val, ((m_reg_value & 0xfff) >> 2), + (tmp_value & 0xfff)); + if ((abs_val >= vlock_delta_limit) && + (abs_cnt > vlock_delta_cnt_limit)) { + tmp_value = (tmp_value & 0xfffff000) | + ((m_reg_value & 0xfff) >> 2); + /*amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);*/ + vlock_set_panel_pll_frac(tmp_value); + vlock_pll_val_last &= 0xffff0000; + vlock_pll_val_last |= (m_reg_value & 0xfff); + } + /*check stable by diff frac*/ + if ((abs_val < (2 * vlock_delta_limit)) && + (abs_cnt < vlock_enc_adj_limit)) + vlock_pll_stable_cnt++; + else + vlock_pll_stable_cnt = 0; + } else { + abs_val = abs((tmp_value & 0x1ffff) - + ((m_reg_value & 0xfff) << 5)); + + if (abs_val > (50 << 5)) + tmp_value = ((tmp_value & 0xfffe0000) | + (((tmp_value & 0x1ffff) + + ((m_reg_value & 0xfff) << 5)) >> 1)); + else + tmp_value = (tmp_value & 0xfffe0000) | + ((m_reg_value & 0xfff) << 5); + + /*16:0*/ + /*amvecm_hiu_reg_write(hhi_pll_reg_frac, tmp_value);*/ + vlock_set_panel_pll_frac(tmp_value); } - /*check stable by diff frac*/ - if ((abs_val < (2 * vlock_delta_limit)) && - (abs_cnt < vlock_enc_adj_limit)) - vlock_pll_stable_cnt++; - else - vlock_pll_stable_cnt = 0; + /*m*/ - amvecm_hiu_reg_read(HHI_HDMI_PLL_CNTL, &tmp_value); - abs_val = abs(((m_reg_value >> 16) & 0x1ff) - (pre_hiu_reg_m & 0x1ff)); - if ((abs_val > vlock_log_delta_m) && (vlock_log_delta_en&(1<<4))) - pr_info("vlock m delta:%d(0x%x,0x%x)\n", - abs_val, ((m_reg_value >> 16) & 0x1ff), - (tmp_value & 0x1ff)); - if ((abs_val <= vlock_pll_m_limit) && - (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) && - (abs_cnt > vlock_delta_cnt_limit)) { - tmp_value = (tmp_value & 0xfffffe00) | - ((m_reg_value >> 16) & 0x1ff); - amvecm_hiu_reg_write(HHI_HDMI_PLL_CNTL, tmp_value); - vlock_pll_val_last &= 0x0000ffff; - vlock_pll_val_last |= (m_reg_value & 0xffff0000); + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &tmp_value);*/ + tmp_value = vlock_get_panel_pll_m(); + if (vlock.dtdata->vlk_hwver < vlock_hw_ver2) { + abs_val = abs(((m_reg_value >> 16) & 0xff) - + (pre_hiu_reg_m & 0xff)); + if ((abs_val > vlock_log_delta_m) && + (vlock_log_delta_en&(1<<4))) + pr_info("vlock m delta:%d(0x%x,0x%x)\n", + abs_val, ((m_reg_value >> 16) & 0x1ff), + (tmp_value & 0x1ff)); + if ((abs_val <= vlock_pll_m_limit) && + (((m_reg_value >> 16) & 0x1ff) != + (tmp_value & 0x1ff)) && + (abs_cnt > vlock_delta_cnt_limit)) { + tmp_value = (tmp_value & 0xfffffe00) | + ((m_reg_value >> 16) & 0x1ff); + /*amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value);*/ + vlock_set_panel_pll_m(tmp_value); + vlock_pll_val_last &= 0x0000ffff; + vlock_pll_val_last |= (m_reg_value & 0xffff0000); + } + } else { + pre_m = (tmp_value & 0xff); + new_m = ((m_reg_value >> 16) & 0x1ff); + org_m = (vlock.val_m & 0xff); + if (pre_m != new_m) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock m chg: pre=0x%x, report=0x%x\n", + pre_m, new_m); + + if (new_m > pre_m) { + tar_m = ((pre_m + 1) < + (org_m + 1))?(pre_m + 1):(org_m + 1); + } else { + /*tar_m < pre_m*/ + tar_m = ((pre_m - 1) < + (org_m - 1))?(org_m - 1):(pre_m - 1); + } + tmp_value = (tmp_value & 0xffffff00) + tar_m; + /*amvecm_hiu_reg_write(hhi_pll_reg_m, tmp_value);*/ + vlock_set_panel_pll_m(tmp_value); + } } + /*check stable by diff m*/ - if (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) - vlock_pll_stable_cnt = 0; + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (((m_reg_value >> 16) & 0xff) != (tmp_value & 0xff)) + vlock_pll_stable_cnt = 0; + } else { + if (((m_reg_value >> 16) & 0x1ff) != (tmp_value & 0x1ff)) + vlock_pll_stable_cnt = 0; + } } /* won't change this function internal seqence, * if really need change,please be carefull and check with vlsi @@ -994,10 +1278,12 @@ void amve_vlock_process(struct vframe_s *vf) } vinfo = get_current_vinfo(); input_hz = vlock_check_input_hz(vf); - output_hz = vlock_check_output_hz(vinfo->sync_duration_num); + output_hz = vlock_check_output_hz(vinfo->sync_duration_num, + vinfo->sync_duration_den); vlock_dis_cnt_no_vf = 0; if (vecm_latch_flag & FLAG_VLOCK_EN) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; vlock_en = 1; vecm_latch_flag &= ~FLAG_VLOCK_EN; } @@ -1035,43 +1321,73 @@ void amve_vlock_process(struct vframe_s *vf) (input_hz != pre_input_freq) || (output_hz != pre_output_freq) || vlock_vmode_changed || - (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) + (vlock_state == VLOCK_STATE_ENABLE_FORCE_RESET)) { vlock_enable_step1(vf, vinfo, input_hz, output_hz); + vlock_state = VLOCK_STATE_ENABLE_STEP1_DONE; + } if ((vlock_sync_limit_flag < 10) && (vlock_state >= VLOCK_STATE_ENABLE_STEP1_DONE)) { vlock_sync_limit_flag++; if ((vlock_sync_limit_flag <= 3) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { + /*reset*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear first 3 frame internal cnt*/ WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-0\n"); } if ((vlock_sync_limit_flag == 4) && ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | VLOCK_MODE_MANUAL_PLL)))) { + /*release reset*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-1\n"); } } + if ((vlock_sync_limit_flag == 5) && (vlock_state == VLOCK_STATE_ENABLE_STEP1_DONE)) { /*input_vs_cnt =*/ /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ /* 0, 28);*/ input_vs_cnt = XTAL_VLOCK_CLOCK/input_hz; - if (vf->type_original & VIDTYPE_TYPEMASK) + /*tl1 not need */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && + vf->type_original & VIDTYPE_TYPEMASK) input_vs_cnt = input_vs_cnt << 1; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, input_vs_cnt*125/100); WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, input_vs_cnt*70/100); + /*cal accum1 value*/ WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); /*cal accum0 value*/ - WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + //WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); vlock_state = VLOCK_STATE_ENABLE_STEP2_DONE; + + /* + * tl1 auto pll,swich clk need after + *several frames + */ + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + else if (IS_MANUAL_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + } + + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("amve_vlock_process-2\n"); } else if (vlock_dynamic_adjust && (vlock_sync_limit_flag > 5) && (vlock_state == VLOCK_STATE_ENABLE_STEP2_DONE) && @@ -1149,18 +1465,566 @@ void amve_vlock_resume(void) } } +void vlock_clear_frame_counter(void) +{ + vlock.frame_cnt_in = 0; + vlock.frame_cnt_no = 0; + vlock_log_cnt = 0; +} + +void vlock_set_en(bool en) +{ + /*if (vlock.dtdata->vlk_support)*/ + vlock_en = en; +} + +void vlock_status_init(void) +{ + /*config vlock mode*/ + /*todo:txlx & g9tv support auto pll,*/ + /*but support not good,need vlsi support optimize*/ + vlock_mode = VLOCK_MODE_MANUAL_PLL; + if (is_meson_gxtvbb_cpu() || + is_meson_txl_cpu() || is_meson_txlx_cpu() + || is_meson_tl1_cpu()) + vlock_en = 1; + else + vlock_en = 0; + + /*initial pll register address*/ + if (is_meson_tl1_cpu()) { + hhi_pll_reg_m = HHI_TCON_PLL_CNTL0; + hhi_pll_reg_frac = HHI_TCON_PLL_CNTL1; + /*hhi_pll_reg_vlock_ctl = HHI_HDMI_PLL_VLOCK_CNTL;*/ + } else if (get_cpu_type() >= + MESON_CPU_MAJOR_ID_GXL) { + hhi_pll_reg_m = HHI_HDMI_PLL_CNTL; + hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; + } else { + hhi_pll_reg_m = HHI_HDMI_PLL_CNTL; + hhi_pll_reg_frac = HHI_HDMI_PLL_CNTL2; + } + + /*initial enc register address*/ + switch (READ_VPP_REG_BITS(VPU_VIU_VENC_MUX_CTRL, + 0, 2)) { + case 0: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; +#if 0 /*enc mode not adapt to ENCP and ENCT*/ + case 2: + enc_max_line_addr = ENCP_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCP_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCP_VIDEO_MODE; + enc_max_line_switch_addr = + ENCP_MAX_LINE_SWITCH_POINT; + break; + case 3: + enc_max_line_addr = ENCT_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCT_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCT_VIDEO_MODE; + enc_max_line_switch_addr = + ENCT_MAX_LINE_SWITCH_POINT; + break; +#endif + default: + enc_max_line_addr = ENCL_VIDEO_MAX_LNCNT; + enc_max_pixel_addr = ENCL_VIDEO_MAX_PXCNT; + enc_video_mode_addr = ENCL_VIDEO_MODE; + enc_video_mode_adv_addr = ENCL_VIDEO_MODE_ADV; + enc_max_line_switch_addr = + ENCL_MAX_LINE_SWITCH_POINT; + break; + } + + /*back up orignal pll value*/ + vlock.val_m = vlock_get_panel_pll_m(); + vlock.val_frac = vlock_get_panel_pll_frac(); + + vlock.fsm_sts = VLOCK_STATE_NULL; + vlock.fsm_prests = VLOCK_STATE_NULL; + vlock.vf_sts = false; + vlock.vmd_chg = false; + vlock.md_support = false; + /* vlock.phlock_percent = phlock_percent; */ + vlock_clear_frame_counter(); + + + pr_info("%s vlock_en:%d\n", __func__, vlock_en); +} + +void vlock_dt_match_init(struct vecm_match_data_s *pdata) +{ + vlock.dtdata = pdata; + /*vlock_en = vlock.dtdata.vlk_support;*/ + pr_info("vlock dt support: %d\n", vlock.dtdata->vlk_support); + pr_info("vlock dt new_fsm: %d\n", vlock.dtdata->vlk_new_fsm); + pr_info("vlock dt hwver: %d\n", vlock.dtdata->vlk_hwver); + pr_info("vlock dt phlock_en: %d\n", vlock.dtdata->vlk_phlock_en); +} + +void vlock_set_phase(u32 percent) +{ + u32 vs_i_val = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + /*u32 vs_o_val = READ_VPP_REG(VPU_VLOCK_RO_VS_O_DIST);*/ + u32 data = 0; + + if (!vlock.dtdata->vlk_phlock_en) + return; + + if (percent > 100) { + pr_info("percent val err:%d\n", percent); + return; + } + + vlock.phlock_percent = percent; + data = (vs_i_val * (100 + vlock.phlock_percent))/200; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, data); + pr_info("LOOP1_PHSDIF_TGT:0x%x\n", data); + + /*reset*/ + data = READ_VPP_REG(VPU_VLOCK_CTRL); + data |= 1 << 2; + data |= 1 << 5; + WRITE_VPP_REG(VPU_VLOCK_CTRL, data); + data &= ~(1 << 2); + data &= ~(1 << 5); + WRITE_VPP_REG(VPU_VLOCK_CTRL, data); +} + +void vlock_set_phase_en(u32 en) +{ + if (en) + vlock.dtdata->vlk_phlock_en = true; + else + vlock.dtdata->vlk_phlock_en = false; + pr_info("vlock phlock_en=%d\n", en); +} + +void vlock_phaselock_check(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + /*vs_i*/ + u32 ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + u32 val; + static u32 cnt = 48; + + if (vlock.dtdata->vlk_phlock_en) { + if (cnt++ > 50) { + ia = READ_VPP_REG(VPU_VLOCK_RO_VS_I_DIST); + val = (ia * (100 + vlock.phlock_percent))/200; + WRITE_VPP_REG(VPU_VLOCK_LOOP1_PHSDIF_TGT, val); + cnt = 0; + #if 0 + /*reset*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + #endif + } + } +} + +bool vlock_get_phlock_flag(void) +{ + u32 flag; + u32 sts; + + if (!vlock.dtdata->vlk_phlock_en) + return false; + + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 17; + flag = flag&0x01; + + if (vlock.dtdata->vlk_new_fsm) + sts = vlock.fsm_sts; + else + sts = vlock_state; + + if (flag && (sts == VLOCK_STATE_ENABLE_STEP2_DONE)) + return true; + else + return false; +} + +bool vlock_get_vlock_flag(void) +{ + u32 flag; + u32 sts; + + flag = READ_VPP_REG(VPU_VLOCK_RO_LCK_FRM) >> 16; + flag = flag&0x01; + + if (vlock.dtdata->vlk_new_fsm) + sts = vlock.fsm_sts; + else + sts = vlock_state; + + if (flag && (sts == VLOCK_STATE_ENABLE_STEP2_DONE)) + return true; + else + return false; +} + +void vlock_enc_timing_monitor(void) +{ + static unsigned int pre_line, pre_pixel; + unsigned int cur_line, cur_pixel; + unsigned int val; + + val = READ_VPP_REG(VPU_VLOCK_RO_LINE_PIX_ADJ); + cur_pixel = (val & 0x0000ffff); + cur_line = (val >> 16) & 0x0000ffff; + + if ((cur_line != pre_line) || (cur_pixel != pre_pixel)) { + pr_info("vlock line=0x%x pixel=0x%x\n", + cur_line, cur_pixel); + pre_line = cur_line; + pre_pixel = cur_pixel; + } +} + +#if 1 + +u32 vlock_fsm_check_support(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = true; + + if (((pvlock->input_hz != pvlock->output_hz) && (vlock_adapt == 0)) || + (pvlock->input_hz == 0) || (pvlock->output_hz == 0) || + (((vf->type_original & VIDTYPE_TYPEMASK) + != VIDTYPE_PROGRESSIVE) && + is_meson_txlx_package_962E())) { + + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("[%s] for no support case!!!\n", + __func__); + pr_info("input_hz:%d, output_hz:%d\n", + pvlock->input_hz, pvlock->output_hz); + pr_info("type_original:0x%x\n", vf->type_original); + } + ret = false; + } + + if (vlock_vmode_change_status == VOUT_EVENT_MODE_CHANGE_PRE) { + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s] for vmode change pre case!!!\n", + __func__); + ret = false; + } + + return ret; +} + +u32 vlock_fsm_input_check(struct stvlock_sig_sts *vlock, struct vframe_s *vf) +{ + u32 ret = 0; + u32 vframe_sts; + struct vinfo_s *vinfo = NULL; + + if (vf == NULL) + vframe_sts = false; + else + vframe_sts = true; + + vlock_vmode_check(); + + if (vf != NULL) { + vinfo = get_current_vinfo(); + vlock->input_hz = vlock_check_input_hz(vf); + vlock->output_hz = vlock_check_output_hz( + vinfo->sync_duration_num, vinfo->sync_duration_den); + } + + /*check vf exist status*/ + if (vlock->vf_sts != vframe_sts) { + vlock->vf_sts = vframe_sts; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock vfsts chg %d\n", vframe_sts); + ret = 1; + } else if (vlock_vmode_change_status) { + /*check video mode status*/ + vlock->vmd_chg = true; + ret = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("vlock vmode chg\n"); + } + + if (vlock->vf_sts) + vlock->md_support = vlock_fsm_check_support(vlock, vf); + + return ret; +} + +u32 vlock_fsm_to_en_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + struct vinfo_s *vinfo; + + if ((vf->source_type != pre_source_type) || + (vf->source_mode != pre_source_mode) || + (pvlock->input_hz != pre_input_freq) || + (pvlock->output_hz != pre_output_freq) || + vlock_vmode_changed || + (pvlock->fsm_sts == + VLOCK_STATE_ENABLE_FORCE_RESET)) { + + /*back up orignal pll value*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &vlock.val_m);*/ + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &vlock.val_frac);*/ + vlock.val_m = vlock_get_panel_pll_m(); + vlock.val_frac = vlock_get_panel_pll_frac(); + if (vlock_debug & VLOCK_DEBUG_INFO) { + pr_info("HIU pll m[0x%x]=0x%x\n", + hhi_pll_reg_m, vlock.val_m); + pr_info("HIU pll f[0x%x]=0x%x\n", + hhi_pll_reg_frac, vlock.val_frac); + } + vinfo = get_current_vinfo(); + vlock_enable_step1(vf, vinfo, + pvlock->input_hz, pvlock->output_hz); + ret = 1; + } + + return ret; +} + +u32 vlock_fsm_en_step1_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + u32 input_vs_cnt; + + if ((pvlock->frame_cnt_in <= 3) && + ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | + VLOCK_MODE_MANUAL_PLL)))) { + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 5, 1); + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 1, 2, 1); + /*clear first 3 frame internal cnt*/ + WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM0, 0); + WRITE_VPP_REG(VPU_VLOCK_OVWRITE_ACCUM1, 0); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -0\n", __func__); + } else if ((pvlock->frame_cnt_in == 4) && + ((vlock_mode & (VLOCK_MODE_MANUAL_ENC | + VLOCK_MODE_MANUAL_PLL)))) { + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -1\n", __func__); + } else if (pvlock->frame_cnt_in == 5) { + /*input_vs_cnt =*/ + /*READ_VPP_REG_BITS(VPU_VLOCK_RO_VS_I_DIST,*/ + /* 0, 28);*/ + input_vs_cnt = XTAL_VLOCK_CLOCK/pvlock->input_hz; + /*tl1 not need */ + if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1) && + vf->type_original & VIDTYPE_TYPEMASK) + input_vs_cnt = input_vs_cnt << 1; + + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MAX, + input_vs_cnt*125/100); + WRITE_VPP_REG(VPU_VLOCK_LOOP1_IMISSYNC_MIN, + input_vs_cnt*70/100); + + /*cal accum1 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 2, 1); + /*cal accum0 value*/ + WRITE_VPP_REG_BITS(VPU_VLOCK_CTRL, 0, 5, 1); + + /* + * tl1 auto pll,swich clk need after + *several frames + */ + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + if (IS_AUTO_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x7, 0, 3); + else if (IS_MANUAL_MODE(vlock_mode)) + amvecm_hiu_reg_write_bits( + HHI_HDMI_PLL_VLOCK_CNTL, 0x6, 0, 3); + } + + ret = 1; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("%s -2\n", __func__); + } + + return ret; +} + +u32 vlock_fsm_en_step2_func(struct stvlock_sig_sts *pvlock, + struct vframe_s *vf) +{ + u32 ret = 0; + + if (vlock_dynamic_adjust && + (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) && + (IS_MANUAL_MODE(vlock_mode))) { + if (IS_MANUAL_ENC_MODE(vlock_mode)) + vlock_enable_step3_enc(); + else if (IS_MANUAL_PLL_MODE(vlock_mode)) + vlock_enable_step3_pll(); + else if (IS_MANUAL_SOFTENC_MODE(vlock_mode)) + vlock_enable_step3_soft_enc(); + } + + if (IS_ENC_MODE(vlock_mode)) + vlock_enc_timing_monitor(); + + /*check phase*/ + vlock_phaselock_check(pvlock, vf); + return ret; +} + + +void vlock_fsm_monitor(struct vframe_s *vf) +{ + u32 changed; + + changed = vlock_fsm_input_check(&vlock, vf); + switch (vlock.fsm_sts) { + case VLOCK_STATE_NULL: + if (vlock.vf_sts) { + /*have frame in*/ + if (vlock.frame_cnt_in++ >= 20) { + /*vframe input valid*/ + if (vlock.md_support) { + if (vlock_fsm_to_en_func(&vlock, vf)) { + vlock_clear_frame_counter(); + vlock.fsm_sts = + VLOCK_STATE_ENABLE_STEP1_DONE; + } else { + /*error waitting here*/ + vlock_clear_frame_counter(); + } + } + } + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE; + } else { + /*disabled and waitting here*/ + vlock_clear_frame_counter(); + } + break; + + case VLOCK_STATE_ENABLE_STEP1_DONE: + if (vlock.vf_sts) { + vlock.frame_cnt_in++; + if (vlock_fsm_en_step1_func(&vlock, vf)) + vlock.fsm_sts = VLOCK_STATE_ENABLE_STEP2_DONE; + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else { + vlock.frame_cnt_in = 0; + if (vlock.frame_cnt_no++ > vlock_dis_cnt_no_vf_limit) { + /*go to disable state*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } + } + break; + + case VLOCK_STATE_ENABLE_STEP2_DONE: + if (vlock.vf_sts) { + if (!vlock.md_support) { + /*function not support*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else if (vecm_latch_flag & FLAG_VLOCK_DIS) { + /*disable vlock by vecm cmd*/ + vlock_disable_step1(); + vlock_disable_step2(); + vlock_en = 0; + vecm_latch_flag &= ~FLAG_VLOCK_DIS; + if (vlock_debug & VLOCK_DEBUG_INFO) + pr_info("[%s] vlock dis\n", __func__); + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_NULL; + } else { + /*normal mode*/ + vlock.frame_cnt_no = 0; + vlock_fsm_en_step2_func(&vlock, vf); + } + } else if (vlock.vmd_chg) { + vlock_clear_frame_counter(); + vlock.vmd_chg = false; + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } else { + /*no frame input*/ + if (vlock.frame_cnt_no++ > vlock_dis_cnt_no_vf_limit) { + /*go to disable state*/ + vlock_clear_frame_counter(); + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP1_DONE; + } + } + break; + + case VLOCK_STATE_DISABLE_STEP1_DONE: + vlock_disable_step1(); + if (vlock_disable_step2()) + vlock.fsm_sts = VLOCK_STATE_NULL; + else + vlock.fsm_sts = VLOCK_STATE_DISABLE_STEP2_DONE; + break; + + case VLOCK_STATE_DISABLE_STEP2_DONE: + if (vlock_disable_step2()) + vlock.fsm_sts = VLOCK_STATE_NULL; + break; + + default: + pr_info("err state %d\n", vlock.fsm_sts); + break; + } + + /*capture log*/ + if (((vlock_mode & (VLOCK_MODE_AUTO_PLL | + VLOCK_MODE_AUTO_ENC))) && + vlock_log_en && (vlock_log_cnt < vlock_log_size) && + (vlock_debug & VLOCK_DEBUG_AUTO_MODE_LOG_EN)) { + vlock_reg_get(); + vlock_log_cnt++; + } + + if ((vlock_debug & VLOCK_DEBUG_INFO) && + vlock.fsm_sts != vlock.fsm_prests) { + pr_info(">>> %s fsm %d to %d\n", __func__, + vlock.fsm_prests, vlock.fsm_sts); + vlock.fsm_prests = vlock.fsm_sts; + } +} +#endif + /*new packed separeted from amvecm_on_vs,avoid the influencec of repeate call, *which may affect vlock process */ void vlock_process(struct vframe_s *vf) { - if (probe_ok == 0) + if (probe_ok == 0 || !vlock_en) + return; + + if (vlock_debug & VLOCK_DEBUG_FSM_DIS) return; /* todo:vlock processs only for tv chip */ - if (is_meson_gxtvbb_cpu() || - is_meson_txl_cpu() || is_meson_txlx_cpu() - || is_meson_txhd_cpu()) { + if (vlock.dtdata->vlk_new_fsm) + vlock_fsm_monitor(vf); + else { if (vf != NULL) amve_vlock_process(vf); else @@ -1216,7 +2080,10 @@ void vlock_param_set(unsigned int val, enum vlock_param_e sel) } void vlock_status(void) { + struct vinfo_s *vinfo; + pr_info("\n current vlock parameters status:\n"); + pr_info("vlock driver version : %s\n", VLOCK_VER); pr_info("vlock_mode:%d\n", vlock_mode); pr_info("vlock_en:%d\n", vlock_en); pr_info("vlock_adapt:%d\n", vlock_adapt); @@ -1227,6 +2094,7 @@ void vlock_status(void) pr_info("vlock_debug:0x%x\n", vlock_debug); pr_info("vlock_dynamic_adjust:%d\n", vlock_dynamic_adjust); pr_info("vlock_state:%d\n", vlock_state); + pr_info("vecm_latch_flag:0x%x\n", vecm_latch_flag); pr_info("vlock_sync_limit_flag:%d\n", vlock_sync_limit_flag); pr_info("pre_hiu_reg_m:0x%x\n", pre_hiu_reg_m); pr_info("pre_hiu_reg_frac:0x%x\n", pre_hiu_reg_frac); @@ -1248,17 +2116,52 @@ void vlock_status(void) pr_info("vlock_intput_type:%d\n", vlock_intput_type); pr_info("vlock_pll_adj_limit:%d\n", vlock_pll_adj_limit); pr_info("vlock_pll_val_last:%d\n", vlock_pll_val_last); - pr_info("vlock driver version : %s\n", VLOCK_VER); + pr_info("vlk_fsm_sts:%d(2 is working)\n", vlock.fsm_sts); + pr_info("vlk_support:%d\n", vlock.dtdata->vlk_support); + pr_info("vlk_new_fsm:%d\n", vlock.dtdata->vlk_new_fsm); + pr_info("vlk_phlock_en:%d\n", vlock.dtdata->vlk_phlock_en); + pr_info("vlk_hwver:%d\n", vlock.dtdata->vlk_hwver); + pr_info("phlock flag:%d\n", vlock_get_phlock_flag()); + pr_info("vlock flag:%d\n", vlock_get_vlock_flag()); + pr_info("phase:%d\n", vlock.phlock_percent); + vinfo = get_current_vinfo(); + pr_info("vinfo sync_duration_num:%d\n", vinfo->sync_duration_num); + pr_info("vinfo sync_duration_den:%d\n", vinfo->sync_duration_den); + pr_info("vinfo video_clk:%d\n", vinfo->video_clk); + pr_info("vframe input_hz:%d\n", vlock.input_hz); + pr_info("vframe output_hz:%d\n", vlock.output_hz); } + void vlock_reg_dump(void) { unsigned int addr; + unsigned int val; pr_info("----dump vlock reg----\n"); for (addr = (0x3000); addr <= (0x3020); addr++) pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", (0xd0100000+(addr<<2)), addr, READ_VPP_REG(addr)); + + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) { + for (addr = (0x3021); addr <= (0x302b); addr++) + pr_info("[0x%x]vcbus[0x%04x]=0x%08x\n", + (0xd0100000+(addr<<2)), addr, + READ_VPP_REG(addr)); + amvecm_hiu_reg_read(HHI_HDMI_PLL_VLOCK_CNTL, &val); + pr_info("HIU [0x%04x]=0x%08x\n", HHI_HDMI_PLL_VLOCK_CNTL, val); + } + /*amvecm_hiu_reg_read(hhi_pll_reg_m, &val);*/ + val = vlock_get_panel_pll_m(); + pr_info("HIU pll m[0x%04x]=0x%08x\n", hhi_pll_reg_m, val); + /*amvecm_hiu_reg_read(hhi_pll_reg_frac, &val);*/ + val = vlock_get_panel_pll_frac(); + pr_info("HIU pll f[0x%04x]=0x%08x\n", hhi_pll_reg_frac, val); + + /*back up orignal pll value*/ + pr_info("HIU pll m[0x%x]=0x%x\n", hhi_pll_reg_m, vlock.val_m); + pr_info("HIU pll f[0x%x]=0x%x\n", hhi_pll_reg_frac, vlock.val_frac); + } /*work around method for vlock process hdmirx input interlace source.@20170803 **for interlace input,TOP and BOT have one line delta, @@ -1270,8 +2173,17 @@ void vlock_reg_dump(void) void vdin_vlock_input_sel(unsigned int type, enum vframe_source_type_e source_type) { + if (vlock.dtdata->vlk_hwver >= vlock_hw_ver2) + return; + /* + *1:fromhdmi rx , + *2:from tv-decoder, + *3:from dvin, + *4:from dvin, + *5:from 2nd bt656 + */ vlock_intput_type = type & VIDTYPE_TYPEMASK; - if ((vlock_intput_type == 0) || + if ((vlock_intput_type == VIDTYPE_PROGRESSIVE) || (vlock_mode & VLOCK_MODE_MANUAL_SOFT_ENC)) return; if (vlock_intput_type == VIDTYPE_INTERLACE_TOP) { @@ -1351,6 +2263,7 @@ void vlock_param_config(struct device_node *node) vlock_mode &= ~VLOCK_MODE_MANUAL_MIX_PLL_ENC; vlock_mode |= VLOCK_MODE_MANUAL_PLL; } + pr_info("param_config vlock_en:%d\n", vlock_en); } int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, @@ -1377,5 +2290,19 @@ int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, return 0; } +static int __init phlock_phase_config(char *str) +{ + unsigned char *ptr = str; + + pr_info("%s: bootargs is %s.\n", __func__, str); + if (strstr(ptr, "1")) + vlock.phlock_percent = 99; + else + vlock.phlock_percent = 40; + + return 0; +} +__setup("video_reverse=", phlock_phase_config); + /*video lock end*/ diff --git a/drivers/amlogic/media/enhancement/amvecm/vlock.h b/drivers/amlogic/media/enhancement/amvecm/vlock.h index 96784fb753f8..a91b1c5bbdbd 100644 --- a/drivers/amlogic/media/enhancement/amvecm/vlock.h +++ b/drivers/amlogic/media/enhancement/amvecm/vlock.h @@ -23,7 +23,7 @@ #include #include "linux/amlogic/media/amvecm/ve.h" -#define VLOCK_VER "Ref.2018/11/07a" +#define VLOCK_VER "Ref.2019/1/24" #define VLOCK_REG_NUM 33 @@ -59,6 +59,21 @@ enum vlock_param_e { VLOCK_PARAM_MAX, }; +struct stvlock_sig_sts { + u32 fsm_sts; + u32 fsm_prests; + u32 vf_sts; + u32 vmd_chg; + u32 frame_cnt_in; + u32 frame_cnt_no; + u32 input_hz; + u32 output_hz; + bool md_support; + u32 phlock_percent; + struct vecm_match_data_s *dtdata; + u32 val_frac; + u32 val_m; +}; extern void amve_vlock_process(struct vframe_s *vf); extern void amve_vlock_resume(void); extern void vlock_param_set(unsigned int val, enum vlock_param_e sel); @@ -67,7 +82,7 @@ extern void vlock_reg_dump(void); extern void vlock_log_start(void); extern void vlock_log_stop(void); extern void vlock_log_print(void); - +extern int phase_lock_check(void); #define VLOCK_STATE_NULL 0 #define VLOCK_STATE_ENABLE_STEP1_DONE 1 @@ -77,12 +92,45 @@ extern void vlock_log_print(void); #define VLOCK_STATE_ENABLE_FORCE_RESET 5 /* video lock */ -#define VLOCK_MODE_AUTO_ENC (1 << 0) -#define VLOCK_MODE_AUTO_PLL (1 << 1) -#define VLOCK_MODE_MANUAL_PLL (1 << 2) -#define VLOCK_MODE_MANUAL_ENC (1 << 3) -#define VLOCK_MODE_MANUAL_SOFT_ENC (1 << 4) -#define VLOCK_MODE_MANUAL_MIX_PLL_ENC (1 << 5) +enum VLOCK_MD { + VLOCK_MODE_AUTO_ENC = 0x01, + VLOCK_MODE_AUTO_PLL = 0x02, + VLOCK_MODE_MANUAL_PLL = 0x04, + VLOCK_MODE_MANUAL_ENC = 0x08, + VLOCK_MODE_MANUAL_SOFT_ENC = 0x10, + VLOCK_MODE_MANUAL_MIX_PLL_ENC = 0x20, +}; + +#define IS_MANUAL_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_PLL | \ + VLOCK_MODE_MANUAL_ENC | \ + VLOCK_MODE_MANUAL_SOFT_ENC)) + +#define IS_AUTO_MODE(md) (md & \ + (VLOCK_MODE_AUTO_PLL | \ + VLOCK_MODE_AUTO_ENC)) + +#define IS_PLL_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_PLL | \ + VLOCK_MODE_AUTO_PLL)) + +#define IS_ENC_MODE(md) (md & \ + (VLOCK_MODE_MANUAL_ENC | \ + VLOCK_MODE_MANUAL_SOFT_ENC | \ + VLOCK_MODE_AUTO_ENC)) + +#define IS_AUTO_PLL_MODE(md) (md & \ + VLOCK_MODE_AUTO_PLL) + +#define IS_MANUAL_ENC_MODE(md) (md & \ + VLOCK_MODE_MANUAL_ENC) + +#define IS_MANUAL_PLL_MODE(md) (md & \ + VLOCK_MODE_MANUAL_PLL) + +#define IS_MANUAL_SOFTENC_MODE(md) (md & \ + VLOCK_MODE_MANUAL_SOFT_ENC) + #define XTAL_VLOCK_CLOCK 24000000/*vlock use xtal clock*/ @@ -95,18 +143,19 @@ extern void vlock_log_print(void); #define VLOCK_PLL_ADJ_LIMIT 9/*vlock pll adj limit(0x300a default)*/ /*vlock_debug mask*/ -#define VLOCK_DEBUG_INFO (1 << 0) -#define VLOCK_DEBUG_FLUSH_REG_DIS (1 << 1) -#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (1 << 2) -#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (1 << 3) -#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (1 << 4) -#define VLOCK_DEBUG_PLL2ENC_DIS (1 << 5) +#define VLOCK_DEBUG_INFO (0x1) +#define VLOCK_DEBUG_FLUSH_REG_DIS (0x2) +#define VLOCK_DEBUG_ENC_LINE_ADJ_DIS (0x4) +#define VLOCK_DEBUG_ENC_PIXEL_ADJ_DIS (0x8) +#define VLOCK_DEBUG_AUTO_MODE_LOG_EN (0x10) +#define VLOCK_DEBUG_PLL2ENC_DIS (0x20) +#define VLOCK_DEBUG_FSM_DIS (0x40) /* 0:enc;1:pll;2:manual pll */ extern unsigned int vlock_mode; extern unsigned int vlock_en; extern unsigned int vecm_latch_flag; -extern void __iomem *amvecm_hiu_reg_base; +/*extern void __iomem *amvecm_hiu_reg_base;*/ extern unsigned int probe_ok; extern void lcd_ss_enable(bool flag); @@ -123,4 +172,9 @@ extern void vlock_lcd_param_work(struct work_struct *p_work); extern int vlock_notify_callback(struct notifier_block *block, unsigned long cmd, void *para); #endif +extern void vlock_status_init(void); +extern void vlock_dt_match_init(struct vecm_match_data_s *pdata); +extern void vlock_set_en(bool en); +extern void vlock_set_phase(u32 percent); +extern void vlock_set_phase_en(u32 en); diff --git a/drivers/amlogic/media/video_processor/pic_dev/picdec.c b/drivers/amlogic/media/video_processor/pic_dev/picdec.c index 7673c1f33cdc..c9604ebcd811 100644 --- a/drivers/amlogic/media/video_processor/pic_dev/picdec.c +++ b/drivers/amlogic/media/video_processor/pic_dev/picdec.c @@ -787,6 +787,7 @@ static int picdec_memset_phyaddr(ulong phys, u32 size, u32 val) if (!p) return -1; memset(p, val, span); + codec_mm_dma_flush(p, span, DMA_TO_DEVICE); codec_mm_unmap_phyaddr(p); } return 0; @@ -896,6 +897,7 @@ static int copy_phybuf_to_file(ulong phys, u32 size, p = codec_mm_vmap(addr, span); if (!p) return -1; + codec_mm_dma_flush(p, span, DMA_FROM_DEVICE); vfs_write(fp, (char *)p, span, &pos); pos += span; diff --git a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c index 8a582116cbd5..78a15aae4099 100644 --- a/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c +++ b/drivers/amlogic/media/video_processor/video_dev/amlvideo2.c @@ -5054,6 +5054,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) } para.dest_hactive = dst_w; para.dest_vactive = dst_h; + para.reserved |= PARAM_STATE_SCREENCAP; if (para.scan_mode == TVIN_SCAN_MODE_INTERLACED) para.dest_vactive = para.dest_vactive / 2; if (para.port == TVIN_PORT_VIU1_VIDEO) { diff --git a/drivers/amlogic/media/video_sink/video.c b/drivers/amlogic/media/video_sink/video.c index 503592d05746..a7e2662ffaab 100644 --- a/drivers/amlogic/media/video_sink/video.c +++ b/drivers/amlogic/media/video_sink/video.c @@ -4091,6 +4091,9 @@ static void viu_set_dcu(struct vpp_frame_par_s *frame_par, struct vframe_s *vf) if (vf && (vf->source_type != VFRAME_SOURCE_TYPE_HDMI)) r |= (1 << 19); /* dos_uncomp */ + + if (type & VIDTYPE_COMB_MODE) + r |= (1 << 20); } VSYNC_WR_MPEG_REG(AFBC_ENABLE, r); diff --git a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c index 0feac45d341b..4f02b42017ae 100644 --- a/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c +++ b/drivers/amlogic/media/vin/tvin/bt656/bt656_601_in.c @@ -1129,7 +1129,8 @@ static int amvdec_656in_probe(struct platform_device *pdev) if (is_meson_gxtvbb_cpu() || is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_g12a_cpu() || - is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + is_meson_g12b_cpu() || is_meson_tl1_cpu() || + is_meson_tm2_cpu()) { hw_cnt = 1; } else if (is_meson_gxbb_cpu()) { hw_cnt = 2; diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c index 2e99da3573fb..66b5242956c0 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.c @@ -764,6 +764,16 @@ void hdmirx_get_repetition_info(struct tvin_sig_property_s *prop) HDMI_DE_REPEAT_DONE_FLAG; } +/* + * hdmirx_get_allm_mode - get allm mode + */ +void hdmirx_get_latency_info(struct tvin_sig_property_s *prop) +{ + prop->latency.allm_mode = rx.vs_info_details.allm_mode; + prop->latency.it_content = it_content; + prop->latency.cn_type = rx.cur.cn_type; +} + /* * hdmirx_get_hdr_info - get hdr info */ @@ -858,6 +868,7 @@ void hdmirx_get_sig_property(struct tvin_frontend_s *fe, hdmirx_set_timing_info(prop); hdmirx_get_hdr_info(prop); hdmirx_get_vsi_info(prop); + hdmirx_get_latency_info(prop); prop->skip_vf_num = vdin_drop_frame_cnt; } diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h index 02fcd27ead24..fb3d89a3ae79 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_drv.h @@ -40,7 +40,7 @@ * * */ -#define RX_VER1 "ver.2018/10/22" +#define RX_VER1 "ver.2018/12/24" /* * * @@ -200,6 +200,13 @@ enum map_addr_module_e { MAP_ADDR_MODULE_NUM }; +enum rx_cn_type_e { + CN_GRAPHICS, + CN_PHOTO, + CN_CINEMA, + CN_GAME, +}; + /** * @short HDMI RX controller video parameters * @@ -244,6 +251,7 @@ struct rx_video_info { enum hdmi_vic_e sw_vic; uint8_t sw_dvi; unsigned int it_content; + enum rx_cn_type_e cn_type; /** AVI Q1-0, RGB quantization range */ unsigned int rgb_quant_range; /** AVI Q1-0, YUV quantization range */ @@ -312,6 +320,7 @@ struct vsi_info_s { bool backlt_md_bit; unsigned int dolby_timeout; unsigned int eff_tmax_pq; + bool allm_mode; }; #define CHANNEL_STATUS_SIZE 24 diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c index f23144455727..d0394cf7cb9b 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.c @@ -2363,6 +2363,8 @@ void rx_get_video_info(void) /* AVI parameters */ rx.cur.hw_vic = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, VID_IDENT_CODE); + rx.cur.cn_type = + hdmirx_rd_bits_dwc(DWC_PDEC_AVI_HB, CONETNT_TYPE); rx.cur.repeat = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_HB, PIX_REP_FACTOR); rx.cur.colorspace = diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h index 8c64f4ed22ee..e221be70c157 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_hw.h @@ -695,6 +695,8 @@ #define N_DECODED MSK(20, 0) /** Register address: auxiliary video information info frame */ #define DWC_PDEC_AVI_HB (0x3A0UL) +/** AVI content type*/ +#define CONETNT_TYPE MSK(2, 28) /** PR3-0, pixel repetition factor */ #define PIX_REP_FACTOR MSK(4, 24) /** Q1-0, YUV quantization range */ diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c index d0ba34c96908..c85fb5c49869 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.c @@ -1391,6 +1391,10 @@ void rx_get_vsi_info(void) ((pkt->sbpkt.payload.data[0] & 0xff) == 0)) { rx.vs_info_details.dolby_vision = false; } + } else if (pkt->ieee == 0xd85dc4) { + /*TODO:hdmi2.1 spec vsi packet*/ + tmp = pkt->sbpkt.payload.data[0] & _BIT(9); + rx.vs_info_details.allm_mode = tmp ? true : false; } else { /*3d VSI*/ if (pkt->sbpkt.vsi_3Dext.vdfmt == VSI_FORMAT_3D_FORMAT) { diff --git a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.h b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.h index c9fcc1a6bec2..8a7f0202ab95 100644 --- a/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.h +++ b/drivers/amlogic/media/vin/tvin/hdmirx/hdmi_rx_pktinfo.h @@ -617,7 +617,18 @@ struct vsi_infoframe_st { /*pb6*/ uint8_t data[22];/* val=0 */ } __packed vsi_DobV; - + /*TODO:hdmi2.1 spec vsi packet*/ + struct vsi_st_21 { + /*pb4*/ + uint8_t ver:8; + /*pb5*/ + uint8_t threeD_valid:1; + uint8_t allm_mode:1; + uint8_t rsvd1:2; + uint8_t ccbpc:4; + /*pb6*/ + /*todo*/ + } __packed vsi_st_21; } __packed sbpkt; } __packed; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index f9e2416f1aa6..630042c9f536 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -101,6 +101,8 @@ static int cutwindow_val_h_level2 = 18; static int cutwindow_val_h_level3 = 20; static int cutwindow_val_h_level4 = 62;/*48-->62 for ntsc-m*/ +/*tvconfig snow config*/ +static bool snow_cfg; /*1: snow function on;*/ /*0: off snow function*/ bool tvafe_snow_function_flag; @@ -259,7 +261,8 @@ int tvafe_dec_open(struct tvin_frontend_s *fe, enum tvin_port_e port) #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT /*only txlx chip enabled*/ if (tvafe_cpu_type() == CPU_TYPE_TXLX || - tvafe_cpu_type() == CPU_TYPE_TL1) { + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2) { /*synctip set to 0 when tvafe working&&av connected*/ /*enable clamp if av connected*/ if (port == TVIN_PORT_CVBS1) { @@ -323,6 +326,7 @@ void tvafe_dec_start(struct tvin_frontend_s *fe, enum tvin_sig_fmt_e fmt) enum tvin_port_e port = devp->tvafe.parm.port; mutex_lock(&devp->afe_mutex); + manual_flag = 0; if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { tvafe_pr_err("tvafe_dec_start(%d) decode havn't opened\n", @@ -352,7 +356,9 @@ void tvafe_dec_start(struct tvin_frontend_s *fe, enum tvin_sig_fmt_e fmt) W_APB_REG(CVD2_H_LOOP_MAXSTATE, 0x9); #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT - if (tvafe_cpu_type() == CPU_TYPE_TXLX) { + if (tvafe_cpu_type() == CPU_TYPE_TXLX || + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2) { if (port == TVIN_PORT_CVBS1) tvafe_avin_detect_ch1_anlog_enable(0); else if (port == TVIN_PORT_CVBS2) @@ -418,7 +424,9 @@ void tvafe_dec_stop(struct tvin_frontend_s *fe, enum tvin_port_e port) tvafe_cvd2_set_default_de(&tvafe->cvd2); } #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT - if (tvafe_cpu_type() == CPU_TYPE_TXLX) { + if (tvafe_cpu_type() == CPU_TYPE_TXLX || + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2) { if (port == TVIN_PORT_CVBS1) tvafe_avin_detect_ch1_anlog_enable(1); else if (port == TVIN_PORT_CVBS2) @@ -487,7 +495,8 @@ void tvafe_dec_close(struct tvin_frontend_s *fe) #endif #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AVDETECT if (tvafe_cpu_type() == CPU_TYPE_TXLX || - tvafe_cpu_type() == CPU_TYPE_TL1) { + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2) { /*avsync tip set 1 to resume av detect*/ if (tvafe->parm.port == TVIN_PORT_CVBS1) { avport_opened = 0; @@ -645,6 +654,17 @@ bool tvafe_is_nosig(struct tvin_frontend_s *fe) if ((port >= TVIN_PORT_CVBS0) && (port <= TVIN_PORT_CVBS3)) { ret = tvafe_cvd2_no_sig(&tvafe->cvd2, &devp->mem); + /*fix black side when config atv snow*/ + if (ret && (port == TVIN_PORT_CVBS3) && + (devp->flags & TVAFE_FLAG_DEV_SNOW_FLAG) && + (tvafe->cvd2.config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) && + (tvafe->cvd2.info.state != TVAFE_CVD2_STATE_FIND)) + tvafe_snow_config_acd(); + else if ((tvafe->cvd2.config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) && + (tvafe->cvd2.info.state == TVAFE_CVD2_STATE_FIND) && + (port == TVIN_PORT_CVBS3)) + tvafe_snow_config_acd_resume(); + /* normal sigal & adc reg error, reload source mux */ if (tvafe->cvd2.info.adc_reload_en && !ret) tvafe_set_source_muxing(port, devp->pinmux); @@ -808,6 +828,18 @@ static bool tvafe_cvbs_get_secam_phase(struct tvin_frontend_s *fe) } +bool tvafe_get_snow_cfg(void) +{ + return snow_cfg; +} +EXPORT_SYMBOL(tvafe_get_snow_cfg); + +void tvafe_set_snow_cfg(bool cfg) +{ + snow_cfg = cfg; +} +EXPORT_SYMBOL(tvafe_set_snow_cfg); + /**check frame skip,only for av input*/ static bool tvafe_cvbs_check_frame_skip(struct tvin_frontend_s *fe) { @@ -878,6 +910,7 @@ static long tvafe_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = 0; + unsigned int snowcfg = 0; void __user *argp = (void __user *)arg; struct tvafe_dev_s *devp = file->private_data; struct tvafe_info_s *tvafe = &devp->tvafe; @@ -893,8 +926,8 @@ static long tvafe_ioctl(struct file *file, return -EPERM; mutex_lock(&devp->afe_mutex); - if (!(devp->flags & TVAFE_FLAG_DEV_OPENED)) { - + if (!(devp->flags & TVAFE_FLAG_DEV_OPENED) && + cmd != TVIN_IOC_S_AFE_SONWCFG) { tvafe_pr_info("%s, tvafe device is disable, ignore the command %d\n", __func__, cmd); mutex_unlock(&devp->afe_mutex); @@ -922,6 +955,20 @@ static long tvafe_ioctl(struct file *file, break; } + case TVIN_IOC_S_AFE_SONWCFG: + /*tl1/txhd tvconfig snow en/disable*/ + if (copy_from_user(&snowcfg, argp, + sizeof(unsigned int))) { + tvafe_pr_info("snowcfg: get param err\n"); + ret = -EINVAL; + break; + } + if (snowcfg == 1) + tvafe_set_snow_cfg(true); + else + tvafe_set_snow_cfg(false); + tvafe_pr_info("tvconfig snow:%d\n", snow_cfg); + break; case TVIN_IOC_S_AFE_SONWON: devp->flags |= TVAFE_FLAG_DEV_SNOW_FLAG; tvafe_snow_function_flag = true; @@ -963,6 +1010,8 @@ static long tvafe_ioctl(struct file *file, tvafe->cvd2.manual_fmt = fmt; tvafe_pr_info("%s: ioctl set cvd2 manual fmt:%s.\n", __func__, tvin_sig_fmt_str(fmt)); + if (fmt != TVIN_SIG_FMT_NULL) + manual_flag = 1; break; } default: @@ -1145,6 +1194,11 @@ struct meson_tvafe_data meson_tl1_tvafe_data = { .name = "meson-tl1-tvafe", }; +struct meson_tvafe_data meson_tm2_tvafe_data = { + .cpu_id = CPU_TYPE_TM2, + .name = "meson-tm2-tvafe", +}; + static const struct of_device_id meson_tvafe_dt_match[] = { { .compatible = "amlogic, tvafe-gxtvbb", @@ -1161,6 +1215,9 @@ static const struct of_device_id meson_tvafe_dt_match[] = { }, { .compatible = "amlogic, tvafe-tl1", .data = &meson_tl1_tvafe_data, + }, { + .compatible = "amlogic, tvafe-tm2", + .data = &meson_tm2_tvafe_data, }, {}, }; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h index 7fe836ff993c..0c42042b9369 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.h @@ -32,7 +32,7 @@ /* ************************************************* */ /* *** macro definitions ********************************************* */ /* *********************************************************** */ -#define TVAFE_VER "Ref.2018/06/27" +#define TVAFE_VER "Ref.2019/03/18" /* used to set the flag of tvafe_dev_s */ #define TVAFE_FLAG_DEV_OPENED 0x00000010 @@ -94,6 +94,9 @@ struct tvafe_dev_s { unsigned int sizeof_tvafe_dev_s; }; +bool tvafe_get_snow_cfg(void); +void tvafe_set_snow_cfg(bool cfg); + typedef int (*hook_func_t)(void); extern void aml_fe_hook_cvd(hook_func_t atv_mode, hook_func_t cvd_hv_lock, hook_func_t get_fmt); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c index 60759b13e39e..b697da41767b 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.c @@ -933,12 +933,20 @@ struct meson_avin_data tl1_data = { .name = "meson-tl1-avin-detect", }; +struct meson_avin_data tm2_data = { + .cpu_id = AVIN_CPU_TYPE_TM2, + .name = "meson-tm2-avin-detect", +}; + static const struct of_device_id tvafe_avin_dt_match[] = { { .compatible = "amlogic, tvafe_avin_detect", }, { .compatible = "amlogic, tl1_tvafe_avin_detect", .data = &tl1_data, }, + { .compatible = "amlogic, tm2_tvafe_avin_detect", + .data = &tm2_data, + }, {}, }; #else diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.h index f95f06e92138..6c8c7656429e 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_avin_detect.h @@ -136,6 +136,7 @@ enum avin_cpu_type { AVIN_CPU_TYPE_TXLX = 1, AVIN_CPU_TYPE_TXHD = 2, AVIN_CPU_TYPE_TL1 = 3, + AVIN_CPU_TYPE_TM2 = 4, AVIN_CPU_TYPE_MAX, }; diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c index 610992f3afd4..2e3ff29864a7 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_cvd.c @@ -27,6 +27,7 @@ #include #include "../tvin_global.h" #include "../tvin_format_table.h" +#include "tvafe.h" #include "tvafe_regs.h" #include "tvafe_cvd.h" #include "tvafe_debug.h" @@ -418,8 +419,10 @@ static void tvafe_cvd2_write_mode_reg(struct tvafe_cvd2_s *cvd2, } /*setting for txhd snow*/ - if (tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_get_snow_cfg() && + (tvafe_cpu_type() == CPU_TYPE_TXHD || + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2)) { W_APB_BIT(CVD2_OUTPUT_CONTROL, 3, 5, 2); W_APB_REG(ACD_REG_6C, 0x80500000); } @@ -1872,15 +1875,15 @@ static void tvafe_cvd2_auto_de(struct tvafe_cvd2_s *cvd2) W_APB_REG(ACD_REG_2E, tmp); scene_colorful_old = 0; if (cvd_dbg_en) - tvafe_pr_info("%s: vlines:%d, de_offset:%d tmp:%x\n", + tvafe_pr_info("%s: lrg vlines:%d, de_offset:%d tmp:%x\n", __func__, l_ave, lines->de_offset, tmp); } } else { if (lines->de_offset > 0) { tmp = ((TVAFE_CVD2_PAL_DE_START - - lines->de_offset) << 16) | + lines->de_offset + 1) << 16) | (288 + TVAFE_CVD2_PAL_DE_START - - lines->de_offset); + lines->de_offset + 1); W_APB_REG(ACD_REG_2E, tmp); scene_colorful_old = 0; if (cvd_dbg_en) @@ -1994,6 +1997,12 @@ static void tvafe_cvd2_reinit(struct tvafe_cvd2_s *cvd2) #ifdef TVAFE_SET_CVBS_PGA_EN tvafe_cvd2_reset_pga(); #endif + /*pali to nosignal,restore default vstart-end after auto de*/ + if (cvd2->config_fmt == TVIN_SIG_FMT_CVBS_PAL_I) { + W_APB_REG(ACD_REG_2E, 0x170137); + if (cvd_dbg_en) + pr_info("[tvafe..] %s: reset auto de.\n", __func__); + } /* init variable */ memset(&cvd2->info, 0, sizeof(struct tvafe_cvd2_info_s)); cvd2->cvd2_init_en = true; @@ -2320,6 +2329,15 @@ inline void tvafe_cvd2_adj_hs(struct tvafe_cvd2_s *cvd2, cvd2->info.hs_adj_level = 0; acd_h = acd_h_back; } + } else { + /*signal unstable,set default value*/ + W_APB_REG(ACD_REG_2D, acd_h_back); + W_APB_BIT(CVD2_ACTIVE_VIDEO_HSTART, cvd_2e, + HACTIVE_START_BIT, HACTIVE_START_WID); + W_APB_BIT(ACD_REG_28, acd_128, 16, 5); + cvd2->info.hs_adj_en = 0; + cvd2->info.hs_adj_level = 0; + acd_h = acd_h_back; } } @@ -2606,7 +2624,8 @@ void tvafe_snow_config(unsigned int onoff) { if (tvafe_snow_function_flag == 0 || tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2) return; if (onoff) W_APB_BIT(CVD2_OUTPUT_CONTROL, 3, BLUE_MODE_BIT, BLUE_MODE_WID); @@ -2617,7 +2636,8 @@ void tvafe_snow_config(unsigned int onoff) void tvafe_snow_config_clamp(unsigned int onoff) { if (tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { + tvafe_cpu_type() == CPU_TYPE_TL1 || + tvafe_cpu_type() == CPU_TYPE_TM2) { if (onoff) vdin_adjust_tvafesnow_brightness(); return; @@ -2637,7 +2657,6 @@ void tvafe_snow_config_acd(void) /*0x8e035e is debug test result*/ if (acd_h_config) W_APB_REG(ACD_REG_2D, acd_h_config); - acd_h = acd_h_back; } /*only for pal-i*/ void tvafe_snow_config_acd_resume(void) diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c index 44993fd201c9..f6786fe1a83a 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_debug.c @@ -256,6 +256,18 @@ static ssize_t tvafe_store(struct device *dev, } } else if (!strncmp(buff, "afe_ver", strlen("afe_ver"))) { tvafe_pr_info("tvafe version : %s\n", TVAFE_VER); + } else if (!strncmp(buff, "snowcfg", strlen("snowcfg"))) { + if (kstrtoul(parm[1], 10, &val) < 0) { + kfree(buf_orig); + return -EINVAL; + } + if (val) { + tvafe_set_snow_cfg(true); + tvafe_pr_info("[tvafe..]hadware snow cfg en\n"); + } else { + tvafe_set_snow_cfg(false); + tvafe_pr_info("[tvafe..]hadware snow cfg dis\n"); + } } else if (!strncmp(buff, "snowon", strlen("snowon"))) { if (kstrtoul(parm[1], 10, &val) < 0) { kfree(buf_orig); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index 70c8faacf8e1..3f7be31d44f7 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -247,21 +247,23 @@ static enum tvafe_adc_ch_e tvafe_adc_pin_muxing( if (tvafe_cpu_type() == CPU_TYPE_TXL || tvafe_cpu_type() == CPU_TYPE_TXLX || tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { + tvafe_cpu_type() >= CPU_TYPE_TL1) { tvafe_pr_info("[tvafe]%s:pin:%d\n", __func__, (unsigned int)pin); if (pin == TVAFE_CVBS_IN0) { W_APB_BIT(TVFE_VAFE_CTRL1, 1, VAFE_IN_SEL_BIT, VAFE_IN_SEL_WID); - W_APB_BIT(TVFE_VAFE_CTRL2, 3, 4, 3); + if (tvafe_cpu_type() < CPU_TYPE_TL1) + W_APB_BIT(TVFE_VAFE_CTRL2, 3, 4, 3); ret = TVAFE_ADC_CH_0; } else if (pin == TVAFE_CVBS_IN1) { W_APB_BIT(TVFE_VAFE_CTRL1, 2, VAFE_IN_SEL_BIT, VAFE_IN_SEL_WID); - W_APB_BIT(TVFE_VAFE_CTRL2, 5, 4, 3); + if (tvafe_cpu_type() < CPU_TYPE_TL1) + W_APB_BIT(TVFE_VAFE_CTRL2, 5, 4, 3); ret = TVAFE_ADC_CH_1; } else if (pin == TVAFE_CVBS_IN2) { @@ -384,7 +386,7 @@ static void tvafe_set_cvbs_default(struct tvafe_cvd2_s *cvd2, unsigned int i = 0; /**disable auto mode clock**/ - if (tvafe_cpu_type() != CPU_TYPE_TL1) + if (tvafe_cpu_type() < CPU_TYPE_TL1) W_HIU_REG(HHI_TVFE_AUTOMODE_CLK_CNTL, 0); /*config adc*/ @@ -400,7 +402,7 @@ static void tvafe_set_cvbs_default(struct tvafe_cvd2_s *cvd2, W_HIU_REG(HHI_DADC_CNTL, 0x00102038); W_HIU_REG(HHI_DADC_CNTL2, 0x00000401); W_HIU_REG(HHI_DADC_CNTL3, 0x00082183); - } else if (tvafe_cpu_type() == CPU_TYPE_TL1) { + } else if (tvafe_cpu_type() >= CPU_TYPE_TL1) { /** DADC CNTL for LIF signal input **/ W_HIU_REG(HHI_DADC_CNTL, 0x0030303c); W_HIU_REG(HHI_DADC_CNTL2, 0x00003480); @@ -421,7 +423,7 @@ static void tvafe_set_cvbs_default(struct tvafe_cvd2_s *cvd2, W_HIU_REG(HHI_DADC_CNTL, 0x00102038); W_HIU_REG(HHI_DADC_CNTL2, 0x00000400); W_HIU_REG(HHI_DADC_CNTL3, 0x00082183); - } else if (tvafe_cpu_type() == CPU_TYPE_TL1) { + } else if (tvafe_cpu_type() >= CPU_TYPE_TL1) { W_HIU_REG(HHI_DADC_CNTL, 0x0030303c); W_HIU_REG(HHI_DADC_CNTL2, 0x00003400); W_HIU_REG(HHI_DADC_CNTL3, 0x08300b83); @@ -440,8 +442,8 @@ static void tvafe_set_cvbs_default(struct tvafe_cvd2_s *cvd2, if (tvafe_cpu_type() == CPU_TYPE_TXL || tvafe_cpu_type() == CPU_TYPE_TXLX || tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { - if (tvafe_cpu_type() == CPU_TYPE_TL1) { + tvafe_cpu_type() >= CPU_TYPE_TL1) { + if (tvafe_cpu_type() >= CPU_TYPE_TL1) { if (port == TVIN_PORT_CVBS3) { W_APB_REG(TVFE_VAFE_CTRL0, 0x000d0710); W_APB_REG(TVFE_VAFE_CTRL1, 0x00003000); @@ -550,7 +552,7 @@ void tvafe_set_ddemod_default(void) W_APB_REG(TVFE_VAFE_CTRL0, 0x000d0710); W_APB_REG(TVFE_VAFE_CTRL1, 0x0); W_APB_REG(TVFE_VAFE_CTRL2, 0x1010eeb0); - } else if (tvafe_cpu_type() == CPU_TYPE_TL1) { + } else if (tvafe_cpu_type() >= CPU_TYPE_TL1) { W_APB_REG(TVFE_VAFE_CTRL0, 0x000d0710); W_APB_REG(TVFE_VAFE_CTRL1, 0x3000); W_APB_REG(TVFE_VAFE_CTRL2, 0x1fe09e31); @@ -571,7 +573,7 @@ void tvafe_enable_avout(enum tvin_port_e port, bool enable) if (tvafe_cpu_type() == CPU_TYPE_TXL || tvafe_cpu_type() == CPU_TYPE_TXLX || tvafe_cpu_type() == CPU_TYPE_TXHD || - tvafe_cpu_type() == CPU_TYPE_TL1) { + tvafe_cpu_type() >= CPU_TYPE_TL1) { if (enable) { tvafe_clk_gate_ctrl(1); if (port == TVIN_PORT_CVBS3) { @@ -627,7 +629,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) break; } mutex_lock(&pll_mutex); - if (tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_cpu_type() >= CPU_TYPE_TL1) { do { W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x012004e0); W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x312004e0); @@ -690,7 +692,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) break; } mutex_lock(&pll_mutex); - if (tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_cpu_type() >= CPU_TYPE_TL1) { do { W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x012004e0); W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x312004e0); @@ -781,7 +783,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) break; } mutex_lock(&pll_mutex); - if (tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_cpu_type() >= CPU_TYPE_TL1) { do { W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x012004e0); W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x312004e0); @@ -888,7 +890,7 @@ int adc_set_pll_cntl(bool on, unsigned int module_sel, void *pDtvPara) W_HIU_REG(HHI_DEMOD_CLK_CNTL, 0x1000502); adc_pll_lock_cnt = 1; - } else if (tvafe_cpu_type() == CPU_TYPE_TL1) { + } else if (tvafe_cpu_type() >= CPU_TYPE_TL1) { do {//25M W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x001104c8); W_HIU_REG(HHI_ADC_PLL_CNTL0_TL1, 0x301104c8); @@ -973,7 +975,7 @@ void tvafe_init_reg(struct tvafe_cvd2_s *cvd2, if ((port >= TVIN_PORT_CVBS0) && (port <= TVIN_PORT_CVBS3)) { #ifdef CRYSTAL_25M - if (tvafe_cpu_type() != CPU_TYPE_TL1) + if (tvafe_cpu_type() < CPU_TYPE_TL1) W_HIU_REG(HHI_VAFE_CLKIN_CNTL, 0x703);/* can't write !!! */ #endif @@ -1033,7 +1035,7 @@ void tvafe_enable_module(bool enable) /* enable */ /* main clk up */ - if (tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_cpu_type() >= CPU_TYPE_TL1) { W_HIU_BIT(HHI_ATV_DMD_SYS_CLK_CNTL, 1, VAFE_CLK_SELECT, VAFE_CLK_SELECT_WIDTH); W_HIU_BIT(HHI_ATV_DMD_SYS_CLK_CNTL, 1, @@ -1076,7 +1078,7 @@ void tvafe_enable_module(bool enable) TVFE_ADC_CLK_DIV_WID); /* main clk down */ - if (tvafe_cpu_type() == CPU_TYPE_TL1) { + if (tvafe_cpu_type() >= CPU_TYPE_TL1) { W_HIU_BIT(HHI_ATV_DMD_SYS_CLK_CNTL, 0, VAFE_CLK_SELECT, VAFE_CLK_SELECT_WIDTH); W_HIU_BIT(HHI_ATV_DMD_SYS_CLK_CNTL, 0, diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h index 85d6a32f9829..2fa4bcb5f22f 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h @@ -159,6 +159,7 @@ enum tvafe_cpu_type { CPU_TYPE_TXHD = 3, CPU_TYPE_GXLX = 4, CPU_TYPE_TL1 = 5, + CPU_TYPE_TM2 = 6, }; struct meson_tvafe_data { diff --git a/drivers/amlogic/media/vin/tvin/tvin_global.h b/drivers/amlogic/media/vin/tvin/tvin_global.h index c6d053b06416..78f4b4029f1a 100644 --- a/drivers/amlogic/media/vin/tvin/tvin_global.h +++ b/drivers/amlogic/media/vin/tvin/tvin_global.h @@ -116,6 +116,15 @@ static inline uint32_t R_APB_BIT(uint32_t reg, return val; } +static inline void W_VCBUS(uint32_t reg, const uint32_t value) +{ + aml_write_vcbus(reg, value); +} + +static inline uint32_t R_VCBUS(uint32_t reg) +{ + return aml_read_vcbus(reg); +} static inline void W_VCBUS_BIT(uint32_t reg, const uint32_t value, @@ -438,6 +447,19 @@ struct tvin_hdr_info_s { unsigned int hdr_check_cnt; }; +enum tvin_cn_type_e { + GRAPHICS, + PHOTO, + CINEMA, + GAME, +}; + +struct tvin_latency_s { + bool allm_mode; + bool it_content; + enum tvin_cn_type_e cn_type; +}; + struct tvin_sig_property_s { enum tvin_trans_fmt trans_fmt; enum tvin_color_fmt_e color_format; @@ -464,6 +486,7 @@ struct tvin_sig_property_s { bool low_latency;/*is low latency dolby mode*/ uint8_t fps; unsigned int skip_vf_num;/*skip pre vframe num*/ + struct tvin_latency_s latency; }; #define TVAFE_VF_POOL_SIZE 6 /* 8 */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/Makefile b/drivers/amlogic/media/vin/tvin/vdin/Makefile index 7f0c556e4178..b8092e9aa0d4 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/Makefile +++ b/drivers/amlogic/media/vin/tvin/vdin/Makefile @@ -1,6 +1,11 @@ # # Makefile for Vdin. # +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +ccflags-y := -DDEBUG_SUPPORT +else +ccflags-y := -DDEBUG +endif obj-$(CONFIG_AMLOGIC_MEDIA_VDIN) = tvin_vdin.o tvin_vdin-objs += vdin_v4l2.o tvin_vdin-objs += vdin_vf.o diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c index eaa9d734e4bb..50fbf475b79a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.c @@ -57,352 +57,157 @@ #include "vdin_canvas.h" #include "vdin_afbce.h" -static unsigned int max_buf_num = VDIN_CANVAS_MAX_CNT; -static unsigned int min_buf_num = 4; -static unsigned int max_buf_width = VDIN_CANVAS_MAX_WIDTH_HD; -static unsigned int max_buf_height = VDIN_CANVAS_MAX_HEIGH; -/* one frame max metadata size:32x280 bits = 1120bytes(0x460) */ -unsigned int dolby_size_bytes = PAGE_SIZE; - -unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp) +/* fixed config mif by default */ +void vdin_mif_config_init(struct vdin_dev_s *devp) { - char vdin_name[6]; - unsigned int mem_size, h_size, v_size; - int flags = CODEC_MM_FLAGS_CMA_FIRST|CODEC_MM_FLAGS_CMA_CLEAR| - CODEC_MM_FLAGS_CPU; - unsigned int max_buffer_num = min_buf_num; - unsigned int i; - /*afbce head need 1036800 byte at most*/ - unsigned int afbce_head_size_byte = PAGE_SIZE * 300;/*1.2M*/ - /*afbce map_table need 218700 byte at most*/ - unsigned int afbce_table_size_byte = PAGE_SIZE * 60;/*0.3M*/ - unsigned int afbce_mem_used; - unsigned int frame_head_size; - unsigned int mmu_used; - //unsigned long afbce_head_phy_addr; - //unsigned long afbce_table_phy_addr; - unsigned long body_start_paddr; - - if (devp->rdma_enable) - max_buffer_num++; - /*todo: need update if vf_skip_cnt used by other port*/ - if (devp->vfp->skip_vf_num && - (((devp->parm.port >= TVIN_PORT_HDMI0) && - (devp->parm.port <= TVIN_PORT_HDMI7)) || - ((devp->parm.port >= TVIN_PORT_CVBS0) && - (devp->parm.port <= TVIN_PORT_CVBS3)))) - max_buffer_num += devp->vfp->skip_vf_num; - if (max_buffer_num > max_buf_num) - max_buffer_num = max_buf_num; - devp->vfmem_max_cnt = max_buffer_num; - devp->canvas_max_num = max_buffer_num; - - if ((devp->cma_config_en == 0) || - (devp->cma_mem_alloc == 1)) { - pr_info("\nvdin%d %s use_reserved mem or cma already alloced (%d,%d)!!!\n", - devp->index, __func__, devp->cma_config_en, - devp->cma_mem_alloc); - return 0; - } - h_size = devp->h_active; - v_size = devp->v_active; - if (devp->canvas_config_mode == 1) { - h_size = max_buf_width; - v_size = max_buf_height; - } - if ((devp->format_convert == VDIN_FORMAT_CONVERT_YUV_YUV444) || - (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_RGB) || - (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444) || - (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_RGB) || - (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_GBR) || - (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_BRG) || - (devp->force_yuv444_malloc == 1)) { - if ((devp->source_bitdepth > VDIN_MIN_SOURCE_BITDEPTH) && - (devp->color_depth_mode != 1)) { - h_size = roundup(h_size * - VDIN_YUV444_10BIT_PER_PIXEL_BYTE, - devp->canvas_align); - devp->canvas_alin_w = h_size / - VDIN_YUV444_10BIT_PER_PIXEL_BYTE; - } else { - h_size = roundup(h_size * - VDIN_YUV444_8BIT_PER_PIXEL_BYTE, - devp->canvas_align); - devp->canvas_alin_w = h_size / - VDIN_YUV444_8BIT_PER_PIXEL_BYTE; - } - } else if ((devp->format_convert == VDIN_FORMAT_CONVERT_YUV_NV12) || - (devp->format_convert == VDIN_FORMAT_CONVERT_YUV_NV21) || - (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_NV12) || - (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_NV21)) { - h_size = roundup(h_size, devp->canvas_align); - devp->canvas_alin_w = h_size; - /*todo change with canvas alloc!!*/ - /* nv21/nv12 only have 8bit mode */ + if (devp->index == 0) { + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN0_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_OUT_MIF_BIT, 1); } else { - /* txl new add mode yuv422 pack mode:canvas-w=h*2*10/8 - *canvas_w must ensure divided exact by 256bit(32byte - */ - if ((devp->source_bitdepth > VDIN_MIN_SOURCE_BITDEPTH) && - ((devp->format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || - (devp->format_convert == VDIN_FORMAT_CONVERT_RGB_YUV422) || - (devp->format_convert == VDIN_FORMAT_CONVERT_GBR_YUV422) || - (devp->format_convert == VDIN_FORMAT_CONVERT_BRG_YUV422)) && - (devp->color_depth_mode == 1)) { - h_size = roundup((h_size * 5)/2, devp->canvas_align); - devp->canvas_alin_w = (h_size * 2) / 5; - } else if ((devp->source_bitdepth > VDIN_MIN_SOURCE_BITDEPTH) && - (devp->color_depth_mode == 0)) { - h_size = roundup(h_size * - VDIN_YUV422_10BIT_PER_PIXEL_BYTE, - devp->canvas_align); - devp->canvas_alin_w = h_size / - VDIN_YUV422_10BIT_PER_PIXEL_BYTE; - } else { - h_size = roundup(h_size * - VDIN_YUV422_8BIT_PER_PIXEL_BYTE, - devp->canvas_align); - devp->canvas_alin_w = h_size / - VDIN_YUV422_8BIT_PER_PIXEL_BYTE; - } + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN1_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN1_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN1_OUT_MIF_BIT, 1); } - mem_size = h_size * v_size; - if ((devp->format_convert >= VDIN_FORMAT_CONVERT_YUV_NV12) && - (devp->format_convert <= VDIN_FORMAT_CONVERT_RGB_NV21)) - mem_size = (mem_size * 3)/2; - devp->vfmem_size = PAGE_ALIGN(mem_size) + dolby_size_bytes; - devp->vfmem_size = (devp->vfmem_size/PAGE_SIZE + 1)*PAGE_SIZE; - - mem_size = PAGE_ALIGN(mem_size) * max_buffer_num + - dolby_size_bytes * max_buffer_num; - mem_size = (mem_size/PAGE_SIZE + 1)*PAGE_SIZE; - if (mem_size > devp->cma_mem_size) - mem_size = devp->cma_mem_size; - if (devp->index == 0) - strcpy(vdin_name, "vdin0"); - else if (devp->index == 1) - strcpy(vdin_name, "vdin1"); - - - if (devp->cma_config_flag == 0x101) { - devp->afbce_info->head_paddr = codec_mm_alloc_for_dma( - vdin_name, afbce_head_size_byte/PAGE_SIZE, 0, flags); - devp->afbce_info->table_paddr = codec_mm_alloc_for_dma( - vdin_name, afbce_table_size_byte/PAGE_SIZE, 0, flags); - devp->afbce_info->head_size = afbce_head_size_byte; - devp->afbce_info->table_size = afbce_table_size_byte; - devp->afbce_info->frame_body_size = devp->vfmem_size; - - pr_info("vdin%d head_start = 0x%lx, head_size = 0x%x\n", - devp->index, devp->afbce_info->head_paddr, - devp->afbce_info->head_size); - pr_info("vdin%d table_start = 0x%lx, table_size = 0x%x\n", - devp->index, devp->afbce_info->table_paddr, - devp->afbce_info->table_size); - - /* set fm_body_paddr */ - for (i = 0; i < max_buffer_num; i++) { - devp->afbce_info->fm_body_paddr[i] = - codec_mm_alloc_for_dma(vdin_name, - devp->vfmem_size/PAGE_SIZE, 0, flags); - if (devp->afbce_info->fm_body_paddr[i] == 0) { - pr_err("\nvdin%d-afbce buf[%d]codec alloc fail!!!\n", - devp->index, i); - devp->cma_mem_alloc = 0; - } else { - devp->cma_mem_alloc = 1; - pr_info("vdin%d fm_body_paddr[%d] = 0x%lx, body_size = 0x%x\n", - devp->index, i, - devp->afbce_info->fm_body_paddr[i], - devp->afbce_info->frame_body_size); - } - - if (devp->cma_mem_alloc == 0) - return 1; - } - pr_info("vdin%d-afbce codec cma alloc ok!\n", devp->index); - devp->mem_size = mem_size; - } else if (devp->cma_config_flag == 0) { - devp->venc_pages = dma_alloc_from_contiguous( - &(devp->this_pdev->dev), - devp->cma_mem_size >> PAGE_SHIFT, 0); - if (devp->venc_pages) { - devp->mem_start = - page_to_phys(devp->venc_pages); - devp->mem_size = mem_size; - devp->cma_mem_alloc = 1; - - devp->afbce_info->head_paddr = devp->mem_start; - devp->afbce_info->head_size = 2*SZ_1M;/*2M*/ - devp->afbce_info->table_paddr = - devp->mem_start + devp->afbce_info->head_paddr; - devp->afbce_info->table_size = 2*SZ_1M;/*2M*/ - devp->afbce_info->frame_body_size = devp->vfmem_size; - - body_start_paddr = devp->afbce_info->table_paddr + - devp->afbce_info->table_size; - - pr_info("vdin%d head_start = 0x%lx, head_size = 0x%x\n", - devp->index, devp->afbce_info->head_paddr, - devp->afbce_info->head_size); - pr_info("vdin%d table_start = 0x%lx, table_size = 0x%x\n", - devp->index, devp->afbce_info->table_paddr, - devp->afbce_info->table_size); - - /* set fm_body_paddr */ - for (i = 0; i < max_buffer_num; i++) { - devp->afbce_info->fm_body_paddr[i] = - body_start_paddr + (devp->vfmem_size * i); - - pr_info("vdin%d body[%d]_start = 0x%lx, body_size = 0x%x\n", - devp->index, i, - devp->afbce_info->fm_body_paddr[i], - devp->afbce_info->frame_body_size); - } - - /*check memory over the boundary*/ - afbce_mem_used = - devp->afbce_info->fm_body_paddr[max_buffer_num] - + devp->afbce_info->frame_body_size - - devp->afbce_info->head_paddr; - if (afbce_mem_used > devp->cma_mem_size) { - pr_info("afbce mem: afbce_mem_used(%d) > cma_mem_size(%d)\n", - afbce_mem_used, devp->cma_mem_size); - return 1; - } - devp->cma_mem_alloc = 1; - pr_info("vdin%d cma alloc ok!\n", devp->index); - } else { - devp->cma_mem_alloc = 0; - pr_err("\nvdin%d-afbce cma mem undefined2.\n", - devp->index); - return 1; - } - } - - /* 1 block = 32 * 4 pixle = 128 pixel */ - /* there is a header in one block, a header has 4 bytes */ - /* set fm_head_paddr start */ - frame_head_size = roundup(devp->h_active * devp->v_active, 128); - /*h_active * v_active / 128 * 4 = frame_head_size*/ - frame_head_size = devp->h_active * devp->v_active / 32; - frame_head_size = PAGE_ALIGN(frame_head_size); - - devp->afbce_info->frame_head_size = frame_head_size; - - for (i = 0; i < max_buffer_num; i++) { - devp->afbce_info->fm_head_paddr[i] = - devp->afbce_info->head_paddr + (frame_head_size*i); - - pr_info("vdin%d fm_head_paddr[%d] = 0x%lx, frame_head_size = 0x%x\n", - devp->index, i, - devp->afbce_info->fm_head_paddr[i], - frame_head_size); - } - /* set fm_head_paddr end */ - - /* set fm_table_paddr start */ - mmu_used = devp->afbce_info->frame_body_size >> 12; - mmu_used = mmu_used * 4; - mmu_used = PAGE_ALIGN(mmu_used); - devp->afbce_info->frame_table_size = mmu_used; - - for (i = 0; i < max_buffer_num; i++) { - devp->afbce_info->fm_table_paddr[i] = - devp->afbce_info->table_paddr + (mmu_used*i); - - pr_info("vdin%d fm_table_paddr[%d]=0x%lx, frame_table_size = 0x%x\n", - devp->index, i, - devp->afbce_info->fm_table_paddr[i], - devp->afbce_info->frame_table_size); - } - /* set fm_table_paddr end */ - - return 0; } -void vdin_afbce_cma_release(struct vdin_dev_s *devp) +/* only support init vdin0 mif/afbce */ +void vdin_write_mif_or_afbce_init(struct vdin_dev_s *devp) { - char vdin_name[6]; - unsigned int i; + enum vdin_output_mif_e sel; - if ((devp->cma_config_en == 0) || - (devp->cma_mem_alloc == 0)) { - pr_err("\nvdin%d %s fail for (%d,%d)!!!\n", - devp->index, __func__, devp->cma_config_en, - devp->cma_mem_alloc); + if ((devp->afbce_flag & VDIN_AFBCE_EN) == 0) return; - } - if (devp->index == 0) - strcpy(vdin_name, "vdin0"); - else if (devp->index == 1) - strcpy(vdin_name, "vdin1"); - if (devp->cma_config_flag == 0x101) { - codec_mm_free_for_dma(vdin_name, devp->afbce_info->head_paddr); - codec_mm_free_for_dma(vdin_name, devp->afbce_info->table_paddr); - for (i = 0; i < devp->vfmem_max_cnt; i++) - codec_mm_free_for_dma(vdin_name, - devp->afbce_info->fm_body_paddr[i]); - pr_info("vdin%d-afbce codec cma release ok!\n", devp->index); - } else if (devp->venc_pages - && devp->cma_mem_size - && (devp->cma_config_flag == 0)) { - dma_release_from_contiguous( - &(devp->this_pdev->dev), - devp->venc_pages, - devp->cma_mem_size >> PAGE_SHIFT); - pr_info("vdin%d-afbce cma release ok!\n", devp->index); - } else { - pr_err("\nvdin%d %s fail for (%d,0x%x,0x%lx)!!!\n", - devp->index, __func__, devp->cma_mem_size, - devp->cma_config_flag, devp->mem_start); + if (devp->afbce_mode == 0) + sel = VDIN_OUTPUT_TO_MIF; + else + sel = VDIN_OUTPUT_TO_AFBCE; + + if (devp->index == 0) { + if (sel == VDIN_OUTPUT_TO_MIF) { + vdin_afbce_hw_disable(); + + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN0_OUT_AFBCE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_OUT_MIF_BIT, 1); + } else if (sel == VDIN_OUTPUT_TO_AFBCE) { + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_MIF_ENABLE_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 0, VDIN0_OUT_MIF_BIT, 1); + W_VCBUS_BIT(VDIN_MISC_CTRL, + 1, VDIN0_OUT_AFBCE_BIT, 1); + + vdin_afbce_hw_enable(); + } } - devp->mem_start = 0; - devp->mem_size = 0; - devp->cma_mem_alloc = 0; } +/* only support config vdin0 mif/afbce dynamically */ void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, enum vdin_output_mif_e sel) { - unsigned int offset = devp->addr_offset; - if (offset == 0) { - if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_AFBCE_BIT, 1); - } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN0_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN0_OUT_AFBCE_BIT, 1); - } - } else { - if (sel == VDIN_OUTPUT_TO_MIF) { - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_AFBCE_BIT, 1); - } else if (sel == VDIN_OUTPUT_TO_AFBCE) { - /*sel vdin1 afbce: not support in sw now, - *just reserved interface - */ - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_MIF_ENABLE_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 0, VDIN1_OUT_MIF_BIT, 1); - W_VCBUS_BIT(VDIN_MISC_CTRL, 1, VDIN1_OUT_AFBCE_BIT, 1); - } + if ((devp->afbce_flag & VDIN_AFBCE_EN) == 0) + return; + + if (sel == VDIN_OUTPUT_TO_MIF) { + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 0, 8, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 0, VDIN0_OUT_AFBCE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN0_OUT_MIF_BIT, 1); + } else if (sel == VDIN_OUTPUT_TO_AFBCE) { + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 0, VDIN0_OUT_MIF_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, VDIN_MISC_CTRL, + 1, VDIN0_OUT_AFBCE_BIT, 1); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 8, 1); } } - +/* static void afbce_wr(uint32_t reg, const uint32_t val) { wr(0, reg, val); } +*/ +#define VDIN_AFBCE_HOLD_LINE_NUM 4 +void vdin_afbce_update(struct vdin_dev_s *devp) +{ + int hold_line_num = VDIN_AFBCE_HOLD_LINE_NUM; + int reg_format_mode;/* 0:444 1:422 2:420 */ + int reg_fmt444_comb; + int sblk_num; + int uncmp_bits; + int uncmp_size; + + if (!devp->afbce_info) + return; + +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA + pr_info("##############################################\n"); + pr_info("vdin afbce must use RDMA,but it not be opened\n"); + pr_info("##############################################\n"); +#endif + + if ((devp->prop.dest_cfmt == TVIN_YUV444) && (devp->h_active > 2048)) + reg_fmt444_comb = 1; + else + reg_fmt444_comb = 0; + + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) { + reg_format_mode = 2; + sblk_num = 12; + } else if ((devp->prop.dest_cfmt == TVIN_YUV422) || + (devp->prop.dest_cfmt == TVIN_YUYV422) || + (devp->prop.dest_cfmt == TVIN_YVYU422) || + (devp->prop.dest_cfmt == TVIN_UYVY422) || + (devp->prop.dest_cfmt == TVIN_VYUY422)) { + reg_format_mode = 1; + sblk_num = 16; + } else { + reg_format_mode = 0; + sblk_num = 24; + } + uncmp_bits = devp->source_bitdepth; + + /* bit size of uncompression mode */ + uncmp_size = (((((16*uncmp_bits*sblk_num)+7)>>3)+31)/32)<<1; + /* + *pr_info("%s: dest_cfmt=%d, reg_format_mode=%d, uncmp_bits=%d, + * sblk_num=%d, uncmp_size=%d\n", + * __func__, devp->prop.dest_cfmt, reg_format_mode, + * uncmp_bits, sblk_num, uncmp_size); + */ + + rdma_write_reg(devp->rdma_handle, AFBCE_MODE, + (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | + (hold_line_num & 0x7f) << 16 | + (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); + + rdma_write_reg_bits(devp->rdma_handle, + AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);/* uncmp_size */ + + rdma_write_reg(devp->rdma_handle, AFBCE_FORMAT, + (reg_format_mode & 0x3) << 8 | + (uncmp_bits & 0xf) << 4 | + (uncmp_bits & 0xf)); +} void vdin_afbce_config(struct vdin_dev_s *devp) { - unsigned int offset = devp->addr_offset; - int hold_line_num = 4; + int hold_line_num = VDIN_AFBCE_HOLD_LINE_NUM; int lbuf_depth = 256; int lossy_luma_en = 0; int lossy_chrm_en = 0; @@ -412,9 +217,9 @@ void vdin_afbce_config(struct vdin_dev_s *devp) int sblk_num; int uncmp_bits; int uncmp_size; - int def_color_0 = 0; - int def_color_1 = 0; - int def_color_2 = 0; + int def_color_0 = 4095; + int def_color_1 = 2048; + int def_color_2 = 2048; int def_color_3 = 0; int hblksize_out = (devp->h_active + 31) >> 5; int vblksize_out = (devp->v_active + 3) >> 2; @@ -427,10 +232,14 @@ void vdin_afbce_config(struct vdin_dev_s *devp) int enc_win_bgn_v;//input scope int enc_win_end_v;//input scope - if (offset != 0) { - pr_info("cat not use afbce on vdin1 at the moment\n"); + if (!devp->afbce_info) return; - } + +#ifndef CONFIG_AMLOGIC_MEDIA_RDMA + pr_info("##############################################\n"); + pr_info("vdin afbce must use RDMA,but it not be opened\n"); + pr_info("##############################################\n"); +#endif enc_win_bgn_h = 0; enc_win_end_h = devp->h_active - 1; @@ -470,7 +279,7 @@ void vdin_afbce_config(struct vdin_dev_s *devp) W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 3, 1);//vpu arb axi_enable W_VCBUS_BIT(VDIN_WRARB_REQEN_SLV, 0x1, 7, 1);//vpu arb axi_enable - afbce_wr(AFBCE_MODE, + W_VCBUS(AFBCE_MODE, (0 & 0x7) << 29 | (0 & 0x3) << 26 | (3 & 0x3) << 24 | (hold_line_num & 0x7f) << 16 | (2 & 0x3) << 14 | (reg_fmt444_comb & 0x1)); @@ -478,92 +287,139 @@ void vdin_afbce_config(struct vdin_dev_s *devp) W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_luma_en & 0x1), 0, 1);//loosy W_VCBUS_BIT(AFBCE_QUANT_ENABLE, (lossy_chrm_en & 0x1), 4, 1);//loosy - afbce_wr(AFBCE_SIZE_IN, + if (devp->afbce_flag & VDIN_AFBCE_EN_LOOSY) { + W_VCBUS(AFBCE_QUANT_ENABLE, 0xc11); + pr_info("afbce use lossy compression mode\n"); + } + + W_VCBUS(AFBCE_SIZE_IN, ((devp->h_active & 0x1fff) << 16) | // hsize_in of afbc input ((devp->v_active & 0x1fff) << 0) // vsize_in of afbc input ); - afbce_wr(AFBCE_BLK_SIZE_IN, + W_VCBUS(AFBCE_BLK_SIZE_IN, ((hblksize_out & 0x1fff) << 16) | // out blk hsize ((vblksize_out & 0x1fff) << 0) // out blk vsize ); //head addr of compressed data - afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[0]); + W_VCBUS(AFBCE_HEAD_BADDR, + devp->afbce_info->fm_head_paddr[0]); W_VCBUS_BIT(AFBCE_MIF_SIZE, (uncmp_size & 0x1fff), 16, 5);//uncmp_size /* how to set reg when we use crop ? */ // scope of hsize_in ,should be a integer multipe of 32 // scope of vsize_in ,should be a integer multipe of 4 - afbce_wr(AFBCE_PIXEL_IN_HOR_SCOPE, + W_VCBUS(AFBCE_PIXEL_IN_HOR_SCOPE, ((enc_win_end_h & 0x1fff) << 16) | ((enc_win_bgn_h & 0x1fff) << 0)); // scope of hsize_in ,should be a integer multipe of 32 // scope of vsize_in ,should be a integer multipe of 4 - afbce_wr(AFBCE_PIXEL_IN_VER_SCOPE, + W_VCBUS(AFBCE_PIXEL_IN_VER_SCOPE, ((enc_win_end_v & 0x1fff) << 16) | ((enc_win_bgn_v & 0x1fff) << 0)); - afbce_wr(AFBCE_CONV_CTRL, lbuf_depth);//fix 256 + W_VCBUS(AFBCE_CONV_CTRL, lbuf_depth);//fix 256 - afbce_wr(AFBCE_MIF_HOR_SCOPE, + W_VCBUS(AFBCE_MIF_HOR_SCOPE, ((blk_out_bgn_h & 0x3ff) << 16) | // scope of out blk hsize ((blk_out_end_h & 0xfff) << 0) // scope of out blk vsize ); - afbce_wr(AFBCE_MIF_VER_SCOPE, + W_VCBUS(AFBCE_MIF_VER_SCOPE, ((blk_out_bgn_v & 0x3ff) << 16) | // scope of out blk hsize ((blk_out_end_v & 0xfff) << 0) // scope of out blk vsize ); - afbce_wr(AFBCE_FORMAT, + W_VCBUS(AFBCE_FORMAT, (reg_format_mode & 0x3) << 8 | (uncmp_bits & 0xf) << 4 | (uncmp_bits & 0xf)); - afbce_wr(AFBCE_DEFCOLOR_1, + W_VCBUS(AFBCE_DEFCOLOR_1, ((def_color_3 & 0xfff) << 12) | // def_color_a ((def_color_0 & 0xfff) << 0) // def_color_y ); - afbce_wr(AFBCE_DEFCOLOR_2, + W_VCBUS(AFBCE_DEFCOLOR_2, ((def_color_2 & 0xfff) << 12) | // def_color_v ((def_color_1 & 0xfff) << 0) // def_color_u ); - //cur_mmu_used += Rd(AFBCE_MMU_NUM); //4k addr have used in every frame; - W_VCBUS_BIT(AFBCE_MMU_RMIF_CTRL4, devp->afbce_info->table_paddr, 0, 32); W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - W_VCBUS_BIT(AFBCE_ENABLE, 1, 8, 1);//enable afbce + W_VCBUS_BIT(AFBCE_ENABLE, 1, 12, 1); //set afbce pulse mode + W_VCBUS_BIT(AFBCE_ENABLE, 0, 8, 1);//disable afbce } void vdin_afbce_maptable_init(struct vdin_dev_s *devp) { unsigned int i, j; - unsigned int *ptable = NULL; + unsigned int highmem_flag = 0; + unsigned long ptable = 0; unsigned int *vtable = NULL; unsigned int body; unsigned int size; + void *p = NULL; + + if (!devp->afbce_info) + return; size = roundup(devp->afbce_info->frame_body_size, 4096); - for (i = 0; i < devp->vfmem_max_cnt; i++) { - ptable = (unsigned int *) - (devp->afbce_info->fm_table_paddr[i]&0xffffffff); - if (devp->cma_config_flag == 0x101) - vtable = codec_mm_phys_to_virt((unsigned long)ptable); - else if (devp->cma_config_flag == 0) - vtable = phys_to_virt((unsigned long)ptable); + ptable = devp->afbce_info->fm_table_paddr[0]; + if (devp->cma_config_flag == 0x101) + highmem_flag = PageHighMem(phys_to_page(ptable)); + else + highmem_flag = PageHighMem(phys_to_page(ptable)); + for (i = 0; i < devp->vfmem_max_cnt; i++) { + ptable = devp->afbce_info->fm_table_paddr[i]; + if (highmem_flag == 0) { + if (devp->cma_config_flag == 0x101) + vtable = codec_mm_phys_to_virt(ptable); + else if (devp->cma_config_flag == 0) + vtable = phys_to_virt(ptable); + else + vtable = phys_to_virt(ptable); + } else { + vtable = (unsigned int *)vdin_vmap(ptable, + devp->afbce_info->frame_table_size); + if (vdin_dbg_en) { + pr_err("----vdin vmap v: %p, p: %lx, size: %d\n", + vtable, ptable, + devp->afbce_info->frame_table_size); + } + if (!vtable) { + pr_err("vmap fail, size: %d.\n", + devp->afbce_info->frame_table_size); + return; + } + + } + + p = vtable; body = devp->afbce_info->fm_body_paddr[i]&0xffffffff; for (j = 0; j < size; j += 4096) { *vtable = ((j + body) >> 12) & 0x000fffff; vtable++; } + + /* clean tail data. */ + memset(vtable, 0, devp->afbce_info->frame_table_size - + ((char *)vtable - (char *)p)); + + vdin_dma_flush(devp, p, + devp->afbce_info->frame_table_size, + DMA_TO_DEVICE); + + if (highmem_flag) + vdin_unmap_phyaddr(p); + + vtable = NULL; } } @@ -571,20 +427,75 @@ void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, unsigned int rdma_enable, struct vf_entry *vfe) { unsigned char i; - unsigned int cur_mmu_used; + + if (!devp->afbce_info) + return; i = vfe->af_num; - cur_mmu_used = devp->afbce_info->fm_table_paddr[i] / 4; + vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; -#ifdef CONFIG_AML_RDMA - if (rdma_enable) - rdma_write_reg_bits(devp->rdma_handle, - AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); - rdma_write_reg(devp->rdma_handle, - AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); - else +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + if (rdma_enable) { + rdma_write_reg(devp->rdma_handle, AFBCE_HEAD_BADDR, + devp->afbce_info->fm_head_paddr[i]); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_MMU_RMIF_CTRL4, + devp->afbce_info->fm_table_paddr[i], 0, 32); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 0, 1); + } else #endif - afbce_wr(AFBCE_HEAD_BADDR, devp->afbce_info->fm_head_paddr[i]); - W_VCBUS_BIT(AFBCE_MMU_RMIF_SCOPE_X, cur_mmu_used, 0, 12); + { + pr_info("afbce must use RDMA.\n"); + } + + vdin_afbce_clear_writedown_flag(devp); } +void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp) +{ + rdma_write_reg(devp->rdma_handle, AFBCE_CLR_FLAG, 1); +} + +/* return 1: write down*/ +int vdin_afbce_read_writedown_flag(void) +{ + int val1, val2; + + val1 = rd_bits(0, AFBCE_STA_FLAGT, 0, 1); + val2 = rd_bits(0, AFBCE_STA_FLAGT, 2, 2); + + if ((val1 == 1) || (val2 == 0)) + return 1; + else + return 0; +} + +void vdin_afbce_hw_disable(void) +{ + /*can not use RDMA*/ + W_VCBUS_BIT(AFBCE_ENABLE, 0, 8, 1);//disable afbce +} + +void vdin_afbce_hw_enable(void) +{ + W_VCBUS_BIT(AFBCE_ENABLE, 1, 8, 1); +} + +void vdin_afbce_hw_disable_rdma(struct vdin_dev_s *devp) +{ + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 0, 8, 1); +} + +void vdin_afbce_hw_enable_rdma(struct vdin_dev_s *devp) +{ + if (devp->afbce_flag & VDIN_AFBCE_EN_LOOSY) + rdma_write_reg(devp->rdma_handle, AFBCE_QUANT_ENABLE, 0xc11); + rdma_write_reg_bits(devp->rdma_handle, AFBCE_ENABLE, 1, 8, 1); +} + +void vdin_afbce_soft_reset(void) +{ + W_VCBUS_BIT(AFBCE_MODE, 0, 30, 1); + W_VCBUS_BIT(AFBCE_MODE, 1, 30, 1); + W_VCBUS_BIT(AFBCE_MODE, 0, 30, 1); +} diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h index feb2d086eca4..0ac61b583c7a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_afbce.h @@ -300,14 +300,20 @@ #define AFBCE_MMU_RMIF_RO_STAT 0x41c6 +extern void vdin_write_mif_or_afbce_init(struct vdin_dev_s *devp); extern void vdin_write_mif_or_afbce(struct vdin_dev_s *devp, enum vdin_output_mif_e sel); -extern unsigned int vdin_afbce_cma_alloc(struct vdin_dev_s *devp); -extern void vdin_afbce_cma_release(struct vdin_dev_s *devp); +extern void vdin_afbce_update(struct vdin_dev_s *devp); extern void vdin_afbce_config(struct vdin_dev_s *devp); extern void vdin_afbce_maptable_init(struct vdin_dev_s *devp); extern void vdin_afbce_set_next_frame(struct vdin_dev_s *devp, -unsigned int rdma_enable, struct vf_entry *vfe); - + unsigned int rdma_enable, struct vf_entry *vfe); +extern void vdin_afbce_clear_writedown_flag(struct vdin_dev_s *devp); +extern int vdin_afbce_read_writedown_flag(void); +extern void vdin_afbce_hw_disable(void); +extern void vdin_afbce_hw_enable(void); +extern void vdin_afbce_hw_disable_rdma(struct vdin_dev_s *devp); +extern void vdin_afbce_hw_enable_rdma(struct vdin_dev_s *devp); +extern void vdin_afbce_soft_reset(void); #endif diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.c index edfa775f5594..1cfa6b1a3e26 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.c @@ -328,6 +328,27 @@ void vdin_canvas_auto_config(struct vdin_dev_s *devp) devp->canvas_max_num = min(devp->canvas_max_num, canvas_num); devp->canvas_max_num = min(devp->canvas_max_num, max_buffer_num); + if (devp->canvas_max_num < devp->vfmem_max_cnt) { + pr_err("\nvdin%d canvas_max_num %d less than vfmem_max_cnt %d\n", + devp->index, devp->canvas_max_num, devp->vfmem_max_cnt); + } + + if (devp->set_canvas_manual == 1) { + for (i = 0; i < 4; i++) { + canvas_id = + vdin_canvas_ids[devp->index][i * canvas_step]; + canvas_addr = vdin_set_canvas_addr[i].paddr; + canvas_config(canvas_id, canvas_addr, + devp->canvas_w, devp->canvas_h, + CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_LINEAR); + pr_info("canvas index=%d- %3d: 0x%lx-0x%lx %ux%u\n", + i, canvas_id, canvas_addr, + canvas_addr + devp->canvas_max_size, + devp->canvas_w, devp->canvas_h); + } + return; + } + if ((devp->cma_config_en != 1) || !(devp->cma_config_flag & 0x100)) { /*use_reserved_mem or alloc_from_contiguous*/ devp->mem_start = roundup(devp->mem_start, devp->canvas_align); @@ -393,6 +414,7 @@ void vdin_canvas_auto_config(struct vdin_dev_s *devp) /* need to be static for pointer use in codec_mm */ static char vdin_name[6]; /* return val:1: fail;0: ok */ +/* combined canvas and afbce memory */ unsigned int vdin_cma_alloc(struct vdin_dev_s *devp) { unsigned int mem_size, h_size, v_size; @@ -400,6 +422,14 @@ unsigned int vdin_cma_alloc(struct vdin_dev_s *devp) CODEC_MM_FLAGS_DMA; unsigned int max_buffer_num = min_buf_num; unsigned int i; + /*head_size:3840*2160*3*9/32*/ + unsigned int afbce_head_size_byte = PAGE_SIZE * 1712; + /*afbce map_table need 218700 byte at most*/ + unsigned int afbce_table_size_byte = PAGE_SIZE * 60;/*0.3M*/ + unsigned long ref_paddr; + unsigned int mem_used; + unsigned int frame_head_size; + unsigned int mmu_used; if (devp->rdma_enable) max_buffer_num++; @@ -490,17 +520,38 @@ unsigned int vdin_cma_alloc(struct vdin_dev_s *devp) devp->vfmem_size = PAGE_ALIGN(mem_size) + dolby_size_byte; devp->vfmem_size = (devp->vfmem_size/PAGE_SIZE + 1)*PAGE_SIZE; + if (devp->set_canvas_manual == 1) { + for (i = 0; i < VDIN_CANVAS_MAX_CNT; i++) { + if (vdin_set_canvas_addr[i].dmabuff == NULL) + break; + + vdin_set_canvas_addr[i].paddr = + roundup(vdin_set_canvas_addr[i].paddr, + devp->canvas_align); + } + + devp->canvas_max_num = max_buffer_num = i; + devp->vfmem_max_cnt = max_buffer_num; + } + + mem_size = PAGE_ALIGN(mem_size) * max_buffer_num + dolby_size_byte * max_buffer_num; mem_size = (mem_size/PAGE_SIZE + 1)*PAGE_SIZE; - if (mem_size > devp->cma_mem_size) + + if (mem_size > devp->cma_mem_size) { mem_size = devp->cma_mem_size; + pr_err("\nvdin%d cma_mem_size is not enough!!!\n", devp->index); + devp->cma_mem_alloc = 0; + return 1; + } if (devp->index == 0) strcpy(vdin_name, "vdin0"); else if (devp->index == 1) strcpy(vdin_name, "vdin1"); if (devp->cma_config_flag == 0x101) { + /* canvas or afbce paddr */ for (i = 0; i < max_buffer_num; i++) { devp->vfmem_start[i] = codec_mm_alloc_for_dma(vdin_name, devp->vfmem_size/PAGE_SIZE, 0, flags); @@ -509,70 +560,185 @@ unsigned int vdin_cma_alloc(struct vdin_dev_s *devp) devp->index, i); devp->cma_mem_alloc = 0; return 1; - } else { - devp->cma_mem_alloc = 1; - pr_info("vdin%d buf[%d] mem_start = 0x%lx, mem_size = 0x%x\n", - devp->index, i, - devp->vfmem_start[i], devp->vfmem_size); } + if (devp->afbce_info) { + devp->afbce_info->fm_body_paddr[i] = + devp->vfmem_start[i]; + } + pr_info("vdin%d buf[%d] mem_start = 0x%lx, mem_size = 0x%x\n", + devp->index, i, + devp->vfmem_start[i], devp->vfmem_size); } - pr_info("vdin%d codec cma alloc ok!\n", devp->index); + if (devp->afbce_info) + devp->afbce_info->frame_body_size = devp->vfmem_size; devp->mem_size = mem_size; + + if (devp->afbce_info) { + devp->afbce_info->head_paddr = codec_mm_alloc_for_dma( + vdin_name, afbce_head_size_byte/PAGE_SIZE, + 0, flags); + if (devp->afbce_info->head_paddr == 0) { + pr_err("\nvdin%d header codec alloc fail!!!\n", + devp->index); + devp->cma_mem_alloc = 0; + return 1; + } + devp->afbce_info->table_paddr = codec_mm_alloc_for_dma( + vdin_name, afbce_table_size_byte/PAGE_SIZE, + 0, flags); + if (devp->afbce_info->table_paddr == 0) { + pr_err("\nvdin%d table codec alloc fail!!!\n", + devp->index); + codec_mm_free_for_dma(vdin_name, + devp->afbce_info->head_paddr); + devp->cma_mem_alloc = 0; + return 1; + } + devp->afbce_info->head_size = afbce_head_size_byte; + devp->afbce_info->table_size = afbce_table_size_byte; + + pr_info("vdin%d head_start = 0x%lx, head_size = 0x%x\n", + devp->index, devp->afbce_info->head_paddr, + devp->afbce_info->head_size); + pr_info("vdin%d table_start = 0x%lx, table_size = 0x%x\n", + devp->index, devp->afbce_info->table_paddr, + devp->afbce_info->table_size); + } + + devp->cma_mem_alloc = 1; } else if (devp->cma_config_flag == 0x1) { devp->mem_start = codec_mm_alloc_for_dma(vdin_name, mem_size/PAGE_SIZE, 0, flags); - devp->mem_size = mem_size; if (devp->mem_start == 0) { pr_err("\nvdin%d codec alloc fail!!!\n", devp->index); devp->cma_mem_alloc = 0; return 1; - } else { - devp->cma_mem_alloc = 1; - pr_info("vdin%d mem_start = 0x%lx, mem_size = 0x%x\n", - devp->index, devp->mem_start, devp->mem_size); - pr_info("vdin%d codec cma alloc ok!\n", devp->index); } + devp->mem_size = mem_size; + devp->cma_mem_alloc = 1; + pr_info("vdin%d mem_start = 0x%lx, mem_size = 0x%x\n", + devp->index, devp->mem_start, devp->mem_size); } else if (devp->cma_config_flag == 0x100) { for (i = 0; i < max_buffer_num; i++) { devp->vfvenc_pages[i] = dma_alloc_from_contiguous( &(devp->this_pdev->dev), devp->vfmem_size >> PAGE_SHIFT, 0); - if (devp->vfvenc_pages[i]) { - devp->vfmem_start[i] = - page_to_phys(devp->vfvenc_pages[i]); - pr_info("vdin%d buf[%d]mem_start = 0x%lx, mem_size = 0x%x\n", - devp->index, i, - devp->vfmem_start[i], devp->vfmem_size); - } else { + if (!devp->vfvenc_pages[i]) { devp->cma_mem_alloc = 0; pr_err("\nvdin%d cma mem undefined2.\n", devp->index); return 1; } + devp->vfmem_start[i] = + page_to_phys(devp->vfvenc_pages[i]); + pr_info("vdin%d buf[%d]mem_start = 0x%lx, mem_size = 0x%x\n", + devp->index, i, + devp->vfmem_start[i], devp->vfmem_size); } + devp->mem_size = mem_size; devp->cma_mem_alloc = 1; - devp->mem_size = mem_size; - pr_info("vdin%d cma alloc ok!\n", devp->index); } else { + /* canvas or afbce paddr */ devp->venc_pages = dma_alloc_from_contiguous( &(devp->this_pdev->dev), devp->cma_mem_size >> PAGE_SHIFT, 0); - if (devp->venc_pages) { - devp->mem_start = - page_to_phys(devp->venc_pages); - devp->mem_size = mem_size; - devp->cma_mem_alloc = 1; - pr_info("vdin%d mem_start = 0x%lx, mem_size = 0x%x\n", - devp->index, devp->mem_start, devp->mem_size); - pr_info("vdin%d cma alloc ok!\n", devp->index); - } else { + if (!devp->venc_pages) { devp->cma_mem_alloc = 0; pr_err("\nvdin%d cma mem undefined2.\n", devp->index); return 1; } + devp->mem_start = page_to_phys(devp->venc_pages); + devp->mem_size = mem_size; + + /* set fm_body_paddr */ + if (devp->afbce_info) { + ref_paddr = devp->mem_start; + devp->afbce_info->frame_body_size = devp->vfmem_size; + for (i = 0; i < max_buffer_num; i++) { + ref_paddr = devp->mem_start + + (devp->vfmem_size * i); + devp->afbce_info->fm_body_paddr[i] = ref_paddr; + + pr_info("vdin%d body[%d]_start = 0x%lx, body_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_body_paddr[i], + devp->afbce_info->frame_body_size); + } + + /* afbce header & table paddr */ + devp->afbce_info->head_paddr = ref_paddr + + devp->vfmem_size; + devp->afbce_info->head_size = 2 * SZ_1M;/*2M*/ + devp->afbce_info->table_paddr = + devp->afbce_info->head_paddr + + devp->afbce_info->head_size; + devp->afbce_info->table_size = 2 * SZ_1M;/*2M*/ + + pr_info("vdin%d head_start = 0x%lx, head_size = 0x%x\n", + devp->index, devp->afbce_info->head_paddr, + devp->afbce_info->head_size); + pr_info("vdin%d table_start = 0x%lx, table_size = 0x%x\n", + devp->index, devp->afbce_info->table_paddr, + devp->afbce_info->table_size); + + /*check memory over the boundary*/ + mem_used = devp->afbce_info->table_paddr + + devp->afbce_info->table_size - + devp->afbce_info->fm_body_paddr[0]; + if (mem_used > devp->cma_mem_size) { + pr_err("vdin%d error: mem_used(%d) > cma_mem_size(%d)\n", + devp->index, mem_used, + devp->cma_mem_size); + return 1; + } + } + + devp->cma_mem_alloc = 1; + pr_info("vdin%d mem_start = 0x%lx, mem_size = 0x%x\n", + devp->index, devp->mem_start, devp->mem_size); } + + /* set afbce head paddr */ + if (devp->afbce_info) { + /* 1 block = 32 * 4 pixle = 128 pixel */ + /* there is a header in one block, a header has 4 bytes */ + frame_head_size = (int)roundup(devp->vfmem_size, 128); + /*h_active * v_active / 128 * 4 = frame_head_size*/ + frame_head_size = PAGE_ALIGN(frame_head_size / 32); + + devp->afbce_info->frame_head_size = frame_head_size; + + for (i = 0; i < max_buffer_num; i++) { + devp->afbce_info->fm_head_paddr[i] = + devp->afbce_info->head_paddr + + (frame_head_size*i); + + pr_info("vdin%d fm_head_paddr[%d] = 0x%lx, frame_head_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_head_paddr[i], + frame_head_size); + } + + /* set afbce table paddr */ + mmu_used = devp->afbce_info->frame_body_size >> 12; + mmu_used = mmu_used * 4; + mmu_used = PAGE_ALIGN(mmu_used); + devp->afbce_info->frame_table_size = mmu_used; + + for (i = 0; i < max_buffer_num; i++) { + devp->afbce_info->fm_table_paddr[i] = + devp->afbce_info->table_paddr + (mmu_used*i); + + pr_info("vdin%d fm_table_paddr[%d]=0x%lx, frame_table_size = 0x%x\n", + devp->index, i, + devp->afbce_info->fm_table_paddr[i], + devp->afbce_info->frame_table_size); + } + } + + pr_info("vdin%d cma alloc ok!\n", devp->index); return 0; } @@ -599,6 +765,17 @@ void vdin_cma_release(struct vdin_dev_s *devp) strcpy(vdin_name, "vdin1"); if (devp->cma_config_flag == 0x101) { + if (devp->afbce_info) { + if (devp->afbce_info->head_paddr) { + codec_mm_free_for_dma(vdin_name, + devp->afbce_info->head_paddr); + } + if (devp->afbce_info->table_paddr) { + codec_mm_free_for_dma(vdin_name, + devp->afbce_info->table_paddr); + } + } + /* canvas or afbce paddr */ for (i = 0; i < devp->vfmem_max_cnt; i++) codec_mm_free_for_dma(vdin_name, devp->vfmem_start[i]); pr_info("vdin%d codec cma release ok!\n", devp->index); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h index 66aababd2c2e..d97d7675a433 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_canvas.h @@ -31,8 +31,8 @@ #define VDIN_MIN_SOURCE_BITDEPTH 8 -#define VDIN_YUV444_MAX_CMA_WIDTH 1920 -#define VDIN_YUV444_MAX_CMA_HEIGH 1080 +#define VDIN_YUV444_MAX_CMA_WIDTH 4096 +#define VDIN_YUV444_MAX_CMA_HEIGH 2160 extern const unsigned int vdin_canvas_ids[2][VDIN_CANVAS_MAX_CNT]; extern void vdin_canvas_init(struct vdin_dev_s *devp); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c index dc61bc0c0ad4..c37ba4b12eb3 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -159,6 +163,79 @@ static unsigned int vpu_reg_27af = 0x3; #define pr_info(fmt, ...) #endif +u8 *vdin_vmap(ulong addr, u32 size) +{ + u8 *vaddr = NULL; + struct page **pages = NULL; + u32 i, npages, offset = 0; + ulong phys, page_start; + /*pgprot_t pgprot = pgprot_noncached(PAGE_KERNEL);*/ + pgprot_t pgprot = PAGE_KERNEL; + + if (!PageHighMem(phys_to_page(addr))) + return phys_to_virt(addr); + + offset = offset_in_page(addr); + page_start = addr - offset; + npages = DIV_ROUND_UP(size + offset, PAGE_SIZE); + + pages = kmalloc_array(npages, sizeof(struct page *), GFP_KERNEL); + if (!pages) + return NULL; + + for (i = 0; i < npages; i++) { + phys = page_start + i * PAGE_SIZE; + pages[i] = pfn_to_page(phys >> PAGE_SHIFT); + } + + vaddr = vmap(pages, npages, VM_MAP, pgprot); + if (!vaddr) { + pr_err("the phy(%lx) vmaped fail, size: %d\n", + page_start, npages << PAGE_SHIFT); + kfree(pages); + return NULL; + } + + kfree(pages); + + if (vdin_dbg_en) { + pr_info("[vdin HIGH-MEM-MAP] %s, pa(%lx) to va(%p), size: %d\n", + __func__, page_start, vaddr, npages << PAGE_SHIFT); + } + + return vaddr + offset; +} + +void vdin_unmap_phyaddr(u8 *vaddr) +{ + void *addr = (void *)(PAGE_MASK & (ulong)vaddr); + + if (is_vmalloc_or_module_addr(vaddr)) { + if (vdin_dbg_en) + pr_info("----vdin unmap v: %p\n", addr); + vunmap(addr); + } +} + +void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr, + int size, enum dma_data_direction dir) +{ + ulong phy_addr; + + if (is_vmalloc_or_module_addr(vaddr)) { + phy_addr = page_to_phys(vmalloc_to_page(vaddr)) + + offset_in_page(vaddr); + if (phy_addr && PageHighMem(phys_to_page(phy_addr))) { + if (vdin_dbg_en) + pr_info("----vdin flush v: %p, p: %lx\n", + vaddr, phy_addr); + dma_sync_single_for_device(&devp->this_pdev->dev, + phy_addr, size, dir); + } + return; + } +} + /*reset reg mif value of vdin0: * VDIN_WR_CTRL \VDIN_COM_CTRL0\ VDIN_MISC_CTRL */ @@ -464,6 +541,8 @@ void vdin_get_format_convert(struct vdin_dev_s *devp) format_convert = VDIN_FORMAT_CONVERT_YUV_NV21; else if (devp->prop.dest_cfmt == TVIN_NV12) format_convert = VDIN_FORMAT_CONVERT_YUV_NV12; + else if (devp->prop.dest_cfmt == TVIN_YUV444) + format_convert = VDIN_FORMAT_CONVERT_YUV_YUV444; else format_convert = VDIN_FORMAT_CONVERT_YUV_YUV422; break; @@ -586,7 +665,9 @@ static void vdin_set_meas_mux(unsigned int offset, enum tvin_port_e port_, meas_mux = MEAS_MUX_656_B; else if ((is_meson_gxl_cpu() || is_meson_gxm_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && (bt_path == BT_PATH_GPIO)) + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && + (bt_path == BT_PATH_GPIO)) meas_mux = MEAS_MUX_656; else pr_info("cpu not define or do not support bt656"); @@ -669,7 +750,7 @@ static void vdin_set_meas_mux(unsigned int offset, enum tvin_port_e port_, b.BT_PATH_GPIO_B:gxtvbb & gxbb c.txl and txlx don't support bt656 */ -void vdin_set_top(unsigned int offset, +void vdin_set_top(struct vdin_dev_s *devp, unsigned int offset, enum tvin_port_e port, enum tvin_color_fmt_e input_cfmt, unsigned int h, enum bt_path_e bt_path) @@ -697,7 +778,9 @@ void vdin_set_top(unsigned int offset, VDI9_ASFIFO_CTRL_BIT, VDI9_ASFIFO_CTRL_WID); } else if ((is_meson_gxm_cpu() || is_meson_gxl_cpu() || is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && (bt_path == BT_PATH_GPIO)) { + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) && + (bt_path == BT_PATH_GPIO)) { vdin_mux = VDIN_MUX_656; wr_bits(offset, VDIN_ASFIFO_CTRL0, 0xe4, VDI1_ASFIFO_CTRL_BIT, VDI1_ASFIFO_CTRL_WID); @@ -745,18 +828,36 @@ void vdin_set_top(unsigned int offset, if (port != TVIN_PORT_VIU1) wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xe4, VDI6_ASFIFO_CTRL_BIT, VDI6_ASFIFO_CTRL_WID); - else - wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, - VDI6_ASFIFO_CTRL_BIT, VDI6_ASFIFO_CTRL_WID); + else { + if (/*is_meson_gxlx2_cpu() || */is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xd4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + else + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + } break; case 0xc0: /* viu2 */ vdin_mux = VDIN_MUX_VIU_2; if (port != TVIN_PORT_VIU2) wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xe4, VDI8_ASFIFO_CTRL_BIT, VDI8_ASFIFO_CTRL_WID); - else - wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, - VDI8_ASFIFO_CTRL_BIT, VDI8_ASFIFO_CTRL_WID); + else { + if (/*is_meson_gxlx2_cpu() || */is_meson_g12b_cpu() + || is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xd4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + else + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0xf4, + VDI6_ASFIFO_CTRL_BIT, + VDI6_ASFIFO_CTRL_WID); + } break; case 0x100:/* mipi in mybe need modify base on truth */ vdin_mux = VDIN_MUX_MIPI; @@ -772,6 +873,7 @@ void vdin_set_top(unsigned int offset, vdin_mux = VDIN_MUX_NULL; break; } + switch (input_cfmt) { case TVIN_YVYU422: vdin_data_bus_1 = VDIN_MAP_RCR; @@ -787,6 +889,14 @@ void vdin_set_top(unsigned int offset, vdin_data_bus_1 = VDIN_MAP_RCR; vdin_data_bus_2 = VDIN_MAP_Y_G; break; + case TVIN_RGB444: + /*RGB mapping*/ + if (devp->set_canvas_manual == 1) { + vdin_data_bus_0 = VDIN_MAP_RCR; + vdin_data_bus_1 = VDIN_MAP_BPB; + vdin_data_bus_2 = VDIN_MAP_Y_G; + } + break; default: break; } @@ -1453,9 +1563,10 @@ static void vdin_set_color_matrix0_g12a(unsigned int offset, VDIN_MATRIX_COEF_INDEX_BIT, VDIN_MATRIX_COEF_INDEX_WID); wr(offset, - VDIN_MATRIX_PRE_OFFSET0_1, matrix_tbl->pre_offset0_1); + VDIN_HDR2_MATRIXI_PRE_OFFSET0_1, + matrix_tbl->pre_offset0_1); wr(offset, - VDIN_MATRIX_PRE_OFFSET2, matrix_tbl->pre_offset2); + VDIN_HDR2_MATRIXI_PRE_OFFSET2, matrix_tbl->pre_offset2); wr(offset, VDIN_HDR2_MATRIXI_COEF00_01, matrix_tbl->coef00_01); wr(offset, VDIN_HDR2_MATRIXI_COEF02_10, matrix_tbl->coef02_10); wr(offset, VDIN_HDR2_MATRIXI_COEF11_12, matrix_tbl->coef11_12); @@ -1491,7 +1602,8 @@ void vdin_set_matrix(struct vdin_dev_s *devp) */ wr_bits(offset, VDIN_MATRIX_CTRL, 0, VDIN_MATRIX1_EN_BIT, VDIN_MATRIX1_EN_WID); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1525,7 +1637,8 @@ void vdin_set_matrix(struct vdin_dev_s *devp) devp->prop.color_fmt_range, devp->prop.vdin_hdr_Flag, devp->color_range_mode); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1563,7 +1676,8 @@ void vdin_set_matrixs(struct vdin_dev_s *devp, unsigned char id, { switch (id) { case 0: - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1613,7 +1727,8 @@ void vdin_set_prob_xy(unsigned int offset, devp->prop.color_fmt_range, devp->prop.vdin_hdr_Flag, devp->color_range_mode); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu() || is_meson_tm2_cpu()) vdin_set_color_matrix0_g12a(devp->addr_offset, devp->fmt_info_p, devp->format_convert, @@ -1746,7 +1861,13 @@ static inline void vdin_set_hist_mux(struct vdin_dev_s *devp) /* use 11: form matrix1 din */ wr_bits(devp->addr_offset, VDIN_HIST_CTRL, 3, HIST_HIST_DIN_SEL_BIT, HIST_HIST_DIN_SEL_WID); + + /*for project get vdin1 hist*/ + //if (devp->index == 1) + // wr_bits(devp->addr_offset, VDIN_WR_CTRL2, 1, 8, 1); } + + /* urgent ctr config */ /*if vdin fifo over up_th,will trigger increase * urgent responds to vdin write, @@ -1888,7 +2009,14 @@ static inline void vdin_set_wr_ctrl(struct vdin_dev_s *devp, VDIN_WRCTRLREG_PAUSE_BIT, 1); /* swap the 2 64bits word in 128 words */ /*if (is_meson_gxbb_cpu())*/ - wr_bits(offset, VDIN_WR_CTRL, 1, 19, 1); + if (devp->set_canvas_manual == 1) { + /*not swap 2 64bits words in 128 words */ + wr_bits(offset, VDIN_WR_CTRL, 0, 19, 1); + /*little endian*/ + wr_bits(offset, VDIN_WR_H_START_END, 1, 30, 1); + } else + wr_bits(offset, VDIN_WR_CTRL, 1, 19, 1); + } void vdin_set_wr_ctrl_vsync(struct vdin_dev_s *devp, unsigned int offset, enum vdin_format_convert_e format_convert, @@ -1938,7 +2066,7 @@ void vdin_set_wr_ctrl_vsync(struct vdin_dev_s *devp, hconv_mode = 2; swap_cbcr = 0; } -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) { rdma_write_reg_bits(devp->rdma_handle, VDIN_WR_CTRL+devp->addr_offset, @@ -2032,9 +2160,10 @@ unsigned int vdin_get_total_v(unsigned int offset) void vdin_set_canvas_id(struct vdin_dev_s *devp, unsigned int rdma_enable, unsigned int canvas_id) { -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_sm1_cpu()) { rdma_write_reg_bits(devp->rdma_handle, VDIN_COM_CTRL0+devp->addr_offset, 1, VDIN_FORCEGOLINE_EN_BIT, 1); @@ -2058,7 +2187,7 @@ unsigned int vdin_get_canvas_id(unsigned int offset) void vdin_set_chma_canvas_id(struct vdin_dev_s *devp, unsigned int rdma_enable, unsigned int canvas_id) { -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (rdma_enable) rdma_write_reg_bits(devp->rdma_handle, VDIN_WR_CTRL2+devp->addr_offset, @@ -2468,7 +2597,7 @@ void vdin_set_all_regs(struct vdin_dev_s *devp) devp->color_depth_mode, devp->source_bitdepth); /* top sub-module */ - vdin_set_top(devp->addr_offset, devp->parm.port, + vdin_set_top(devp, devp->addr_offset, devp->parm.port, devp->prop.color_format, devp->h_active, devp->bt_path); @@ -2476,7 +2605,6 @@ void vdin_set_all_regs(struct vdin_dev_s *devp) vdin_set_meas_mux(devp->addr_offset, devp->parm.port, devp->bt_path); - } static void vdin_delay_line(unsigned short num, unsigned int offset) @@ -2620,6 +2748,8 @@ void vdin_set_default_regmap(unsigned int offset) is_meson_gxtvbb_cpu() || is_meson_txl_cpu() || is_meson_txlx_cpu() || is_meson_tl1_cpu()) wr(offset, VDIN_LFIFO_CTRL, 0x00000f00); + else if (is_meson_tm2_cpu()) + wr(offset, VDIN_LFIFO_CTRL, 0xc0020f00); else wr(offset, VDIN_LFIFO_CTRL, 0x00000780); /* [15:14] clkgate.bbar = 0/(auto, off, on, on) */ @@ -2858,6 +2988,18 @@ unsigned int vdin_get_field_type(unsigned int offset) { return rd_bits(offset, VDIN_COM_STATUS0, 0, 1); } + +bool vdin_check_vdi6_afifo_overflow(unsigned int offset) +{ + return rd_bits(offset, VDIN_COM_STATUS2, 15, 1); +} + +void vdin_clear_vdi6_afifo_overflow_flg(unsigned int offset) +{ + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0x1, 1, 1); + wr_bits(offset, VDIN_ASFIFO_CTRL3, 0x0, 1, 1); +} + static unsigned int vdin_reset_flag; inline int vdin_vsync_reset_mif(int index) { @@ -3485,6 +3627,7 @@ void vdin_force_gofiled(struct vdin_dev_s *devp) void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) { unsigned int index, alloc_size; + int highmem_flag; alloc_size = dolby_size_byte*size; devp->dv.dv_dma_vaddr = dma_alloc_coherent(&devp->this_pdev->dev, @@ -3494,41 +3637,87 @@ void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size) return; } memset(devp->dv.dv_dma_vaddr, 0, alloc_size); + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + for (index = 0; index < size; index++) { devp->vfp->dv_buf_mem[index] = devp->dv.dv_dma_paddr + dolby_size_byte * index; devp->vfp->dv_buf_vmem[index] = devp->dv.dv_dma_vaddr + dolby_size_byte * index; - if ((devp->cma_config_flag & 0x100) && devp->cma_config_en) - devp->vfp->dv_buf_ori[index] = - phys_to_virt(devp->vfmem_start[index] + - devp->vfmem_size - - dolby_size_byte); - else - devp->vfp->dv_buf_ori[index] = - phys_to_virt(devp->mem_start + devp->mem_size - - dolby_size_byte * - (devp->canvas_max_num - index)); + + if (highmem_flag == 0) { + if ((devp->cma_config_flag & 0x100) + && devp->cma_config_en) + devp->vfp->dv_buf_ori[index] = + phys_to_virt(devp->vfmem_start[index] + + devp->vfmem_size - + dolby_size_byte); + else + devp->vfp->dv_buf_ori[index] = + phys_to_virt(devp->mem_start + + devp->mem_size - + dolby_size_byte * + (devp->canvas_max_num - index)); + } else { + if ((devp->cma_config_flag & 0x100) + && devp->cma_config_en) + devp->vfp->dv_buf_ori[index] = + vdin_vmap(devp->vfmem_start[index] + + devp->vfmem_size-dolby_size_byte, + dolby_size_byte); + else + devp->vfp->dv_buf_ori[index] = + vdin_vmap(devp->mem_start + + devp->mem_size - + dolby_size_byte * + (devp->canvas_max_num - index), + dolby_size_byte); + } pr_info("%s:dv_buf[%d]=0x%p(0x%x,0x%p)\n", __func__, index, devp->vfp->dv_buf_ori[index], devp->vfp->dv_buf_mem[index], devp->vfp->dv_buf_vmem[index]); } + devp->dv.dv_mem_alloced = 1; pr_info("%s:dv_dma_vaddr=0x%p,dv_dma_paddr=0x%lx\n", __func__, devp->dv.dv_dma_vaddr, (ulong)devp->dv.dv_dma_paddr); } void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size) { unsigned int alloc_size; + int highmem_flag; + int index; + + if (devp->dv.dv_mem_alloced == 0) + return; alloc_size = dolby_size_byte*size; if (devp->dv.dv_dma_vaddr) dma_free_coherent(&devp->this_pdev->dev, alloc_size, devp->dv.dv_dma_vaddr, devp->dv.dv_dma_paddr); devp->dv.dv_dma_vaddr = NULL; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag) { + for (index = 0; index < size; index++) { + if (devp->vfp->dv_buf_ori[index]) { + vdin_unmap_phyaddr( + devp->vfp->dv_buf_ori[index]); + devp->vfp->dv_buf_ori[index] = NULL; + } + } + } + devp->dv.dv_mem_alloced = 0; } -static void vdin_dolby_metadata_swap(char *buf) +static void vdin_dolby_metadata_swap(struct vdin_dev_s *devp, char *buf) { char ext; unsigned int i, j; @@ -3540,6 +3729,8 @@ static void vdin_dolby_metadata_swap(char *buf) buf[i*16+15-j] = ext; } } + + vdin_dma_flush(devp, buf, dolby_size_byte, DMA_TO_DEVICE); } #define swap32(num) \ @@ -3637,7 +3828,8 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index) for (count = 0; count < META_RETRY_MAX; count++) { if (dv_dbg_mask & DV_READ_MODE_AXI) { memcpy(p, devp->vfp->dv_buf_vmem[index], 128); - vdin_dolby_metadata_swap(c); + vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE); + vdin_dolby_metadata_swap(devp, c); } else { wr(offset, VDIN_DOLBY_DSC_CTRL3, 0); wr(offset, VDIN_DOLBY_DSC_CTRL2, 0xd180c0d5); @@ -3650,7 +3842,9 @@ void vdin_dolby_buffer_update(struct vdin_dev_s *devp, unsigned int index) if ((i == 31) && (multimeta_flag == 0)) break; } + vdin_dma_flush(devp, p, 128, DMA_TO_DEVICE); } + meta_size = (c[3] << 8) | c[4]; crc = p[31]; crc_result = crc32(0, p, 124); @@ -3778,6 +3972,7 @@ void vdin_dolby_config(struct vdin_dev_s *devp) } } +unsigned int vdin0_afbce_debug_force; int vdin_event_cb(int type, void *data, void *op_arg) { unsigned long flags; @@ -3849,6 +4044,26 @@ int vdin_event_cb(int type, void *data, void *op_arg) pr_info("%s(type 0x%x vf index 0x%x)=>disp_mode %d,req_mode:%d\n", __func__, type, index_disp, req->disp_mode, req->req_mode); + } else if (type & VFRAME_EVENT_RECEIVER_NEED_NO_COMP) { + struct vdin_dev_s *devp = vdin_get_dev(0); + unsigned int *cnt; + + /* use for debug */ + if (vdin0_afbce_debug_force) + return 0; + + cnt = (unsigned int *)data; + if (*cnt) { + devp->afbce_mode = 0; + } else { + if (devp->afbce_valid) + devp->afbce_mode = 1; + } + + if (vdin_ctl_dbg&(1<<1)) + pr_info("%s(type 0x%x vdin%d) afbce_mode: %d, vpp_cnt: %d\n", + __func__, type, devp->index, + devp->afbce_mode, *cnt); } return 0; } @@ -4026,9 +4241,11 @@ u32 vdin_get_curr_field_type(struct vdin_dev_s *devp) } format_convert = devp->format_convert; if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV444) || - (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444)) + (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV444)) { type |= VIDTYPE_VIU_444; - else if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || + if (devp->afbce_mode_pre) + type |= VIDTYPE_COMB_MODE; + } else if ((format_convert == VDIN_FORMAT_CONVERT_YUV_YUV422) || (format_convert == VDIN_FORMAT_CONVERT_RGB_YUV422)) type |= VIDTYPE_VIU_422; else if (devp->prop.dest_cfmt == TVIN_NV21) { @@ -4039,6 +4256,17 @@ u32 vdin_get_curr_field_type(struct vdin_dev_s *devp) type &= (~VIDTYPE_VIU_SINGLE_PLANE); } + + if (devp->afbce_valid) + type |= VIDTYPE_SUPPORT_COMPRESS; + if (devp->afbce_mode_pre) { + type |= VIDTYPE_COMPRESS; + type |= VIDTYPE_NO_DW; + type |= VIDTYPE_SCATTER; + if (devp->afbce_flag & VDIN_AFBCE_EN_LOOSY) + type |= VIDTYPE_COMPRESS_LOSS; + } + return type; } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h index 178c74a0a387..93ff0b3e37f8 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_ctl.h @@ -17,7 +17,11 @@ #ifndef __TVIN_VDIN_CTL_H #define __TVIN_VDIN_CTL_H - +#include +#include +#include +#include +#include #include "vdin_drv.h" #define DV_SWAP_EN (1 << 0) @@ -111,10 +115,16 @@ struct ldim_max_s { #endif extern unsigned int game_mode; +extern bool vdin_dbg_en; /* ************************************************************************ */ /* ******** GLOBAL FUNCTION CLAIM ******** */ /* ************************************************************************ */ +extern u8 *vdin_vmap(ulong addr, u32 size); +extern void vdin_unmap_phyaddr(u8 *vaddr); +extern void vdin_dma_flush(struct vdin_dev_s *devp, void *vaddr, + int size, enum dma_data_direction dir); + extern void vdin_set_vframe_prop_info(struct vframe_s *vf, struct vdin_dev_s *devp); extern void LDIM_Initial_2(int pic_h, int pic_v, int BLK_Vnum, @@ -135,6 +145,8 @@ extern void vdin_hw_enable(unsigned int offset); extern void vdin_hw_disable(unsigned int offset); extern unsigned int vdin_get_field_type(unsigned int offset); extern int vdin_vsync_reset_mif(int index); +extern bool vdin_check_vdi6_afifo_overflow(unsigned int offset); +extern void vdin_clear_vdi6_afifo_overflow_flg(unsigned int offset); extern void vdin_set_cutwin(struct vdin_dev_s *devp); extern void vdin_set_decimation(struct vdin_dev_s *devp); extern void vdin_fix_nonstd_vsync(struct vdin_dev_s *devp); @@ -177,7 +189,7 @@ extern void vdin_dolby_addr_alloc(struct vdin_dev_s *devp, unsigned int size); extern void vdin_dolby_addr_release(struct vdin_dev_s *devp, unsigned int size); extern int vdin_event_cb(int type, void *data, void *op_arg); extern void vdin_hdmiin_patch(struct vdin_dev_s *devp); -extern void vdin_set_top(unsigned int offset, +extern void vdin_set_top(struct vdin_dev_s *devp, unsigned int offset, enum tvin_port_e port, enum tvin_color_fmt_e input_cfmt, unsigned int h, enum bt_path_e bt_path); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c index cf16fb1f027e..475106b5634a 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_debug.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include /* Local Headers */ @@ -31,6 +32,7 @@ #include "vdin_drv.h" #include "vdin_ctl.h" #include "vdin_regs.h" +#include "vdin_afbce.h" /*2018-07-18 add debugfs*/ #include #include @@ -273,7 +275,11 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, struct file *filp = NULL; loff_t pos = 0; void *buf = NULL; - unsigned int i; + unsigned int i, j; + unsigned int span = 0, count = 0; + int highmem_flag; + unsigned long highaddr; + unsigned long phys; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); @@ -288,7 +294,22 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, pr_info("%s:no cma alloc mem!!!\n", __func__); return; } - if (buf_num < devp->canvas_max_num) { + + if (buf_num >= devp->canvas_max_num) { + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + pr_info("buf_num > canvas_max_num, vdin exit dump\n"); + return; + } + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + pr_info("low mem area\n"); if (devp->cma_config_flag == 0x1) buf = codec_mm_phys_to_virt(devp->mem_start + devp->canvas_max_size*buf_num); @@ -307,6 +328,34 @@ static void vdin_dump_one_buf_mem(char *path, struct vdin_dev_s *devp, /*vfs_write(filp, buf, devp->canvas_max_size, &pos);*/ pr_info("write buffer %2d of %2u to %s.\n", buf_num, devp->canvas_max_num, path); + } else { + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + + if (devp->cma_config_flag == 0x1) + phys = devp->mem_start + devp->canvas_max_size*buf_num; + else if (devp->cma_config_flag == 0x101) + phys = devp->vfmem_start[buf_num]; + else if (devp->cma_config_flag == 0x100) + phys = devp->vfmem_start[buf_num]; + else + phys = devp->mem_start + devp->canvas_max_size*buf_num; + + for (j = 0; j < count; j++) { + highaddr = phys + j * devp->canvas_w; + buf = vdin_vmap(highaddr, span); + if (!buf) { + pr_info("vdin_vmap error\n"); + return; + } + + vdin_dma_flush(devp, buf, span, DMA_FROM_DEVICE); + vfs_write(filp, buf, span, &pos); + vdin_unmap_phyaddr(buf); + } + pr_info("high-mem write buffer %2d of %2u to %s.\n", + buf_num, devp->canvas_max_num, path); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -317,15 +366,20 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) { struct file *filp = NULL; loff_t pos = 0; - loff_t i = 0, j = 0; - unsigned int mem_size = 0; + loff_t mem_size = 0; + unsigned int i = 0, j = 0; + unsigned int span = 0; + unsigned int count = 0; + unsigned long highaddr; + unsigned long phys; + int highmem_flag; void *buf = NULL; void *vfbuf[VDIN_CANVAS_MAX_CNT]; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); filp = filp_open(path, O_RDWR|O_CREAT, 0666); - mem_size = devp->canvas_active_w * devp->canvas_h; + mem_size = (loff_t)devp->canvas_active_w * devp->canvas_h; for (i = 0; i < VDIN_CANVAS_MAX_CNT; i++) vfbuf[i] = NULL; if (IS_ERR(filp)) { @@ -337,33 +391,79 @@ static void vdin_dump_mem(char *path, struct vdin_dev_s *devp) pr_info("%s:no cma alloc mem!!!\n", __func__); return; } - for (i = 0; i < devp->canvas_max_num; i++) { - pos = mem_size * i; - if (devp->cma_config_flag == 0x1) - buf = codec_mm_phys_to_virt(devp->mem_start + - devp->canvas_max_size*i); - else if (devp->cma_config_flag == 0x101) - vfbuf[i] = codec_mm_phys_to_virt( - devp->vfmem_start[i]); - else if (devp->cma_config_flag == 0x100) - vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); - else - buf = phys_to_virt(devp->mem_start + - devp->canvas_max_size*i); - /*only write active data*/ - for (j = 0; j < devp->canvas_h; j++) { - if (devp->cma_config_flag & 0x100) { - vfs_write(filp, vfbuf[i], - devp->canvas_active_w, &pos); - vfbuf[i] += devp->canvas_w; - } else { - vfs_write(filp, buf, - devp->canvas_active_w, &pos); - buf += devp->canvas_w; + + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + /*low mem area*/ + pr_info("low mem area\n"); + for (i = 0; i < devp->canvas_max_num; i++) { + pos = mem_size * i; + if (devp->cma_config_flag == 0x1) + buf = codec_mm_phys_to_virt(devp->mem_start + + devp->canvas_max_size*i); + else if (devp->cma_config_flag == 0x101) + vfbuf[i] = codec_mm_phys_to_virt( + devp->vfmem_start[i]); + else if (devp->cma_config_flag == 0x100) + vfbuf[i] = phys_to_virt(devp->vfmem_start[i]); + else + buf = phys_to_virt(devp->mem_start + + devp->canvas_max_size*i); + /*only write active data*/ + for (j = 0; j < devp->canvas_h; j++) { + if (devp->cma_config_flag & 0x100) { + vfs_write(filp, vfbuf[i], + devp->canvas_active_w, &pos); + vfbuf[i] += devp->canvas_w; + } else { + vfs_write(filp, buf, + devp->canvas_active_w, &pos); + buf += devp->canvas_w; + } } + pr_info("write buffer %2d of %2u to %s.\n", + i, devp->canvas_max_num, path); + } + } else { + /*high mem area*/ + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + + for (i = 0; i < devp->canvas_max_num; i++) { + pos = mem_size * i; + if (devp->cma_config_flag == 0x1) { + phys = devp->mem_start + + devp->canvas_max_size*i; + } else if (devp->cma_config_flag == 0x101) + phys = devp->vfmem_start[i]; + else if (devp->cma_config_flag == 0x100) + phys = devp->vfmem_start[i]; + else { + phys = devp->mem_start + + devp->canvas_max_size*i; + } + + for (j = 0; j < count; j++) { + highaddr = phys + j * devp->canvas_w; + buf = vdin_vmap(highaddr, span); + if (!buf) { + pr_info("vdin_vmap error\n"); + return; + } + + vdin_dma_flush(devp, buf, span, + DMA_FROM_DEVICE); + vfs_write(filp, buf, span, &pos); + vdin_unmap_phyaddr(buf); + } + pr_info("high-mem write buffer %2d of %2u to %s.\n", + i, devp->canvas_max_num, path); } - pr_info("write buffer %lld of %2u to %s.\n", - i, devp->canvas_max_num, path); } vfs_fsync(filp, 0); filp_close(filp, NULL); @@ -378,6 +478,14 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, void *buf_head = NULL; void *buf_table = NULL; void *buf_body = NULL; + unsigned long highaddr; + unsigned long phys; + int highmem_flag = 0; + unsigned int span = 0; + unsigned int remain = 0; + unsigned int count = 0; + unsigned int j = 0; + void *vbuf = NULL; unsigned char buff[100]; mm_segment_t old_fs = get_fs(); @@ -392,30 +500,52 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } - if (devp->cma_config_flag == 0x101) { - buf_head = codec_mm_phys_to_virt( - devp->afbce_info->fm_head_paddr[buf_num]); - buf_table = codec_mm_phys_to_virt( - devp->afbce_info->fm_table_paddr[buf_num]); - buf_body = codec_mm_phys_to_virt( - devp->afbce_info->fm_body_paddr[buf_num]); + highmem_flag = PageHighMem( + phys_to_page(devp->afbce_info->fm_body_paddr[0])); + + if (highmem_flag == 0) { + /*low mem area*/ + pr_info("low mem area\n"); + if (devp->cma_config_flag == 0x101) { + buf_head = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = codec_mm_phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } else if (devp->cma_config_flag == 0) { + buf_head = phys_to_virt( + devp->afbce_info->fm_head_paddr[buf_num]); + buf_table = phys_to_virt( + devp->afbce_info->fm_table_paddr[buf_num]); + buf_body = phys_to_virt( + devp->afbce_info->fm_body_paddr[buf_num]); + + pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", + devp->afbce_info->fm_head_paddr[buf_num], + (devp->afbce_info->fm_table_paddr[buf_num]), + devp->afbce_info->fm_body_paddr[buf_num]); + } + } else { + /*high mem area*/ + pr_info("high mem area\n"); + buf_head = vdin_vmap( + devp->afbce_info->fm_head_paddr[buf_num], + devp->afbce_info->frame_head_size); + + buf_table = vdin_vmap( + devp->afbce_info->fm_table_paddr[buf_num], + devp->afbce_info->frame_table_size); pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", devp->afbce_info->fm_head_paddr[buf_num], (devp->afbce_info->fm_table_paddr[buf_num]), devp->afbce_info->fm_body_paddr[buf_num]); - } else if (devp->cma_config_flag == 0) { - buf_head = phys_to_virt( - devp->afbce_info->fm_head_paddr[buf_num]); - buf_table = phys_to_virt( - devp->afbce_info->fm_table_paddr[buf_num]); - buf_body = phys_to_virt( - devp->afbce_info->fm_body_paddr[buf_num]); - - pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->fm_head_paddr[buf_num], - (devp->afbce_info->fm_table_paddr[buf_num]), - devp->afbce_info->fm_body_paddr[buf_num]); } set_fs(KERNEL_DS); @@ -429,7 +559,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, return; } + vdin_dma_flush(devp, buf_head, + devp->afbce_info->frame_head_size, + DMA_FROM_DEVICE); vfs_write(filp, buf_head, devp->afbce_info->frame_head_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(buf_head); pr_info("write buffer %2d of %2u head to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -444,7 +579,12 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, pr_info("create %s table error.\n", buff); return; } + vdin_dma_flush(devp, buf_table, + devp->afbce_info->frame_table_size, + DMA_FROM_DEVICE); vfs_write(filp, buf_table, devp->afbce_info->frame_table_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(buf_table); pr_info("write buffer %2d of %2u table to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -459,7 +599,42 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, pr_info("create %s body error.\n", buff); return; } - vfs_write(filp, buf_body, devp->afbce_info->frame_body_size, &pos); + if (highmem_flag == 0) { + vfs_write(filp, buf_body, + devp->afbce_info->frame_body_size, &pos); + } else { + span = SZ_1M; + count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span); + remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span); + phys = devp->afbce_info->fm_body_paddr[buf_num]; + + for (j = 0; j < count; j++) { + highaddr = phys + j * span; + vbuf = vdin_vmap(highaddr, span); + if (!vbuf) { + pr_info("vdin_vmap error\n"); + return; + } + + vdin_dma_flush(devp, vbuf, span, DMA_FROM_DEVICE); + vfs_write(filp, vbuf, span, &pos); + vdin_unmap_phyaddr(vbuf); + } + + if (remain) { + span = devp->afbce_info->frame_body_size - remain; + highaddr = phys + span; + vbuf = vdin_vmap(highaddr, remain); + if (!vbuf) { + pr_info("vdin_vmap1 error\n"); + return; + } + + vdin_dma_flush(devp, vbuf, remain, DMA_FROM_DEVICE); + vfs_write(filp, vbuf, remain, &pos); + vdin_unmap_phyaddr(vbuf); + } + } pr_info("write buffer %2d of %2u body to %s.\n", buf_num, devp->canvas_max_num, buff); vfs_fsync(filp, 0); @@ -468,119 +643,6 @@ static void vdin_dump_one_afbce_mem(char *path, struct vdin_dev_s *devp, set_fs(old_fs); } -static void vdin_dump_afbce_mem(char *path, struct vdin_dev_s *devp) -{ - struct file *filp = NULL; - loff_t pos = 0; - void *buf_head = NULL; - void *buf_table = NULL; - void *buf_body = NULL; - unsigned char buff[100]; - unsigned int i; - mm_segment_t old_fs = get_fs(); - - if ((devp->cma_config_flag & 0x1) && - (devp->cma_mem_alloc == 0)) { - pr_info("%s:no cma alloc mem!!!\n", __func__); - return; - } - - if (devp->cma_config_flag == 0x101) { - buf_head = codec_mm_phys_to_virt( - devp->afbce_info->head_paddr); - buf_table = codec_mm_phys_to_virt( - devp->afbce_info->table_paddr); - buf_body = codec_mm_phys_to_virt( - devp->afbce_info->fm_body_paddr[0]); - - pr_info(".head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->head_paddr, - (devp->afbce_info->table_paddr), - devp->afbce_info->fm_body_paddr[0]); - } else if (devp->cma_config_flag == 0) { - buf_head = phys_to_virt( - devp->afbce_info->head_paddr); - buf_table = phys_to_virt( - devp->afbce_info->table_paddr); - buf_body = phys_to_virt( - devp->afbce_info->fm_body_paddr[0]); - - pr_info("head_paddr=0x%lx,table_paddr=0x%lx,body_paddr=0x%lx\n", - devp->afbce_info->head_paddr, - (devp->afbce_info->table_paddr), - devp->afbce_info->fm_body_paddr[0]); - } - - set_fs(KERNEL_DS); - - /* write header bin start */ - strcpy(buff, path); - strcat(buff, "_header.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s header error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_head, - devp->afbce_info->frame_head_size, &pos); - buf_head += devp->afbce_info->frame_head_size; - pr_info("write buffer %2d(0x%x bytes) of %2u head to %s.\n", - i, devp->afbce_info->frame_head_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write header bin end */ - - /* write table bin start */ - pos = 0; - strcpy(buff, path); - strcat(buff, "_table.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s table error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_table, - devp->afbce_info->frame_table_size, &pos); - buf_table += devp->afbce_info->frame_table_size; - pr_info("write buffer %2d(0x%x bytes) of %2u table to %s.\n", - i, devp->afbce_info->frame_table_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write table bin end */ - - /* write body bin start */ - pos = 0; - strcpy(buff, path); - strcat(buff, "_body.bin"); - filp = filp_open(buff, O_RDWR|O_CREAT, 0666); - if (IS_ERR(filp)) { - pr_info("create %s body error.\n", buff); - return; - } - - for (i = 0; i < devp->vfmem_max_cnt; i++) { - vfs_write(filp, buf_body, - devp->afbce_info->frame_body_size, &pos); - buf_body += devp->afbce_info->frame_body_size; - pr_info("write buffer %2d(0x%x bytes) of %2u body to %s.\n", - i, devp->afbce_info->frame_body_size, - devp->canvas_max_num, buff); - } - vfs_fsync(filp, 0); - filp_close(filp, NULL); - /* write body bin end */ - - set_fs(old_fs); -} - static void dump_other_mem(char *path, unsigned int start, unsigned int offset) { @@ -699,6 +761,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("color_depth_support:0x%x\n", devp->color_depth_support); pr_info("cma_flag:0x%x\n", devp->cma_config_flag); pr_info("auto_cutwindow_en:%d\n", devp->auto_cutwindow_en); + pr_info("cutwindow_cfg:%d\n", devp->cutwindow_cfg); pr_info("auto_ratio_en:%d\n", devp->auto_ratio_en); pr_info("cma_mem_alloc:%d\n", devp->cma_mem_alloc); pr_info("cma_mem_size:0x%x\n", devp->cma_mem_size); @@ -745,7 +808,7 @@ static void vdin_dump_state(struct vdin_dev_s *devp) pr_info("vdin_irq_flag: %d, vdin_rest_flag: %d, irq_cnt: %d, rdma_irq_cnt: %d\n", devp->vdin_irq_flag, devp->vdin_reset_flag, devp->irq_cnt, devp->rdma_irq_cnt); - pr_info("rdma_enable : %d\n", devp->rdma_enable); + pr_info("game_mode : %d\n", devp->game_mode); pr_info("dolby_input : %d\n", devp->dv.dolby_input); if ((devp->cma_config_en != 1) || !(devp->cma_config_flag & 0x100)) pr_info("dolby_mem_start = %ld, dolby_mem_size = %d\n", @@ -766,6 +829,8 @@ static void vdin_dump_state(struct vdin_dev_s *devp) devp->dv.dv_flag, devp->dv.dv_config, devp->prop.dolby_vision); pr_info("size of struct vdin_dev_s: %d\n", devp->vdin_dev_ssize); + pr_info("afbce_flag: 0x%x\n", devp->afbce_flag); + pr_info("afbce_mode: %d\n", devp->afbce_mode); if (devp->afbce_mode == 1) { for (i = 0; i < devp->vfmem_max_cnt; i++) { pr_info("head(%d) addr:0x%lx, size:0x%x\n", @@ -789,13 +854,9 @@ static void vdin_dump_state(struct vdin_dev_s *devp) devp->afbce_info->frame_body_size); } } - pr_info("Vdin driver version : %s\n", VDIN_VER); } -/*2018-07-18 add debugfs*/ -struct vdin_dev_s *vdin_get_dev(unsigned int index); - /*same as vdin_dump_state*/ static int seq_file_vdin_state_show(struct seq_file *seq, void *v) { @@ -936,6 +997,140 @@ static void vdin_dump_histgram(struct vdin_dev_s *devp) } } +/*type: 1:nv21 2:yuv422 3:yuv444*/ +static void vdin_write_afbce_mem(struct vdin_dev_s *devp, char *type, + char *path) +{ + char md_path_head[100], md_path_body[100]; + unsigned int i, j; + int highmem_flag = 0; + unsigned int size = 0; + unsigned int span = 0; + unsigned int remain = 0; + unsigned int count = 0; + unsigned long highaddr; + unsigned long phys; + long val; + struct file *filp = NULL; + loff_t pos = 0; + mm_segment_t old_fs; + void *head_dts = NULL; + void *body_dts = NULL; + void *vbuf = NULL; + + if (kstrtol(type, 10, &val) < 0) + return; + if (!path) + return; + + if (!devp->curr_wr_vfe) { + devp->curr_wr_vfe = provider_vf_get(devp->vfp); + if (!devp->curr_wr_vfe) { + pr_info("no buffer to write.\n"); + return; + } + } + + sprintf(md_path_head, "%s_1header.bin", path); + sprintf(md_path_body, "%s_1body.bin", path); + + i = devp->curr_wr_vfe->af_num; + devp->curr_wr_vfe->vf.type = VIDTYPE_VIU_SINGLE_PLANE | + VIDTYPE_VIU_FIELD | VIDTYPE_COMPRESS | VIDTYPE_SCATTER; + switch (val) { + case 1: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_NV21; + break; + case 2: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_422; + break; + case 3: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_444; + break; + default: + devp->curr_wr_vfe->vf.type |= VIDTYPE_VIU_422; + break; + } + + devp->curr_wr_vfe->vf.compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + devp->curr_wr_vfe->vf.compBodyAddr = devp->afbce_info->fm_body_paddr[i]; + + highmem_flag = PageHighMem( + phys_to_page(devp->afbce_info->fm_body_paddr[0])); + if (highmem_flag == 0) { + pr_info("low mem area\n"); + head_dts = codec_mm_phys_to_virt( + devp->afbce_info->fm_head_paddr[i]); + } else { + pr_info("high mem area\n"); + head_dts = vdin_vmap( + devp->afbce_info->fm_head_paddr[i], + devp->afbce_info->frame_head_size); + } + + old_fs = get_fs(); + set_fs(KERNEL_DS); + pr_info("head bin file path = %s\n", md_path_head); + filp = filp_open(md_path_head, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_info("read %s error.\n", md_path_head); + return; + } + + size = vfs_read(filp, head_dts, + devp->afbce_info->frame_head_size, &pos); + if (highmem_flag) + vdin_unmap_phyaddr(head_dts); + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + + pos = 0; + old_fs = get_fs(); + set_fs(KERNEL_DS); + pr_info("body bin file path = %s\n", md_path_body); + filp = filp_open(md_path_body, O_RDONLY, 0); + if (IS_ERR(filp)) { + pr_info("read %s error.\n", md_path_body); + return; + } + + if (highmem_flag == 0) { + body_dts = codec_mm_phys_to_virt( + devp->afbce_info->fm_body_paddr[i]); + + size = vfs_read(filp, body_dts, + devp->afbce_info->frame_body_size, &pos); + } else { + span = SZ_1M; + count = devp->afbce_info->frame_body_size/PAGE_ALIGN(span); + remain = devp->afbce_info->frame_body_size%PAGE_ALIGN(span); + phys = devp->afbce_info->fm_body_paddr[i]; + + + for (j = 0; j < count; j++) { + highaddr = phys + j * span; + vbuf = vdin_vmap(highaddr, span); + if (!vbuf) { + pr_info("vdin_vmap error\n"); + return; + } + vfs_read(filp, vbuf, span, &pos); + vdin_unmap_phyaddr(vbuf); + } + } + + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + + provider_vf_put(devp->curr_wr_vfe, devp->vfp); + devp->curr_wr_vfe = NULL; + vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); +} + static void vdin_write_mem( struct vdin_dev_s *devp, char *type, char *path, char *md_path) @@ -946,8 +1141,10 @@ static void vdin_write_mem( mm_segment_t old_fs; void *dts = NULL; long val; - int index; + int index, j, span; + int highmem_flag, count; unsigned long addr; + unsigned long highaddr; struct vf_pool *p = devp->vfp; /* vtype = simple_strtol(type, NULL, 10); */ @@ -996,15 +1193,43 @@ static void vdin_write_mem( addr = canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr); /* dts = ioremap(canvas_get_addr(devp->curr_wr_vfe->vf.canvas0Addr), */ /* real_size); */ - dts = phys_to_virt(addr); - size = vfs_read(filp, dts, devp->canvas_max_size, &pos); - pr_info("warning: %s read %u < %u\n", - __func__, size, devp->canvas_max_size); - vfs_fsync(filp, 0); - iounmap(dts); - filp_close(filp, NULL); - set_fs(old_fs); + if (devp->cma_config_flag & 0x100) + highmem_flag = PageHighMem(phys_to_page(devp->vfmem_start[0])); + else + highmem_flag = PageHighMem(phys_to_page(devp->mem_start)); + + if (highmem_flag == 0) { + pr_info("low mem area\n"); + dts = phys_to_virt(addr); + for (j = 0; j < devp->canvas_h; j++) { + vfs_read(filp, dts+(devp->canvas_w*j), + devp->canvas_active_w, &pos); + } + vfs_fsync(filp, 0); + iounmap(dts); + filp_close(filp, NULL); + set_fs(old_fs); + } else { + pr_info("high mem area\n"); + count = devp->canvas_h; + span = devp->canvas_active_w; + for (j = 0; j < count; j++) { + highaddr = addr + j * devp->canvas_w; + dts = vdin_vmap(highaddr, span); + if (!dts) { + pr_info("vdin_vmap error\n"); + return; + } + vfs_read(filp, dts, span, &pos); + vdin_dma_flush(devp, dts, span, DMA_TO_DEVICE); + vdin_unmap_phyaddr(dts); + } + vfs_fsync(filp, 0); + filp_close(filp, NULL); + set_fs(old_fs); + } + if (vtype == 8) { old_fs = get_fs(); set_fs(KERNEL_DS); @@ -1020,7 +1245,7 @@ static void vdin_write_mem( u8 *c = devp->vfp->dv_buf_ori[index]; pos = 0; - size = vfs_read(md_flip, + size = (unsigned int)vfs_read(md_flip, devp->vfp->dv_buf_ori[index], 4096, &pos); p->dv_buf_size[index] = size; @@ -1352,6 +1577,9 @@ start_chk: } else if (!strcmp(parm[1], "video")) { param.port = TVIN_PORT_VIU1_VIDEO; pr_info(" port is TVIN_PORT_VIU_VIDEO\n"); + } else if (!strcmp(parm[1], "viu_wb0_vpp")) { + param.port = TVIN_PORT_VIU1_WB0_VPP; + pr_info(" port is TVIN_PORT_VIU1_WB0_VPP\n"); } else if (!strcmp(parm[1], "viu_wb0_vd1")) { param.port = TVIN_PORT_VIU1_WB0_VD1; pr_info(" port is TVIN_PORT_VIU_WB0_VD1\n"); @@ -1367,6 +1595,9 @@ start_chk: } else if (!strcmp(parm[1], "viu_wb0_post_blend")) { param.port = TVIN_PORT_VIU1_WB0_POST_BLEND; pr_info(" port is TVIN_PORT_VIU_WB0_POST_BLEND\n"); + } else if (!strcmp(parm[1], "viu_wb1_vpp")) { + param.port = TVIN_PORT_VIU1_WB1_VPP; + pr_info(" port is TVIN_PORT_VIU1_WB1_VPP\n"); } else if (!strcmp(parm[1], "viu_wb1_vd1")) { param.port = TVIN_PORT_VIU1_WB1_VD1; pr_info(" port is TVIN_PORT_VIU_WB1_VD1\n"); @@ -1388,6 +1619,9 @@ start_chk: } else if (!strcmp(parm[1], "video2")) { param.port = TVIN_PORT_VIU2_VIDEO; pr_info(" port is TVIN_PORT_VIU_VIDEO\n"); + } else if (!strcmp(parm[1], "viu2_wb0_vpp")) { + param.port = TVIN_PORT_VIU2_WB0_VPP; + pr_info(" port is TVIN_PORT_VIU2_WB0_VPP\n"); } else if (!strcmp(parm[1], "viu2_wb0_vd1")) { param.port = TVIN_PORT_VIU2_WB0_VD1; pr_info(" port is TVIN_PORT_VIU_WB0_VD1\n"); @@ -1403,6 +1637,9 @@ start_chk: } else if (!strcmp(parm[1], "viu2_wb0_post_blend")) { param.port = TVIN_PORT_VIU2_WB0_POST_BLEND; pr_info(" port is TVIN_PORT_VIU_WB0_POST_BLEND\n"); + } else if (!strcmp(parm[1], "viu2_wb1_vpp")) { + param.port = TVIN_PORT_VIU2_WB1_VPP; + pr_info(" port is TVIN_PORT_VIU2_WB1_VPP\n"); } else if (!strcmp(parm[1], "viu2_wb1_vd1")) { param.port = TVIN_PORT_VIU2_WB1_VD1; pr_info(" port is TVIN_PORT_VIU_WB1_VD1\n"); @@ -1509,6 +1746,11 @@ start_chk: #endif } else if (!strcmp(parm[0], "force_recycle")) { devp->flags |= VDIN_FLAG_FORCE_RECYCLE; + } else if (!strcmp(parm[0], "read_pic_afbce")) { + if (parm[1] && parm[2]) + vdin_write_afbce_mem(devp, parm[1], parm[2]); + else + pr_err("miss parameters.\n"); } else if (!strcmp(parm[0], "read_pic")) { if (parm[1] && parm[2]) vdin_write_mem(devp, parm[1], parm[2], parm[3]); @@ -1524,11 +1766,23 @@ start_chk: unsigned int offset = devp->addr_offset; pr_info("vdin%d addr offset:0x%x regs start----\n", devp->index, offset); - for (reg = VDIN_SCALE_COEF_IDX; reg <= 0x1273; reg++) - pr_info("[0x%x]reg:0x%x-0x%x\n", - (0xd0100000 + ((reg+offset)<<2)), - (reg+offset), rd(offset, reg)); - pr_info("vdin%d regs end----\n", devp->index); + for (reg = VDIN_SCALE_COEF_IDX; reg <= 0x1273; reg++) { + pr_info("0x%04x = 0x%08x\n", + (reg+offset), rd(offset, reg)); + } + pr_info("vdin%d regs end----\n", devp->index); + if (devp->afbce_flag & VDIN_AFBCE_EN) { + pr_info("vdin%d afbce regs start----\n", devp->index); + for (reg = AFBCE_ENABLE; reg <= AFBCE_MMU_RMIF_RO_STAT; + reg++) { + pr_info("0x%04x = 0x%08x\n", + (reg), R_VCBUS(reg)); + } + pr_info("vdin%d afbce regs end----\n", devp->index); + } + reg = VDIN_MISC_CTRL; + pr_info("0x%04x = 0x%08x\n", (reg), R_VCBUS(reg)); + pr_info("\n"); } else if (!strcmp(parm[0], "rgb_xy")) { unsigned int x = 0, y = 0; @@ -1847,15 +2101,9 @@ start_chk: pr_info("urgent_en (%d):%d\n", devp->index, devp->urgent_en); } - } else if (!strcmp(parm[0], "irq_flag")) { - if (!parm[1]) - pr_err("miss parameters .\n"); - else if (kstrtoul(parm[1], 10, &val) == 0) { - devp->vdin_irq_flag = val; - pr_info("vdin(%d) irq_flag: %d\n", devp->index, - devp->vdin_irq_flag); - } - } else if (!strcmp(parm[0], "skip_vf_num")) { + } else if (!strcmp(parm[0], "irq_cnt")) + pr_info("vdin(%d) irq_cnt: %d\n", devp->index, devp->irq_cnt); + else if (!strcmp(parm[0], "skip_vf_num")) { if (!parm[1]) pr_err("miss parameters .\n"); else if ((kstrtoul(parm[1], 10, &val) == 0) && (devp->vfp)) { @@ -1875,11 +2123,83 @@ start_chk: buf_num = val; vdin_dump_one_afbce_mem(parm[1], devp, buf_num); } else if (parm[1] != NULL) { - vdin_dump_afbce_mem(parm[1], devp); + vdin_dump_one_afbce_mem(parm[1], devp, 0); } - } else { + } else if (!strcmp(parm[0], "skip_frame_debug")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &skip_frame_debug) == 0) + pr_info("set skip_frame_debug: %d\n", + skip_frame_debug); + } else { + pr_info("skip_frame_debug: %d\n", skip_frame_debug); + } + } else if (!strcmp(parm[0], "max_recycle_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, + &max_recycle_frame_cnt) == 0) + pr_info("set max_recycle_frame_cnt: %d\n", + max_recycle_frame_cnt); + } else { + pr_info("max_recycle_frame_cnt: %d\n", + max_recycle_frame_cnt); + } + } else if (!strcmp(parm[0], "max_ignore_cnt")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &max_ignore_frame_cnt) == 0) + pr_info("set max_ignore_frame_cnt: %d\n", + max_ignore_frame_cnt); + } else { + pr_info("max_ignore_frame_cnt: %d\n", + max_ignore_frame_cnt); + } + } else if (!strcmp(parm[0], "afbce_flag")) { + if (parm[1] != NULL) { + if (kstrtouint(parm[1], 16, &devp->afbce_flag) == 0) { + pr_info("set vdin_afbce_flag: 0x%x\n", + devp->afbce_flag); + } + } else { + pr_info("vdin_afbce_flag: 0x%x\n", devp->afbce_flag); + } + } else if (!strcmp(parm[0], "afbce_mode")) { + unsigned int mode = 0, flag = 0; + + if (parm[2] != NULL) { + if ((kstrtouint(parm[1], 10, &mode) == 0) && + (kstrtouint(parm[2], 10, &flag) == 0)) { + vdin0_afbce_debug_force = flag; + if (devp->afbce_flag & VDIN_AFBCE_EN) + devp->afbce_mode = mode; + else + devp->afbce_mode = 0; + if (vdin0_afbce_debug_force) { + pr_info("set force vdin_afbce_mode: %d\n", + devp->afbce_mode); + } else { + pr_info("set vdin_afbce_mode: %d\n", + devp->afbce_mode); + } + } + } else if (parm[1] != NULL) { + if (kstrtouint(parm[1], 10, &mode) == 0) { + if (devp->afbce_flag & VDIN_AFBCE_EN) + devp->afbce_mode = mode; + else + devp->afbce_mode = 0; + pr_info("set vdin_afbce_mode: %d\n", + devp->afbce_mode); + } + } else { + pr_info("vdin_afbce_mode: %d\n", devp->afbce_mode); + } + } else if (!strcmp(parm[0], "vdi6_afifo_overflow")) + pr_info("%d\n", + vdin_check_vdi6_afifo_overflow(devp->addr_offset)); + else if (!strcmp(parm[0], "vdi6_afifo_clear")) + vdin_clear_vdi6_afifo_overflow_flg(devp->addr_offset); + else pr_info("unknown command\n"); - } + kfree(buf_orig); return len; } diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c index 74993dc3c561..a0dd165822c3 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.c @@ -41,9 +41,13 @@ #include #include #include +#include +#include +#include #include #include #include +#include /* Amlogic Headers */ #include #include @@ -78,6 +82,10 @@ static unsigned int vdin_addr_offset[VDIN_MAX_DEVS] = {0, 0x80}; static struct vdin_dev_s *vdin_devp[VDIN_MAX_DEVS]; static unsigned long mem_start, mem_end; static unsigned int use_reserved_mem; +static unsigned int pr_times; + +struct vdin_set_canvas_addr_s vdin_set_canvas_addr[VDIN_CANVAS_MAX_CNT]; +static DECLARE_WAIT_QUEUE_HEAD(vframe_waitq); /* * canvas_config_mode * 0: canvas_config in driver probe @@ -86,13 +94,23 @@ static unsigned int use_reserved_mem; */ static int canvas_config_mode = 2; static bool work_mode_simple; -static int max_ignore_frames = 2; -static int ignore_frames; +static int phase_lock_flag; +/*game_mode_switch_frames:min num is 5 by 1080p60hz input test*/ +static int game_mode_switch_frames = 10; +static int game_mode_phlock_switch_frames = 60; static unsigned int dv_work_delby; + +static struct vf_entry *vfe_drop_force; + +unsigned int max_recycle_frame_cnt; +unsigned int max_ignore_frame_cnt = 2; +unsigned int skip_frame_debug; + /* viu isr select: * enable viu_hw_irq for the bandwidth is enough on gxbb/gxtvbb and laters ic */ static bool viu_hw_irq = 1; +static bool de_fmt_flag; #ifdef DEBUG_SUPPORT module_param(canvas_config_mode, int, 0664); @@ -101,20 +119,21 @@ MODULE_PARM_DESC(canvas_config_mode, "canvas configure mode"); module_param(work_mode_simple, bool, 0664); MODULE_PARM_DESC(work_mode_simple, "enable/disable simple work mode"); -module_param(max_ignore_frames, int, 0664); -MODULE_PARM_DESC(max_ignore_frames, "ignore first frames"); - -module_param(ignore_frames, int, 0664); -MODULE_PARM_DESC(ignore_frames, "ignore first frames"); +module_param(viu_hw_irq, bool, 0664); +MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); module_param(dv_work_delby, uint, 0664); MODULE_PARM_DESC(dv_work_delby, "dv_work_delby"); -module_param(viu_hw_irq, bool, 0664); -MODULE_PARM_DESC(viu_hw_irq, "viu_hw_irq"); +module_param(game_mode_switch_frames, int, 0664); +MODULE_PARM_DESC(game_mode_switch_frames, "game mode switch frames"); + +module_param(game_mode_phlock_switch_frames, int, 0664); +MODULE_PARM_DESC(game_mode_phlock_switch_frames, + "game mode switch frames for phase_lock"); #endif -static bool vdin_dbg_en; +bool vdin_dbg_en; module_param(vdin_dbg_en, bool, 0664); MODULE_PARM_DESC(vdin_dbg_en, "enable/disable vdin debug information"); @@ -134,6 +153,8 @@ static unsigned int vdin_drop_cnt; module_param(vdin_drop_cnt, uint, 0664); MODULE_PARM_DESC(vdin_drop_cnt, "vdin_drop_cnt"); +struct vdin_hist_s vdin1_hist; +struct vdin_v4l2_param_s vdin_v4l2_param; static int irq_max_count; @@ -266,11 +287,30 @@ static void vdin_game_mode_check(struct vdin_dev_s *devp) (devp->parm.port != TVIN_PORT_CVBS3)) { if (devp->h_active > 720 && ((devp->parm.info.fps == 50) || (devp->parm.info.fps == 60))) - devp->game_mode = 3; + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + } else { + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_1); + } else - devp->game_mode = 1; - } else + devp->game_mode = VDIN_GAME_MODE_0; + } else if (game_mode == 2)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1); + else if (game_mode == 3)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + else if (game_mode == 4)/*for debug force game mode*/ + devp->game_mode = VDIN_GAME_MODE_0; + else if (game_mode == 5)/*for debug force game mode*/ + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + else devp->game_mode = 0; + + pr_info("%s: game_mode flag=%d, game_mode=%d\n", + __func__, game_mode, devp->game_mode); } /* *based on the bellow parameters: @@ -318,6 +358,7 @@ static void vdin_vf_init(struct vdin_dev_s *devp) #ifndef VDIN_DYNAMIC_DURATION vf->duration = devp->fmt_info_p->duration; #endif + /* init canvas config */ /*if output fmt is nv21 or nv12 , * use the two continuous canvas for one field */ @@ -325,14 +366,20 @@ static void vdin_vf_init(struct vdin_dev_s *devp) (devp->prop.dest_cfmt == TVIN_NV21)) { chromaid = (vdin_canvas_ids[index][(vf->index<<1)+1])<<8; - addr = - vdin_canvas_ids[index][vf->index<<1] | - chromaid; - } else + addr = vdin_canvas_ids[index][vf->index<<1] | chromaid; + } else { addr = vdin_canvas_ids[index][vf->index]; - + } vf->canvas0Addr = vf->canvas1Addr = addr; + /* init afbce config */ + if (devp->afbce_info) { + vf->compHeadAddr = devp->afbce_info->fm_head_paddr[i]; + vf->compBodyAddr = devp->afbce_info->fm_body_paddr[i]; + vf->compWidth = devp->h_active; + vf->compHeight = devp->v_active; + } + /* set source type & mode */ vdin_set_source_type(devp, vf); vdin_set_source_mode(devp, vf); @@ -367,7 +414,7 @@ static void vdin_vf_init(struct vdin_dev_s *devp) } } -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA static void vdin_rdma_irq(void *arg) { struct vdin_dev_s *devp = arg; @@ -376,12 +423,37 @@ static void vdin_rdma_irq(void *arg) return; } -static struct rdma_op_s vdin_rdma_op = { - vdin_rdma_irq, - NULL -}; +static struct rdma_op_s vdin_rdma_op[VDIN_MAX_DEVS]; #endif +static void vdin_afbce_mode_init(struct vdin_dev_s *devp) +{ + /* afbce_valid means can switch into afbce mode */ + devp->afbce_valid = 0; + if (devp->afbce_flag & VDIN_AFBCE_EN) { + if ((devp->h_active > 1920) && (devp->v_active > 1080)) { + if (devp->afbce_flag & VDIN_AFBCE_EN_4K) + devp->afbce_valid = 1; + } else if ((devp->h_active > 1280) && (devp->v_active > 720)) { + if (devp->afbce_flag & VDIN_AFBCE_EN_1080P) + devp->afbce_valid = 1; + } else if ((devp->h_active > 720) && (devp->v_active > 576)) { + if (devp->afbce_flag & VDIN_AFBCE_EN_720P) + devp->afbce_valid = 1; + } else { + if (devp->afbce_flag & VDIN_AFBCE_EN_SMALL) + devp->afbce_valid = 1; + } + } + + /* default non-afbce mode + * switch to afbce_mode if need by vpp notify + */ + devp->afbce_mode = 0; + devp->afbce_mode_pre = devp->afbce_mode; + pr_info("vdin%d init afbce_mode: %d\n", devp->index, devp->afbce_mode); +} + /* * 1. config canvas base on canvas_config_mode * 0: canvas_config in driver probe @@ -408,10 +480,10 @@ void vdin_start_dec(struct vdin_dev_s *devp) pr_info("[vdin]%s null error.\n", __func__); return; } + if (devp->frontend && devp->frontend->sm_ops) { sm_ops = devp->frontend->sm_ops; sm_ops->get_sig_property(devp->frontend, &devp->prop); - if (!(devp->flags & VDIN_FLAG_V4L2_DEBUG)) devp->parm.info.cfmt = devp->prop.color_format; if ((devp->parm.dest_width != 0) || @@ -434,7 +506,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->prop.ve = devp->debug.cutwin.ve; } } - /*gxbb/gxl/gxm use clkb as vdin clk, *for clkb is low speed,wich is enough for 1080p process, *gxtvbb/txl use vpu clk for process 4k @@ -452,6 +523,21 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->canvas_config_mode = canvas_config_mode; /* h_active/v_active will be recalculated by bellow calling */ vdin_set_decimation(devp); + if (de_fmt_flag == 1 && + (devp->prop.vs != 0 || + devp->prop.ve != 0 || + devp->prop.hs != 0 || + devp->prop.he != 0)) { + devp->prop.vs = 0; + devp->prop.ve = 0; + devp->prop.hs = 0; + devp->prop.he = 0; + devp->prop.pre_vs = 0; + devp->prop.pre_ve = 0; + devp->prop.pre_hs = 0; + devp->prop.pre_he = 0; + pr_info("ioctl start dec,restore the cutwin param.\n"); + } vdin_set_cutwin(devp); vdin_set_hvscale(devp); if (cpu_after_eq(MESON_CPU_MAJOR_ID_GXTVBB)) @@ -460,37 +546,33 @@ void vdin_start_dec(struct vdin_dev_s *devp) if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXL) vdin_fix_nonstd_vsync(devp); - - /*reverse / disable reverse write buffer*/ + /*reverse / disable reverse write buffer*/ vdin_wr_reverse(devp->addr_offset, - devp->parm.h_reverse, - devp->parm.v_reverse); + devp->parm.h_reverse, devp->parm.v_reverse); + + /* check if need enable afbce */ + vdin_afbce_mode_init(devp); + #ifdef CONFIG_CMA vdin_cma_malloc_mode(devp); - if (devp->afbce_mode == 1) { - if (vdin_afbce_cma_alloc(devp)) { - pr_err("\nvdin%d-afbce %s fail for cma alloc fail!!!\n", - devp->index, __func__); - return; - } - } else if (devp->afbce_mode == 0) { - if (vdin_cma_alloc(devp)) { - pr_err("\nvdin%d %s fail for cma alloc fail!!!\n", - devp->index, __func__); - return; - } + if (vdin_cma_alloc(devp)) { + pr_err("\nvdin%d %s fail for cma alloc fail!!!\n", + devp->index, __func__); + return; } #endif + /* h_active/v_active will be used by bellow calling */ - if (devp->afbce_mode == 0) { - if (canvas_config_mode == 1) - vdin_canvas_start_config(devp); - else if (canvas_config_mode == 2) - vdin_canvas_auto_config(devp); - } else if (devp->afbce_mode == 1) { + if (canvas_config_mode == 1) + vdin_canvas_start_config(devp); + else if (canvas_config_mode == 2) + vdin_canvas_auto_config(devp); + + if (devp->afbce_info) { vdin_afbce_maptable_init(devp); vdin_afbce_config(devp); } + #if 0 if ((devp->prop.dest_cfmt == TVIN_NV12) || (devp->prop.dest_cfmt == TVIN_NV21)) @@ -505,7 +587,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) else devp->duration = devp->fmt_info_p->duration; - devp->vfp->size = devp->canvas_max_num; + devp->vfp->size = devp->vfmem_max_cnt; /* canvas and afbce compatible */ vf_pool_init(devp->vfp, devp->vfp->size); vdin_game_mode_check(devp); vdin_vf_init(devp); @@ -523,6 +605,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->abnormal_cnt = 0; devp->last_wr_vfe = NULL; irq_max_count = 0; + vdin_drop_cnt = 0; /* devp->stamp_valid = false; */ devp->stamp = 0; devp->cycle = 0; @@ -537,13 +620,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) vdin_hw_enable(devp->addr_offset); vdin_set_all_regs(devp); - - if (is_meson_tl1_cpu()) { - if (devp->afbce_mode == 0) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); - else if (devp->afbce_mode == 1) - vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); - } + vdin_write_mif_or_afbce_init(devp); if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && (devp->frontend) && @@ -554,7 +631,7 @@ void vdin_start_dec(struct vdin_dev_s *devp) devp->frontend->dec_ops->start(devp->frontend, devp->parm.info.fmt); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA /*it is better put after all reg init*/ if (devp->rdma_enable && devp->rdma_handle > 0) devp->flags |= VDIN_FLAG_RDMA_ENABLE; @@ -576,14 +653,6 @@ void vdin_start_dec(struct vdin_dev_s *devp) #endif vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_START, NULL); - if ((devp->parm.port != TVIN_PORT_VIU1) || - (viu_hw_irq != 0)) { - /*enable irq */ - enable_irq(devp->irq); - if (vdin_dbg_en) - pr_info("****[%s]enable_irq ifdef VDIN_V2****\n", - __func__); - } if (vdin_dbg_en) pr_info("****[%s]ok!****\n", __func__); @@ -599,10 +668,16 @@ void vdin_start_dec(struct vdin_dev_s *devp) #endif devp->irq_cnt = 0; devp->rdma_irq_cnt = 0; + devp->frame_cnt = 0; + phase_lock_flag = 0; + if (time_en) pr_info("vdin.%d start time: %ums, run time:%ums.\n", devp->index, jiffies_to_msecs(jiffies), jiffies_to_msecs(jiffies)-devp->start_time); + + vfe_drop_force = NULL; + devp->recycle_frames = 0; } /* @@ -615,6 +690,9 @@ void vdin_start_dec(struct vdin_dev_s *devp) */ void vdin_stop_dec(struct vdin_dev_s *devp) { + int afbc_write_down_timeout = 500; /* 50ms to cover a 24Hz vsync */ + int i = 0; + /* avoid null pointer oops */ if (!devp || !devp->frontend) return; @@ -624,8 +702,21 @@ void vdin_stop_dec(struct vdin_dev_s *devp) return; } #endif + disable_irq_nosync(devp->irq); - vdin_hw_disable(devp->addr_offset); + + if (devp->afbce_mode == 1) { + while (i++ < afbc_write_down_timeout) { + if (vdin_afbce_read_writedown_flag()) + break; + usleep_range(100, 105); + } + if (i >= afbc_write_down_timeout) { + pr_info("vdin.%d afbc write done timeout\n", + devp->index); + } + } + if (!(devp->parm.flag & TVIN_PARM_FLAG_CAP) && devp->frontend->dec_ops && devp->frontend->dec_ops->stop && @@ -633,6 +724,8 @@ void vdin_stop_dec(struct vdin_dev_s *devp) ((devp->flags & VDIN_FLAG_SNOW_FLAG) == 0))) devp->frontend->dec_ops->stop(devp->frontend, devp->parm.port); + vdin_hw_disable(devp->addr_offset); + vdin_set_default_regmap(devp->addr_offset); /*only for vdin0*/ if (devp->urgent_en && (devp->index == 0)) @@ -649,24 +742,29 @@ void vdin_stop_dec(struct vdin_dev_s *devp) #endif vf_unreg_provider(&devp->vprov); devp->dv.dv_config = 0; -#ifdef CONFIG_CMA - if (devp->afbce_mode == 1) - vdin_afbce_cma_release(devp); - else if (devp->afbce_mode == 0) - vdin_cma_release(devp); -#endif + + if (devp->afbce_mode == 1) { + vdin_afbce_hw_disable(); + vdin_afbce_soft_reset(); + } + +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION vdin_dolby_addr_release(devp, devp->vfp->size); +#endif - +#ifdef CONFIG_CMA + vdin_cma_release(devp); +#endif switch_vpu_mem_pd_vmod(devp->addr_offset?VPU_VIU_VDIN1:VPU_VIU_VDIN0, VPU_MEM_POWER_DOWN); memset(&devp->prop, 0, sizeof(struct tvin_sig_property_s)); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA rdma_clear(devp->rdma_handle); #endif devp->flags &= (~VDIN_FLAG_RDMA_ENABLE); - ignore_frames = 0; + devp->ignore_frames = 0; devp->cycle = 0; + /* clear color para*/ memset(&devp->prop, 0, sizeof(devp->prop)); if (time_en) @@ -694,6 +792,7 @@ int start_tvin_service(int no, struct vdin_parm_s *para) __func__, no); return -1; } + fmt = devp->parm.info.fmt; if (vdin_dbg_en) { pr_info("**[%s]cfmt:%d;dfmt:%d;dest_hactive:%d;", @@ -705,21 +804,24 @@ int start_tvin_service(int no, struct vdin_parm_s *para) pr_info("v_active:%d;scan_mode:%d**\n", para->v_active, para->scan_mode); } + + if (devp->index == 1) { + devp->parm.reserved |= para->reserved; + pr_info("vdin1 add reserved = 0x%lx\n", para->reserved); + pr_info("vdin1 all reserved = 0x%x\n", devp->parm.reserved); + } devp->start_time = jiffies_to_msecs(jiffies); if (devp->flags & VDIN_FLAG_DEC_STARTED) { pr_err("%s: port 0x%x, decode started already.\n", __func__, para->port); - ret = -EBUSY; - return ret; - } - if ((para->port != TVIN_PORT_VIU1) || - (viu_hw_irq != 0)) { - ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, - devp->irq_name, (void *)devp); - devp->flags |= VDIN_FLAG_ISR_REQ; - /*disable vsync irq until vdin configured completely*/ - disable_irq_nosync(devp->irq); + if ((devp->parm.reserved & PARAM_STATE_SCREENCAP) && + (devp->parm.reserved & PARAM_STATE_HISTGRAM) && + (devp->index == 1)) + return 0; + else + return -EBUSY; } + vdin_clk_onoff(devp, true); /*config the vdin use default value*/ vdin_set_default_regmap(devp->addr_offset); @@ -778,6 +880,7 @@ int start_tvin_service(int no, struct vdin_parm_s *para) fe = tvin_get_frontend(para->port, 1); } else fe = tvin_get_frontend(para->port, 0); + if (fe) { fe->private_data = para; fe->port = para->port; @@ -801,6 +904,17 @@ int start_tvin_service(int no, struct vdin_parm_s *para) devp->flags |= VDIN_FLAG_DEC_OPENED; devp->flags |= VDIN_FLAG_DEC_STARTED; + if ((para->port != TVIN_PORT_VIU1) || + (viu_hw_irq != 0)) { + ret = request_irq(devp->irq, vdin_v4l2_isr, IRQF_SHARED, + devp->irq_name, (void *)devp); + + if (ret != 0) { + pr_info("vdin_v4l2_isr request irq error.\n"); + return -1; + } + devp->flags |= VDIN_FLAG_ISR_REQ; + } return 0; } EXPORT_SYMBOL(start_tvin_service); @@ -816,6 +930,14 @@ int stop_tvin_service(int no) unsigned int end_time; devp = vdin_devp[no]; + if ((devp->parm.reserved & PARAM_STATE_HISTGRAM) && + (devp->parm.reserved & PARAM_STATE_SCREENCAP) && + (devp->index == 1)) { + pr_info("stop vdin v4l2 screencap.\n"); + devp->parm.reserved &= ~PARAM_STATE_SCREENCAP; + return 0; + } + if (!(devp->flags&VDIN_FLAG_DEC_STARTED)) { pr_err("%s:decode hasn't started.\n", __func__); return -EBUSY; @@ -1171,6 +1293,77 @@ static u64 func_div(u64 cur, u32 divid) return cur; } +static void vdin_hist_tgt(struct vdin_dev_s *devp, struct vframe_s *vf) +{ + int ave_luma; + int pix_sum; + ulong flags; + + spin_lock_irqsave(&devp->hist_lock, flags); + vdin1_hist.sum = vf->prop.hist.luma_sum; + pix_sum = vf->prop.hist.pixel_sum; + vdin1_hist.height = vf->prop.hist.height; + vdin1_hist.width = vf->prop.hist.width; + + if ((vdin1_hist.height == 0) || (vdin1_hist.width == 0)) { + spin_unlock_irqrestore(&devp->hist_lock, flags); + return; + } + + vdin1_hist.ave = + vdin1_hist.sum/(vdin1_hist.height * vdin1_hist.width); + + ave_luma = vdin1_hist.ave; + ave_luma = (ave_luma - 16) < 0 ? 0 : (ave_luma - 16); + vdin1_hist.ave = ave_luma*255/(235-16); + if (vdin1_hist.ave > 255) + vdin1_hist.ave = 255; + + spin_unlock_irqrestore(&devp->hist_lock, flags); +} + +static bool vdin_recycle_frame_check(struct vdin_dev_s *devp) +{ + int skip_flag = 0; + + if (devp->index) + return false; + + if (devp->recycle_frames < max_recycle_frame_cnt) { + devp->recycle_frames++; + skip_flag = 1; + } + + if (skip_flag) { + vfe_drop_force = receiver_vf_get(devp->vfp); + if (vfe_drop_force) + receiver_vf_put(&vfe_drop_force->vf, devp->vfp); + else + pr_info("vdin.%d: skip vf get error\n", devp->index); + return true; + } + + return false; +} + +static void vdin_afbce_mode_update(struct vdin_dev_s *devp) +{ + /* vdin mif/afbce mode update */ + if (devp->afbce_mode) { + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_AFBCE); + vdin_afbce_hw_enable_rdma(devp); + } else { + vdin_afbce_hw_disable_rdma(devp); + vdin_write_mif_or_afbce(devp, VDIN_OUTPUT_TO_MIF); + } + + if (vdin_dbg_en) { + pr_info("vdin.%d: change afbce_mode %d->%d\n", + devp->index, devp->afbce_mode_pre, devp->afbce_mode); + } + devp->afbce_mode_pre = devp->afbce_mode; +} + /* *VDIN_FLAG_RDMA_ENABLE=1 * provider_vf_put(devp->last_wr_vfe, devp->vfp); @@ -1209,12 +1402,21 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (!devp->frontend) { devp->vdin_irq_flag = 1; - goto irq_handled; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + return IRQ_HANDLED; } /* ignore fake irq caused by sw reset*/ if (devp->vdin_reset_flag) { devp->vdin_reset_flag = 0; + devp->vdin_irq_flag = 10; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } return IRQ_HANDLED; } vf_drop_cnt = vdin_drop_cnt; @@ -1230,28 +1432,47 @@ irqreturn_t vdin_isr(int irq, void *dev_id) */ spin_lock_irqsave(&devp->isr_lock, flags); - /* W_VCBUS_BIT(VDIN_MISC_CTRL, 0, 0, 2); */ - devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); + + if (devp->afbce_mode == 1) { + /* no need reset mif under afbc mode */ + devp->vdin_reset_flag = 0; + } else { + /* W_VCBUS_BIT(VDIN_MISC_CTRL, 0, 0, 2); */ + devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); + } if ((devp->flags & VDIN_FLAG_DEC_STOP_ISR) && (!(isr_flag & VDIN_BYPASS_STOP_CHECK))) { vdin_hw_disable(offset); devp->flags &= ~VDIN_FLAG_DEC_STOP_ISR; devp->vdin_irq_flag = 2; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } stamp = vdin_get_meas_vstamp(offset); if (!devp->curr_wr_vfe) { devp->curr_wr_vfe = provider_vf_get(devp->vfp); - devp->curr_wr_vfe->vf.ready_jiffies64 = jiffies_64; - devp->curr_wr_vfe->vf.ready_clock[0] = sched_clock(); + if (devp->curr_wr_vfe) { + devp->curr_wr_vfe->vf.ready_jiffies64 = jiffies_64; + devp->curr_wr_vfe->vf.ready_clock[0] = sched_clock(); + } /*save the first field stamp*/ devp->stamp = stamp; devp->vdin_irq_flag = 3; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } goto irq_handled; } + + /* use RDMA and not game mode */ if (devp->last_wr_vfe && (devp->flags&VDIN_FLAG_RDMA_ENABLE) && - !(devp->game_mode & (1 << 1))) { + !(devp->game_mode & VDIN_GAME_MODE_1) && + !(devp->game_mode & VDIN_GAME_MODE_2)) { /*dolby vision metadata process*/ if (dv_dbg_mask & DV_UPDATE_DATA_MODE_DELBY_WORK && devp->dv.dv_config) { @@ -1281,6 +1502,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } else { devp->vdin_irq_flag = 15; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1295,15 +1520,33 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (devp->dv.dv_config == true)) vf_notify_receiver("dv_vdin", VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + else { +#endif + if (vdin_recycle_frame_check(devp)) { + devp->vdin_irq_flag = 16; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } #endif - vf_notify_receiver(devp->name, - VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); } /*check vs is valid base on the time during continuous vs*/ if (vdin_check_cycle(devp) && (!(isr_flag & VDIN_BYPASS_CYC_CHECK)) && (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) { devp->vdin_irq_flag = 4; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1329,6 +1572,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (state != TVIN_SM_STATUS_STABLE)) && (!(devp->flags & VDIN_FLAG_SNOW_FLAG))) { devp->vdin_irq_flag = 6; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1340,23 +1587,35 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (((devp->parm.flag & TVIN_PARM_FLAG_2D_TO_3D) || (trans_fmt && (trans_fmt != TVIN_TFMT_3D_FP))) && ((last_field_type & VIDTYPE_INTERLACE_BOTTOM) == - VIDTYPE_INTERLACE_BOTTOM) - ) { + VIDTYPE_INTERLACE_BOTTOM)) { devp->vdin_irq_flag = 7; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } curr_wr_vfe = devp->curr_wr_vfe; curr_wr_vf = &curr_wr_vfe->vf; + /* change afbce mode */ + if (devp->afbce_mode_pre != devp->afbce_mode) + vdin_afbce_mode_update(devp); + /* change color matrix */ if (devp->csc_cfg != 0) { prop = &devp->prop; pre_prop = &devp->pre_prop; if ((prop->color_format != pre_prop->color_format) || (prop->vdin_hdr_Flag != pre_prop->vdin_hdr_Flag) || - (prop->color_fmt_range != pre_prop->color_fmt_range)) + (prop->color_fmt_range != pre_prop->color_fmt_range)) { vdin_set_matrix(devp); + if (skip_frame_debug) { + pr_info("vdin.%d color_format changed\n", + devp->index); + } + } if (prop->dest_cfmt != pre_prop->dest_cfmt) { vdin_set_bitdepth(devp); vdin_source_bitdepth_reinit(devp); @@ -1364,15 +1623,29 @@ irqreturn_t vdin_isr(int irq, void *dev_id) devp->format_convert, devp->color_depth_mode, devp->source_bitdepth, devp->flags&VDIN_FLAG_RDMA_ENABLE); - vdin_set_top(devp->addr_offset, devp->parm.port, + vdin_set_top(devp, devp->addr_offset, devp->parm.port, devp->prop.color_format, devp->h_active, devp->bt_path); + + if (devp->afbce_valid) + vdin_afbce_update(devp); + + if (skip_frame_debug) { + pr_info("vdin.%d dest_cfmt changed: %d->%d\n", + devp->index, + pre_prop->dest_cfmt, prop->dest_cfmt); + } } pre_prop->color_format = prop->color_format; pre_prop->vdin_hdr_Flag = prop->vdin_hdr_Flag; pre_prop->color_fmt_range = prop->color_fmt_range; pre_prop->dest_cfmt = prop->dest_cfmt; - ignore_frames = 0; + devp->ignore_frames = 0; + devp->vdin_irq_flag = 20; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1398,6 +1671,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) decops = devp->frontend->dec_ops; if (decops->decode_isr(devp->frontend, devp->hcnt64) == TVIN_BUF_SKIP) { devp->vdin_irq_flag = 8; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1406,10 +1683,13 @@ irqreturn_t vdin_isr(int irq, void *dev_id) curr_wr_vf->phase = sm_ops->get_secam_phase(devp->frontend) ? VFRAME_PHASE_DB : VFRAME_PHASE_DR; - - if (ignore_frames < max_ignore_frames) { - ignore_frames++; + if (devp->ignore_frames < max_ignore_frame_cnt) { devp->vdin_irq_flag = 12; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + devp->ignore_frames++; vdin_drop_cnt++; goto irq_handled; } @@ -1417,19 +1697,38 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (sm_ops->check_frame_skip && sm_ops->check_frame_skip(devp->frontend)) { devp->vdin_irq_flag = 13; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; if (devp->flags&VDIN_FLAG_RDMA_ENABLE) - ignore_frames = 0; + devp->ignore_frames = 0; goto irq_handled; } next_wr_vfe = provider_vf_peek(devp->vfp); if (!next_wr_vfe) { - devp->vdin_irq_flag = 14; - vdin_drop_cnt++; - vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ - goto irq_handled; + /*add for force vdin buffer recycle*/ + if (devp->flags & VDIN_FLAG_FORCE_RECYCLE) { + next_wr_vfe = receiver_vf_get(devp->vfp); + if (next_wr_vfe) + receiver_vf_put(&next_wr_vfe->vf, devp->vfp); + else + pr_err("[vdin.%d]force recycle error,no buffer in ready list", + devp->index); + } else { + devp->vdin_irq_flag = 14; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + vdin_drop_cnt++; + vf_drop_cnt = vdin_drop_cnt;/*avoid do skip*/ + goto irq_handled; + } } + #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (((devp->dv.dolby_input & (1 << devp->index)) || (devp->dv.dv_flag && is_dolby_vision_enable())) && @@ -1440,11 +1739,11 @@ irqreturn_t vdin_isr(int irq, void *dev_id) #endif vdin2nr = vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_QUREY_VDIN2NR, NULL); + /*if vdin-nr,di must get * vdin current field type which di pre will read */ - if ((vdin2nr || (devp->flags & VDIN_FLAG_RDMA_ENABLE)) && - !(devp->game_mode & (1 << 1))) + if (vdin2nr || (devp->flags & VDIN_FLAG_RDMA_ENABLE)) curr_wr_vf->type = devp->curr_field_type; else curr_wr_vf->type = last_field_type; @@ -1454,8 +1753,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) */ if (((devp->parm.flag & TVIN_PARM_FLAG_2D_TO_3D) || (curr_wr_vf->trans_fmt)) && - (last_field_type & VIDTYPE_INTERLACE) - ) { + (last_field_type & VIDTYPE_INTERLACE)) { curr_wr_vf->type &= ~VIDTYPE_INTERLACE_TOP; curr_wr_vf->type |= VIDTYPE_PROGRESSIVE; curr_wr_vf->type |= VIDTYPE_PRE_INTERLACE; @@ -1500,9 +1798,9 @@ irqreturn_t vdin_isr(int irq, void *dev_id) (devp->parm.port <= TVIN_PORT_CVBS3)) vdin_set_display_ratio(devp, curr_wr_vf); if ((devp->flags&VDIN_FLAG_RDMA_ENABLE) && - !(devp->game_mode & (1 << 1))) { + !(devp->game_mode & VDIN_GAME_MODE_1)) { devp->last_wr_vfe = curr_wr_vfe; - } else { + } else if (!(devp->game_mode & VDIN_GAME_MODE_2)) { /*dolby vision metadata process*/ if (dv_dbg_mask & DV_UPDATE_DATA_MODE_DELBY_WORK && devp->dv.dv_config) { @@ -1517,6 +1815,7 @@ irqreturn_t vdin_isr(int irq, void *dev_id) vdin_dolby_addr_update(devp, next_wr_vfe->vf.index); } else devp->dv.dv_crc_check = true; + if ((devp->dv.dv_crc_check == true) || (!(dv_dbg_mask & DV_CRC_CHECK))) { provider_vf_put(curr_wr_vfe, devp->vfp); @@ -1529,6 +1828,10 @@ irqreturn_t vdin_isr(int irq, void *dev_id) } } else { devp->vdin_irq_flag = 15; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } vdin_drop_cnt++; goto irq_handled; } @@ -1536,49 +1839,127 @@ irqreturn_t vdin_isr(int irq, void *dev_id) if (devp->vfp->skip_vf_num > 0) vdin_vf_disp_mode_update(curr_wr_vfe, devp->vfp); } + /*switch to game mode 2 from game mode 1,otherwise may appear blink*/ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { + if (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN) { + /* make sure phase lock for next few frames */ + if (vlock_get_phlock_flag()) + phase_lock_flag++; + if (phase_lock_flag >= game_mode_phlock_switch_frames) { + if (vdin_dbg_en) { + pr_info("switch game mode (%d-->5), frame_cnt=%d\n", + devp->game_mode, + devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | + VDIN_GAME_MODE_2); + } + } +#if 0 + if (phase_lock_flag >= game_mode_phlock_switch_frames) { + if (!vlock_get_phlock_flag()) + phase_lock_flag = 0; + if (vdin_dbg_en) { + pr_info( + "switch game mode to %d, frame_cnt=%d\n", + devp->game_mode, devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_1 | + VDIN_GAME_MODE_SWITCH_EN); + } +#endif + } else { + if ((devp->frame_cnt >= game_mode_switch_frames) && + (devp->game_mode & VDIN_GAME_MODE_SWITCH_EN)) { + if (vdin_dbg_en) { + pr_info("switch game mode (%d-->5), frame_cnt=%d\n", + devp->game_mode, devp->frame_cnt); + } + devp->game_mode = (VDIN_GAME_MODE_0 | VDIN_GAME_MODE_2); + } + } + /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - if (devp->afbce_mode == 0) + if (devp->afbce_mode == 0) { vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr&0xff)); - else if (devp->afbce_mode == 1) + + /* prepare for chroma canvas*/ + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) + vdin_set_chma_canvas_id(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), + (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } else if (devp->afbce_mode == 1) { vdin_afbce_set_next_frame(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); - - /* prepare for chroma canvas*/ - if ((devp->prop.dest_cfmt == TVIN_NV12) || - (devp->prop.dest_cfmt == TVIN_NV21)) - vdin_set_chma_canvas_id(devp, - (devp->flags&VDIN_FLAG_RDMA_ENABLE), - (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } devp->curr_wr_vfe = next_wr_vfe; + next_wr_vfe->vf.type = vdin_get_curr_field_type(devp); /* debug for video latency */ next_wr_vfe->vf.ready_jiffies64 = jiffies_64; next_wr_vfe->vf.ready_clock[0] = sched_clock(); if (!(devp->flags&VDIN_FLAG_RDMA_ENABLE) || - (devp->game_mode & (1 << 1))) { + (devp->game_mode & VDIN_GAME_MODE_1)) { + /* not RDMA, or game mode 1 */ #ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION if (((devp->dv.dolby_input & (1 << devp->index)) || - (devp->dv.dv_flag && is_dolby_vision_enable())) && - (devp->dv.dv_config == true)) + (devp->dv.dv_flag && is_dolby_vision_enable())) + && (devp->dv.dv_config == true)) vf_notify_receiver("dv_vdin", VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); - else + else { #endif + if (vdin_recycle_frame_check(devp)) { + devp->vdin_irq_flag = 17; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, + devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, + NULL); + } +#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION + } +#endif + } else if (devp->game_mode & VDIN_GAME_MODE_2) { + /* game mode 2 */ + provider_vf_put(next_wr_vfe, devp->vfp); + if (vdin_recycle_frame_check(devp)) { + devp->vdin_irq_flag = 18; + if (skip_frame_debug) { + pr_info("vdin.%d: vdin_irq_flag=%d\n", + devp->index, devp->vdin_irq_flag); + } + vdin_drop_cnt++; + } else { vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + if (vdin_dbg_en) { + next_wr_vfe->vf.ready_clock[1] = sched_clock(); + pr_info("vdin put latency %lld us.first %lld us\n", + func_div(next_wr_vfe->vf.ready_clock[1], 1000), + func_div(next_wr_vfe->vf.ready_clock[0], 1000)); + } + } } + devp->frame_cnt++; irq_handled: - /*hdmi skip policy should adapt to all drop vframe case*/ + /*hdmi skip policy should adapt to all drop front vframe case*/ if ((devp->vfp->skip_vf_num > 0) && (vf_drop_cnt < vdin_drop_cnt)) vdin_vf_disp_mode_skip(devp->vfp); spin_unlock_irqrestore(&devp->isr_lock, flags); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (devp->flags & VDIN_FLAG_RDMA_ENABLE) rdma_config(devp->rdma_handle, (devp->rdma_enable&1) ? @@ -1597,6 +1978,15 @@ module_param(skip_ratio, ushort, 0664); MODULE_PARM_DESC(skip_ratio, "\n vdin skip frame ratio 1/ratio will reserved.\n"); +static struct vf_entry *check_vdin_readlist(struct vdin_dev_s *devp) +{ + struct vf_entry *vfe; + + vfe = receiver_vf_peek(devp->vfp); + + return vfe; +} + irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) { ulong flags; @@ -1608,7 +1998,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) struct tvin_decoder_ops_s *decops; struct tvin_state_machine_ops_s *sm_ops; int ret = 0; - int offset; + unsigned int offset; if (!devp) return IRQ_HANDLED; @@ -1623,6 +2013,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) spin_lock_irqsave(&devp->isr_lock, flags); devp->vdin_reset_flag = vdin_vsync_reset_mif(devp->index); offset = devp->addr_offset; + if (devp) /* avoid null pointer oops */ stamp = vdin_get_meas_vstamp(offset); @@ -1646,12 +2037,21 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) } } + if ((devp->set_canvas_manual == 1) && check_vdin_readlist(devp)) { + devp->keystone_vframe_ready = 1; + wake_up_interruptible(&vframe_waitq); + } + if (devp->last_wr_vfe) { provider_vf_put(devp->last_wr_vfe, devp->vfp); devp->last_wr_vfe = NULL; - vf_notify_receiver(devp->name, + + if (devp->set_canvas_manual != 1) { + vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); + } } + /*check vs is valid base on the time during continuous vs*/ vdin_check_cycle(devp); @@ -1680,6 +2080,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) vdin_set_vframe_prop_info(curr_wr_vf, devp); vdin_backup_histgram(curr_wr_vf, devp); + vdin_hist_tgt(devp, curr_wr_vf); if (devp->frontend && devp->frontend->dec_ops) { decops = devp->frontend->dec_ops; @@ -1727,6 +2128,7 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) goto irq_handled; } } + if (curr_wr_vfe) { curr_wr_vfe->flag |= VF_FLAG_NORMAL_FRAME; /* provider_vf_put(curr_wr_vfe, devp->vfp); */ @@ -1735,26 +2137,29 @@ irqreturn_t vdin_v4l2_isr(int irq, void *dev_id) /* prepare for next input data */ next_wr_vfe = provider_vf_get(devp->vfp); - if (devp->afbce_mode == 0) + if (devp->afbce_mode == 0) { vdin_set_canvas_id(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), (next_wr_vfe->vf.canvas0Addr&0xff)); - else if (devp->afbce_mode == 1) + + if ((devp->prop.dest_cfmt == TVIN_NV12) || + (devp->prop.dest_cfmt == TVIN_NV21)) + vdin_set_chma_canvas_id(devp, + (devp->flags&VDIN_FLAG_RDMA_ENABLE), + (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } else if (devp->afbce_mode == 1) { vdin_afbce_set_next_frame(devp, (devp->flags&VDIN_FLAG_RDMA_ENABLE), next_wr_vfe); - - if ((devp->prop.dest_cfmt == TVIN_NV12) || - (devp->prop.dest_cfmt == TVIN_NV21)) - vdin_set_chma_canvas_id(devp, - (devp->flags&VDIN_FLAG_RDMA_ENABLE), - (next_wr_vfe->vf.canvas0Addr>>8)&0xff); + } devp->curr_wr_vfe = next_wr_vfe; - vf_notify_receiver(devp->name, VFRAME_EVENT_PROVIDER_VFRAME_READY, - NULL); + + if (devp->set_canvas_manual != 1) + vf_notify_receiver(devp->name, + VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL); irq_handled: spin_unlock_irqrestore(&devp->isr_lock, flags); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA if (devp->flags & VDIN_FLAG_RDMA_ENABLE) rdma_config(devp->rdma_handle, (devp->rdma_enable&1) ? @@ -1813,6 +2218,9 @@ static int vdin_open(struct inode *inode, struct file *file) devp = container_of(inode->i_cdev, struct vdin_dev_s, cdev); file->private_data = devp; + if (devp->set_canvas_manual == 1) + return 0; + if (devp->index >= VDIN_MAX_DEVS) return -ENXIO; @@ -1823,6 +2231,9 @@ static int vdin_open(struct inode *inode, struct file *file) return 0; } + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu())) + switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_ON); + devp->flags |= VDIN_FLAG_FS_OPENED; /* request irq */ @@ -1868,6 +2279,9 @@ static int vdin_release(struct inode *inode, struct file *file) return 0; } + if ((is_meson_tl1_cpu() || is_meson_tm2_cpu())) + switch_vpu_mem_pd_vmod(VPU_AFBCE, VPU_MEM_POWER_DOWN); + devp->flags &= (~VDIN_FLAG_FS_OPENED); if (devp->flags & VDIN_FLAG_DEC_STARTED) { devp->flags |= VDIN_FLAG_DEC_STOP_ISR; @@ -1912,9 +2326,17 @@ static int vdin_release(struct inode *inode, struct file *file) static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = 0; + int i; int callmaster_status = 0; struct vdin_dev_s *devp = NULL; void __user *argp = (void __user *)arg; + struct vdin_parm_s param; + ulong flags; + struct vdin_hist_s vdin1_hist_temp; + struct page *page; + struct vdin_set_canvas_s vdinsetcanvas[VDIN_CANVAS_MAX_CNT]; + unsigned int idx = 0; + unsigned int recov_idx = 0; /* Get the per-device structure that contains this cdev */ devp = file->private_data; @@ -1995,11 +2417,14 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } if ((devp->parm.info.fmt == TVIN_SIG_FMT_NULL) && - (devp->parm.port == TVIN_PORT_CVBS3)) + (devp->parm.port == TVIN_PORT_CVBS3)) { + de_fmt_flag = 1; fmt = devp->parm.info.fmt = TVIN_SIG_FMT_CVBS_NTSC_M; - else + } else { + de_fmt_flag = 0; fmt = devp->parm.info.fmt = parm.info.fmt; - devp->fmt_info_p = + } + devp->fmt_info_p = (struct tvin_format_s *)tvin_get_fmt_info(fmt); if (!devp->fmt_info_p) { pr_err("TVIN_IOC_START_DEC(%d) error, fmt is null\n", @@ -2009,6 +2434,16 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } vdin_start_dec(devp); + + if ((devp->parm.port != TVIN_PORT_VIU1) || + (viu_hw_irq != 0)) { + /*enable irq */ + enable_irq(devp->irq); + if (vdin_dbg_en) + pr_info("****[%s]enable_irq ifdef VDIN_V2****\n", + __func__); + } + devp->flags |= VDIN_FLAG_DEC_STARTED; if (vdin_dbg_en) pr_info("TVIN_IOC_START_DEC port %s, decode started ok\n\n", @@ -2018,6 +2453,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case TVIN_IOC_STOP_DEC: { struct tvin_parm_s *parm = &devp->parm; + mutex_lock(&devp->fe_lock); if (!(devp->flags & VDIN_FLAG_DEC_STARTED)) { pr_err("TVIN_IOC_STOP_DEC(%d) decode havn't started\n", @@ -2040,6 +2476,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (vdin_dbg_en) pr_info("TVIN_IOC_STOP_DEC(%d) port %s, decode stop ok\n\n", parm->index, tvin_port_str(parm->port)); + mutex_unlock(&devp->fe_lock); reset_tvin_smr(parm->index); break; @@ -2073,6 +2510,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case TVIN_IOC_CLOSE: { struct tvin_parm_s *parm = &devp->parm; enum tvin_port_e port = parm->port; + mutex_lock(&devp->fe_lock); if (!(devp->flags & VDIN_FLAG_DEC_OPENED)) { pr_err("TVIN_IOC_CLOSE(%d) you have not opened port\n", @@ -2090,6 +2528,7 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pr_info("TVIN_IOC_CLOSE(%d) port %s closed ok\n\n", parm->index, tvin_port_str(port)); + mutex_unlock(&devp->fe_lock); break; } @@ -2132,6 +2571,28 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) mutex_unlock(&devp->fe_lock); break; } + case TVIN_IOC_G_FRONTEND_INFO: { + struct tvin_frontend_info_s info; + + if ((!devp) || (!devp->fmt_info_p) || (!devp->curr_wr_vfe)) { + ret = -EFAULT; + break; + } + + memset(&info, 0, sizeof(struct tvin_frontend_info_s)); + mutex_lock(&devp->fe_lock); + info.cfmt = devp->parm.info.cfmt; + info.fps = devp->parm.info.fps; + info.colordepth = devp->prop.colordepth; + info.scan_mode = devp->fmt_info_p->scan_mode; + info.height = devp->curr_wr_vfe->vf.height; + info.width = devp->curr_wr_vfe->vf.width; + if (copy_to_user(argp, &info, + sizeof(struct tvin_frontend_info_s))) + ret = -EFAULT; + mutex_unlock(&devp->fe_lock); + break; + } case TVIN_IOC_G_BUF_INFO: { struct tvin_buf_info_s buf_info; memset(&buf_info, 0, sizeof(buf_info)); @@ -2285,6 +2746,207 @@ static long vdin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) devp->auto_ratio_en); } break; + case TVIN_IOC_GET_LATENCY_MODE: + mutex_unlock(&devp->fe_lock); + if (copy_to_user(argp, + &(devp->prop.latency), + sizeof(struct tvin_latency_s))) { + mutex_unlock(&devp->fe_lock); + ret = -EFAULT; + pr_info("TVIN_IOC_GET_ALLM_MODE err\n\n"); + break; + } + pr_info("allm mode-%d,IT=%d,CN=%d\n\n", + devp->prop.latency.allm_mode, + devp->prop.latency.it_content, + devp->prop.latency.cn_type); + mutex_unlock(&devp->fe_lock); + break; + case TVIN_IOC_G_VDIN_HIST: + if (devp->index == 0) { + pr_info("TVIN_IOC_G_VDIN_HIST cann't be used at vdin0\n"); + break; + } + + spin_lock_irqsave(&devp->hist_lock, flags); + vdin1_hist_temp.sum = vdin1_hist.sum; + vdin1_hist_temp.width = vdin1_hist.width; + vdin1_hist_temp.height = vdin1_hist.height; + vdin1_hist_temp.ave = vdin1_hist.ave; + spin_unlock_irqrestore(&devp->hist_lock, flags); + if (vdin_dbg_en) { + if (pr_times++ > 10) { + pr_times = 0; + pr_info("-:h=%d,w=%d,a=%d\n", + vdin1_hist_temp.height, + vdin1_hist_temp.width, + vdin1_hist_temp.ave); + } + } + + if ((vdin1_hist.height == 0) || (vdin1_hist.width == 0)) + ret = -EFAULT; + else if (copy_to_user(argp, + &vdin1_hist_temp, + sizeof(struct vdin_hist_s))) { + pr_info("vdin1_hist copy fail\n"); + ret = -EFAULT; + } + break; + case TVIN_IOC_S_VDIN_V4L2START: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_VDIN_V4L2START cann't be used at vdin0\n"); + break; + } + if (devp->flags & VDIN_FLAG_ISR_REQ) + free_irq(devp->irq, (void *)devp); + + if (copy_from_user(&vdin_v4l2_param, argp, + sizeof(struct vdin_v4l2_param_s))) { + pr_info("vdin_v4l2_param copy fail\n"); + return -EFAULT; + } + memset(¶m, 0, sizeof(struct vdin_parm_s)); + if (is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) + param.port = TVIN_PORT_VIU1_WB0_VPP; + else + param.port = TVIN_PORT_VIU1; + + param.h_active = vdin_v4l2_param.width; + param.v_active = vdin_v4l2_param.height; + + if (devp->set_canvas_manual != 1) { + param.reserved |= PARAM_STATE_HISTGRAM; + /* use 1280X720 for histgram*/ + if ((vdin_v4l2_param.width > 1280) && + (vdin_v4l2_param.height > 720)) { + devp->debug.scaler4w = 1280; + devp->debug.scaler4h = 720; + devp->debug.dest_cfmt = TVIN_YUV422; + devp->flags |= VDIN_FLAG_MANUAL_CONVERSION; + } + } + + param.frame_rate = vdin_v4l2_param.fps; + param.cfmt = TVIN_YUV422; + + if (devp->set_canvas_manual == 1) + param.dfmt = TVIN_RGB444; + else + param.dfmt = TVIN_YUV422; + + param.scan_mode = TVIN_SCAN_MODE_PROGRESSIVE; + param.fmt = TVIN_SIG_FMT_MAX; + //devp->flags |= VDIN_FLAG_V4L2_DEBUG; + devp->hist_bar_enable = 1; + start_tvin_service(devp->index, ¶m); + break; + + case TVIN_IOC_S_VDIN_V4L2STOP: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_VDIN_V4L2STOP cann't be used at vdin0\n"); + break; + } + devp->parm.reserved &= ~PARAM_STATE_HISTGRAM; + devp->flags &= (~VDIN_FLAG_ISR_REQ); + devp->flags &= (~VDIN_FLAG_FS_OPENED); + stop_tvin_service(devp->index); + + /*release manual set dma-bufs*/ + if (devp->set_canvas_manual == 1) { + for (i = 0; i < 4; i++) { + if (vdin_set_canvas_addr[i].dmabuff == 0) + continue; + + dma_buf_unmap_attachment( + vdin_set_canvas_addr[i].dmabufattach, + vdin_set_canvas_addr[i].sgtable, + DMA_BIDIRECTIONAL); + dma_buf_detach( + vdin_set_canvas_addr[i].dmabuff, + vdin_set_canvas_addr[i].dmabufattach); + dma_buf_put(vdin_set_canvas_addr[i].dmabuff); + devp->keystone_entry[i] = NULL; + } + memset(vdin_set_canvas_addr, 0, + sizeof(struct vdin_set_canvas_addr_s) * + VDIN_CANVAS_MAX_CNT); + } + break; + + case TVIN_IOC_S_CANVAS_ADDR: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_CANVAS_ADDR can't be used at vdin0\n"); + break; + } + + if (copy_from_user(vdinsetcanvas, argp, + sizeof(struct vdin_set_canvas_s) * 4)) { + pr_info("TVIN_IOC_S_CANVAS_ADDR copy fail\n"); + return -EFAULT; + } + + for (i = 0; i < 4; i++) { + /*when fd means, the canvas list reaches end*/ + if (vdinsetcanvas[i].fd < 0) + break; + + if (vdinsetcanvas[i].index >= VDIN_CANVAS_MAX_CNT) { + pr_err("vdin buf idx range (0 ~ %d), current idx is too big.\n ", + VDIN_CANVAS_MAX_CNT - 1); + continue; + } + + idx = vdinsetcanvas[i].index; + + vdin_set_canvas_addr[idx].dmabuff = + dma_buf_get(vdinsetcanvas[i].fd); + + vdin_set_canvas_addr[idx].dmabufattach = + dma_buf_attach( + vdin_set_canvas_addr[idx].dmabuff, + devp->dev); + vdin_set_canvas_addr[idx].sgtable = + dma_buf_map_attachment( + vdin_set_canvas_addr[idx].dmabufattach, + DMA_BIDIRECTIONAL); + + page = sg_page(vdin_set_canvas_addr[idx].sgtable->sgl); + vdin_set_canvas_addr[idx].paddr = + PFN_PHYS(page_to_pfn(page)); + vdin_set_canvas_addr[idx].size = + vdin_set_canvas_addr[idx].dmabuff->size; + + pr_info("TVIN_IOC_S_CANVAS_ADDR[%d] addr=0x%lx, len=0x%x.\n", + i, + vdin_set_canvas_addr[idx].paddr, + vdin_set_canvas_addr[idx].size); + + __close_fd(current->files, vdinsetcanvas[i].fd); + } + break; + + case TVIN_IOC_S_CANVAS_RECOVERY: + if (devp->index == 0) { + pr_info("TVIN_IOC_S_CANVAS_RECOVERY can't be used at vdin0\n"); + break; + } + + if (copy_from_user(&recov_idx, argp, sizeof(unsigned int))) { + pr_info("TVIN_IOC_S_CANVAS_RECOVERY copy fail\n"); + return -EFAULT; + } + + if (devp->keystone_entry[recov_idx]) { + receiver_vf_put(&devp->keystone_entry[recov_idx]->vf, + devp->vfp); + devp->keystone_entry[recov_idx] = NULL; + } else + pr_err("[vdin.%d] idx %d RECOVERY error\n", + devp->index, recov_idx); + break; + default: ret = -ENOIOCTLCMD; /* pr_info("%s %d is not supported command\n", __func__, cmd); */ @@ -2346,22 +3008,57 @@ static unsigned int vdin_poll(struct file *file, poll_table *wait) struct vdin_dev_s *devp = file->private_data; unsigned int mask = 0; - poll_wait(file, &devp->queue, wait); - mask = (POLLIN | POLLRDNORM); + if (devp->set_canvas_manual == 1) { + poll_wait(file, &vframe_waitq, wait); + + if (devp->keystone_vframe_ready == 1) + mask = (POLLIN | POLLRDNORM); + } else { + poll_wait(file, &devp->queue, wait); + mask = (POLLIN | POLLRDNORM); + } return mask; } +static ssize_t vdin_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + int index; + long ret; + struct vf_entry *vfe; + struct vdin_dev_s *devp = file->private_data; + + vfe = receiver_vf_peek(devp->vfp); + if (!vfe) + return 0; + + vfe = receiver_vf_get(devp->vfp); + /*index = report_canvas_index;*/ + index = vfe->vf.index; + devp->keystone_entry[index] = vfe; + ret = copy_to_user(buf, (void *)(&index), sizeof(int)); + if (ret) { + pr_info("vdin_read copy_to_user error\n"); + return -1; + } + + devp->keystone_vframe_ready = 0; + + return sizeof(int); +} + static const struct file_operations vdin_fops = { - .owner = THIS_MODULE, - .open = vdin_open, - .release = vdin_release, - .unlocked_ioctl = vdin_ioctl, + .owner = THIS_MODULE, + .open = vdin_open, + .read = vdin_read, + .release = vdin_release, + .unlocked_ioctl = vdin_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = vdin_compat_ioctl, #endif - .mmap = vdin_mmap, - .poll = vdin_poll, + .mmap = vdin_mmap, + .poll = vdin_poll, }; @@ -2423,9 +3120,10 @@ static int vdin_drv_probe(struct platform_device *pdev) } } vdin_devp[vdevp->index] = vdevp; -#ifdef CONFIG_AML_RDMA - vdin_rdma_op.arg = vdin_devp; - vdevp->rdma_handle = rdma_register(&vdin_rdma_op, +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA + vdin_rdma_op[vdevp->index].irq_cb = vdin_rdma_irq; + vdin_rdma_op[vdevp->index].arg = vdevp; + vdevp->rdma_handle = rdma_register(&vdin_rdma_op[vdevp->index], NULL, RDMA_TABLE_SIZE); pr_info("%s:vdin.%d rdma hanld %d.\n", __func__, vdevp->index, vdevp->rdma_handle); @@ -2528,25 +3226,36 @@ static int vdin_drv_probe(struct platform_device *pdev) else vdevp->color_depth_mode = 0; - /*set afbce mode*/ - ret = of_property_read_u32(pdev->dev.of_node, - "afbce_bit_mode", &vdevp->afbce_mode); - if (ret) { - vdevp->afbce_mode = 0; - pr_info("no afbce mode found, use normal mode\n"); - } else { - if ((is_meson_tl1_cpu()) && (vdevp->index == 0)) { - /* just use afbce at vdin0 */ - pr_info("afbce mode = %d\n", vdevp->afbce_mode); + /*set afbce config*/ + vdevp->afbce_flag = 0; + if (vdevp->index == 0) { /* just use afbce at vdin0 */ + if (is_meson_tl1_cpu() || is_meson_tm2_cpu()) { vdevp->afbce_info = devm_kzalloc(vdevp->dev, sizeof(struct vdin_afbce_s), GFP_KERNEL); if (!vdevp->afbce_info) goto fail_kzalloc_vdev; - } else { - vdevp->afbce_mode = 0; - pr_info("get afbce from dts, but chip cannot support\n"); + + ret = of_property_read_u32(pdev->dev.of_node, + "afbce_bit_mode", &vdevp->afbce_flag); + if (ret) { + vdevp->afbce_flag = 0; + } else { + pr_info("afbce flag = 0x%x\n", + vdevp->afbce_flag); + } } } + + ret = of_property_read_u32(pdev->dev.of_node, + "set_canvas_manual", &vdevp->set_canvas_manual); + + if (ret) { + vdevp->set_canvas_manual = 0; + pr_info("set_canvas_manual = 0\n"); + } else { + pr_info("set_canvas_manual = %d\n", vdevp->set_canvas_manual); + } + /*vdin urgent en*/ ret = of_property_read_u32(pdev->dev.of_node, "urgent_en", &urgent_en); @@ -2560,18 +3269,18 @@ static int vdin_drv_probe(struct platform_device *pdev) vdevp->flags &= (~VDIN_FLAG_FS_OPENED); mutex_init(&vdevp->fe_lock); spin_lock_init(&vdevp->isr_lock); + spin_lock_init(&vdevp->hist_lock); vdevp->frontend = NULL; /* @todo vdin_addr_offset */ if (is_meson_gxbb_cpu() && vdevp->index) vdin_addr_offset[vdevp->index] = 0x70; - else if ((is_meson_g12a_cpu() || is_meson_g12b_cpu() || - is_meson_tl1_cpu()) && vdevp->index) + else if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A) && vdevp->index) vdin_addr_offset[vdevp->index] = 0x100; vdevp->addr_offset = vdin_addr_offset[vdevp->index]; vdevp->flags = 0; /*canvas align number*/ - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) vdevp->canvas_align = 64; else vdevp->canvas_align = 32; @@ -2675,6 +3384,7 @@ static int vdin_drv_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&vdevp->dv.dv_dwork, vdin_dv_dwork); INIT_DELAYED_WORK(&vdevp->vlock_dwork, vdin_vlock_dwork); + vdin_mif_config_init(vdevp); /* 2019-0425 add, ensure mif/afbc bit */ vdin_debugfs_init(vdevp);/*2018-07-18 add debugfs*/ pr_info("%s: driver initialized ok\n", __func__); return 0; @@ -2705,7 +3415,7 @@ static int vdin_drv_remove(struct platform_device *pdev) vdevp = platform_get_drvdata(pdev); ret = cancel_delayed_work(&vdevp->vlock_dwork); -#ifdef CONFIG_AML_RDMA +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA rdma_unregister(vdevp->rdma_handle); #endif mutex_destroy(&vdevp->fe_lock); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h index 43e719ef8576..1c2b04f93922 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_drv.h @@ -36,8 +36,8 @@ #include #include #include -#ifdef CONFIG_AML_RDMA -#include +#ifdef CONFIG_AMLOGIC_MEDIA_RDMA +#include #endif /* Local Headers */ @@ -45,7 +45,10 @@ #include "vdin_vf.h" #include "vdin_regs.h" -#define VDIN_VER "Ref.2018/11/07a" +/* Ref.2019/04/25: tl1 vdin0 afbce dynamically switch support, + * vpp also should support this function + */ +#define VDIN_VER "Ref.2019/04/25" /*the counter of vdin*/ #define VDIN_MAX_DEVS 2 @@ -85,6 +88,12 @@ #define VDIN_BYPASS_VGA_CHECK 0x00000008 #define VDIN_CANVAS_MAX_CNT 9 +/*values of vdin game mode process flag */ +#define VDIN_GAME_MODE_0 (1 << 0) +#define VDIN_GAME_MODE_1 (1 << 1) +#define VDIN_GAME_MODE_2 (1 << 2) +#define VDIN_GAME_MODE_SWITCH_EN (1 << 3) + /*flag for flush vdin buff*/ #define VDIN_FLAG_BLACK_SCREEN_ON 1 #define VDIN_FLAG_BLACK_SCREEN_OFF 0 @@ -100,6 +109,13 @@ /*TXL new add*/ #define VDIN_WR_COLOR_DEPTH_10BIT_FULL_PCAK_MODE (1 << 4) +/* vdin afbce flag */ +#define VDIN_AFBCE_EN (1 << 0) +#define VDIN_AFBCE_EN_LOOSY (1 << 1) +#define VDIN_AFBCE_EN_4K (1 << 4) +#define VDIN_AFBCE_EN_1080P (1 << 5) +#define VDIN_AFBCE_EN_720P (1 << 6) +#define VDIN_AFBCE_EN_SMALL (1 << 7) static inline const char *vdin_fmt_convert_str( enum vdin_format_convert_e fmt_cvt) @@ -141,6 +157,21 @@ static inline const char *vdin_fmt_convert_str( } } +struct vdin_set_canvas_s { + int fd; + int index; +}; + +struct vdin_set_canvas_addr_s { + long paddr; + int size; + + struct dma_buf *dmabuff; + struct dma_buf_attachment *dmabufattach; + struct sg_table *sgtable; +}; +extern struct vdin_set_canvas_addr_s vdin_set_canvas_addr[VDIN_CANVAS_MAX_CNT]; + /*******for debug **********/ struct vdin_debug_s { struct tvin_cutwin_s cutwin; @@ -160,6 +191,7 @@ struct vdin_dv_s { bool dv_flag; bool dv_config; bool dv_crc_check;/*0:fail;1:ok*/ + unsigned int dv_mem_alloced; }; struct vdin_afbce_s { @@ -199,6 +231,7 @@ struct vdin_dev_s { struct timer_list timer; spinlock_t isr_lock; + spinlock_t hist_lock; struct mutex fe_lock; struct clk *msr_clk; unsigned int msr_clk_val; @@ -312,6 +345,8 @@ struct vdin_dev_s { *game_mode: *bit0:enable/disable *bit1:for true bypas and put vframe in advance one vsync + *bit2:for true bypas and put vframe in advance two vsync, + *vdin & vpp read/write same buffer may happen */ unsigned int game_mode; unsigned int rdma_enable; @@ -320,25 +355,62 @@ struct vdin_dev_s { * 1: use afbce non-mmu mode: head/body addr set by code * 2: use afbce mmu mode: head set by code, body addr assigning by hw */ + /*afbce_flag: + *bit[0]: enable afbce + *bit[1]: enable afbce_loosy + *bit[4]: afbce enable for 4k + *bit[5]: afbce enable for 1080p + *bit[6]: afbce enable for 720p + *bit[7]: afbce enable for other small resolution + */ + unsigned int afbce_flag; + unsigned int afbce_mode_pre; unsigned int afbce_mode; + unsigned int afbce_valid; + + /*fot 'T correction' on projector*/ + unsigned int set_canvas_manual; + unsigned int keystone_vframe_ready; + struct vf_entry *keystone_entry[VDIN_CANVAS_MAX_CNT]; unsigned int canvas_config_mode; bool prehsc_en; bool vshrk_en; bool urgent_en; bool black_bar_enable; bool hist_bar_enable; + unsigned int ignore_frames; + unsigned int recycle_frames; /*use frame rate to cal duraton*/ unsigned int use_frame_rate; unsigned int irq_cnt; + unsigned int frame_cnt; unsigned int rdma_irq_cnt; unsigned int vdin_irq_flag; unsigned int vdin_reset_flag; unsigned int vdin_dev_ssize; wait_queue_head_t queue; - struct dentry *dbg_root; /*dbg_fs*/ }; +struct vdin_hist_s { + ulong sum; + int width; + int height; + int ave; +}; + +struct vdin_v4l2_param_s { + int width; + int height; + int fps; +}; + +extern unsigned int max_recycle_frame_cnt; +extern unsigned int max_ignore_frame_cnt; +extern unsigned int skip_frame_debug; + +extern unsigned int vdin0_afbce_debug_force; + extern struct vframe_provider_s *vf_get_provider_by_name( const char *provider_name); extern bool enable_reset; @@ -367,8 +439,6 @@ extern void ldim_get_matrix(int *data, int reg_sel); extern void ldim_set_matrix(int *data, int reg_sel); extern void tvafe_snow_config(unsigned int onoff); extern void tvafe_snow_config_clamp(unsigned int onoff); -extern void tvafe_snow_config_acd(void); -extern void tvafe_snow_config_acd_resume(void); extern void vdin_vf_reg(struct vdin_dev_s *devp); extern void vdin_vf_unreg(struct vdin_dev_s *devp); extern void vdin_pause_dec(struct vdin_dev_s *devp); @@ -378,5 +448,10 @@ extern bool is_dolby_vision_enable(void); extern void vdin_debugfs_init(struct vdin_dev_s *vdevp); extern void vdin_debugfs_exit(struct vdin_dev_s *vdevp); +extern bool vlock_get_phlock_flag(void); + +extern struct vdin_dev_s *vdin_get_dev(unsigned int index); +extern void vdin_mif_config_init(struct vdin_dev_s *devp); + #endif /* __TVIN_VDIN_DRV_H */ diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c index 252a3ab0d2d2..1ac4fbe53744 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.c @@ -92,9 +92,11 @@ static int atv_stable_fmt_check_enable; static int atv_prestable_out_cnt = 100; static int other_stable_out_cnt = EXIT_STABLE_MAX_CNT; static int other_unstable_out_cnt = BACK_STABLE_MAX_CNT; +static int manual_unstable_out_cnt = 30; static int other_unstable_in_cnt = UNSTABLE_MAX_CNT; static int nosig_in_cnt = NOSIG_MAX_CNT; static int nosig2_unstable_cnt = EXIT_NOSIG_MAX_CNT; +bool manual_flag; #ifdef DEBUG_SUPPORT module_param(back_nosig_max_cnt, int, 0664); @@ -332,11 +334,8 @@ void tvin_smr(struct vdin_dev_s *devp) ++sm_p->state_cnt; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AFE if ((port == TVIN_PORT_CVBS3) && - (devp->flags & VDIN_FLAG_SNOW_FLAG)) { + (devp->flags & VDIN_FLAG_SNOW_FLAG)) tvafe_snow_config_clamp(1); - /*fix black side when config atv snow*/ - tvafe_snow_config_acd(); - } #endif if (sm_ops->nosig(devp->frontend)) { sm_p->exit_nosig_cnt = 0; @@ -411,6 +410,9 @@ void tvin_smr(struct vdin_dev_s *devp) (port == TVIN_PORT_CVBS0)) && (devp->flags & VDIN_FLAG_SNOW_FLAG)) unstb_in = sm_p->atv_unstable_out_cnt; + else if ((port == TVIN_PORT_CVBS3) && + manual_flag) + unstb_in = manual_unstable_out_cnt; else if ((port >= TVIN_PORT_HDMI0) && (port <= TVIN_PORT_HDMI7)) unstb_in = sm_p->hdmi_unstable_out_cnt; @@ -475,11 +477,8 @@ void tvin_smr(struct vdin_dev_s *devp) devp->unstable_flag = true; #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_AFE if ((port == TVIN_PORT_CVBS3) && - (devp->flags & VDIN_FLAG_SNOW_FLAG)) { + (devp->flags & VDIN_FLAG_SNOW_FLAG)) tvafe_snow_config_clamp(0); - /*fix black side when config atv snow*/ - tvafe_snow_config_acd_resume(); - } #endif if (sm_ops->nosig(devp->frontend)) { nosig = true; diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h index b3009111cc5b..92fdd32d3013 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_sm.h @@ -49,6 +49,9 @@ struct tvin_sm_s { int atv_stable_out_cnt; int hdmi_unstable_out_cnt; }; + +extern bool manual_flag; + void tvin_smr(struct vdin_dev_s *pdev); void tvin_smr_init(int index); void reset_tvin_smr(unsigned int index); diff --git a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c index afd3446df7f0..886ec3510adc 100644 --- a/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c +++ b/drivers/amlogic/media/vin/tvin/vdin/vdin_vf.c @@ -1018,9 +1018,11 @@ void vdin_vf_disp_mode_update(struct vf_entry *vfe, struct vf_pool *p) p->disp_index[0] = 0; vfe->vf.index_disp = p->disp_index[0]; - p->disp_mode[p->disp_index[p->skip_vf_num]] = VFRAME_DISP_MODE_OK; - for (i = p->skip_vf_num - 1; i < VFRAME_DISP_MAX_NUM; i--) - p->disp_mode[p->disp_index[i]] = VFRAME_DISP_MODE_UNKNOWN; + if (p->disp_mode[p->disp_index[p->skip_vf_num]] != + VFRAME_DISP_MODE_SKIP) + p->disp_mode[p->disp_index[p->skip_vf_num]] = + VFRAME_DISP_MODE_OK; + p->disp_mode[p->disp_index[0]] = VFRAME_DISP_MODE_UNKNOWN; } /*disp mode skip *skip_vf_num diff --git a/drivers/amlogic/media/vin/tvin/viu/viuin.c b/drivers/amlogic/media/vin/tvin/viu/viuin.c index 3fe16a66aaae..c79f379d7657 100644 --- a/drivers/amlogic/media/vin/tvin/viu/viuin.c +++ b/drivers/amlogic/media/vin/tvin/viu/viuin.c @@ -165,6 +165,9 @@ void viuin_check_venc_line(struct viuin_s *devp_local) pr_info("**************%s,vencv_line_cur:%d,cnt:%d***********\n", __func__, vencv_line_cur, cnt); } + +/*g12a/g12b and before: use viu_loop encl/encp*/ +/*tl1: use viu_loop vpp */ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) { struct viuin_s *devp = container_of(fe, struct viuin_s, frontend); @@ -178,8 +181,9 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) /*open the venc to vdin path*/ switch (rd_bits_viu(VPU_VIU_VENC_MUX_CTRL, 0, 2)) { case 0: - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) viu_mux = 0x4; else viu_mux = 0x8; @@ -213,7 +217,7 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) wr_viu(VPU_VIU2VDIN_HDN_CTRL, 0x40f00); } else wr_bits_viu(VPU_VIU2VDIN_HDN_CTRL, devp->parm.h_active, 0, 14); - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || is_meson_tl1_cpu()) { + if (cpu_after_eq(MESON_CPU_MAJOR_ID_G12A)) { if (((port >= TVIN_PORT_VIU1_WB0_VD1) && (port <= TVIN_PORT_VIU1_WB0_POST_BLEND)) || ((port >= TVIN_PORT_VIU2_WB0_VD1) && @@ -256,8 +260,14 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) else if ((port == TVIN_PORT_VIU1_WB0_POST_BLEND) || (port == TVIN_PORT_VIU2_WB0_POST_BLEND)) wr_bits_viu(VPP_WRBAK_CTRL, 5, 0, 3); - else + else if ((port == TVIN_PORT_VIU1_WB0_VPP) || + (port == TVIN_PORT_VIU2_WB0_VPP)) { + wr_bits_viu(VPP_WRBAK_CTRL, 6, 0, 3); + /*increase h banking in case vdin afifo overflow*/ + wr_bits_viu(VPP_WRBAK_CTRL, 0xff, 16, 8); + } else wr_bits_viu(VPP_WRBAK_CTRL, 0, 4, 3); + if ((port == TVIN_PORT_VIU1_WB1_VD1) || (port == TVIN_PORT_VIU2_WB1_VD1)) wr_bits_viu(VPP_WRBAK_CTRL, 1, 4, 3); @@ -273,8 +283,12 @@ static int viuin_open(struct tvin_frontend_s *fe, enum tvin_port_e port) else if ((port == TVIN_PORT_VIU1_WB1_POST_BLEND) || (port == TVIN_PORT_VIU2_WB1_POST_BLEND)) wr_bits_viu(VPP_WRBAK_CTRL, 5, 4, 3); + else if ((port == TVIN_PORT_VIU1_WB1_VPP) || + (port == TVIN_PORT_VIU2_WB1_VPP)) + wr_bits_viu(VPP_WRBAK_CTRL, 6, 4, 3); else wr_bits_viu(VPP_WRBAK_CTRL, 0, 4, 3); + /*wrback hsync en*/ if (((port >= TVIN_PORT_VIU1_WB0_VD1) && (port <= TVIN_PORT_VIU1_WB0_POST_BLEND)) || @@ -308,8 +322,9 @@ static void viuin_close(struct tvin_frontend_s *fe) if (open_cnt) open_cnt--; if (open_cnt == 0) { - if (is_meson_g12a_cpu() || is_meson_g12b_cpu() - || is_meson_tl1_cpu()) { + if (is_meson_g12a_cpu() || is_meson_g12b_cpu() || + is_meson_tl1_cpu() || is_meson_sm1_cpu() || + is_meson_tm2_cpu()) { wr_viu(VPU_VIU_VDIN_IF_MUX_CTRL, 0); wr_viu(VPP_WRBAK_CTRL, 0); @@ -384,14 +399,27 @@ static void viuin_sig_property(struct tvin_frontend_s *fe, static const struct vinfo_s *vinfo; struct viuin_s *devp = container_of(fe, struct viuin_s, frontend); - if (devp->parm.port == TVIN_PORT_VIU1_VIDEO) + switch (devp->parm.port) { + case TVIN_PORT_VIU1_VIDEO: + case TVIN_PORT_VIU1_WB0_POST_BLEND: prop->color_format = TVIN_YUV444; - else if ((devp->parm.port == TVIN_PORT_VIU1) || - (devp->parm.port == TVIN_PORT_VIU2)) { + break; + + case TVIN_PORT_VIU1: + case TVIN_PORT_VIU2: + case TVIN_PORT_VIU1_WB0_VPP: + case TVIN_PORT_VIU1_WB1_VPP: + case TVIN_PORT_VIU2_WB0_VPP: + case TVIN_PORT_VIU2_WB1_VPP: vinfo = get_current_vinfo(); prop->color_format = vinfo->viu_color_fmt; - } else + break; + + default: prop->color_format = devp->parm.cfmt; + break; + } + prop->dest_cfmt = devp->parm.dfmt; prop->scaling4w = devp->parm.dest_hactive; diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.c b/drivers/amlogic/media/vout/cvbs/cvbs_out.c index 9d0c1180b398..23c14545bfd9 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.c +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.c @@ -1479,6 +1479,12 @@ struct meson_cvbsout_data meson_sm1_cvbsout_data = { .name = "meson-sm1-cvbsout", }; +struct meson_cvbsout_data meson_tm2_cvbsout_data = { + .cntl0_val = 0x906001, + .cpu_id = CVBS_CPU_TYPE_TM2, + .name = "meson-tm2-cvbsout", +}; + static const struct of_device_id meson_cvbsout_dt_match[] = { { .compatible = "amlogic, cvbsout-gxl", @@ -1501,6 +1507,9 @@ static const struct of_device_id meson_cvbsout_dt_match[] = { }, { .compatible = "amlogic, cvbsout-sm1", .data = &meson_sm1_cvbsout_data, + }, { + .compatible = "amlogic, cvbsout-tm2", + .data = &meson_tm2_cvbsout_data, }, {}, }; diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out.h b/drivers/amlogic/media/vout/cvbs/cvbs_out.h index 05f6961225e4..3016b70921d4 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out.h +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out.h @@ -53,6 +53,7 @@ enum cvbs_cpu_type { CVBS_CPU_TYPE_G12B = 5, CVBS_CPU_TYPE_TL1 = 6, CVBS_CPU_TYPE_SM1 = 7, + CVBS_CPU_TYPE_TM2 = 8, }; struct meson_cvbsout_data { diff --git a/drivers/amlogic/media/vout/cvbs/cvbs_out_reg.h b/drivers/amlogic/media/vout/cvbs/cvbs_out_reg.h index be66ef438f37..268d7dcaaeaf 100644 --- a/drivers/amlogic/media/vout/cvbs/cvbs_out_reg.h +++ b/drivers/amlogic/media/vout/cvbs/cvbs_out_reg.h @@ -126,6 +126,13 @@ /*G12A*/ #define HHI_HDMI_PLL_CNTL7 0xce +/* TL1 */ +#define HHI_TCON_PLL_CNTL0 0x020 +#define HHI_TCON_PLL_CNTL1 0x021 +#define HHI_TCON_PLL_CNTL2 0x022 +#define HHI_TCON_PLL_CNTL3 0x023 +#define HHI_TCON_PLL_CNTL4 0x0df + #define HHI_GP0_PLL_CNTL0 0x10 #define HHI_GP0_PLL_CNTL1 0x11 #define HHI_GP0_PLL_CNTL2 0x12 diff --git a/drivers/amlogic/media/vout/cvbs/enc_clk_config.c b/drivers/amlogic/media/vout/cvbs/enc_clk_config.c index 379e19b2a850..1f1a029689ce 100644 --- a/drivers/amlogic/media/vout/cvbs/enc_clk_config.c +++ b/drivers/amlogic/media/vout/cvbs/enc_clk_config.c @@ -214,6 +214,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) { + 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 { pr_info("config eqafter gxl hdmi pll\n"); cvbs_out_hiu_write(HHI_HDMI_PLL_CNTL, 0x4000027b); @@ -236,6 +258,12 @@ void set_vmode_clk(void) cvbs_set_vid1_clk(cvbs_clk_path & 0x1); else cvbs_set_vid2_clk(cvbs_clk_path & 0x1); + } else if (cvbs_cpu_type() == CVBS_CPU_TYPE_TL1 || + cvbs_cpu_type() == CVBS_CPU_TYPE_TM2) { + if (cvbs_clk_path & 0x2) + cvbs_set_vid1_clk(0); + else + cvbs_set_vid2_clk(0); } else { cvbs_set_vid2_clk(0); } diff --git a/drivers/amlogic/media/vout/vdac/vdac_dev.c b/drivers/amlogic/media/vout/vdac/vdac_dev.c index 361e7deefb34..7e925f41a908 100644 --- a/drivers/amlogic/media/vout/vdac/vdac_dev.c +++ b/drivers/amlogic/media/vout/vdac/vdac_dev.c @@ -443,14 +443,16 @@ void vdac_enable(bool on, unsigned int module_sel) 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) { + 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); } } else { ana_ref_cntl0_bit9(0, VDAC_MODULE_TVAFE); - if (s_vdac_data->cpu_id == VDAC_CPU_TL1) { + 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); @@ -594,6 +596,11 @@ struct meson_vdac_data meson_sm1_vdac_data = { .name = "meson-sm1-vdac", }; +struct meson_vdac_data meson_tm2_vdac_data = { + .cpu_id = VDAC_CPU_TM2, + .name = "meson-tm2-vdac", +}; + static const struct of_device_id meson_vdac_dt_match[] = { { .compatible = "amlogic, vdac-gxtvbb", @@ -628,6 +635,9 @@ static const struct of_device_id meson_vdac_dt_match[] = { }, { .compatible = "amlogic, vdac-sm1", .data = &meson_sm1_vdac_data, + }, { + .compatible = "amlogic, vdac-tm2", + .data = &meson_tm2_vdac_data, }, {}, }; @@ -712,12 +722,19 @@ 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); + 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); pr_info("%s: suspend module\n", __func__); return 0; } 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); pr_info("%s: resume module\n", __func__); return 0; } diff --git a/include/linux/amlogic/media/amvecm/amvecm.h b/include/linux/amlogic/media/amvecm/amvecm.h index 59e88fe6c5e2..50b0f95921f3 100644 --- a/include/linux/amlogic/media/amvecm/amvecm.h +++ b/include/linux/amlogic/media/amvecm/amvecm.h @@ -292,6 +292,29 @@ enum ve_pq_timing_e { TIMING_MAX, }; +enum vlock_hw_ver_e { + /*gxtvbb*/ + vlock_hw_org, + /* + *txl + *txlx + */ + vlock_hw_ver1, + /* tl1 later + * fix bug:i problem + * fix bug:affect ss function + * add: phase lock + */ + vlock_hw_ver2, +}; + +struct vecm_match_data_s { + u32 vlk_support; + u32 vlk_new_fsm; + enum vlock_hw_ver_e vlk_hwver; + u32 vlk_phlock_en; +}; + /*overscan: *length 0~31bit :number of crop; *src_timing: bit31: on: load/save all crop diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin.h b/include/linux/amlogic/media/frame_provider/tvin/tvin.h index 181796ff88e2..508585acd746 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin.h @@ -64,11 +64,13 @@ enum tvin_port_e { TVIN_PORT_VIU1_WB0_VD2, TVIN_PORT_VIU1_WB0_OSD1, TVIN_PORT_VIU1_WB0_OSD2, + TVIN_PORT_VIU1_WB0_VPP, TVIN_PORT_VIU1_WB0_POST_BLEND, TVIN_PORT_VIU1_WB1_VD1, TVIN_PORT_VIU1_WB1_VD2, TVIN_PORT_VIU1_WB1_OSD1, TVIN_PORT_VIU1_WB1_OSD2, + TVIN_PORT_VIU1_WB1_VPP, TVIN_PORT_VIU1_WB1_POST_BLEND, TVIN_PORT_VIU2 = 0x0000C000, TVIN_PORT_VIU2_VIDEO, @@ -76,11 +78,13 @@ enum tvin_port_e { TVIN_PORT_VIU2_WB0_VD2, TVIN_PORT_VIU2_WB0_OSD1, TVIN_PORT_VIU2_WB0_OSD2, + TVIN_PORT_VIU2_WB0_VPP, TVIN_PORT_VIU2_WB0_POST_BLEND, TVIN_PORT_VIU2_WB1_VD1, TVIN_PORT_VIU2_WB1_VD2, TVIN_PORT_VIU2_WB1_OSD1, TVIN_PORT_VIU2_WB1_OSD2, + TVIN_PORT_VIU2_WB1_VPP, TVIN_PORT_VIU2_WB1_POST_BLEND, TVIN_PORT_MIPI = 0x00010000, TVIN_PORT_ISP = 0x00020000, @@ -312,6 +316,15 @@ struct tvin_info_s { unsigned int is_dvi; }; +struct tvin_frontend_info_s { + enum tvin_scan_mode_e scan_mode; + enum tvin_color_fmt_e cfmt; + unsigned int fps; + unsigned int width; + unsigned int height; + unsigned int colordepth; +}; + struct tvin_buf_info_s { unsigned int vf_size; unsigned int buf_count; @@ -432,7 +445,13 @@ struct tvafe_pin_mux_s { enum tvin_force_color_range_e) #define TVIN_IOC_GAME_MODE _IOW(_TM_T, 0x4b, unsigned int) #define TVIN_IOC_SET_AUTO_RATIO_EN _IOW(_TM_T, 0x4c, unsigned int) - +#define TVIN_IOC_GET_LATENCY_MODE _IOR(_TM_T, 0x4d,\ + struct tvin_latency_s) +#define TVIN_IOC_G_FRONTEND_INFO _IOR(_TM_T, 0x4e,\ + struct tvin_frontend_info_s) +#define TVIN_IOC_S_CANVAS_ADDR _IOW(_TM_T, 0x4f,\ + struct vdin_set_canvas_s) +#define TVIN_IOC_S_CANVAS_RECOVERY _IO(_TM_T, 0x0a) /* TVAFE */ #define TVIN_IOC_S_AFE_VGA_PARM _IOW(_TM_T, 0x16, struct tvafe_vga_parm_s) #define TVIN_IOC_G_AFE_VGA_PARM _IOR(_TM_T, 0x17, struct tvafe_vga_parm_s) @@ -444,6 +463,10 @@ struct tvafe_pin_mux_s { #define TVIN_IOC_LOAD_REG _IOW(_TM_T, 0x20, struct am_regs_s) #define TVIN_IOC_S_AFE_SONWON _IO(_TM_T, 0x22) #define TVIN_IOC_S_AFE_SONWOFF _IO(_TM_T, 0x23) +#define TVIN_IOC_G_VDIN_HIST _IOW(_TM_T, 0x24, struct vdin_hist_s) +#define TVIN_IOC_S_VDIN_V4L2START _IOW(_TM_T, 0x25, struct vdin_v4l2_param_s) +#define TVIN_IOC_S_VDIN_V4L2STOP _IO(_TM_T, 0x26) +#define TVIN_IOC_S_AFE_SONWCFG _IOW(_TM_T, 0x27, unsigned int) /* *function defined applied for other driver diff --git a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h index 493bc9a22051..b1233faf5e3d 100644 --- a/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h +++ b/include/linux/amlogic/media/frame_provider/tvin/tvin_v4l2.h @@ -742,6 +742,10 @@ enum cam_interface_e { CAM_MIPI, }; +#define PARAM_STATE_NULL 0x00000000 +#define PARAM_STATE_HISTGRAM 0x00000001 +#define PARAM_STATE_SCREENCAP 0x00000002 + /* *********************************************************************** */ /* *** IOCTL command definitions ***************************************** */ @@ -813,6 +817,7 @@ struct vdin_parm_s { unsigned short skip_count; /* for skip frame */ struct csi_parm_s csi_hw_info; + /*for reserved */ uintptr_t reserved; }; diff --git a/include/linux/amlogic/media/vfm/vframe.h b/include/linux/amlogic/media/vfm/vframe.h index 7cc60caa1138..dd7c8821486a 100644 --- a/include/linux/amlogic/media/vfm/vframe.h +++ b/include/linux/amlogic/media/vfm/vframe.h @@ -44,8 +44,11 @@ #define VIDTYPE_COMPRESS 0x100000 #define VIDTYPE_PIC 0x200000 #define VIDTYPE_SCATTER 0x400000 -#define VIDTYPE_VD2 0x800000 +#define VIDTYPE_VD2 0x800000 #define VIDTYPE_COMPRESS_LOSS 0x1000000 +#define VIDTYPE_COMB_MODE 0x2000000 +#define VIDTYPE_NO_DW 0x4000000 +#define VIDTYPE_SUPPORT_COMPRESS 0x8000000 #define DISP_RATIO_FORCECONFIG 0x80000000 #define DISP_RATIO_FORCE_NORMALWIDE 0x40000000 diff --git a/include/linux/amlogic/media/vfm/vframe_provider.h b/include/linux/amlogic/media/vfm/vframe_provider.h index 014f16373fcc..f67776e4085a 100644 --- a/include/linux/amlogic/media/vfm/vframe_provider.h +++ b/include/linux/amlogic/media/vfm/vframe_provider.h @@ -40,6 +40,7 @@ struct vframe_states { #define VFRAME_EVENT_RECEIVER_GET_AUX_DATA 0x80 #define VFRAME_EVENT_RECEIVER_DISP_MODE 0x100 #define VFRAME_EVENT_RECEIVER_DOLBY_BYPASS_EL 0x200 +#define VFRAME_EVENT_RECEIVER_NEED_NO_COMP 0x400 /* for VFRAME_EVENT_RECEIVER_GET_AUX_DATA*/ struct provider_aux_req_s { diff --git a/include/linux/amlogic/media/vout/vdac_dev.h b/include/linux/amlogic/media/vout/vdac_dev.h index 90e409653c5d..fe9cb85db601 100644 --- a/include/linux/amlogic/media/vout/vdac_dev.h +++ b/include/linux/amlogic/media/vout/vdac_dev.h @@ -28,6 +28,7 @@ enum vdac_cpu_type { VDAC_CPU_G12AB = 6, VDAC_CPU_TL1 = 7, VDAC_CPU_SM1 = 8, + VDAC_CPU_TM2 = 9, VDAC_CPU_MAX, };