From e981d562c221688f8b61f96f7629477372b8ec4e Mon Sep 17 00:00:00 2001 From: Zheng Yang Date: Thu, 2 Apr 2015 16:56:40 +0800 Subject: [PATCH] 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 --- .../video/rockchip/hdmi/rockchip-hdmi-cec.c | 19 +++- .../rockchip-hdmiv2/rockchip_hdmiv2_cec.c | 94 ++++++++++++++----- 2 files changed, 86 insertions(+), 27 deletions(-) diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c b/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c index b73574bfc69b..c7457320b0c1 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c @@ -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; } diff --git a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c index e7c1a8337101..60c23bbfe56b 100644 --- a/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c +++ b/drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c @@ -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; -- 2.34.1