mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user