diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 3f8675c3f4ad..eef3efaed204 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -72,6 +72,8 @@ MODULE_PARM_DESC(debug, "debug level (0-3)"); #define WAIT_PHY_REG_TIME 50 #define WAIT_TIMER_LOCK_TIME 50 #define WAIT_SIGNAL_LOCK_TIME 600 /* if 5V present: 7ms each time */ +#define NO_LOCK_CFG_RETRY_TIME 300 +#define WAIT_LOCK_STABLE_TIME 20 #define WAIT_AVI_PKT_TIME 300 #define is_validfs(x) (x == 32000 || \ @@ -266,6 +268,7 @@ static void hdmirx_audio_interrupts_setup(struct rk_hdmirx_dev *hdmirx_dev, bool static int hdmirx_set_cpu_limit_freq(struct rk_hdmirx_dev *hdmirx_dev); static void hdmirx_cancel_cpu_limit_freq(struct rk_hdmirx_dev *hdmirx_dev); static void hdmirx_plugout(struct rk_hdmirx_dev *hdmirx_dev); +static void process_signal_change(struct rk_hdmirx_dev *hdmirx_dev); static u8 edid_init_data_340M[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, @@ -770,8 +773,6 @@ static void hdmirx_get_timings(struct rk_hdmirx_dev *hdmirx_dev, hact = (hact * 24) / hdmirx_dev->color_depth; fps = (bt->pixelclock + (htotal * vtotal) / 2) / (htotal * vtotal); - if (hdmirx_dev->pix_fmt == HDMIRX_YUV420) - fps *= 2; bt->width = hact; bt->height = vact; bt->hfrontporch = hfp; @@ -846,6 +847,8 @@ static int hdmirx_get_detected_timings(struct rk_hdmirx_dev *hdmirx_dev, do_div(tmp_data, color_depth); pix_clk = tmp_data; bt->pixelclock = tmds_clk; + if (hdmirx_dev->pix_fmt == HDMIRX_YUV420) + bt->pixelclock *= 2; hdmirx_get_timings(hdmirx_dev, bt, from_dma); if (bt->interlaced == V4L2_DV_INTERLACED) { @@ -1473,11 +1476,11 @@ static void hdmirx_set_ddr_store_fmt(struct rk_hdmirx_dev *hdmirx_dev) static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev) { - u32 i; + u32 i, j = 0; u32 mu_status, scdc_status, dma_st10, cmu_st; struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev; - for (i = 0; i < WAIT_SIGNAL_LOCK_TIME; i++) { + for (i = 1; i < WAIT_SIGNAL_LOCK_TIME; i++) { mu_status = hdmirx_readl(hdmirx_dev, MAINUNIT_STATUS); scdc_status = hdmirx_readl(hdmirx_dev, SCDC_REGBANK_STATUS3); dma_st10 = hdmirx_readl(hdmirx_dev, DMA_STATUS10); @@ -1486,8 +1489,16 @@ static int hdmirx_wait_lock_and_get_timing(struct rk_hdmirx_dev *hdmirx_dev) if ((mu_status & TMDSVALID_STABLE_ST) && (dma_st10 & HDMIRX_LOCK) && (cmu_st & TMDSQPCLK_LOCKED_ST)) + j++; + else + j = 0; + + if (j > WAIT_LOCK_STABLE_TIME) break; + if (i % NO_LOCK_CFG_RETRY_TIME == 0) + hdmirx_phy_config(hdmirx_dev); + if (!tx_5v_power_present(hdmirx_dev)) { v4l2_err(v4l2_dev, "%s HDMI pull out, return!\n", __func__); return -1; @@ -2022,6 +2033,12 @@ static int hdmirx_start_streaming(struct vb2_queue *queue, unsigned int count) return 0; } + if (signal_not_lock(hdmirx_dev)) { + v4l2_err(v4l2_dev, "%s: signal is not locked, retry!\n", __func__); + process_signal_change(hdmirx_dev); + return 0; + } + mutex_lock(&hdmirx_dev->stream_lock); sip_hdmirx_config(HDMIRX_AUTO_TOUCH_EN, 0, 1, 100); stream->frame_idx = 0; @@ -3269,6 +3286,14 @@ static irqreturn_t hdmirx_5v_det_irq_handler(int irq, void *dev_id) { struct rk_hdmirx_dev *hdmirx_dev = dev_id; u32 val; + u32 dma_cfg6; + + dma_cfg6 = hdmirx_readl(hdmirx_dev, DMA_CONFIG6); + if (dma_cfg6 & HDMIRX_DMA_EN) { + hdmirx_update_bits(hdmirx_dev, MAINUNIT_2_INT_MASK_N, + TMDSVALID_STABLE_CHG, TMDSVALID_STABLE_CHG); + hdmirx_writel(hdmirx_dev, MAINUNIT_2_INT_FORCE, TMDSVALID_STABLE_CHG); + } val = gpiod_get_value(hdmirx_dev->hdmirx_det_gpio); v4l2_dbg(3, debug, &hdmirx_dev->v4l2_dev, "%s: 5v:%d\n", __func__, val);