drm: bridge: dw-hdmi: add more check for HDCP function
authorZheng Yang <zhengyang@rock-chips.com>
Mon, 19 Jun 2017 09:49:31 +0000 (17:49 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 20 Jun 2017 01:23:45 +0000 (09:23 +0800)
On RK3328, dw-hdmi HDCP driver is loaded slower than dw-hdmi.
hdmi->hdcp->hdcp_start is NULL when dw-hdmi call the hdcp_start,
cause following system crash:

Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = ffffff8009292000
[00000000] *pgd=000000007e1fe003, *pud=000000007e1fe003, *pmd=0000000000000000
Internal error: Oops: 86000005 [#1] SMP
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.4.70 #418
Hardware name: Rockchip RK3328 EVB (DT)
task: ffffffc0003a0000 ti: ffffffc0003a8000 task.ti: ffffffc0003a8000
PC is at 0x0
LR is at dw_hdmi_update_power+0xef4/0x1004
pc : [<0000000000000000>] lr : [<ffffff800849e778>] pstate: 60000045
sp : ffffffc0003ab3b0
x29: ffffffc0003ab3b0 x28: 000000000000410b
x27: 0000000000000000 x26: 0000000000000000
x25: ffffffc07770d028 x24: 000000000000410b
x23: 0000000000000000 x22: 0000000000000001
x21: 0000000000000002 x20: ffffff8008c02000
x19: ffffff8008c02d90 x18: 0000000062475a46
x17: 0000000000000000 x16: 000000000000000e
x15: 0000000000000007 x14: 0ffffffffffffffd
x13: 0000000000000018 x12: 0101010101010101
x11: 7f7f7f7f7f7fff7f x10: fefefefeff01f305
x9 : ff7fff7f7f7f7f7f x8 : ffffff80091db5df
x7 : 0000000000000000 x6 : 0000000000000004
x5 : 0000000000000015 x4 : 0000000000140b82
x3 : 000000000106b1af x2 : 0000000000000001
x1 : 0000000000000000 x0 : ffffffc076e25e00

Change-Id: I0fccf9d8e06f7acdb56d8e5360acf0df026fee10
Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
drivers/gpu/drm/bridge/dw-hdmi.c

index 6e34106c0a06e0dbc2ff1eb166b5da182dbff518..c5b5963f39239b899bc24eb87664c4d18428713f 100644 (file)
@@ -1581,7 +1581,7 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi,
        hdmi_modb(hdmi, hdmi_dvi, HDMI_A_HDCPCFG0_HDMIDVI_MASK,
                  HDMI_A_HDCPCFG0);
 
-       if (hdmi->hdcp)
+       if (hdmi->hdcp && hdmi->hdcp->hdcp_start)
                hdmi->hdcp->hdcp_start(hdmi->hdcp);
 }
 
@@ -2159,7 +2159,7 @@ static void dw_hdmi_poweroff(struct dw_hdmi *hdmi)
                hdmi->phy.enabled = false;
        }
 
-       if (hdmi->hdcp)
+       if (hdmi->hdcp && hdmi->hdcp->hdcp_stop)
                hdmi->hdcp->hdcp_stop(hdmi->hdcp);
        hdmi->bridge_is_on = false;
 }
@@ -2478,7 +2478,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
 
        hdcp_stat = hdmi_readb(hdmi, HDMI_A_APIINTSTAT);
        if (hdcp_stat) {
-               if (hdmi->hdcp)
+               if (hdmi->hdcp && hdmi->hdcp->hdcp_isr)
                        hdmi->hdcp->hdcp_isr(hdmi->hdcp, hdcp_stat);
                hdmi_writeb(hdmi, hdcp_stat, HDMI_A_APIINTCLR);
                hdmi_writeb(hdmi, 0x00, HDMI_A_APIINTMSK);