hc
2023-12-11 6778948f9de86c3cfaf36725a7c87dcff9ba247f
kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
....@@ -4,6 +4,7 @@
44 * Author:
55 * Algea Cao <algea.cao@rock-chips.com>
66 */
7
+#include <linux/bitfield.h>
78 #include <linux/clk.h>
89 #include <linux/delay.h>
910 #include <linux/dma-mapping.h>
....@@ -25,6 +26,7 @@
2526 #include <drm/drm_dsc.h>
2627 #include <drm/drm_edid.h>
2728 #include <drm/drm_encoder_slave.h>
29
+#include <drm/drm_hdcp.h>
2830 #include <drm/drm_of.h>
2931 #include <drm/drm_panel.h>
3032 #include <drm/drm_print.h>
....@@ -38,6 +40,7 @@
3840 #include "dw-hdmi-qp-audio.h"
3941 #include "dw-hdmi-qp.h"
4042 #include "dw-hdmi-qp-cec.h"
43
+#include "dw-hdmi-qp-hdcp.h"
4144
4245 #include <media/cec-notifier.h>
4346
....@@ -51,6 +54,19 @@
5154
5255 #define HDMI14_MAX_TMDSCLK 340000000
5356 #define HDMI20_MAX_TMDSCLK_KHZ 600000
57
+
58
+#define HDMI_VH0 0x20
59
+#define HDMI_HDCP_ADDR 0x3a
60
+#define HDMI_BCAPS 0x40
61
+#define HDMI_HDCP14_SUPPORT BIT(7)
62
+#define HDMI_HDCP2_VERSION 0x50
63
+#define HDMI_HDCP2_SUPPORT BIT(2)
64
+
65
+#define SINK_CAP_HDCP14 BIT(0)
66
+#define SINK_CAP_HDCP2 BIT(1)
67
+
68
+#define HDMI_HDCP2_AUTH BIT(1)
69
+#define HDMI_HDCP14_AUTH BIT(0)
5470
5571 static const unsigned int dw_hdmi_cable[] = {
5672 EXTCON_DISP_HDMI,
....@@ -221,6 +237,7 @@
221237 struct dw_hdmi_qp {
222238 struct drm_connector connector;
223239 struct drm_bridge bridge;
240
+ struct drm_bridge *next_bridge;
224241 struct drm_panel *panel;
225242 struct platform_device *hdcp_dev;
226243 struct platform_device *audio;
....@@ -230,7 +247,7 @@
230247
231248 struct hdmi_qp_data_info hdmi_data;
232249 const struct dw_hdmi_plat_data *plat_data;
233
-
250
+ struct dw_qp_hdcp *hdcp;
234251 int vic;
235252 int main_irq;
236253 int avp_irq;
....@@ -249,6 +266,7 @@
249266
250267 struct i2c_adapter *ddc;
251268 void __iomem *regs;
269
+ void __iomem *hdcp14_mem;
252270 bool sink_is_hdmi;
253271 bool sink_has_audio;
254272 bool dclk_en;
....@@ -256,6 +274,7 @@
256274 bool cec_enable;
257275 bool allm_enable;
258276 bool support_hdmi;
277
+ bool skip_connector;
259278 int force_output;
260279 int vp_id;
261280 int old_vp_id;
....@@ -268,6 +287,8 @@
268287 bool rxsense; /* rxsense state */
269288 u8 phy_mask; /* desired phy int mask settings */
270289 u8 mc_clkdis; /* clock disable register */
290
+ u8 hdcp_caps;
291
+ u8 hdcp_status;
271292
272293 bool update;
273294 bool hdr2sdr;
....@@ -944,8 +965,6 @@
944965 {
945966 /* Software reset */
946967 hdmi_writel(hdmi, 0x01, I2CM_CONTROL0);
947
-
948
- hdmi_writel(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0);
949968
950969 hdmi_modb(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0);
951970
....@@ -1877,6 +1896,58 @@
18771896 return tmdsclock;
18781897 }
18791898
1899
+static void dw_hdmi_qp_hdcp_enable(struct dw_hdmi_qp *hdmi,
1900
+ struct drm_connector *connector)
1901
+{
1902
+ int ret, val;
1903
+ const struct drm_connector_state *conn_state = connector->state;
1904
+ void *data = hdmi->plat_data->phy_data;
1905
+
1906
+ if (conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_DESIRED)
1907
+ return;
1908
+
1909
+ /* sink support hdcp2.x */
1910
+ if (hdmi->hdcp_caps & SINK_CAP_HDCP2) {
1911
+ hdmi_writel(hdmi, HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ, AVP_3_INT_CLEAR);
1912
+ hdmi_modb(hdmi, HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ,
1913
+ HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ, AVP_3_INT_MASK_N);
1914
+
1915
+ hdmi_writel(hdmi, 0x35, HDCP2LOGIC_ESM_GPIO_IN);
1916
+ hdmi_modb(hdmi, 0, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
1917
+ if (hdmi->plat_data->set_hdcp2_enable)
1918
+ hdmi->plat_data->set_hdcp2_enable(data, true);
1919
+
1920
+ /* wait hdcp2.X auth success */
1921
+ ret = regmap_read_poll_timeout(hdmi->regm, HDCP2LOGIC_ESM_GPIO_OUT, val,
1922
+ FIELD_GET(HDCP2_AUTHENTICATION_SUCCESS, val),
1923
+ 10000, 2000000);
1924
+ if (ret) {
1925
+ hdmi->hdcp_status &= ~HDMI_HDCP2_AUTH;
1926
+ dev_info(hdmi->dev, "hdcp2 auth failed,start hdcp1.4\n");
1927
+
1928
+ hdmi_writel(hdmi, 0, HDCP2LOGIC_ESM_GPIO_IN);
1929
+ hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
1930
+
1931
+ if (hdmi->plat_data->set_hdcp2_enable)
1932
+ hdmi->plat_data->set_hdcp2_enable(data, false);
1933
+
1934
+ if (hdmi->hdcp && hdmi->hdcp->hdcp_start)
1935
+ hdmi->hdcp->hdcp_start(hdmi->hdcp);
1936
+ goto exit;
1937
+ }
1938
+
1939
+ hdmi->hdcp_status |= HDMI_HDCP2_AUTH;
1940
+ drm_hdcp_update_content_protection(connector, DRM_MODE_CONTENT_PROTECTION_ENABLED);
1941
+ dev_info(hdmi->dev, "HDCP2 authentication succeed\n");
1942
+ } else {
1943
+ if (hdmi->hdcp && hdmi->hdcp->hdcp_start)
1944
+ hdmi->hdcp->hdcp_start(hdmi->hdcp);
1945
+ }
1946
+exit:
1947
+ if (hdmi->plat_data->set_hdcp_status)
1948
+ hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
1949
+}
1950
+
18801951 static int dw_hdmi_qp_setup(struct dw_hdmi_qp *hdmi,
18811952 const struct drm_connector *connector,
18821953 struct drm_display_mode *mode)
....@@ -2038,6 +2109,7 @@
20382109 dev_info(hdmi->dev, "%s DVI mode\n", __func__);
20392110 }
20402111
2112
+ dw_hdmi_qp_hdcp_enable(hdmi, hdmi->curr_conn);
20412113 hdmi->frl_switch = false;
20422114 return 0;
20432115 }
....@@ -2056,6 +2128,9 @@
20562128
20572129 if (hdmi->panel)
20582130 return connector_status_connected;
2131
+
2132
+ if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_DETECT)
2133
+ return drm_bridge_detect(hdmi->next_bridge);
20592134
20602135 if (hdmi->plat_data->left)
20612136 secondary = hdmi->plat_data->left;
....@@ -2124,6 +2199,58 @@
21242199 return false;
21252200 }
21262201
2202
+static ssize_t hdcp_ddc_read(struct i2c_adapter *adapter, u8 address,
2203
+ u8 offset, void *buffer)
2204
+{
2205
+ int ret;
2206
+ struct i2c_msg msgs[2] = {
2207
+ {
2208
+ .addr = address,
2209
+ .flags = 0,
2210
+ .len = 1,
2211
+ .buf = &offset,
2212
+ }, {
2213
+ .addr = address,
2214
+ .flags = I2C_M_RD,
2215
+ .len = 1,
2216
+ .buf = buffer,
2217
+ }
2218
+ };
2219
+
2220
+ ret = i2c_transfer(adapter, msgs, ARRAY_SIZE(msgs));
2221
+ if (ret < 0)
2222
+ return ret;
2223
+ if (ret != ARRAY_SIZE(msgs))
2224
+ return -EPROTO;
2225
+
2226
+ return 0;
2227
+}
2228
+
2229
+static u8 dw_hdmi_qp_hdcp_capable(struct dw_hdmi_qp *hdmi)
2230
+{
2231
+ u8 version = 0;
2232
+ u8 bcaps;
2233
+ int ret;
2234
+
2235
+ ret = hdcp_ddc_read(hdmi->ddc, HDMI_HDCP_ADDR, HDMI_BCAPS, &bcaps);
2236
+ if (ret < 0) {
2237
+ dev_err(hdmi->dev, "get hdcp1.4 capable failed:%d\n", ret);
2238
+ return 0;
2239
+ }
2240
+ if (bcaps & HDMI_HDCP14_SUPPORT)
2241
+ version |= SINK_CAP_HDCP14;
2242
+
2243
+ ret = hdcp_ddc_read(hdmi->ddc, HDMI_HDCP_ADDR, HDMI_HDCP2_VERSION, &bcaps);
2244
+ if (ret < 0) {
2245
+ dev_err(hdmi->dev, "get hdcp2.x capable failed:%d\n", ret);
2246
+ return 0;
2247
+ }
2248
+ if (bcaps & HDMI_HDCP2_SUPPORT)
2249
+ version |= SINK_CAP_HDCP2;
2250
+
2251
+ return version;
2252
+}
2253
+
21272254 static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
21282255 {
21292256 struct dw_hdmi_qp *hdmi =
....@@ -2134,16 +2261,39 @@
21342261 struct drm_display_mode *mode;
21352262 struct drm_display_info *info = &connector->display_info;
21362263 void *data = hdmi->plat_data->phy_data;
2264
+ struct drm_property_blob *edid_blob_ptr = connector->edid_blob_ptr;
21372265 int i, ret = 0;
2266
+
2267
+ if (hdmi->plat_data->right && hdmi->plat_data->right->next_bridge) {
2268
+ struct drm_bridge *bridge = hdmi->plat_data->right->next_bridge;
2269
+
2270
+ if (bridge->ops & DRM_BRIDGE_OP_MODES) {
2271
+ if (!drm_bridge_get_modes(bridge, connector))
2272
+ return 0;
2273
+ }
2274
+ }
21382275
21392276 if (hdmi->panel)
21402277 return drm_panel_get_modes(hdmi->panel, connector);
2278
+
2279
+ if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_MODES)
2280
+ return drm_bridge_get_modes(hdmi->next_bridge, connector);
21412281
21422282 if (!hdmi->ddc)
21432283 return 0;
21442284
21452285 memset(metedata, 0, sizeof(*metedata));
2146
- edid = drm_get_edid(connector, hdmi->ddc);
2286
+
2287
+ if (edid_blob_ptr && edid_blob_ptr->length) {
2288
+ edid = kmalloc(edid_blob_ptr->length, GFP_KERNEL);
2289
+ if (!edid)
2290
+ return -ENOMEM;
2291
+ memcpy(edid, edid_blob_ptr->data, edid_blob_ptr->length);
2292
+ } else {
2293
+ edid = drm_get_edid(connector, hdmi->ddc);
2294
+ hdmi->hdcp_caps = dw_hdmi_qp_hdcp_capable(hdmi);
2295
+ }
2296
+
21472297 if (edid) {
21482298 dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
21492299 edid->width_cm, edid->height_cm);
....@@ -2161,6 +2311,7 @@
21612311 if (hdmi->plat_data->get_yuv422_format)
21622312 hdmi->plat_data->get_yuv422_format(connector, edid);
21632313 dw_hdmi_update_hdr_property(connector);
2314
+ hdmi->hdcp_caps = dw_hdmi_qp_hdcp_capable(hdmi);
21642315 if (ret > 0 && hdmi->plat_data->split_mode) {
21652316 struct dw_hdmi_qp *secondary = NULL;
21662317 void *secondary_data;
....@@ -2170,8 +2321,10 @@
21702321 else if (hdmi->plat_data->right)
21712322 secondary = hdmi->plat_data->right;
21722323
2173
- if (!secondary)
2324
+ if (!secondary) {
2325
+ kfree(edid);
21742326 return -ENOMEM;
2327
+ }
21752328 secondary_data = secondary->plat_data->phy_data;
21762329
21772330 list_for_each_entry(mode, &connector->probed_modes, head)
....@@ -2224,7 +2377,6 @@
22242377
22252378 dev_info(hdmi->dev, "failed to get edid\n");
22262379 }
2227
- dw_hdmi_qp_check_output_type_changed(hdmi);
22282380
22292381 return ret;
22302382 }
....@@ -2444,6 +2596,37 @@
24442596 return false;
24452597 }
24462598
2599
+static bool check_dw_hdcp_state_changed(struct drm_connector *conn,
2600
+ struct drm_atomic_state *state)
2601
+{
2602
+ struct drm_connector_state *old_state, *new_state;
2603
+ u64 old_cp, new_cp;
2604
+
2605
+ old_state = drm_atomic_get_old_connector_state(state, conn);
2606
+ new_state = drm_atomic_get_new_connector_state(state, conn);
2607
+ old_cp = old_state->content_protection;
2608
+ new_cp = new_state->content_protection;
2609
+
2610
+ if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
2611
+ new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
2612
+ new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
2613
+ return true;
2614
+ }
2615
+
2616
+ if (!new_state->crtc) {
2617
+ if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
2618
+ new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
2619
+ return false;
2620
+ }
2621
+
2622
+ if (old_cp == new_cp ||
2623
+ (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
2624
+ new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
2625
+ return false;
2626
+
2627
+ return true;
2628
+}
2629
+
24472630 static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
24482631 struct drm_atomic_state *state)
24492632 {
....@@ -2546,7 +2729,8 @@
25462729 }
25472730
25482731 if (check_hdr_color_change(old_state, new_state, hdmi) || hdmi->logo_plug_out ||
2549
- dw_hdmi_color_changed(connector, state)) {
2732
+ dw_hdmi_color_changed(connector, state) ||
2733
+ dw_hdmi_qp_check_output_type_changed(hdmi)) {
25502734 u32 mtmdsclk;
25512735
25522736 crtc_state = drm_atomic_get_crtc_state(state, crtc);
....@@ -2580,13 +2764,16 @@
25802764 hdmi_modb(hdmi, PKTSCHED_GCP_TX_EN, PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN);
25812765 mdelay(50);
25822766 } else if (!hdmi->disabled) {
2583
- if (mode.clock > 600000)
2767
+ if (hdmi->previous_mode.clock > 600000 && mode.clock > 600000)
25842768 hdmi->frl_switch = true;
25852769 hdmi->update = false;
25862770 crtc_state->mode_changed = true;
25872771 hdmi->logo_plug_out = false;
25882772 }
25892773 }
2774
+
2775
+ if (check_dw_hdcp_state_changed(connector, state))
2776
+ crtc_state->mode_changed = true;
25902777
25912778 return 0;
25922779 }
....@@ -2608,17 +2795,6 @@
26082795 void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val)
26092796 {
26102797 hdmi->force_output = val;
2611
-
2612
- if (!dw_hdmi_qp_check_output_type_changed(hdmi))
2613
- return;
2614
-
2615
- if (hdmi->disabled)
2616
- return;
2617
-
2618
- if (!hdmi->sink_is_hdmi)
2619
- hdmi_modb(hdmi, OPMODE_DVI, OPMODE_DVI, LINK_CONFIG0);
2620
- else
2621
- hdmi_modb(hdmi, 0, OPMODE_DVI, LINK_CONFIG0);
26222798 }
26232799 EXPORT_SYMBOL_GPL(dw_hdmi_qp_set_output_type);
26242800
....@@ -2682,13 +2858,31 @@
26822858 struct drm_connector *connector = &hdmi->connector;
26832859 struct cec_connector_info conn_info;
26842860 struct cec_notifier *notifier;
2861
+ bool skip_connector = false;
26852862
2686
- if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
2863
+ if (hdmi->next_bridge) {
2864
+ struct drm_bridge *next_bridge = hdmi->next_bridge;
2865
+ int ret;
2866
+
2867
+ ret = drm_bridge_attach(bridge->encoder, next_bridge, bridge,
2868
+ next_bridge->ops & DRM_BRIDGE_OP_MODES ?
2869
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR : 0);
2870
+ if (ret) {
2871
+ DRM_ERROR("failed to attach next bridge: %d\n", ret);
2872
+ return ret;
2873
+ }
2874
+
2875
+ skip_connector = !(next_bridge->ops & DRM_BRIDGE_OP_MODES);
2876
+ }
2877
+
2878
+ hdmi->skip_connector = skip_connector;
2879
+ if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR || skip_connector)
26872880 return 0;
26882881
26892882 connector->interlace_allowed = 1;
26902883 connector->polled = DRM_CONNECTOR_POLL_HPD;
2691
-
2884
+ if (hdmi->next_bridge && hdmi->next_bridge->ops & DRM_BRIDGE_OP_DETECT)
2885
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
26922886 drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs);
26932887
26942888 drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs,
....@@ -2728,8 +2922,18 @@
27282922 const struct drm_display_info *info,
27292923 const struct drm_display_mode *mode)
27302924 {
2925
+ struct dw_hdmi_qp *hdmi = bridge->driver_private;
2926
+ const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
2927
+
27312928 if (mode->clock <= 25000)
27322929 return MODE_CLOCK_RANGE;
2930
+
2931
+ if (!hdmi->sink_is_hdmi && mode->clock > 340000)
2932
+ return MODE_BAD;
2933
+
2934
+ if (pdata->mode_valid)
2935
+ return pdata->mode_valid(NULL, pdata->priv_data, info,
2936
+ mode);
27332937
27342938 return MODE_OK;
27352939 }
....@@ -2757,6 +2961,7 @@
27572961 {
27582962 struct dw_hdmi_qp *hdmi = bridge->driver_private;
27592963 void *data = hdmi->plat_data->phy_data;
2964
+ const struct drm_connector_state *conn_state = hdmi->curr_conn->state;
27602965
27612966 if (hdmi->panel)
27622967 drm_panel_disable(hdmi->panel);
....@@ -2764,6 +2969,19 @@
27642969 /* set avmute */
27652970 hdmi_writel(hdmi, 1, PKTSCHED_PKT_CONTROL0);
27662971 mdelay(50);
2972
+
2973
+ hdmi_modb(hdmi, 0, HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ,
2974
+ AVP_3_INT_MASK_N);
2975
+ if (hdmi->hdcp && hdmi->hdcp->hdcp_stop)
2976
+ hdmi->hdcp->hdcp_stop(hdmi->hdcp);
2977
+
2978
+ hdmi_writel(hdmi, 0, HDCP2LOGIC_ESM_GPIO_IN);
2979
+ if (conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
2980
+ drm_hdcp_update_content_protection(hdmi->curr_conn,
2981
+ DRM_MODE_CONTENT_PROTECTION_DESIRED);
2982
+
2983
+ if (hdmi->plat_data->set_hdcp_status)
2984
+ hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
27672985
27682986 extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false);
27692987 handle_plugged_change(hdmi, false);
....@@ -2781,7 +2999,7 @@
27812999 hdmi_writel(hdmi, 0, FLT_CONFIG0);
27823000 hdmi_writel(hdmi, 0, SCRAMB_CONFIG0);
27833001 /* set sink frl mode disable */
2784
- if (hdmi->curr_conn && dw_hdmi_support_scdc(hdmi, &hdmi->curr_conn->display_info))
3002
+ if (dw_hdmi_support_scdc(hdmi, &hdmi->curr_conn->display_info))
27853003 drm_scdc_writeb(hdmi->ddc, 0x31, 0);
27863004
27873005 hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
....@@ -2913,17 +3131,77 @@
29133131 static irqreturn_t dw_hdmi_qp_avp_hardirq(int irq, void *dev_id)
29143132 {
29153133 struct dw_hdmi_qp *hdmi = dev_id;
2916
- u32 stat;
3134
+ u32 stat1, stat3;
29173135
2918
- stat = hdmi_readl(hdmi, AVP_1_INT_STATUS);
2919
- if (stat) {
2920
- dev_dbg(hdmi->dev, "HDCP irq %#x\n", stat);
2921
- stat &= ~stat;
2922
- hdmi_writel(hdmi, stat, AVP_1_INT_MASK_N);
2923
- return IRQ_WAKE_THREAD;
3136
+ stat1 = hdmi_readl(hdmi, AVP_1_INT_STATUS);
3137
+ stat3 = hdmi_readl(hdmi, AVP_3_INT_STATUS);
3138
+
3139
+ if (!stat1 && !stat3)
3140
+ return IRQ_NONE;
3141
+
3142
+ return IRQ_WAKE_THREAD;
3143
+}
3144
+
3145
+static irqreturn_t dw_hdmi_qp_avp_irq(int irq, void *dev_id)
3146
+{
3147
+ struct dw_hdmi_qp *hdmi = dev_id;
3148
+ struct drm_connector_state *conn_state;
3149
+ void *data = hdmi->plat_data->phy_data;
3150
+ u32 stat1, stat3, val;
3151
+
3152
+ stat1 = hdmi_readl(hdmi, AVP_1_INT_STATUS);
3153
+ stat3 = hdmi_readl(hdmi, AVP_3_INT_STATUS);
3154
+
3155
+ hdmi_writel(hdmi, stat1, AVP_1_INT_CLEAR);
3156
+ hdmi_writel(hdmi, stat3, AVP_3_INT_CLEAR);
3157
+
3158
+ if (!hdmi->curr_conn || !hdmi->curr_conn->state)
3159
+ return IRQ_HANDLED;
3160
+
3161
+ conn_state = hdmi->curr_conn->state;
3162
+ val = conn_state->content_protection;
3163
+
3164
+ if (hdmi->hdcp && hdmi->hdcp->hdcp_isr) {
3165
+ u32 hdcp_status = hdmi_readl(hdmi, HDCP14_STATUS0);
3166
+
3167
+ if (stat1 & HDCP14_AUTH_CHG_MASK_N) {
3168
+ /* hdcp14 auth success */
3169
+ if (hdcp_status & BIT(2)) {
3170
+ hdmi->hdcp_status |= HDMI_HDCP14_AUTH;
3171
+ if (conn_state->content_protection !=
3172
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
3173
+ val = DRM_MODE_CONTENT_PROTECTION_ENABLED;
3174
+ } else if (!(hdcp_status & BIT(2))) {
3175
+ hdmi->hdcp_status &= ~HDMI_HDCP14_AUTH;
3176
+ if (conn_state->content_protection !=
3177
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
3178
+ val = DRM_MODE_CONTENT_PROTECTION_DESIRED;
3179
+ }
3180
+ conn_state->content_protection = val;
3181
+ }
3182
+ hdmi->hdcp->hdcp_isr(hdmi->hdcp, stat1, hdcp_status);
29243183 }
29253184
2926
- return IRQ_NONE;
3185
+ if (stat3 & HDCP2_ESM_P0_GPIO_OUT_2_CHG_IRQ) {
3186
+ stat3 = hdmi_readl(hdmi, HDCP2LOGIC_ESM_GPIO_OUT);
3187
+ if (stat3 & HDCP2_AUTHENTICATION_SUCCESS) {
3188
+ hdmi->hdcp_status |= HDMI_HDCP2_AUTH;
3189
+ if (conn_state->content_protection !=
3190
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
3191
+ val = DRM_MODE_CONTENT_PROTECTION_ENABLED;
3192
+ } else if (!(stat3 & HDCP2_AUTHENTICATION_SUCCESS)) {
3193
+ hdmi->hdcp_status &= ~HDMI_HDCP2_AUTH;
3194
+ if (conn_state->content_protection !=
3195
+ DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
3196
+ val = DRM_MODE_CONTENT_PROTECTION_DESIRED;
3197
+ }
3198
+ conn_state->content_protection = val;
3199
+ }
3200
+
3201
+ if (hdmi->plat_data->set_hdcp_status)
3202
+ hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
3203
+
3204
+ return IRQ_HANDLED;
29273205 }
29283206
29293207 static irqreturn_t dw_hdmi_qp_earc_hardirq(int irq, void *dev_id)
....@@ -2940,21 +3218,6 @@
29403218 }
29413219
29423220 return IRQ_NONE;
2943
-}
2944
-
2945
-static irqreturn_t dw_hdmi_qp_avp_irq(int irq, void *dev_id)
2946
-{
2947
- struct dw_hdmi_qp *hdmi = dev_id;
2948
- u32 stat;
2949
-
2950
- stat = hdmi_readl(hdmi, AVP_1_INT_STATUS);
2951
-
2952
- if (!stat)
2953
- return IRQ_NONE;
2954
-
2955
- hdmi_writel(hdmi, stat, AVP_1_INT_CLEAR);
2956
-
2957
- return IRQ_HANDLED;
29583221 }
29593222
29603223 static irqreturn_t dw_hdmi_qp_earc_irq(int irq, void *dev_id)
....@@ -3124,6 +3387,11 @@
31243387 struct dw_hdmi_qp *hdmi = s->private;
31253388 u32 i = 0, j = 0, val = 0;
31263389
3390
+ if (hdmi->disabled) {
3391
+ dev_err(hdmi->dev, "hdmi is disabled\n");
3392
+ return -EACCES;
3393
+ }
3394
+
31273395 seq_puts(s, "\n---------------------------------------------------");
31283396
31293397 for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
....@@ -3154,6 +3422,11 @@
31543422 ((struct seq_file *)file->private_data)->private;
31553423 u32 reg, val;
31563424 char kbuf[25];
3425
+
3426
+ if (hdmi->disabled) {
3427
+ dev_err(hdmi->dev, "hdmi is disabled\n");
3428
+ return -EACCES;
3429
+ }
31573430
31583431 if (count > 24) {
31593432 dev_err(hdmi->dev, "out of buf range\n");
....@@ -3339,6 +3612,70 @@
33393612 hdmi, &dw_hdmi_ctrl_fops);
33403613 }
33413614
3615
+static void dw_hdmi_qp_hdcp14_get_mem(struct dw_hdmi_qp *hdmi, u8 *data, u32 len)
3616
+{
3617
+ u32 ksv_len, i, val;
3618
+ void *hdmi_data = hdmi->plat_data->phy_data;
3619
+
3620
+ if (hdmi->plat_data->set_hdcp14_mem)
3621
+ hdmi->plat_data->set_hdcp14_mem(hdmi_data, true);
3622
+
3623
+ ksv_len = len - BSTATUS_LEN - M0_LEN - SHAMAX;
3624
+ for (i = 0; i < len; i++) {
3625
+ /* read ksv list */
3626
+ if (i < ksv_len)
3627
+ val = readl(hdmi->hdcp14_mem + HDMI_HDCP14_MEM_KSV0 + i * 4);
3628
+ /* read bstatus */
3629
+ else if (i < len - SHAMAX - M0_LEN)
3630
+ val = readl(hdmi->hdcp14_mem + HDMI_HDCP14_MEM_BSTATUS0 +
3631
+ (i - ksv_len) * 4);
3632
+ /* read M0 */
3633
+ else if (i < len - SHAMAX)
3634
+ val = readl(hdmi->hdcp14_mem + HDMI_HDCP14_MEM_M0_1 +
3635
+ (i - ksv_len - BSTATUS_LEN) * 4);
3636
+ else
3637
+ /* VH0 save in external memory is error, we need to read VH0 via ddc */
3638
+ hdcp_ddc_read(hdmi->ddc, HDMI_HDCP_ADDR, HDMI_VH0 + i - (len - SHAMAX),
3639
+ &val);
3640
+
3641
+ data[i] = val;
3642
+ }
3643
+
3644
+ if (hdmi->plat_data->set_hdcp14_mem)
3645
+ hdmi->plat_data->set_hdcp14_mem(hdmi_data, false);
3646
+}
3647
+
3648
+static int dw_hdmi_qp_register_hdcp(struct device *dev,
3649
+ struct dw_hdmi_qp *hdmi)
3650
+{
3651
+ struct dw_qp_hdcp hdmi_hdcp = {
3652
+ .hdmi = hdmi,
3653
+ .write = hdmi_writel,
3654
+ .read = hdmi_readl,
3655
+ .regs = hdmi->regs,
3656
+ .get_mem = dw_hdmi_qp_hdcp14_get_mem,
3657
+ };
3658
+ struct platform_device_info hdcp_device_info = {
3659
+ .parent = dev,
3660
+ .id = PLATFORM_DEVID_AUTO,
3661
+ .res = NULL,
3662
+ .num_res = 0,
3663
+ .name = DW_HDCP_QP_DRIVER_NAME,
3664
+ .data = &hdmi_hdcp,
3665
+ .size_data = sizeof(hdmi_hdcp),
3666
+ .dma_mask = DMA_BIT_MASK(32),
3667
+ };
3668
+ hdmi->hdcp_dev = platform_device_register_full(&hdcp_device_info);
3669
+ if (IS_ERR(hdmi->hdcp_dev)) {
3670
+ dev_err(dev, "failed to register hdcp!\n");
3671
+ return -ENOMEM;
3672
+ }
3673
+
3674
+ hdmi->hdcp = hdmi->hdcp_dev->dev.platform_data;
3675
+
3676
+ return 0;
3677
+}
3678
+
33423679 static struct dw_hdmi_qp *
33433680 __dw_hdmi_probe(struct platform_device *pdev,
33443681 const struct dw_hdmi_plat_data *plat_data)
....@@ -3352,10 +3689,11 @@
33523689 struct dw_hdmi_qp_cec_data cec;
33533690 struct resource *iores = NULL;
33543691 struct drm_panel *panel = NULL;
3692
+ struct drm_bridge *bridge = NULL;
33553693 int irq;
33563694 int ret;
33573695
3358
- ret = drm_of_find_panel_or_bridge(np, 1, -1, &panel, NULL);
3696
+ ret = drm_of_find_panel_or_bridge(np, 1, -1, &panel, &bridge);
33593697 if (ret < 0 && ret != -ENODEV)
33603698 return ERR_PTR(ret);
33613699
....@@ -3364,6 +3702,7 @@
33643702 return ERR_PTR(-ENOMEM);
33653703
33663704 hdmi->panel = panel;
3705
+ hdmi->next_bridge = bridge;
33673706 hdmi->connector.stereo_allowed = 1;
33683707 hdmi->plat_data = plat_data;
33693708 hdmi->dev = dev;
....@@ -3512,7 +3851,7 @@
35123851 hdmi->avp_irq = irq;
35133852 ret = devm_request_threaded_irq(dev, hdmi->avp_irq,
35143853 dw_hdmi_qp_avp_hardirq,
3515
- dw_hdmi_qp_avp_irq, IRQF_SHARED,
3854
+ dw_hdmi_qp_avp_irq, IRQF_ONESHOT,
35163855 dev_name(dev), hdmi);
35173856 if (ret)
35183857 goto err_aud;
....@@ -3564,6 +3903,20 @@
35643903 goto err_cec;
35653904
35663905 dw_hdmi_register_debugfs(dev, hdmi);
3906
+
3907
+ if (hdmi_readl(hdmi, CONFIG_REG) & CONFIG_HDCP14) {
3908
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 1);
3909
+ hdmi->hdcp14_mem = devm_ioremap_resource(dev, iores);
3910
+
3911
+ if (IS_ERR(hdmi->hdcp14_mem)) {
3912
+ ret = PTR_ERR(hdmi->hdcp14_mem);
3913
+ goto err_cec;
3914
+ }
3915
+
3916
+ ret = dw_hdmi_qp_register_hdcp(dev, hdmi);
3917
+ if (ret)
3918
+ goto err_cec;
3919
+ }
35673920
35683921 return hdmi;
35693922
....@@ -3617,6 +3970,8 @@
36173970 hdmi->bridge.encoder->funcs->destroy(hdmi->bridge.encoder);
36183971 if (!IS_ERR(hdmi->cec))
36193972 platform_device_unregister(hdmi->cec);
3973
+ if (!IS_ERR(hdmi->hdcp_dev))
3974
+ platform_device_unregister(hdmi->hdcp_dev);
36203975 if (hdmi->i2c)
36213976 i2c_del_adapter(&hdmi->i2c->adap);
36223977 else
....@@ -3646,6 +4001,10 @@
36464001 }
36474002
36484003 plat_data->connector = &hdmi->connector;
4004
+ if (hdmi->skip_connector && hdmi->next_bridge)
4005
+ plat_data->bridge = hdmi->next_bridge;
4006
+ else
4007
+ plat_data->bridge = NULL;
36494008 }
36504009
36514010 if (plat_data->split_mode && !hdmi->plat_data->first_screen) {
....@@ -3703,6 +4062,7 @@
37034062 disable_irq(hdmi->earc_irq);
37044063
37054064 pinctrl_pm_select_sleep_state(dev);
4065
+ drm_connector_update_edid_property(&hdmi->connector, NULL);
37064066 }
37074067 EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend);
37084068