From 61b94a7e7616213447dd435fb07aac569d581c18 Mon Sep 17 00:00:00 2001 From: yxj Date: Thu, 27 Mar 2014 19:10:29 +0800 Subject: [PATCH] rk32 edp: workround irq --- drivers/video/rockchip/transmitter/rk32_dp.c | 43 ++++++++++++++----- drivers/video/rockchip/transmitter/rk32_dp.h | 1 + .../video/rockchip/transmitter/rk32_dp_reg.c | 12 +++++- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/video/rockchip/transmitter/rk32_dp.c b/drivers/video/rockchip/transmitter/rk32_dp.c index dc4b3be4990b..47bbd2b1b1fa 100644 --- a/drivers/video/rockchip/transmitter/rk32_dp.c +++ b/drivers/video/rockchip/transmitter/rk32_dp.c @@ -34,8 +34,7 @@ //#define EDP_BIST_MODE static struct rk32_edp *rk32_edp; - - +static int lcdc_probed = 0; static int rk32_edp_clk_enable(struct rk32_edp *edp) { if (!edp->clk_on) { @@ -76,7 +75,6 @@ static int rk32_edp_pre_init(void) val = 0x80000000; writel_relaxed(val, RK_CRU_VIRT + 0x01d0); udelay(1); - return 0; } @@ -1098,8 +1096,34 @@ static irqreturn_t rk32_edp_isr(int irq, void *arg) struct rk32_edp *edp = arg; enum dp_irq_type irq_type; - irq_type = rk32_edp_get_irq_type(edp); + if (!lcdc_probed) { + disable_irq_nosync(edp->irq); + return 0; + } + irq_type = rk32_edp_get_irq_type(edp); + switch (irq_type) { + case DP_IRQ_TYPE_HP_CABLE_IN: + dev_info(edp->dev, "Received irq - cable in\n"); + rk32_edp_clear_hotplug_interrupts(edp); + break; + case DP_IRQ_TYPE_HP_CABLE_OUT: + dev_info(edp->dev, "Received irq - cable out\n"); + rk32_edp_clear_hotplug_interrupts(edp); + break; + case DP_IRQ_TYPE_HP_CHANGE: + /* + * We get these change notifications once in a while, but there + * is nothing we can do with them. Just ignore it for now and + * only handle cable changes. + */ + dev_info(edp->dev, "Received irq - hotplug change; ignoring.\n"); + rk32_edp_clear_hotplug_interrupts(edp); + break; + default: + dev_err(edp->dev, "Received irq - unknown type!\n"); + break; + } return IRQ_HANDLED; } @@ -1111,8 +1135,9 @@ static int rk32_edp_enable(void) rk32_edp_clk_enable(edp); rk32_edp_pre_init(); + lcdc_probed = 1; rk32_edp_init_edp(edp); - + enable_irq(edp->irq); /*ret = rk32_edp_handle_edid(edp); if (ret) { dev_err(edp->dev, "unable to handle edid\n"); @@ -1160,6 +1185,7 @@ static int rk32_edp_disable(void ) { struct rk32_edp *edp = rk32_edp; + disable_irq(edp->irq); rk32_edp_reset(edp); rk32_edp_analog_power_ctr(edp, 0); rk32_edp_clk_disable(edp); @@ -1196,7 +1222,7 @@ static int rk32_edp_probe(struct platform_device *pdev) edp->video_info.color_space = CS_RGB; edp->video_info.dynamic_range = VESA; edp->video_info.ycbcr_coeff = COLOR_YCBCR601; - edp->video_info.color_depth = COLOR_8; + edp->video_info.color_depth = COLOR_6; edp->video_info.link_rate = LINK_RATE_1_62GBPS; edp->video_info.lane_count = LANE_CNT4; @@ -1236,8 +1262,6 @@ static int rk32_edp_probe(struct platform_device *pdev) clk_prepare(edp->pclk); clk_prepare(edp->clk_edp); clk_prepare(edp->clk_24m); - rk32_edp_clk_enable(edp); - rk32_edp_pre_init(); edp->irq = platform_get_irq(pdev, 0); if (edp->irq < 0) { dev_err(&pdev->dev, "cannot find IRQ\n"); @@ -1249,8 +1273,7 @@ static int rk32_edp_probe(struct platform_device *pdev) dev_err(&pdev->dev, "cannot claim IRQ %d\n", edp->irq); return ret; } - disable_irq(edp->irq); - rk32_edp_clk_disable(edp); + disable_irq_nosync(edp->irq); rk32_edp = edp; rk_fb_trsm_ops_register(&trsm_edp_ops, SCREEN_EDP); dev_info(&pdev->dev, "rk32 edp driver probe success\n"); diff --git a/drivers/video/rockchip/transmitter/rk32_dp.h b/drivers/video/rockchip/transmitter/rk32_dp.h index 360c6dc5c651..cba57b34bf14 100644 --- a/drivers/video/rockchip/transmitter/rk32_dp.h +++ b/drivers/video/rockchip/transmitter/rk32_dp.h @@ -617,5 +617,6 @@ void rk32_edp_hw_link_training_en(struct rk32_edp * edp); int rk32_edp_get_hw_lt_status(struct rk32_edp *edp); int rk32_edp_wait_hw_lt_done(struct rk32_edp *edp); enum dp_irq_type rk32_edp_get_irq_type(struct rk32_edp *edp); +void rk32_edp_clear_hotplug_interrupts(struct rk32_edp *edp); #endif diff --git a/drivers/video/rockchip/transmitter/rk32_dp_reg.c b/drivers/video/rockchip/transmitter/rk32_dp_reg.c index 3c28a455023b..f25a4b2366d4 100644 --- a/drivers/video/rockchip/transmitter/rk32_dp_reg.c +++ b/drivers/video/rockchip/transmitter/rk32_dp_reg.c @@ -1287,7 +1287,6 @@ enum dp_irq_type rk32_edp_get_irq_type(struct rk32_edp *edp) /* Parse hotplug interrupt status register */ val = readl(edp->regs + COMMON_INT_STA_4); - if (val & PLUG) return DP_IRQ_TYPE_HP_CABLE_IN; @@ -1300,3 +1299,14 @@ enum dp_irq_type rk32_edp_get_irq_type(struct rk32_edp *edp) return DP_IRQ_TYPE_UNKNOWN; } +void rk32_edp_clear_hotplug_interrupts(struct rk32_edp *edp) +{ + u32 val; + + val = HOTPLUG_CHG | HPD_LOST | PLUG; + writel(val, edp->regs + COMMON_INT_STA_4); + + val = INT_HPD; + writel(val, edp->regs + DP_INT_STA); +} + -- 2.34.1