mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
media: rockchip: hdmirx: fix audio fifo underflow or overflow when working for audio with high jitter
Signed-off-by: Shunhua Lan <lsh@rock-chips.com> Change-Id: Ibf4dc35997e742119aaae28a9a4deb4bcdf65b7e
This commit is contained in:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user