mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
media: rockchip: hdmirx: enhance compatibility and stability
1.Add phy configuration retry when signal can not be locked. 2.Add the judgment that signal locking has stabilized. 3.Add the judgment of signal loss when starting stream. 4.Modify the calculation method of pixclk and fps in YUV420 format. 5.When DMA is enabled, if the 5V_Det level changes, an interrupt will be forcibly triggered to reset the controller in BL31 as soon as possible. Signed-off-by: Dingxian Wen <shawn.wen@rock-chips.com> Change-Id: I27846bca7059d834b5bd069b5959a2279295568d
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user