| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| */ |
| |
| #include <linux/version.h> |
| #include <linux/module.h> |
| #include <linux/types.h> |
| #include <linux/kernel.h> |
| #include <linux/kthread.h> |
| #include <linux/delay.h> |
| #include <linux/interrupt.h> |
| #include <linux/spinlock.h> |
| #include <linux/fs.h> |
| #include <linux/init.h> |
| #include <linux/device.h> |
| #include <linux/mm.h> |
| #include <linux/major.h> |
| #include <linux/platform_device.h> |
| #include <linux/mutex.h> |
| #include <linux/cdev.h> |
| #include <linux/uaccess.h> |
| #include <linux/delay.h> |
| #include <linux/io.h> |
| #include <linux/amlogic/media/frame_provider/tvin/tvin.h> |
| #include <linux/amlogic/media/vout/vdac_dev.h> |
| #include <linux/arm-smccc.h> |
| #include <linux/slab.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/highmem.h> |
| #include <linux/amlogic/clk_measure.h> |
| |
| /* Local include */ |
| #include "hdmi_rx_eq.h" |
| #include "hdmi_rx_repeater.h" |
| #include "hdmi_rx_drv.h" |
| #include "hdmi_rx_hw.h" |
| #include "hdmi_rx_edid.h" |
| #include "hdmi_rx_wrapper.h" |
| #include "hdmi_rx_pktinfo.h" |
| |
| /*------------------------marco define------------------------------*/ |
| #define SCRAMBLE_SEL 1 |
| #define HYST_HDMI_TO_DVI 5 |
| /* must = 0, other agilent source fail */ |
| #define HYST_DVI_TO_HDMI 0 |
| #define GCP_GLOBAVMUTE_EN 1 /* ag506 must clear this bit */ |
| #define EDID_CLK_DIV 9 /* sys clk/(9+1) = 20M */ |
| #define HDCP_KEY_WR_TRIES (5) |
| |
| /*------------------------variable define------------------------------*/ |
| static DEFINE_SPINLOCK(reg_rw_lock); |
| /* should enable fast switching, since some devices in non-current port */ |
| /* will suspend because of RxSense = 0, such as xiaomi-mtk box */ |
| static bool phy_fast_switching; |
| static bool phy_fsm_enhancement = true; |
| /*unsigned int last_clk_rate;*/ |
| static u32 modet_clk = 24000; |
| int hdcp_enc_mode; |
| /* top_irq_en bit[16:13] hdcp_sts */ |
| /* bit27 DE rise */ |
| int top_intr_maskn_value; |
| u32 afifo_overflow_cnt; |
| u32 afifo_underflow_cnt; |
| int rx_afifo_dbg_en; |
| bool hdcp_enable = 1; |
| int acr_mode; |
| int auto_aclk_mute = 2; |
| int aud_avmute_en = 1; |
| int aud_mute_sel = 2; |
| int force_clk_rate; |
| u32 rx_ecc_err_thres = 100; |
| u32 rx_ecc_err_frames = 50; |
| int md_ists_en = VIDEO_MODE; |
| int pdec_ists_en;/* = AVI_CKS_CHG | DVIDET | DRM_CKS_CHG | DRM_RCV_EN;*/ |
| u32 packet_fifo_cfg; |
| int pd_fifo_start_cnt = 0x8; |
| /* Controls equalizer reference voltage. */ |
| int hdcp22_on; |
| MODULE_PARM_DESC(hdcp22_on, "\n hdcp22_on\n"); |
| module_param(hdcp22_on, int, 0664); |
| |
| MODULE_PARM_DESC(force_clk_rate, "\n force_clk_rate\n"); |
| module_param(force_clk_rate, int, 0664); |
| |
| /* test for HBR CTS, audio module can set it to force 8ch */ |
| int hbr_force_8ch; |
| /* |
| * hdcp14_key_mode:hdcp1.4 key handle method select |
| * NORMAL_MODE:systemcontrol path |
| * SECURE_MODE:secure OS path |
| */ |
| int hdcp14_key_mode = NORMAL_MODE; |
| int aud_ch_map; |
| int ignore_sscp_charerr = 1; |
| int ignore_sscp_tmds = 1; |
| int find_best_eq; |
| int eq_try_cnt = 20; |
| int pll_rst_max = 5; |
| /* cdr lock threshold */ |
| int cdr_lock_level; |
| u32 term_cal_val; |
| bool term_cal_en; |
| int clock_lock_th = 2; |
| int scdc_force_en = 1; |
| /* for hdcp_hpd debug, disable by default */ |
| u32 hdcp_hpd_ctrl_en; |
| int eq_dbg_lvl; |
| u32 phy_trim_val; |
| /* bit'4: tdr enable |
| * bit [3:0]: tdr level control |
| */ |
| int phy_term_lel; |
| bool phy_tdr_en; |
| int hdcp_tee_path; |
| |
| /* emp buffer */ |
| char emp_buf[1024]; |
| int i2c_err_cnt; |
| |
| /*------------------------variable define end------------------------------*/ |
| |
| static int check_regmap_flag(unsigned int addr) |
| { |
| return 1; |
| } |
| |
| /* |
| * hdmirx_rd_dwc - Read data from HDMI RX CTRL |
| * @addr: register address |
| * |
| * return data read value |
| */ |
| unsigned int hdmirx_rd_dwc(unsigned int addr) |
| { |
| ulong flags; |
| int data; |
| unsigned long dev_offset = 0x10; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| spin_lock_irqsave(®_rw_lock, flags); |
| data = rd_reg(MAP_ADDR_MODULE_TOP, |
| addr + rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } else { |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_addr_port | dev_offset, addr); |
| data = rd_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_data_port | dev_offset); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| return data; |
| } |
| |
| /* |
| * hdmirx_rd_bits_dwc - read specfied bits of HDMI RX CTRL reg |
| * @addr: register address |
| * @mask: bits mask |
| * |
| * return masked bits of register value |
| */ |
| unsigned int hdmirx_rd_bits_dwc(unsigned int addr, unsigned int mask) |
| { |
| return rx_get_bits(hdmirx_rd_dwc(addr), mask); |
| } |
| |
| /* |
| * hdmirx_wr_dwc - Write data to HDMI RX CTRL |
| * @addr: register address |
| * @data: new register value |
| */ |
| void hdmirx_wr_dwc(unsigned int addr, unsigned int data) |
| { |
| ulong flags; |
| unsigned int dev_offset = 0x10; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| addr + rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr, data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } else { |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_addr_port | dev_offset, addr); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_data_port | dev_offset, data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| } |
| |
| /* |
| * hdmirx_wr_bits_dwc - write specfied bits of HDMI RX CTRL reg |
| * @addr: register address |
| * @mask: bits mask |
| * @value: new register value |
| */ |
| void hdmirx_wr_bits_dwc(unsigned int addr, |
| unsigned int mask, |
| unsigned int value) |
| { |
| hdmirx_wr_dwc(addr, rx_set_bits(hdmirx_rd_dwc(addr), mask, value)); |
| } |
| |
| /* |
| * hdmirx_rd_phy - Read data from HDMI RX phy |
| * @addr: register address |
| * |
| * return data read value |
| */ |
| unsigned int hdmirx_rd_phy(unsigned int reg_address) |
| { |
| int cnt = 0; |
| |
| /* hdmirx_wr_dwc(DWC_I2CM_PHYG3_SLAVE, 0x39); */ |
| hdmirx_wr_dwc(DWC_I2CM_PHYG3_ADDRESS, reg_address); |
| hdmirx_wr_dwc(DWC_I2CM_PHYG3_OPERATION, 0x02); |
| do { |
| if ((cnt % 10) == 0) { |
| /* wait i2cmpdone */ |
| if (hdmirx_rd_dwc(DWC_HDMI_ISTS) & (1 << 28)) { |
| hdmirx_wr_dwc(DWC_HDMI_ICLR, 1 << 28); |
| break; |
| } |
| } |
| cnt++; |
| if (cnt > 50000) { |
| rx_pr("[HDMIRX err]: %s(%x,%x) timeout\n", |
| __func__, 0x39, reg_address); |
| break; |
| } |
| } while (1); |
| |
| return (unsigned int)(hdmirx_rd_dwc(DWC_I2CM_PHYG3_DATAI)); |
| } |
| |
| /* |
| * hdmirx_rd_bits_phy - read specfied bits of HDMI RX phy reg |
| * @addr: register address |
| * @mask: bits mask |
| * |
| * return masked bits of register value |
| */ |
| unsigned int hdmirx_rd_bits_phy(unsigned int addr, unsigned int mask) |
| { |
| return rx_get_bits(hdmirx_rd_phy(addr), mask); |
| } |
| |
| /* |
| * hdmirx_wr_phy - Write data to HDMI RX phy |
| * @addr: register address |
| * @data: new register value |
| * |
| * return 0 on write succeed, return -1 otherwise. |
| */ |
| unsigned int hdmirx_wr_phy(unsigned int reg_address, unsigned int data) |
| { |
| int error = 0; |
| int cnt = 0; |
| |
| /* hdmirx_wr_dwc(DWC_I2CM_PHYG3_SLAVE, 0x39); */ |
| hdmirx_wr_dwc(DWC_I2CM_PHYG3_ADDRESS, reg_address); |
| hdmirx_wr_dwc(DWC_I2CM_PHYG3_DATAO, data); |
| hdmirx_wr_dwc(DWC_I2CM_PHYG3_OPERATION, 0x01); |
| |
| do { |
| /* wait i2cmpdone */ |
| if ((cnt % 10) == 0) { |
| if (hdmirx_rd_dwc(DWC_HDMI_ISTS) & (1 << 28)) { |
| hdmirx_wr_dwc(DWC_HDMI_ICLR, 1 << 28); |
| break; |
| } |
| } |
| cnt++; |
| if (cnt > 50000) { |
| error = -1; |
| rx_pr("[err-%s]:(%x,%x)timeout\n", |
| __func__, reg_address, data); |
| break; |
| } |
| } while (1); |
| return error; |
| } |
| |
| /* |
| * hdmirx_wr_bits_phy - write specfied bits of HDMI RX phy reg |
| * @addr: register address |
| * @mask: bits mask |
| * @value: new register value |
| * |
| * return 0 on write succeed, return -1 otherwise. |
| */ |
| int hdmirx_wr_bits_phy(u16 addr, u32 mask, u32 value) |
| { |
| return hdmirx_wr_phy(addr, rx_set_bits(hdmirx_rd_phy(addr), |
| mask, value)); |
| } |
| |
| /* |
| * hdmirx_rd_top - read hdmirx top reg |
| * @addr: register address |
| * |
| * return data read value |
| */ |
| unsigned int hdmirx_rd_top(unsigned int addr) |
| { |
| ulong flags; |
| int data; |
| unsigned int dev_offset = 0; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| spin_lock_irqsave(®_rw_lock, flags); |
| if (rx.chip_id >= CHIP_ID_T7) |
| dev_offset = rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| else |
| dev_offset = TOP_DWC_BASE_OFFSET + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| if (addr >= TOP_EDID_ADDR_S && |
| addr <= (TOP_EDID_PORT3_ADDR_E)) { |
| data = rd_reg_b(MAP_ADDR_MODULE_TOP, |
| dev_offset + addr); |
| } else { |
| data = rd_reg(MAP_ADDR_MODULE_TOP, |
| dev_offset + (addr << 2)); |
| } |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } else { |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_addr_port | dev_offset, addr); |
| data = rd_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_data_port | dev_offset); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| return data; |
| } |
| |
| /* |
| * hdmirx_rd_bits_top - read specified bits of hdmirx top reg |
| * @addr: register address |
| * @mask: bits mask |
| * |
| * return masked bits of register value |
| */ |
| u32 hdmirx_rd_bits_top(u16 addr, u32 mask) |
| { |
| return rx_get_bits(hdmirx_rd_top(addr), mask); |
| } |
| |
| /* |
| * hdmirx_wr_top - Write data to hdmirx top reg |
| * @addr: register address |
| * @data: new register value |
| */ |
| void hdmirx_wr_top(unsigned int addr, unsigned int data) |
| { |
| ulong flags; |
| unsigned long dev_offset = 0; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| spin_lock_irqsave(®_rw_lock, flags); |
| if (rx.chip_id >= CHIP_ID_T7) |
| dev_offset = rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| else |
| dev_offset = TOP_DWC_BASE_OFFSET + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| if (addr >= TOP_EDID_ADDR_S && |
| addr <= (TOP_EDID_PORT3_ADDR_E)) { |
| wr_reg_b(MAP_ADDR_MODULE_TOP, |
| dev_offset + addr, (unsigned char)data); |
| } else { |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| dev_offset + (addr << 2), data); |
| } |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } else { |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_TOP, hdmirx_addr_port | dev_offset, addr); |
| wr_reg(MAP_ADDR_MODULE_TOP, hdmirx_data_port | dev_offset, data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| } |
| |
| /* |
| * hdmirx_wr_bits_top - write specified bits of hdmirx top reg |
| * @addr: register address |
| * @mask: bits mask |
| * @value: new register value |
| */ |
| void hdmirx_wr_bits_top(unsigned int addr, |
| unsigned int mask, |
| unsigned int value) |
| { |
| hdmirx_wr_top(addr, rx_set_bits(hdmirx_rd_top(addr), mask, value)); |
| } |
| |
| /* |
| * hdmirx_rd_amlphy - read hdmirx amlphy reg |
| * @addr: register address |
| * |
| * return data read value |
| */ |
| unsigned int hdmirx_rd_amlphy(unsigned int addr) |
| { |
| ulong flags; |
| int data; |
| unsigned int dev_offset = 0; |
| u32 base_ofst = 0; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| base_ofst = TOP_AMLPHY_BASE_OFFSET_T7; |
| else |
| base_ofst = TOP_AMLPHY_BASE_OFFSET_T5; |
| spin_lock_irqsave(®_rw_lock, flags); |
| dev_offset = base_ofst + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| data = rd_reg(MAP_ADDR_MODULE_TOP, dev_offset + addr); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| return data; |
| } |
| |
| /* |
| * hdmirx_rd_bits_amlphy - read specified bits of hdmirx amlphy reg |
| * @addr: register address |
| * @mask: bits mask |
| * |
| * return masked bits of register value |
| */ |
| u32 hdmirx_rd_bits_amlphy(u16 addr, u32 mask) |
| { |
| return rx_get_bits(hdmirx_rd_amlphy(addr), mask); |
| } |
| |
| /* |
| * hdmirx_wr_amlphy - Write data to hdmirx amlphy reg |
| * @addr: register address |
| * @data: new register value |
| */ |
| void hdmirx_wr_amlphy(unsigned int addr, unsigned int data) |
| { |
| ulong flags; |
| unsigned long dev_offset = 0; |
| u32 base_ofst = 0; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| base_ofst = TOP_AMLPHY_BASE_OFFSET_T7; |
| else |
| base_ofst = TOP_AMLPHY_BASE_OFFSET_T5; |
| spin_lock_irqsave(®_rw_lock, flags); |
| dev_offset = base_ofst + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| wr_reg(MAP_ADDR_MODULE_TOP, dev_offset + addr, data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| /* |
| * hdmirx_wr_bits_amlphy - write specified bits of hdmirx amlphy reg |
| * @addr: register address |
| * @mask: bits mask |
| * @value: new register value |
| */ |
| void hdmirx_wr_bits_amlphy(unsigned int addr, |
| unsigned int mask, |
| unsigned int value) |
| { |
| hdmirx_wr_amlphy(addr, rx_set_bits(hdmirx_rd_amlphy(addr), mask, value)); |
| } |
| |
| /* for T7 */ |
| u8 hdmirx_rd_cor(u32 addr) |
| { |
| ulong flags; |
| u8 data; |
| u32 dev_offset = 0; |
| bool need_wr_twice = false; |
| |
| /* addr bit[8:15] is 0x1d or 0x1e need write twice */ |
| need_wr_twice = ((((addr >> 8) & 0xff) == 0x1d) || |
| (((addr >> 8) & 0xff) == 0x1e)); |
| dev_offset = TOP_COR_BASE_OFFSET_T7 + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| spin_lock_irqsave(®_rw_lock, flags); |
| data = rd_reg_b(MAP_ADDR_MODULE_TOP, |
| addr + dev_offset); |
| if (need_wr_twice) |
| data = rd_reg_b(MAP_ADDR_MODULE_TOP, |
| addr + dev_offset); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| |
| return data; |
| } |
| |
| u8 hdmirx_rd_bits_cor(u32 addr, u32 mask) |
| { |
| return rx_get_bits(hdmirx_rd_cor(addr), mask); |
| } |
| |
| void hdmirx_wr_cor(u32 addr, u8 data) |
| { |
| ulong flags; |
| u32 dev_offset = 0; |
| bool need_wr_twice = false; |
| |
| /* addr bit[8:15] is 0x1d or 0x1e need write twice */ |
| need_wr_twice = ((((addr >> 8) & 0xff) == 0x1d) || |
| (((addr >> 8) & 0xff) == 0x1e)); |
| dev_offset = TOP_COR_BASE_OFFSET_T7 + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg_b(MAP_ADDR_MODULE_TOP, |
| addr + dev_offset, data); |
| if (need_wr_twice) |
| wr_reg_b(MAP_ADDR_MODULE_TOP, |
| addr + dev_offset, data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| void hdmirx_wr_bits_cor(u32 addr, u32 mask, u8 value) |
| { |
| hdmirx_wr_cor(addr, rx_set_bits(hdmirx_rd_cor(addr), mask, value)); |
| } |
| |
| unsigned int rd_reg_clk_ctl(unsigned int offset) |
| { |
| unsigned int ret; |
| unsigned long flags; |
| unsigned int addr; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| addr = offset + rx_reg_maps[MAP_ADDR_MODULE_CLK_CTRL].phy_addr; |
| ret = rd_reg(MAP_ADDR_MODULE_CLK_CTRL, addr); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| return ret; |
| } |
| |
| void wr_reg_clk_ctl(unsigned int offset, unsigned int val) |
| { |
| unsigned long flags; |
| unsigned int addr; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| addr = offset + rx_reg_maps[MAP_ADDR_MODULE_CLK_CTRL].phy_addr; |
| wr_reg(MAP_ADDR_MODULE_CLK_CTRL, addr, val); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| /* For analog modules register rd */ |
| unsigned int rd_reg_ana_ctl(unsigned int offset) |
| { |
| unsigned int ret; |
| unsigned long flags; |
| unsigned int addr; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| addr = offset + rx_reg_maps[MAP_ADDR_MODULE_ANA_CTRL].phy_addr; |
| ret = rd_reg(MAP_ADDR_MODULE_ANA_CTRL, addr); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| return ret; |
| } |
| |
| /* For analog modules register wr */ |
| void wr_reg_ana_ctl(unsigned int offset, unsigned int val) |
| { |
| unsigned long flags; |
| unsigned int addr; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| addr = offset + rx_reg_maps[MAP_ADDR_MODULE_ANA_CTRL].phy_addr; |
| wr_reg(MAP_ADDR_MODULE_ANA_CTRL, addr, val); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| /* |
| * rd_reg_hhi |
| * @offset: offset address of hhi physical addr |
| * |
| * returns unsigned int bytes read from the addr |
| */ |
| unsigned int rd_reg_hhi(unsigned int offset) |
| { |
| unsigned int ret; |
| unsigned long flags; |
| unsigned int addr; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| addr = offset + rx_reg_maps[MAP_ADDR_MODULE_HIU].phy_addr; |
| ret = rd_reg(MAP_ADDR_MODULE_HIU, addr); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| return ret; |
| } |
| |
| /* |
| * rd_reg_hhi_bits - read specfied bits of HHI reg |
| * @addr: register address |
| * @mask: bits mask |
| * |
| * return masked bits of register value |
| */ |
| unsigned int rd_reg_hhi_bits(unsigned int offset, unsigned int mask) |
| { |
| return rx_get_bits(rd_reg_hhi(offset), mask); |
| } |
| |
| /* |
| * wr_reg_hhi |
| * @offset: offset address of hhi physical addr |
| * @val: value being written |
| */ |
| void wr_reg_hhi(unsigned int offset, unsigned int val) |
| { |
| unsigned long flags; |
| unsigned int addr; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| addr = offset + rx_reg_maps[MAP_ADDR_MODULE_HIU].phy_addr; |
| wr_reg(MAP_ADDR_MODULE_HIU, addr, val); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| /* |
| * wr_reg_hhi_bits |
| * @offset: offset address of hhi physical addr |
| * @mask: modify bits mask |
| * @val: value being written |
| */ |
| void wr_reg_hhi_bits(unsigned int offset, unsigned int mask, unsigned int val) |
| { |
| wr_reg_hhi(offset, rx_set_bits(rd_reg_hhi(offset), mask, val)); |
| } |
| |
| /* |
| * rd_reg - regisger read |
| * @module: module index of the reg_map table |
| * @reg_addr: offset address of specified phy addr |
| * |
| * returns unsigned int bytes read from the addr |
| */ |
| unsigned int rd_reg(enum map_addr_module_e module, |
| unsigned int reg_addr) |
| { |
| unsigned int val = 0; |
| |
| if (module < MAP_ADDR_MODULE_NUM && check_regmap_flag(reg_addr)) |
| val = readl(rx_reg_maps[module].p + |
| (reg_addr - rx_reg_maps[module].phy_addr)); |
| else |
| rx_pr("rd reg %x error,md %d\n", reg_addr, module); |
| return val; |
| } |
| |
| /* |
| * wr_reg - regisger write |
| * @module: module index of the reg_map table |
| * @reg_addr: offset address of specified phy addr |
| * @val: value being written |
| */ |
| void wr_reg(enum map_addr_module_e module, |
| unsigned int reg_addr, unsigned int val) |
| { |
| if (module < MAP_ADDR_MODULE_NUM && check_regmap_flag(reg_addr)) |
| writel(val, rx_reg_maps[module].p + |
| (reg_addr - rx_reg_maps[module].phy_addr)); |
| else |
| rx_pr("wr reg %x err\n", reg_addr); |
| } |
| |
| /* |
| * rd_reg_b - regisger read byte mode |
| * @module: module index of the reg_map table |
| * @reg_addr: offset address of specified phy addr |
| * |
| * returns unsigned char bytes read from the addr |
| */ |
| unsigned char rd_reg_b(enum map_addr_module_e module, |
| unsigned int reg_addr) |
| { |
| unsigned char val = 0; |
| |
| if (module < MAP_ADDR_MODULE_NUM && check_regmap_flag(reg_addr)) |
| val = readb(rx_reg_maps[module].p + |
| (reg_addr - rx_reg_maps[module].phy_addr)); |
| else |
| rx_pr("rd reg %x error,md %d\n", reg_addr, module); |
| return val; |
| } |
| |
| /* |
| * wr_reg_b - regisger write byte mode |
| * @module: module index of the reg_map table |
| * @reg_addr: offset address of specified phy addr |
| * @val: value being written |
| */ |
| void wr_reg_b(enum map_addr_module_e module, |
| unsigned int reg_addr, unsigned char val) |
| { |
| if (module < MAP_ADDR_MODULE_NUM && check_regmap_flag(reg_addr)) |
| writeb(val, rx_reg_maps[module].p + |
| (reg_addr - rx_reg_maps[module].phy_addr)); |
| else |
| rx_pr("wr reg %x err\n", reg_addr); |
| } |
| |
| /* |
| * rx_hdcp22_wr_only |
| */ |
| void rx_hdcp22_wr_only(unsigned int addr, unsigned int data) |
| { |
| unsigned long flags; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_HDMIRX_CAPB3, |
| rx_reg_maps[MAP_ADDR_MODULE_HDMIRX_CAPB3].phy_addr | addr, |
| data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| unsigned int rx_hdcp22_rd(unsigned int addr) |
| { |
| unsigned int data; |
| unsigned long flags; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| data = rd_reg(MAP_ADDR_MODULE_HDMIRX_CAPB3, |
| rx_reg_maps[MAP_ADDR_MODULE_HDMIRX_CAPB3].phy_addr | addr); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| return data; |
| } |
| |
| void rx_hdcp22_rd_check(unsigned int addr, |
| unsigned int exp_data, |
| unsigned int mask) |
| { |
| unsigned int rd_data; |
| |
| rd_data = rx_hdcp22_rd(addr); |
| if ((rd_data | mask) != (exp_data | mask)) |
| rx_pr("addr=0x%02x rd_data=0x%08x\n", addr, rd_data); |
| } |
| |
| void rx_hdcp22_wr(unsigned int addr, unsigned int data) |
| { |
| rx_hdcp22_wr_only(addr, data); |
| rx_hdcp22_rd_check(addr, data, 0); |
| } |
| |
| /* |
| * rx_hdcp22_rd_reg - hdcp2.2 reg write |
| * @addr: register address |
| * @value: new register value |
| */ |
| void rx_hdcp22_wr_reg(unsigned int addr, unsigned int data) |
| { |
| rx_sec_reg_write((unsigned int *)(unsigned long) |
| (rx_reg_maps[MAP_ADDR_MODULE_HDMIRX_CAPB3].phy_addr + addr), |
| data); |
| } |
| |
| /* |
| * rx_hdcp22_rd_reg - hdcp2.2 reg read |
| * @addr: register address |
| */ |
| unsigned int rx_hdcp22_rd_reg(unsigned int addr) |
| { |
| return (u32)rx_sec_reg_read((unsigned int *)(unsigned long) |
| (rx_reg_maps[MAP_ADDR_MODULE_HDMIRX_CAPB3].phy_addr + addr)); |
| } |
| |
| /* |
| * rx_hdcp22_rd_reg_bits - hdcp2.2 reg masked bits read |
| * @addr: register address |
| * @mask: bits mask |
| */ |
| unsigned int rx_hdcp22_rd_reg_bits(unsigned int addr, unsigned int mask) |
| { |
| return rx_get_bits(rx_hdcp22_rd_reg(addr), mask); |
| } |
| |
| /* |
| * rx_hdcp22_wr_reg_bits - hdcp2.2 reg masked bits write |
| * @addr: register address |
| * @mask: bits mask |
| * @value: new register value |
| */ |
| void rx_hdcp22_wr_reg_bits(unsigned int addr, |
| unsigned int mask, |
| unsigned int value) |
| { |
| rx_hdcp22_wr_reg(addr, rx_set_bits(rx_hdcp22_rd_reg(addr), |
| mask, value)); |
| } |
| |
| /* |
| * hdcp22_wr_top - hdcp2.2 top reg write |
| * @addr: register address |
| * @data: new register value |
| */ |
| void rx_hdcp22_wr_top(unsigned int addr, unsigned int data) |
| { |
| sec_top_write((unsigned int *)(unsigned long)addr, data); |
| } |
| |
| /* |
| * hdcp22_rd_top - hdcp2.2 top reg read |
| * @addr: register address |
| */ |
| unsigned int rx_hdcp22_rd_top(u32 addr) |
| { |
| return (unsigned int)sec_top_read((unsigned int *)(unsigned long)addr); |
| } |
| |
| /* |
| * sec_top_write - secure top write |
| */ |
| void sec_top_write(unsigned int *addr, unsigned int value) |
| { |
| struct arm_smccc_res res; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| arm_smccc_smc(HDMIRX_WR_SEC_TOP_NEW, (unsigned long)(uintptr_t)addr, |
| value, 0, 0, 0, 0, 0, &res); |
| else |
| arm_smccc_smc(HDMIRX_WR_SEC_TOP, (unsigned long)(uintptr_t)addr, |
| value, 0, 0, 0, 0, 0, &res); |
| } |
| |
| /* |
| * sec_top_read - secure top read |
| */ |
| unsigned int sec_top_read(unsigned int *addr) |
| { |
| struct arm_smccc_res res; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| arm_smccc_smc(HDMIRX_RD_SEC_TOP_NEW, (unsigned long)(uintptr_t)addr, |
| 0, 0, 0, 0, 0, 0, &res); |
| else |
| arm_smccc_smc(HDMIRX_RD_SEC_TOP, (unsigned long)(uintptr_t)addr, |
| 0, 0, 0, 0, 0, 0, &res); |
| |
| return (unsigned int)((res.a0) & 0xffffffff); |
| } |
| |
| /* |
| * rx_sec_reg_write - secure region write |
| */ |
| void rx_sec_reg_write(unsigned int *addr, unsigned int value) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc(HDCP22_RX_ESM_WRITE, (unsigned long)(uintptr_t)addr, |
| value, 0, 0, 0, 0, 0, &res); |
| } |
| |
| /* |
| * rx_sec_reg_read - secure region read |
| */ |
| unsigned int rx_sec_reg_read(unsigned int *addr) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc(HDCP22_RX_ESM_READ, (unsigned long)(uintptr_t)addr, |
| 0, 0, 0, 0, 0, 0, &res); |
| |
| return (unsigned int)((res.a0) & 0xffffffff); |
| } |
| |
| /* |
| * rx_sec_reg_write - aes reg write |
| */ |
| void rx_sec_reg_aes_write(unsigned int *addr, unsigned int value) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc(HDMIRX_WR_AES, (unsigned long)(uintptr_t)addr, |
| value, 0, 0, 0, 0, 0, &res); |
| } |
| |
| unsigned int rx_sec_reg_aes_read(unsigned int *addr) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc(HDMIRX_RD_AES, (unsigned long)(uintptr_t)addr, |
| 0, 0, 0, 0, 0, 0, &res); |
| return (unsigned int)((res.a0) & 0xffffffff); |
| } |
| |
| unsigned int rx_rd_aes(u32 addr) |
| { |
| return (unsigned int)rx_sec_reg_aes_read((unsigned int *)(unsigned long)addr); |
| } |
| |
| void rx_wr_aes(unsigned int addr, unsigned int data) |
| { |
| rx_sec_reg_aes_write((unsigned int *)(unsigned long)addr, data); |
| } |
| |
| void rx_sec_reg_cor_write(unsigned int *addr, unsigned int value) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc(HDMIRX_WR_COR, (unsigned long)(uintptr_t)addr, |
| value, 0, 0, 0, 0, 0, &res); |
| } |
| |
| unsigned int rx_sec_reg_cor_read(unsigned int *addr) |
| { |
| struct arm_smccc_res res; |
| |
| arm_smccc_smc(HDMIRX_RD_COR, (unsigned long)(uintptr_t)addr, |
| 0, 0, 0, 0, 0, 0, &res); |
| |
| return (unsigned int)((res.a0) & 0xffffffff); |
| } |
| |
| unsigned int rx_rd_cor(u32 addr) |
| { |
| return (unsigned int)rx_sec_reg_cor_read((unsigned int *)(unsigned long)addr); |
| } |
| |
| void rx_wr_cor(unsigned int addr, unsigned int data) |
| { |
| rx_sec_reg_cor_write((unsigned int *)(unsigned long)addr, data); |
| } |
| |
| /* |
| * rx_sec_set_duk |
| */ |
| unsigned int rx_sec_set_duk(bool repeater) |
| { |
| struct arm_smccc_res res; |
| |
| if (repeater) |
| arm_smccc_smc(HDCP22_RP_SET_DUK_KEY, 0, 0, 0, 0, 0, 0, 0, &res); |
| else |
| arm_smccc_smc(HDCP22_RX_SET_DUK_KEY, 0, 0, 0, 0, 0, 0, 0, &res); |
| |
| return (unsigned int)((res.a0) & 0xffffffff); |
| } |
| |
| /* |
| * rx_set_hdcp14_secure_key |
| */ |
| unsigned int rx_set_hdcp14_secure_key(void) |
| { |
| struct arm_smccc_res res; |
| |
| /* 0x8200002d is the SMC cmd defined in BL31,this CMD |
| * will call set hdcp1.4 key function |
| */ |
| arm_smccc_smc(HDCP14_RX_SETKEY, 0, 0, 0, 0, 0, 0, 0, &res); |
| |
| return (unsigned int)((res.a0) & 0xffffffff); |
| } |
| |
| void hdmirx_phy_pddq_tl1_tm2(unsigned int enable, unsigned int term_val) |
| { |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_MISC_CNTL2, |
| _BIT(1), !enable); |
| /* set rxsense */ |
| if (enable) |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_MISC_CNTL0, |
| MSK(3, 0), 0); |
| else |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_MISC_CNTL0, |
| MSK(3, 0), term_val); |
| } |
| |
| void hdmirx_phy_pddq_t5(unsigned int enable, unsigned int term_val) |
| { |
| hdmirx_wr_bits_amlphy(HHI_RX_PHY_MISC_CNTL2, |
| _BIT(1), !enable); |
| /* set rxsense */ |
| if (enable) |
| hdmirx_wr_bits_amlphy(HHI_RX_PHY_MISC_CNTL0, |
| MSK(3, 0), 0); |
| else |
| hdmirx_wr_bits_amlphy(HHI_RX_PHY_MISC_CNTL0, |
| MSK(3, 0), term_val); |
| } |
| |
| void hdmirx_phy_pddq_snps(unsigned int enable) |
| { |
| hdmirx_wr_bits_dwc(DWC_SNPS_PHYG3_CTRL, MSK(1, 1), enable); |
| } |
| |
| /* |
| * hdmirx_phy_pddq - phy pddq config |
| * @enable: enable phy pddq up |
| */ |
| void hdmirx_phy_pddq(unsigned int enable) |
| { |
| u32 term_value = hdmirx_rd_top(TOP_HPD_PWR5V) & 0x7; |
| |
| if (rx.chip_id >= CHIP_ID_TL1 && |
| rx.chip_id <= CHIP_ID_TM2) { |
| hdmirx_phy_pddq_tl1_tm2(enable, term_value); |
| } else if (rx.chip_id >= CHIP_ID_T5) { |
| hdmirx_phy_pddq_t5(enable, term_value); |
| } else { |
| hdmirx_wr_bits_dwc(DWC_SNPS_PHYG3_CTRL, MSK(1, 1), enable); |
| } |
| } |
| |
| /* |
| * hdmirx_wr_ctl_port |
| */ |
| void hdmirx_wr_ctl_port(unsigned int offset, unsigned int data) |
| { |
| unsigned long flags; |
| |
| if (rx.chip_id < CHIP_ID_TL1) { |
| spin_lock_irqsave(®_rw_lock, flags); |
| wr_reg(MAP_ADDR_MODULE_TOP, hdmirx_ctrl_port + offset, data); |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| } |
| |
| /* |
| * hdmirx_top_sw_reset |
| */ |
| void hdmirx_top_sw_reset(void) |
| { |
| ulong flags; |
| unsigned long dev_offset = 0; |
| |
| spin_lock_irqsave(®_rw_lock, flags); |
| if (rx.chip_id >= CHIP_ID_TL1 && |
| rx.chip_id <= CHIP_ID_T5D) { |
| dev_offset = TOP_DWC_BASE_OFFSET + |
| rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| wr_reg(MAP_ADDR_MODULE_TOP, dev_offset + TOP_SW_RESET, 1); |
| udelay(1); |
| wr_reg(MAP_ADDR_MODULE_TOP, dev_offset + TOP_SW_RESET, 0); |
| } else if (rx.chip_id >= CHIP_ID_T7) { |
| dev_offset = rx_reg_maps[MAP_ADDR_MODULE_TOP].phy_addr; |
| wr_reg(MAP_ADDR_MODULE_TOP, dev_offset + TOP_SW_RESET, 1); |
| udelay(1); |
| wr_reg(MAP_ADDR_MODULE_TOP, dev_offset + TOP_SW_RESET, 0); |
| } else { |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_addr_port | dev_offset, TOP_SW_RESET); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_data_port | dev_offset, 1); |
| udelay(1); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_addr_port | dev_offset, TOP_SW_RESET); |
| wr_reg(MAP_ADDR_MODULE_TOP, |
| hdmirx_data_port | dev_offset, 0); |
| } |
| spin_unlock_irqrestore(®_rw_lock, flags); |
| } |
| |
| /* |
| * rx_irq_en - hdmirx controller irq config |
| * @enable - irq set or clear |
| */ |
| void rx_set_irq_t5(bool enable) |
| { |
| unsigned int data32 = 0; |
| if (enable) { |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| data32 |= 1 << 31; /* DRC_CKS_CHG */ |
| data32 |= 1 << 30; /* DRC_RCV */ |
| data32 |= 0 << 29; /* AUD_TYPE_CHG */ |
| data32 |= 0 << 28; /* DVI_DET */ |
| data32 |= 0 << 27; /* VSI_CKS_CHG */ |
| data32 |= 0 << 26; /* GMD_CKS_CHG */ |
| data32 |= 0 << 25; /* AIF_CKS_CHG */ |
| data32 |= 1 << 24; /* AVI_CKS_CHG */ |
| data32 |= 0 << 23; /* ACR_N_CHG */ |
| data32 |= 0 << 22; /* ACR_CTS_CHG */ |
| data32 |= 1 << 21; /* GCP_AV_MUTE_CHG */ |
| data32 |= 0 << 20; /* GMD_RCV */ |
| data32 |= 0 << 19; /* AIF_RCV */ |
| data32 |= 1 << 18; /* AVI_RCV */ |
| data32 |= 0 << 17; /* ACR_RCV */ |
| data32 |= 0 << 16; /* GCP_RCV */ |
| #ifdef VSIF_PKT_READ_FROM_PD_FIFO |
| data32 |= 0 << 15; /* VSI_RCV */ |
| #else |
| data32 |= 1 << 15; /* VSI_RCV */ |
| #endif |
| data32 |= 0 << 14; /* AMP_RCV */ |
| data32 |= 0 << 13; /* AMP_CHG */ |
| data32 |= 1 << 9; /* EMP_RCV*/ |
| data32 |= 0 << 8; /* PD_FIFO_NEW_ENTRY */ |
| #ifdef VSIF_PKT_READ_FROM_PD_FIFO |
| data32 |= 1 << 4; /* PD_FIFO_OVERFL */ |
| data32 |= 1 << 3; /* PD_FIFO_UNDERFL */ |
| #else |
| data32 |= 0 << 4; /* PD_FIFO_OVERFL */ |
| data32 |= 0 << 3; /* PD_FIFO_UNDERFL */ |
| #endif |
| data32 |= 0 << 2; /* PD_FIFO_TH_START_PASS */ |
| data32 |= 0 << 1; /* PD_FIFO_TH_MAX_PASS */ |
| data32 |= 0 << 0; /* PD_FIFO_TH_MIN_PASS */ |
| data32 |= pdec_ists_en; |
| } else if (rx.chip_id == CHIP_ID_TXLX) { |
| data32 |= 1 << 31; /* DRC_CKS_CHG */ |
| data32 |= 1 << 30; /* DRC_RCV */ |
| data32 |= 0 << 29; /* AUD_TYPE_CHG */ |
| data32 |= 0 << 28; /* DVI_DET */ |
| data32 |= 1 << 27; /* VSI_CKS_CHG */ |
| data32 |= 0 << 26; /* GMD_CKS_CHG */ |
| data32 |= 0 << 25; /* AIF_CKS_CHG */ |
| data32 |= 1 << 24; /* AVI_CKS_CHG */ |
| data32 |= 0 << 23; /* ACR_N_CHG */ |
| data32 |= 0 << 22; /* ACR_CTS_CHG */ |
| data32 |= 1 << 21; /* GCP_AV_MUTE_CHG */ |
| data32 |= 0 << 20; /* GMD_RCV */ |
| data32 |= 0 << 19; /* AIF_RCV */ |
| data32 |= 0 << 18; /* AVI_RCV */ |
| data32 |= 0 << 17; /* ACR_RCV */ |
| data32 |= 0 << 16; /* GCP_RCV */ |
| data32 |= 1 << 15; /* VSI_RCV */ |
| data32 |= 0 << 14; /* AMP_RCV */ |
| data32 |= 0 << 13; /* AMP_CHG */ |
| data32 |= 0 << 8; /* PD_FIFO_NEW_ENTRY */ |
| data32 |= 0 << 4; /* PD_FIFO_OVERFL */ |
| data32 |= 0 << 3; /* PD_FIFO_UNDERFL */ |
| data32 |= 0 << 2; /* PD_FIFO_TH_START_PASS */ |
| data32 |= 0 << 1; /* PD_FIFO_TH_MAX_PASS */ |
| data32 |= 0 << 0; /* PD_FIFO_TH_MIN_PASS */ |
| data32 |= pdec_ists_en; |
| } else if (rx.chip_id == CHIP_ID_TXHD) { |
| /* data32 |= 1 << 31; DRC_CKS_CHG */ |
| /* data32 |= 1 << 30; DRC_RCV */ |
| data32 |= 0 << 29; /* AUD_TYPE_CHG */ |
| data32 |= 0 << 28; /* DVI_DET */ |
| data32 |= 1 << 27; /* VSI_CKS_CHG */ |
| data32 |= 0 << 26; /* GMD_CKS_CHG */ |
| data32 |= 0 << 25; /* AIF_CKS_CHG */ |
| data32 |= 1 << 24; /* AVI_CKS_CHG */ |
| data32 |= 0 << 23; /* ACR_N_CHG */ |
| data32 |= 0 << 22; /* ACR_CTS_CHG */ |
| data32 |= 1 << 21; /* GCP_AV_MUTE_CHG */ |
| data32 |= 0 << 20; /* GMD_RCV */ |
| data32 |= 0 << 19; /* AIF_RCV */ |
| data32 |= 0 << 18; /* AVI_RCV */ |
| data32 |= 0 << 17; /* ACR_RCV */ |
| data32 |= 0 << 16; /* GCP_RCV */ |
| data32 |= 1 << 15; /* VSI_RCV */ |
| /* data32 |= 0 << 14; AMP_RCV */ |
| /* data32 |= 0 << 13; AMP_CHG */ |
| data32 |= 0 << 8; /* PD_FIFO_NEW_ENTRY */ |
| data32 |= 0 << 4; /* PD_FIFO_OVERFL */ |
| data32 |= 0 << 3; /* PD_FIFO_UNDERFL */ |
| data32 |= 0 << 2; /* PD_FIFO_TH_START_PASS */ |
| data32 |= 0 << 1; /* PD_FIFO_TH_MAX_PASS */ |
| data32 |= 0 << 0; /* PD_FIFO_TH_MIN_PASS */ |
| data32 |= pdec_ists_en; |
| } else { /* TXL and previous Chip */ |
| data32 = 0; |
| data32 |= 0 << 29; /* AUD_TYPE_CHG */ |
| data32 |= 0 << 28; /* DVI_DET */ |
| data32 |= 1 << 27; /* VSI_CKS_CHG */ |
| data32 |= 0 << 26; /* GMD_CKS_CHG */ |
| data32 |= 0 << 25; /* AIF_CKS_CHG */ |
| data32 |= 1 << 24; /* AVI_CKS_CHG */ |
| data32 |= 0 << 23; /* ACR_N_CHG */ |
| data32 |= 0 << 22; /* ACR_CTS_CHG */ |
| data32 |= 1 << 21; /* GCP_AV_MUTE_CHG */ |
| data32 |= 0 << 20; /* GMD_RCV */ |
| data32 |= 0 << 19; /* AIF_RCV */ |
| data32 |= 0 << 18; /* AVI_RCV */ |
| data32 |= 0 << 17; /* ACR_RCV */ |
| data32 |= 0 << 16; /* GCP_RCV */ |
| data32 |= 0 << 15; /* VSI_RCV */ |
| data32 |= 0 << 14; /* AMP_RCV */ |
| data32 |= 0 << 13; /* AMP_CHG */ |
| /* diff */ |
| data32 |= 1 << 10; /* DRC_CKS_CHG */ |
| data32 |= 1 << 9; /* DRC_RCV */ |
| /* diff */ |
| data32 |= 0 << 8; /* PD_FIFO_NEW_ENTRY */ |
| data32 |= 0 << 4; /* PD_FIFO_OVERFL */ |
| data32 |= 0 << 3; /* PD_FIFO_UNDERFL */ |
| data32 |= 0 << 2; /* PD_FIFO_TH_START_PASS */ |
| data32 |= 0 << 1; /* PD_FIFO_TH_MAX_PASS */ |
| data32 |= 0 << 0; /* PD_FIFO_TH_MIN_PASS */ |
| data32 |= pdec_ists_en; |
| } |
| hdmirx_wr_dwc(DWC_PDEC_IEN_SET, data32); |
| hdmirx_wr_dwc(DWC_AUD_FIFO_IEN_SET, OVERFL | UNDERFL); |
| } else { |
| /* clear enable */ |
| hdmirx_wr_dwc(DWC_PDEC_IEN_CLR, ~0); |
| hdmirx_wr_dwc(DWC_AUD_CEC_IEN_CLR, ~0); |
| hdmirx_wr_dwc(DWC_AUD_FIFO_IEN_CLR, ~0); |
| hdmirx_wr_dwc(DWC_MD_IEN_CLR, ~0); |
| /* clear status */ |
| hdmirx_wr_dwc(DWC_PDEC_ICLR, ~0); |
| hdmirx_wr_dwc(DWC_AUD_CEC_ICLR, ~0); |
| hdmirx_wr_dwc(DWC_AUD_FIFO_ICLR, ~0); |
| hdmirx_wr_dwc(DWC_MD_ICLR, ~0); |
| } |
| } |
| |
| /* |
| * rx_irq_en - hdmirx controller irq config |
| * @enable - irq set or clear |
| */ |
| void rx_irq_en(bool enable) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) |
| rx_set_irq_t7(enable); |
| else |
| rx_set_irq_t5(enable); |
| } |
| |
| /* |
| * hdmirx_irq_hdcp_enable - hdcp irq enalbe |
| */ |
| void hdmirx_irq_hdcp_enable(bool enable) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) { |
| if (enable) { |
| /* encrypted sts changed en */ |
| //hdmirx_wr_cor(RX_HDCP1X_INTR0_MASK_HDCP1X_IVCRX, 1); |
| /* AKE init received en */ |
| hdmirx_wr_cor(CP2PAX_INTR1_MASK_HDCP2X_IVCRX, 4); |
| } else { |
| /* clear enable */ |
| hdmirx_wr_cor(RX_HDCP1X_INTR0_MASK_HDCP1X_IVCRX, 0); |
| /* clear status */ |
| hdmirx_wr_cor(RX_HDCP1X_INTR0_HDCP1X_IVCRX, 0xff); |
| /* clear enable */ |
| hdmirx_wr_cor(CP2PAX_INTR1_MASK_HDCP2X_IVCRX, 0); |
| /* clear status */ |
| hdmirx_wr_cor(CP2PAX_INTR1_HDCP2X_IVCRX, 0xff); |
| } |
| } else { |
| if (enable) { |
| /* hdcp2.2 */ |
| if (hdcp22_on) |
| hdmirx_wr_dwc(DWC_HDMI2_IEN_SET, 0x1f); |
| /* hdcp1.4 */ |
| hdmirx_wr_dwc(DWC_HDMI_IEN_SET, AKSV_RCV); |
| } else { |
| /* hdcp2.2 */ |
| if (hdcp22_on) { |
| /* clear enable */ |
| hdmirx_wr_dwc(DWC_HDMI2_IEN_CLR, ~0); |
| /* clear status */ |
| hdmirx_wr_dwc(DWC_HDMI2_ICLR, ~0); |
| } |
| /* hdcp1.4 */ |
| /* clear enable */ |
| hdmirx_wr_dwc(DWC_HDMI_IEN_CLR, ~0); |
| /* clear status */ |
| hdmirx_wr_dwc(DWC_HDMI_ICLR, ~0); |
| } |
| } |
| } |
| |
| void hdmirx_top_irq_en(bool flag) |
| { |
| u32 data32; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| data32 = 0; |
| data32 |= (0 << 30); // [ 30] aud_chg; |
| data32 |= (0 << 29); // [ 29] hdmirx_sqofclk_fall; |
| data32 |= (0 << 28); // [ 28] hdmirx_sqofclk_rise; |
| data32 |= (1 << 27); // [ 27] de_rise_del_irq; |
| data32 |= (0 << 26); // [ 26] last_emp_done; |
| data32 |= (1 << 25); // [ 25] emp_field_done; |
| data32 |= (0 << 23); // [ 23] meter_stable_chg_cable; |
| data32 |= (0 << 19); // [ 19] edid_addr2_intr |
| data32 |= (0 << 18); // [ 18] edid_addr1_intr |
| data32 |= (0 << 17); // [ 17] edid_addr0_intr |
| data32 |= (0 << 16); // [ 16] hdcp_enc_state_fall |
| data32 |= (0 << 15); // [ 15] hdcp_enc_state_rise |
| data32 |= (0 << 14); // [ 14] hdcp_auth_start_fall |
| data32 |= (0 << 13); // [ 13] hdcp_auth_start_rise |
| data32 |= (0 << 12); // [ 12] meter_stable_chg_hdmi |
| data32 |= (0 << 11); // [ 11] vid_colour_depth_chg |
| data32 |= (0 << 10); // [ 10] vid_fmt_chg |
| data32 |= (0x0 << 6); // [ 8: 6] hdmirx_5v_fall |
| data32 |= (0x0 << 3); // [ 5: 3] hdmirx_5v_rise |
| // [ 2] sherman_phy_intr: phy digital interrupt |
| data32 |= (0 << 2); |
| // [ 1] pwd_sherman_intr: controller pwd interrupt |
| data32 |= (1 << 1); |
| // [ 0] aon_sherman_intr: controller aon interrupt |
| data32 |= (0 << 0); |
| top_intr_maskn_value = data32; |
| } else { |
| /* top_irq_en bit[16:13] hdcp_sts */ |
| /* bit27 DE rise */ |
| top_intr_maskn_value = 0x28000001; |
| } |
| if (flag) |
| hdmirx_wr_top(TOP_INTR_MASKN, top_intr_maskn_value); |
| else |
| hdmirx_wr_top(TOP_INTR_MASKN, 0); |
| } |
| |
| /* |
| * rx_get_audinfo - get aduio info |
| */ |
| void rx_get_audinfo(struct aud_info_s *audio_info) |
| { |
| /* refer to hdmi spec. CT = 0 */ |
| audio_info->coding_type = 0; |
| /* refer to hdmi spec. SS = 0 */ |
| audio_info->sample_size = 0; |
| /* refer to hdmi spec. SF = 0*/ |
| audio_info->sample_frequency = 0; |
| if (rx.chip_id >= CHIP_ID_T7) { |
| audio_info->n = hdmirx_rd_top(TOP_ACR_N_STAT); |
| audio_info->cts = hdmirx_rd_top(TOP_ACR_CTS_STAT); |
| //audio_info->channel_count = |
| //hdmirx_rd_bits_dwc(DWC_PDEC_AIF_PB0, CHANNEL_COUNT); |
| //audio_info->coding_extension = |
| //hdmirx_rd_bits_dwc(DWC_PDEC_AIF_PB0, AIF_DATA_BYTE_3); |
| //audio_info->auds_ch_alloc = |
| //hdmirx_rd_bits_dwc(DWC_PDEC_AIF_PB0, CH_SPEAK_ALLOC); |
| //audio_info->auds_layout = |
| //hdmirx_rd_bits_dwc(DWC_PDEC_STS, PD_AUD_LAYOUT); |
| audio_info->aud_hbr_rcv = |
| (hdmirx_rd_cor(RX_AUDP_STAT_DP2_IVCRX) >> 6) & 1; |
| if (rx.chip_id >= CHIP_ID_T3) { |
| audio_info->aud_packet_received = |
| hdmirx_rd_top(TOP_MISC_STAT0) >> 16 & 0xff; |
| } else { |
| if (audio_info->aud_hbr_rcv) |
| audio_info->aud_packet_received = 8; |
| else |
| audio_info->aud_packet_received = 1; |
| } |
| audio_info->ch_sts[0] = hdmirx_rd_cor(RX_CHST1_AUD_IVCRX); |
| audio_info->ch_sts[1] = hdmirx_rd_cor(RX_CHST2_AUD_IVCRX); |
| audio_info->ch_sts[2] = hdmirx_rd_cor(RX_CHST3a_AUD_IVCRX); |
| audio_info->ch_sts[3] = hdmirx_rd_cor(RX_CHST4_AUD_IVCRX); |
| audio_info->ch_sts[4] = hdmirx_rd_cor(RX_CHST5_AUD_IVCRX); |
| audio_info->ch_sts[5] = hdmirx_rd_cor(RX_CHST6_AUD_IVCRX); |
| audio_info->ch_sts[6] = hdmirx_rd_cor(RX_CHST7_AUD_IVCRX); |
| } else { |
| audio_info->channel_count = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AIF_PB0, CHANNEL_COUNT); |
| audio_info->coding_extension = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AIF_PB0, AIF_DATA_BYTE_3); |
| audio_info->auds_ch_alloc = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AIF_PB0, CH_SPEAK_ALLOC); |
| audio_info->auds_layout = |
| hdmirx_rd_bits_dwc(DWC_PDEC_STS, PD_AUD_LAYOUT); |
| audio_info->aud_hbr_rcv = |
| hdmirx_rd_dwc(DWC_PDEC_AUD_STS) & AUDS_HBR_RCV; |
| audio_info->aud_packet_received = |
| hdmirx_rd_dwc(DWC_PDEC_AUD_STS); |
| audio_info->aud_mute_en = |
| (hdmirx_rd_bits_dwc(DWC_PDEC_STS, PD_GCP_MUTE_EN) == 0) |
| ? false : true; |
| audio_info->cts = hdmirx_rd_dwc(DWC_PDEC_ACR_CTS); |
| audio_info->n = hdmirx_rd_dwc(DWC_PDEC_ACR_N); |
| } |
| if (audio_info->cts != 0) { |
| audio_info->arc = |
| (rx.clk.tmds_clk / audio_info->cts) * |
| audio_info->n / 128; |
| } else { |
| audio_info->arc = 0; |
| } |
| audio_info->aud_clk = rx.clk.aud_pll; |
| } |
| |
| /* |
| * rx_get_audio_status - interface for audio module |
| */ |
| void rx_get_audio_status(struct rx_audio_stat_s *aud_sts) |
| { |
| if (rx.state == FSM_SIG_READY && |
| rx.pre.sw_vic != HDMI_UNKNOWN && |
| rx.pre.sw_vic != HDMI_UNSUPPORT && |
| rx.avmute_skip == 0) { |
| if (rx.chip_id < CHIP_ID_T7) { |
| aud_sts->aud_alloc = rx.aud_info.auds_ch_alloc; |
| aud_sts->aud_sr = rx.aud_info.real_sr; |
| aud_sts->aud_channel_cnt = rx.aud_info.channel_count; |
| aud_sts->aud_type = rx.aud_info.coding_type; |
| aud_sts->afifo_thres_pass = |
| ((hdmirx_rd_dwc(DWC_AUD_FIFO_STS) & |
| THS_PASS_STS) == 0) ? false : true; |
| aud_sts->aud_rcv_packet = rx.aud_info.aud_packet_received; |
| aud_sts->aud_stb_flag = |
| aud_sts->afifo_thres_pass && |
| !rx.aud_info.aud_mute_en; |
| } else { |
| if ((rx.afifo_sts & 3) == 0) |
| aud_sts->aud_stb_flag = true; |
| aud_sts->aud_rcv_packet = rx.aud_info.aud_packet_received; |
| aud_sts->aud_sr = rx.aud_info.real_sr; |
| memcpy(aud_sts->ch_sts, &rx.aud_info.ch_sts, 7); |
| } |
| } else { |
| memset(aud_sts, 0, sizeof(struct rx_audio_stat_s)); |
| } |
| } |
| EXPORT_SYMBOL(rx_get_audio_status); |
| |
| /* |
| * rx_get_audio_status - interface for audio module |
| */ |
| |
| int rx_set_audio_param(u32 param) |
| { |
| if (rx.chip_id < CHIP_ID_T7) |
| hbr_force_8ch = param & 1; |
| else |
| rx_set_aud_output_t7(param); |
| return 1; |
| } |
| EXPORT_SYMBOL(rx_set_audio_param); |
| |
| /* |
| * rx_get_hdmi5v_sts - get current pwr5v status on all ports |
| */ |
| unsigned int rx_get_hdmi5v_sts(void) |
| { |
| return (hdmirx_rd_top(TOP_HPD_PWR5V) >> 20) & 0xf; |
| } |
| |
| /* |
| * rx_get_hpd_sts - get current hpd status on all ports |
| */ |
| unsigned int rx_get_hpd_sts(void) |
| { |
| return hdmirx_rd_top(TOP_HPD_PWR5V) & 0xf; |
| } |
| |
| /* |
| * rx_get_scdc_clkrate_sts - get tmds clk ratio |
| */ |
| unsigned int rx_get_scdc_clkrate_sts(void) |
| { |
| u32 clk_rate = 0; |
| |
| if (rx.chip_id == CHIP_ID_TXHD || |
| rx.chip_id == CHIP_ID_T5D) |
| clk_rate = 0; |
| else if (rx.chip_id >= CHIP_ID_T7) |
| clk_rate = (hdmirx_rd_cor(SCDCS_TMDS_CONFIG_SCDC_IVCRX) >> 1) & 1; |
| else |
| clk_rate = (hdmirx_rd_dwc(DWC_SCDC_REGS0) >> 17) & 1; |
| /* for debug */ |
| if (force_clk_rate & 0x10) |
| clk_rate = force_clk_rate & 1; |
| |
| return clk_rate; |
| } |
| |
| /* |
| * rx_get_pll_lock_sts - tmds pll lock indication |
| * return true if tmds pll locked, false otherwise. |
| */ |
| unsigned int rx_get_pll_lock_sts(void) |
| { |
| return hdmirx_rd_dwc(DWC_HDMI_PLL_LCK_STS) & 1; |
| } |
| |
| /* |
| * rx_get_aud_pll_lock_sts - audio pll lock indication |
| * no use |
| */ |
| bool rx_get_aud_pll_lock_sts(void) |
| { |
| /* if ((hdmirx_rd_dwc(DWC_AUD_PLL_CTRL) & (1 << 31)) == 0) */ |
| if ((rd_reg_hhi(HHI_AUD_PLL_CNTL_I) & (1 << 31)) == 0) |
| return false; |
| else |
| return true; |
| } |
| |
| /* |
| * is_clk_stable - phy clock stable detection |
| */ |
| bool is_clk_stable(void) |
| { |
| u32 clk = 0; |
| |
| if (rx.phy_ver == PHY_VER_TM2) { |
| if (rx.clk.cable_clk <= MAX_TMDS_CLK && |
| rx.clk.cable_clk >= MIN_TMDS_CLK) |
| clk = rx.clk.cable_clk; |
| } else if (rx.chip_id >= CHIP_ID_TL1) { |
| /* sqofclk */ |
| clk = hdmirx_rd_top(TOP_MISC_STAT0) & 0x1; |
| } else { |
| /* phy clk */ |
| clk = hdmirx_rd_phy(PHY_MAINFSM_STATUS1) & 0x100; |
| } |
| |
| if (clk) |
| return true; |
| else |
| return false; |
| } |
| |
| void rx_afifo_store_all_subpkt(bool all_pkt) |
| { |
| static bool flag = true; |
| |
| if (rx.chip_id > CHIP_ID_T7) |
| return; |
| |
| if (all_pkt) { |
| if (log_level & AUDIO_LOG) |
| rx_pr("afifo store all subpkts: %d\n", flag); |
| /* when afifo overflow, try afifo store |
| * configuration alternatively |
| */ |
| if (flag) |
| hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, |
| AFIF_SUBPACKETS, 0); |
| else |
| hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, |
| AFIF_SUBPACKETS, 1); |
| flag = !flag; |
| } else { |
| hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, |
| AFIF_SUBPACKETS, 1); |
| } |
| } |
| |
| /* |
| * hdmirx_audio_fifo_rst - reset afifo |
| */ |
| unsigned int hdmirx_audio_fifo_rst(void) |
| { |
| int error = 0; |
| |
| if (rx.chip_id > CHIP_ID_T7) |
| return 0; |
| |
| hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, AFIF_INIT, 1); |
| udelay(20); |
| hdmirx_wr_bits_dwc(DWC_AUD_FIFO_CTRL, AFIF_INIT, 0); |
| hdmirx_wr_dwc(DWC_DMI_SW_RST, 0x10); |
| if (log_level & AUDIO_LOG) |
| rx_pr("%s\n", __func__); |
| return error; |
| } |
| |
| /* |
| * hdmirx_control_clk_range |
| */ |
| int hdmirx_control_clk_range(unsigned long min, unsigned long max) |
| { |
| int error = 0; |
| unsigned int evaltime = 0; |
| unsigned long ref_clk; |
| |
| ref_clk = modet_clk; |
| evaltime = (ref_clk * 4095) / 158000; |
| min = (min * evaltime) / ref_clk; |
| max = (max * evaltime) / ref_clk; |
| hdmirx_wr_bits_dwc(DWC_HDMI_CKM_F, MINFREQ, min); |
| hdmirx_wr_bits_dwc(DWC_HDMI_CKM_F, CKM_MAXFREQ, max); |
| return error; |
| } |
| |
| /* |
| * set_scdc_cfg |
| */ |
| void set_scdc_cfg(int hpdlow, int pwrprovided) |
| { |
| switch (rx.chip_id) { |
| case CHIP_ID_TXHD: |
| case CHIP_ID_T5D: |
| break; |
| case CHIP_ID_GXTVBB: |
| case CHIP_ID_TXL: |
| case CHIP_ID_TXLX: |
| case CHIP_ID_TL1: |
| case CHIP_ID_TM2: |
| case CHIP_ID_T5: |
| hdmirx_wr_dwc(DWC_SCDC_CONFIG, |
| (hpdlow << 1) | (pwrprovided << 0)); |
| break; |
| case CHIP_ID_T7: |
| case CHIP_ID_T3: |
| case CHIP_ID_T5W: |
| default: |
| //hdmirx_wr_cor(RX_HPD_C_CTRL_AON_IVCRX, pwrprovided); |
| break; |
| } |
| } |
| |
| int packet_init_t5(void) |
| { |
| int error = 0; |
| int data32 = 0; |
| |
| data32 |= 1 << 12; /* emp_err_filter, tl1*/ |
| data32 |= 1 << 11; |
| data32 |= 1 << 9; /* amp_err_filter */ |
| data32 |= 1 << 8; /* isrc_err_filter */ |
| data32 |= 1 << 7; /* gmd_err_filter */ |
| data32 |= 1 << 6; /* aif_err_filter */ |
| data32 |= 1 << 5; /* avi_err_filter */ |
| data32 |= 1 << 4; /* vsi_err_filter */ |
| data32 |= 1 << 3; /* gcp_err_filter */ |
| data32 |= 1 << 2; /* acrp_err_filter */ |
| data32 |= 1 << 1; /* ph_err_filter */ |
| data32 |= 0 << 0; /* checksum_err_filter */ |
| hdmirx_wr_dwc(DWC_PDEC_ERR_FILTER, data32); |
| |
| data32 = hdmirx_rd_dwc(DWC_PDEC_CTRL); |
| data32 |= 1 << 31; /* PFIFO_STORE_FILTER_EN */ |
| data32 |= 0 << 30; /* Enable packet FIFO store EMP pkt*/ |
| #ifdef VSIF_PKT_READ_FROM_PD_FIFO |
| data32 |= 1 << 22; |
| #endif |
| data32 |= 1 << 4; /* PD_FIFO_WE */ |
| data32 |= 0 << 1; /* emp pkt rev int,0:last 1:every */ |
| data32 |= 1 << 0; /* PDEC_BCH_EN */ |
| data32 &= (~GCP_GLOBAVMUTE); |
| data32 |= GCP_GLOBAVMUTE_EN << 15; |
| data32 |= packet_fifo_cfg; |
| hdmirx_wr_dwc(DWC_PDEC_CTRL, data32); |
| |
| data32 = 0; |
| data32 |= pd_fifo_start_cnt << 20; /* PD_start */ |
| data32 |= 640 << 10; /* PD_max */ |
| data32 |= 8 << 0; /* PD_min */ |
| hdmirx_wr_dwc(DWC_PDEC_FIFO_CFG, data32); |
| |
| return error; |
| } |
| |
| int packet_init_t7(void) |
| { |
| u8 data8 = 0; |
| |
| /* vsif id check en */ |
| hdmirx_wr_cor(VSI_CTRL2_DP3_IVCRX, 1); |
| /* vsif pkt id cfg, default is 000c03 */ |
| //hdmirx_wr_cor(VSIF_ID1_DP3_IVCRX, 0x03); |
| //hdmirx_wr_cor(VSIF_ID2_DP3_IVCRX, 0x0c); |
| //hdmirx_wr_cor(VSIF_ID3_DP3_IVCRX, 0); |
| //hdmirx_wr_cor(VSIF_ID4_DP3_IVCRX, 0); |
| |
| /* hf-vsif id check en */ |
| hdmirx_wr_bits_cor(HF_VSIF_CTRL_DP3_IVCRX, _BIT(3), 1); |
| /* hf-vsif set to get dv, default is 0xc45dd8 */ |
| hdmirx_wr_cor(HF_VSIF_ID1_DP3_IVCRX, 0x46); |
| hdmirx_wr_cor(HF_VSIF_ID2_DP3_IVCRX, 0xd0); |
| hdmirx_wr_cor(HF_VSIF_ID3_DP3_IVCRX, 0x00); |
| |
| data8 = 0; |
| data8 |= 1 << 7; /* enable clr vsif pkt */ |
| data8 |= 1 << 5; /* enable comparison first 3 bytes IEEE */ |
| data8 |= 4 << 2; /* clr register if 4 frames no pkt */ |
| hdmirx_wr_cor(VSI_CTRL1_DP3_IVCRX, data8); |
| hdmirx_wr_cor(VSI_CTRL3_DP3_IVCRX, 1); |
| /* aif to stort hdr10+ */ |
| hdmirx_wr_cor(VSI_ID1_DP3_IVCRX, 0x8b); |
| hdmirx_wr_cor(VSI_ID2_DP3_IVCRX, 0x84); |
| hdmirx_wr_cor(VSI_ID3_DP3_IVCRX, 0x90); |
| |
| /* use unrec to store hf-vsif */ |
| hdmirx_wr_cor(RX_UNREC_CTRL_DP2_IVCRX, 1); |
| hdmirx_wr_cor(RX_UNREC_DEC_DP2_IVCRX, PKT_TYPE_INFOFRAME_VSI); |
| /* get data 0x11c0-11de */ |
| |
| data8 = 0; |
| data8 |= 1 << 7; /* use AIF to VSI */ |
| data8 |= 1 << 6; /* irq is set for any VSIF */ |
| data8 |= 0 << 5; /* irq is set for any ACP */ |
| data8 |= 1 << 4; /* irq is set for any UN-REC */ |
| data8 |= 0 << 3; /* irq is set for any MPEG */ |
| data8 |= 1 << 2; /* irq is set for any AUD */ |
| data8 |= 0 << 1; /* irq is set for any SPD */ |
| data8 |= 0 << 0; /* irq is set for any AVI */ |
| hdmirx_wr_cor(RX_INT_IF_CTRL_DP2_IVCRX, data8); |
| |
| data8 = 0; |
| data8 |= 0 << 7; /* rsvd */ |
| data8 |= 0 << 6; /* rsvd */ |
| data8 |= 0 << 5; /* rsvd */ |
| data8 |= 0 << 4; /* rsvd */ |
| data8 |= 0 << 3; /* irq is set for any ACR */ |
| data8 |= 0 << 2; /* irq is set for any GCP */ |
| data8 |= 0 << 1; /* irq is set for any ISC2 */ |
| data8 |= 0 << 0; /* irq is set for any ISC1 */ |
| hdmirx_wr_cor(RX_INT_IF_CTRL2_DP2_IVCRX, data8); |
| |
| /* auto clr pkt if cable-unplugged/sync lost */ |
| data8 = 0; |
| data8 |= 1 << 7; /* */ |
| data8 |= 1 << 6; /* */ |
| data8 |= 1 << 5; /* */ |
| data8 |= 1 << 4; /* */ |
| data8 |= 1 << 3; /* */ |
| data8 |= 1 << 2; /* */ |
| data8 |= 1 << 1; /* */ |
| data8 |= 1 << 0; /* */ |
| hdmirx_wr_cor(RX_AUTO_CLR_PKT1_DP2_IVCRX, data8); |
| |
| /* auto clr pkt if cable-unplugged/sync lost */ |
| data8 = 0; |
| data8 |= 1 << 7; /* */ |
| data8 |= 1 << 6; /* */ |
| data8 |= 1 << 5; /* */ |
| data8 |= 1 << 4; /* */ |
| data8 |= 1 << 3; /* */ |
| data8 |= 1 << 2; /* */ |
| data8 |= 1 << 1; /* */ |
| data8 |= 1 << 0; /* */ |
| hdmirx_wr_cor(RX_AUTO_CLR_PKT2_DP2_IVCRX, data8); |
| |
| /* auto clr pkt if did not get update */ |
| data8 = 0; |
| data8 |= 1 << 1; /* meta data */ |
| data8 |= 1 << 0; /* GCP */ |
| hdmirx_wr_cor(IF_CTRL2_DP3_IVCRX, data8); |
| |
| return 0; |
| } |
| |
| /* |
| * packet_init - packet receiving config |
| */ |
| int packet_init(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) |
| packet_init_t7(); |
| else |
| packet_init_t5(); |
| return 0; |
| } |
| |
| /* |
| * pd_fifo_irq_ctl |
| */ |
| void pd_fifo_irq_ctl(bool en) |
| { |
| int i = hdmirx_rd_dwc(DWC_PDEC_IEN); |
| |
| if (en == 0) |
| hdmirx_wr_bits_dwc(DWC_PDEC_IEN_CLR, _BIT(2), 1); |
| else |
| hdmirx_wr_dwc(DWC_PDEC_IEN_SET, _BIT(2) | i); |
| } |
| |
| /* |
| * hdmirx_packet_fifo_rst - reset packet fifo |
| */ |
| unsigned int hdmirx_packet_fifo_rst(void) |
| { |
| int error = 0; |
| |
| hdmirx_wr_bits_dwc(DWC_PDEC_CTRL, |
| PD_FIFO_FILL_INFO_CLR | PD_FIFO_CLR, ~0); |
| hdmirx_wr_bits_dwc(DWC_PDEC_CTRL, |
| PD_FIFO_FILL_INFO_CLR | PD_FIFO_CLR, 0); |
| return error; |
| } |
| |
| void rx_set_suspend_edid_clk(bool en) |
| { |
| if (en) { |
| hdmirx_wr_bits_top(TOP_EDID_GEN_CNTL, |
| MSK(7, 0), 1); |
| } else { |
| hdmirx_wr_bits_top(TOP_EDID_GEN_CNTL, |
| MSK(7, 0), EDID_CLK_DIV); |
| } |
| } |
| |
| void rx_i2c_init(void) |
| { |
| int data32 = 0; |
| |
| data32 |= (0xf << 13); /* bit[16:13] */ |
| data32 |= 0 << 11; |
| data32 |= 0 << 10; |
| data32 |= 0 << 9; |
| data32 |= 0 << 8; |
| data32 |= EDID_CLK_DIV << 0; |
| hdmirx_wr_top(TOP_EDID_GEN_CNTL, data32); |
| |
| data32 = 0; |
| /* SDA filter internal clk div */ |
| data32 |= 1 << 29; |
| /* SDA sampling clk div */ |
| data32 |= 1 << 16; |
| /* SCL filter internal clk div */ |
| data32 |= 1 << 13; |
| /* SCL sampling clk div */ |
| data32 |= 1 << 0; |
| hdmirx_wr_top(TOP_INFILTER_HDCP, data32); |
| |
| data32 = 0; |
| /* SDA filter internal clk div */ |
| data32 |= 1 << 29; |
| /* SDA sampling clk div */ |
| data32 |= 1 << 16; |
| /* SCL filter internal clk div */ |
| data32 |= 1 << 13; |
| /* SCL sampling clk div */ |
| data32 |= 1 << 0; |
| hdmirx_wr_top(TOP_INFILTER_I2C0, data32); |
| hdmirx_wr_top(TOP_INFILTER_I2C1, data32); |
| hdmirx_wr_top(TOP_INFILTER_I2C2, data32); |
| hdmirx_wr_top(TOP_INFILTER_I2C3, data32); |
| } |
| |
| /* |
| * TOP_init - hdmirx top initialization |
| */ |
| static int TOP_init(void) |
| { |
| int err = 0; |
| int data32 = 0; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| rx_hdcp22_wr_top(TOP_SECURE_MODE, 1); |
| /* Filter 100ns glitch */ |
| hdmirx_wr_top(TOP_AUDPLL_LOCK_FILTER, 32); |
| data32 = 0; |
| data32 |= (1 << 1);// [1:0] sel |
| hdmirx_wr_top(TOP_PHYIF_CNTL0, data32); |
| } |
| rx_i2c_init(); |
| data32 = 0; |
| if (rx.chip_id >= CHIP_ID_T7) { |
| /*420to444_en*/ |
| data32 |= 1 << 21; |
| /*422to444_en*/ |
| data32 |= 1 << 20; |
| } |
| /* conversion mode of 422 to 444 */ |
| data32 |= 0 << 19; |
| /* pixel_repeat_ovr 0=auto 1 only for T7!!! */ |
| if (rx.chip_id == CHIP_ID_T7) |
| data32 |= 1 << 7; |
| /* !!!!dolby vision 422 to 444 ctl bit */ |
| data32 |= 0 << 0; |
| hdmirx_wr_top(TOP_VID_CNTL, data32); |
| |
| if (rx.chip_id != CHIP_ID_TXHD && |
| rx.chip_id != CHIP_ID_T5D) { |
| data32 = 0; |
| data32 |= 0 << 20; |
| data32 |= 0 << 8; |
| data32 |= 0x0a << 0; |
| hdmirx_wr_top(TOP_VID_CNTL2, data32); |
| } |
| data32 = 0; |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| /* n_cts_auto_mode: */ |
| /* 0-every ACR packet */ |
| /* 1-on N or CTS value change */ |
| data32 |= 1 << 4; |
| } |
| /* delay cycles before n/cts update pulse */ |
| data32 |= 7 << 0; |
| if (rx.chip_id >= CHIP_ID_TL1) |
| hdmirx_wr_top(TOP_TL1_ACR_CNTL2, data32); |
| else |
| hdmirx_wr_top(TOP_ACR_CNTL2, data32); |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| /* Configure channel switch */ |
| data32 = 0; |
| data32 |= (0 << 4); /* [ 4] valid_always*/ |
| data32 |= (7 << 0); /* [3:0] decoup_thresh*/ |
| hdmirx_wr_top(TOP_CHAN_SWITCH_1, data32); |
| |
| data32 = 0; |
| data32 |= (2 << 28); /* [29:28] source_2 */ |
| data32 |= (1 << 26); /* [27:26] source_1 */ |
| data32 |= (0 << 24); /* [25:24] source_0 */ |
| hdmirx_wr_top(TOP_CHAN_SWITCH_0, data32); |
| |
| /* Configure TMDS algin T7 unused */ |
| data32 = 0; |
| hdmirx_wr_top(TOP_TMDS_ALIGN_CNTL0, data32); |
| data32 = 0; |
| hdmirx_wr_top(TOP_TMDS_ALIGN_CNTL1, data32); |
| |
| /* Enable channel output */ |
| data32 = hdmirx_rd_top(TOP_CHAN_SWITCH_0); |
| hdmirx_wr_top(TOP_CHAN_SWITCH_0, data32 | (1 << 0)); |
| |
| /* configure cable clock measure */ |
| data32 = 0; |
| data32 |= (1 << 28); /* [31:28] meas_tolerance */ |
| data32 |= (8192 << 0); /* [23: 0] ref_cycles */ |
| hdmirx_wr_top(TOP_METER_CABLE_CNTL, data32); |
| } |
| |
| /* configure hdmi clock measure */ |
| data32 = 0; |
| data32 |= (1 << 28); /* [31:28] meas_tolerance */ |
| data32 |= (8192 << 0); /* [23: 0] ref_cycles */ |
| hdmirx_wr_top(TOP_METER_HDMI_CNTL, data32); |
| |
| data32 = 0; |
| /* bit4: hpd override, bit5: hpd reverse */ |
| data32 |= 1 << 4; |
| if (rx.chip_id == CHIP_ID_GXTVBB) |
| data32 |= 0 << 5; |
| else |
| data32 |= 1 << 5; |
| /* pull down all the hpd */ |
| hdmirx_wr_top(TOP_HPD_PWR5V, data32); |
| |
| data32 |= 7 << 13; |
| data32 |= 0 << 12; |
| data32 |= 1 << 11; |
| data32 |= 0 << 10; |
| |
| data32 |= 0 << 9; |
| data32 |= 1 << 8; |
| data32 |= 1 << 6; |
| data32 |= 3 << 4; |
| data32 |= 0 << 3; |
| data32 |= acr_mode << 2; |
| data32 |= acr_mode << 1; |
| data32 |= acr_mode << 0; |
| hdmirx_wr_top(TOP_ACR_CNTL_STAT, data32); |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| data32 = 0; |
| data32 |= 0 << 2;/*meas_mode*/ |
| data32 |= 1 << 1;/*enable*/ |
| data32 |= 1 << 0;/*reset*/ |
| if (acr_mode) |
| data32 |= 2 << 16;/*aud pll*/ |
| else |
| data32 |= 500 << 16;/*acr*/ |
| hdmirx_wr_top(TOP_AUDMEAS_CTRL, data32); |
| hdmirx_wr_top(TOP_AUDMEAS_CYCLES_M1, 65535); |
| /*start messure*/ |
| hdmirx_wr_top(TOP_AUDMEAS_CTRL, data32 & (~0x1)); |
| } |
| return err; |
| } |
| |
| /* |
| * DWC_init - DWC controller initialization |
| */ |
| static int DWC_init(void) |
| { |
| int err = 0; |
| unsigned long data32; |
| unsigned int evaltime = 0; |
| |
| evaltime = (modet_clk * 4095) / 158000; |
| /* enable all */ |
| hdmirx_wr_dwc(DWC_HDMI_OVR_CTRL, ~0); |
| /* recover to default value.*/ |
| /* remain code for some time.*/ |
| /* if no side effect then remove it */ |
| /*hdmirx_wr_bits_dwc(DWC_HDMI_SYNC_CTRL,*/ |
| /* VS_POL_ADJ_MODE, VS_POL_ADJ_AUTO);*/ |
| /*hdmirx_wr_bits_dwc(DWC_HDMI_SYNC_CTRL,*/ |
| /* HS_POL_ADJ_MODE, HS_POL_ADJ_AUTO);*/ |
| |
| hdmirx_wr_bits_dwc(DWC_HDMI_CKM_EVLTM, EVAL_TIME, evaltime); |
| hdmirx_control_clk_range(TMDS_CLK_MIN, TMDS_CLK_MAX); |
| |
| /* hdmirx_wr_bits_dwc(DWC_SNPS_PHYG3_CTRL,*/ |
| /*((1 << 2) - 1) << 2, port); */ |
| |
| data32 = 0; |
| data32 |= 0 << 20; |
| data32 |= 1 << 19; |
| data32 |= 5 << 16; /* [18:16] valid_mode */ |
| data32 |= 0 << 12; /* [13:12] ctrl_filt_sens */ |
| data32 |= 3 << 10; /* [11:10] vs_filt_sens */ |
| data32 |= 0 << 8; /* [9:8] hs_filt_sens */ |
| data32 |= 2 << 6; /* [7:6] de_measure_mode */ |
| data32 |= 0 << 5; /* [5] de_regen */ |
| data32 |= 3 << 3; /* [4:3] de_filter_sens */ |
| hdmirx_wr_dwc(DWC_HDMI_ERROR_PROTECT, data32); |
| |
| data32 = 0; |
| data32 |= 0 << 8; /* [10:8] hact_pix_ith */ |
| data32 |= 0 << 5; /* [5] hact_pix_src */ |
| data32 |= 1 << 4; /* [4] htot_pix_src */ |
| hdmirx_wr_dwc(DWC_MD_HCTRL1, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 12; /* [14:12] hs_clk_ith */ |
| data32 |= 7 << 8; /* [10:8] htot32_clk_ith */ |
| data32 |= 1 << 5; /* [5] vs_act_time */ |
| data32 |= 3 << 3; /* [4:3] hs_act_time */ |
| /* bit[1:0] default setting should be 2 */ |
| data32 |= 2 << 0; /* [1:0] h_start_pos */ |
| hdmirx_wr_dwc(DWC_MD_HCTRL2, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 4; /* [4] v_offs_lin_mode */ |
| data32 |= 1 << 1; /* [1] v_edge */ |
| data32 |= 0 << 0; /* [0] v_mode */ |
| hdmirx_wr_dwc(DWC_MD_VCTRL, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 10; /* [11:10] vofs_lin_ith */ |
| data32 |= 3 << 8; /* [9:8] vact_lin_ith */ |
| data32 |= 0 << 6; /* [7:6] vtot_lin_ith */ |
| data32 |= 7 << 3; /* [5:3] vs_clk_ith */ |
| data32 |= 2 << 0; /* [2:0] vtot_clk_ith */ |
| hdmirx_wr_dwc(DWC_MD_VTH, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 2; /* [2] fafielddet_en */ |
| data32 |= 0 << 0; /* [1:0] field_pol_mode */ |
| hdmirx_wr_dwc(DWC_MD_IL_POL, data32); |
| |
| data32 = 0; |
| data32 |= 0 << 1; |
| data32 |= 1 << 0; |
| hdmirx_wr_dwc(DWC_HDMI_RESMPL_CTRL, data32); |
| |
| data32 = 0; |
| data32 |= (hdmirx_rd_dwc(DWC_HDMI_MODE_RECOVER) & 0xf8000000); |
| data32 |= (0 << 24); |
| data32 |= (0 << 18); |
| data32 |= (HYST_HDMI_TO_DVI << 13); |
| data32 |= (HYST_DVI_TO_HDMI << 8); |
| data32 |= (0 << 6); |
| data32 |= (0 << 4); |
| /* EESS_OESS */ |
| /* 0: new auto mode,check on HDMI mode or 1.1 features en */ |
| /* 1: force OESS */ |
| /* 2: force EESS */ |
| /* 3: auto mode,check CTL[3:0]=d9/d8 during WOO */ |
| data32 |= (hdcp_enc_mode << 2); |
| data32 |= (0 << 0); |
| hdmirx_wr_dwc(DWC_HDMI_MODE_RECOVER, data32); |
| |
| data32 = hdmirx_rd_dwc(DWC_HDCP_CTRL); |
| /* 0: Original behaviour */ |
| /* 1: Balance path delay between non-HDCP and HDCP */ |
| data32 |= 1 << 27; /* none & hdcp */ |
| /* 0: Original behaviour */ |
| /* 1: Balance path delay between HDCP14 and HDCP22. */ |
| data32 |= 1 << 26; /* 1.4 & 2.2 */ |
| hdmirx_wr_dwc(DWC_HDCP_CTRL, data32); |
| |
| return err; |
| } |
| |
| void rx_hdcp14_set_normal_key(const struct hdmi_rx_hdcp *hdcp) |
| { |
| unsigned int i = 0; |
| unsigned int k = 0; |
| int error = 0; |
| |
| for (i = 0; i < HDCP_KEYS_SIZE; i += 2) { |
| for (k = 0; k < HDCP_KEY_WR_TRIES; k++) { |
| if (hdmirx_rd_bits_dwc(DWC_HDCP_STS, |
| HDCP_KEY_WR_OK_STS) != 0) { |
| break; |
| } |
| } |
| if (k < HDCP_KEY_WR_TRIES) { |
| hdmirx_wr_dwc(DWC_HDCP_KEY1, hdcp->keys[i + 0]); |
| hdmirx_wr_dwc(DWC_HDCP_KEY0, hdcp->keys[i + 1]); |
| } else { |
| error = -EAGAIN; |
| break; |
| } |
| } |
| hdmirx_wr_dwc(DWC_HDCP_BKSV1, hdcp->bksv[0]); |
| hdmirx_wr_dwc(DWC_HDCP_BKSV0, hdcp->bksv[1]); |
| } |
| |
| /* |
| * hdmi_rx_ctrl_hdcp_config - config hdcp1.4 keys |
| */ |
| void rx_hdcp14_config(const struct hdmi_rx_hdcp *hdcp) |
| { |
| unsigned int data32 = 0; |
| |
| /* I2C_SPIKE_SUPPR */ |
| data32 |= 1 << 16; |
| /* FAST_I2C */ |
| data32 |= 0 << 12; |
| /* ONE_DOT_ONE */ |
| data32 |= 0 << 9; |
| /* FAST_REAUTH */ |
| data32 |= 0 << 8; |
| /* DDC_ADDR */ |
| data32 |= 0x3a << 1; |
| hdmirx_wr_dwc(DWC_HDCP_SETTINGS, data32); |
| /* hdmirx_wr_bits_dwc(DWC_HDCP_SETTINGS, HDCP_FAST_MODE, 0); */ |
| /* Enable hdcp bcaps bit(bit7). In hdcp1.4 spec: Use of |
| * this bit is reserved, hdcp Receivers not capable of |
| * supporting HDMI must clear this bit to 0. For YAMAHA |
| * RX-V377 amplifier, enable this bit is needed, in case |
| * the amplifier won't do hdcp1.4 interaction occasionally. |
| */ |
| hdmirx_wr_bits_dwc(DWC_HDCP_SETTINGS, HDCP_BCAPS, 1); |
| hdmirx_wr_bits_dwc(DWC_HDCP_CTRL, ENCRIPTION_ENABLE, 0); |
| /* hdmirx_wr_bits_dwc(ctx, DWC_HDCP_CTRL, KEY_DECRYPT_ENABLE, 1); */ |
| hdmirx_wr_bits_dwc(DWC_HDCP_CTRL, KEY_DECRYPT_ENABLE, 0); |
| hdmirx_wr_dwc(DWC_HDCP_SEED, hdcp->seed); |
| if (hdcp14_key_mode == SECURE_MODE || hdcp_tee_path) { |
| rx_set_hdcp14_secure_key(); |
| rx_pr("hdcp1.4 secure mode\n"); |
| } else { |
| rx_hdcp14_set_normal_key(&rx.hdcp); |
| rx_pr("hdcp1.4 normal mode\n"); |
| } |
| if (rx.chip_id != CHIP_ID_TXHD && |
| rx.chip_id != CHIP_ID_T5D) { |
| hdmirx_wr_bits_dwc(DWC_HDCP_RPT_CTRL, |
| REPEATER, hdcp->repeat ? 1 : 0); |
| /* nothing attached downstream */ |
| hdmirx_wr_dwc(DWC_HDCP_RPT_BSTATUS, 0); |
| } |
| hdmirx_wr_bits_dwc(DWC_HDCP_CTRL, ENCRIPTION_ENABLE, 1); |
| } |
| |
| /* rst cdr to clr tmds_valid */ |
| bool rx_clr_tmds_valid(void) |
| { |
| bool ret = false; |
| |
| if (rx.state >= FSM_SIG_STABLE) { |
| rx.state = FSM_WAIT_CLK_STABLE; |
| hdmirx_output_en(false); |
| hdmirx_top_irq_en(false); |
| if (log_level & VIDEO_LOG) |
| rx_pr("%s!\n", __func__); |
| } |
| if (rx.phy_ver == PHY_VER_TL1) { |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_MISC_CNTL0, MSK(3, 7), 0); |
| if (log_level & VIDEO_LOG) |
| rx_pr("%s!\n", __func__); |
| ret = true; |
| } else if (rx.phy_ver == PHY_VER_TM2) { |
| if (rx.aml_phy.force_sqo) { |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_DCHD_CNTL0, _BIT(25), 0); |
| udelay(5); |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_DCHD_CNTL0, _BIT(25), 1); |
| if (log_level & VIDEO_LOG) |
| rx_pr("low empplitue %s!\n", __func__); |
| ret = true; |
| } |
| } else if (rx.phy_ver >= PHY_VER_T5) { |
| hdmirx_wr_bits_amlphy(HHI_RX_PHY_DCHD_CNTL0, CDR_RST, 0); |
| ret = true; |
| if (log_level & VIDEO_LOG) |
| rx_pr("%s!\n", __func__); |
| } |
| return ret; |
| } |
| |
| void rx_set_term_value_pre(unsigned char port, bool value) |
| { |
| u32 data32; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| data32 = rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0); |
| if (port < E_PORT3) { |
| if (value) { |
| data32 |= (1 << port); |
| } else { |
| /* rst cdr to clr tmds_valid */ |
| data32 &= ~(MSK(3, 7)); |
| data32 &= ~(1 << port); |
| } |
| wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data32); |
| } else if (port == ALL_PORTS) { |
| if (value) { |
| data32 |= 0x7; |
| } else { |
| /* rst cdr to clr tmds_valid */ |
| data32 &= 0xfffffc78; |
| data32 |= (MSK(3, 7)); |
| /* data32 &= 0xfffffff8; */ |
| } |
| wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data32); |
| } |
| } else { |
| if (port < E_PORT_NUM) { |
| if (value) |
| hdmirx_wr_bits_phy(PHY_MAIN_FSM_OVERRIDE1, |
| _BIT(port + 4), 1); |
| else |
| hdmirx_wr_bits_phy(PHY_MAIN_FSM_OVERRIDE1, |
| _BIT(port + 4), 0); |
| } else if (port == ALL_PORTS) { |
| if (value) |
| hdmirx_wr_bits_phy(PHY_MAIN_FSM_OVERRIDE1, |
| PHY_TERM_OV_VALUE, 0xF); |
| else |
| hdmirx_wr_bits_phy(PHY_MAIN_FSM_OVERRIDE1, |
| PHY_TERM_OV_VALUE, 0); |
| } |
| } |
| } |
| |
| void rx_set_term_value_t5(unsigned char port, bool value) |
| { |
| u32 data32; |
| |
| data32 = hdmirx_rd_amlphy(HHI_RX_PHY_MISC_CNTL0); |
| if (port < E_PORT3) { |
| if (value) { |
| data32 |= (1 << port); |
| } else { |
| /* rst cdr to clr tmds_valid */ |
| data32 &= ~(MSK(3, 7)); |
| data32 &= ~(1 << port); |
| } |
| hdmirx_wr_amlphy(HHI_RX_PHY_MISC_CNTL0, data32); |
| } else if (port == ALL_PORTS) { |
| if (value) { |
| data32 |= 0x7; |
| } else { |
| /* rst cdr to clr tmds_valid */ |
| data32 &= 0xfffffc78; |
| data32 |= (MSK(3, 7)); |
| /* data32 &= 0xfffffff8; */ |
| } |
| hdmirx_wr_amlphy(HHI_RX_PHY_MISC_CNTL0, data32); |
| } |
| } |
| |
| void rx_set_term_value(unsigned char port, bool value) |
| { |
| if (rx.chip_id >= CHIP_ID_T5) |
| rx_set_term_value_t5(port, value); |
| else |
| rx_set_term_value_pre(port, value); |
| } |
| |
| int rx_set_port_hpd(u8 port_id, bool val) |
| { |
| if (port_id < E_PORT_NUM) { |
| if (val) { |
| hdmirx_wr_bits_top(TOP_HPD_PWR5V, _BIT(port_id), 1); |
| rx_set_term_value(port_id, 1); |
| } else { |
| hdmirx_wr_bits_top(TOP_HPD_PWR5V, _BIT(port_id), 0); |
| rx_set_term_value(port_id, 0); |
| } |
| } else if (port_id == ALL_PORTS) { |
| if (val) { |
| hdmirx_wr_bits_top(TOP_HPD_PWR5V, MSK(4, 0), 0xF); |
| rx_set_term_value(port_id, 1); |
| } else { |
| hdmirx_wr_bits_top(TOP_HPD_PWR5V, MSK(4, 0), 0x0); |
| rx_set_term_value(port_id, 0); |
| } |
| } else { |
| return -1; |
| } |
| if (log_level & LOG_EN) |
| rx_pr("%s, port:%d, val:%d\n", __func__, port_id, val); |
| return 0; |
| } |
| |
| /* add param to differentiate repeater/main state machine/etc |
| * 0: main loop; 2: workaround; 3: repeater flow; 4: special use |
| */ |
| void rx_set_cur_hpd(u8 val, u8 func) |
| { |
| rx_pr("func-%d to", func); |
| rx_set_port_hpd(rx.port, val); |
| } |
| |
| /* |
| * rx_force_hpd_config - force config hpd level on all ports |
| * @hpd_level: hpd level |
| */ |
| void rx_force_hpd_cfg(u8 hpd_level) |
| { |
| unsigned int hpd_value; |
| |
| if (hpd_level) { |
| if (disable_port_en) |
| hpd_value = (~(1 << disable_port_num)) & 0xF; |
| else |
| hpd_value = 0xF; |
| |
| hdmirx_wr_bits_top(TOP_HPD_PWR5V, MSK(4, 0), hpd_value); |
| } else { |
| hdmirx_wr_bits_top(TOP_HPD_PWR5V, MSK(4, 0), 0x0); |
| } |
| } |
| |
| /* |
| * rx_force_rxsense_cfg_pre - force config rxsense level on all ports |
| * for the chips before t5 |
| * @level: rxsense level |
| */ |
| void rx_force_rxsense_cfg_pre(u8 level) |
| { |
| unsigned int term_ovr_value; |
| unsigned int data32; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| /* enable terminal connect */ |
| data32 = rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0); |
| if (level) { |
| if (disable_port_en) |
| term_ovr_value = |
| (~(1 << disable_port_num)) & 0x7; |
| else |
| term_ovr_value = 0x7; |
| data32 |= term_ovr_value; |
| } else { |
| data32 &= 0xfffffff8; |
| } |
| wr_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL0, data32); |
| } else { |
| if (level) { |
| if (disable_port_en) |
| term_ovr_value = |
| (~(1 << disable_port_num)) & 0xF; |
| else |
| term_ovr_value = 0xF; |
| |
| hdmirx_wr_bits_phy(PHY_MAIN_FSM_OVERRIDE1, |
| PHY_TERM_OV_VALUE, term_ovr_value); |
| } else { |
| hdmirx_wr_bits_phy(PHY_MAIN_FSM_OVERRIDE1, |
| PHY_TERM_OV_VALUE, 0x0); |
| } |
| } |
| } |
| |
| void rx_force_rxsense_cfg_t5(u8 level) |
| { |
| unsigned int term_ovr_value; |
| unsigned int data32; |
| |
| /* enable terminal connect */ |
| data32 = hdmirx_rd_amlphy(HHI_RX_PHY_MISC_CNTL0); |
| if (level) { |
| if (disable_port_en) |
| term_ovr_value = |
| (~(1 << disable_port_num)) & 0x7; |
| else |
| term_ovr_value = 0x7; |
| data32 |= term_ovr_value; |
| } else { |
| data32 &= 0xfffffff8; |
| } |
| hdmirx_wr_amlphy(HHI_RX_PHY_MISC_CNTL0, data32); |
| } |
| |
| void rx_force_rxsense_cfg(u8 level) |
| { |
| if (rx.chip_id >= CHIP_ID_T5) |
| rx_force_rxsense_cfg_t5(level); |
| else |
| rx_force_rxsense_cfg_pre(level); |
| } |
| |
| /* |
| * rx_force_hpd_rxsense_cfg - force config |
| * hpd & rxsense level on all ports |
| * @level: hpd & rxsense level |
| */ |
| void rx_force_hpd_rxsense_cfg(u8 level) |
| { |
| rx_force_hpd_cfg(level); |
| rx_force_rxsense_cfg(level); |
| if (log_level & LOG_EN) |
| rx_pr("hpd & rxsense force val:%d\n", level); |
| } |
| |
| /* |
| * control_reset - hdmirx controller reset |
| */ |
| void control_reset(void) |
| { |
| unsigned long data32; |
| |
| /* Enable functional modules */ |
| data32 = 0; |
| data32 |= 1 << 5; /* [5] cec_enable */ |
| data32 |= 1 << 4; /* [4] aud_enable */ |
| data32 |= 1 << 3; /* [3] bus_enable */ |
| data32 |= 1 << 2; /* [2] hdmi_enable */ |
| data32 |= 1 << 1; /* [1] modet_enable */ |
| data32 |= 1 << 0; /* [0] cfg_enable */ |
| hdmirx_wr_dwc(DWC_DMI_DISABLE_IF, data32); |
| mdelay(1); |
| hdmirx_wr_dwc(DWC_DMI_SW_RST, 0x0000001F); |
| } |
| |
| void rx_esm_tmdsclk_en(bool en) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) |
| return; |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, HDCP22_TMDSCLK_EN, en); |
| if (hdcp22_on && hdcp_hpd_ctrl_en) |
| hdmirx_hdcp22_hpd(en); |
| if (log_level & HDCP_LOG) |
| rx_pr("%s:%d\n", __func__, en); |
| } |
| |
| /* |
| * hdcp22_clk_en - clock gating for hdcp2.2 |
| * @en: enable or disable clock |
| */ |
| void hdcp22_clk_en(bool en) |
| { |
| u32 data32; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| return; |
| if (en) { |
| if (rx.chip_id >= CHIP_ID_T5) |
| data32 = rd_reg_clk_ctl(HHI_HDCP22_CLK_CNTL); |
| else |
| data32 = rd_reg_hhi(HHI_HDCP22_CLK_CNTL); |
| /* [26:25] select cts_oscin_clk=24 MHz */ |
| data32 |= 0 << 25; |
| /* [ 24] Enable gated clock */ |
| data32 |= 1 << 24; |
| data32 |= 0 << 16; |
| /* [10: 9] fclk_div7=2000/7=285.71 MHz */ |
| data32 |= 0 << 9; |
| /* [ 8] clk_en. Enable gated clock */ |
| data32 |= 1 << 8; |
| /* [ 6: 0] Divide by 1. = 285.71/1 = 285.71 MHz */ |
| data32 |= 0 << 0; |
| if (rx.chip_id >= CHIP_ID_T5) |
| wr_reg_clk_ctl(HHI_HDCP22_CLK_CNTL, data32); |
| else |
| wr_reg_hhi(HHI_HDCP22_CLK_CNTL, data32); |
| /* axi clk config*/ |
| if (rx.chip_id >= CHIP_ID_T5) |
| data32 = rd_reg_clk_ctl(HHI_AXI_CLK_CTNL); |
| else |
| data32 = rd_reg_hhi(HHI_AXI_CLK_CTNL); |
| /* [ 8] clk_en. Enable gated clock */ |
| data32 |= 1 << 8; |
| if (rx.chip_id >= CHIP_ID_T5) |
| wr_reg_clk_ctl(HHI_AXI_CLK_CTNL, data32); |
| else |
| wr_reg_hhi(HHI_AXI_CLK_CTNL, data32); |
| |
| if (rx.chip_id >= CHIP_ID_TL1) |
| /* TL1:esm related clk bit9-11 */ |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, MSK(3, 9), 0x7); |
| else |
| /* TL1:esm related clk bit3-5 */ |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, MSK(3, 3), 0x7); |
| |
| if (rx.chip_id >= CHIP_ID_TM2) |
| /* Enable axi_clk,for tm2 */ |
| /* AXI arbiter is moved outside of hdmitx. */ |
| /* There is an AXI arbiter in the chip’s EE domain */ |
| /* for arbitrating AXI requests from HDMI TX and RX.*/ |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, MSK(1, 12), 0x1); |
| } else { |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, MSK(3, 3), 0x0); |
| if (rx.chip_id >= CHIP_ID_T5) |
| wr_reg_clk_ctl(HHI_HDCP22_CLK_CNTL, 0); |
| else |
| wr_reg_hhi(HHI_HDCP22_CLK_CNTL, 0); |
| } |
| } |
| |
| /* |
| * hdmirx_hdcp22_esm_rst - software reset esm |
| */ |
| void hdmirx_hdcp22_esm_rst(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) |
| return; |
| |
| /* For TL1,the sw_reset_hdcp22 bit is top reg 0x0,bit'12 */ |
| if (rx.chip_id >= CHIP_ID_TL1) |
| hdmirx_wr_top(TOP_SW_RESET, 0x1000); |
| else |
| /* For txlx and previous chips,the sw_reset_hdcp22 is bit'8 */ |
| hdmirx_wr_top(TOP_SW_RESET, 0x100); |
| mdelay(1); |
| hdmirx_wr_top(TOP_SW_RESET, 0x0); |
| rx_pr("esm rst\n"); |
| } |
| |
| /* |
| * hdmirx_hdcp22_init - hdcp2.2 initialization |
| */ |
| void rx_is_hdcp22_support(void) |
| { |
| int temp; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| return; |
| temp = rx_sec_set_duk(hdmirx_repeat_support()); |
| if (temp > 0) { |
| rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 7); |
| hdcp22_on = 1; |
| if (temp == 2) |
| rx_pr("2.2 test key!!!\n"); |
| } else { |
| hdcp22_on = 0; |
| } |
| rx_pr("hdcp22 == %d\n", hdcp22_on); |
| } |
| |
| /* |
| * hdmirx_hdcp22_hpd - set hpd level for hdcp2.2 |
| * @value: whether to set hpd high |
| */ |
| void hdmirx_hdcp22_hpd(bool value) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) |
| return; |
| unsigned long data32 = hdmirx_rd_dwc(DWC_HDCP22_CONTROL); |
| |
| if (value) |
| data32 |= 0x1000; |
| else |
| data32 &= (~0x1000); |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, data32); |
| } |
| |
| /* |
| * hdcp_22_off |
| */ |
| void hdcp_22_off(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) { |
| return; |
| } else { |
| /* note: can't pull down hpd before enter suspend */ |
| /* it will stop cec wake up func if EE domain still working */ |
| /* rx_set_cur_hpd(0); */ |
| hpd_to_esm = 0; |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x0); |
| if (hdcp22_kill_esm == 0) |
| hdmirx_hdcp22_esm_rst(); |
| else |
| hdcp22_kill_esm = 0; |
| hdcp22_clk_en(0); |
| } |
| rx_pr("hdcp22 off\n"); |
| } |
| |
| /* |
| * hdcp_22_on |
| */ |
| void hdcp_22_on(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) { |
| //TODO.. |
| } else { |
| hdcp22_kill_esm = 0; |
| /* switch_set_state(&rx.hpd_sdev, 0x0); */ |
| /* extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 0); */ |
| rx_hdcp22_send_uevent(0); |
| hdcp22_clk_en(1); |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x1000); |
| /* rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 0x1); */ |
| /* hdmirx_hw_config(); */ |
| /* switch_set_state(&rx.hpd_sdev, 0x1); */ |
| /* extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 1); */ |
| rx_hdcp22_send_uevent(1); |
| hpd_to_esm = 1; |
| /* dont need to delay 900ms to wait sysctl start hdcp_rx22,*/ |
| /*sysctl is userspace it wakes up later than driver */ |
| /* mdelay(900); */ |
| /* rx_set_cur_hpd(1); */ |
| } |
| rx_pr("hdcp22 on\n"); |
| } |
| |
| /* |
| * clk_init - clock initialization |
| * config clock for hdmirx module |
| */ |
| void clk_init_cor(void) |
| { |
| unsigned int data32; |
| |
| rx_pr("\n clk_init\n"); |
| /* DWC clock enable */ |
| /* Turn on clk_hdmirx_pclk, also = sysclk */ |
| wr_reg_clk_ctl(CLKCTRL_SYS_CLK_EN0_REG2, |
| rd_reg_clk_ctl(CLKCTRL_SYS_CLK_EN0_REG2) | (1 << 9)); |
| |
| data32 = 0; |
| data32 |= (0 << 25);// [26:25] clk_sel for cts_hdmirx_2m_clk: 0=cts_oscin_clk |
| data32 |= (0 << 24);// [ 24] clk_en for cts_hdmirx_2m_clk |
| data32 |= (11 << 16);// [22:16] clk_div for cts_hdmirx_2m_clk: 24/12=2M |
| data32 |= (3 << 9);// [10: 9] clk_sel for cts_hdmirx_5m_clk: 3=fclk_div5 |
| data32 |= (0 << 8);// [ 8] clk_en for cts_hdmirx_5m_clk |
| data32 |= (79 << 0);// [ 6: 0] clk_div for cts_hdmirx_5m_clk: fclk_dvi5/80=400/80=5M |
| wr_reg_clk_ctl(RX_CLK_CTRL, data32); |
| data32 |= (1 << 24);// [ 24] clk_en for cts_hdmirx_2m_clk |
| data32 |= (1 << 8);// [ 8] clk_en for cts_hdmirx_5m_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL, data32); |
| |
| data32 = 0; |
| data32 |= (3 << 25);// [26:25] clk_sel for cts_hdmirx_hdcp2x_eclk: 3=fclk_div5 |
| data32 |= (0 << 24);// [ 24] clk_en for cts_hdmirx_hdcp2x_eclk |
| data32 |= (15 << 16);// [22:16] clk_div for cts_hdmirx_hdcp2x_eclk: fclk_dvi5/16=400/16=25M |
| data32 |= (3 << 9);// [10: 9] clk_sel for cts_hdmirx_cfg_clk: 3=fclk_div5 |
| data32 |= (0 << 8);// [ 8] clk_en for cts_hdmirx_cfg_clk |
| data32 |= (7 << 0);// [ 6: 0] clk_div for cts_hdmirx_cfg_clk: fclk_dvi5/8=400/8=50M |
| wr_reg_clk_ctl(RX_CLK_CTRL1, data32); |
| data32 |= (1 << 24);// [ 24] clk_en for cts_hdmirx_hdcp2x_eclk |
| data32 |= (1 << 8);// [ 8] clk_en for cts_hdmirx_cfg_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL1, data32); |
| |
| data32 = 0; |
| data32 |= (1 << 25);// [26:25] clk_sel for cts_hdmirx_acr_ref_clk: 1=fclk_div4 |
| data32 |= (0 << 24);// [ 24] clk_en for cts_hdmirx_acr_ref_clk |
| data32 |= (0 << 16);// [22:16] clk_div for cts_hdmirx_acr_ref_clk: fclk_div4/1=500M |
| data32 |= (0 << 9);// [10: 9] clk_sel for cts_hdmirx_aud_pll_clk: 0=hdmirx_aud_pll_clk |
| data32 |= (0 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| data32 |= (0 << 0);// [ 6: 0] clk_div for cts_hdmirx_aud_pll_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL2, data32); |
| data32 |= (1 << 24);// [ 24] clk_en for cts_hdmirx_acr_ref_clk |
| data32 |= (1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL2, data32); |
| |
| data32 = 0; |
| data32 |= (0 << 9);// [10: 9] clk_sel for cts_hdmirx_meter_clk: 0=cts_oscin_clk |
| data32 |= (0 << 8);// [ 8] clk_en for cts_hdmirx_meter_clk |
| data32 |= (0 << 0);// [ 6: 0] clk_div for cts_hdmirx_meter_clk: 24M |
| wr_reg_clk_ctl(RX_CLK_CTRL3, data32); |
| data32 |= (1 << 8);// [ 8] clk_en for cts_hdmirx_meter_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL3, data32); |
| |
| data32 = 0; |
| data32 |= (0 << 31);// [31] free_clk_en |
| data32 |= (0 << 15);// [15] hbr_spdif_en |
| data32 |= (0 << 8);// [8] tmds_ch2_clk_inv |
| data32 |= (0 << 7);// [7] tmds_ch1_clk_inv |
| data32 |= (0 << 6);// [6] tmds_ch0_clk_inv |
| data32 |= (0 << 5);// [5] pll4x_cfg |
| data32 |= (0 << 4);// [4] force_pll4x |
| data32 |= (0 << 3);// [3] phy_clk_inv |
| hdmirx_wr_top(TOP_CLK_CNTL, data32); |
| } |
| |
| void clk_init_dwc(void) |
| { |
| unsigned int data32; |
| |
| /* DWC clock enable */ |
| /* Turn on clk_hdmirx_pclk, also = sysclk */ |
| wr_reg_hhi(HHI_GCLK_MPEG0, |
| rd_reg_hhi(HHI_GCLK_MPEG0) | (1 << 21)); |
| |
| hdmirx_wr_ctl_port(0, 0x93ff); |
| hdmirx_wr_ctl_port(0x10, 0x93ff); |
| |
| if (rx.chip_id == CHIP_ID_TXLX || |
| rx.chip_id == CHIP_ID_TXHD || |
| rx.chip_id >= CHIP_ID_TL1) { |
| data32 = 0; |
| data32 |= (0 << 15); |
| data32 |= (1 << 14); |
| data32 |= (0 << 5); |
| data32 |= (0 << 4); |
| data32 |= (0 << 0); |
| if (rx.chip_id >= CHIP_ID_T5) { |
| wr_reg_clk_ctl(HHI_AUDPLL_CLK_OUT_CNTL, data32); |
| data32 |= (1 << 4); |
| wr_reg_clk_ctl(HHI_AUDPLL_CLK_OUT_CNTL, data32); |
| } else { |
| wr_reg_hhi(HHI_AUDPLL_CLK_OUT_CNTL, data32); |
| data32 |= (1 << 4); |
| wr_reg_hhi(HHI_AUDPLL_CLK_OUT_CNTL, data32); |
| } |
| } |
| data32 = hdmirx_rd_top(TOP_CLK_CNTL); |
| data32 |= 0 << 31; /* [31] disable clkgating */ |
| data32 |= 1 << 17; /* [17] audfifo_rd_en */ |
| data32 |= 1 << 16; /* [16] pktfifo_rd_en */ |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| data32 |= 0 << 8; /* [8] tmds_ch2_clk_inv */ |
| data32 |= 0 << 7; /* [7] tmds_ch1_clk_inv */ |
| data32 |= 0 << 6; /* [6] tmds_ch0_clk_inv */ |
| data32 |= 0 << 5; /* [5] pll4x_cfg */ |
| data32 |= 0 << 4; /* [4] force_pll4x */ |
| data32 |= 0 << 3; /* [3] phy_clk_inv: 1-invert */ |
| } else { |
| data32 |= 1 << 2; /* [2] hdmirx_cecclk_en */ |
| data32 |= 0 << 1; /* [1] bus_clk_inv */ |
| data32 |= 0 << 0; /* [0] hdmi_clk_inv */ |
| } |
| hdmirx_wr_top(TOP_CLK_CNTL, data32); /* DEFAULT: {32'h0} */ |
| } |
| |
| void clk_init(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) |
| clk_init_cor(); |
| else |
| clk_init_dwc(); |
| } |
| |
| /* |
| * hdmirx_20_init - hdmi2.0 config |
| */ |
| void hdmirx_20_init(void) |
| { |
| unsigned long data32; |
| bool scdc_en = |
| scdc_force_en ? 1 : get_edid_selection(rx.port); |
| |
| data32 = 0; |
| data32 |= 1 << 12; /* [12] vid_data_checken */ |
| data32 |= 1 << 11; /* [11] data_island_checken */ |
| data32 |= 1 << 10; /* [10] gb_checken */ |
| data32 |= 1 << 9; /* [9] preamb_checken */ |
| data32 |= 1 << 8; /* [8] ctrl_checken */ |
| data32 |= scdc_en << 4; /* [4] scdc_enable */ |
| /* To support some TX that sends out SSCP even when not scrambling: |
| * 0: Original behaviour |
| * 1: During TMDS character error detection, treat SSCP character |
| * as normal TMDS character. |
| * Note: If scramble is turned on, this bit will not take effect, |
| * revert to original IP behaviour. |
| */ |
| data32 |= ignore_sscp_charerr << 3; /* [3]ignore sscp character err */ |
| /* To support some TX that sends out SSCP even when not scrambling: |
| * 0: Original behaviour |
| * 1: During TMDS decoding, treat SSCP character |
| * as normal TMDS character |
| * Note: If scramble is turned on, this bit will not take effect, |
| * revert to original IP behaviour. |
| */ |
| data32 |= ignore_sscp_tmds << 2; /* [2] ignore sscp tmds */ |
| data32 |= SCRAMBLE_SEL << 0; /* [1:0] scramble_sel */ |
| hdmirx_wr_dwc(DWC_HDMI20_CONTROL, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 24; /* [25:24] i2c_spike_suppr */ |
| data32 |= 0 << 20; /* [20] i2c_timeout_en */ |
| data32 |= 0 << 0; /* [19:0] i2c_timeout_cnt */ |
| hdmirx_wr_dwc(DWC_SCDC_I2CCONFIG, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 1; /* [1] hpd_low */ |
| data32 |= 0 << 0; /* [0] power_provided */ |
| hdmirx_wr_dwc(DWC_SCDC_CONFIG, data32); |
| |
| data32 = 0; |
| data32 |= 0xabcdef << 8; /* [31:8] manufacture_oui */ |
| data32 |= 1 << 0; /* [7:0] sink_version */ |
| hdmirx_wr_dwc(DWC_SCDC_WRDATA0, data32); |
| |
| data32 = 0; |
| data32 |= 10 << 20; /* [29:20] chlock_max_err */ |
| data32 |= 24000 << 0; /* [15:0] milisec_timer_limit */ |
| hdmirx_wr_dwc(DWC_CHLOCK_CONFIG, data32); |
| |
| /* hdcp2.2 ctl */ |
| if (hdcp22_on) { |
| /* set hdcp_hpd high later */ |
| if (hdcp_hpd_ctrl_en) |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0); |
| else |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x1000); |
| } else { |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 2); |
| } |
| } |
| |
| /* |
| * hdmirx_audio_init - audio initialization |
| */ |
| int hdmirx_audio_init(void) |
| { |
| /* 0=I2S 2-channel; 1=I2S 4 x 2-channel. */ |
| int err = 0; |
| unsigned long data32 = 0; |
| |
| /* |
| *recover to default value, bit[27:24] |
| *set aud_pll_lock filter |
| *data32 = 0; |
| *data32 |= 0 << 28; |
| *data32 |= 0 << 24; |
| *hdmirx_wr_dwc(DWC_AUD_PLL_CTRL, data32); |
| */ |
| |
| /* AFIFO depth 1536word.*/ |
| /*increase start threshold to middle position */ |
| data32 = 0; |
| data32 |= 160 << 18; /* start */ |
| data32 |= 200 << 9; /* max */ |
| data32 |= 8 << 0; /* min */ |
| hdmirx_wr_dwc(DWC_AUD_FIFO_TH, data32); |
| |
| /* recover to default value.*/ |
| /*remain code for some time.*/ |
| /*if no side effect then remove it */ |
| /* |
| *data32 = 0; |
| *data32 |= 1 << 16; |
| *data32 |= 0 << 0; |
| *hdmirx_wr_dwc(DWC_AUD_FIFO_CTRL, data32); |
| */ |
| |
| data32 = 0; |
| data32 |= 0 << 8; |
| data32 |= 1 << 7; |
| data32 |= aud_ch_map << 2; |
| data32 |= 1 << 0; |
| hdmirx_wr_dwc(DWC_AUD_CHEXTR_CTRL, data32); |
| |
| data32 = 0; |
| /* [22:21] aport_shdw_ctrl */ |
| data32 |= 3 << 21; |
| /* [20:19] auto_aclk_mute */ |
| data32 |= auto_aclk_mute << 19; |
| /* [16:10] aud_mute_speed */ |
| data32 |= 1 << 10; |
| /* [7] aud_avmute_en */ |
| data32 |= aud_avmute_en << 7; |
| /* [6:5] aud_mute_sel */ |
| data32 |= aud_mute_sel << 5; |
| /* [4:3] aud_mute_mode */ |
| data32 |= 1 << 3; |
| /* [2:1] aud_ttone_fs_sel */ |
| data32 |= 0 << 1; |
| /* [0] testtone_en */ |
| data32 |= 0 << 0; |
| hdmirx_wr_dwc(DWC_AUD_MUTE_CTRL, data32); |
| |
| /* recover to default value.*/ |
| /*remain code for some time.*/ |
| /*if no side effect then remove it */ |
| /* |
| *data32 = 0; |
| *data32 |= 0 << 16; |
| *data32 |= 0 << 12; |
| *data32 |= 0 << 4; |
| *data32 |= 0 << 1; |
| *data32 |= 0 << 0; |
| *hdmirx_wr_dwc(DWC_AUD_PAO_CTRL, data32); |
| */ |
| |
| /* recover to default value.*/ |
| /*remain code for some time.*/ |
| /*if no side effect then remove it */ |
| /* |
| *data32 = 0; |
| *data32 |= 0 << 8; |
| *hdmirx_wr_dwc(DWC_PDEC_AIF_CTRL, data32); |
| */ |
| |
| data32 = 0; |
| /* [4:2] deltacts_irqtrig */ |
| data32 |= 0 << 2; |
| /* [1:0] cts_n_meas_mode */ |
| data32 |= 0 << 0; |
| /* DEFAULT: {27'd0, 3'd0, 2'd1} */ |
| hdmirx_wr_dwc(DWC_PDEC_ACRM_CTRL, data32); |
| |
| /* unsupport HBR serial mode. invalid bit */ |
| if (rx.chip_id < CHIP_ID_TM2) |
| hdmirx_wr_bits_dwc(DWC_AUD_CTRL, DWC_AUD_HBR_ENABLE, 1); |
| |
| /* SAO cfg, disable I2S output, no use */ |
| data32 = 0; |
| data32 |= 1 << 10; |
| data32 |= 0 << 9; |
| data32 |= 0x0f << 5; |
| data32 |= 0 << 1; |
| data32 |= 1 << 0; |
| hdmirx_wr_dwc(DWC_AUD_SAO_CTRL, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 6; |
| data32 |= 0xf << 2; |
| hdmirx_wr_dwc(DWC_PDEC_ASP_CTRL, data32); |
| |
| return err; |
| } |
| |
| /* |
| * snps phy g3 initial |
| */ |
| void snps_phyg3_init(void) |
| { |
| unsigned int data32; |
| unsigned int term_value = |
| hdmirx_rd_top(TOP_HPD_PWR5V); |
| |
| data32 = 0; |
| data32 |= 1 << 6; |
| data32 |= 1 << 4; |
| data32 |= rx.port << 2; |
| data32 |= 1 << 1; |
| data32 |= 1 << 0; |
| hdmirx_wr_dwc(DWC_SNPS_PHYG3_CTRL, data32); |
| usleep_range(1000, 1010); |
| |
| data32 = 0; |
| data32 |= 1 << 6; |
| data32 |= 1 << 4; |
| data32 |= rx.port << 2; |
| data32 |= 1 << 1; |
| data32 |= 0 << 0; |
| hdmirx_wr_dwc(DWC_SNPS_PHYG3_CTRL, data32); |
| |
| data32 = 0; |
| data32 |= 6 << 10; |
| data32 |= 1 << 9; |
| data32 |= ((24000 * 4) / 1000); |
| hdmirx_wr_phy(PHY_CMU_CONFIG, data32); |
| |
| hdmirx_wr_phy(PHY_VOLTAGE_LEVEL, 0x1ea); |
| |
| data32 = 0; |
| data32 |= 0 << 15; |
| data32 |= 0 << 13; |
| data32 |= 0 << 12; |
| data32 |= phy_fast_switching << 11; |
| data32 |= 0 << 10; |
| data32 |= phy_fsm_enhancement << 9; |
| data32 |= 0 << 8; |
| data32 |= 0 << 7; |
| data32 |= 0 << 5; |
| data32 |= 0 << 3; |
| data32 |= 0 << 2; |
| data32 |= 0 << 0; |
| hdmirx_wr_phy(PHY_SYSTEM_CONFIG, data32); |
| |
| hdmirx_wr_phy(MPLL_PARAMETERS2, 0x1c94); |
| hdmirx_wr_phy(MPLL_PARAMETERS3, 0x3713); |
| /*default 0x24da , EQ optimizing for kaiboer box */ |
| hdmirx_wr_phy(MPLL_PARAMETERS4, 0x24dc); |
| hdmirx_wr_phy(MPLL_PARAMETERS5, 0x5492); |
| hdmirx_wr_phy(MPLL_PARAMETERS6, 0x4b0d); |
| hdmirx_wr_phy(MPLL_PARAMETERS7, 0x4760); |
| hdmirx_wr_phy(MPLL_PARAMETERS8, 0x008c); |
| hdmirx_wr_phy(MPLL_PARAMETERS9, 0x0010); |
| hdmirx_wr_phy(MPLL_PARAMETERS10, 0x2d20); |
| hdmirx_wr_phy(MPLL_PARAMETERS11, 0x2e31); |
| hdmirx_wr_phy(MPLL_PARAMETERS12, 0x4b64); |
| hdmirx_wr_phy(MPLL_PARAMETERS13, 0x2493); |
| hdmirx_wr_phy(MPLL_PARAMETERS14, 0x676d); |
| hdmirx_wr_phy(MPLL_PARAMETERS15, 0x23e0); |
| hdmirx_wr_phy(MPLL_PARAMETERS16, 0x001b); |
| hdmirx_wr_phy(MPLL_PARAMETERS17, 0x2218); |
| hdmirx_wr_phy(MPLL_PARAMETERS18, 0x1b25); |
| hdmirx_wr_phy(MPLL_PARAMETERS19, 0x2492); |
| hdmirx_wr_phy(MPLL_PARAMETERS20, 0x48ea); |
| hdmirx_wr_phy(MPLL_PARAMETERS21, 0x0011); |
| hdmirx_wr_phy(MPLL_PARAMETERS22, 0x04d2); |
| hdmirx_wr_phy(MPLL_PARAMETERS23, 0x0414); |
| |
| /* Configuring I2C to work in fastmode */ |
| hdmirx_wr_dwc(DWC_I2CM_PHYG3_MODE, 0x1); |
| /* disable overload protect for Philips DVD */ |
| /* NOTE!!!!! don't remove below setting */ |
| hdmirx_wr_phy(OVL_PROT_CTRL, 0xa); |
| |
| /* clear clkrate cfg */ |
| hdmirx_wr_bits_phy(PHY_CDR_CTRL_CNT, CLK_RATE_BIT, 0); |
| /*last_clk_rate = 0;*/ |
| rx.phy.clk_rate = 0; |
| /* enable all ports's termination */ |
| data32 = 0; |
| data32 |= 1 << 8; |
| data32 |= ((term_value & 0xF) << 4); |
| hdmirx_wr_phy(PHY_MAIN_FSM_OVERRIDE1, data32); |
| |
| data32 = 0; |
| data32 |= 1 << 6; |
| data32 |= 1 << 4; |
| data32 |= rx.port << 2; |
| data32 |= 0 << 1; |
| data32 |= 0 << 0; |
| hdmirx_wr_dwc(DWC_SNPS_PHYG3_CTRL, data32); |
| } |
| |
| void rx_run_eq(void) |
| { |
| if (rx.chip_id < CHIP_ID_TL1) |
| rx_eq_algorithm(); |
| else |
| hdmirx_phy_init(); |
| } |
| |
| bool rx_eq_done(void) |
| { |
| bool ret = true; |
| |
| if (rx_get_eq_run_state() == E_EQ_START) |
| ret = false; |
| return ret; |
| } |
| |
| void aml_phy_offset_cal(void) |
| { |
| if (rx.phy_ver >= PHY_VER_T7) |
| aml_phy_offset_cal_t7(); |
| else if (rx.phy_ver == PHY_VER_T5) |
| aml_phy_offset_cal_t5(); |
| } |
| |
| /* |
| * rx_clkrate_monitor - clock ratio monitor |
| * detect SCDC tmds clk ratio changes and |
| * update phy setting |
| */ |
| bool rx_clkrate_monitor(void) |
| { |
| u32 clk_rate, phy_band, pll_band; |
| bool changed = false; |
| int i; |
| int error = 0; |
| |
| clk_rate = rx_get_scdc_clkrate_sts(); |
| /* should rm squelch judgement for low-emplitude issue */ |
| /* otherwise,sw can not detect the low-emplitude signal */ |
| /* if (rx.state < FSM_WAIT_CLK_STABLE) */ |
| /*return changed;*/ |
| /*if (is_clk_stable()) { */ |
| pll_band = aml_phy_pll_band(rx.clk.cable_clk, clk_rate); |
| phy_band = aml_cable_clk_band(rx.clk.cable_clk, clk_rate); |
| if (rx.phy.pll_bw != pll_band || |
| rx.phy.phy_bw != phy_band) { |
| rx.phy.cablesel = 0; |
| rx.phy.phy_bw = phy_band; |
| rx.phy.pll_bw = pll_band; |
| } |
| /* } */ |
| |
| if (clk_rate != rx.phy.clk_rate) { |
| changed = true; |
| if (rx.chip_id < CHIP_ID_TL1) { |
| for (i = 0; i < 3; i++) { |
| error = hdmirx_wr_bits_phy(PHY_CDR_CTRL_CNT, |
| CLK_RATE_BIT, clk_rate); |
| |
| if (error == 0) |
| break; |
| } |
| } else { |
| hdmirx_phy_init(); |
| } |
| if (log_level & VIDEO_LOG) |
| rx_pr("clk_rate:%d, last_clk_rate: %d\n", |
| clk_rate, rx.phy.clk_rate); |
| rx.phy.clk_rate = clk_rate; |
| } |
| if (changed) { |
| if (rx.state >= FSM_WAIT_CLK_STABLE) |
| rx.state = FSM_WAIT_CLK_STABLE; |
| i2c_err_cnt = 0; |
| } |
| return changed; |
| } |
| |
| void rx_afifo_monitor(void) |
| { |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| if (rx.state != FSM_SIG_READY) |
| return; |
| if (rx_afifo_dbg_en) |
| return; |
| |
| rx.afifo_sts = hdmirx_rd_cor(RX_INTR4_PWD_IVCRX) & 3; |
| hdmirx_wr_cor(RX_INTR4_PWD_IVCRX, 3); |
| if (rx.afifo_sts & 2) { |
| afifo_overflow_cnt++; |
| if (log_level & AUDIO_LOG) |
| rx_pr("overflow\n"); |
| } else if (rx.afifo_sts & 1) { |
| afifo_underflow_cnt++; |
| rx_aud_fifo_rst(); |
| if (log_level & AUDIO_LOG) |
| rx_pr("underflow\n"); |
| } else { |
| if (afifo_overflow_cnt) |
| afifo_overflow_cnt--; |
| if (afifo_underflow_cnt) |
| afifo_underflow_cnt--; |
| } |
| if (afifo_overflow_cnt > 150) { |
| afifo_overflow_cnt = 0; |
| hdmirx_output_en(false); |
| hdmirx_hbr2spdif(0); |
| rx_set_cur_hpd(0, 5); |
| rx.state = FSM_5V_LOST; |
| rx_pr("!!force reset\n"); |
| } |
| //if (afifo_underflow_cnt) { |
| //afifo_underflow_cnt = 0; |
| //rx_aud_fifo_rst(); |
| //rx_pr("!!pll rst\n"); |
| //} |
| } |
| |
| void rx_hdcp_monitor(void) |
| { |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| if (rx.hdcp.hdcp_version != HDCP_VER_NONE && |
| rx.state == FSM_SIG_READY) { |
| if (rx.ecc_err_frames_cnt >= rx_ecc_err_frames) { |
| skip_frame(5); |
| if (rx.hdcp.hdcp_version == HDCP_VER_22) |
| rx_hdcp_22_sent_reauth(); |
| else if (rx.hdcp.hdcp_version == HDCP_VER_14) |
| rx_hdcp_14_sent_reauth(); |
| rx_pr("reauth-err:%d\n", rx.ecc_err); |
| if (rx.state >= FSM_SIG_STABLE) |
| rx.state = FSM_SIG_WAIT_STABLE; |
| rx.ecc_err = 0; |
| rx.ecc_err_frames_cnt = 0; |
| } |
| } |
| } |
| |
| bool is_special_func_en(void) |
| { |
| bool ret = false; |
| |
| #ifdef SPECIAL_FUNC_EN |
| if (rx.port == E_PORT2) |
| ret = true; |
| #endif |
| |
| return ret; |
| } |
| |
| bool rx_need_support_fastswitch(void) |
| { |
| bool ret = false; |
| |
| if (rx.chip_id <= CHIP_ID_T7) |
| return ret; |
| |
| #ifdef SPECIAL_FUNC_EN |
| if (rx.boot_flag && rx.port == E_PORT0) { |
| if (hdmirx_rd_cor(SCDCS_TMDS_CONFIG_SCDC_IVCRX) & 2) |
| ret = true; |
| rx_pr("pc port first boot\n"); |
| } |
| #endif |
| |
| return ret; |
| } |
| |
| /* |
| * rx_hdcp_init - hdcp1.4 init and enable |
| */ |
| void rx_hdcp_init(void) |
| { |
| if (hdcp_enable) |
| rx_hdcp14_config(&rx.hdcp); |
| else |
| hdmirx_wr_bits_dwc(DWC_HDCP_CTRL, ENCRIPTION_ENABLE, 0); |
| } |
| |
| /*type 1 pull down hpd,reset hdcp2.2 |
| *type 2 only pull down hpd |
| */ |
| void hdmirx_load_firm_reset(int type) |
| { |
| int ret = 0; |
| |
| rx_pr("%s\n", __func__); |
| rx_pr("3firm_change:%d,repeat_plug:%d,repeat:%d\n", |
| rx.firm_change, repeat_plug, rx.hdcp.repeat); |
| /*wait the fsm end*/ |
| rx.firm_change = 1; |
| msleep(20); |
| /*External_Mute(1);rx_aud_pll_ctl(0);*/ |
| rx_set_cur_hpd(0, 4); |
| /*type 2 only pull down hpd*/ |
| if (type == 2) { |
| downstream_hpd_flag = 0; |
| fsm_restart(); |
| return; |
| } |
| if (!repeat_plug) |
| downstream_hpd_flag = 1; |
| else |
| downstream_hpd_flag = 0; |
| ret = rx_sec_set_duk(hdmirx_repeat_support()); |
| rx_pr("ret = %d\n", ret); |
| if (ret) { |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x0); |
| hdmirx_hdcp22_esm_rst(); |
| mdelay(100); |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x1000); |
| rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 0x1); |
| fsm_restart(); |
| rx_is_hdcp22_support(); |
| } |
| rx_pr("4firm_change:%d,repeat_plug:%d,repeat:%d\n", |
| rx.firm_change, repeat_plug, rx.hdcp.repeat); |
| } |
| |
| /* need reset bandgap when |
| * aud_clk=0 & req_clk!=0 |
| * according to analog team's request |
| */ |
| void rx_audio_bandgap_rst(void) |
| { |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0, _BIT(10), 1); |
| udelay(10); |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0, _BIT(10), 0); |
| } else { |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0_TXLX, _BIT(13), 1); |
| udelay(10); |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0_TXLX, _BIT(13), 0); |
| } |
| if (log_level & AUDIO_LOG) |
| rx_pr("%s\n", __func__); |
| } |
| |
| void rx_audio_bandgap_en(void) |
| { |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| /* for tl1/tm2 0:bg on 1: bg off */ |
| wr_reg_hhi_bits(HHI_VDAC_CNTL1, _BIT(7), 0); |
| |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0, _BIT(10), 1); |
| udelay(10); |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0, _BIT(10), 0); |
| } else { |
| /* for txlx/txl... 1:bg on 0: bg off */ |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0_TXLX, _BIT(9), 1); |
| |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0_TXLX, _BIT(13), 1); |
| udelay(10); |
| wr_reg_hhi_bits(HHI_VDAC_CNTL0_TXLX, _BIT(13), 0); |
| } |
| if (log_level & AUDIO_LOG) |
| rx_pr("%s\n", __func__); |
| } |
| |
| void rx_sw_reset(int level) |
| { |
| unsigned long data32 = 0; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| rx_sw_reset_t7(level); |
| } else { |
| if (level == 1) { |
| data32 |= 0 << 7; /* [7]vid_enable */ |
| data32 |= 0 << 5; /* [5]cec_enable */ |
| data32 |= 0 << 4; /* [4]aud_enable */ |
| data32 |= 0 << 3; /* [3]bus_enable */ |
| data32 |= 0 << 2; /* [2]hdmi_enable */ |
| data32 |= 1 << 1; /* [1]modet_enable */ |
| data32 |= 0 << 0; /* [0]cfg_enable */ |
| |
| } else if (level == 2) { |
| data32 |= 0 << 7; /* [7]vid_enable */ |
| data32 |= 0 << 5; /* [5]cec_enable */ |
| data32 |= 1 << 4; /* [4]aud_enable */ |
| data32 |= 0 << 3; /* [3]bus_enable */ |
| data32 |= 1 << 2; /* [2]hdmi_enable */ |
| data32 |= 1 << 1; /* [1]modet_enable */ |
| data32 |= 0 << 0; /* [0]cfg_enable */ |
| } |
| hdmirx_wr_dwc(DWC_DMI_SW_RST, data32); |
| hdmirx_audio_fifo_rst(); |
| hdmirx_packet_fifo_rst(); |
| } |
| } |
| |
| void rx_esm_reset(int level) |
| { |
| if (rx.chip_id >= CHIP_ID_T7 || !hdcp22_on) |
| return; |
| if (level == 0) {//for state machine |
| esm_set_stable(false); |
| if (esm_recovery_mode |
| == ESM_REC_MODE_RESET) |
| esm_set_reset(true); |
| /* for some hdcp2.2 devices which |
| * don't retry 2.2 interaction |
| * continuously and don't response |
| * to re-auth, such as chroma 2403, |
| * esm needs to be on work even |
| * before tmds is valid so that to |
| * not miss 2.2 interaction |
| */ |
| /* else */ |
| /* rx_esm_tmdsclk_en(false); */ |
| } else if (level == 1) {//for open port |
| esm_set_stable(false); |
| esm_set_reset(true); |
| if (esm_recovery_mode == ESM_REC_MODE_TMDS) |
| rx_esm_tmdsclk_en(false); |
| } else if (level == 2) {//for fsm_restart&signal_status_init |
| if (esm_recovery_mode == ESM_REC_MODE_TMDS) |
| rx_esm_tmdsclk_en(false); |
| esm_set_stable(false); |
| } else if (level == 3) {//for dwc_reset |
| if (rx.hdcp.hdcp_version != HDCP_VER_14) { |
| if (esm_recovery_mode == ESM_REC_MODE_TMDS) |
| rx_esm_tmdsclk_en(true); |
| esm_set_stable(true); |
| if (rx.hdcp.hdcp_version == HDCP_VER_22) |
| hdmirx_hdcp22_reauth(); |
| } |
| } |
| } |
| |
| void cor_init(void) |
| { |
| u8 data8; |
| u32 data32; |
| |
| //--------AON REG------ |
| data8 = 0; |
| data8 |= (0 << 4);// [4] reg_sw_rst_auto |
| data8 |= (1 << 0);// [0] reg_sw_rst |
| hdmirx_wr_cor(RX_AON_SRST, data8);//register address: 0x0005 |
| |
| data8 = 0; |
| data8 |= (0 << 5);// [5] reg_scramble_on_ovr |
| data8 |= (1 << 4);// [4] reg_hdmi2_on_ovr |
| data8 |= (0 << 2);// [3:2]rsvd |
| data8 |= (0 << 1);// [1] reg_scramble_on_val |
| data8 |= (1 << 0);// [0] reg_hdmi2_on_val |
| hdmirx_wr_cor(RX_HDMI2_MODE_CTRL, data8);//register address: 0x0040 |
| |
| data8 = 0; |
| data8 |= (0 << 3);// [3] reg_soft_intr_en |
| data8 |= (0 << 1);// [1] reg_intr_polarity (default is 1) |
| hdmirx_wr_cor(RX_INT_CTRL, data8);//register address: 0x0079 |
| |
| //-------PWD REG------- |
| data8 = 0; |
| data8 |= (0 << 7);// [7] reg_mhl3ce_sel_rx |
| data8 |= (0 << 6);// [6] rsvd |
| data8 |= (0 << 5);// [5] reg_vdi_rx_dig_bypass |
| data8 |= (0 << 4);// [4] reg_tmds_mode_inv |
| data8 |= (0 << 3);// [3] reg_bypass_rx2tx_dsc_video |
| data8 |= (0 << 2);// [2] rsvd |
| data8 |= (0 << 1);// [1] rsvd |
| data8 |= (0 << 0);// [0] reg_core_iso_en TMDS core isolation enable |
| hdmirx_wr_cor(RX_PWD_CTRL, data8);//register address: 0x1001 |
| |
| data8 = 0; |
| data8 |= (0 << 3);// [4:3] reg_dsc_bypass_align |
| data8 |= (0 << 2);// [2] reg_hv_sync_cntrl |
| data8 |= (1 << 1);// [1] reg_sync_pol |
| data8 |= (1 << 0);// [0] reg_pd_all 0:power down; 1: normal operation |
| hdmirx_wr_cor(RX_SYS_CTRL1, data8);//register address: 0x1007 |
| |
| data8 = 0; |
| data8 |= (1 << 4);// [5:4] reg_di_ch2_sel |
| data8 |= (0 << 2);// [3:2] reg_di_ch1_sel |
| data8 |= (2 << 0);// [1:0] reg_di_ch0_sel |
| hdmirx_wr_cor(RX_SYS_TMDS_CH_MAP, data8);//register address: 0x100E |
| |
| data8 = 0; |
| data8 |= (0 << 7);//rsvd |
| data8 |= (1 << 6);//reg_phy_di_dff_en : enable for dff latching data coming from TMDS phy |
| data8 |= (0 << 5);//reg_di_ch2_invt |
| data8 |= (1 << 4);//reg_di_ch1_invt |
| data8 |= (0 << 3);//reg_di_ch0_invt |
| data8 |= (0 << 2);//reg_di_ch2_bsi |
| data8 |= (1 << 1);//reg_di_ch1_bsi |
| data8 |= (0 << 0);//reg_di_ch0_bsi |
| hdmirx_wr_cor(RX_SYS_TMDS_D_IR, data8);//register address: 0x100F |
| |
| /* deep color clock source */ |
| data8 = 0; |
| data8 |= (0 << 6);//[7:6] reg_pp_status |
| data8 |= (1 << 5);//[5] reg_offset_coen |
| data8 |= (0 << 4);//[4] rerg_dc_ctl_ow //!!!! |
| data8 |= (0 << 0);//[3:0] reg_dc_ctl deep-color clock from the TMDS RX core |
| hdmirx_wr_cor(RX_TMDS_CCTRL2, data8);//register address: 0x1013 |
| |
| data8 = 0; |
| data8 |= (1 << 7);//reg_tst_xclk 1:Crystal oscillator clock muxed to test output pin |
| data8 |= (0 << 6);//reg_tst_ckdt 1:CKDT muxed to test output pin |
| data8 |= (0 << 5);//reg_invert_tclk |
| hdmirx_wr_cor(RX_TEST_STAT, data8);//register address: 0x103b (0x80) |
| |
| data8 = 0; |
| data8 |= (0 << 3);//[5:3] divides the vpc out clock |
| //[2:0] divides the vpc core clock: |
| //0: divide by 1; 1: divide by 2; 3: divide by 4; 7: divide by 8 |
| data8 |= (1 << 0); |
| hdmirx_wr_cor(RX_PWD0_CLK_DIV_0, data8) ;//register address: 0x10c1 |
| |
| data8 = 0; |
| data8 |= (0 << 7);// [ 7] cbcr_order |
| data8 |= (0 << 6);// [ 6] yc_demux_polarity |
| data8 |= (0 << 5);// [ 5] yc_demux_enable |
| hdmirx_wr_cor(RX_VP_INPUT_FORMAT_LO, data8); |
| |
| data8 = 0; |
| data8 |= (0 << 3);// [ 3] mux_cb_or_cr |
| data8 |= (0 << 2);// [ 2] mux_420_enable |
| data8 |= (0 << 0);// [1:0] input_pixel_rate |
| hdmirx_wr_cor(RX_VP_INPUT_FORMAT_HI, data8); |
| |
| //===hdcp 1.4 needed |
| hdmirx_wr_cor(RX_SW_HDMI_MODE_PWD_IVCRX, 0x04);//register address: 0x1022 |
| |
| //[0] reg_ext_mclk_en; 1 select external mclk; 0: select internal dacr mclk |
| hdmirx_wr_cor(EXT_MCLK_SEL_PWD_IVCRX, 0x01);//register address: 0x10c6 |
| |
| //DEPACK |
| data8 = 0; |
| data8 |= (1 << 4);//[4] reg_wait4_two_avi_pkts default is 1, but need two packet |
| data8 |= (0 << 0);//[0] reg_all_if_clr_en |
| hdmirx_wr_cor(VSI_CTRL4_DP3_IVCRX, data8); //register_address: 0x120f |
| |
| // ------PHY CLK/RST----- |
| hdmirx_wr_cor(PWD0_CLK_EN_1_PHYCK_IVCRX, 0xff);//register address: 0x20a3 |
| hdmirx_wr_cor(PWD0_CLK_EN_2_PHYCK_IVCRX, 0x3f);//register address: 0x20a4 |
| hdmirx_wr_cor(PWD0_CLK_EN_3_PHYCK_IVCRX, 0x01);//register address: 0x20a5 |
| |
| hdmirx_wr_cor(RX_AON_SRST_AON_IVCRX, 0x00);//reset |
| hdmirx_wr_cor(RX_PWD_INT_CTRL, 0x00);//[1] reg_intr_polarity, default = 1 |
| //------------------- |
| // vp core config |
| //------------------- |
| //invecase Rx 422 output directly |
| //mux 422 12bit*2 in to 8bit*3 out |
| data8 = 0; |
| data8 |= (0 << 3);// de_polarity |
| data8 |= (0 << 2);// rsvd |
| data8 |= (0 << 1);// hsync_polarity |
| data8 |= (0 << 0);// vsync_polarity |
| hdmirx_wr_cor(VP_OUTPUT_SYNC_CFG_VID_IVCRX, data8);//register address: 0x1842 |
| |
| data32 = 0; |
| //data32 |= (((rx_color_format==HDMI_COLOR_FORMAT_422)?3:2) << 9); |
| data32 |= (2 << 9); |
| // [11: 9] select_cr: 0=ch1(Y); 1=ch0(Cb); 2=ch2(Cr); 3={ch2 8-b,ch0 4-b}(422). |
| //data32 |= (((rx_color_format==HDMI_COLOR_FORMAT_422)?3:1) << 6); |
| data32 |= (1 << 6); |
| // [ 8: 6] select_cb: 0=ch1(Y); 1=ch0(Cb); 2=ch2(Cr); 3={ch2 8-b,ch0 4-b}(422). |
| //data32 |= (((rx_color_format==HDMI_COLOR_FORMAT_422)?3:0) << 3); |
| data32 |= (0 << 3); |
| // [ 5: 3] select_y : 0=ch1(Y); 1=ch0(Cb); 2=ch2(Cr); 3={ch1 8-b,ch0 4-b}(422). |
| data32 |= (0 << 2);// [ 2] reverse_cr |
| data32 |= (0 << 1);// [ 1] reverse_cb |
| data32 |= (0 << 0);// [ 0] reverse_y |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX, data32 & 0xff); |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX + 1, (data32 >> 8) & 0xff); |
| |
| //------------------ |
| // audio I2S config |
| //------------------ |
| data8 = 0; |
| data8 |= (5 << 4);//reg_vres_xclk_diff |
| data8 |= (0 << 0);//reg_vid_xlckpclk_en |
| hdmirx_wr_cor(VID_XPCLK_EN_AUD_IVCRX, data8);//register address: 0x1468 (0x50) |
| |
| data8 = 0xc; //[5:0] reg_post_val_sw |
| hdmirx_wr_cor(RX_POST_SVAL_AUD_IVCRX, data8);//register address: 0x1411 (0x0c) |
| |
| data8 = 0; |
| data8 |= (1 << 6);//[7:6] reg_fm_val_sw 0:128*fs; 1: 256*fs; 2:384*fs; 3: 512*fs |
| data8 |= (3 << 0);//[5:0] reg_fs_val_sw |
| hdmirx_wr_cor(RX_FREQ_SVAL_AUD_IVCRX, data8);//register address: 0x1402 (0x43) |
| |
| hdmirx_wr_cor(RX_UPLL_SVAL_AUD_IVCRX, 0x00);//UPLL_SVAL |
| |
| hdmirx_wr_cor(RX_AVG_WINDOW_AUD_IVCRX, 0xff);//AVG_WINDOW |
| |
| data8 |= (0 << 7); //[7] cts_dropped_auto_en |
| data8 |= (0 << 6); //[6] post_hw_sw_sel |
| data8 |= (0 << 5); //[5] upll_hw_sw_sel |
| data8 |= (0 << 4); //[4] cts_hw_sw_sel: 0=hw; 1=sw. |
| data8 |= (0 << 3); //[3] n_hw_sw_sel: 0=hw; 1=sw. |
| data8 |= (0 << 2); //[2] cts_reused_auto_en |
| data8 |= (0 << 1); //[1] fs_hw_sw_sel: 0=hw; 1=sw. |
| data8 |= (0 << 0); //[0] acr_init_wp |
| hdmirx_wr_cor(RX_ACR_CTRL1_AUD_IVCRX, data8);//register address: 0x1400 (0x7a) |
| |
| data8 = 0; |
| data8 |= (0 << 6);//[7:6] rhdmi_aud_smaple_f_extn |
| data8 |= (0 << 4);//[4] reg_fs_filter_en |
| data8 |= (0 << 0);//[3:0] rhdmi_aud_sample_f |
| hdmirx_wr_cor(RX_TCLK_FS_AUD_IVCRX, data8); //register address: 0x1417 (0x0) |
| |
| data8 = 0; |
| data8 |= (1 << 3);//[6:3] reg_cts_thresh |
| data8 |= (1 << 2);//[2] reg_mclk_loopback |
| data8 |= (0 << 1);//[1] reg_log_win_ena |
| data8 |= (0 << 0);//[0] reg_post_div2_ena |
| hdmirx_wr_cor(RX_ACR_CTRL3_AUD_IVCRX, data8);//register address: 0x1418 (0xc) |
| |
| data8 = 0; |
| data8 |= (1 << 7);//[7] reg_sd3_en |
| data8 |= (1 << 6);//[6] reg_sd2_en |
| data8 |= (1 << 5);//[5] reg_sd1_en |
| data8 |= (1 << 4);//[4] reg_sd0_en |
| data8 |= (0 << 3);//[3] reg_mclk_en |
| data8 |= (1 << 2);//[2] reg_mute_flag |
| data8 |= (0 << 1);//[1] reg_vucp |
| data8 |= (0 << 0);//[0] reg_pcm |
| hdmirx_wr_cor(RX_I2S_CTRL2_AUD_IVCRX, data8); |
| |
| data8 = 0; |
| data8 |= (3 << 6);//[7:6] reg_sd3_map |
| data8 |= (2 << 4);//[5:4] reg_sd2_map |
| data8 |= (1 << 2);//[3:2] reg_sd1_map |
| //[1:0] reg_sd0_map : 0 from FIFO#1; 1 from FIFO#2; 2:from FIFO#3; 3: from FIFO#3 |
| data8 |= (0 << 0); |
| hdmirx_wr_cor(RX_I2S_MAP_AUD_IVCRX, data8);//register address: 0x1428 (0xe4) |
| |
| hdmirx_wr_cor(RX_I2S_CTRL1_AUD_IVCRX, 0x40);//I2S_CTRL1 |
| hdmirx_wr_cor(RX_SW_OW_AUD_IVCRX, 0x00);//SW_OW |
| |
| hdmirx_wr_cor(RX_AUDO_MUTE_AUD_IVCRX, 0x00);//AUDO_MODE |
| hdmirx_wr_cor(RX_OW_15_8_AUD_IVCRX, 0x00);//OW_15_8 |
| hdmirx_wr_cor(AAC_MCLK_SEL_AUD_IVCRX, 0x80);//MCLK_SEL [5:4]=>00:128*Fs;01:256*Fs |
| |
| data8 = 0; |
| data8 |= (0 << 7);//[7] enable overwrite length ralated cbit |
| data8 |= (0 << 6);//[6] enable sine wave |
| data8 |= (1 << 5);//[5] enable hardware mute |
| data8 |= (1 << 4);//[4] pass spdif error |
| data8 |= (1 << 3);//[3] pass aud error |
| data8 |= (1 << 2);//[2] reg_i2s_mode |
| data8 |= (1 << 1);//[1] reg_spdif_mode |
| data8 |= (1 << 0);//[0] reg_spidf_en |
| hdmirx_wr_cor(RX_AUDRX_CTRL_AUD_IVCRX, data8);//AUDRX_CTRL |
| |
| data8 = 0; |
| data8 |= (1 << 1);//[1] dont_clr_sys_intr |
| hdmirx_wr_cor(AEC4_CTRL_AUD_IVCRX, data8); //AEC4 CTRL |
| |
| data8 = 0; |
| data8 |= (1 << 7);//ctl acr en |
| data8 |= (1 << 6);//aac exp sel |
| data8 |= (0 << 5);//[5] reg_aac_out_off_en |
| data8 |= (0 << 2);//[2] reserved |
| data8 |= (1 << 1);//[1] aac hw auto unmute enable |
| data8 |= (1 << 0);//[0] aac hw auto mute enable |
| hdmirx_wr_cor(AEC0_CTRL_AUD_IVCRX, data8); //AEC0 CTRL |
| |
| data8 = 0; |
| data8 |= (0 << 7);//[7] H resoslution change |
| data8 |= (0 << 6);//[6] polarity change |
| data8 |= (0 << 5);//[5] change of interlaced |
| data8 |= (0 << 4);//[4] change of the FS |
| data8 |= (0 << 3);//[3] CTS reused |
| data8 |= (0 << 2);//[2] audio fifo overrun |
| data8 |= (0 << 1);//[1] audio fifo underrun |
| data8 |= (0 << 0);//[0] hdmi mode |
| hdmirx_wr_cor(RX_AEC_EN2_AUD_IVCRX, data8);//RX_AEC_EN2 |
| |
| data8 = 0; |
| //if(rx_hbr_sel_i2s_spdif == 1){ //hbr_i2s |
| //data8 |= (0 << 4);} |
| //else if(rx_hbr_sel_i2s_spdif == 2){ //hbr_spdif |
| //data8 |= (0 << 4);} |
| //else{ //not hbr |
| data8 |= (1 << 4); |
| //} |
| hdmirx_wr_cor(RX_3D_SW_OW2_AUD_IVCRX, data8);//duplicate |
| |
| //====================================== |
| // HDCP 1.X Config ---- RX |
| //====================================== |
| hdmirx_wr_cor(RX_SYS_SWTCHC_AON_IVCRX, 0x86);//SYS_SWTCHC,Enable HDCP DDC,SCDC DDC |
| |
| //----initial KSV list-------- |
| //for(i=0;i<5;i++) //ksv list number |
| //{ |
| //for(j=0;j<5;j++) //40bit ksv 5 byte write |
| //{ |
| //register address: 0x16a8 |
| //hdmirx_wr_cor(RX_KSV_FIFO_HDCP1X_IVCRX,SampleKSVList[i*5+j]); |
| //} |
| //} |
| |
| //----clear ksv fifo rdy -------- |
| data8 = 0; |
| data8 |= (1 << 3);//bit[ 3] reg_hdmi_clr_en |
| data8 |= (7 << 0);//bit[2:0] reg_fifordy_clr_en |
| hdmirx_wr_cor(RX_RPT_RDY_CTRL_PWD_IVCRX, data8);//register address: 0x1010 (0x0f) |
| |
| //----BCAPS config----- |
| data8 = 0; |
| data8 |= (0 << 4);//bit[4] reg_fast I2C transfers speed. |
| data8 |= (0 << 5);//bit[5] reg_fifo_rdy |
| data8 |= (0 << 6);//bit[6] reg_repeater Rx Repeater |
| data8 |= (1 << 7);//bit[7] reg_hdmi_capable HDMI capable |
| hdmirx_wr_cor(RX_BCAPS_SET_HDCP1X_IVCRX, data8);//register address: 0x169e (0x80) |
| |
| //----BCAPS1 config----- |
| data8 = 0; |
| data8 |= (0 << 0);//bit[6:0] reg_dve_cnt |
| data8 |= (0 << 7);//bit[ 7] reg_dve_exceed |
| hdmirx_wr_cor(RX_SHD_BSTATUS1_HDCP1X_IVCRX, data8);//register address: 0x169f (0x00) |
| |
| //----Rx Sha length in bytes---- |
| //hdmirx_wr_cor(RX_SHA_length1_HDCP1X_IVCRX, 0x0a);//[7:0] 10=2ksv*5byte |
| //hdmirx_wr_cor(RX_SHA_length2_HDCP1X_IVCRX, 0x00);//[9:8] |
| |
| //----Rx Sha repeater KSV fifo start addr---- |
| //hdmirx_wr_cor(RX_KSV_SHA_start1_HDCP1X_IVCRX, 0x00);//[7:0] |
| //hdmirx_wr_cor(RX_KSV_SHA_start2_HDCP1X_IVCRX, 0x00);//[9:8] |
| hdmirx_wr_cor(RX_PWD_SRST_PWD_IVCRX, 0x12);//SRST = 1 |
| /* BIT0 AUTO RST AUD FIFO when fifo err */ |
| hdmirx_wr_cor(RX_PWD_SRST_PWD_IVCRX, 0x01);//SRST = 0 |
| |
| /* TDM cfg */ |
| hdmirx_wr_cor(RX_TDM_CTRL1_AUD_IVCRX, 0x00); |
| hdmirx_wr_cor(RX_TDM_CTRL2_AUD_IVCRX, 0x10); |
| |
| //clr gcp wr; disable hw avmute |
| hdmirx_wr_cor(DEC_AV_MUTE_DP2_IVCRX, 0x20); |
| |
| // hdcp 2x ECC detection enable mode 3 |
| hdmirx_wr_cor(HDCP2X_RX_ECC_CTRL, 3); |
| hdmirx_wr_cor(HDCP2X_RX_ECC_CONS_ERR_THR, 50); |
| hdmirx_wr_cor(HDCP2X_RX_ECC_FRM_ERR_THR_0, 0x1); |
| hdmirx_wr_cor(HDCP2X_RX_ECC_FRM_ERR_THR_1, 0x0); |
| //hdmirx_wr_cor(HDCP2X_RX_ECC_GVN_FRM_ERR_THR_2, 0xff); |
| //hdmirx_wr_cor(HDCP2X_RX_GVN_FRM, 30); |
| |
| //DPLL |
| hdmirx_wr_cor(DPLL_CFG6_DPLL_IVCRX, 0x10); |
| hdmirx_wr_cor(DPLL_HDMI2_DPLL_IVCRX, 0); |
| } |
| |
| void hdcp_init_t7(void) |
| { |
| //key config and crc check |
| //rx_sec_hdcp_cfg_t7(); |
| //hdcp config |
| hdmirx_wr_cor(RX_HPD_C_CTRL_AON_IVCRX, 0x1);//HPD |
| hdmirx_wr_cor(RX_HDCP2x_CTRL_PWD_IVCRX, 0x01);//ri_hdcp2x_en |
| //hdmirx_wr_cor(RX_INTR13_MASK_PWD_IVCRX, 0x02);// irq |
| hdmirx_wr_cor(PWD_SW_CLMP_AUE_OIF_PWD_IVCRX, 0x0); |
| //hdmirx_wr_cor(CP2PAX_CTRL_0_HDCP2X_IVCRX, 0x1);//no use |
| //hdmirx_wr_cor(CP2PAX_INTR0_MASK_HDCP2X_IVCRX, 0x3); irq |
| //hdmirx_wr_cor(RX_HDCP2x_CTRL_PWD_IVCRX, 0x1); //same as L3309 |
| //hdmirx_wr_cor(CP2PA_TP1_HDCP2X_IVCRX, 0x9e); |
| //hdmirx_wr_cor(CP2PA_TP3_HDCP2X_IVCRX, 0x32); |
| //hdmirx_wr_cor(CP2PA_TP5_HDCP2X_IVCRX, 0x32); |
| //hdmirx_wr_cor(CP2PAX_GP_IN1_HDCP2X_IVCRX, 0x2); |
| //hdmirx_wr_cor(CP2PAX_GP_CTL_HDCP2X_IVCRX, 0xdb); |
| hdmirx_wr_cor(RX_PWD_SRST2_PWD_IVCRX, 0x8); |
| hdmirx_wr_cor(RX_PWD_SRST2_PWD_IVCRX, 0x2); |
| } |
| |
| void hdmirx_hbr2spdif(u8 val) |
| { |
| /* if (rx.chip_id < CHIP_ID_T7) */ |
| return; |
| |
| if (hdmirx_rd_cor(RX_AUDP_STAT_DP2_IVCRX) & _BIT(6)) |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, _BIT(15), val); |
| else |
| hdmirx_wr_bits_top(TOP_CLK_CNTL, _BIT(15), 0); |
| } |
| |
| void hdmirx_output_en(bool en) |
| { |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| if (en) |
| hdmirx_wr_top(TOP_OVID_OVERRIDE0, 0); |
| else |
| hdmirx_wr_top(TOP_OVID_OVERRIDE0, 0x80000000); |
| } |
| |
| void hdmirx_hw_config(void) |
| { |
| rx_pr("%s port:%d\n", __func__, rx.port); |
| hdmirx_top_sw_reset(); |
| //rx_i2c_init(); |
| hdmirx_output_en(false); |
| if (rx.chip_id >= CHIP_ID_T7) { |
| cor_init(); |
| } else { |
| control_reset(); |
| rx_hdcp_init(); |
| hdmirx_audio_init(); |
| //packet_init(); |
| if (rx.chip_id != CHIP_ID_TXHD) |
| hdmirx_20_init(); |
| DWC_init(); |
| } |
| hdmirx_irq_hdcp_enable(false); |
| if (rx.chip_id >= CHIP_ID_T7) |
| hdcp_init_t7(); |
| packet_init(); |
| if (rx.chip_id >= CHIP_ID_TL1) |
| aml_phy_switch_port(); |
| hdmirx_phy_init(); |
| //if (rx.chip_id < CHIP_ID_T7) |
| //hdmirx_top_irq_en(true); |
| rx_pr("%s %d Done!\n", __func__, rx.port); |
| /* hdmi reset will cause cec not working*/ |
| /* cec modult need reset */ |
| if (rx.chip_id <= CHIP_ID_TXL) |
| cec_hw_reset(1); |
| pre_port = 0xff; |
| } |
| |
| /* |
| * hdmirx_hw_probe - hdmirx top/controller/phy init |
| */ |
| void hdmirx_hw_probe(void) |
| { |
| if (rx.chip_id < CHIP_ID_T7) |
| hdmirx_wr_top(TOP_MEM_PD, 0); |
| hdmirx_top_irq_en(false); |
| hdmirx_wr_top(TOP_SW_RESET, 0); |
| clk_init(); |
| TOP_init(); |
| hdmirx_top_sw_reset(); |
| if (rx.chip_id >= CHIP_ID_T7) { |
| cor_init(); |
| } else { |
| control_reset(); |
| DWC_init(); |
| hdcp22_clk_en(1); |
| hdmirx_audio_init(); |
| //packet_init(); |
| if (rx.chip_id != CHIP_ID_TXHD) |
| hdmirx_20_init(); |
| } |
| rx_emp_to_ddr_init(); |
| hdmi_rx_top_edid_update(); |
| if (rx.chip_id >= CHIP_ID_TL1) |
| aml_phy_switch_port(); |
| |
| /* for t5,offset_cal also did some phy & pll init operation*/ |
| /* dont need to do phy init again */ |
| if (rx.phy_ver >= PHY_VER_T5) |
| aml_phy_offset_cal(); |
| else |
| hdmirx_phy_init(); |
| if (rx.chip_id >= CHIP_ID_T7) |
| hdcp_init_t7(); |
| hdmirx_wr_top(TOP_PORT_SEL, 0x10); |
| hdmirx_wr_top(TOP_INTR_STAT_CLR, ~0); |
| //if (rx.chip_id < CHIP_ID_T7) |
| //hdmirx_top_irq_en(true); |
| rx_pr("%s Done!\n", __func__); |
| } |
| |
| /* |
| * rx_audio_pll_sw_update |
| * Sent an update pulse to audio pll module. |
| * Indicate the ACR info is changed. |
| */ |
| void rx_audio_pll_sw_update(void) |
| { |
| hdmirx_wr_bits_top(TOP_ACR_CNTL_STAT, _BIT(11), 1); |
| |
| hdmirx_wr_bits_cor(RX_PWD_SRST_PWD_IVCRX, _BIT(1), 1); |
| udelay(1); |
| hdmirx_wr_bits_cor(RX_PWD_SRST_PWD_IVCRX, _BIT(1), 0); |
| } |
| |
| /* |
| * func: rx_acr_info_update |
| * refresh aud_pll by manual N/CTS changing |
| */ |
| void rx_acr_info_sw_update(void) |
| { |
| hdmirx_wr_dwc(DWC_AUD_CLK_CTRL, 0x10); |
| udelay(100); |
| hdmirx_wr_dwc(DWC_AUD_CLK_CTRL, 0x0); |
| } |
| |
| /* |
| * is_afifo_error - audio fifo unnormal detection |
| * check if afifo block or not |
| * bit4: indicate FIFO is overflow |
| * bit3: indicate FIFO is underflow |
| * bit2: start threshold pass |
| * bit1: wr point above max threshold |
| * bit0: wr point below mix threshold |
| * |
| * return true if afifo under/over flow, false otherwise. |
| */ |
| bool is_afifo_error(void) |
| { |
| bool ret = false; |
| |
| if ((hdmirx_rd_dwc(DWC_AUD_FIFO_STS) & |
| (OVERFL_STS | UNDERFL_STS)) != 0) { |
| ret = true; |
| if (log_level & AUDIO_LOG) |
| rx_pr("afifo err\n"); |
| } |
| return ret; |
| } |
| |
| /* |
| * is_aud_pll_error - audio clock range detection |
| * noraml mode: aud_pll = aud_sample_rate * 128 |
| * HBR: aud_pll = aud_sample_rate * 128 * 4 |
| * |
| * return true if audio clock is in range, false otherwise. |
| */ |
| bool is_aud_pll_error(void) |
| { |
| bool ret = true; |
| u32 clk = rx.aud_info.aud_clk; |
| u32 aud_128fs = rx.aud_info.real_sr * 128; |
| u32 aud_512fs = rx.aud_info.real_sr * 512; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| return false; |
| if (rx.aud_info.real_sr == 0) |
| return false; |
| if (abs(clk - aud_128fs) < AUD_PLL_THRESHOLD || |
| abs(clk - aud_512fs) < AUD_PLL_THRESHOLD) |
| ret = false; |
| if ((ret) && (log_level & AUDIO_LOG)) |
| rx_pr("clk:%d,128fs:%d,512fs:%d,\n", clk, aud_128fs, aud_512fs); |
| return ret; |
| } |
| |
| void rx_aud_fifo_rst(void) |
| { |
| //u8 tmp; |
| |
| hdmirx_wr_bits_cor(RX_PWD_SRST_PWD_IVCRX, _BIT(1), 1); |
| udelay(1); |
| hdmirx_wr_bits_cor(RX_PWD_SRST_PWD_IVCRX, _BIT(1), 0); |
| //tmp = rd_reg_clk_ctl(RX_CLK_CTRL2); |
| //tmp &= ~(1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| //wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| //udelay(2); |
| //tmp |= (1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| //wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| //if (log_level & AUDIO_LOG) |
| //rx_pr("aud pll rst\n"); |
| } |
| |
| /* |
| * rx_aud_pll_ctl - audio pll config |
| */ |
| void rx_aud_pll_ctl(bool en) |
| { |
| int tmp = 0; |
| /*unsigned int od, od2;*/ |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| if (rx.chip_id == CHIP_ID_T7) { |
| if (en) { |
| tmp = rd_reg_clk_ctl(RX_CLK_CTRL2); |
| tmp |= (1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| /* AUD_CLK=N/CTS*TMDS_CLK */ |
| hdmirx_wr_amlphy(HHI_AUD_PLL_CNTL_T7, 0x40001540); |
| /* use mpll */ |
| tmp = 0; |
| tmp |= 2 << 2; /* 0:tmds_clk 1:ref_clk 2:mpll_clk */ |
| hdmirx_wr_amlphy(HHI_AUD_PLL_CNTL2_T7, tmp); |
| /* cntl3 2:0 000=1*cts 001=2*cts 010=4*cts 011=8*cts */ |
| hdmirx_wr_amlphy(HHI_AUD_PLL_CNTL3_T7, rx.phy.aud_div); |
| if (log_level & AUDIO_LOG) |
| rx_pr("aud div=%d\n", rd_reg_hhi(HHI_AUD_PLL_CNTL3)); |
| hdmirx_wr_amlphy(HHI_AUD_PLL_CNTL_T7, 0x60001540); |
| if (log_level & AUDIO_LOG) |
| rx_pr("audio pll lock:0x%x\n", |
| hdmirx_rd_amlphy(HHI_AUD_PLL_CNTL_I_T7)); |
| rx_audio_pll_sw_update(); |
| } else { |
| /* disable pll, into reset mode */ |
| hdmirx_wr_amlphy(HHI_AUD_PLL_CNTL_T7, 0x0); |
| tmp = rd_reg_clk_ctl(RX_CLK_CTRL2); |
| tmp &= ~(1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| } |
| } else if (rx.chip_id == CHIP_ID_T3) { |
| if (en) { |
| tmp = rd_reg_clk_ctl(RX_CLK_CTRL2); |
| tmp |= (1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| /* AUD_CLK=N/CTS*TMDS_CLK */ |
| wr_reg_ana_ctl(ANACTL_AUD_PLL_CNTL, 0x40001540); |
| /* use mpll */ |
| tmp = 0; |
| tmp |= 2 << 2; /* 0:tmds_clk 1:ref_clk 2:mpll_clk */ |
| wr_reg_ana_ctl(ANACTL_AUD_PLL_CNTL2, tmp); |
| /* cntl3 2:0 000=1*cts 001=2*cts 010=4*cts 011=8*cts */ |
| wr_reg_ana_ctl(ANACTL_AUD_PLL_CNTL3, rx.phy.aud_div); |
| if (log_level & AUDIO_LOG) |
| rx_pr("aud div=%d\n", rd_reg_ana_ctl(ANACTL_AUD_PLL_CNTL3)); |
| wr_reg_ana_ctl(ANACTL_AUD_PLL_CNTL, 0x60001540); |
| if (log_level & AUDIO_LOG) |
| /* t3 audio pll lock bit: top reg acr_cntl_stat bit'31 */ |
| rx_pr("audio pll lock:0x%x\n", |
| (hdmirx_rd_top(TOP_ACR_CNTL_STAT) >> 31)); |
| rx_audio_pll_sw_update(); |
| } else { |
| /* disable pll, into reset mode */ |
| wr_reg_ana_ctl(ANACTL_AUD_PLL_CNTL, 0x0); |
| tmp = rd_reg_clk_ctl(RX_CLK_CTRL2); |
| tmp &= ~(1 << 8);// [ 8] clk_en for cts_hdmirx_aud_pll_clk |
| wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| } |
| } else if (rx.chip_id == CHIP_ID_T5W) { |
| if (en) { |
| tmp = rd_reg_clk_ctl(RX_CLK_CTRL2_T5W); |
| /* [ 8] clk_en for cts_hdmirx_aud_pll_clk */ |
| tmp |= (1 << 8); |
| wr_reg_clk_ctl(RX_CLK_CTRL2_T5W, tmp); |
| /* AUD_CLK=N/CTS*TMDS_CLK */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x40001540); |
| /* use mpll */ |
| tmp = 0; |
| /* 0:tmds_clk 1:ref_clk 2:mpll_clk */ |
| tmp |= 2 << 2; |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, tmp); |
| /* cntl3 2:0 0=1*cts 1=2*cts */ |
| /* 010=4*cts 011=8*cts */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, rx.phy.aud_div); |
| if (log_level & AUDIO_LOG) |
| rx_pr("aud div=%d\n", |
| rd_reg_hhi(ANACTL_AUD_PLL_CNTL3)); |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x60001540); |
| if (log_level & AUDIO_LOG) { |
| /* pll lock bit:*/ |
| /*top reg acr_cntl_stat bit'31 */ |
| tmp = hdmirx_rd_top(TOP_ACR_CNTL_STAT); |
| rx_pr("apll lock:0x%x\n", (tmp >> 31)); |
| } |
| rx_audio_pll_sw_update(); |
| } else { |
| /* disable pll, into reset mode */ |
| wr_reg_ana_ctl(ANACTL_AUD_PLL_CNTL, 0x0); |
| tmp = rd_reg_clk_ctl(RX_CLK_CTRL2); |
| /* [ 8] clk_en for cts_hdmirx_aud_pll_clk */ |
| tmp &= ~(1 << 8); |
| wr_reg_clk_ctl(RX_CLK_CTRL2, tmp); |
| } |
| } else { |
| if (en) { |
| /* AUD_CLK=N/CTS*TMDS_CLK */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x40001540); |
| /* use mpll */ |
| tmp = 0; |
| tmp |= 2 << 2; /* 0:tmds_clk 1:ref_clk 2:mpll_clk */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL2, tmp); |
| /* cntl3 2:0 000=1*cts 001=2*cts 010=4*cts 011=8*cts */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL3, rx.phy.aud_div); |
| |
| if (log_level & AUDIO_LOG) |
| rx_pr("aud div=%d\n", rd_reg_hhi(HHI_AUD_PLL_CNTL3)); |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x60001540); |
| if (log_level & AUDIO_LOG) |
| rx_pr("audio pll lock:0x%x\n", |
| rd_reg_hhi(HHI_AUD_PLL_CNTL_I)); |
| /*rx_audio_pll_sw_update();*/ |
| } else { |
| /* disable pll, into reset mode */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x0); |
| } |
| } |
| } else { |
| if (en) { |
| rx_audio_bandgap_en(); |
| tmp = hdmirx_rd_phy(PHY_MAINFSM_STATUS1); |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x20000000); |
| /* audio pll div depends on input freq */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL6, (tmp >> 9 & 3) << 28); |
| /* audio pll div fixed to N/CTS as below*/ |
| /* wr_reg_hhi(HHI_AUD_PLL_CNTL6, 0x40000000); */ |
| wr_reg_hhi(HHI_AUD_PLL_CNTL5, 0x0000002e); |
| wr_reg_hhi(HHI_AUD_PLL_CNTL4, 0x30000000); |
| wr_reg_hhi(HHI_AUD_PLL_CNTL3, 0x00000000); |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x40000000); |
| wr_reg_hhi(HHI_ADC_PLL_CNTL4, 0x805); |
| rx_audio_pll_sw_update(); |
| /*External_Mute(0);*/ |
| } else { |
| wr_reg_hhi(HHI_AUD_PLL_CNTL, 0x20000000); |
| } |
| } |
| } |
| |
| void rx_get_vtem_info(void) |
| { |
| u8 tmp; |
| |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| if (rx.vrr_en) { |
| tmp = hdmirx_rd_cor(RX_VT_EMP_DBYTE0_DP0B_IVCRX); |
| rx.vtem_info.vrr_en = tmp & 1; |
| rx.vtem_info.m_const = (tmp >> 1) & 1; |
| rx.vtem_info.fva_factor_m1 = (tmp >> 4) & 0x0f; |
| tmp = hdmirx_rd_cor(RX_VT_EMP_DBYTE1_DP0B_IVCRX); |
| rx.vtem_info.base_vfront = tmp; |
| tmp = hdmirx_rd_cor(RX_VT_EMP_DBYTE2_DP0B_IVCRX); |
| rx.vtem_info.rb = (tmp > 2) & 1; |
| rx.vtem_info.base_framerate = hdmirx_rd_cor(RX_VT_EMP_DBYTE3_DP0B_IVCRX); |
| rx.vtem_info.base_framerate |= (tmp & 3) << 8; |
| } else { |
| rx.vtem_info.vrr_en = 0; |
| rx.vtem_info.m_const = 0; |
| rx.vtem_info.fva_factor_m1 = 0; |
| rx.vtem_info.base_vfront = 0; |
| rx.vtem_info.rb = 0; |
| rx.vtem_info.base_framerate = 0; |
| } |
| } |
| |
| unsigned char rx_get_hdcp14_sts(void) |
| { |
| return (unsigned char)((hdmirx_rd_dwc(DWC_HDCP_STS) >> 8) & 3); |
| } |
| |
| /* |
| * rx_get_video_info - get current avi info |
| */ |
| bool rx_get_dvi_mode(void) |
| { |
| u32 ret; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| ret = hdmirx_rd_cor(RX_AUDP_STAT_DP2_IVCRX) & 1; |
| else |
| ret = !hdmirx_rd_bits_dwc(DWC_PDEC_STS, DVIDET); |
| if (ret) |
| return false; |
| else |
| return true; |
| } |
| |
| u8 rx_get_hdcp_type(void) |
| { |
| u32 tmp; |
| u8 data_dec, data_auth; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| data_auth = hdmirx_rd_cor(CP2PAX_AUTH_STAT_HDCP2X_IVCRX); |
| data_dec = hdmirx_rd_cor(RX_HDCP_STATUS_PWD_IVCRX); |
| rx.cur.hdcp14_state = (hdmirx_rd_cor(RX_HDCP_STAT_HDCP1X_IVCRX) >> 4) & 3; |
| rx.cur.hdcp22_state = ((data_dec & 1) << 1) | (data_auth & 1); |
| if ((rx.cur.hdcp22_state & 3) && rx.cur.hdcp14_state == 0) |
| rx.hdcp.hdcp_version = HDCP_VER_22; |
| else if (rx.cur.hdcp14_state == 3 && rx.cur.hdcp22_state == 0) |
| rx.hdcp.hdcp_version = HDCP_VER_14; |
| else |
| rx.hdcp.hdcp_version = HDCP_VER_NONE; |
| } else { |
| if (hdcp22_on) { |
| tmp = hdmirx_rd_dwc(DWC_HDCP22_STATUS); |
| rx.cur.hdcp_type = (tmp >> 4) & 1; |
| rx.cur.hdcp22_state = tmp & 1; |
| } |
| if (!rx.cur.hdcp_type) |
| rx.cur.hdcp14_state = (hdmirx_rd_dwc(DWC_HDCP_STS) >> 8) & 3; |
| } |
| return 1; |
| } |
| |
| void rx_get_avi_params(void) |
| { |
| u8 data8, data8_lo, data8_up; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| /*byte 1*/ |
| data8 = hdmirx_rd_cor(AVIRX_DBYTE1_DP2_IVCRX); |
| /*byte1:bit[7:5]*/ |
| rx.cur.colorspace = (data8 >> 5) & 0x07; |
| /*byte 1 bit'4*/ |
| rx.cur.active_valid = (data8 >> 4) & 0x01; |
| /*byte1:bit[3:2]*/ |
| rx.cur.bar_valid = (data8 >> 2) & 0x03; |
| |
| /*byte1:bit[1:0]*/ |
| rx.cur.scan_info = data8 & 0x3; |
| |
| /*byte 2*/ |
| data8 = hdmirx_rd_cor(AVIRX_DBYTE2_DP2_IVCRX); |
| /*byte1:bit[7:6]*/ |
| rx.cur.colorimetry = (data8 >> 6) & 0x3; |
| /*byte1:bit[5:4]*/ |
| rx.cur.picture_ratio = (data8 >> 4) & 0x3; |
| /*byte1:bit[3:0]*/ |
| rx.cur.active_ratio = data8 & 0xf; |
| |
| /*byte 3*/ |
| data8 = hdmirx_rd_cor(AVIRX_DBYTE3_DP2_IVCRX); |
| /* byte3 bit'7 */ |
| rx.cur.it_content = (data8 >> 7) & 0x1; |
| /* byte3 bit[6:4] */ |
| rx.cur.ext_colorimetry = (data8 >> 4) & 0x7; |
| /* byte3 bit[3:2]*/ |
| rx.cur.rgb_quant_range = (data8 >> 2) & 0x3; |
| /* byte3 bit[1:0]*/ |
| rx.cur.n_uniform_scale = data8 & 0x3; |
| |
| /*byte 4*/ |
| rx.cur.hw_vic = hdmirx_rd_cor(AVIRX_DBYTE4_DP2_IVCRX); |
| |
| /*byte 5*/ |
| data8 = hdmirx_rd_cor(AVIRX_DBYTE5_DP2_IVCRX); |
| /*byte5:bit[7:6]*/ |
| rx.cur.yuv_quant_range = (data8 >> 6) & 0x3; |
| /*byte5:bit[5:4]*/ |
| rx.cur.cn_type = (data8 >> 4) & 0x3; |
| /*byte5:bit[3:0]*/ |
| rx.cur.repeat = data8 & 0xf; |
| |
| /* byte [9:6]*/ |
| if (rx.cur.bar_valid == 3) { |
| data8_lo = hdmirx_rd_cor(AVIRX_DBYTE6_DP2_IVCRX); |
| data8_up = hdmirx_rd_cor(AVIRX_DBYTE7_DP2_IVCRX); |
| rx.cur.bar_end_top = (data8_lo | (data8_up << 8)); |
| data8_lo = hdmirx_rd_cor(AVIRX_DBYTE8_DP2_IVCRX); |
| data8_up = hdmirx_rd_cor(AVIRX_DBYTE9_DP2_IVCRX); |
| rx.cur.bar_start_bottom = (data8_lo | (data8_up << 8)); |
| data8_lo = hdmirx_rd_cor(AVIRX_DBYTE10_DP2_IVCRX); |
| data8_up = hdmirx_rd_cor(AVIRX_DBYTE11_DP2_IVCRX); |
| rx.cur.bar_end_left = (data8_lo | (data8_up << 8)); |
| data8_lo = hdmirx_rd_cor(AVIRX_DBYTE12_DP2_IVCRX); |
| data8_up = hdmirx_rd_cor(AVIRX_DBYTE13_DP2_IVCRX); |
| rx.cur.bar_start_right = (data8_lo | (data8_up << 8)); |
| } |
| } else { |
| 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 = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, VIDEO_FORMAT); |
| rx.cur.it_content = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, IT_CONTENT); |
| rx.cur.rgb_quant_range = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, RGB_QUANT_RANGE); |
| rx.cur.yuv_quant_range = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_HB, YUV_QUANT_RANGE); |
| rx.cur.scan_info = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, SCAN_INFO); |
| rx.cur.n_uniform_scale = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, NON_UNIF_SCALE); |
| rx.cur.ext_colorimetry = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, EXT_COLORIMETRY); |
| rx.cur.active_ratio = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, ACT_ASPECT_RATIO); |
| rx.cur.active_valid = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, ACT_INFO_PRESENT); |
| rx.cur.bar_valid = hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, BAR_INFO_VALID); |
| if (rx.cur.bar_valid == 3) { |
| rx.cur.bar_end_top = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AVI_TBB, LIN_END_TOP_BAR); |
| rx.cur.bar_start_bottom = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AVI_TBB, LIN_ST_BOT_BAR); |
| rx.cur.bar_end_left = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AVI_LRB, PIX_END_LEF_BAR); |
| rx.cur.bar_start_right = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AVI_LRB, PIX_ST_RIG_BAR); |
| } |
| rx.cur.colorimetry = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, COLORIMETRY); |
| rx.cur.picture_ratio = |
| hdmirx_rd_bits_dwc(DWC_PDEC_AVI_PB, PIC_ASPECT_RATIO); |
| } |
| } |
| |
| void rx_get_colordepth(void) |
| { |
| u8 tmp; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| tmp = hdmirx_rd_cor(COR_VININ_STS); |
| else |
| tmp = hdmirx_rd_bits_dwc(DWC_HDMI_STS, DCM_CURRENT_MODE); |
| switch (tmp) { |
| case DCM_CURRENT_MODE_48b: |
| rx.cur.colordepth = E_COLORDEPTH_16; |
| break; |
| case DCM_CURRENT_MODE_36b: |
| rx.cur.colordepth = E_COLORDEPTH_12; |
| break; |
| case DCM_CURRENT_MODE_30b: |
| rx.cur.colordepth = E_COLORDEPTH_10; |
| break; |
| default: |
| rx.cur.colordepth = E_COLORDEPTH_8; |
| break; |
| } |
| } |
| |
| void rx_get_framerate(void) |
| { |
| u32 tmp; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| tmp = (hdmirx_rd_cor(COR_FRAME_RATE_HI) << 16) | |
| (hdmirx_rd_cor(COR_FRAME_RATE_MI) << 8) | |
| (hdmirx_rd_cor(COR_FRAME_RATE_LO)); |
| if (tmp == 0) |
| rx.cur.frame_rate = 0; |
| else |
| rx.cur.frame_rate = rx.clk.p_clk / (tmp / 100); |
| } else { |
| tmp = hdmirx_rd_bits_dwc(DWC_MD_VTC, VTOT_CLK); |
| if (tmp == 0) |
| rx.cur.frame_rate = 0; |
| else |
| rx.cur.frame_rate = (modet_clk * 100000) / tmp; |
| } |
| } |
| |
| void rx_get_interlaced(void) |
| { |
| u8 tmp; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| tmp = hdmirx_rd_cor(COR_FDET_STS) & _BIT(2); |
| else |
| tmp = hdmirx_rd_bits_dwc(DWC_MD_STS, ILACE); |
| |
| if (tmp) |
| rx.cur.interlaced = true; |
| else |
| rx.cur.interlaced = false; |
| } |
| |
| void rx_get_de_sts(void) |
| { |
| u32 tmp; |
| |
| if (!rx.cur.colordepth) |
| rx.cur.colordepth = 8; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| tmp = hdmirx_rd_cor(COR_PIXEL_CNT_LO) | |
| (hdmirx_rd_cor(COR_PIXEL_CNT_HI) << 8); |
| rx.cur.hactive = tmp; |
| rx.cur.vactive = hdmirx_rd_cor(COR_LINE_CNT_LO) | |
| (hdmirx_rd_cor(COR_LINE_CNT_HI) << 8); |
| rx.cur.htotal = (hdmirx_rd_cor(COR_HSYNC_LOW_COUNT_LO) | |
| (hdmirx_rd_cor(COR_HSYNC_LOW_COUNT_HI) << 8)) + |
| (hdmirx_rd_cor(COR_HSYNC_HIGH_COUNT_LO) | |
| (hdmirx_rd_cor(COR_HSYNC_HIGH_COUNT_HI) << 8)); |
| rx.cur.vtotal = (hdmirx_rd_cor(COR_VSYNC_LOW_COUNT_LO) | |
| (hdmirx_rd_cor(COR_VSYNC_LOW_COUNT_HI) << 8)) + |
| (hdmirx_rd_cor(COR_VSYNC_HIGH_COUNT_LO) | |
| (hdmirx_rd_cor(COR_VSYNC_HIGH_COUNT_HI) << 8)); |
| } else { |
| rx.cur.vactive = hdmirx_rd_bits_dwc(DWC_MD_VAL, VACT_LIN); |
| rx.cur.vtotal = hdmirx_rd_bits_dwc(DWC_MD_VTL, VTOT_LIN); |
| rx.cur.hactive = hdmirx_rd_bits_dwc(DWC_MD_HACT_PX, HACT_PIX); |
| rx.cur.htotal = hdmirx_rd_bits_dwc(DWC_MD_HT1, HTOT_PIX); |
| rx.cur.hactive = rx.cur.hactive / rx.cur.colordepth * 8; |
| rx.cur.htotal = rx.cur.htotal / rx.cur.colordepth * 8; |
| } |
| } |
| |
| /* |
| * rx_get_video_info - get current avi info |
| */ |
| void rx_get_video_info(void) |
| { |
| /* DVI mode */ |
| rx.cur.hw_dvi = rx_get_dvi_mode(); |
| /* HDCP sts*/ |
| rx_get_hdcp_type(); |
| /* AVI parameters */ |
| rx_get_avi_params(); |
| /* frame rate */ |
| rx_get_framerate(); |
| /* deep color mode */ |
| rx_get_colordepth(); |
| /* pixel clock */ |
| /*rx.cur.pixel_clk = rx.clk.pixel_clk / rx.cur.colordepth * 8;*/ |
| /* image parameters */ |
| rx_get_de_sts(); |
| /* interlace */ |
| rx_get_interlaced(); |
| } |
| |
| /* |
| * hdmirx_set_video_mute - video mute |
| * @mute: mute enable or disable |
| */ |
| void hdmirx_set_video_mute(bool mute) |
| { |
| /* bluescreen cfg */ |
| if (rx.chip_id >= CHIP_ID_T7) { |
| /* TODO */ |
| } else { |
| if (rx.pre.colorspace == E_COLOR_RGB) { |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH2, MSK(16, 0), 0x00); |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH_0_1, MSK(16, 0), 0x00); |
| } else if (rx.pre.colorspace == E_COLOR_YUV420) { |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH2, MSK(16, 0), 0x1000); |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH_0_1, MSK(16, 0), 0x8000); |
| } else { |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH2, MSK(16, 0), 0x8000); |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH_0_1, MSK(16, 0), 0x8000); |
| } |
| hdmirx_wr_bits_dwc(DWC_HDMI_VM_CFG_CH2, _BIT(16), mute); |
| } |
| } |
| |
| void set_dv_ll_mode(bool en) |
| { |
| if (en) { |
| hdmirx_wr_bits_top(TOP_VID_CNTL, _BIT(17), 1); |
| hdmirx_wr_bits_top(TOP_VID_CNTL, _BIT(19), 1); |
| } else { |
| hdmirx_wr_bits_top(TOP_VID_CNTL, _BIT(17), 0); |
| hdmirx_wr_bits_top(TOP_VID_CNTL, _BIT(19), 0); |
| } |
| } |
| |
| /* |
| * hdmirx_config_video - video mute config |
| */ |
| void hdmirx_config_video(void) |
| { |
| u32 data32 = 0; |
| u32 temp = 0; |
| u8 data8; |
| |
| int reg_clk_vp_core_div, reg_clk_vp_out_div; |
| if (dbg_cs & 0x10) |
| temp = dbg_cs & 0x0f; |
| else |
| temp = rx.pre.colorspace; |
| |
| hdmirx_set_video_mute(0); |
| set_dv_ll_mode(false); |
| |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| |
| switch (temp) { |
| case E_COLOR_YUV422: |
| data32 |= 3 << 9; |
| data32 |= 3 << 6; |
| data32 |= 3 << 3; |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX, data32 & 0xff); |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX + 1, (data32 >> 8) & 0xff); |
| data32 = hdmirx_rd_top(TOP_VID_CNTL); |
| data32 &= (~(0x7 << 24)); |
| data32 |= 1 << 24; |
| hdmirx_wr_top(TOP_VID_CNTL, data32); |
| break; |
| case E_COLOR_YUV420: |
| case E_COLOR_RGB: |
| data32 |= 2 << 9; |
| data32 |= 1 << 6; |
| data32 |= 0 << 3; |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX, data32 & 0xff); |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX + 1, (data32 >> 8) & 0xff); |
| data32 = hdmirx_rd_top(TOP_VID_CNTL); |
| data32 &= (~(0x7 << 24)); |
| data32 |= 0 << 24; |
| hdmirx_wr_top(TOP_VID_CNTL, data32); |
| break; |
| case E_COLOR_YUV444: |
| default: |
| data32 |= 2 << 9; |
| data32 |= 1 << 6; |
| data32 |= 0 << 3; |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX, data32 & 0xff); |
| hdmirx_wr_cor(VP_INPUT_MAPPING_VID_IVCRX + 1, (data32 >> 8) & 0xff); |
| data32 = hdmirx_rd_top(TOP_VID_CNTL); |
| data32 &= (~(0x7 << 24)); |
| data32 |= 2 << 24; |
| hdmirx_wr_top(TOP_VID_CNTL, data32); |
| break; |
| } |
| |
| if (rx.chip_id == CHIP_ID_T7) { |
| /* repeatition config */ |
| switch (rx.cur.repeat) { |
| case 1: |
| reg_clk_vp_core_div = 3; |
| reg_clk_vp_out_div = 1; |
| break; |
| case 3: |
| reg_clk_vp_core_div = 7; |
| reg_clk_vp_out_div = 3; |
| break; |
| default: |
| reg_clk_vp_core_div = 1; |
| reg_clk_vp_out_div = 0; |
| break; |
| } |
| data8 = hdmirx_rd_cor(RX_PWD0_CLK_DIV_0); |
| data8 &= (~0x3f); |
| //[5:3] divides the vpc out clock |
| data8 |= (reg_clk_vp_out_div << 3);//[5:3] divides the vpc out clock |
| //[2:0] divides the vpc core clock: |
| //0: divide by 1; 1: divide by 2; 3: divide by 4; 7: divide by 8 |
| data8 |= (reg_clk_vp_core_div << 0); |
| hdmirx_wr_cor(RX_PWD0_CLK_DIV_0, data8) ;//register address: 0x10c1 |
| |
| data8 = hdmirx_rd_cor(RX_VP_INPUT_FORMAT_HI); |
| data8 &= (~0x7); |
| data8 |= ((rx.cur.repeat & 0x3) << 0); |
| hdmirx_wr_cor(RX_VP_INPUT_FORMAT_HI, data8); |
| } |
| rx_sw_reset_t7(2); |
| hdmirx_output_en(true); |
| rx_irq_en(true); |
| hdmirx_top_irq_en(true); |
| } |
| |
| /* |
| * hdmirx_config_audio - audio channel map |
| */ |
| void hdmirx_config_audio(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T7) { |
| /* set MCLK for I2S/SPDIF */ |
| hdmirx_wr_cor(AAC_MCLK_SEL_AUD_IVCRX, 0x80); |
| hdmirx_hbr2spdif(1); |
| } else { |
| /* if audio layout bit = 1, set audio channel map |
| * according to audio speaker allocation, if layout |
| * bit = 0, use ch1 & ch2 by default. |
| */ |
| if (rx.aud_info.aud_hbr_rcv && hbr_force_8ch) { |
| hdmirx_wr_dwc(DWC_AUD_CHEXTR_CTRL, 0xff); |
| if (log_level & AUDIO_LOG) |
| rx_pr("HBR rcv, force 8ch\n"); |
| } else if (rx.aud_info.auds_layout) { |
| hdmirx_wr_bits_dwc(DWC_AUD_CHEXTR_CTRL, |
| AUD_CH_MAP_CFG, |
| rx.aud_info.auds_ch_alloc); |
| } else { |
| hdmirx_wr_bits_dwc(DWC_AUD_CHEXTR_CTRL, AUD_CH_MAP_CFG, 0); |
| } |
| } |
| } |
| |
| /* |
| * rx_get_clock: git clock from hdmi top |
| * tl1: have hdmi, cable clock |
| * other: have hdmi clock |
| */ |
| int rx_get_clock(enum measure_clk_top_e clk_src) |
| { |
| int clock = -1; |
| u32 tmp_data = 0; |
| u32 meas_cycles = 0; |
| u64 tmp_data2 = 0; |
| u64 audclk = 0; |
| |
| if (clk_src == TOP_HDMI_TMDSCLK) { |
| tmp_data = hdmirx_rd_top(TOP_METER_HDMI_STAT); |
| if (tmp_data & 0x80000000) { |
| meas_cycles = tmp_data & 0xffffff; |
| clock = (2930 * meas_cycles); |
| } |
| } else if (clk_src == TOP_HDMI_CABLECLK) { |
| if (rx.chip_id >= CHIP_ID_TL1) |
| tmp_data = hdmirx_rd_top(TOP_METER_CABLE_STAT); |
| if (tmp_data & 0x80000000) { |
| meas_cycles = tmp_data & 0xffffff; |
| clock = (2930 * meas_cycles); |
| } |
| } else if (clk_src == TOP_HDMI_AUDIOCLK) { |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| /*get audio clk*/ |
| tmp_data = hdmirx_rd_top(TOP_AUDMEAS_REF_CYCLES_STAT0); |
| tmp_data2 = hdmirx_rd_top(TOP_AUDMEAS_REF_CYCLES_STAT1); |
| audclk = ((tmp_data2 & 0xffff) << 32) | tmp_data; |
| if (tmp_data2 & (0x1 << 17)) |
| audclk = div_u64((24000 * 65536), div_u64((audclk + 1), 1000)); |
| else |
| rx_pr("audio clk measure fail\n"); |
| } |
| clock = audclk; |
| } else { |
| tmp_data = 0; |
| } |
| |
| /*reset hdmi,cable clk meter*/ |
| hdmirx_wr_top(TOP_SW_RESET, 0x60); |
| hdmirx_wr_top(TOP_SW_RESET, 0x0); |
| return clock; |
| } |
| |
| void rx_clkmsr_monitor(void) |
| { |
| schedule_work(&clkmsr_dwork); |
| } |
| |
| void rx_clkmsr_handler(struct work_struct *work) |
| { |
| switch (rx.chip_id) { |
| case CHIP_ID_T5W: |
| rx.clk.cable_clk = meson_clk_measure_with_precision(30, 32); |
| rx.clk.tmds_clk = meson_clk_measure_with_precision(63, 32); |
| rx.clk.aud_pll = meson_clk_measure_with_precision(74, 32); |
| /* renamed to clk81_hdmirx_pclk,id=7 */ |
| rx.clk.p_clk = meson_clk_measure_with_precision(7, 32); |
| break; |
| case CHIP_ID_T7: |
| case CHIP_ID_T3: |
| /* to decrease cpu loading of clk_msr work queue */ |
| /* 64: clk_msr resample time 32us,previous setting is 640us */ |
| rx.clk.cable_clk = meson_clk_measure_with_precision(44, 32); |
| rx.clk.tmds_clk = meson_clk_measure_with_precision(43, 32); |
| rx.clk.aud_pll = meson_clk_measure_with_precision(104, 32); |
| rx.clk.p_clk = meson_clk_measure_with_precision(0, 32); |
| break; |
| case CHIP_ID_T5: |
| case CHIP_ID_T5D: |
| case CHIP_ID_TM2: |
| case CHIP_ID_TL1: |
| rx.clk.cable_clk = meson_clk_measure_with_precision(30, 32); |
| rx.clk.tmds_clk = meson_clk_measure_with_precision(63, 32); |
| rx.clk.aud_pll = meson_clk_measure_with_precision(104, 32); |
| rx.clk.pixel_clk = meson_clk_measure_with_precision(29, 32); |
| break; |
| default: |
| rx.clk.aud_pll = meson_clk_measure_with_precision(24, 32); |
| rx.clk.pixel_clk = meson_clk_measure_with_precision(29, 32); |
| rx.clk.tmds_clk = meson_clk_measure_with_precision(25, 32); |
| if (rx.clk.tmds_clk == 0) { |
| rx.clk.tmds_clk = |
| hdmirx_rd_dwc(DWC_HDMI_CKM_RESULT) & 0xffff; |
| rx.clk.tmds_clk = |
| rx.clk.tmds_clk * 158000 / 4095 * 1000; |
| } |
| if (rx.state == FSM_SIG_READY) |
| /* phy request clk */ |
| rx.clk.mpll_clk = |
| meson_clk_measure_with_precision(27, 32); |
| break; |
| } |
| } |
| |
| /* |
| * function - get clk related with hdmirx |
| */ |
| unsigned int rx_measure_clock(enum measure_clk_src_e clksrc) |
| { |
| unsigned int clock = 0; |
| |
| /* from clock measure: txlx_clk_measure |
| * cable [x] need read from hdmitop |
| * tmds clock [25] Hdmirx_tmds_clk |
| * pixel clock [29] Hdmirx_pix_clk |
| * audio clock [24] Hdmirx_aud_pll_clk |
| * cts audio [98] cts_hdmirx_aud_pll_clk |
| * mpll clock [27] Hdmirx_mpll_div_clk |
| * esm clock [68] Cts_hdcp22_esm |
| */ |
| |
| /* from clock measure: tl1_table |
| * cable clock [30] hdmirx_cable_clk |
| * tmds clock [63] hdmirx_tmds_clk |
| * pixel clock [29] hdmirx_apll_clk_out_div |
| * audio clock [74] hdmirx_aud_pll_clk |
| * cts audio [60] cts_hdmirx_aud_pll_clk |
| * mpll clock [67] hdmirx_apll_clk_audio |
| * esm clock [68] Cts_hdcp22_esm |
| */ |
| |
| /* from clock measure: t7_table |
| * cable clock [44] hdmirx_cable_clk |
| * tmds clock [43] hdmirx_tmds_clk |
| * pixel clock [29] hdmirx_apll_clk_out_div |
| * audio clock [74] hdmirx_aud_pll_clk |
| * cts audio [60] cts_hdmirx_aud_pll_clk |
| * mpll clock [67] hdmirx_apll_clk_audio |
| * esm clock [68] Cts_hdcp22_esm |
| */ |
| if (clksrc == MEASURE_CLK_CABLE) { |
| if (rx.chip_id >= CHIP_ID_TL1 && |
| rx.chip_id <= CHIP_ID_T5D) { |
| clock = meson_clk_measure(30); |
| /*clock = rx_get_clock(TOP_HDMI_CABLECLK);*/ |
| } else if (rx.chip_id >= CHIP_ID_T7) { |
| clock = meson_clk_measure(44); |
| /*clock = rx_get_clock(TOP_HDMI_CABLECLK);*/ |
| } |
| } else if (clksrc == MEASURE_CLK_TMDS) { |
| if (rx.chip_id >= CHIP_ID_TL1 && |
| rx.chip_id <= CHIP_ID_T5D) { |
| clock = meson_clk_measure(63); |
| } else if (rx.chip_id >= CHIP_ID_T7) { |
| clock = meson_clk_measure(43); |
| } else { |
| clock = meson_clk_measure(25); |
| if (clock == 0) { |
| clock = hdmirx_rd_dwc(DWC_HDMI_CKM_RESULT) & 0xffff; |
| clock = clock * 158000 / 4095 * 1000; |
| } |
| } |
| } else if (clksrc == MEASURE_CLK_PIXEL) { |
| if (rx.chip_id >= CHIP_ID_T7) |
| clock = 1; |
| else |
| clock = meson_clk_measure(29); |
| } else if (clksrc == MEASURE_CLK_AUD_PLL) { |
| if (rx.chip_id >= CHIP_ID_TL1) |
| clock = meson_clk_measure(104);/*audio vid out*/ |
| else |
| clock = meson_clk_measure(24); |
| } else if (clksrc == MEASURE_CLK_AUD_DIV) { |
| if (rx.chip_id >= CHIP_ID_TL1) |
| clock = meson_clk_measure(67);/*apll_clk_audio*/ |
| else |
| clock = meson_clk_measure(98); |
| |
| } else if (clksrc == MEASURE_CLK_MPLL) { |
| if (rx.chip_id >= CHIP_ID_TL1) |
| clock = 2;//meson_clk_measure(29);/*apll_clk_out_div*/ |
| else |
| clock = meson_clk_measure(27); |
| } else if (clksrc == MEASURE_CLK_PCLK) { |
| clock = meson_clk_measure(0); |
| } |
| return clock; |
| } |
| |
| void rx_earc_hpd_handler(struct work_struct *work) |
| { |
| cancel_delayed_work(&eq_dwork); |
| rx_set_port_hpd(rx.arc_port, 0); |
| usleep_range(150000, 200000); |
| rx_set_port_hpd(rx.arc_port, 1); |
| } |
| |
| static const unsigned int wr_only_register[] = { |
| 0x0c, 0x3c, 0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, 0x8c, 0xa0, |
| 0xac, 0xc8, 0xd8, 0xdc, 0x184, 0x188, 0x18c, 0x190, 0x194, 0x198, 0x19c, |
| 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc, 0x1c0, 0x1c4, |
| 0x1c8, 0x1cc, 0x1d0, 0x1d4, 0x1d8, 0x1dc, 0x1e0, 0x1e4, 0x1e8, 0x1ec, |
| 0x1f0, 0x1f4, 0x1f8, 0x1fc, 0x204, 0x20c, 0x210, 0x214, 0x218, 0x21c, |
| 0x220, 0x224, 0x228, 0x22c, 0x230, 0x234, 0x238, 0x268, 0x26c, 0x270, |
| 0x274, 0x278, 0x290, 0x294, 0x298, 0x29c, 0x2a8, 0x2ac, 0x2b0, 0x2b4, |
| 0x2b8, 0x2bc, 0x2d4, 0x2dc, 0x2e8, 0x2ec, 0x2f0, 0x2f4, 0x2f8, 0x2fc, |
| 0x314, 0x318, 0x328, 0x32c, 0x348, 0x34c, 0x350, 0x354, 0x358, 0x35c, |
| 0x384, 0x388, 0x38c, 0x398, 0x39c, 0x3d8, 0x3dc, 0x400, 0x404, 0x408, |
| 0x40c, 0x410, 0x414, 0x418, 0x810, 0x814, 0x818, 0x830, 0x834, 0x838, |
| 0x83c, 0x854, 0x858, 0x85c, 0xf60, 0xf64, 0xf70, 0xf74, 0xf78, 0xf7c, |
| 0xf88, 0xf8c, 0xf90, 0xf94, 0xfa0, 0xfa4, 0xfa8, 0xfac, 0xfb8, 0xfbc, |
| 0xfc0, 0xfc4, 0xfd0, 0xfd4, 0xfd8, 0xfdc, 0xfe8, 0xfec, 0xff0, 0x1f04, |
| 0x1f0c, 0x1f10, 0x1f24, 0x1f28, 0x1f2c, 0x1f30, 0x1f34, 0x1f38, 0x1f3c |
| }; |
| |
| bool is_wr_only_reg(u32 addr) |
| { |
| int i; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| return false; |
| |
| for (i = 0; i < sizeof(wr_only_register) / sizeof(u32); i++) { |
| if (addr == wr_only_register[i]) |
| return true; |
| } |
| return false; |
| } |
| |
| void rx_debug_load22key(void) |
| { |
| int ret = 0; |
| int wait_kill_done_cnt = 0; |
| |
| if (rx.chip_id >= CHIP_ID_T7) |
| return; |
| ret = rx_sec_set_duk(hdmirx_repeat_support()); |
| rx_pr("22 = %d\n", ret); |
| if (ret) { |
| rx_pr("load 2.2 key\n"); |
| sm_pause = 1; |
| rx_set_cur_hpd(0, 4); |
| hdcp22_on = 1; |
| hdcp22_kill_esm = 1; |
| while (wait_kill_done_cnt++ < 10) { |
| if (!hdcp22_kill_esm) |
| break; |
| msleep(20); |
| } |
| hdcp22_kill_esm = 0; |
| /* extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 0); */ |
| rx_hdcp22_send_uevent(0); |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x0); |
| /* if key_a is already exist on platform,*/ |
| /*need to set valid bit to 0 before burning key_b,*/ |
| /*otherwise,key_b will not be activated*/ |
| rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 0x1); |
| hdmirx_hdcp22_esm_rst(); |
| mdelay(110); |
| rx_is_hdcp22_support(); |
| hdmirx_wr_dwc(DWC_HDCP22_CONTROL, 0x1000); |
| /* rx_hdcp22_wr_top(TOP_SKP_CNTL_STAT, 0x1); */ |
| hdcp22_clk_en(1); |
| /* extcon_set_state_sync(rx.rx_excton_rx22, EXTCON_DISP_HDMI, 1); */ |
| rx_hdcp22_send_uevent(1); |
| mdelay(100); |
| hdmi_rx_top_edid_update(); |
| hdmirx_hw_config(); |
| hpd_to_esm = 1; |
| /* mdelay(900); */ |
| rx_set_cur_hpd(1, 4); |
| sm_pause = 0; |
| } |
| } |
| |
| void rx_debug_loadkey(void) |
| { |
| rx_pr("load hdcp key\n"); |
| hdmi_rx_top_edid_update(); |
| hdmirx_hw_config(); |
| pre_port = 0xfe; |
| } |
| |
| void print_reg(uint start_addr, uint end_addr) |
| { |
| int i; |
| |
| if (end_addr < start_addr) |
| return; |
| |
| for (i = start_addr; i <= end_addr; i += sizeof(uint)) { |
| if ((i - start_addr) % (sizeof(uint) * 4) == 0) |
| rx_pr("[0x%-4x] ", i); |
| if (!is_wr_only_reg(i)) |
| if (rx.chip_id >= CHIP_ID_T7) |
| rx_pr("0x%-8x,", hdmirx_rd_cor(i)); |
| else |
| rx_pr("0x%-8x,", hdmirx_rd_dwc(i)); |
| else |
| rx_pr("xxxxxx ,"); |
| |
| if ((i - start_addr) % (sizeof(uint) * 4) == sizeof(uint) * 3) |
| rx_pr("\n"); |
| } |
| |
| if ((end_addr - start_addr + sizeof(uint)) % (sizeof(uint) * 4) != 0) |
| rx_pr("\n"); |
| } |
| |
| void dump_reg(void) |
| { |
| int i = 0; |
| |
| rx_pr("\n***Top registers***\n"); |
| rx_pr("[addr ] addr + 0x0,"); |
| rx_pr("addr + 0x1, addr + 0x2, addr + 0x3\n"); |
| for (i = 0; i <= 0x24;) { |
| rx_pr("[0x%-3x]", i); |
| rx_pr("0x%-8x", hdmirx_rd_top(i)); |
| rx_pr("0x%-8x,0x%-8x,0x%-8x\n", |
| hdmirx_rd_top(i + 1), |
| hdmirx_rd_top(i + 2), |
| hdmirx_rd_top(i + 3)); |
| i = i + 4; |
| } |
| |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| for (i = 0x25; i <= 0x84;) { |
| rx_pr("[0x%-3x]", i); |
| rx_pr("0x%-8x", hdmirx_rd_top(i)); |
| rx_pr("0x%-8x,0x%-8x,0x%-8x\n", |
| hdmirx_rd_top(i + 1), |
| hdmirx_rd_top(i + 2), |
| hdmirx_rd_top(i + 3)); |
| i = i + 4; |
| } |
| } |
| |
| if (rx.chip_id < CHIP_ID_TL1) { |
| rx_pr("\n***PHY registers***\n"); |
| rx_pr("[addr ] addr + 0x0,"); |
| rx_pr("addr + 0x1,addr + 0x2,"); |
| rx_pr("addr + 0x3\n"); |
| for (i = 0; i <= 0x9a;) { |
| rx_pr("[0x%-3x]", i); |
| rx_pr("0x%-8x", hdmirx_rd_phy(i)); |
| rx_pr("0x%-8x,0x%-8x,0x%-8x\n", |
| hdmirx_rd_phy(i + 1), |
| hdmirx_rd_phy(i + 2), |
| hdmirx_rd_phy(i + 3)); |
| i = i + 4; |
| } |
| |
| } else if (rx.chip_id >= CHIP_ID_TL1) { |
| /* dump phy register */ |
| dump_reg_phy(); |
| } |
| |
| if (rx.chip_id < CHIP_ID_T7) { |
| rx_pr("\n**Controller registers**\n"); |
| rx_pr("[addr ] addr + 0x0,"); |
| rx_pr("addr + 0x4, addr + 0x8,"); |
| rx_pr("addr + 0xc\n"); |
| print_reg(0, 0xfc); |
| print_reg(0x140, 0x3ac); |
| print_reg(0x3c0, 0x418); |
| print_reg(0x480, 0x4bc); |
| print_reg(0x600, 0x610); |
| print_reg(0x800, 0x87c); |
| print_reg(0x8e0, 0x8e0); |
| print_reg(0x8fc, 0x8fc); |
| print_reg(0xf60, 0xffc); |
| } else { |
| print_reg(0x0, 0xfe); |
| print_reg(0x300, 0x3ff); |
| print_reg(0x1001, 0x1f78); |
| } |
| } |
| |
| void dump_reg_phy(void) |
| { |
| if (rx.phy_ver == PHY_VER_T5) |
| dump_reg_phy_t5(); |
| else if (rx.phy_ver >= PHY_VER_T7) |
| dump_reg_phy_t7(); |
| else |
| dump_reg_phy_tl1_tm2(); |
| } |
| |
| void dump_edid_reg(void) |
| { |
| int i = 0; |
| int j = 0; |
| |
| rx_pr("\n***********************\n"); |
| rx_pr("0x1 1.4 edid\n"); |
| rx_pr("0x2 1.4 edid with audio blocks\n"); |
| rx_pr("0x3 1.4 edid with 420 capability\n"); |
| rx_pr("0x4 1.4 edid with 420 video data\n"); |
| rx_pr("0x5 2.0 edid with HDR,DV,420\n"); |
| rx_pr("********************************\n"); |
| if (rx.chip_id < CHIP_ID_TL1) { |
| for (i = 0; i < 16; i++) { |
| rx_pr("[%2d] ", i); |
| for (j = 0; j < 16; j++) { |
| rx_pr("0x%02x, ", |
| hdmirx_rd_top(TOP_EDID_OFFSET + |
| (i * 16 + j))); |
| } |
| rx_pr("\n"); |
| } |
| } else if (rx.chip_id == CHIP_ID_TL1) { |
| for (i = 0; i < 16; i++) { |
| rx_pr("[%2d] ", i); |
| for (j = 0; j < 16; j++) { |
| rx_pr("0x%02x, ", |
| hdmirx_rd_top(TOP_EDID_ADDR_S + |
| (i * 16 + j))); |
| } |
| rx_pr("\n"); |
| } |
| } else { |
| for (i = 0; i < 16; i++) { |
| rx_pr("[%2d] ", i); |
| for (j = 0; j < 16; j++) { |
| rx_pr("0x%02x, ", |
| hdmirx_rd_top(TOP_EDID_ADDR_S + |
| (i * 16 + j))); |
| } |
| rx_pr("\n"); |
| } |
| for (i = 0; i < 16; i++) { |
| rx_pr("[%2d] ", i); |
| for (j = 0; j < 16; j++) { |
| rx_pr("0x%02x, ", |
| hdmirx_rd_top(TOP_EDID_PORT2_ADDR_S + |
| (i * 16 + j))); |
| } |
| rx_pr("\n"); |
| } |
| for (i = 0; i < 16; i++) { |
| rx_pr("[%2d] ", i); |
| for (j = 0; j < 16; j++) { |
| rx_pr("0x%02x, ", |
| hdmirx_rd_top(TOP_EDID_PORT3_ADDR_S + |
| (i * 16 + j))); |
| } |
| rx_pr("\n"); |
| } |
| } |
| } |
| |
| int rx_debug_wr_reg(const char *buf, char *tmpbuf, int i) |
| { |
| u32 adr = 0; |
| u32 value = 0; |
| |
| if (kstrtou32(tmpbuf + 3, 16, &adr) < 0) |
| return -EINVAL; |
| rx_pr("adr = %#x\n", adr); |
| if (kstrtou32(buf + i + 1, 16, &value) < 0) |
| return -EINVAL; |
| rx_pr("value = %#x\n", value); |
| if (tmpbuf[1] == 'h') { |
| if (buf[2] == 't') { |
| hdmirx_wr_top(adr, value); |
| rx_pr("write %x to TOP [%x]\n", value, adr); |
| } else if (buf[2] == 'd') { |
| if (rx.chip_id >= CHIP_ID_T7) |
| hdmirx_wr_cor(adr, value); |
| else |
| hdmirx_wr_dwc(adr, value); |
| rx_pr("write %x to DWC [%x]\n", value, adr); |
| } else if (buf[2] == 'p') { |
| hdmirx_wr_phy(adr, value); |
| rx_pr("write %x to PHY [%x]\n", value, adr); |
| } else if (buf[2] == 'u') { |
| wr_reg_hhi(adr, value); |
| rx_pr("write %x to hiu [%x]\n", value, adr); |
| } else if (buf[2] == 's') { |
| rx_hdcp22_wr_top(adr, value); |
| rx_pr("write %x to sec-top [%x]\n", value, adr); |
| } else if (buf[2] == 'h') { |
| rx_hdcp22_wr_reg(adr, value); |
| rx_pr("write %x to esm [%x]\n", value, adr); |
| } else if (buf[2] == 'a') { |
| hdmirx_wr_amlphy(adr, value); |
| rx_pr("write %x to amlphy [%x]\n", value, adr); |
| } else if (buf[2] == 'c') { |
| rx_wr_cor(adr, value); |
| rx_pr("write %x to sec cor [%x]\n", value, adr); |
| } else if (buf[2] == 'e') { |
| rx_wr_aes(adr, value); |
| rx_pr("write %x to aes reg [%x]\n", value, adr); |
| } |
| } |
| return 0; |
| } |
| |
| int rx_debug_rd_reg(const char *buf, char *tmpbuf) |
| { |
| u32 adr = 0; |
| u32 value = 0; |
| |
| if (tmpbuf[1] == 'h') { |
| if (kstrtou32(tmpbuf + 3, 16, &adr) < 0) |
| return -EINVAL; |
| if (tmpbuf[2] == 't') { |
| value = hdmirx_rd_top(adr); |
| rx_pr("TOP [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'd') { |
| if (rx.chip_id >= CHIP_ID_T7) |
| value = hdmirx_rd_cor(adr); |
| else |
| value = hdmirx_rd_dwc(adr); |
| rx_pr("DWC [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'p') { |
| value = hdmirx_rd_phy(adr); |
| rx_pr("PHY [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'u') { |
| value = rd_reg_hhi(adr); |
| rx_pr("HIU [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 's') { |
| value = rx_hdcp22_rd_top(adr); |
| rx_pr("SEC-TOP [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'h') { |
| value = rx_hdcp22_rd_reg(adr); |
| rx_pr("esm [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'a') { |
| value = hdmirx_rd_amlphy(adr); |
| rx_pr("amlphy [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'c') { |
| value = rx_rd_cor(adr); |
| rx_pr("sec cor [%x]=%x\n", adr, value); |
| } else if (tmpbuf[2] == 'e') { |
| value = rx_rd_aes(adr); |
| rx_pr("aes [%x]=%x\n", adr, value); |
| } |
| } |
| return 0; |
| } |
| |
| int rx_get_aud_pll_err_sts(void) |
| { |
| int ret = E_AUDPLL_OK; |
| u32 req_clk = 0; |
| u32 aud_clk = 0;//rx.aud_info.aud_clk; |
| u32 phy_pll_rate = 0;//(hdmirx_rd_phy(PHY_MAINFSM_STATUS1) >> 9) & 0x3; |
| u32 aud_pll_cntl = 0;//(rd_reg_hhi(HHI_AUD_PLL_CNTL6) >> 28) & 0x3; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) |
| return ret; |
| |
| req_clk = rx.clk.mpll_clk; |
| aud_clk = rx.aud_info.aud_clk; |
| phy_pll_rate = (hdmirx_rd_phy(PHY_MAINFSM_STATUS1) >> 9) & 0x3; |
| aud_pll_cntl = (rd_reg_hhi(HHI_AUD_PLL_CNTL6) >> 28) & 0x3; |
| |
| if (req_clk > PHY_REQUEST_CLK_MAX || |
| req_clk < PHY_REQUEST_CLK_MIN) { |
| ret = E_REQUESTCLK_ERR; |
| if (log_level & AUDIO_LOG) |
| rx_pr("request clk err:%d\n", req_clk); |
| } else if (phy_pll_rate != aud_pll_cntl) { |
| ret = E_PLLRATE_CHG; |
| if (log_level & AUDIO_LOG) |
| rx_pr("pll rate chg,phy=%d,pll=%d\n", |
| phy_pll_rate, aud_pll_cntl); |
| } else if (aud_clk == 0) { |
| ret = E_AUDCLK_ERR; |
| if (log_level & AUDIO_LOG) |
| rx_pr("aud_clk=0\n"); |
| } |
| |
| return ret; |
| } |
| |
| u32 aml_cable_clk_band(u32 cableclk, u32 clkrate) |
| { |
| u32 bw; |
| u32 cab_clk = cableclk; |
| |
| if (rx.chip_id < CHIP_ID_TL1) |
| return PHY_BW_2; |
| |
| /* rx_pr("cable clk=%d, clkrate=%d\n", cableclk, clkrate); */ |
| /* 1:40 */ |
| if (clkrate) |
| cab_clk = cableclk << 2; |
| |
| /* 1:10 */ |
| if (cab_clk < (45 * MHz)) |
| bw = PHY_BW_0; |
| else if (cab_clk < (77 * MHz)) |
| bw = PHY_BW_1; |
| else if (cab_clk < (155 * MHz)) |
| bw = PHY_BW_2; |
| else if (cab_clk < (340 * MHz)) |
| bw = PHY_BW_3; |
| else if (cab_clk < (525 * MHz)) |
| bw = PHY_BW_4; |
| else if (cab_clk < (600 * MHz)) |
| bw = PHY_BW_5; |
| else |
| bw = PHY_BW_2; |
| return bw; |
| } |
| |
| u32 aml_phy_pll_band(u32 cableclk, u32 clkrate) |
| { |
| u32 bw; |
| u32 cab_clk = cableclk; |
| |
| if (clkrate) |
| cab_clk = cableclk << 2; |
| |
| /* 1:10 */ |
| if (cab_clk < (35 * MHz)) |
| bw = PLL_BW_0; |
| else if (cab_clk < (77 * MHz)) |
| bw = PLL_BW_1; |
| else if (cab_clk < (155 * MHz)) |
| bw = PLL_BW_2; |
| else if (cab_clk < (300 * MHz)) |
| bw = PLL_BW_3; |
| else if (cab_clk < (600 * MHz)) |
| bw = PLL_BW_4; |
| else |
| bw = PLL_BW_2; |
| |
| return bw; |
| } |
| |
| void aml_phy_switch_port(void) |
| { |
| if (rx.chip_id == CHIP_ID_TL1) |
| aml_phy_switch_port_tl1(); |
| else if (rx.chip_id == CHIP_ID_TM2) |
| aml_phy_switch_port_tm2(); |
| else if (rx.chip_id >= CHIP_ID_T5 && |
| rx.chip_id <= CHIP_ID_T5D) |
| aml_phy_switch_port_t5(); |
| else if (rx.chip_id >= CHIP_ID_T7) |
| aml_phy_switch_port_t7(); |
| } |
| |
| bool is_ft_trim_done(void) |
| { |
| int ret = phy_trim_val & 0x1; |
| |
| rx_pr("ft trim=%d\n", ret); |
| return ret; |
| } |
| |
| /*T5 todo:*/ |
| void aml_phy_get_trim_val_tl1_tm2(void) |
| { |
| u32 data32; |
| |
| phy_tdr_en = (phy_term_lel >> 4) & 0x1; |
| phy_term_lel = phy_term_lel & 0xf; |
| phy_trim_val = rd_reg_hhi(HHI_HDMIRX_PHY_MISC_CNTL1); |
| data32 = (phy_trim_val >> 12) & 0x3ff; |
| data32 = (~((~data32) << phy_term_lel) | (1 << phy_term_lel)); |
| phy_trim_val = ((phy_trim_val & (~(0x3ff << 12))) | (data32 << 12)); |
| } |
| |
| void aml_phy_get_trim_val(void) |
| { |
| if (rx.chip_id >= CHIP_ID_TL1 && |
| rx.chip_id <= CHIP_ID_TM2) |
| aml_phy_get_trim_val_tl1_tm2(); |
| else if (rx.chip_id >= CHIP_ID_T5 && |
| rx.chip_id <= CHIP_ID_T5D) |
| aml_phy_get_trim_val_t5(); |
| else if (rx.chip_id >= CHIP_ID_T7) |
| aml_phy_get_trim_val_t7(); |
| } |
| |
| void rx_get_best_eq_setting(void) |
| { |
| u32 ch0, ch1, ch2; |
| static u32 err_sum; |
| static u32 time_cnt; |
| static u32 array_cnt; |
| |
| if (rx.chip_id < CHIP_ID_TL1 || !find_best_eq) |
| return; |
| if (find_best_eq >= 0x7777 || array_cnt >= 255) { |
| rx_pr("eq traversal completed.\n"); |
| rx_pr("best eq value:%d\n", array_cnt); |
| if (array_cnt) { |
| do { |
| rx_pr("%x:\n", rx.phy.eq_data[array_cnt]); |
| } while (array_cnt--); |
| } else { |
| rx_pr("%x:\n", rx.phy.eq_data[array_cnt]); |
| } |
| find_best_eq = 0; |
| array_cnt = 0; |
| return; |
| } |
| if (time_cnt == 0) { |
| hdmirx_phy_init(); |
| udelay(1); |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_DCHD_CNTL1, MSK(16, 4), find_best_eq); |
| udelay(2); |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_DCHD_CNTL1, _BIT(22), 1); |
| rx_pr("set eq:%x\n", find_best_eq); |
| err_sum = 0; |
| do { |
| find_best_eq++; |
| } while (((find_best_eq & 0xf) > 7) || |
| (((find_best_eq >> 4) & 0xf) > 7) || |
| (((find_best_eq >> 8) & 0xf) > 7) || |
| (((find_best_eq >> 12) & 0xf) > 7)); |
| } |
| time_cnt++; |
| if (time_cnt > 2) { |
| if (!is_tmds_valid()) |
| return; |
| } |
| if (time_cnt > 4) { |
| rx_get_error_cnt(&ch0, &ch1, &ch2); |
| err_sum += (ch0 + ch1 + ch2); |
| } |
| if (time_cnt > eq_try_cnt) { |
| time_cnt = 0; |
| if (err_sum < rx.phy.err_sum) { |
| rx.phy.err_sum = err_sum; |
| rx_pr("err_sum = %d\n", err_sum); |
| array_cnt = 0; |
| rx.phy.eq_data[array_cnt] = find_best_eq; |
| } else if ((err_sum == rx.phy.err_sum) || |
| (err_sum == 0)) { |
| rx.phy.err_sum = err_sum; |
| array_cnt++; |
| rx_pr("array = %x\n", array_cnt); |
| rx.phy.eq_data[array_cnt] = find_best_eq; |
| } |
| } |
| } |
| |
| bool is_tmds_clk_stable(void) |
| { |
| bool ret = true; |
| u32 cableclk; |
| |
| if (rx.phy.clk_rate) |
| cableclk = rx.clk.cable_clk * 4; |
| else |
| cableclk = rx.clk.cable_clk; |
| |
| if (abs(cableclk - rx.clk.tmds_clk) > clock_lock_th * MHz) { |
| if (log_level & VIDEO_LOG) |
| rx_pr("cableclk=%d,tmdsclk=%d,\n", |
| cableclk / MHz, rx.clk.tmds_clk / MHz); |
| ret = false; |
| } else { |
| ret = true; |
| } |
| return ret; |
| } |
| |
| void aml_phy_init_handler(struct work_struct *work) |
| { |
| //cancel_work(&amlphy_dwork); |
| if (rx.phy_ver == PHY_VER_TL1) |
| aml_phy_init_tl1(); |
| else if (rx.phy_ver == PHY_VER_TM2) |
| aml_phy_init_tm2(); |
| else if (rx.phy_ver == PHY_VER_T5) |
| aml_phy_init_t5(); |
| else if (rx.phy_ver >= PHY_VER_T7) |
| aml_phy_init_t7(); |
| eq_sts = E_EQ_FINISH; |
| } |
| |
| void aml_phy_init(void) |
| { |
| schedule_work(&amlphy_dwork); |
| eq_sts = E_EQ_START; |
| } |
| |
| /* |
| * hdmirx_phy_init - hdmirx phy initialization |
| */ |
| void hdmirx_phy_init(void) |
| { |
| if (rx.chip_id >= CHIP_ID_TL1) |
| aml_phy_init(); |
| else |
| snps_phyg3_init(); |
| } |
| |
| void rx_phy_short_bist(void) |
| { |
| if (rx.phy_ver == PHY_VER_TL1) |
| aml_phy_short_bist_tl1(); |
| else if (rx.phy_ver == PHY_VER_TM2) |
| aml_phy_short_bist_tm2(); |
| else if (rx.phy_ver == PHY_VER_T5) |
| aml_phy_short_bist_t5(); |
| else if (rx.phy_ver >= PHY_VER_T7) |
| aml_phy_short_bist_t7(); |
| } |
| |
| unsigned int aml_phy_pll_lock_tm2(void) |
| { |
| if (rd_reg_hhi(HHI_HDMIRX_APLL_CNTL0) & 0x80000000) |
| return true; |
| else |
| return false; |
| } |
| |
| unsigned int aml_phy_pll_lock_t5(void) |
| { |
| if (hdmirx_rd_amlphy(HHI_RX_APLL_CNTL0) & 0x80000000) |
| return true; |
| else |
| return false; |
| } |
| |
| unsigned int aml_phy_pll_lock(void) |
| { |
| if (rx.chip_id >= CHIP_ID_T5) |
| return aml_phy_pll_lock_t5(); |
| else |
| return aml_phy_pll_lock_tm2(); |
| } |
| |
| bool is_tmds_valid(void) |
| { |
| if (force_vic) |
| return true; |
| |
| if (!rx.cableclk_stb_flg) |
| return false; |
| |
| if (rx.chip_id >= CHIP_ID_TL1) |
| return (aml_phy_tmds_valid() == 1) ? true : false; |
| else |
| return (rx_get_pll_lock_sts() == 1) ? true : false; |
| } |
| |
| unsigned int aml_phy_tmds_valid(void) |
| { |
| if (rx.phy_ver == PHY_VER_TL1) |
| return aml_get_tmds_valid_tl1(); |
| else if (rx.phy_ver == PHY_VER_TM2) |
| return aml_get_tmds_valid_tm2(); |
| else if (rx.phy_ver == PHY_VER_T5) |
| return aml_get_tmds_valid_t5(); |
| else if (rx.phy_ver >= PHY_VER_T7) |
| return aml_get_tmds_valid_t7(); |
| else |
| return false; |
| } |
| |
| void rx_phy_rxsense_pulse(unsigned int t1, unsigned int t2, bool en) |
| { |
| /* set rxsense pulse */ |
| hdmirx_phy_pddq(!en); |
| mdelay(t1); |
| hdmirx_phy_pddq(en); |
| mdelay(t2); |
| } |
| |
| void aml_phy_power_off(void) |
| { |
| /* phy power down */ |
| if (rx.phy_ver == PHY_VER_TL1) { |
| /* pll power down */ |
| aml_phy_power_off_tl1(); |
| } else if (rx.phy_ver == PHY_VER_TM2) { |
| /* pll power down */ |
| aml_phy_power_off_tm2(); |
| } else if (rx.phy_ver == PHY_VER_T5) { |
| /* pll power down */ |
| aml_phy_power_off_t5(); |
| } else if (rx.phy_ver >= PHY_VER_T7) { |
| /* pll power down */ |
| aml_phy_power_off_t7(); |
| } |
| if (log_level & VIDEO_LOG) |
| rx_pr("%s\n", __func__); |
| } |
| |
| void rx_phy_power_on(unsigned int onoff) |
| { |
| if (onoff) |
| hdmirx_phy_pddq(0); |
| else |
| hdmirx_phy_pddq(1); |
| if (rx.chip_id >= CHIP_ID_TL1) { |
| /*the enable of these regs are in phy init*/ |
| if (onoff == 0) |
| aml_phy_power_off(); |
| } |
| } |
| |
| void aml_phy_iq_skew_monitor(void) |
| { |
| if (rx.phy_ver == PHY_VER_T5) |
| aml_phy_iq_skew_monitor_t5(); |
| else if (rx.phy_ver >= PHY_VER_T7) |
| aml_phy_iq_skew_monitor_t7(); |
| } |
| |
| void aml_eq_eye_monitor(void) |
| { |
| if (rx.phy_ver == PHY_VER_T5) |
| aml_eq_eye_monitor_t5(); |
| else if (rx.phy_ver >= PHY_VER_T7) |
| aml_eq_eye_monitor_t7(); |
| } |
| |
| void rx_emp_to_ddr_init(void) |
| { |
| u32 data32; |
| |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| |
| if (rx.empbuff.pg_addr) { |
| rx_pr("%s\n", __func__); |
| /*disable field done and last pkt interrupt*/ |
| data32 = hdmirx_rd_top(TOP_INTR_MASKN); |
| data32 &= ~(1 << 25); |
| data32 &= ~(1 << 26); |
| hdmirx_wr_top(TOP_INTR_MASKN, data32); |
| |
| if (rx.empbuff.p_addr_a) { |
| /* emp int enable */ |
| /* config ddr buffer */ |
| hdmirx_wr_top(TOP_EMP_DDR_START_A, rx.empbuff.p_addr_a >> 2); |
| hdmirx_wr_top(TOP_EMP_DDR_START_B, rx.empbuff.p_addr_b >> 2); |
| } |
| /* enable store EMP pkt type */ |
| data32 = 0; |
| data32 |= 0x1 << 22;/* ddr_store_drm */ |
| data32 |= 0x1 << 15;/* ddr_store_emp */ |
| hdmirx_wr_top(TOP_EMP_DDR_FILTER, data32); |
| /* max pkt count */ |
| hdmirx_wr_top(TOP_EMP_CNTMAX, EMP_BUFF_MAX_PKT_CNT); |
| |
| data32 = 0; |
| data32 |= 0xf << 16;/*[23:16] hs_beat_rate=0xf */ |
| data32 |= 0x0 << 14;/*[14] buffer_info_mode=0 */ |
| data32 |= 0x1 << 13;/*[13] reset_on_de=1 */ |
| data32 |= 0x1 << 12;/*[12] burst_end_on_last_emp=1 */ |
| data32 |= 0x3ff << 2;/*[11:2] de_rise_delay=0 */ |
| data32 |= 0x0 << 0;/*[1:0] Endian = 0 */ |
| hdmirx_wr_top(TOP_EMP_CNTL_0, data32); |
| |
| data32 = 0; |
| data32 |= 0 << 1;/*ddr_mode[1] 0: emp 1: tmds*/ |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data32); |
| |
| data32 = 0; |
| data32 |= 0 << 1; /*ddr_mode[1] 0: emp 1: tmds*/ |
| data32 |= 1 << 0; /*ddr_en[0] 1:enable*/ |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data32); |
| |
| /* emp int enable TOP_INTR_MASKN*/ |
| /* emp field end done at DE rist bit[25]*/ |
| /* emp last EMP pkt recv done bit[26]*/ |
| /* disable emp irq */ |
| //top_intr_maskn_value |= _BIT(25); |
| //hdmirx_wr_top(TOP_INTR_MASKN, top_intr_maskn_value); |
| } |
| |
| rx.empbuff.ready = NULL; |
| rx.empbuff.irqcnt = 0; |
| rx.empbuff.emppktcnt = 0; |
| rx.empbuff.tmdspktcnt = 720 * 480; |
| } |
| |
| void rx_emp_field_done_irq(void) |
| { |
| phys_addr_t p_addr; |
| unsigned int recv_pkt_cnt, recv_byte_cnt, recv_pagenum; |
| unsigned int emp_pkt_cnt = 0; |
| unsigned char *src_addr = 0; |
| unsigned char *dts_addr; |
| unsigned int i, j, k; |
| unsigned int datacnt = 0; |
| struct page *cur_start_pg_addr; |
| |
| /*emp data start physical address*/ |
| p_addr = hdmirx_rd_top(TOP_EMP_DDR_PTR_S_BUF) << 2; |
| |
| /*buffer number*/ |
| recv_pkt_cnt = hdmirx_rd_top(TOP_EMP_RCV_CNT_BUF); |
| recv_byte_cnt = recv_pkt_cnt * 32; |
| recv_pagenum = (recv_byte_cnt >> PAGE_SHIFT) + 1; |
| |
| if (rx.empbuff.irqcnt & 0x1) |
| dts_addr = rx.empbuff.store_b; |
| else |
| dts_addr = rx.empbuff.store_a; |
| |
| if (recv_pkt_cnt >= EMP_BUFF_MAX_PKT_CNT) { |
| recv_pkt_cnt = EMP_BUFF_MAX_PKT_CNT - 1; |
| rx_pr("pkt cnt err:%d\n", recv_pkt_cnt); |
| } |
| |
| for (i = 0; i < recv_pagenum;) { |
| /*one page 4k*/ |
| cur_start_pg_addr = phys_to_page(p_addr + i * PAGE_SIZE); |
| src_addr = kmap_atomic(cur_start_pg_addr); |
| dma_sync_single_for_cpu(hdmirx_dev, (p_addr + i * PAGE_SIZE), |
| PAGE_SIZE, DMA_TO_DEVICE); |
| if (recv_byte_cnt >= PAGE_SIZE) { |
| for (j = 0; j < PAGE_SIZE;) { |
| //if (src_addr[j] == 0x7f) { |
| emp_pkt_cnt++; |
| /*32 bytes per emp pkt*/ |
| for (k = 0; k < 32; k++) { |
| dts_addr[datacnt] = |
| src_addr[PAGE_SIZE * i + j + k]; |
| datacnt++; |
| } |
| //} |
| j += 32; |
| } |
| recv_byte_cnt -= PAGE_SIZE; |
| } else { |
| for (j = 0; j < recv_byte_cnt;) { |
| //if (src_addr[j] == 0x7f) { |
| emp_pkt_cnt++; |
| /*32 bytes per emp pkt*/ |
| for (k = 0; k < 32; k++) { |
| dts_addr[datacnt] = |
| src_addr[PAGE_SIZE * i + j + k]; |
| datacnt++; |
| } |
| //} |
| j += 32; |
| } |
| } |
| /*release*/ |
| /*__kunmap_atomic(src_addr);*/ |
| kunmap_atomic(src_addr); |
| i++; |
| } |
| |
| if (emp_pkt_cnt * 32 > 1024) { |
| if (log_level & 0x400) |
| rx_pr("emp buffer overflow!!\n"); |
| } else { |
| /*ready address*/ |
| rx.empbuff.ready = dts_addr; |
| /*ready pkt cnt*/ |
| rx.empbuff.emppktcnt = emp_pkt_cnt; |
| for (i = 0; i < rx.empbuff.emppktcnt; i++) |
| memcpy((char *)(emp_buf + 31 * i), |
| (char *)(dts_addr + 32 * i), 31); |
| /*emp field dont irq counter*/ |
| rx.empbuff.irqcnt++; |
| } |
| } |
| |
| void rx_emp_status(void) |
| { |
| rx_pr("p_addr_a=0x%p\n", (void *)rx.empbuff.p_addr_a); |
| rx_pr("p_addr_b=0x%p\n", (void *)rx.empbuff.p_addr_b); |
| rx_pr("store_a=0x%p\n", rx.empbuff.store_a); |
| rx_pr("store_b=0x%p\n", rx.empbuff.store_b); |
| rx_pr("irq cnt =0x%x\n", (unsigned int)rx.empbuff.irqcnt); |
| rx_pr("ready=0x%p\n", rx.empbuff.ready); |
| rx_pr("dump_mode =0x%x\n", rx.empbuff.dump_mode); |
| rx_pr("recv emp pkt cnt=0x%x\n", rx.empbuff.emppktcnt); |
| rx_pr("recv tmds pkt cnt=0x%x\n", rx.empbuff.tmdspktcnt); |
| } |
| |
| void rx_tmds_to_ddr_init(void) |
| { |
| unsigned int data, data2; |
| unsigned int i = 0; |
| |
| if (rx.chip_id < CHIP_ID_T7) |
| return; |
| |
| if (rx.empbuff.pg_addr) { |
| rx_pr("%s\n", __func__); |
| /*disable field done and last pkt interrupt*/ |
| top_intr_maskn_value &= ~(1 << 25); |
| top_intr_maskn_value &= ~(1 << 26); |
| hdmirx_wr_top(TOP_INTR_MASKN, top_intr_maskn_value); |
| |
| /* disable emp rev */ |
| data = hdmirx_rd_top(TOP_EMP_CNTL_1); |
| data &= ~0x1; |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data); |
| /* wait until emp finish */ |
| data2 = hdmirx_rd_top(TOP_EMP_STAT_0) & 0x7fffffff; |
| data = hdmirx_rd_top(TOP_EMP_STAT_1); |
| while (data2 || data) { |
| mdelay(1); |
| data2 = hdmirx_rd_top(TOP_EMP_STAT_0) & 0x7fffffff; |
| data = hdmirx_rd_top(TOP_EMP_STAT_1); |
| if (i++ > 100) { |
| rx_pr("warning: wait emp timeout\n"); |
| break; |
| } |
| } |
| if (rx.empbuff.p_addr_a) { |
| /* config ddr buffer */ |
| hdmirx_wr_top(TOP_EMP_DDR_START_A, rx.empbuff.p_addr_a >> 2); |
| hdmirx_wr_top(TOP_EMP_DDR_START_B, rx.empbuff.p_addr_a >> 2); |
| rx_pr("cfg hw addr=0x%p\n", (void *)rx.empbuff.p_addr_a); |
| } |
| |
| /* max pkt count to avoid buffer overflow */ |
| /* one pixel 4bytes */ |
| data = ((rx.empbuff.tmdspktcnt / 8) * 8) - 1; |
| hdmirx_wr_top(TOP_EMP_CNTMAX, data); |
| rx_pr("pkt max cnt limit=0x%x\n", data); |
| |
| data = 0; |
| data |= 0x0 << 16;/*[23:16] hs_beat_rate=0xf */ |
| data |= 0x1 << 14;/*[14] buffer_info_mode=0 */ |
| data |= 0x1 << 13;/*[13] reset_on_de=1 */ |
| data |= 0x0 << 12;/*[12] burst_end_on_last_emp=1 */ |
| data |= 0x0 << 2;/*[11:2] de_rise_delay=0 */ |
| data |= 0x0 << 0;/*[1:0] Endian = 0 */ |
| hdmirx_wr_top(TOP_EMP_CNTL_0, data); |
| |
| /* working mode: tmds data to ddr enable */ |
| data = hdmirx_rd_top(TOP_EMP_CNTL_1); |
| data |= 0x1 << 1;/*ddr_mode[1] 0: emp 1: tmds*/ |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data); |
| |
| /* emp int enable TOP_INTR_MASKN*/ |
| /* emp field end done at DE rist bit[25]*/ |
| /* emp last EMP pkt recv done bit[26]*/ |
| top_intr_maskn_value |= _BIT(26); |
| hdmirx_wr_top(TOP_INTR_MASKN, top_intr_maskn_value); |
| |
| /*start record*/ |
| data |= 0x1; /*ddr_en[0] 1:enable*/ |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data); |
| } |
| } |
| |
| void rx_emp_lastpkt_done_irq(void) |
| { |
| unsigned int data; |
| |
| /* disable record */ |
| data = hdmirx_rd_top(TOP_EMP_CNTL_1); |
| data &= ~0x1; /*ddr_en[0] 1:enable*/ |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data); |
| |
| /*need capture data*/ |
| |
| rx_pr(">> lastpkt_done_irq >\n"); |
| } |
| |
| void rx_emp_capture_stop(void) |
| { |
| unsigned int i = 0, data, data2; |
| |
| /*disable field done and last pkt interrupt*/ |
| top_intr_maskn_value &= ~(1 << 25); |
| top_intr_maskn_value &= ~(1 << 26); |
| hdmirx_wr_top(TOP_INTR_MASKN, top_intr_maskn_value); |
| |
| /* disable emp rev */ |
| data = hdmirx_rd_top(TOP_EMP_CNTL_1); |
| data &= ~0x1; |
| hdmirx_wr_top(TOP_EMP_CNTL_1, data); |
| /* wait until emp finish */ |
| data2 = hdmirx_rd_top(TOP_EMP_STAT_0) & 0x7fffffff; |
| data = hdmirx_rd_top(TOP_EMP_STAT_1); |
| while (data2 || data) { |
| mdelay(1); |
| data2 = hdmirx_rd_top(TOP_EMP_STAT_0) & 0x7fffffff; |
| data = hdmirx_rd_top(TOP_EMP_STAT_1); |
| if (i++ > 100) { |
| rx_pr("warning: wait emp timeout\n"); |
| break; |
| } |
| } |
| rx_pr("emp capture stop\n"); |
| } |
| |
| /* |
| * get hdmi data error counter |
| * for tl1 |
| * return: |
| * ch0 , ch1 , ch2 error counter value |
| */ |
| void rx_get_error_cnt(u32 *ch0, u32 *ch1, u32 *ch2) |
| { |
| u32 val; |
| |
| if (rx.chip_id == CHIP_ID_T7) { |
| /* t7 top 0x41/0x42 can not shadow IP's periodical error counter */ |
| /* use cor register to get err cnt,t3 fix it */ |
| hdmirx_wr_bits_cor(DPLL_CTRL0_DPLL_IVCRX, MSK(3, 0), 0x0); |
| *ch0 = hdmirx_rd_cor(SCDCS_CED0_L_SCDC_IVCRX) | |
| ((hdmirx_rd_cor(SCDCS_CED0_H_SCDC_IVCRX & 0x7f) << 8)); |
| *ch1 = hdmirx_rd_cor(SCDCS_CED1_L_SCDC_IVCRX) | |
| ((hdmirx_rd_cor(SCDCS_CED1_H_SCDC_IVCRX & 0x7f) << 8)); |
| *ch2 = hdmirx_rd_cor(SCDCS_CED2_L_SCDC_IVCRX) | |
| ((hdmirx_rd_cor(SCDCS_CED2_H_SCDC_IVCRX & 0x7f) << 8)); |
| udelay(1); |
| hdmirx_wr_bits_cor(DPLL_CTRL0_DPLL_IVCRX, MSK(3, 0), 0x7); |
| } else { |
| val = hdmirx_rd_top(TOP_CHAN01_ERRCNT); |
| *ch0 = val & 0xffff; |
| *ch1 = (val >> 16) & 0xffff; |
| val = hdmirx_rd_top(TOP_CHAN2_ERRCNT); |
| *ch2 = val & 0xffff; |
| } |
| } |
| |
| /* |
| * get hdmi audio N CTS |
| * for tl1 |
| * return: |
| * audio ACR N |
| * audio ACR CTS |
| */ |
| void rx_get_audio_N_CTS(u32 *N, u32 *CTS) |
| { |
| *N = hdmirx_rd_top(TOP_ACR_N_STAT); |
| *CTS = hdmirx_rd_top(TOP_ACR_CTS_STAT); |
| } |
| |
| u8 rx_get_avmute_sts(void) |
| { |
| u8 ret = 0; |
| |
| if (rx.chip_id >= CHIP_ID_T7) { |
| if (hdmirx_rd_cor(RX_GCP_DBYTE0_DP3_IVCRX) & 1) |
| ret = 1; |
| } else { |
| if (hdmirx_rd_dwc(DWC_PDEC_GCP_AVMUTE) & 0x02) |
| ret = 1; |
| } |
| return ret; |
| } |
| /* termination calibration */ |
| void rx_phy_rt_cal(void) |
| { |
| int i = 0, j = 0; |
| u32 x_val[100][2]; |
| u32 temp; |
| int val_cnt = 1; |
| |
| for (; i < 100; i++) { |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_MISC_CNTL0, MISCI_COMMON_RST, 0); |
| wr_reg_hhi_bits(HHI_HDMIRX_PHY_MISC_CNTL0, MISCI_COMMON_RST, 1); |
| udelay(1); |
| temp = (rd_reg_hhi(HHI_HDMIRX_PHY_MISC_STAT) >> 1) & 0x3ff; |
| if (i == 0) { |
| x_val[0][0] = temp; |
| x_val[0][1] = 1; |
| } |
| |
| for (; j < i; j++) { |
| if (temp == x_val[j][0]) { |
| x_val[j][1] += 1; |
| goto todo; |
| } |
| } |
| todo: |
| if (j == (val_cnt + 1)) { |
| x_val[j][0] = temp; |
| x_val[j][1] = 1; |
| val_cnt++; |
| rx_pr("new\n"); |
| } |
| |
| if (x_val[j][1] == 10) { |
| term_cal_val = (~((x_val[j][0]) << 1)) & 0x3ff; |
| rx_pr("tdr cal val=0x%x", term_cal_val); |
| return; |
| } |
| j = 0; |
| } |
| } |
| |
| /* |
| * for Nvdia PC long detection time issue |
| */ |
| void rx_i2c_err_monitor(void) |
| { |
| int data32 = 0; |
| |
| if (!(rx.ddc_filter_en || is_ddc_filter_en())) |
| return; |
| |
| i2c_err_cnt++; |
| data32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL); |
| if ((i2c_err_cnt % 3) != 1) |
| data32 = ((data32 & (~0xff)) | 0x9); |
| else |
| data32 = ((data32 & (~0xff)) | 0x4f); |
| hdmirx_wr_top(TOP_EDID_GEN_CNTL, data32); |
| if (log_level & EDID_LOG) |
| rx_pr("data32: 0x%x,\n", data32); |
| } |
| |
| bool is_ddc_filter_en(void) |
| { |
| bool ret = false; |
| int data32 = 0; |
| |
| data32 = hdmirx_rd_top(TOP_EDID_GEN_CNTL); |
| if ((data32 & 0xff) > 0x10) |
| ret = true; |
| |
| return ret; |
| } |
| |
| /* |
| * FUNC: rx_ddc_active_monitor |
| * ddc active monitor |
| */ |
| void rx_ddc_active_monitor(void) |
| { |
| u32 temp = 0; |
| |
| if (rx.state != FSM_WAIT_CLK_STABLE) |
| return; |
| |
| if (!((1 << rx.port) & EDID_DETECT_PORT)) |
| return; |
| |
| //if (rx.ddc_filter_en) |
| //return; |
| |
| switch (rx.port) { |
| case E_PORT0: |
| temp = hdmirx_rd_top(TOP_EDID_GEN_STAT); |
| break; |
| case E_PORT1: |
| temp = hdmirx_rd_top(TOP_EDID_GEN_STAT_B); |
| break; |
| case E_PORT2: |
| temp = hdmirx_rd_top(TOP_EDID_GEN_STAT_C); |
| break; |
| case E_PORT3: |
| temp = hdmirx_rd_top(TOP_EDID_GEN_STAT_D); |
| break; |
| default: |
| break; |
| } |
| |
| temp = temp & 0xff; |
| if (temp < 0x3f && temp != 8 && temp) { |
| rx.ddc_filter_en = true; |
| if (log_level & EDID_LOG) |
| rx_pr("port: %d, edid_status: 0x%x,\n", rx.port, temp); |
| } else { |
| if ((log_level & EDID_LOG) && rx.ddc_filter_en) |
| rx_pr("port: %d, edid_status: 0x%x,\n", rx.port, temp); |
| rx.ddc_filter_en = false; |
| } |
| } |
| |
| u32 rx_get_ecc_pkt_cnt(void) |
| { |
| u32 pkt_cnt; |
| |
| pkt_cnt = hdmirx_rd_cor(RX_PKT_CNT_DP2_IVCRX) | |
| (hdmirx_rd_cor(RX_PKT_CNT2_DP2_IVCRX) << 8); |
| |
| return pkt_cnt; |
| } |
| |
| u32 rx_get_ecc_err(void) |
| { |
| u32 err_cnt; |
| |
| hdmirx_wr_cor(RX_ECC_CTRL_DP2_IVCRX, 3); |
| err_cnt = hdmirx_rd_cor(RX_HDCP_ERR_DP2_IVCRX) | |
| (hdmirx_rd_cor(RX_HDCP_ERR2_DP2_IVCRX) << 8); |
| |
| return err_cnt; |
| } |
| |
| void rx_hdcp_22_sent_reauth(void) |
| { |
| hdmirx_wr_cor(CP2PAX_CTRL_0_HDCP2X_IVCRX, 0x0); |
| hdmirx_wr_cor(CP2PAX_CTRL_0_HDCP2X_IVCRX, 0x0); |
| //hdmirx_wr_cor(RX_ECC_CTRL_DP2_IVCRX, 3); |
| hdmirx_wr_cor(CP2PAX_CTRL_0_HDCP2X_IVCRX, 0x80); |
| } |
| |
| void rx_hdcp_14_sent_reauth(void) |
| { |
| hdmirx_wr_cor(RX_HDCP_DEBUG_HDCP1X_IVCRX, 0x80); |
| } |
| |