rk32 edp: workround irq
authoryxj <yxj@rock-chips.com>
Thu, 27 Mar 2014 11:10:29 +0000 (19:10 +0800)
committeryxj <yxj@rock-chips.com>
Thu, 27 Mar 2014 11:16:32 +0000 (19:16 +0800)
drivers/video/rockchip/transmitter/rk32_dp.c
drivers/video/rockchip/transmitter/rk32_dp.h
drivers/video/rockchip/transmitter/rk32_dp_reg.c

index dc4b3be4990bde25acf0f6996a4b316e04bd7c66..47bbd2b1b1fab0b14ae783194e26e6acd52a2b75 100644 (file)
@@ -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");
index 360c6dc5c6512ddb91d2c5757766446b5d9510e9..cba57b34bf144c4d37c4fddf5dc06946108868ff 100644 (file)
@@ -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
index 3c28a455023bb6bd2d5c1cfee0f6956f7ec64796..f25a4b2366d4a5c1a668cd12cdf58cacb098ea7c 100644 (file)
@@ -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);
+}
+