cec: for support multi-logical address [2/2]

PD#SWPL-418

Problem:
cec: support multi-logical address

Solution:
1.enable cec_a, cec_b
2.enable two interrupt
3.enable two pinmux oa_7, ao_8
4.cec_a only send all msg
5.cec_b only receive all msg
6.discard ceca broadcast msg

Verify:
r311 r321

Change-Id: I8f983ed6ad329ca5ec0144587a7ad1f03ad68031
Signed-off-by: Yong Qin <yong.qin@amlogic.com>

Conflicts:
	drivers/amlogic/cec/hdmi_ao_cec.c
This commit is contained in:
Yong Qin
2018-09-26 09:14:40 +08:00
committed by Dongjin Kim
parent faad940baf
commit 42565ac96b
2 changed files with 151 additions and 65 deletions

View File

@@ -242,8 +242,7 @@ unsigned int waiting_aocec_free(unsigned int r)
while (readl(cec_dev->cec_reg + r) & (1<<23)) {\
if (cnt++ == 3500) { \
pr_info("waiting aocec %x free time out\n", r);\
if (cec_dev->proble_finish) \
cec_hw_reset(CEC_A);\
cec_hw_reset(CEC_A);\
break;\
} \
} \
@@ -575,6 +574,7 @@ void cecb_irq_handle(void)
static irqreturn_t cecb_isr(int irq, void *dev_instance)
{
/*CEC_INFO("cecb_isr\n");*/
cecb_irq_handle();
return IRQ_HANDLED;
}
@@ -692,7 +692,7 @@ void eecec_irq_enable(bool enable)
writel(readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN)
& ~CECB_IRQ_EN_MASK,
cec_dev->cec_reg + AO_CECB_INTR_MASKN);
CEC_INFO("ao enable:int mask:0x%x\n",
CEC_INFO("cecb enable:int mask:0x%x\n",
readl(cec_dev->cec_reg + AO_CECB_INTR_MASKN));
}
}
@@ -906,7 +906,7 @@ void cec_logicaddr_set(int l_add)
/* save logical address for suspend/wake up */
cec_set_reg_bits(AO_DEBUG_REG1, l_add, 16, 4);
cec_dev->cec_info.addr_enable = (1 << l_add);
if (ee_cec) {
if (ee_cec == CEC_B) {
/* set ee_cec logical addr */
if (l_add < 8)
hdmirx_cec_write(DWC_CEC_ADDR_L, 1 << l_add);
@@ -975,7 +975,7 @@ void cecb_addr_add(unsigned int l_add)
hdmirx_cec_write(DWC_CEC_ADDR_L, addr);
} else {
addr = hdmirx_cec_read(DWC_CEC_ADDR_H);
addr |= (1 << (l_add - 8))|0x80;
addr |= (1 << (l_add - 8));
hdmirx_cec_write(DWC_CEC_ADDR_H, addr);
}
CEC_INFO("cec b add addr %d\n", l_add);
@@ -983,18 +983,18 @@ void cecb_addr_add(unsigned int l_add)
void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add)
{
if (cec_sel)
if (cec_sel == CEC_B)
cecb_addr_add(l_add);
else
ceca_addr_add(l_add);
}
void cec_logicaddr_remove(unsigned int l_add)
void cec_logicaddr_remove(unsigned int cec_sel, unsigned int l_add)
{
unsigned int addr;
unsigned int i;
if (ee_cec) {
if (cec_sel == CEC_B) {
if (l_add < 8) {
addr = hdmirx_cec_read(DWC_CEC_ADDR_L);
addr &= ~(1 << l_add);
@@ -1020,45 +1020,50 @@ void cec_logicaddr_remove(unsigned int l_add)
}
}
void cec_restore_logical_addr(unsigned int addr_en)
void cec_restore_logical_addr(unsigned int cec_sel, unsigned int addr_en)
{
unsigned int i;
unsigned int addr_enable = addr_en;
cec_clear_all_logical_addr(ee_cec);
cec_clear_all_logical_addr(cec_sel);
for (i = 0; i < 15; i++) {
if (addr_enable & 0x1)
cec_logicaddr_add(ee_cec, i);
cec_logicaddr_add(cec_sel, i);
addr_enable = addr_enable >> 1;
}
}
void cec_hw_reset(void)
void ceca_hw_reset(void)
{
if (ee_cec) {
writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL);
/* Enable gated clock (Normal mode). */
cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1);
/* Release SW reset */
udelay(100);
cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1);
/* Enable all AO_CEC interrupt sources */
cec_irq_enable(true);
/* cec_logicaddr_set(cec_dev->cec_info.log_addr); */
/* Cec arbitration 3/5/7 bit time set. */
cec_arbit_bit_time_set(3, 0x118, 0);
cec_arbit_bit_time_set(5, 0x000, 0);
cec_arbit_bit_time_set(7, 0x2aa, 0);
}
void cec_hw_reset(unsigned int cec_sel)
{
if (cec_sel == CEC_B) {
ao_cecb_init();
/* cec_logicaddr_set(cec_dev->cec_info.log_addr); */
} else {
writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL);
/* Enable gated clock (Normal mode). */
cec_set_reg_bits(AO_CEC_GEN_CNTL, 1, 1, 1);
/* Release SW reset */
udelay(100);
cec_set_reg_bits(AO_CEC_GEN_CNTL, 0, 0, 1);
/* Enable all AO_CEC interrupt sources */
cec_irq_enable(true);
/* cec_logicaddr_set(cec_dev->cec_info.log_addr); */
/* Cec arbitration 3/5/7 bit time set. */
cec_arbit_bit_time_set(3, 0x118, 0);
cec_arbit_bit_time_set(5, 0x000, 0);
cec_arbit_bit_time_set(7, 0x2aa, 0);
ceca_hw_reset();
}
/* cec_logicaddr_set(cec_dev->cec_info.log_addr); */
cec_restore_logical_addr(cec_dev->cec_info.addr_enable);
cec_restore_logical_addr(cec_sel, cec_dev->cec_info.addr_enable);
}
void cec_rx_buf_clear(void)
@@ -1110,9 +1115,9 @@ void cec_clear_all_logical_addr(unsigned int cec_sel)
{
CEC_INFO("clear all logical addr\n");
if (cec_sel) {
if (cec_sel == CEC_B) {
hdmirx_cec_write(DWC_CEC_ADDR_L, 0);
hdmirx_cec_write(DWC_CEC_ADDR_H, 0x80);
hdmirx_cec_write(DWC_CEC_ADDR_H, 0);
} else {
aocec_wr_reg(CEC_LOGICAL_ADDR0, 0);
aocec_wr_reg(CEC_LOGICAL_ADDR1, 0);
@@ -1162,7 +1167,10 @@ int cec_rx_buf_check(void)
if (ee_cec == CEC_B) {
cecrx_check_irq_enable();
cecb_irq_handle();
return 0;
} else {
rx_num_msg = aocec_rd_reg(CEC_RX_NUM_MSG);
if (rx_num_msg)
CEC_INFO("rx msg num:0x%02x\n", rx_num_msg);
}
return rx_num_msg;
}
@@ -1404,7 +1412,7 @@ int cec_ll_tx(const unsigned char *msg, unsigned char len)
* address already set. Must clear it before poll again
*/
if (is_poll_message(msg[0]))
cec_clear_all_logical_addr(ee_cec);
cec_clear_all_logical_addr(cec_sel);
/*
* for CEC CTS 9.3. Android will try 3 poll message if got NACK
@@ -1439,7 +1447,7 @@ try_again:
return CEC_FAIL_BUSY;
}
if (ee_cec)
if (cec_sel == CEC_B)
ret = cecb_trigle_tx(msg, len);
else
ret = ceca_trigle_tx(msg, len);
@@ -1683,7 +1691,7 @@ unsigned int cec_phyaddr_config(unsigned int value, bool wr_flag)
/*
void cec_keep_reset(void)
{
if (ee_cec)
if (ee_cec == CEC_B)
cecb_hw_reset();
else
writel(0x1, cec_dev->cec_reg + AO_CEC_GEN_CNTL);
@@ -1702,16 +1710,21 @@ static void cec_pre_init(void)
wake_ok = 0;
pr_info("cec: wake up flag:%x\n", reg);
if (ee_cec) {
ao_cecb_init();
/*cec_logicaddr_set(cec_dev->cec_info.log_addr);*/
} else {
if (cec_dev->cec_num > 1) {
ao_ceca_init();
ao_cecb_init();
} else {
if (ee_cec == CEC_B)
ao_cecb_init();
else
ao_ceca_init();
}
//need restore all logical address
cec_restore_logical_addr(cec_dev->cec_info.addr_enable);
if (cec_dev->cec_num > 1)
cec_restore_logical_addr(CEC_B, cec_dev->cec_info.addr_enable);
else
cec_restore_logical_addr(ee_cec, cec_dev->cec_info.addr_enable);
}
static int cec_late_check_rx_buffer(void)
@@ -2159,7 +2172,37 @@ static ssize_t port_num_show(struct class *cla,
static ssize_t dump_reg_show(struct class *cla,
struct class_attribute *attr, char *b)
{
return dump_cecrx_reg(b);
int i, s = 0;
if (ee_cec == CEC_B)
return dump_cecrx_reg(b);
s += sprintf(b + s, "TX buffer:\n");
for (i = 0; i <= CEC_TX_MSG_F_OP14; i++)
s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i));
for (i = 0; i < ARRAY_SIZE(cec_reg_name1); i++) {
s += sprintf(b + s, "%s:%2x\n",
cec_reg_name1[i], aocec_rd_reg(i + 0x10));
}
s += sprintf(b + s, "RX buffer:\n");
for (i = 0; i <= CEC_TX_MSG_F_OP14; i++)
s += sprintf(b + s, "%2d:%2x\n", i, aocec_rd_reg(i + 0x80));
for (i = 0; i < ARRAY_SIZE(cec_reg_name2); i++) {
s += sprintf(b + s, "%s:%2x\n",
cec_reg_name2[i], aocec_rd_reg(i + 0x90));
}
if (cec_dev->plat_data->chip_id >= CEC_CHIP_ID_TL1) {
for (i = 0; i < ARRAY_SIZE(ceca_reg_name3); i++) {
s += sprintf(b + s, "%s:%2x\n",
ceca_reg_name3[i], aocec_rd_reg(i + 0xA0));
}
}
return s;
}
static ssize_t arc_port_show(struct class *cla,
@@ -2479,21 +2522,30 @@ static ssize_t dbg_store(struct class *cla, struct class_attribute *attr,
} else if (token && strncmp(token, "clraddr", 7) == 0) {
cec_dev->cec_info.addr_enable = 0;
cec_clear_all_logical_addr(ee_cec);
} else if (token && strncmp(token, "clralladdr", 10) == 0) {
cec_dev->cec_info.addr_enable = 0;
cec_clear_all_logical_addr(0);
cec_clear_all_logical_addr(1);
} else if (token && strncmp(token, "addaddr", 7) == 0) {
token = strsep(&cur, delim);
/*string to int*/
if (!token || kstrtouint(token, 16, &addr) < 0)
return count;
cec_dev->cec_info.addr_enable |= (1 << (addr & 0xf));
cec_logicaddr_add(ee_cec, addr);
if (cec_dev->cec_num > 1)
cec_logicaddr_add(CEC_B, addr);
else
cec_logicaddr_add(ee_cec, addr);
} else if (token && strncmp(token, "rmaddr", 6) == 0) {
token = strsep(&cur, delim);
/*string to int*/
if (!token || kstrtouint(token, 16, &addr) < 0)
return count;
cec_dev->cec_info.addr_enable &= ~(1 << (addr & 0xf));
cec_logicaddr_remove(addr);
if (cec_dev->cec_num > 1)
cec_logicaddr_remove(CEC_B, addr);
else
cec_logicaddr_remove(ee_cec, addr);
} else {
if (token)
CEC_ERR("no cmd:%s\n", token);
@@ -2715,15 +2767,33 @@ void cec_dump_info(void)
kfree(port);
}
if (ee_cec) {
if (cec_dev->cec_num > 1) {
CEC_ERR("addrL 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_L));
CEC_ERR("addrH 0x%x\n", hdmirx_cec_read(DWC_CEC_ADDR_H));
} else {
CEC_ERR("addr0 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR0));
CEC_ERR("addr1 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR1));
CEC_ERR("addr2 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR2));
CEC_ERR("addr3 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR3));
CEC_ERR("addr4 0x%x\n", aocec_rd_reg(CEC_LOGICAL_ADDR4));
} else {
if (ee_cec == CEC_B) {
CEC_ERR("addrL 0x%x\n",
hdmirx_cec_read(DWC_CEC_ADDR_L));
CEC_ERR("addrH 0x%x\n",
hdmirx_cec_read(DWC_CEC_ADDR_H));
} else {
CEC_ERR("addr0 0x%x\n",
aocec_rd_reg(CEC_LOGICAL_ADDR0));
CEC_ERR("addr1 0x%x\n",
aocec_rd_reg(CEC_LOGICAL_ADDR1));
CEC_ERR("addr2 0x%x\n",
aocec_rd_reg(CEC_LOGICAL_ADDR2));
CEC_ERR("addr3 0x%x\n",
aocec_rd_reg(CEC_LOGICAL_ADDR3));
CEC_ERR("addr4 0x%x\n",
aocec_rd_reg(CEC_LOGICAL_ADDR4));
}
}
CEC_ERR("addr_enable:0x%x\n", cec_dev->cec_info.addr_enable);
}
@@ -2894,6 +2964,10 @@ static long hdmitx_cec_ioctl(struct file *f,
tmp = arg & 0xf;
/*cec_logicaddr_set(tmp);*/
cec_logicaddr_add(ee_cec, tmp);
if (cec_dev->cec_num > 1)
cec_logicaddr_add(CEC_B, tmp);
else
cec_logicaddr_add(ee_cec, tmp);
cec_dev->cec_info.addr_enable |= (1 << tmp);
/* add by hal, to init some data structure */
@@ -2905,7 +2979,10 @@ static long hdmitx_cec_ioctl(struct file *f,
break;
case CEC_IOC_CLR_LOGICAL_ADDR:
cec_clear_all_logical_addr(ee_cec);
if (cec_dev->cec_num > 1)
cec_clear_all_logical_addr(CEC_B);
else
cec_clear_all_logical_addr(ee_cec);
cec_dev->cec_info.addr_enable = 0;
break;
@@ -3203,6 +3280,7 @@ static int aml_cec_probe(struct platform_device *pdev)
input_free_device(cec_dev->cec_info.remote_cec_dev);
}
#ifdef CONFIG_OF
/* config: read from dts */
r = of_property_read_u32(node, "cec_sel", &(cec_dev->cec_num));
if (r) {
@@ -3383,15 +3461,16 @@ static int aml_cec_probe(struct platform_device *pdev)
CEC_ERR("irq cnt:%d\n", of_irq_count(node));
if (of_get_property(node, "interrupt-names", NULL)) {
r = of_property_read_string(node, "interrupt-names", &irq_name);
if (!r && !ee_cec) {
r = request_irq(irq_idx, &ceca_isr, IRQF_SHARED,
irq_name, (void *)cec_dev);
if (cec_dev->cec_num > 1) {
/* request two int source */
CEC_ERR("request_irq two irq src\n");
r = request_irq(cec_dev->irq_ceca, &ceca_isr,
IRQF_SHARED, irq_name, (void *)cec_dev);
if (r < 0)
CEC_INFO("aocec irq request fail\n");
}
if (!r && ee_cec) {
r = request_irq(irq_idx, &cecb_isr, IRQF_SHARED,
irq_name, (void *)cec_dev);
r = request_irq(cec_dev->irq_cecb, &cecb_isr,
IRQF_SHARED, irq_name, (void *)cec_dev);
if (r < 0)
CEC_INFO("cecb irq request fail\n");
} else {
@@ -3411,12 +3490,15 @@ static int aml_cec_probe(struct platform_device *pdev)
}
}
last_cec_msg = devm_kzalloc(&pdev->dev,
sizeof(*last_cec_msg), GFP_KERNEL);
if (!last_cec_msg) {
CEC_ERR("allocate last_cec_msg failed\n");
ret = -ENOMEM;
goto tag_cec_msg_alloc_err;
/* if (ee_cec == CEC_A) */
{
last_cec_msg = devm_kzalloc(&pdev->dev,
sizeof(*last_cec_msg), GFP_KERNEL);
if (!last_cec_msg) {
CEC_ERR("allocate last_cec_msg failed\n");
ret = -ENOMEM;
goto tag_cec_msg_alloc_err;
}
}
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -3527,7 +3609,10 @@ static int aml_cec_suspend_noirq(struct device *dev)
int ret = 0;
CEC_INFO("cec suspend noirq\n");
cec_clear_all_logical_addr(ee_cec);
if (cec_dev->cec_num > 1)
cec_clear_all_logical_addr(CEC_B);
else
cec_clear_all_logical_addr(ee_cec);
if (!IS_ERR(cec_dev->dbg_dev->pins->sleep_state))
ret = pinctrl_pm_select_sleep_state(cec_dev->dbg_dev);

View File

@@ -541,8 +541,9 @@ void aocec_irq_enable(bool enable);
extern void dump_reg(void);
#endif
extern void cec_dump_info(void);
extern void cec_hw_reset(void);
extern void cec_restore_logical_addr(unsigned int addr_en);
extern void cec_hw_reset(unsigned int cec_sel);
extern void cec_restore_logical_addr(unsigned int cec_sel,
unsigned int addr_en);
extern void cec_logicaddr_add(unsigned int cec_sel, unsigned int l_add);
extern void cec_clear_all_logical_addr(unsigned int cec_sel);
#endif /* __AO_CEC_H__ */