/* * Allwinner SoCs tv driver. * * Copyright (C) 2016 Allwinner. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ #include "drv_tv.h" #include "de_tvec.h" #include static void __iomem *tve_reg_base[TVE_DEVICE_NUM]; static void __iomem *sid_reg_base; static s32 tve_low_dac_auto_cali(u32 sel, u32 *cali); s32 tve_low_set_reg_base(u32 sel, void __iomem *address) { if (sel < TVE_DEVICE_NUM) tve_reg_base[sel] = address; return 0; } s32 tve_low_set_top_reg_base(void __iomem *address) { return 0; } s32 tve_low_set_sid_base(void __iomem *address) { sid_reg_base = address; return 0; } s32 tve_low_init(u32 sel, u32 *dac_no, u32 *cali, s32 *offset, u32 *dac_type, u32 num) { s32 val = (*cali) ? (*cali) : 0x285; val += *offset; TVE_WUINT32(sel, TVE_304, val << 16); TVE_WUINT32(sel, TVE_30C, 0x00101110); TVE_WUINT32(sel, TVE_008, 0x433e12b1); TVE_WUINT32(sel, TVE_000, 0x80000000); return 0; } s32 tve_low_exit(u32 sel) { return 0; } s32 tve_low_dac_enable(u32 sel) { TVE_SET_BIT(sel, TVE_008, 0x1 << 0); return 0; } s32 tve_low_dac_disable(u32 sel) { TVE_CLR_BIT(sel, TVE_008, 0x1 << 0); return 0; } s32 tve_low_open(u32 sel) { TVE_CLR_BIT(sel, TVE_000, 0x1 << 31); TVE_SET_BIT(sel, TVE_000, 0x1 << 0); return 0; } s32 tve_low_close(u32 sel) { TVE_CLR_BIT(sel, TVE_000, 0x1 << 0); TVE_SET_BIT(sel, TVE_000, 0x1 << 31); return 0; } s32 tve_low_set_tv_mode(u32 sel, enum disp_tv_mode mode, u32 *cali) { tve_low_dac_auto_cali(sel, cali); if (mode == DISP_TV_MOD_NTSC) { TVE_WUINT32(sel, TVE_000, 0x00000300); TVE_WUINT32(sel, TVE_004, 0x07070000); TVE_WUINT32(sel, TVE_00C, 0x30001400); TVE_WUINT32(sel, TVE_010, 0x21F07C1F); TVE_WUINT32(sel, TVE_014, 0x00760020); TVE_WUINT32(sel, TVE_018, 0x00000016); TVE_WUINT32(sel, TVE_01C, 0x0016020D); TVE_WUINT32(sel, TVE_020, 0x00F0011A); TVE_WUINT32(sel, TVE_100, 0x00000001); TVE_WUINT32(sel, TVE_104, 0x00000000); TVE_WUINT32(sel, TVE_108, 0x00000002); TVE_WUINT32(sel, TVE_10C, 0x0000004F); TVE_WUINT32(sel, TVE_110, 0x00000000); TVE_WUINT32(sel, TVE_114, 0x0016447E); TVE_WUINT32(sel, TVE_118, 0x0000A0A0); TVE_WUINT32(sel, TVE_11C, 0x001000F0); TVE_WUINT32(sel, TVE_120, 0x01E80320); TVE_WUINT32(sel, TVE_124, 0x000005A0); TVE_WUINT32(sel, TVE_128, 0x00010000); TVE_WUINT32(sel, TVE_12C, 0x00000101); TVE_WUINT32(sel, TVE_130, 0x20050368); TVE_WUINT32(sel, TVE_134, 0x00000000); TVE_WUINT32(sel, TVE_138, 0x00000000); TVE_WUINT32(sel, TVE_13C, 0x00000000); } else { TVE_WUINT32(sel, TVE_000, 0x00000300); TVE_WUINT32(sel, TVE_004, 0x07070001); TVE_WUINT32(sel, TVE_00C, 0x30001400); TVE_WUINT32(sel, TVE_010, 0x2A098ACB); TVE_WUINT32(sel, TVE_014, 0x008A0018); TVE_WUINT32(sel, TVE_018, 0x00000016); TVE_WUINT32(sel, TVE_01C, 0x00160271); TVE_WUINT32(sel, TVE_020, 0x00FC00FC); TVE_WUINT32(sel, TVE_100, 0x00000000); TVE_WUINT32(sel, TVE_104, 0x00000001); TVE_WUINT32(sel, TVE_108, 0x00000005); TVE_WUINT32(sel, TVE_10C, 0x00002929); TVE_WUINT32(sel, TVE_110, 0x00000000); TVE_WUINT32(sel, TVE_114, 0x0016447E); TVE_WUINT32(sel, TVE_118, 0x0000A8A8); TVE_WUINT32(sel, TVE_11C, 0x001000FC); TVE_WUINT32(sel, TVE_120, 0x01E80320); TVE_WUINT32(sel, TVE_124, 0x000005A0); TVE_WUINT32(sel, TVE_128, 0x00010000); TVE_WUINT32(sel, TVE_12C, 0x00000101); TVE_WUINT32(sel, TVE_130, 0x2005000A); TVE_WUINT32(sel, TVE_134, 0x00000000); TVE_WUINT32(sel, TVE_138, 0x00000000); TVE_WUINT32(sel, TVE_13C, 0x00000000); TVE_WUINT32(sel, TVE_3A0, 0x00030001); } return 0; } /* 0:unconnected; 1:connected; 3:short to ground */ s32 tve_low_get_dac_status(u32 sel) { u32 readval; readval = TVE_RUINT32(sel, TVE_038); return readval & 0x3; } s32 tve_low_dac_autocheck_enable(u32 sel) { TVE_WUINT32(sel, TVE_0F8, 0x00000280); /* 20ms x 10 */ TVE_WUINT32(sel, TVE_0FC, 0x028F00FF); /* 1.0v refer for 0.71v/1.43v detect */ TVE_WUINT32(sel, TVE_03C, 0x00000009); /* detect enable */ TVE_WUINT32(sel, TVE_030, 0x00000001); return 0; } s32 tve_low_dac_autocheck_disable(u32 sel) { TVE_WUINT32(sel, TVE_030, 0x0); TVE_WUINT32(sel, TVE_0F8, 0x0); return 0; } static s32 tve_low_dac_auto_cali(u32 sel, u32 *cali) { u32 dac_err_reg[10]; s32 dac_err_val[10]; u32 cali_err_1[10]; u32 cali_err_2[10]; s32 dac_err_auto; s32 dac_err_efuse; s32 dac_err_opti; u32 dac_err_set; u32 i; TVE_WUINT32(sel, TVE_000, 0x80000300); /* tvclk enable */ TVE_WUINT32(sel, TVE_030, 0x00000000); /* auto detect disable */ TVE_WUINT32(sel, TVE_008, 0x433e12b1); /* dac setting */ TVE_WUINT32(sel, TVE_304, *cali << 16 | 0xc << 8); TVE_SET_BIT(sel, TVE_300, 0x1); /* force DAC for cali */ for (i = 0; i < 3; i++) { TVE_SET_BIT(sel, TVE_304, 0x1 << 4); mdelay(1); TVE_SET_BIT(sel, TVE_304, 0x1 << 0); mdelay(1); dac_err_reg[i] = (TVE_RUINT32(sel, TVE_308) >> 16) & 0x3ff; TVE_CLR_BIT(sel, TVE_304, 0x1 << 0); TVE_CLR_BIT(sel, TVE_304, 0x1 << 4); mdelay(1); if (dac_err_reg[i] & (1 << 9)) dac_err_val[i] = 0 + (dac_err_reg[i] & 0x1ff); else dac_err_val[i] = 0 - (dac_err_reg[i] & 0x1ff); } cali_err_1[0] = abs(dac_err_val[1] - dac_err_val[0]); cali_err_1[1] = abs(dac_err_val[2] - dac_err_val[1]); cali_err_1[2] = abs(dac_err_val[0] - dac_err_val[2]); cali_err_2[0] = cali_err_1[2] + cali_err_1[0]; cali_err_2[1] = cali_err_1[0] + cali_err_1[1]; cali_err_2[2] = cali_err_1[1] + cali_err_1[2]; if (cali_err_2[0] < cali_err_2[1] && cali_err_2[0] < cali_err_2[2]) dac_err_auto = dac_err_val[0]; else if (cali_err_2[1] < cali_err_2[0] && cali_err_2[1] < cali_err_2[2]) dac_err_auto = dac_err_val[1]; else dac_err_auto = dac_err_val[2]; if (*cali & (1 << 9)) dac_err_efuse = 0 + (*cali & 0x1ff); else dac_err_efuse = 0 - (*cali & 0x1ff); if (abs(dac_err_auto - dac_err_efuse) < 100) dac_err_opti = dac_err_auto; else dac_err_opti = dac_err_efuse; if (dac_err_opti >= 0) dac_err_set = (1 << 9) | dac_err_opti; else dac_err_set = 0 - dac_err_opti; TVE_WUINT32(sel, TVE_304, dac_err_set << 16 | 0xc << 8); TVE_CLR_BIT(sel, TVE_300, 0x1); TVE_WUINT32(sel, TVE_030, 0x1); /* enable plug detect */ return 0; } s32 tve_low_enhance(u32 sel, u32 mode) { if (mode == 0) { TVE_CLR_BIT(sel, TVE_000, 0xf << 10); /* deflick off */ TVE_SET_BIT(sel, TVE_000, 0x5 << 10); /* deflick is 5 */ TVE_SET_BIT(sel, TVE_00C, 0x1 << 31); /* lti on */ TVE_SET_BIT(sel, TVE_00C, 0x1 << 16); /* notch off */ } else if (mode == 1) { TVE_CLR_BIT(sel, TVE_000, 0xf << 10); /* deflick off */ TVE_SET_BIT(sel, TVE_000, 0x5 << 10); /* deflick is 5 */ TVE_SET_BIT(sel, TVE_00C, 0x1 << 31); /* lti on */ TVE_CLR_BIT(sel, TVE_00C, 0x1 << 16); /* notch on */ } else if (mode == 2) { TVE_CLR_BIT(sel, TVE_000, 0xf << 10); /* deflick off */ TVE_CLR_BIT(sel, TVE_00C, 0x1 << 31); /* lti off */ TVE_SET_BIT(sel, TVE_00C, 0x1 << 16); /* notch off */ } return 0; } u32 tve_low_get_sid(u32 index) { u32 cali_value = 0; /* Share register with OEM */ if (sunxi_efuse_read(EFUSE_OEM_NAME, &cali_value)) pr_err("get TV%d efuse fail!\n", index); else return cali_value; return 0; }