Commit | Line | Data |
---|---|---|
c6a57a50 | 1 | /* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved. |
2 | * | |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License version 2 and | |
5 | * only version 2 as published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | * | |
12 | */ | |
13 | ||
14 | #include "hdmi.h" | |
15 | #include <linux/qcom_scm.h> | |
16 | ||
17 | #define HDCP_REG_ENABLE 0x01 | |
18 | #define HDCP_REG_DISABLE 0x00 | |
19 | #define HDCP_PORT_ADDR 0x74 | |
20 | ||
21 | #define HDCP_INT_STATUS_MASK ( \ | |
22 | HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_INT | \ | |
23 | HDMI_HDCP_INT_CTRL_AUTH_FAIL_INT | \ | |
24 | HDMI_HDCP_INT_CTRL_AUTH_XFER_REQ_INT | \ | |
25 | HDMI_HDCP_INT_CTRL_AUTH_XFER_DONE_INT) | |
26 | ||
27 | #define AUTH_WORK_RETRIES_TIME 100 | |
28 | #define AUTH_RETRIES_TIME 30 | |
29 | ||
30 | /* QFPROM Registers for HDMI/HDCP */ | |
31 | #define QFPROM_RAW_FEAT_CONFIG_ROW0_LSB 0x000000F8 | |
32 | #define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB 0x000000FC | |
33 | #define HDCP_KSV_LSB 0x000060D8 | |
34 | #define HDCP_KSV_MSB 0x000060DC | |
35 | ||
36 | enum DS_TYPE { /* type of downstream device */ | |
37 | DS_UNKNOWN, | |
38 | DS_RECEIVER, | |
39 | DS_REPEATER, | |
40 | }; | |
41 | ||
42 | enum hdmi_hdcp_state { | |
43 | HDCP_STATE_NO_AKSV, | |
44 | HDCP_STATE_INACTIVE, | |
45 | HDCP_STATE_AUTHENTICATING, | |
46 | HDCP_STATE_AUTHENTICATED, | |
47 | HDCP_STATE_AUTH_FAILED | |
48 | }; | |
49 | ||
50 | struct hdmi_hdcp_reg_data { | |
51 | u32 reg_id; | |
52 | u32 off; | |
53 | char *name; | |
54 | u32 reg_val; | |
55 | }; | |
56 | ||
57 | struct hdmi_hdcp_ctrl { | |
58 | struct hdmi *hdmi; | |
59 | u32 auth_retries; | |
60 | bool tz_hdcp; | |
61 | enum hdmi_hdcp_state hdcp_state; | |
62 | struct work_struct hdcp_auth_work; | |
63 | struct work_struct hdcp_reauth_work; | |
64 | ||
65 | #define AUTH_ABORT_EV 1 | |
66 | #define AUTH_RESULT_RDY_EV 2 | |
67 | unsigned long auth_event; | |
68 | wait_queue_head_t auth_event_queue; | |
69 | ||
70 | u32 ksv_fifo_w_index; | |
71 | /* | |
72 | * store aksv from qfprom | |
73 | */ | |
74 | u32 aksv_lsb; | |
75 | u32 aksv_msb; | |
76 | bool aksv_valid; | |
77 | u32 ds_type; | |
78 | u32 bksv_lsb; | |
79 | u32 bksv_msb; | |
80 | u8 dev_count; | |
81 | u8 depth; | |
82 | u8 ksv_list[5 * 127]; | |
83 | bool max_cascade_exceeded; | |
84 | bool max_dev_exceeded; | |
85 | }; | |
86 | ||
fcda50c8 | 87 | static int msm_hdmi_ddc_read(struct hdmi *hdmi, u16 addr, u8 offset, |
c6a57a50 | 88 | u8 *data, u16 data_len) |
89 | { | |
90 | int rc; | |
91 | int retry = 5; | |
92 | struct i2c_msg msgs[] = { | |
93 | { | |
94 | .addr = addr >> 1, | |
95 | .flags = 0, | |
96 | .len = 1, | |
97 | .buf = &offset, | |
98 | }, { | |
99 | .addr = addr >> 1, | |
100 | .flags = I2C_M_RD, | |
101 | .len = data_len, | |
102 | .buf = data, | |
103 | } | |
104 | }; | |
105 | ||
106 | DBG("Start DDC read"); | |
107 | retry: | |
108 | rc = i2c_transfer(hdmi->i2c, msgs, 2); | |
109 | ||
110 | retry--; | |
111 | if (rc == 2) | |
112 | rc = 0; | |
113 | else if (retry > 0) | |
114 | goto retry; | |
115 | else | |
116 | rc = -EIO; | |
117 | ||
118 | DBG("End DDC read %d", rc); | |
119 | ||
120 | return rc; | |
121 | } | |
122 | ||
123 | #define HDCP_DDC_WRITE_MAX_BYTE_NUM 32 | |
124 | ||
fcda50c8 | 125 | static int msm_hdmi_ddc_write(struct hdmi *hdmi, u16 addr, u8 offset, |
c6a57a50 | 126 | u8 *data, u16 data_len) |
127 | { | |
128 | int rc; | |
129 | int retry = 10; | |
130 | u8 buf[HDCP_DDC_WRITE_MAX_BYTE_NUM]; | |
131 | struct i2c_msg msgs[] = { | |
132 | { | |
133 | .addr = addr >> 1, | |
134 | .flags = 0, | |
135 | .len = 1, | |
136 | } | |
137 | }; | |
138 | ||
139 | DBG("Start DDC write"); | |
140 | if (data_len > (HDCP_DDC_WRITE_MAX_BYTE_NUM - 1)) { | |
141 | pr_err("%s: write size too big\n", __func__); | |
142 | return -ERANGE; | |
143 | } | |
144 | ||
145 | buf[0] = offset; | |
146 | memcpy(&buf[1], data, data_len); | |
147 | msgs[0].buf = buf; | |
148 | msgs[0].len = data_len + 1; | |
149 | retry: | |
150 | rc = i2c_transfer(hdmi->i2c, msgs, 1); | |
151 | ||
152 | retry--; | |
153 | if (rc == 1) | |
154 | rc = 0; | |
155 | else if (retry > 0) | |
156 | goto retry; | |
157 | else | |
158 | rc = -EIO; | |
159 | ||
160 | DBG("End DDC write %d", rc); | |
161 | ||
162 | return rc; | |
163 | } | |
164 | ||
fcda50c8 | 165 | static int msm_hdmi_hdcp_scm_wr(struct hdmi_hdcp_ctrl *hdcp_ctrl, u32 *preg, |
c6a57a50 | 166 | u32 *pdata, u32 count) |
167 | { | |
168 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
169 | struct qcom_scm_hdcp_req scm_buf[QCOM_SCM_HDCP_MAX_REQ_CNT]; | |
170 | u32 resp, phy_addr, idx = 0; | |
171 | int i, ret = 0; | |
172 | ||
173 | WARN_ON(!pdata || !preg || (count == 0)); | |
174 | ||
175 | if (hdcp_ctrl->tz_hdcp) { | |
176 | phy_addr = (u32)hdmi->mmio_phy_addr; | |
177 | ||
178 | while (count) { | |
179 | memset(scm_buf, 0, sizeof(scm_buf)); | |
180 | for (i = 0; i < count && i < QCOM_SCM_HDCP_MAX_REQ_CNT; | |
181 | i++) { | |
182 | scm_buf[i].addr = phy_addr + preg[idx]; | |
183 | scm_buf[i].val = pdata[idx]; | |
184 | idx++; | |
185 | } | |
186 | ret = qcom_scm_hdcp_req(scm_buf, i, &resp); | |
187 | ||
188 | if (ret || resp) { | |
189 | pr_err("%s: error: scm_call ret=%d resp=%u\n", | |
190 | __func__, ret, resp); | |
191 | ret = -EINVAL; | |
192 | break; | |
193 | } | |
194 | ||
195 | count -= i; | |
196 | } | |
197 | } else { | |
198 | for (i = 0; i < count; i++) | |
199 | hdmi_write(hdmi, preg[i], pdata[i]); | |
200 | } | |
201 | ||
202 | return ret; | |
203 | } | |
204 | ||
fcda50c8 | 205 | void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 206 | { |
207 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
208 | u32 reg_val, hdcp_int_status; | |
209 | unsigned long flags; | |
210 | ||
211 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
212 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_INT_CTRL); | |
213 | hdcp_int_status = reg_val & HDCP_INT_STATUS_MASK; | |
214 | if (!hdcp_int_status) { | |
215 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
216 | return; | |
217 | } | |
218 | /* Clear Interrupts */ | |
219 | reg_val |= hdcp_int_status << 1; | |
220 | /* Clear AUTH_FAIL_INFO as well */ | |
221 | if (hdcp_int_status & HDMI_HDCP_INT_CTRL_AUTH_FAIL_INT) | |
222 | reg_val |= HDMI_HDCP_INT_CTRL_AUTH_FAIL_INFO_ACK; | |
223 | hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, reg_val); | |
224 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
225 | ||
226 | DBG("hdcp irq %x", hdcp_int_status); | |
227 | ||
228 | if (hdcp_int_status & HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_INT) { | |
229 | pr_info("%s:AUTH_SUCCESS_INT received\n", __func__); | |
230 | if (HDCP_STATE_AUTHENTICATING == hdcp_ctrl->hdcp_state) { | |
231 | set_bit(AUTH_RESULT_RDY_EV, &hdcp_ctrl->auth_event); | |
232 | wake_up_all(&hdcp_ctrl->auth_event_queue); | |
233 | } | |
234 | } | |
235 | ||
236 | if (hdcp_int_status & HDMI_HDCP_INT_CTRL_AUTH_FAIL_INT) { | |
237 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); | |
238 | pr_info("%s: AUTH_FAIL_INT rcvd, LINK0_STATUS=0x%08x\n", | |
239 | __func__, reg_val); | |
240 | if (HDCP_STATE_AUTHENTICATED == hdcp_ctrl->hdcp_state) | |
241 | queue_work(hdmi->workq, &hdcp_ctrl->hdcp_reauth_work); | |
242 | else if (HDCP_STATE_AUTHENTICATING == | |
243 | hdcp_ctrl->hdcp_state) { | |
244 | set_bit(AUTH_RESULT_RDY_EV, &hdcp_ctrl->auth_event); | |
245 | wake_up_all(&hdcp_ctrl->auth_event_queue); | |
246 | } | |
247 | } | |
248 | } | |
249 | ||
fcda50c8 | 250 | static int msm_hdmi_hdcp_msleep(struct hdmi_hdcp_ctrl *hdcp_ctrl, u32 ms, u32 ev) |
c6a57a50 | 251 | { |
252 | int rc; | |
253 | ||
254 | rc = wait_event_timeout(hdcp_ctrl->auth_event_queue, | |
255 | !!test_bit(ev, &hdcp_ctrl->auth_event), | |
256 | msecs_to_jiffies(ms)); | |
257 | if (rc) { | |
258 | pr_info("%s: msleep is canceled by event %d\n", | |
259 | __func__, ev); | |
260 | clear_bit(ev, &hdcp_ctrl->auth_event); | |
261 | return -ECANCELED; | |
262 | } | |
263 | ||
264 | return 0; | |
265 | } | |
266 | ||
fcda50c8 | 267 | static int msm_hdmi_hdcp_read_validate_aksv(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 268 | { |
269 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
270 | ||
271 | /* Fetch aksv from QFPROM, this info should be public. */ | |
272 | hdcp_ctrl->aksv_lsb = hdmi_qfprom_read(hdmi, HDCP_KSV_LSB); | |
273 | hdcp_ctrl->aksv_msb = hdmi_qfprom_read(hdmi, HDCP_KSV_MSB); | |
274 | ||
275 | /* check there are 20 ones in AKSV */ | |
276 | if ((hweight32(hdcp_ctrl->aksv_lsb) + hweight32(hdcp_ctrl->aksv_msb)) | |
277 | != 20) { | |
278 | pr_err("%s: AKSV QFPROM doesn't have 20 1's, 20 0's\n", | |
279 | __func__); | |
280 | pr_err("%s: QFPROM AKSV chk failed (AKSV=%02x%08x)\n", | |
281 | __func__, hdcp_ctrl->aksv_msb, | |
282 | hdcp_ctrl->aksv_lsb); | |
283 | return -EINVAL; | |
284 | } | |
285 | DBG("AKSV=%02x%08x", hdcp_ctrl->aksv_msb, hdcp_ctrl->aksv_lsb); | |
286 | ||
287 | return 0; | |
288 | } | |
289 | ||
fcda50c8 | 290 | static int msm_reset_hdcp_ddc_failures(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 291 | { |
292 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
293 | u32 reg_val, failure, nack0; | |
294 | int rc = 0; | |
295 | ||
296 | /* Check for any DDC transfer failures */ | |
297 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_STATUS); | |
298 | failure = reg_val & HDMI_HDCP_DDC_STATUS_FAILED; | |
299 | nack0 = reg_val & HDMI_HDCP_DDC_STATUS_NACK0; | |
300 | DBG("HDCP_DDC_STATUS=0x%x, FAIL=%d, NACK0=%d", | |
301 | reg_val, failure, nack0); | |
302 | ||
303 | if (failure) { | |
304 | /* | |
305 | * Indicates that the last HDCP HW DDC transfer failed. | |
306 | * This occurs when a transfer is attempted with HDCP DDC | |
307 | * disabled (HDCP_DDC_DISABLE=1) or the number of retries | |
308 | * matches HDCP_DDC_RETRY_CNT. | |
309 | * Failure occurred, let's clear it. | |
310 | */ | |
311 | DBG("DDC failure detected"); | |
312 | ||
313 | /* First, Disable DDC */ | |
314 | hdmi_write(hdmi, REG_HDMI_HDCP_DDC_CTRL_0, | |
315 | HDMI_HDCP_DDC_CTRL_0_DISABLE); | |
316 | ||
317 | /* ACK the Failure to Clear it */ | |
318 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_CTRL_1); | |
319 | reg_val |= HDMI_HDCP_DDC_CTRL_1_FAILED_ACK; | |
320 | hdmi_write(hdmi, REG_HDMI_HDCP_DDC_CTRL_1, reg_val); | |
321 | ||
322 | /* Check if the FAILURE got Cleared */ | |
323 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_STATUS); | |
324 | if (reg_val & HDMI_HDCP_DDC_STATUS_FAILED) | |
325 | pr_info("%s: Unable to clear HDCP DDC Failure\n", | |
326 | __func__); | |
327 | ||
328 | /* Re-Enable HDCP DDC */ | |
329 | hdmi_write(hdmi, REG_HDMI_HDCP_DDC_CTRL_0, 0); | |
330 | } | |
331 | ||
332 | if (nack0) { | |
333 | DBG("Before: HDMI_DDC_SW_STATUS=0x%08x", | |
334 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); | |
335 | /* Reset HDMI DDC software status */ | |
336 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
337 | reg_val |= HDMI_DDC_CTRL_SW_STATUS_RESET; | |
338 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
339 | ||
fcda50c8 | 340 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 341 | |
342 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
343 | reg_val &= ~HDMI_DDC_CTRL_SW_STATUS_RESET; | |
344 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
345 | ||
346 | /* Reset HDMI DDC Controller */ | |
347 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
348 | reg_val |= HDMI_DDC_CTRL_SOFT_RESET; | |
349 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
350 | ||
351 | /* If previous msleep is aborted, skip this msleep */ | |
352 | if (!rc) | |
fcda50c8 | 353 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 354 | |
355 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_CTRL); | |
356 | reg_val &= ~HDMI_DDC_CTRL_SOFT_RESET; | |
357 | hdmi_write(hdmi, REG_HDMI_DDC_CTRL, reg_val); | |
358 | DBG("After: HDMI_DDC_SW_STATUS=0x%08x", | |
359 | hdmi_read(hdmi, REG_HDMI_DDC_SW_STATUS)); | |
360 | } | |
361 | ||
362 | return rc; | |
363 | } | |
364 | ||
fcda50c8 | 365 | static int msm_hdmi_hdcp_hw_ddc_clean(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 366 | { |
367 | int rc; | |
368 | u32 hdcp_ddc_status, ddc_hw_status; | |
369 | u32 xfer_done, xfer_req, hw_done; | |
370 | bool hw_not_ready; | |
371 | u32 timeout_count; | |
372 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
373 | ||
374 | if (hdmi_read(hdmi, REG_HDMI_DDC_HW_STATUS) == 0) | |
375 | return 0; | |
376 | ||
377 | /* Wait to be clean on DDC HW engine */ | |
378 | timeout_count = 100; | |
379 | do { | |
380 | hdcp_ddc_status = hdmi_read(hdmi, REG_HDMI_HDCP_DDC_STATUS); | |
381 | ddc_hw_status = hdmi_read(hdmi, REG_HDMI_DDC_HW_STATUS); | |
382 | ||
383 | xfer_done = hdcp_ddc_status & HDMI_HDCP_DDC_STATUS_XFER_DONE; | |
384 | xfer_req = hdcp_ddc_status & HDMI_HDCP_DDC_STATUS_XFER_REQ; | |
385 | hw_done = ddc_hw_status & HDMI_DDC_HW_STATUS_DONE; | |
386 | hw_not_ready = !xfer_done || xfer_req || !hw_done; | |
387 | ||
388 | if (hw_not_ready) | |
389 | break; | |
390 | ||
391 | timeout_count--; | |
392 | if (!timeout_count) { | |
393 | pr_warn("%s: hw_ddc_clean failed\n", __func__); | |
394 | return -ETIMEDOUT; | |
395 | } | |
396 | ||
fcda50c8 | 397 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 398 | if (rc) |
399 | return rc; | |
400 | } while (1); | |
401 | ||
402 | return 0; | |
403 | } | |
404 | ||
fcda50c8 | 405 | static void msm_hdmi_hdcp_reauth_work(struct work_struct *work) |
c6a57a50 | 406 | { |
407 | struct hdmi_hdcp_ctrl *hdcp_ctrl = container_of(work, | |
408 | struct hdmi_hdcp_ctrl, hdcp_reauth_work); | |
409 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
410 | unsigned long flags; | |
411 | u32 reg_val; | |
412 | ||
413 | DBG("HDCP REAUTH WORK"); | |
414 | /* | |
415 | * Disable HPD circuitry. | |
416 | * This is needed to reset the HDCP cipher engine so that when we | |
417 | * attempt a re-authentication, HW would clear the AN0_READY and | |
418 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register | |
419 | */ | |
420 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
421 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
422 | reg_val &= ~HDMI_HPD_CTRL_ENABLE; | |
423 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
424 | ||
425 | /* Disable HDCP interrupts */ | |
426 | hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, 0); | |
427 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
428 | ||
429 | hdmi_write(hdmi, REG_HDMI_HDCP_RESET, | |
430 | HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE); | |
431 | ||
432 | /* Wait to be clean on DDC HW engine */ | |
fcda50c8 | 433 | if (msm_hdmi_hdcp_hw_ddc_clean(hdcp_ctrl)) { |
c6a57a50 | 434 | pr_info("%s: reauth work aborted\n", __func__); |
435 | return; | |
436 | } | |
437 | ||
438 | /* Disable encryption and disable the HDCP block */ | |
439 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, 0); | |
440 | ||
441 | /* Enable HPD circuitry */ | |
442 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
443 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
444 | reg_val |= HDMI_HPD_CTRL_ENABLE; | |
445 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
446 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
447 | ||
448 | /* | |
449 | * Only retry defined times then abort current authenticating process | |
450 | */ | |
451 | if (++hdcp_ctrl->auth_retries == AUTH_RETRIES_TIME) { | |
452 | hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE; | |
453 | hdcp_ctrl->auth_retries = 0; | |
454 | pr_info("%s: abort reauthentication!\n", __func__); | |
455 | ||
456 | return; | |
457 | } | |
458 | ||
459 | DBG("Queue AUTH WORK"); | |
460 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; | |
461 | queue_work(hdmi->workq, &hdcp_ctrl->hdcp_auth_work); | |
462 | } | |
463 | ||
fcda50c8 | 464 | static int msm_hdmi_hdcp_auth_prepare(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 465 | { |
466 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
467 | u32 link0_status; | |
468 | u32 reg_val; | |
469 | unsigned long flags; | |
470 | int rc; | |
471 | ||
472 | if (!hdcp_ctrl->aksv_valid) { | |
fcda50c8 | 473 | rc = msm_hdmi_hdcp_read_validate_aksv(hdcp_ctrl); |
c6a57a50 | 474 | if (rc) { |
475 | pr_err("%s: ASKV validation failed\n", __func__); | |
476 | hdcp_ctrl->hdcp_state = HDCP_STATE_NO_AKSV; | |
477 | return -ENOTSUPP; | |
478 | } | |
479 | hdcp_ctrl->aksv_valid = true; | |
480 | } | |
481 | ||
482 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
483 | /* disable HDMI Encrypt */ | |
484 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
485 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
486 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
487 | ||
488 | /* Enabling Software DDC */ | |
489 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION); | |
490 | reg_val &= ~HDMI_DDC_ARBITRATION_HW_ARBITRATION; | |
491 | hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val); | |
492 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
493 | ||
494 | /* | |
495 | * Write AKSV read from QFPROM to the HDCP registers. | |
496 | * This step is needed for HDCP authentication and must be | |
497 | * written before enabling HDCP. | |
498 | */ | |
499 | hdmi_write(hdmi, REG_HDMI_HDCP_SW_LOWER_AKSV, hdcp_ctrl->aksv_lsb); | |
500 | hdmi_write(hdmi, REG_HDMI_HDCP_SW_UPPER_AKSV, hdcp_ctrl->aksv_msb); | |
501 | ||
502 | /* | |
503 | * HDCP setup prior to enabling HDCP_CTRL. | |
504 | * Setup seed values for random number An. | |
505 | */ | |
506 | hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF); | |
507 | hdmi_write(hdmi, REG_HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE); | |
508 | ||
509 | /* Disable the RngCipher state */ | |
510 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL); | |
511 | reg_val &= ~HDMI_HDCP_DEBUG_CTRL_RNG_CIPHER; | |
512 | hdmi_write(hdmi, REG_HDMI_HDCP_DEBUG_CTRL, reg_val); | |
513 | DBG("HDCP_DEBUG_CTRL=0x%08x", | |
514 | hdmi_read(hdmi, REG_HDMI_HDCP_DEBUG_CTRL)); | |
515 | ||
516 | /* | |
517 | * Ensure that all register writes are completed before | |
518 | * enabling HDCP cipher | |
519 | */ | |
520 | wmb(); | |
521 | ||
522 | /* | |
523 | * Enable HDCP | |
524 | * This needs to be done as early as possible in order for the | |
525 | * hardware to make An available to read | |
526 | */ | |
527 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, HDMI_HDCP_CTRL_ENABLE); | |
528 | ||
529 | /* | |
530 | * If we had stale values for the An ready bit, it should most | |
531 | * likely be cleared now after enabling HDCP cipher | |
532 | */ | |
533 | link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); | |
534 | DBG("After enabling HDCP Link0_Status=0x%08x", link0_status); | |
535 | if (!(link0_status & | |
536 | (HDMI_HDCP_LINK0_STATUS_AN_0_READY | | |
537 | HDMI_HDCP_LINK0_STATUS_AN_1_READY))) | |
538 | DBG("An not ready after enabling HDCP"); | |
539 | ||
540 | /* Clear any DDC failures from previous tries before enable HDCP*/ | |
fcda50c8 | 541 | rc = msm_reset_hdcp_ddc_failures(hdcp_ctrl); |
c6a57a50 | 542 | |
543 | return rc; | |
544 | } | |
545 | ||
fcda50c8 | 546 | static void msm_hdmi_hdcp_auth_fail(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 547 | { |
548 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
549 | u32 reg_val; | |
550 | unsigned long flags; | |
551 | ||
552 | DBG("hdcp auth failed, queue reauth work"); | |
553 | /* clear HDMI Encrypt */ | |
554 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
555 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
556 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
557 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
558 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
559 | ||
560 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTH_FAILED; | |
561 | queue_work(hdmi->workq, &hdcp_ctrl->hdcp_reauth_work); | |
562 | } | |
563 | ||
fcda50c8 | 564 | static void msm_hdmi_hdcp_auth_done(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 565 | { |
566 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
567 | u32 reg_val; | |
568 | unsigned long flags; | |
569 | ||
570 | /* | |
571 | * Disable software DDC before going into part3 to make sure | |
572 | * there is no Arbitration between software and hardware for DDC | |
573 | */ | |
574 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
575 | reg_val = hdmi_read(hdmi, REG_HDMI_DDC_ARBITRATION); | |
576 | reg_val |= HDMI_DDC_ARBITRATION_HW_ARBITRATION; | |
577 | hdmi_write(hdmi, REG_HDMI_DDC_ARBITRATION, reg_val); | |
578 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
579 | ||
580 | /* enable HDMI Encrypt */ | |
581 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
582 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
583 | reg_val |= HDMI_CTRL_ENCRYPTED; | |
584 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
585 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
586 | ||
587 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATED; | |
588 | hdcp_ctrl->auth_retries = 0; | |
589 | } | |
590 | ||
591 | /* | |
592 | * hdcp authenticating part 1 | |
593 | * Wait Key/An ready | |
594 | * Read BCAPS from sink | |
595 | * Write BCAPS and AKSV into HDCP engine | |
596 | * Write An and AKSV to sink | |
597 | * Read BKSV from sink and write into HDCP engine | |
598 | */ | |
fcda50c8 | 599 | static int msm_hdmi_hdcp_wait_key_an_ready(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 600 | { |
601 | int rc; | |
602 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
603 | u32 link0_status, keys_state; | |
604 | u32 timeout_count; | |
605 | bool an_ready; | |
606 | ||
607 | /* Wait for HDCP keys to be checked and validated */ | |
608 | timeout_count = 100; | |
609 | do { | |
610 | link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); | |
611 | keys_state = (link0_status >> 28) & 0x7; | |
612 | if (keys_state == HDCP_KEYS_STATE_VALID) | |
613 | break; | |
614 | ||
615 | DBG("Keys not ready(%d). s=%d, l0=%0x08x", | |
616 | timeout_count, keys_state, link0_status); | |
617 | ||
618 | timeout_count--; | |
619 | if (!timeout_count) { | |
620 | pr_err("%s: Wait key state timedout", __func__); | |
621 | return -ETIMEDOUT; | |
622 | } | |
623 | ||
fcda50c8 | 624 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 625 | if (rc) |
626 | return rc; | |
627 | } while (1); | |
628 | ||
629 | timeout_count = 100; | |
630 | do { | |
631 | link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); | |
632 | an_ready = (link0_status & HDMI_HDCP_LINK0_STATUS_AN_0_READY) | |
633 | && (link0_status & HDMI_HDCP_LINK0_STATUS_AN_1_READY); | |
634 | if (an_ready) | |
635 | break; | |
636 | ||
637 | DBG("An not ready(%d). l0_status=0x%08x", | |
638 | timeout_count, link0_status); | |
639 | ||
640 | timeout_count--; | |
641 | if (!timeout_count) { | |
642 | pr_err("%s: Wait An timedout", __func__); | |
643 | return -ETIMEDOUT; | |
644 | } | |
645 | ||
fcda50c8 | 646 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 647 | if (rc) |
648 | return rc; | |
649 | } while (1); | |
650 | ||
651 | return 0; | |
652 | } | |
653 | ||
fcda50c8 | 654 | static int msm_hdmi_hdcp_send_aksv_an(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 655 | { |
656 | int rc = 0; | |
657 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
658 | u32 link0_aksv_0, link0_aksv_1; | |
659 | u32 link0_an[2]; | |
660 | u8 aksv[5]; | |
661 | ||
662 | /* Read An0 and An1 */ | |
663 | link0_an[0] = hdmi_read(hdmi, REG_HDMI_HDCP_RCVPORT_DATA5); | |
664 | link0_an[1] = hdmi_read(hdmi, REG_HDMI_HDCP_RCVPORT_DATA6); | |
665 | ||
666 | /* Read AKSV */ | |
667 | link0_aksv_0 = hdmi_read(hdmi, REG_HDMI_HDCP_RCVPORT_DATA3); | |
668 | link0_aksv_1 = hdmi_read(hdmi, REG_HDMI_HDCP_RCVPORT_DATA4); | |
669 | ||
670 | DBG("Link ASKV=%08x%08x", link0_aksv_0, link0_aksv_1); | |
671 | /* Copy An and AKSV to byte arrays for transmission */ | |
672 | aksv[0] = link0_aksv_0 & 0xFF; | |
673 | aksv[1] = (link0_aksv_0 >> 8) & 0xFF; | |
674 | aksv[2] = (link0_aksv_0 >> 16) & 0xFF; | |
675 | aksv[3] = (link0_aksv_0 >> 24) & 0xFF; | |
676 | aksv[4] = link0_aksv_1 & 0xFF; | |
677 | ||
678 | /* Write An to offset 0x18 */ | |
fcda50c8 | 679 | rc = msm_hdmi_ddc_write(hdmi, HDCP_PORT_ADDR, 0x18, (u8 *)link0_an, |
c6a57a50 | 680 | (u16)sizeof(link0_an)); |
681 | if (rc) { | |
682 | pr_err("%s:An write failed\n", __func__); | |
683 | return rc; | |
684 | } | |
685 | DBG("Link0-An=%08x%08x", link0_an[0], link0_an[1]); | |
686 | ||
687 | /* Write AKSV to offset 0x10 */ | |
fcda50c8 | 688 | rc = msm_hdmi_ddc_write(hdmi, HDCP_PORT_ADDR, 0x10, aksv, 5); |
c6a57a50 | 689 | if (rc) { |
690 | pr_err("%s:AKSV write failed\n", __func__); | |
691 | return rc; | |
692 | } | |
693 | DBG("Link0-AKSV=%02x%08x", link0_aksv_1 & 0xFF, link0_aksv_0); | |
694 | ||
695 | return 0; | |
696 | } | |
697 | ||
fcda50c8 | 698 | static int msm_hdmi_hdcp_recv_bksv(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 699 | { |
700 | int rc = 0; | |
701 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
702 | u8 bksv[5]; | |
703 | u32 reg[2], data[2]; | |
704 | ||
705 | /* Read BKSV at offset 0x00 */ | |
fcda50c8 | 706 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x00, bksv, 5); |
c6a57a50 | 707 | if (rc) { |
708 | pr_err("%s:BKSV read failed\n", __func__); | |
709 | return rc; | |
710 | } | |
711 | ||
712 | hdcp_ctrl->bksv_lsb = bksv[0] | (bksv[1] << 8) | | |
713 | (bksv[2] << 16) | (bksv[3] << 24); | |
714 | hdcp_ctrl->bksv_msb = bksv[4]; | |
715 | DBG(":BKSV=%02x%08x", hdcp_ctrl->bksv_msb, hdcp_ctrl->bksv_lsb); | |
716 | ||
717 | /* check there are 20 ones in BKSV */ | |
718 | if ((hweight32(hdcp_ctrl->bksv_lsb) + hweight32(hdcp_ctrl->bksv_msb)) | |
719 | != 20) { | |
720 | pr_err(": BKSV doesn't have 20 1's and 20 0's\n"); | |
721 | pr_err(": BKSV chk fail. BKSV=%02x%02x%02x%02x%02x\n", | |
722 | bksv[4], bksv[3], bksv[2], bksv[1], bksv[0]); | |
723 | return -EINVAL; | |
724 | } | |
725 | ||
726 | /* Write BKSV read from sink to HDCP registers */ | |
727 | reg[0] = REG_HDMI_HDCP_RCVPORT_DATA0; | |
728 | data[0] = hdcp_ctrl->bksv_lsb; | |
729 | reg[1] = REG_HDMI_HDCP_RCVPORT_DATA1; | |
730 | data[1] = hdcp_ctrl->bksv_msb; | |
fcda50c8 | 731 | rc = msm_hdmi_hdcp_scm_wr(hdcp_ctrl, reg, data, 2); |
c6a57a50 | 732 | |
733 | return rc; | |
734 | } | |
735 | ||
fcda50c8 | 736 | static int msm_hdmi_hdcp_recv_bcaps(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 737 | { |
738 | int rc = 0; | |
739 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
740 | u32 reg, data; | |
741 | u8 bcaps; | |
742 | ||
fcda50c8 | 743 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x40, &bcaps, 1); |
c6a57a50 | 744 | if (rc) { |
745 | pr_err("%s:BCAPS read failed\n", __func__); | |
746 | return rc; | |
747 | } | |
748 | DBG("BCAPS=%02x", bcaps); | |
749 | ||
750 | /* receiver (0), repeater (1) */ | |
751 | hdcp_ctrl->ds_type = (bcaps & BIT(6)) ? DS_REPEATER : DS_RECEIVER; | |
752 | ||
753 | /* Write BCAPS to the hardware */ | |
754 | reg = REG_HDMI_HDCP_RCVPORT_DATA12; | |
755 | data = (u32)bcaps; | |
fcda50c8 | 756 | rc = msm_hdmi_hdcp_scm_wr(hdcp_ctrl, ®, &data, 1); |
c6a57a50 | 757 | |
758 | return rc; | |
759 | } | |
760 | ||
fcda50c8 | 761 | static int msm_hdmi_hdcp_auth_part1_key_exchange(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 762 | { |
763 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
764 | unsigned long flags; | |
765 | int rc; | |
766 | ||
767 | /* Wait for AKSV key and An ready */ | |
fcda50c8 | 768 | rc = msm_hdmi_hdcp_wait_key_an_ready(hdcp_ctrl); |
c6a57a50 | 769 | if (rc) { |
770 | pr_err("%s: wait key and an ready failed\n", __func__); | |
771 | return rc; | |
772 | }; | |
773 | ||
774 | /* Read BCAPS and send to HDCP engine */ | |
fcda50c8 | 775 | rc = msm_hdmi_hdcp_recv_bcaps(hdcp_ctrl); |
c6a57a50 | 776 | if (rc) { |
777 | pr_err("%s: read bcaps error, abort\n", __func__); | |
778 | return rc; | |
779 | } | |
780 | ||
781 | /* | |
782 | * 1.1_Features turned off by default. | |
783 | * No need to write AInfo since 1.1_Features is disabled. | |
784 | */ | |
785 | hdmi_write(hdmi, REG_HDMI_HDCP_RCVPORT_DATA4, 0); | |
786 | ||
787 | /* Send AKSV and An to sink */ | |
fcda50c8 | 788 | rc = msm_hdmi_hdcp_send_aksv_an(hdcp_ctrl); |
c6a57a50 | 789 | if (rc) { |
790 | pr_err("%s:An/Aksv write failed\n", __func__); | |
791 | return rc; | |
792 | } | |
793 | ||
794 | /* Read BKSV and send to HDCP engine*/ | |
fcda50c8 | 795 | rc = msm_hdmi_hdcp_recv_bksv(hdcp_ctrl); |
c6a57a50 | 796 | if (rc) { |
797 | pr_err("%s:BKSV Process failed\n", __func__); | |
798 | return rc; | |
799 | } | |
800 | ||
801 | /* Enable HDCP interrupts and ack/clear any stale interrupts */ | |
802 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
803 | hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, | |
804 | HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_ACK | | |
805 | HDMI_HDCP_INT_CTRL_AUTH_SUCCESS_MASK | | |
806 | HDMI_HDCP_INT_CTRL_AUTH_FAIL_ACK | | |
807 | HDMI_HDCP_INT_CTRL_AUTH_FAIL_MASK | | |
808 | HDMI_HDCP_INT_CTRL_AUTH_FAIL_INFO_ACK); | |
809 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
810 | ||
811 | return 0; | |
812 | } | |
813 | ||
814 | /* read R0' from sink and pass it to HDCP engine */ | |
fcda50c8 | 815 | static int msm_hdmi_hdcp_auth_part1_recv_r0(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 816 | { |
817 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
818 | int rc = 0; | |
819 | u8 buf[2]; | |
820 | ||
821 | /* | |
822 | * HDCP Compliance Test case 1A-01: | |
823 | * Wait here at least 100ms before reading R0' | |
824 | */ | |
fcda50c8 | 825 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 125, AUTH_ABORT_EV); |
c6a57a50 | 826 | if (rc) |
827 | return rc; | |
828 | ||
829 | /* Read R0' at offset 0x08 */ | |
fcda50c8 | 830 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x08, buf, 2); |
c6a57a50 | 831 | if (rc) { |
832 | pr_err("%s:R0' read failed\n", __func__); | |
833 | return rc; | |
834 | } | |
835 | DBG("R0'=%02x%02x", buf[1], buf[0]); | |
836 | ||
837 | /* Write R0' to HDCP registers and check to see if it is a match */ | |
838 | hdmi_write(hdmi, REG_HDMI_HDCP_RCVPORT_DATA2_0, | |
839 | (((u32)buf[1]) << 8) | buf[0]); | |
840 | ||
841 | return 0; | |
842 | } | |
843 | ||
844 | /* Wait for authenticating result: R0/R0' are matched or not */ | |
fcda50c8 | 845 | static int msm_hdmi_hdcp_auth_part1_verify_r0(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 846 | { |
847 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
848 | u32 link0_status; | |
849 | int rc; | |
850 | ||
851 | /* wait for hdcp irq, 10 sec should be long enough */ | |
fcda50c8 | 852 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 10000, AUTH_RESULT_RDY_EV); |
c6a57a50 | 853 | if (!rc) { |
854 | pr_err("%s: Wait Auth IRQ timeout\n", __func__); | |
855 | return -ETIMEDOUT; | |
856 | } | |
857 | ||
858 | link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); | |
859 | if (!(link0_status & HDMI_HDCP_LINK0_STATUS_RI_MATCHES)) { | |
860 | pr_err("%s: Authentication Part I failed\n", __func__); | |
861 | return -EINVAL; | |
862 | } | |
863 | ||
864 | /* Enable HDCP Encryption */ | |
865 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, | |
866 | HDMI_HDCP_CTRL_ENABLE | | |
867 | HDMI_HDCP_CTRL_ENCRYPTION_ENABLE); | |
868 | ||
869 | return 0; | |
870 | } | |
871 | ||
fcda50c8 | 872 | static int msm_hdmi_hdcp_recv_check_bstatus(struct hdmi_hdcp_ctrl *hdcp_ctrl, |
c6a57a50 | 873 | u16 *pbstatus) |
874 | { | |
875 | int rc; | |
876 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
877 | bool max_devs_exceeded = false, max_cascade_exceeded = false; | |
878 | u32 repeater_cascade_depth = 0, down_stream_devices = 0; | |
879 | u16 bstatus; | |
880 | u8 buf[2]; | |
881 | ||
882 | /* Read BSTATUS at offset 0x41 */ | |
fcda50c8 | 883 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x41, buf, 2); |
c6a57a50 | 884 | if (rc) { |
885 | pr_err("%s: BSTATUS read failed\n", __func__); | |
886 | goto error; | |
887 | } | |
888 | *pbstatus = bstatus = (buf[1] << 8) | buf[0]; | |
889 | ||
890 | ||
891 | down_stream_devices = bstatus & 0x7F; | |
892 | repeater_cascade_depth = (bstatus >> 8) & 0x7; | |
893 | max_devs_exceeded = (bstatus & BIT(7)) ? true : false; | |
894 | max_cascade_exceeded = (bstatus & BIT(11)) ? true : false; | |
895 | ||
896 | if (down_stream_devices == 0) { | |
897 | /* | |
898 | * If no downstream devices are attached to the repeater | |
899 | * then part II fails. | |
900 | * todo: The other approach would be to continue PART II. | |
901 | */ | |
902 | pr_err("%s: No downstream devices\n", __func__); | |
903 | rc = -EINVAL; | |
904 | goto error; | |
905 | } | |
906 | ||
907 | /* | |
908 | * HDCP Compliance 1B-05: | |
909 | * Check if no. of devices connected to repeater | |
910 | * exceed max_devices_connected from bit 7 of Bstatus. | |
911 | */ | |
912 | if (max_devs_exceeded) { | |
913 | pr_err("%s: no. of devs connected exceeds max allowed", | |
914 | __func__); | |
915 | rc = -EINVAL; | |
916 | goto error; | |
917 | } | |
918 | ||
919 | /* | |
920 | * HDCP Compliance 1B-06: | |
921 | * Check if no. of cascade connected to repeater | |
922 | * exceed max_cascade_connected from bit 11 of Bstatus. | |
923 | */ | |
924 | if (max_cascade_exceeded) { | |
925 | pr_err("%s: no. of cascade conn exceeds max allowed", | |
926 | __func__); | |
927 | rc = -EINVAL; | |
928 | goto error; | |
929 | } | |
930 | ||
931 | error: | |
932 | hdcp_ctrl->dev_count = down_stream_devices; | |
933 | hdcp_ctrl->max_cascade_exceeded = max_cascade_exceeded; | |
934 | hdcp_ctrl->max_dev_exceeded = max_devs_exceeded; | |
935 | hdcp_ctrl->depth = repeater_cascade_depth; | |
936 | return rc; | |
937 | } | |
938 | ||
fcda50c8 | 939 | static int msm_hdmi_hdcp_auth_part2_wait_ksv_fifo_ready( |
c6a57a50 | 940 | struct hdmi_hdcp_ctrl *hdcp_ctrl) |
941 | { | |
942 | int rc; | |
943 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
944 | u32 reg, data; | |
945 | u32 timeout_count; | |
946 | u16 bstatus; | |
947 | u8 bcaps; | |
948 | ||
949 | /* | |
950 | * Wait until READY bit is set in BCAPS, as per HDCP specifications | |
951 | * maximum permitted time to check for READY bit is five seconds. | |
952 | */ | |
953 | timeout_count = 100; | |
954 | do { | |
955 | /* Read BCAPS at offset 0x40 */ | |
fcda50c8 | 956 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x40, &bcaps, 1); |
c6a57a50 | 957 | if (rc) { |
958 | pr_err("%s: BCAPS read failed\n", __func__); | |
959 | return rc; | |
960 | } | |
961 | ||
962 | if (bcaps & BIT(5)) | |
963 | break; | |
964 | ||
965 | timeout_count--; | |
966 | if (!timeout_count) { | |
967 | pr_err("%s: Wait KSV fifo ready timedout", __func__); | |
968 | return -ETIMEDOUT; | |
969 | } | |
970 | ||
fcda50c8 | 971 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 972 | if (rc) |
973 | return rc; | |
974 | } while (1); | |
975 | ||
fcda50c8 | 976 | rc = msm_hdmi_hdcp_recv_check_bstatus(hdcp_ctrl, &bstatus); |
c6a57a50 | 977 | if (rc) { |
978 | pr_err("%s: bstatus error\n", __func__); | |
979 | return rc; | |
980 | } | |
981 | ||
982 | /* Write BSTATUS and BCAPS to HDCP registers */ | |
983 | reg = REG_HDMI_HDCP_RCVPORT_DATA12; | |
984 | data = bcaps | (bstatus << 8); | |
fcda50c8 | 985 | rc = msm_hdmi_hdcp_scm_wr(hdcp_ctrl, ®, &data, 1); |
c6a57a50 | 986 | if (rc) { |
987 | pr_err("%s: BSTATUS write failed\n", __func__); | |
988 | return rc; | |
989 | } | |
990 | ||
991 | return 0; | |
992 | } | |
993 | ||
994 | /* | |
995 | * hdcp authenticating part 2: 2nd | |
996 | * read ksv fifo from sink | |
997 | * transfer V' from sink to HDCP engine | |
998 | * reset SHA engine | |
999 | */ | |
fcda50c8 | 1000 | static int msm_hdmi_hdcp_transfer_v_h(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1001 | { |
1002 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
1003 | int rc = 0; | |
1004 | struct hdmi_hdcp_reg_data reg_data[] = { | |
1005 | {REG_HDMI_HDCP_RCVPORT_DATA7, 0x20, "V' H0"}, | |
1006 | {REG_HDMI_HDCP_RCVPORT_DATA8, 0x24, "V' H1"}, | |
1007 | {REG_HDMI_HDCP_RCVPORT_DATA9, 0x28, "V' H2"}, | |
1008 | {REG_HDMI_HDCP_RCVPORT_DATA10, 0x2C, "V' H3"}, | |
1009 | {REG_HDMI_HDCP_RCVPORT_DATA11, 0x30, "V' H4"}, | |
1010 | }; | |
1011 | struct hdmi_hdcp_reg_data *rd; | |
1012 | u32 size = ARRAY_SIZE(reg_data); | |
1013 | u32 reg[ARRAY_SIZE(reg_data)]; | |
1014 | u32 data[ARRAY_SIZE(reg_data)]; | |
1015 | int i; | |
1016 | ||
1017 | for (i = 0; i < size; i++) { | |
1018 | rd = ®_data[i]; | |
fcda50c8 | 1019 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, |
c6a57a50 | 1020 | rd->off, (u8 *)&data[i], (u16)sizeof(data[i])); |
1021 | if (rc) { | |
1022 | pr_err("%s: Read %s failed\n", __func__, rd->name); | |
1023 | goto error; | |
1024 | } | |
1025 | ||
1026 | DBG("%s =%x", rd->name, data[i]); | |
1027 | reg[i] = reg_data[i].reg_id; | |
1028 | } | |
1029 | ||
fcda50c8 | 1030 | rc = msm_hdmi_hdcp_scm_wr(hdcp_ctrl, reg, data, size); |
c6a57a50 | 1031 | |
1032 | error: | |
1033 | return rc; | |
1034 | } | |
1035 | ||
fcda50c8 | 1036 | static int msm_hdmi_hdcp_recv_ksv_fifo(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1037 | { |
1038 | int rc; | |
1039 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
1040 | u32 ksv_bytes; | |
1041 | ||
1042 | ksv_bytes = 5 * hdcp_ctrl->dev_count; | |
1043 | ||
fcda50c8 | 1044 | rc = msm_hdmi_ddc_read(hdmi, HDCP_PORT_ADDR, 0x43, |
c6a57a50 | 1045 | hdcp_ctrl->ksv_list, ksv_bytes); |
1046 | if (rc) | |
1047 | pr_err("%s: KSV FIFO read failed\n", __func__); | |
1048 | ||
1049 | return rc; | |
1050 | } | |
1051 | ||
fcda50c8 | 1052 | static int msm_hdmi_hdcp_reset_sha_engine(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1053 | { |
1054 | u32 reg[2], data[2]; | |
1055 | u32 rc = 0; | |
1056 | ||
1057 | reg[0] = REG_HDMI_HDCP_SHA_CTRL; | |
1058 | data[0] = HDCP_REG_ENABLE; | |
1059 | reg[1] = REG_HDMI_HDCP_SHA_CTRL; | |
1060 | data[1] = HDCP_REG_DISABLE; | |
1061 | ||
fcda50c8 | 1062 | rc = msm_hdmi_hdcp_scm_wr(hdcp_ctrl, reg, data, 2); |
c6a57a50 | 1063 | |
1064 | return rc; | |
1065 | } | |
1066 | ||
fcda50c8 | 1067 | static int msm_hdmi_hdcp_auth_part2_recv_ksv_fifo( |
c6a57a50 | 1068 | struct hdmi_hdcp_ctrl *hdcp_ctrl) |
1069 | { | |
1070 | int rc; | |
1071 | u32 timeout_count; | |
1072 | ||
1073 | /* | |
1074 | * Read KSV FIFO over DDC | |
1075 | * Key Selection vector FIFO Used to pull downstream KSVs | |
1076 | * from HDCP Repeaters. | |
1077 | * All bytes (DEVICE_COUNT * 5) must be read in a single, | |
1078 | * auto incrementing access. | |
1079 | * All bytes read as 0x00 for HDCP Receivers that are not | |
1080 | * HDCP Repeaters (REPEATER == 0). | |
1081 | */ | |
1082 | timeout_count = 100; | |
1083 | do { | |
fcda50c8 | 1084 | rc = msm_hdmi_hdcp_recv_ksv_fifo(hdcp_ctrl); |
c6a57a50 | 1085 | if (!rc) |
1086 | break; | |
1087 | ||
1088 | timeout_count--; | |
1089 | if (!timeout_count) { | |
1090 | pr_err("%s: Recv ksv fifo timedout", __func__); | |
1091 | return -ETIMEDOUT; | |
1092 | } | |
1093 | ||
fcda50c8 | 1094 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 25, AUTH_ABORT_EV); |
c6a57a50 | 1095 | if (rc) |
1096 | return rc; | |
1097 | } while (1); | |
1098 | ||
fcda50c8 | 1099 | rc = msm_hdmi_hdcp_transfer_v_h(hdcp_ctrl); |
c6a57a50 | 1100 | if (rc) { |
1101 | pr_err("%s: transfer V failed\n", __func__); | |
1102 | return rc; | |
1103 | } | |
1104 | ||
1105 | /* reset SHA engine before write ksv fifo */ | |
fcda50c8 | 1106 | rc = msm_hdmi_hdcp_reset_sha_engine(hdcp_ctrl); |
c6a57a50 | 1107 | if (rc) { |
1108 | pr_err("%s: fail to reset sha engine\n", __func__); | |
1109 | return rc; | |
1110 | } | |
1111 | ||
1112 | return 0; | |
1113 | } | |
1114 | ||
1115 | /* | |
1116 | * Write KSV FIFO to HDCP_SHA_DATA. | |
1117 | * This is done 1 byte at time starting with the LSB. | |
1118 | * Once 64 bytes have been written, we need to poll for | |
1119 | * HDCP_SHA_BLOCK_DONE before writing any further | |
1120 | * If the last byte is written, we need to poll for | |
1121 | * HDCP_SHA_COMP_DONE to wait until HW finish | |
1122 | */ | |
fcda50c8 | 1123 | static int msm_hdmi_hdcp_write_ksv_fifo(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1124 | { |
1125 | int i; | |
1126 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
1127 | u32 ksv_bytes, last_byte = 0; | |
1128 | u8 *ksv_fifo = NULL; | |
1129 | u32 reg_val, data, reg; | |
1130 | u32 rc = 0; | |
1131 | ||
1132 | ksv_bytes = 5 * hdcp_ctrl->dev_count; | |
1133 | ||
1134 | /* Check if need to wait for HW completion */ | |
1135 | if (hdcp_ctrl->ksv_fifo_w_index) { | |
1136 | reg_val = hdmi_read(hdmi, REG_HDMI_HDCP_SHA_STATUS); | |
1137 | DBG("HDCP_SHA_STATUS=%08x", reg_val); | |
1138 | if (hdcp_ctrl->ksv_fifo_w_index == ksv_bytes) { | |
1139 | /* check COMP_DONE if last write */ | |
1140 | if (reg_val & HDMI_HDCP_SHA_STATUS_COMP_DONE) { | |
1141 | DBG("COMP_DONE"); | |
1142 | return 0; | |
1143 | } else { | |
1144 | return -EAGAIN; | |
1145 | } | |
1146 | } else { | |
1147 | /* check BLOCK_DONE if not last write */ | |
1148 | if (!(reg_val & HDMI_HDCP_SHA_STATUS_BLOCK_DONE)) | |
1149 | return -EAGAIN; | |
1150 | ||
1151 | DBG("BLOCK_DONE"); | |
1152 | } | |
1153 | } | |
1154 | ||
1155 | ksv_bytes -= hdcp_ctrl->ksv_fifo_w_index; | |
1156 | if (ksv_bytes <= 64) | |
1157 | last_byte = 1; | |
1158 | else | |
1159 | ksv_bytes = 64; | |
1160 | ||
1161 | ksv_fifo = hdcp_ctrl->ksv_list; | |
1162 | ksv_fifo += hdcp_ctrl->ksv_fifo_w_index; | |
1163 | ||
1164 | for (i = 0; i < ksv_bytes; i++) { | |
1165 | /* Write KSV byte and set DONE bit[0] for last byte*/ | |
1166 | reg_val = ksv_fifo[i] << 16; | |
1167 | if ((i == (ksv_bytes - 1)) && last_byte) | |
1168 | reg_val |= HDMI_HDCP_SHA_DATA_DONE; | |
1169 | ||
1170 | reg = REG_HDMI_HDCP_SHA_DATA; | |
1171 | data = reg_val; | |
fcda50c8 | 1172 | rc = msm_hdmi_hdcp_scm_wr(hdcp_ctrl, ®, &data, 1); |
c6a57a50 | 1173 | |
1174 | if (rc) | |
1175 | return rc; | |
1176 | } | |
1177 | ||
1178 | hdcp_ctrl->ksv_fifo_w_index += ksv_bytes; | |
1179 | ||
1180 | /* | |
1181 | *return -EAGAIN to notify caller to wait for COMP_DONE or BLOCK_DONE | |
1182 | */ | |
1183 | return -EAGAIN; | |
1184 | } | |
1185 | ||
1186 | /* write ksv fifo into HDCP engine */ | |
fcda50c8 | 1187 | static int msm_hdmi_hdcp_auth_part2_write_ksv_fifo( |
c6a57a50 | 1188 | struct hdmi_hdcp_ctrl *hdcp_ctrl) |
1189 | { | |
1190 | int rc; | |
1191 | u32 timeout_count; | |
1192 | ||
1193 | hdcp_ctrl->ksv_fifo_w_index = 0; | |
1194 | timeout_count = 100; | |
1195 | do { | |
fcda50c8 | 1196 | rc = msm_hdmi_hdcp_write_ksv_fifo(hdcp_ctrl); |
c6a57a50 | 1197 | if (!rc) |
1198 | break; | |
1199 | ||
1200 | if (rc != -EAGAIN) | |
1201 | return rc; | |
1202 | ||
1203 | timeout_count--; | |
1204 | if (!timeout_count) { | |
1205 | pr_err("%s: Write KSV fifo timedout", __func__); | |
1206 | return -ETIMEDOUT; | |
1207 | } | |
1208 | ||
fcda50c8 | 1209 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 1210 | if (rc) |
1211 | return rc; | |
1212 | } while (1); | |
1213 | ||
1214 | return 0; | |
1215 | } | |
1216 | ||
fcda50c8 | 1217 | static int msm_hdmi_hdcp_auth_part2_check_v_match(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1218 | { |
1219 | int rc = 0; | |
1220 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
1221 | u32 link0_status; | |
1222 | u32 timeout_count = 100; | |
1223 | ||
1224 | do { | |
1225 | link0_status = hdmi_read(hdmi, REG_HDMI_HDCP_LINK0_STATUS); | |
1226 | if (link0_status & HDMI_HDCP_LINK0_STATUS_V_MATCHES) | |
1227 | break; | |
1228 | ||
1229 | timeout_count--; | |
1230 | if (!timeout_count) { | |
1231 | pr_err("%s: HDCP V Match timedout", __func__); | |
1232 | return -ETIMEDOUT; | |
1233 | } | |
1234 | ||
fcda50c8 | 1235 | rc = msm_hdmi_hdcp_msleep(hdcp_ctrl, 20, AUTH_ABORT_EV); |
c6a57a50 | 1236 | if (rc) |
1237 | return rc; | |
1238 | } while (1); | |
1239 | ||
1240 | return 0; | |
1241 | } | |
1242 | ||
fcda50c8 | 1243 | static void msm_hdmi_hdcp_auth_work(struct work_struct *work) |
c6a57a50 | 1244 | { |
1245 | struct hdmi_hdcp_ctrl *hdcp_ctrl = container_of(work, | |
1246 | struct hdmi_hdcp_ctrl, hdcp_auth_work); | |
1247 | int rc; | |
1248 | ||
fcda50c8 | 1249 | rc = msm_hdmi_hdcp_auth_prepare(hdcp_ctrl); |
c6a57a50 | 1250 | if (rc) { |
1251 | pr_err("%s: auth prepare failed %d\n", __func__, rc); | |
1252 | goto end; | |
1253 | } | |
1254 | ||
1255 | /* HDCP PartI */ | |
fcda50c8 | 1256 | rc = msm_hdmi_hdcp_auth_part1_key_exchange(hdcp_ctrl); |
c6a57a50 | 1257 | if (rc) { |
1258 | pr_err("%s: key exchange failed %d\n", __func__, rc); | |
1259 | goto end; | |
1260 | } | |
1261 | ||
fcda50c8 | 1262 | rc = msm_hdmi_hdcp_auth_part1_recv_r0(hdcp_ctrl); |
c6a57a50 | 1263 | if (rc) { |
1264 | pr_err("%s: receive r0 failed %d\n", __func__, rc); | |
1265 | goto end; | |
1266 | } | |
1267 | ||
fcda50c8 | 1268 | rc = msm_hdmi_hdcp_auth_part1_verify_r0(hdcp_ctrl); |
c6a57a50 | 1269 | if (rc) { |
1270 | pr_err("%s: verify r0 failed %d\n", __func__, rc); | |
1271 | goto end; | |
1272 | } | |
1273 | pr_info("%s: Authentication Part I successful\n", __func__); | |
1274 | if (hdcp_ctrl->ds_type == DS_RECEIVER) | |
1275 | goto end; | |
1276 | ||
1277 | /* HDCP PartII */ | |
fcda50c8 | 1278 | rc = msm_hdmi_hdcp_auth_part2_wait_ksv_fifo_ready(hdcp_ctrl); |
c6a57a50 | 1279 | if (rc) { |
1280 | pr_err("%s: wait ksv fifo ready failed %d\n", __func__, rc); | |
1281 | goto end; | |
1282 | } | |
1283 | ||
fcda50c8 | 1284 | rc = msm_hdmi_hdcp_auth_part2_recv_ksv_fifo(hdcp_ctrl); |
c6a57a50 | 1285 | if (rc) { |
1286 | pr_err("%s: recv ksv fifo failed %d\n", __func__, rc); | |
1287 | goto end; | |
1288 | } | |
1289 | ||
fcda50c8 | 1290 | rc = msm_hdmi_hdcp_auth_part2_write_ksv_fifo(hdcp_ctrl); |
c6a57a50 | 1291 | if (rc) { |
1292 | pr_err("%s: write ksv fifo failed %d\n", __func__, rc); | |
1293 | goto end; | |
1294 | } | |
1295 | ||
fcda50c8 | 1296 | rc = msm_hdmi_hdcp_auth_part2_check_v_match(hdcp_ctrl); |
c6a57a50 | 1297 | if (rc) |
1298 | pr_err("%s: check v match failed %d\n", __func__, rc); | |
1299 | ||
1300 | end: | |
1301 | if (rc == -ECANCELED) { | |
1302 | pr_info("%s: hdcp authentication canceled\n", __func__); | |
1303 | } else if (rc == -ENOTSUPP) { | |
1304 | pr_info("%s: hdcp is not supported\n", __func__); | |
1305 | } else if (rc) { | |
1306 | pr_err("%s: hdcp authentication failed\n", __func__); | |
fcda50c8 | 1307 | msm_hdmi_hdcp_auth_fail(hdcp_ctrl); |
c6a57a50 | 1308 | } else { |
fcda50c8 | 1309 | msm_hdmi_hdcp_auth_done(hdcp_ctrl); |
c6a57a50 | 1310 | } |
1311 | } | |
1312 | ||
fcda50c8 | 1313 | void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1314 | { |
1315 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
1316 | u32 reg_val; | |
1317 | unsigned long flags; | |
1318 | ||
1319 | if ((HDCP_STATE_INACTIVE != hdcp_ctrl->hdcp_state) || | |
1320 | (HDCP_STATE_NO_AKSV == hdcp_ctrl->hdcp_state)) { | |
1321 | DBG("still active or activating or no askv. returning"); | |
1322 | return; | |
1323 | } | |
1324 | ||
1325 | /* clear HDMI Encrypt */ | |
1326 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
1327 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
1328 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
1329 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
1330 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
1331 | ||
1332 | hdcp_ctrl->auth_event = 0; | |
1333 | hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING; | |
1334 | hdcp_ctrl->auth_retries = 0; | |
1335 | queue_work(hdmi->workq, &hdcp_ctrl->hdcp_auth_work); | |
1336 | } | |
1337 | ||
fcda50c8 | 1338 | void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) |
c6a57a50 | 1339 | { |
1340 | struct hdmi *hdmi = hdcp_ctrl->hdmi; | |
1341 | unsigned long flags; | |
1342 | u32 reg_val; | |
1343 | ||
1344 | if ((HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) || | |
1345 | (HDCP_STATE_NO_AKSV == hdcp_ctrl->hdcp_state)) { | |
1346 | DBG("hdcp inactive or no aksv. returning"); | |
1347 | return; | |
1348 | } | |
1349 | ||
1350 | /* | |
1351 | * Disable HPD circuitry. | |
1352 | * This is needed to reset the HDCP cipher engine so that when we | |
1353 | * attempt a re-authentication, HW would clear the AN0_READY and | |
1354 | * AN1_READY bits in HDMI_HDCP_LINK0_STATUS register | |
1355 | */ | |
1356 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
1357 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
1358 | reg_val &= ~HDMI_HPD_CTRL_ENABLE; | |
1359 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
1360 | ||
1361 | /* | |
1362 | * Disable HDCP interrupts. | |
1363 | * Also, need to set the state to inactive here so that any ongoing | |
1364 | * reauth works will know that the HDCP session has been turned off. | |
1365 | */ | |
1366 | hdmi_write(hdmi, REG_HDMI_HDCP_INT_CTRL, 0); | |
1367 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
1368 | ||
1369 | /* | |
1370 | * Cancel any pending auth/reauth attempts. | |
1371 | * If one is ongoing, this will wait for it to finish. | |
1372 | * No more reauthentication attempts will be scheduled since we | |
1373 | * set the current state to inactive. | |
1374 | */ | |
1375 | set_bit(AUTH_ABORT_EV, &hdcp_ctrl->auth_event); | |
1376 | wake_up_all(&hdcp_ctrl->auth_event_queue); | |
1377 | cancel_work_sync(&hdcp_ctrl->hdcp_auth_work); | |
1378 | cancel_work_sync(&hdcp_ctrl->hdcp_reauth_work); | |
1379 | ||
1380 | hdmi_write(hdmi, REG_HDMI_HDCP_RESET, | |
1381 | HDMI_HDCP_RESET_LINK0_DEAUTHENTICATE); | |
1382 | ||
1383 | /* Disable encryption and disable the HDCP block */ | |
1384 | hdmi_write(hdmi, REG_HDMI_HDCP_CTRL, 0); | |
1385 | ||
1386 | spin_lock_irqsave(&hdmi->reg_lock, flags); | |
1387 | reg_val = hdmi_read(hdmi, REG_HDMI_CTRL); | |
1388 | reg_val &= ~HDMI_CTRL_ENCRYPTED; | |
1389 | hdmi_write(hdmi, REG_HDMI_CTRL, reg_val); | |
1390 | ||
1391 | /* Enable HPD circuitry */ | |
1392 | reg_val = hdmi_read(hdmi, REG_HDMI_HPD_CTRL); | |
1393 | reg_val |= HDMI_HPD_CTRL_ENABLE; | |
1394 | hdmi_write(hdmi, REG_HDMI_HPD_CTRL, reg_val); | |
1395 | spin_unlock_irqrestore(&hdmi->reg_lock, flags); | |
1396 | ||
1397 | hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE; | |
1398 | ||
1399 | DBG("HDCP: Off"); | |
1400 | } | |
1401 | ||
fcda50c8 | 1402 | struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi) |
c6a57a50 | 1403 | { |
1404 | struct hdmi_hdcp_ctrl *hdcp_ctrl = NULL; | |
1405 | ||
1406 | if (!hdmi->qfprom_mmio) { | |
1407 | pr_err("%s: HDCP is not supported without qfprom\n", | |
1408 | __func__); | |
1409 | return ERR_PTR(-EINVAL); | |
1410 | } | |
1411 | ||
1412 | hdcp_ctrl = kzalloc(sizeof(*hdcp_ctrl), GFP_KERNEL); | |
1413 | if (!hdcp_ctrl) | |
1414 | return ERR_PTR(-ENOMEM); | |
1415 | ||
fcda50c8 AB |
1416 | INIT_WORK(&hdcp_ctrl->hdcp_auth_work, msm_hdmi_hdcp_auth_work); |
1417 | INIT_WORK(&hdcp_ctrl->hdcp_reauth_work, msm_hdmi_hdcp_reauth_work); | |
c6a57a50 | 1418 | init_waitqueue_head(&hdcp_ctrl->auth_event_queue); |
1419 | hdcp_ctrl->hdmi = hdmi; | |
1420 | hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE; | |
1421 | hdcp_ctrl->aksv_valid = false; | |
1422 | ||
1423 | if (qcom_scm_hdcp_available()) | |
1424 | hdcp_ctrl->tz_hdcp = true; | |
1425 | else | |
1426 | hdcp_ctrl->tz_hdcp = false; | |
1427 | ||
1428 | return hdcp_ctrl; | |
1429 | } | |
1430 | ||
fcda50c8 | 1431 | void msm_hdmi_hdcp_destroy(struct hdmi *hdmi) |
c6a57a50 | 1432 | { |
1433 | if (hdmi && hdmi->hdcp_ctrl) { | |
1434 | kfree(hdmi->hdcp_ctrl); | |
1435 | hdmi->hdcp_ctrl = NULL; | |
1436 | } | |
1437 | } |