HDMI: improve cec function:
authorZheng Yang <zhengyang@rock-chips.com>
Thu, 2 Apr 2015 08:56:40 +0000 (16:56 +0800)
committerZheng Yang <zhengyang@rock-chips.com>
Thu, 2 Apr 2015 09:00:23 +0000 (17:00 +0800)
        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>
drivers/video/rockchip/hdmi/rockchip-hdmi-cec.c
drivers/video/rockchip/hdmi/rockchip-hdmiv2/rockchip_hdmiv2_cec.c

index b73574bfc69b8e9a6aed4ab05235cba4e2c1c0ff..c7457320b0c1b94dff2dcd2a1b12b7ff362c11cb 100644 (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;
                }
index e7c1a8337101e530c8b06bf83c9755d997ea8140..60c23bbfe56b08a60ec16a941c7f7caa62c7c6db 100644 (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;