HDMI: improve cec function:

1. To get logic address more stable, we ping 3 times to each
	   logic address. If the result is NACK for two times, this
	   logic address is not occupied.
        2. If transmmit cec data failed, retry immediately.
        4. set CECOP_IMAGE_VIEW_ON only taget to TV, not broadcasting.

Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
This commit is contained in:
Zheng Yang
2015-04-02 16:56:40 +08:00
parent 9e22aee0dd
commit e981d562c2
2 changed files with 86 additions and 27 deletions

View File

@@ -85,7 +85,7 @@ static void cecsendimageview(void)
cecframe.opcode = CECOP_IMAGE_VIEW_ON;
cecframe.srcdestaddr = MAKE_SRCDEST(cec_dev->address_logic,
CEC_LOGADDR_UNREGORBC);
CEC_LOGADDR_TV);
cecframe.argcount = 0;
cecsendframe(&cecframe);
}
@@ -394,14 +394,27 @@ static void cecenumeration(void)
CEC_LOGADDR_PLAYBACK2,
CEC_LOGADDR_PLAYBACK3};
int i;
int trynum;
int rtvalue;
int availablecnt;
if (!cec_dev)
return;
for (i = 0; i < 3; i++) {
if (cecsendping(logicaddress[i])) {
rtvalue = 0;
availablecnt = 0;
for (trynum = 0; trynum < 3; trynum++) {
rtvalue = cecsendping(logicaddress[i]);
if (rtvalue == 1) {
availablecnt++;
CECDBG("availablecnt: %d\n", availablecnt);
}
mdelay(5);
}
if (availablecnt > 1) {
cec_dev->address_logic = logicaddress[i];
CECDBG("Logic Address is 0x%x\n",
CECDBG("logic address is 0x%x\n",
cec_dev->address_logic);
break;
}

View File

@@ -51,8 +51,10 @@ static int rockchip_hdmiv2_cec_sendframe(struct hdmi *hdmi,
{
struct hdmi_dev *hdmi_dev = hdmi->property->priv;
int i, interrupt;
int retrycnt = 0;
int pingretry = 0, pingflg = 0;
CECDBG("TX srcdestaddr %02x opcode %02x ",
CECDBG("TX srcDestAddr %02x opcode %02x ",
frame->srcdestaddr, frame->opcode);
if (frame->argcount) {
CECDBG("args:");
@@ -60,32 +62,76 @@ static int rockchip_hdmiv2_cec_sendframe(struct hdmi *hdmi,
CECDBG("%02x ", frame->args[i]);
}
CECDBG("\n");
if ((frame->srcdestaddr & 0x0f) == ((frame->srcdestaddr >> 4) & 0x0f)) {
/*it is a ping command*/
hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
hdmi_writel(hdmi_dev, CEC_TX_CNT, 1);
} else {
hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
hdmi_writel(hdmi_dev, CEC_TX_DATA0 + 1, frame->opcode);
for (i = 0; i < frame->argcount; i++)
hdmi_writel(hdmi_dev,
CEC_TX_DATA0 + 2 + i, frame->args[i]);
hdmi_writel(hdmi_dev, CEC_TX_CNT, frame->argcount + 2);
}
/*Start TX*/
hdmi_msk_reg(hdmi_dev, CEC_CTRL, m_CEC_SEND, v_CEC_SEND(1));
i = 20;
while (i--) {
usleep_range(900, 1000);
interrupt = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
if (interrupt & (m_ERR_INITIATOR | m_ARB_LOST |
m_NACK | m_DONE)) {
hdmi_writel(hdmi_dev, IH_CEC_STAT0,
interrupt & (m_ERR_INITIATOR |
m_ARB_LOST | m_NACK | m_DONE));
while (retrycnt < 3) {
if (retrycnt) {
hdmi_msk_reg(hdmi_dev, CEC_CTRL, m_CEC_FRAME_TYPE,
v_CEC_FRAME_TYPE(0));
}
CECDBG("reTryCnt: %d\n", retrycnt);
if ((frame->srcdestaddr & 0x0f) ==
((frame->srcdestaddr >> 4) & 0x0f)) {
/*it is a ping command*/
pingflg = 1;
if (pingretry >= 3)
break;
CECDBG("PingRetry: %d\n", pingretry);
hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
hdmi_writel(hdmi_dev, CEC_TX_CNT, 1);
} else {
hdmi_writel(hdmi_dev, CEC_TX_DATA0, frame->srcdestaddr);
hdmi_writel(hdmi_dev, CEC_TX_DATA0 + 1, frame->opcode);
for (i = 0; i < frame->argcount; i++)
hdmi_writel(hdmi_dev,
CEC_TX_DATA0 + 2 + i,
frame->args[i]);
hdmi_writel(hdmi_dev, CEC_TX_CNT,
frame->argcount + 2);
}
/*Start TX*/
hdmi_msk_reg(hdmi_dev, CEC_CTRL, m_CEC_SEND, v_CEC_SEND(1));
i = 60;
while (i--) {
usleep_range(900, 1000);
interrupt = hdmi_readl(hdmi_dev, IH_CEC_STAT0);
if (interrupt & (m_ERR_INITIATOR | m_ARB_LOST |
m_NACK | m_DONE)) {
hdmi_writel(hdmi_dev, IH_CEC_STAT0,
interrupt & (m_ERR_INITIATOR |
m_ARB_LOST | m_NACK | m_DONE));
break;
}
}
if ((interrupt & m_DONE)) {
if (retrycnt > 1)
hdmi_msk_reg(hdmi_dev, CEC_CTRL,
m_CEC_FRAME_TYPE,
v_CEC_FRAME_TYPE(2));
break;
} else {
retrycnt++;
}
if (pingflg == 1) {
if (!(interrupt & (m_DONE | m_NACK))) {
pingretry++;
} else {
/*got ack or no nack, finish ping retry action*/
if (retrycnt > 1)
hdmi_msk_reg(hdmi_dev, CEC_CTRL,
m_CEC_FRAME_TYPE,
v_CEC_FRAME_TYPE(2));
break;
}
}
}
if (retrycnt >= 3)
CECDBG("send cec frame retry timeout !\n");
if (pingretry >= 3)
CECDBG("send cec frame pingretry timeout !\n");
CECDBG("%s interrupt 0x%02x\n", __func__, interrupt);
if (interrupt & m_DONE)
return 0;