media: rockchip: hdmirx: fix issue that interrupt cannot be cleared

Change-Id: I93e39371dc6823b7498a358dce6faea8488509a7
Signed-off-by: Chen Shunqing <csq@rock-chips.com>
This commit is contained in:
Chen Shunqing
2022-12-12 08:49:09 +00:00
committed by Tao Huang
parent 8aca10e8ce
commit b70ef84c17

View File

@@ -444,6 +444,17 @@ static void hdmirx_update_bits(struct rk_hdmirx_dev *hdmirx_dev, int reg, u32 ma
spin_unlock_irqrestore(&hdmirx_dev->rst_lock, lock_flags);
}
/*
* Before clearing interrupt need to read the interrupt status.
*/
static inline void hdmirx_clear_interrupt(struct rk_hdmirx_dev *hdmirx_dev,
u32 reg, u32 val)
{
/* (interrupt status register) = (interrupt clear register) - 0x8 */
hdmirx_readl(hdmirx_dev, reg - 0x8);
hdmirx_writel(hdmirx_dev, reg, val);
}
static int hdmirx_subscribe_event(struct v4l2_fh *fh,
const struct v4l2_event_subscription *sub)
{
@@ -1230,7 +1241,7 @@ static int hdmirx_phy_register_read(struct rk_hdmirx_dev *hdmirx_dev,
hdmirx_dev->cr_read_done = false;
/* clear irq status */
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
/* en irq */
hdmirx_update_bits(hdmirx_dev, MAINUNIT_2_INT_MASK_N,
PHYCREG_CR_READ_DONE, PHYCREG_CR_READ_DONE);
@@ -1264,7 +1275,7 @@ static int hdmirx_phy_register_write(struct rk_hdmirx_dev *hdmirx_dev,
hdmirx_dev->cr_write_done = false;
/* clear irq status */
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
/* en irq */
hdmirx_update_bits(hdmirx_dev, MAINUNIT_2_INT_MASK_N,
PHYCREG_CR_WRITE_DONE, PHYCREG_CR_WRITE_DONE);
@@ -1313,7 +1324,7 @@ static void hdmirx_phy_config(struct rk_hdmirx_dev *hdmirx_dev)
{
struct device *dev = hdmirx_dev->dev;
hdmirx_writel(hdmirx_dev, SCDC_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, SCDC_INT_CLEAR, 0xffffffff);
hdmirx_update_bits(hdmirx_dev, SCDC_INT_MASK_N, SCDCTMDSCCFG_CHG,
SCDCTMDSCCFG_CHG);
/* cr_para_clk 24M */
@@ -1379,7 +1390,7 @@ static void hdmirx_controller_init(struct rk_hdmirx_dev *hdmirx_dev)
struct device *dev = hdmirx_dev->dev;
hdmirx_dev->timer_base_lock = false;
hdmirx_writel(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
/* en irq */
hdmirx_update_bits(hdmirx_dev, MAINUNIT_0_INT_MASK_N,
TIMER_BASE_LOCKED_IRQ, TIMER_BASE_LOCKED_IRQ);
@@ -1517,7 +1528,7 @@ static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev)
hdmirx_writel(hdmirx_dev, GLOBAL_SWRESET_REQUEST, DATAPATH_SWRESETREQ);
hdmirx_dev->avi_pkt_rcv = false;
hdmirx_writel(hdmirx_dev, PKT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, PKT_2_INT_CLEAR, 0xffffffff);
hdmirx_update_bits(hdmirx_dev, PKT_2_INT_MASK_N,
PKTDEC_AVIIF_RCV_IRQ, PKTDEC_AVIIF_RCV_IRQ);
@@ -2056,7 +2067,7 @@ static int hdmirx_get_hdcp_auth_status(struct rk_hdmirx_dev *hdmirx_dev)
{
u32 val;
hdmirx_writel(hdmirx_dev, HDCP_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, HDCP_INT_CLEAR, 0xffffffff);
msleep(200);
val = hdmirx_readl(hdmirx_dev, HDCP_INT_STATUS) & 0x40;
@@ -2284,7 +2295,7 @@ static void avpunit_0_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
*handled = true;
}
hdmirx_writel(hdmirx_dev, AVPUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, AVPUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, AVPUNIT_0_INT_FORCE, 0x0);
}
@@ -2328,7 +2339,7 @@ static void mainunit_0_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
*handled = true;
}
hdmirx_writel(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_0_INT_FORCE, 0x0);
}
@@ -2358,7 +2369,7 @@ static void mainunit_2_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
*handled = true;
}
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_FORCE, 0x0);
}
@@ -2376,7 +2387,7 @@ static void pkt_2_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
*handled = true;
}
hdmirx_writel(hdmirx_dev, PKT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, PKT_2_INT_CLEAR, 0xffffffff);
}
static void scdc_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
@@ -2390,7 +2401,7 @@ static void scdc_int_handler(struct rk_hdmirx_dev *hdmirx_dev,
*handled = true;
}
hdmirx_writel(hdmirx_dev, SCDC_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, SCDC_INT_CLEAR, 0xffffffff);
}
static irqreturn_t hdmirx_hdmi_irq_handler(int irq, void *dev_id)
@@ -2625,11 +2636,9 @@ static void hdmirx_interrupts_setup(struct rk_hdmirx_dev *hdmirx_dev, bool en)
v4l2_dbg(1, debug, &hdmirx_dev->v4l2_dev, "%s: %sable\n",
__func__, en ? "en" : "dis");
/* Note: In DVI mode, it needs to be written twice to take effect. */
hdmirx_writel(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, AVPUNIT_0_INT_CLEAR, 0xffffffff);
if (en) {
hdmirx_update_bits(hdmirx_dev, MAINUNIT_0_INT_MASK_N,
@@ -2857,7 +2866,7 @@ static void hdmirx_audio_setup(struct rk_hdmirx_dev *hdmirx_dev)
hdmirx_update_bits(hdmirx_dev, DEFRAMER_CONFIG0, VS_CNT_THR_QST_MASK, VS_CNT_THR_QST(3));
hdmirx_audio_interrupts_setup(hdmirx_dev, true);
hdmirx_writel(hdmirx_dev, DEFRAMER_VSYNC_CNT_CLEAR, VSYNC_CNT_CLR_P);
hdmirx_writel(hdmirx_dev, AVPUNIT_1_INT_CLEAR, DEFRAMER_VSYNC_THR_REACHED_CLEAR);
hdmirx_clear_interrupt(hdmirx_dev, AVPUNIT_1_INT_CLEAR, DEFRAMER_VSYNC_THR_REACHED_CLEAR);
hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR_PASS, INIT_FIFO_STATE);
hdmirx_writel(hdmirx_dev, AUDIO_FIFO_THR,
AFIFO_THR_LOW_QST(0x20) | AFIFO_THR_HIGH_QST(0x160));
@@ -3248,18 +3257,18 @@ static void hdmirx_disable_all_interrupts(struct rk_hdmirx_dev *hdmirx_dev)
hdmirx_writel(hdmirx_dev, HDCP_1_INT_MASK_N, 0);
hdmirx_writel(hdmirx_dev, CEC_INT_MASK_N, 0);
hdmirx_writel(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_1_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, AVPUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, AVPUNIT_1_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, PKT_0_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, PKT_1_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, PKT_2_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, SCDC_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, HDCP_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, HDCP_1_INT_CLEAR, 0xffffffff);
hdmirx_writel(hdmirx_dev, CEC_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_1_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, MAINUNIT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, AVPUNIT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, AVPUNIT_1_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, PKT_0_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, PKT_1_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, PKT_2_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, SCDC_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, HDCP_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, HDCP_1_INT_CLEAR, 0xffffffff);
hdmirx_clear_interrupt(hdmirx_dev, CEC_INT_CLEAR, 0xffffffff);
}
static int hdmirx_power_on(struct rk_hdmirx_dev *hdmirx_dev)