diff --git a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c index 3e02633437a0..bde56ea9377b 100644 --- a/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c +++ b/drivers/media/platform/rockchip/hdmirx/rk_hdmirx.c @@ -71,7 +71,7 @@ MODULE_PARM_DESC(low_latency, "low_latency en(0-1)"); #define MEMORY_ALIGN_ROUND_UP_BYTES 64 #define HDMIRX_PLANE_Y 0 #define HDMIRX_PLANE_CBCR 1 -#define INIT_FIFO_STATE 64 +#define INIT_FIFO_STATE 128 #define RK_IRQ_HDMIRX_HDMI 210 #define FILTER_FRAME_CNT 6 #define CPU_LIMIT_FREQ_KHZ 1200000 @@ -3492,12 +3492,43 @@ static void hdmirx_audio_clk_ppm_inc(struct rk_hdmirx_dev *hdmirx_dev, int ppm) delta = (int)div64_u64((uint64_t)rate * ppm + 500000, 1000000); delta *= inc; rate = hdmirx_dev->audio_state.hdmirx_aud_clkrate + delta; - dev_dbg(hdmirx_dev->dev, "%s: %u to %u(delta:%d)\n", - __func__, hdmirx_dev->audio_state.hdmirx_aud_clkrate, rate, delta); + dev_dbg(hdmirx_dev->dev, "%s: %u to %u(delta:%d ppm:%d)\n", + __func__, hdmirx_dev->audio_state.hdmirx_aud_clkrate, rate, delta, ppm); clk_set_rate(hdmirx_dev->clks[1].clk, rate); hdmirx_dev->audio_state.hdmirx_aud_clkrate = rate; } +static int hdmirx_audio_clk_adjust(struct rk_hdmirx_dev *hdmirx_dev, + int total_offset, int single_offset) +{ + int shedule_time = 500; + int ppm = 10; + uint32_t offset_abs; + + offset_abs = abs(total_offset); + if (offset_abs > 200) { + ppm += 200; + shedule_time -= 100; + } + if (offset_abs > 100) { + ppm += 200; + shedule_time -= 100; + } + if (offset_abs > 32) { + ppm += 20; + shedule_time -= 100; + } + if (offset_abs > 16) + ppm += 20; + if (total_offset > 16 && single_offset > 0) + hdmirx_audio_clk_ppm_inc(hdmirx_dev, ppm); + else if (total_offset < -16 && single_offset < 0) + hdmirx_audio_clk_ppm_inc(hdmirx_dev, -ppm); + if (!hdmirx_dev->audio_present) + shedule_time = 50; + return shedule_time; +} + static void hdmirx_audio_set_state(struct rk_hdmirx_dev *hdmirx_dev, enum audio_stat stat) { switch (stat) { @@ -3730,10 +3761,8 @@ static void hdmirx_delayed_work_audio(struct work_struct *work) process_audio_change(hdmirx_dev); hdmirx_dev->audio_present = true; } - if (cur_state - init_state > 16 && cur_state - pre_state > 0) - hdmirx_audio_clk_ppm_inc(hdmirx_dev, 10); - else if (cur_state - init_state < -16 && cur_state - pre_state < 0) - hdmirx_audio_clk_ppm_inc(hdmirx_dev, -10); + delay = hdmirx_audio_clk_adjust(hdmirx_dev, cur_state - init_state, + cur_state - pre_state); } else { if (hdmirx_dev->audio_present) { dev_info(hdmirx_dev->dev, "audio off");