OLD | NEW |
(Empty) | |
| 1 /* linux/drivers/media/video/samsung/tv20/hdcp_s5pv210.c |
| 2 * |
| 3 * Copyright (c) 2010 Samsung Electronics Co., Ltd. |
| 4 * http://www.samsung.com/ |
| 5 * |
| 6 * S5PV210 - hdcp raw ftn file for Samsung TVOut driver |
| 7 * |
| 8 * This program is free software; you can redistribute it and/or modify |
| 9 * it under the terms of the GNU General Public License version 2 as |
| 10 * published by the Free Software Foundation. |
| 11 */ |
| 12 |
| 13 #include <linux/module.h> |
| 14 #include <linux/kernel.h> |
| 15 #include <linux/delay.h> |
| 16 #include <linux/device.h> |
| 17 #include <linux/wait.h> |
| 18 #include <linux/interrupt.h> |
| 19 #include <linux/workqueue.h> |
| 20 #include <linux/delay.h> |
| 21 #include <linux/i2c.h> |
| 22 #include <linux/irq.h> |
| 23 |
| 24 #include <linux/io.h> |
| 25 #include <mach/gpio.h> |
| 26 |
| 27 #include "ddc.h" |
| 28 #include "tv_out_s5pv210.h" |
| 29 #include <mach/regs-hdmi.h> |
| 30 |
| 31 #include <plat/gpio-cfg.h> |
| 32 |
| 33 /* for Operation check */ |
| 34 #ifdef CONFIG_TVOUT_RAW_DBG |
| 35 #define S5P_HDCP_DEBUG 1 |
| 36 #define S5P_HDCP_I2C_DEBUG 1 |
| 37 #define S5P_HDCP_AUTH_DEBUG 1 |
| 38 #endif |
| 39 |
| 40 #ifdef S5P_HDCP_DEBUG |
| 41 #define HDCPPRINTK(fmt, args...) \ |
| 42 printk(KERN_INFO "\t\t[HDCP] %s: " fmt, __func__ , ## args) |
| 43 #else |
| 44 #define HDCPPRINTK(fmt, args...) |
| 45 #endif |
| 46 |
| 47 /* for authentication key check */ |
| 48 #ifdef S5P_HDCP_AUTH_DEBUG |
| 49 #define AUTHPRINTK(fmt, args...) \ |
| 50 printk(KERN_INFO "\t\t\t[AUTHKEY] %s: " fmt, __func__ , ## args) |
| 51 #else |
| 52 #define AUTHPRINTK(fmt, args...) |
| 53 #endif |
| 54 |
| 55 enum hdmi_run_mode { |
| 56 DVI_MODE, |
| 57 HDMI_MODE |
| 58 }; |
| 59 |
| 60 enum hdmi_resolution { |
| 61 SD480P, |
| 62 SD480I, |
| 63 WWSD480P, |
| 64 HD720P, |
| 65 SD576P, |
| 66 WWSD576P, |
| 67 HD1080I |
| 68 }; |
| 69 |
| 70 enum hdmi_color_bar_type { |
| 71 HORIZONTAL, |
| 72 VERTICAL |
| 73 }; |
| 74 |
| 75 enum hdcp_event { |
| 76 /* Stop HDCP */ |
| 77 HDCP_EVENT_STOP, |
| 78 /* Start HDCP*/ |
| 79 HDCP_EVENT_START, |
| 80 /* Start to read Bksv,Bcaps */ |
| 81 HDCP_EVENT_READ_BKSV_START, |
| 82 /* Start to write Aksv,An */ |
| 83 HDCP_EVENT_WRITE_AKSV_START, |
| 84 /* Start to check if Ri is equal to Rj */ |
| 85 HDCP_EVENT_CHECK_RI_START, |
| 86 /* Start 2nd authentication process */ |
| 87 HDCP_EVENT_SECOND_AUTH_START |
| 88 }; |
| 89 |
| 90 enum hdcp_state { |
| 91 NOT_AUTHENTICATED, |
| 92 RECEIVER_READ_READY, |
| 93 BCAPS_READ_DONE, |
| 94 BKSV_READ_DONE, |
| 95 AN_WRITE_DONE, |
| 96 AKSV_WRITE_DONE, |
| 97 FIRST_AUTHENTICATION_DONE, |
| 98 SECOND_AUTHENTICATION_RDY, |
| 99 RECEIVER_FIFOLSIT_READY, |
| 100 SECOND_AUTHENTICATION_DONE, |
| 101 }; |
| 102 |
| 103 /* |
| 104 * Below CSC_TYPE is temporary. CSC_TYPE enum. |
| 105 * may be included in SetSD480pVars_60Hz etc. |
| 106 * |
| 107 * LR : Limited Range (16~235) |
| 108 * FR : Full Range (0~255) |
| 109 */ |
| 110 enum hdmi_intr_src { |
| 111 WAIT_FOR_ACTIVE_RX, |
| 112 WDT_FOR_REPEATER, |
| 113 EXCHANGE_KSV, |
| 114 UPDATE_P_VAL, |
| 115 UPDATE_R_VAL, |
| 116 AUDIO_OVERFLOW, |
| 117 AUTHEN_ACK, |
| 118 UNKNOWN_INT |
| 119 }; |
| 120 |
| 121 struct s5p_hdcp_info { |
| 122 bool is_repeater; |
| 123 bool hpd_status; |
| 124 u32 time_out; |
| 125 u32 hdcp_enable; |
| 126 |
| 127 spinlock_t lock; |
| 128 |
| 129 struct i2c_client *client; |
| 130 |
| 131 wait_queue_head_t waitq; |
| 132 enum hdcp_event event; |
| 133 enum hdcp_state auth_status; |
| 134 |
| 135 struct work_struct work; |
| 136 }; |
| 137 |
| 138 static struct s5p_hdcp_info hdcp_info = { |
| 139 .is_repeater = false, |
| 140 .time_out = 0, |
| 141 .hdcp_enable = false, |
| 142 .client = NULL, |
| 143 .event = HDCP_EVENT_STOP, |
| 144 .auth_status = NOT_AUTHENTICATED, |
| 145 |
| 146 }; |
| 147 |
| 148 #define HDCP_RI_OFFSET 0x08 |
| 149 #define INFINITE 0xffffffff |
| 150 |
| 151 #define HDMI_SYS_ENABLE (1 << 0) |
| 152 #define HDMI_ASP_ENABLE (1 << 2) |
| 153 #define HDMI_ASP_DISABLE (~HDMI_ASP_ENABLE) |
| 154 |
| 155 #define MAX_DEVS_EXCEEDED (0x1 << 7) |
| 156 #define MAX_CASCADE_EXCEEDED (0x1 << 3) |
| 157 |
| 158 #define MAX_CASCADE_EXCEEDED_ERROR (-1) |
| 159 #define MAX_DEVS_EXCEEDED_ERROR (-2) |
| 160 #define REPEATER_ILLEGAL_DEVICE_ERROR (-3) |
| 161 |
| 162 #define AINFO_SIZE 1 |
| 163 #define BCAPS_SIZE 1 |
| 164 #define BSTATUS_SIZE 2 |
| 165 #define SHA_1_HASH_SIZE 20 |
| 166 |
| 167 #define KSV_FIFO_READY (0x1 << 5) |
| 168 |
| 169 /* spmoon for test : it's not in manual */ |
| 170 #define SET_HDCP_KSV_WRITE_DONE (0x1 << 3) |
| 171 #define CLEAR_HDCP_KSV_WRITE_DONE (~SET_HDCP_KSV_WRITE_DONE) |
| 172 |
| 173 #define SET_HDCP_KSV_LIST_EMPTY (0x1 << 2) |
| 174 #define CLEAR_HDCP_KSV_LIST_EMPTY (~SET_HDCP_KSV_LIST_EMPTY) |
| 175 #define SET_HDCP_KSV_END (0x1 << 1) |
| 176 #define CLEAR_HDCP_KSV_END (~SET_HDCP_KSV_END) |
| 177 #define SET_HDCP_KSV_READ (0x1 << 0) |
| 178 #define CLEAR_HDCP_KSV_READ (~SET_HDCP_KSV_READ) |
| 179 |
| 180 #define SET_HDCP_SHA_VALID_READY (0x1 << 1) |
| 181 #define CLEAR_HDCP_SHA_VALID_READY (~SET_HDCP_SHA_VALID_READY) |
| 182 #define SET_HDCP_SHA_VALID (0x1 << 0) |
| 183 #define CLEAR_HDCP_SHA_VALID (~SET_HDCP_SHA_VALID) |
| 184 |
| 185 #define TRANSMIT_EVERY_VSYNC (0x1 << 1) |
| 186 |
| 187 /* |
| 188 * 1st Authentication step func. |
| 189 * Write the Ainfo data to Rx |
| 190 */ |
| 191 static bool write_ainfo(void) |
| 192 { |
| 193 int ret = 0; |
| 194 u8 ainfo[2]; |
| 195 |
| 196 ainfo[0] = HDCP_Ainfo; |
| 197 ainfo[1] = 0; |
| 198 |
| 199 ret = ddc_write(ainfo, 2); |
| 200 if (ret < 0) |
| 201 HDCPPRINTK("Can't write ainfo data through i2c bus\n"); |
| 202 |
| 203 return (ret < 0) ? false : true; |
| 204 } |
| 205 |
| 206 /* |
| 207 * Write the An data to Rx |
| 208 */ |
| 209 static bool write_an(void) |
| 210 { |
| 211 int ret = 0; |
| 212 u8 an[AN_SIZE+1]; |
| 213 |
| 214 an[0] = HDCP_An; |
| 215 |
| 216 /* Read An from HDMI */ |
| 217 an[1] = readb(hdmi_base + S5P_HDCP_An_0_0); |
| 218 an[2] = readb(hdmi_base + S5P_HDCP_An_0_1); |
| 219 an[3] = readb(hdmi_base + S5P_HDCP_An_0_2); |
| 220 an[4] = readb(hdmi_base + S5P_HDCP_An_0_3); |
| 221 an[5] = readb(hdmi_base + S5P_HDCP_An_1_0); |
| 222 an[6] = readb(hdmi_base + S5P_HDCP_An_1_1); |
| 223 an[7] = readb(hdmi_base + S5P_HDCP_An_1_2); |
| 224 an[8] = readb(hdmi_base + S5P_HDCP_An_1_3); |
| 225 |
| 226 ret = ddc_write(an, AN_SIZE + 1); |
| 227 if (ret < 0) |
| 228 HDCPPRINTK("Can't write an data through i2c bus\n"); |
| 229 |
| 230 #ifdef S5P_HDCP_AUTH_DEBUG |
| 231 { |
| 232 u16 i = 0; |
| 233 for (i = 1; i < AN_SIZE + 1; i++) |
| 234 AUTHPRINTK("HDCPAn[%d]: 0x%x \n", i, an[i]); |
| 235 } |
| 236 #endif |
| 237 |
| 238 return (ret < 0) ? false : true; |
| 239 } |
| 240 |
| 241 /* |
| 242 * Write the Aksv data to Rx |
| 243 */ |
| 244 static bool write_aksv(void) |
| 245 { |
| 246 int ret = 0; |
| 247 u8 aksv[AKSV_SIZE+1]; |
| 248 |
| 249 aksv[0] = HDCP_Aksv; |
| 250 |
| 251 /* Read Aksv from HDMI */ |
| 252 aksv[1] = readb(hdmi_base + S5P_HDCP_AKSV_0_0); |
| 253 aksv[2] = readb(hdmi_base + S5P_HDCP_AKSV_0_1); |
| 254 aksv[3] = readb(hdmi_base + S5P_HDCP_AKSV_0_2); |
| 255 aksv[4] = readb(hdmi_base + S5P_HDCP_AKSV_0_3); |
| 256 aksv[5] = readb(hdmi_base + S5P_HDCP_AKSV_1); |
| 257 |
| 258 ret = ddc_write(aksv, AKSV_SIZE + 1); |
| 259 if (ret < 0) |
| 260 HDCPPRINTK("Can't write aksv data through i2c bus\n"); |
| 261 |
| 262 #ifdef S5P_HDCP_AUTH_DEBUG |
| 263 { |
| 264 u16 i = 0; |
| 265 for (i = 1; i < AKSV_SIZE + 1; i++) |
| 266 AUTHPRINTK("HDCPAksv[%d]: 0x%x\n", i, aksv[i]); |
| 267 } |
| 268 #endif |
| 269 |
| 270 return (ret < 0) ? false : true; |
| 271 } |
| 272 |
| 273 static bool read_bcaps(void) |
| 274 { |
| 275 int ret = 0; |
| 276 u8 bcaps[BCAPS_SIZE] = {0}; |
| 277 |
| 278 ret = ddc_read(HDCP_Bcaps, bcaps, BCAPS_SIZE); |
| 279 |
| 280 if (ret < 0) { |
| 281 HDCPPRINTK("Can't read bcaps data from i2c bus\n"); |
| 282 return false; |
| 283 } |
| 284 |
| 285 writel(bcaps[0], hdmi_base + S5P_HDCP_BCAPS); |
| 286 |
| 287 HDCPPRINTK("BCAPS(from i2c) : 0x%08x\n", bcaps[0]); |
| 288 |
| 289 if (bcaps[0] & REPEATER_SET) |
| 290 hdcp_info.is_repeater = true; |
| 291 else |
| 292 hdcp_info.is_repeater = false; |
| 293 |
| 294 HDCPPRINTK("attached device type : %s !! \n\r", |
| 295 hdcp_info.is_repeater ? "REPEATER" : "SINK"); |
| 296 HDCPPRINTK("BCAPS(from sfr) = 0x%08x\n", |
| 297 readl(hdmi_base + S5P_HDCP_BCAPS)); |
| 298 |
| 299 return true; |
| 300 } |
| 301 |
| 302 static bool read_again_bksv(void) |
| 303 { |
| 304 u8 bk_sv[BKSV_SIZE] = {0, 0, 0, 0, 0}; |
| 305 u8 i = 0; |
| 306 u8 j = 0; |
| 307 u32 no_one = 0; |
| 308 u32 no_zero = 0; |
| 309 u32 result = 0; |
| 310 int ret = 0; |
| 311 |
| 312 ret = ddc_read(HDCP_Bksv, bk_sv, BKSV_SIZE); |
| 313 |
| 314 if (ret < 0) { |
| 315 HDCPPRINTK("Can't read bk_sv data from i2c bus\n"); |
| 316 return false; |
| 317 } |
| 318 |
| 319 #ifdef S5P_HDCP_AUTH_DEBUG |
| 320 for (i = 0; i < BKSV_SIZE; i++) |
| 321 AUTHPRINTK("i2c read : Bksv[%d]: 0x%x\n", i, bk_sv[i]); |
| 322 #endif |
| 323 |
| 324 for (i = 0; i < BKSV_SIZE; i++) { |
| 325 |
| 326 for (j = 0; j < 8; j++) { |
| 327 |
| 328 result = bk_sv[i] & (0x1 << j); |
| 329 |
| 330 if (result == 0) |
| 331 no_zero += 1; |
| 332 else |
| 333 no_one += 1; |
| 334 } |
| 335 } |
| 336 |
| 337 if ((no_zero == 20) && (no_one == 20)) { |
| 338 HDCPPRINTK("Suucess: no_zero, and no_one is 20\n"); |
| 339 |
| 340 writel(bk_sv[0], hdmi_base + S5P_HDCP_BKSV_0_0); |
| 341 writel(bk_sv[1], hdmi_base + S5P_HDCP_BKSV_0_1); |
| 342 writel(bk_sv[2], hdmi_base + S5P_HDCP_BKSV_0_2); |
| 343 writel(bk_sv[3], hdmi_base + S5P_HDCP_BKSV_0_3); |
| 344 writel(bk_sv[4], hdmi_base + S5P_HDCP_BKSV_1); |
| 345 |
| 346 #ifdef S5P_HDCP_AUTH_DEBUG |
| 347 for (i = 0; i < BKSV_SIZE; i++) |
| 348 AUTHPRINTK("set reg : Bksv[%d]: 0x%x\n", i, bk_sv[i]); |
| 349 |
| 350 /* writel(HDCP_ENC_ENABLE, hdmi_base + S5P_ENC_EN); */ |
| 351 #endif |
| 352 return true; |
| 353 } else { |
| 354 HDCPPRINTK("Failed: no_zero or no_one is NOT 20\n"); |
| 355 return false; |
| 356 } |
| 357 } |
| 358 |
| 359 static bool read_bksv(void) |
| 360 { |
| 361 u8 bk_sv[BKSV_SIZE] = {0, 0, 0, 0, 0}; |
| 362 |
| 363 int i = 0; |
| 364 int j = 0; |
| 365 |
| 366 u32 no_one = 0; |
| 367 u32 no_zero = 0; |
| 368 u32 result = 0; |
| 369 u32 count = 0; |
| 370 int ret = 0; |
| 371 |
| 372 ret = ddc_read(HDCP_Bksv, bk_sv, BKSV_SIZE); |
| 373 |
| 374 if (ret < 0) { |
| 375 HDCPPRINTK("Can't read bk_sv data from i2c bus\n"); |
| 376 return false; |
| 377 } |
| 378 |
| 379 #ifdef S5P_HDCP_AUTH_DEBUG |
| 380 for (i = 0; i < BKSV_SIZE; i++) |
| 381 AUTHPRINTK("i2c read : Bksv[%d]: 0x%x\n", i, bk_sv[i]); |
| 382 #endif |
| 383 |
| 384 for (i = 0; i < BKSV_SIZE; i++) { |
| 385 |
| 386 for (j = 0; j < 8; j++) { |
| 387 |
| 388 result = bk_sv[i] & (0x1 << j); |
| 389 |
| 390 if (result == 0) |
| 391 no_zero++; |
| 392 else |
| 393 no_one++; |
| 394 } |
| 395 } |
| 396 |
| 397 if ((no_zero == 20) && (no_one == 20)) { |
| 398 |
| 399 writel(bk_sv[0], hdmi_base + S5P_HDCP_BKSV_0_0); |
| 400 writel(bk_sv[1], hdmi_base + S5P_HDCP_BKSV_0_1); |
| 401 writel(bk_sv[2], hdmi_base + S5P_HDCP_BKSV_0_2); |
| 402 writel(bk_sv[3], hdmi_base + S5P_HDCP_BKSV_0_3); |
| 403 writel(bk_sv[4], hdmi_base + S5P_HDCP_BKSV_1); |
| 404 |
| 405 #ifdef S5P_HDCP_AUTH_DEBUG |
| 406 for (i = 0; i < BKSV_SIZE; i++) |
| 407 AUTHPRINTK("set reg : Bksv[%d]: 0x%x\n", i, bk_sv[i]); |
| 408 #endif |
| 409 |
| 410 HDCPPRINTK("Success: no_zero, and no_one is 20\n"); |
| 411 |
| 412 } else { |
| 413 |
| 414 HDCPPRINTK("Failed: no_zero or no_one is NOT 20\n"); |
| 415 |
| 416 /* writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN); */ |
| 417 |
| 418 while (!read_again_bksv()) { |
| 419 |
| 420 count++; |
| 421 |
| 422 mdelay(20); |
| 423 |
| 424 if (count == 140) |
| 425 return false; |
| 426 } |
| 427 } |
| 428 |
| 429 return true; |
| 430 } |
| 431 |
| 432 /* |
| 433 * Compare the R value of Tx with that of Rx |
| 434 */ |
| 435 static bool compare_r_val(void) |
| 436 { |
| 437 int ret = 0; |
| 438 u8 ri[2] = {0, 0}; |
| 439 u8 rj[2] = {0, 0}; |
| 440 u16 i; |
| 441 |
| 442 for (i = 0; i < R_VAL_RETRY_CNT; i++) { |
| 443 /* Read R value from Tx */ |
| 444 ri[0] = readl(hdmi_base + S5P_HDCP_Ri_0); |
| 445 ri[1] = readl(hdmi_base + S5P_HDCP_Ri_1); |
| 446 |
| 447 /* Read R value from Rx */ |
| 448 ret = ddc_read(HDCP_Ri, rj, 2); |
| 449 if (ret < 0) { |
| 450 HDCPPRINTK("Can't read r data from i2c bus\n"); |
| 451 return false; |
| 452 } |
| 453 |
| 454 #ifdef S5P_HDCP_AUTH_DEBUG |
| 455 AUTHPRINTK("retries :: %d\n", i); |
| 456 printk("\t\t\t Rx(ddc) ->"); |
| 457 printk("rj[0]: 0x%02x, rj[1]: 0x%02x\n", rj[0], rj[1]); |
| 458 printk(KERN_INFO "\t\t\t Tx(register) ->"); |
| 459 printk("ri[0]: 0x%02x, ri[1]: 0x%02x\n", ri[0], ri[1]); |
| 460 #endif |
| 461 |
| 462 /* Compare R value */ |
| 463 if ((ri[0] == rj[0]) && (ri[1] == rj[1]) && (ri[0] | ri[1])) { |
| 464 writel(Ri_MATCH_RESULT__YES, |
| 465 hdmi_base + S5P_HDCP_CHECK_RESULT); |
| 466 HDCPPRINTK("R0, R0' is matched!!\n"); |
| 467 ret = true; |
| 468 break; |
| 469 } else { |
| 470 writel(Ri_MATCH_RESULT__NO, |
| 471 hdmi_base + S5P_HDCP_CHECK_RESULT); |
| 472 HDCPPRINTK("R0, R0' is not matched!!\n"); |
| 473 ret = false; |
| 474 } |
| 475 |
| 476 } |
| 477 |
| 478 return ret ? true : false; |
| 479 } |
| 480 |
| 481 |
| 482 /* |
| 483 * Enable/Disable Software HPD control |
| 484 */ |
| 485 void sw_hpd_enable(bool enable) |
| 486 { |
| 487 u8 reg; |
| 488 |
| 489 reg = readb(hdmi_base + S5P_HPD); |
| 490 reg &= ~HPD_SW_ENABLE; |
| 491 |
| 492 if (enable) |
| 493 writeb(reg | HPD_SW_ENABLE, hdmi_base + S5P_HPD); |
| 494 else |
| 495 writeb(reg, hdmi_base + S5P_HPD); |
| 496 } |
| 497 |
| 498 /* |
| 499 * Set Software HPD level |
| 500 * |
| 501 * @param level [in] if 0 - low;othewise, high |
| 502 */ |
| 503 void set_sw_hpd(bool level) |
| 504 { |
| 505 u8 reg; |
| 506 |
| 507 reg = readb(hdmi_base + S5P_HPD); |
| 508 reg &= ~HPD_ON; |
| 509 |
| 510 if (level) |
| 511 writeb(reg | HPD_ON, hdmi_base + S5P_HPD); |
| 512 else |
| 513 writeb(reg, hdmi_base + S5P_HPD); |
| 514 } |
| 515 |
| 516 |
| 517 /* |
| 518 * Reset Authentication |
| 519 */ |
| 520 void reset_authentication(void) |
| 521 { |
| 522 u8 reg; |
| 523 |
| 524 hdcp_info.time_out = INFINITE; |
| 525 hdcp_info.event = HDCP_EVENT_STOP; |
| 526 hdcp_info.auth_status = NOT_AUTHENTICATED; |
| 527 |
| 528 HDCPPRINTK("Now reset authentication\n"); |
| 529 |
| 530 /* set hdcp_int disable */ |
| 531 reg = readb(hdmi_base + S5P_STATUS_EN); |
| 532 reg &= ~(WTFORACTIVERX_INT_OCCURRED | WATCHDOG_INT_OCCURRED | |
| 533 EXCHANGEKSV_INT_OCCURRED | UPDATE_RI_INT_OCCURRED); |
| 534 writeb(reg, hdmi_base + S5P_STATUS_EN); |
| 535 |
| 536 /* clear all result */ |
| 537 writeb(CLEAR_ALL_RESULTS, hdmi_base + S5P_HDCP_CHECK_RESULT); |
| 538 |
| 539 /* disable hdmi status enable reg. */ |
| 540 reg = readb(hdmi_base + S5P_STATUS_EN); |
| 541 reg &= HDCP_STATUS_DIS_ALL; |
| 542 writeb(reg, hdmi_base + S5P_STATUS_EN); |
| 543 |
| 544 /* clear all status pending */ |
| 545 reg = readb(hdmi_base + S5P_STATUS); |
| 546 reg |= HDCP_STATUS_EN_ALL; |
| 547 writeb(reg, hdmi_base + S5P_STATUS); |
| 548 |
| 549 /* Disable encryption */ |
| 550 writeb(HDCP_ENC_DIS, hdmi_base + S5P_ENC_EN); |
| 551 |
| 552 /* Disable hdcp */ |
| 553 writeb(0x0, hdmi_base + S5P_HDCP_CTRL1); |
| 554 writeb(0x0, hdmi_base + S5P_HDCP_CTRL2); |
| 555 |
| 556 /* |
| 557 * 1. Mask HPD plug and unplug interrupt |
| 558 * disable HPD INT |
| 559 */ |
| 560 s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG); |
| 561 s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG); |
| 562 |
| 563 /* 2. Enable software HPD */ |
| 564 sw_hpd_enable(true); |
| 565 |
| 566 /* 3. Make software HPD logical 0 */ |
| 567 set_sw_hpd(false); |
| 568 |
| 569 /* 4. Make software HPD logical 1 */ |
| 570 set_sw_hpd(true); |
| 571 |
| 572 /* 5. Disable software HPD */ |
| 573 sw_hpd_enable(false); |
| 574 |
| 575 /* 6. Unmask HPD plug and unplug interrupt */ |
| 576 s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG); |
| 577 s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG); |
| 578 |
| 579 /* set hdcp_int enable */ |
| 580 reg = readb(hdmi_base + S5P_STATUS_EN); |
| 581 reg |= WTFORACTIVERX_INT_OCCURRED | |
| 582 WATCHDOG_INT_OCCURRED | |
| 583 EXCHANGEKSV_INT_OCCURRED | |
| 584 UPDATE_RI_INT_OCCURRED; |
| 585 writeb(reg, hdmi_base + S5P_STATUS_EN); |
| 586 |
| 587 /* HDCP Enable */ |
| 588 writeb(CP_DESIRED_EN, hdmi_base + S5P_HDCP_CTRL1); |
| 589 |
| 590 } |
| 591 |
| 592 /* |
| 593 * Set the timing parameter for load e-fuse key. |
| 594 */ |
| 595 |
| 596 /* TODO: must use clk_get for pclk rate */ |
| 597 #define PCLK_D_RATE_FOR_HDCP 166000000 |
| 598 |
| 599 u32 efuse_ceil(u32 val, u32 time) |
| 600 { |
| 601 u32 res; |
| 602 |
| 603 res = val / time; |
| 604 |
| 605 if (val % time) |
| 606 res += 1; |
| 607 |
| 608 return res; |
| 609 } |
| 610 |
| 611 static void hdcp_efuse_timing(void) |
| 612 { |
| 613 u32 time, val; |
| 614 |
| 615 /* TODO: must use clk_get for pclk rate */ |
| 616 time = 1000000000/PCLK_D_RATE_FOR_HDCP; |
| 617 |
| 618 val = efuse_ceil(EFUSE_ADDR_WIDTH, time); |
| 619 writeb(val, hdmi_base + S5P_EFUSE_ADDR_WIDTH); |
| 620 |
| 621 val = efuse_ceil(EFUSE_SIGDEV_ASSERT, time); |
| 622 writeb(val, hdmi_base + S5P_EFUSE_SIGDEV_ASSERT); |
| 623 |
| 624 val = efuse_ceil(EFUSE_SIGDEV_DEASSERT, time); |
| 625 writeb(val, hdmi_base + S5P_EFUSE_SIGDEV_DEASSERT); |
| 626 |
| 627 val = efuse_ceil(EFUSE_PRCHG_ASSERT, time); |
| 628 writeb(val, hdmi_base + S5P_EFUSE_PRCHG_ASSERT); |
| 629 |
| 630 val = efuse_ceil(EFUSE_PRCHG_DEASSERT, time); |
| 631 writeb(val, hdmi_base + S5P_EFUSE_PRCHG_DEASSERT); |
| 632 |
| 633 val = efuse_ceil(EFUSE_FSET_ASSERT, time); |
| 634 writeb(val, hdmi_base + S5P_EFUSE_FSET_ASSERT); |
| 635 |
| 636 val = efuse_ceil(EFUSE_FSET_DEASSERT, time); |
| 637 writeb(val, hdmi_base + S5P_EFUSE_FSET_DEASSERT); |
| 638 |
| 639 val = efuse_ceil(EFUSE_SENSING, time); |
| 640 writeb(val, hdmi_base + S5P_EFUSE_SENSING); |
| 641 |
| 642 val = efuse_ceil(EFUSE_SCK_ASSERT, time); |
| 643 writeb(val, hdmi_base + S5P_EFUSE_SCK_ASSERT); |
| 644 |
| 645 val = efuse_ceil(EFUSE_SCK_DEASSERT, time); |
| 646 writeb(val, hdmi_base + S5P_EFUSE_SCK_DEASSERT); |
| 647 |
| 648 val = efuse_ceil(EFUSE_SDOUT_OFFSET, time); |
| 649 writeb(val, hdmi_base + S5P_EFUSE_SDOUT_OFFSET); |
| 650 |
| 651 val = efuse_ceil(EFUSE_READ_OFFSET, time); |
| 652 writeb(val, hdmi_base + S5P_EFUSE_READ_OFFSET); |
| 653 |
| 654 } |
| 655 |
| 656 /* |
| 657 * load hdcp key from e-fuse mem. |
| 658 */ |
| 659 static int hdcp_loadkey(void) |
| 660 { |
| 661 u8 status; |
| 662 |
| 663 hdcp_efuse_timing(); |
| 664 |
| 665 /* read HDCP key from E-Fuse */ |
| 666 writeb(EFUSE_CTRL_ACTIVATE, hdmi_base + S5P_EFUSE_CTRL); |
| 667 |
| 668 do { |
| 669 status = readb(hdmi_base + S5P_EFUSE_STATUS); |
| 670 } while (!(status & EFUSE_ECC_DONE)); |
| 671 |
| 672 if (readb(hdmi_base + S5P_EFUSE_STATUS) & EFUSE_ECC_FAIL) { |
| 673 HDCPPRINTK("Can't load key from fuse ctrl.\n"); |
| 674 return -EINVAL; |
| 675 } |
| 676 |
| 677 return 0; |
| 678 |
| 679 } |
| 680 |
| 681 /* |
| 682 * Start encryption |
| 683 */ |
| 684 static void start_encryption(void) |
| 685 { |
| 686 u32 hdcp_status; |
| 687 |
| 688 /* Ri == Ri' |Ready the compared result of Ri */ |
| 689 writel(Ri_MATCH_RESULT__YES, hdmi_base + S5P_HDCP_CHECK_RESULT); |
| 690 |
| 691 do { |
| 692 hdcp_status = readl(hdmi_base + S5P_STATUS); |
| 693 /* Wait for STATUS[7] to '1'*/ |
| 694 } while ((hdcp_status & AUTHENTICATED) != AUTHENTICATED); |
| 695 |
| 696 /* Start encryption */ |
| 697 writel(HDCP_ENC_ENABLE, hdmi_base + S5P_ENC_EN); |
| 698 |
| 699 } |
| 700 |
| 701 /* |
| 702 * Check whether Rx is repeater or not |
| 703 */ |
| 704 static int check_repeater(void) |
| 705 { |
| 706 int ret = 0; |
| 707 u8 i = 0; |
| 708 u16 j = 0; |
| 709 |
| 710 u8 bcaps[BCAPS_SIZE] = {0}; |
| 711 u8 status[BSTATUS_SIZE] = {0, 0}; |
| 712 u8 rx_v[SHA_1_HASH_SIZE] = {0}; |
| 713 u8 ksv_list[HDCP_MAX_DEVS*HDCP_KSV_SIZE] = {0}; |
| 714 |
| 715 u32 hdcp_ctrl = 0; |
| 716 u32 dev_cnt; |
| 717 u32 stat; |
| 718 |
| 719 bool ksv_fifo_ready = false; |
| 720 |
| 721 memset(rx_v, 0x0, SHA_1_HASH_SIZE); |
| 722 memset(ksv_list, 0x0, HDCP_MAX_DEVS*HDCP_KSV_SIZE); |
| 723 |
| 724 while (j <= 500) { |
| 725 ret = ddc_read(HDCP_Bcaps, |
| 726 bcaps, BCAPS_SIZE); |
| 727 |
| 728 if (ret < 0) { |
| 729 HDCPPRINTK("Can't read bcaps data from i2c bus\n"); |
| 730 return false; |
| 731 } |
| 732 |
| 733 if (bcaps[0] & KSV_FIFO_READY) { |
| 734 HDCPPRINTK("ksv fifo is ready\n"); |
| 735 ksv_fifo_ready = true; |
| 736 writel(bcaps[0], hdmi_base + S5P_HDCP_BCAPS); |
| 737 break; |
| 738 } else { |
| 739 HDCPPRINTK("ksv fifo is not ready\n"); |
| 740 ksv_fifo_ready = false; |
| 741 mdelay(10); |
| 742 j++; |
| 743 } |
| 744 |
| 745 } |
| 746 |
| 747 if (j == 500) { |
| 748 HDCPPRINTK("ksv fifo check timeout occurred!!\n"); |
| 749 return false; |
| 750 } |
| 751 |
| 752 if (ksv_fifo_ready) { |
| 753 hdcp_ctrl = readl(hdmi_base + S5P_HDCP_CTRL1); |
| 754 hdcp_ctrl &= CLEAR_REPEATER_TIMEOUT; |
| 755 writel(hdcp_ctrl, hdmi_base + S5P_HDCP_CTRL1); |
| 756 } else |
| 757 return false; |
| 758 |
| 759 /* |
| 760 * Check MAX_CASCADE_EXCEEDED |
| 761 * or MAX_DEVS_EXCEEDED indicator |
| 762 */ |
| 763 ret = ddc_read(HDCP_BStatus, status, BSTATUS_SIZE); |
| 764 |
| 765 if (ret < 0) { |
| 766 HDCPPRINTK("Can't read status data from i2c bus\n"); |
| 767 return false; |
| 768 } |
| 769 |
| 770 /* MAX_CASCADE_EXCEEDED || MAX_DEVS_EXCEEDED */ |
| 771 if (status[1] & MAX_CASCADE_EXCEEDED) { |
| 772 HDCPPRINTK("MAX_CASCADE_EXCEEDED\n"); |
| 773 return MAX_CASCADE_EXCEEDED_ERROR; |
| 774 } else if (status[0] & MAX_DEVS_EXCEEDED) { |
| 775 HDCPPRINTK("MAX_CASCADE_EXCEEDED\n"); |
| 776 return MAX_DEVS_EXCEEDED_ERROR; |
| 777 } |
| 778 |
| 779 writel(status[0], hdmi_base + S5P_HDCP_BSTATUS_0); |
| 780 writel(status[1], hdmi_base + S5P_HDCP_BSTATUS_1); |
| 781 |
| 782 /* Read KSV list */ |
| 783 dev_cnt = (*status) & 0x7f; |
| 784 |
| 785 HDCPPRINTK("status[0] :0x%08x, status[1] :0x%08x!!\n", |
| 786 status[0], status[1]); |
| 787 |
| 788 if (dev_cnt) { |
| 789 |
| 790 u32 val = 0; |
| 791 |
| 792 /* read ksv */ |
| 793 ret = ddc_read(HDCP_KSVFIFO, ksv_list, |
| 794 dev_cnt * HDCP_KSV_SIZE); |
| 795 if (ret < 0) { |
| 796 HDCPPRINTK("Can't read ksv fifo!!\n"); |
| 797 return false; |
| 798 } |
| 799 |
| 800 /* write ksv */ |
| 801 for (i = 0; i < dev_cnt; i++) { |
| 802 |
| 803 writel(ksv_list[(i*5) + 0], |
| 804 hdmi_base + S5P_HDCP_RX_KSV_0_0); |
| 805 writel(ksv_list[(i*5) + 1], |
| 806 hdmi_base + S5P_HDCP_RX_KSV_0_1); |
| 807 writel(ksv_list[(i*5) + 2], |
| 808 hdmi_base + S5P_HDCP_RX_KSV_0_2); |
| 809 writel(ksv_list[(i*5) + 3], |
| 810 hdmi_base + S5P_HDCP_RX_KSV_0_3); |
| 811 writel(ksv_list[(i*5) + 4], |
| 812 hdmi_base + S5P_HDCP_RX_KSV_0_4); |
| 813 |
| 814 if (i != (dev_cnt - 1)) { /* if it's not end */ |
| 815 /* it's not in manual */ |
| 816 writel(SET_HDCP_KSV_WRITE_DONE, |
| 817 S5P_HDCP_RX_KSV_LIST_CTRL); |
| 818 |
| 819 mdelay(20); |
| 820 |
| 821 /* check ksv readed */ |
| 822 do { |
| 823 if (!hdcp_info.hdcp_enable) |
| 824 return false; |
| 825 |
| 826 stat = readl(hdmi_base + |
| 827 S5P_HDCP_RX_KSV_LIST_CTRL); |
| 828 |
| 829 } while (!(stat & SET_HDCP_KSV_READ)); |
| 830 |
| 831 |
| 832 HDCPPRINTK("read complete\n"); |
| 833 |
| 834 } |
| 835 |
| 836 HDCPPRINTK("HDCP_RX_KSV_1 = 0x%x\n\r", |
| 837 readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL)); |
| 838 HDCPPRINTK("i : %d, dev_cnt : %d, val = 0x%08x\n", |
| 839 i, dev_cnt, val); |
| 840 } |
| 841 |
| 842 /* end of ksv */ |
| 843 val = readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL); |
| 844 val |= SET_HDCP_KSV_END|SET_HDCP_KSV_WRITE_DONE; |
| 845 writel(val, hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL); |
| 846 |
| 847 HDCPPRINTK("HDCP_RX_KSV_1 = 0x%x\n\r", |
| 848 readl(hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL)); |
| 849 HDCPPRINTK("i : %d, dev_cnt : %d, val = 0x%08x\n", |
| 850 i, dev_cnt, val); |
| 851 |
| 852 } else { |
| 853 |
| 854 /* mdelay(200); */ |
| 855 |
| 856 writel(SET_HDCP_KSV_LIST_EMPTY, |
| 857 hdmi_base + S5P_HDCP_RX_KSV_LIST_CTRL); |
| 858 } |
| 859 |
| 860 |
| 861 /* Read SHA-1 from receiver */ |
| 862 ret = ddc_read(HDCP_SHA1, rx_v, SHA_1_HASH_SIZE); |
| 863 |
| 864 if (ret < 0) { |
| 865 HDCPPRINTK("Can't read sha_1_hash data from i2c bus\n"); |
| 866 return false; |
| 867 } |
| 868 |
| 869 for (i = 0; i < SHA_1_HASH_SIZE; i++) |
| 870 HDCPPRINTK("SHA_1 rx :: %x\n", rx_v[i]); |
| 871 |
| 872 /* write SHA-1 to register */ |
| 873 writel(rx_v[0], hdmi_base + S5P_HDCP_RX_SHA1_0_0); |
| 874 writel(rx_v[1], hdmi_base + S5P_HDCP_RX_SHA1_0_1); |
| 875 writel(rx_v[2], hdmi_base + S5P_HDCP_RX_SHA1_0_2); |
| 876 writel(rx_v[3], hdmi_base + S5P_HDCP_RX_SHA1_0_3); |
| 877 writel(rx_v[4], hdmi_base + S5P_HDCP_RX_SHA1_1_0); |
| 878 writel(rx_v[5], hdmi_base + S5P_HDCP_RX_SHA1_1_1); |
| 879 writel(rx_v[6], hdmi_base + S5P_HDCP_RX_SHA1_1_2); |
| 880 writel(rx_v[7], hdmi_base + S5P_HDCP_RX_SHA1_1_3); |
| 881 writel(rx_v[8], hdmi_base + S5P_HDCP_RX_SHA1_2_0); |
| 882 writel(rx_v[9], hdmi_base + S5P_HDCP_RX_SHA1_2_1); |
| 883 writel(rx_v[10], hdmi_base + S5P_HDCP_RX_SHA1_2_2); |
| 884 writel(rx_v[11], hdmi_base + S5P_HDCP_RX_SHA1_2_3); |
| 885 writel(rx_v[12], hdmi_base + S5P_HDCP_RX_SHA1_3_0); |
| 886 writel(rx_v[13], hdmi_base + S5P_HDCP_RX_SHA1_3_1); |
| 887 writel(rx_v[14], hdmi_base + S5P_HDCP_RX_SHA1_3_2); |
| 888 writel(rx_v[15], hdmi_base + S5P_HDCP_RX_SHA1_3_3); |
| 889 writel(rx_v[16], hdmi_base + S5P_HDCP_RX_SHA1_4_0); |
| 890 writel(rx_v[17], hdmi_base + S5P_HDCP_RX_SHA1_4_1); |
| 891 writel(rx_v[18], hdmi_base + S5P_HDCP_RX_SHA1_4_2); |
| 892 writel(rx_v[19], hdmi_base + S5P_HDCP_RX_SHA1_4_3); |
| 893 |
| 894 /* SHA write done, and wait for SHA computation being done */ |
| 895 mdelay(1); |
| 896 |
| 897 /* check authentication success or not */ |
| 898 stat = readl(hdmi_base + S5P_HDCP_AUTH_STATUS); |
| 899 |
| 900 HDCPPRINTK("auth status %d\n", stat); |
| 901 |
| 902 if (stat & SET_HDCP_SHA_VALID_READY) { |
| 903 |
| 904 HDCPPRINTK("SHA valid ready 0x%x \n\r", stat); |
| 905 |
| 906 stat = readl(hdmi_base + S5P_HDCP_AUTH_STATUS); |
| 907 |
| 908 if (stat & SET_HDCP_SHA_VALID) { |
| 909 |
| 910 HDCPPRINTK("SHA valid 0x%x \n\r", stat); |
| 911 |
| 912 ret = true; |
| 913 } else { |
| 914 HDCPPRINTK("SHA valid ready, but not valid 0x%x \n\r", |
| 915 stat); |
| 916 ret = false; |
| 917 } |
| 918 |
| 919 } else { |
| 920 |
| 921 HDCPPRINTK("SHA not ready 0x%x \n\r", stat); |
| 922 ret = false; |
| 923 } |
| 924 |
| 925 |
| 926 /* clear all validate bit */ |
| 927 writel(0x0, hdmi_base + S5P_HDCP_AUTH_STATUS); |
| 928 |
| 929 return ret; |
| 930 |
| 931 } |
| 932 |
| 933 static bool try_read_receiver(void) |
| 934 { |
| 935 u8 i = 0; |
| 936 bool ret = false; |
| 937 |
| 938 for (i = 0; i < 40; i++) { |
| 939 |
| 940 mdelay(250); |
| 941 |
| 942 if (hdcp_info.auth_status != RECEIVER_READ_READY) { |
| 943 |
| 944 HDCPPRINTK("hdcp stat. changed!!" |
| 945 "failed attempt no = %d\n\r", i); |
| 946 |
| 947 return false; |
| 948 } |
| 949 |
| 950 ret = read_bcaps(); |
| 951 |
| 952 if (ret) { |
| 953 |
| 954 HDCPPRINTK("succeeded at attempt no= %d \n\r", i); |
| 955 |
| 956 return true; |
| 957 |
| 958 } else |
| 959 HDCPPRINTK("can't read bcaps!!" |
| 960 "failed attempt no=%d\n\r", i); |
| 961 } |
| 962 |
| 963 return false; |
| 964 } |
| 965 |
| 966 |
| 967 /* |
| 968 * stop - stop functions are only called under running HDCP |
| 969 */ |
| 970 bool tv_stop_hdcp(void) |
| 971 { |
| 972 u32 sfr_val = 0; |
| 973 |
| 974 HDCPPRINTK("HDCP ftn. Stop!!\n"); |
| 975 |
| 976 s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG); |
| 977 s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG); |
| 978 s5p_hdmi_disable_interrupts(HDMI_IRQ_HDCP); |
| 979 |
| 980 hdcp_protocol_status = 0; |
| 981 |
| 982 hdcp_info.time_out = INFINITE; |
| 983 hdcp_info.event = HDCP_EVENT_STOP; |
| 984 hdcp_info.auth_status = NOT_AUTHENTICATED; |
| 985 hdcp_info.hdcp_enable = false; |
| 986 |
| 987 /* hdcp_info.client = NULL; */ |
| 988 |
| 989 /* 3. disable hdcp control reg. */ |
| 990 sfr_val = readl(hdmi_base + S5P_HDCP_CTRL1); |
| 991 sfr_val &= (ENABLE_1_DOT_1_FEATURE_DIS |
| 992 & CLEAR_REPEATER_TIMEOUT |
| 993 & EN_PJ_DIS |
| 994 & CP_DESIRED_DIS); |
| 995 writel(sfr_val, hdmi_base + S5P_HDCP_CTRL1); |
| 996 |
| 997 /* 1-3. disable hdmi hpd reg. */ |
| 998 writel(CABLE_UNPLUGGED, hdmi_base + S5P_HPD); |
| 999 |
| 1000 /* 1-2. disable hdmi status enable reg. */ |
| 1001 sfr_val = readl(hdmi_base + S5P_STATUS_EN); |
| 1002 sfr_val &= HDCP_STATUS_DIS_ALL; |
| 1003 writel(sfr_val, hdmi_base + S5P_STATUS_EN); |
| 1004 |
| 1005 /* 1-1. clear all status pending */ |
| 1006 sfr_val = readl(hdmi_base + S5P_STATUS); |
| 1007 sfr_val |= HDCP_STATUS_EN_ALL; |
| 1008 writel(sfr_val, hdmi_base + S5P_STATUS); |
| 1009 |
| 1010 /* disable encryption */ |
| 1011 writel(HDCP_ENC_DISABLE, hdmi_base + S5P_ENC_EN); |
| 1012 |
| 1013 /* clear result */ |
| 1014 writel(Ri_MATCH_RESULT__NO, hdmi_base + S5P_HDCP_CHECK_RESULT); |
| 1015 writel(readl(hdmi_base + S5P_HDMI_CON_0) & HDMI_DIS, |
| 1016 hdmi_base + S5P_HDMI_CON_0); |
| 1017 writel(readl(hdmi_base + S5P_HDMI_CON_0) | HDMI_EN, |
| 1018 hdmi_base + S5P_HDMI_CON_0); |
| 1019 writel(CLEAR_ALL_RESULTS, hdmi_base + S5P_HDCP_CHECK_RESULT); |
| 1020 |
| 1021 /* hdmi disable */ |
| 1022 /* |
| 1023 sfr_val = readl(hdmi_base + S5P_HDMI_CON_0); |
| 1024 sfr_val &= ~(PWDN_ENB_NORMAL | HDMI_EN | ASP_EN); |
| 1025 writel( sfr_val, hdmi_base + S5P_HDMI_CON_0); |
| 1026 */ |
| 1027 HDCPPRINTK("\tSTATUS \t0x%08x\n", readl(hdmi_base + S5P_STATUS)); |
| 1028 HDCPPRINTK("\tSTATUS_EN \t0x%08x\n", |
| 1029 readl(hdmi_base + S5P_STATUS_EN)); |
| 1030 HDCPPRINTK("\tHPD \t0x%08x\n", readl(hdmi_base + S5P_HPD)); |
| 1031 HDCPPRINTK("\tHDCP_CTRL \t0x%08x\n", |
| 1032 readl(hdmi_base + S5P_HDCP_CTRL1)); |
| 1033 HDCPPRINTK("\tMODE_SEL \t0x%08x\n", |
| 1034 readl(hdmi_base + S5P_MODE_SEL)); |
| 1035 HDCPPRINTK("\tENC_EN \t0x%08x\n", readl(hdmi_base + S5P_ENC_EN)); |
| 1036 HDCPPRINTK("\tHDMI_CON_0 \t0x%08x\n", |
| 1037 readl(hdmi_base + S5P_HDMI_CON_0)); |
| 1038 |
| 1039 return true; |
| 1040 } |
| 1041 |
| 1042 void tv_hdcp_reset(void) |
| 1043 { |
| 1044 tv_stop_hdcp(); |
| 1045 |
| 1046 hdcp_protocol_status = 2; |
| 1047 |
| 1048 HDCPPRINTK("HDCP ftn. reset!!\n"); |
| 1049 } |
| 1050 |
| 1051 /* |
| 1052 * start - start functions are only called under stopping HDCP |
| 1053 */ |
| 1054 bool tv_start_hdcp(void) |
| 1055 { |
| 1056 u32 sfr_val; |
| 1057 |
| 1058 hdcp_info.event = HDCP_EVENT_STOP; |
| 1059 hdcp_info.time_out = INFINITE; |
| 1060 hdcp_info.auth_status = NOT_AUTHENTICATED; |
| 1061 |
| 1062 HDCPPRINTK("HDCP ftn. Start!!\n"); |
| 1063 |
| 1064 /* from hpd for test */ |
| 1065 s5p_hdmi_hpd_gen(); |
| 1066 |
| 1067 s3c_gpio_cfgpin(S5PV210_GPH1(5), S5P_GPH1_5_HDMI_HPD); |
| 1068 s3c_gpio_setpull(S5PV210_GPH1(5), S3C_GPIO_PULL_UP); |
| 1069 |
| 1070 s5p_hdmi_enable_interrupts(HDMI_IRQ_HDCP); |
| 1071 |
| 1072 s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_PLUG); |
| 1073 s5p_hdmi_disable_interrupts(HDMI_IRQ_HPD_UNPLUG); |
| 1074 |
| 1075 /* 2. Enable software HPD */ |
| 1076 sw_hpd_enable(true); |
| 1077 |
| 1078 /* 3. Make software HPD logical 0 */ |
| 1079 set_sw_hpd(false); |
| 1080 |
| 1081 /* 4. Make software HPD logical 1 */ |
| 1082 set_sw_hpd(true); |
| 1083 |
| 1084 /* 5. Disable software HPD */ |
| 1085 sw_hpd_enable(false); |
| 1086 |
| 1087 /* 6. Unmask HPD plug and unplug interrupt */ |
| 1088 s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_PLUG); |
| 1089 s5p_hdmi_enable_interrupts(HDMI_IRQ_HPD_UNPLUG); |
| 1090 |
| 1091 |
| 1092 hdcp_protocol_status = 1; |
| 1093 |
| 1094 if (!read_bcaps()) { |
| 1095 HDCPPRINTK("can't read ddc port!\n"); |
| 1096 reset_authentication(); |
| 1097 } |
| 1098 |
| 1099 /* for av mute */ |
| 1100 writel(DO_NOT_TRANSMIT, hdmi_base + S5P_GCP_CON); |
| 1101 |
| 1102 /* |
| 1103 * 1-1. set hdmi status enable reg. |
| 1104 * Update_Ri_int_en should be enabled after |
| 1105 * s/w gets ExchangeKSV_int. |
| 1106 */ |
| 1107 writel(HDCP_STATUS_EN_ALL, hdmi_base + S5P_STATUS_EN); |
| 1108 |
| 1109 /* 1-2. set hdmi hpd reg. */ |
| 1110 writel(CABLE_PLUGGED, hdmi_base+S5P_HPD); |
| 1111 |
| 1112 if (hdcp_loadkey() < 0) |
| 1113 return false; |
| 1114 |
| 1115 /* |
| 1116 * 3. set hdcp control reg. |
| 1117 * Disable advance cipher option, Enable CP(Content Protection), |
| 1118 * Disable time-out (This bit is only available in a REPEATER) |
| 1119 * Disable XOR shift,Disable Pj port update,Use external key |
| 1120 */ |
| 1121 sfr_val = 0; |
| 1122 sfr_val |= CP_DESIRED_EN; |
| 1123 writel(sfr_val, hdmi_base + S5P_HDCP_CTRL1); |
| 1124 |
| 1125 hdcp_info.hdcp_enable = true; |
| 1126 |
| 1127 HDCPPRINTK("\tSTATUS \t0x%08x\n", readl(hdmi_base + S5P_STATUS)); |
| 1128 HDCPPRINTK("\tSTATUS_EN \t0x%08x\n", |
| 1129 readl(hdmi_base + S5P_STATUS_EN)); |
| 1130 HDCPPRINTK("\tHPD \t0x%08x\n", readl(hdmi_base + S5P_HPD)); |
| 1131 HDCPPRINTK("\tHDCP_CTRL \t0x%08x\n", |
| 1132 readl(hdmi_base + S5P_HDCP_CTRL1)); |
| 1133 HDCPPRINTK("\tMODE_SEL \t0x%08x\n", |
| 1134 readl(hdmi_base + S5P_MODE_SEL)); |
| 1135 HDCPPRINTK("\tENC_EN \t0x%08x\n", readl(hdmi_base + S5P_ENC_EN)); |
| 1136 HDCPPRINTK("\tHDMI_CON_0 \t0x%08x\n", |
| 1137 readl(hdmi_base + S5P_HDMI_CON_0)); |
| 1138 |
| 1139 return true; |
| 1140 } |
| 1141 |
| 1142 static void bksv_start_bh(void) |
| 1143 { |
| 1144 bool ret = false; |
| 1145 |
| 1146 HDCPPRINTK("HDCP_EVENT_READ_BKSV_START bh\n"); |
| 1147 |
| 1148 hdcp_info.auth_status = RECEIVER_READ_READY; |
| 1149 |
| 1150 ret = read_bcaps(); |
| 1151 |
| 1152 if (!ret) { |
| 1153 |
| 1154 ret = try_read_receiver(); |
| 1155 |
| 1156 if (!ret) { |
| 1157 HDCPPRINTK("Can't read bcaps!! retry failed!!\n" |
| 1158 "\t\t\t\thdcp ftn. will be stopped\n"); |
| 1159 |
| 1160 tv_stop_hdcp(); |
| 1161 return; |
| 1162 } |
| 1163 } |
| 1164 |
| 1165 hdcp_info.auth_status = BCAPS_READ_DONE; |
| 1166 |
| 1167 ret = read_bksv(); |
| 1168 |
| 1169 if (!ret) { |
| 1170 HDCPPRINTK("Can't read bksv!!" |
| 1171 "hdcp ftn. will be reset\n"); |
| 1172 |
| 1173 tv_stop_hdcp(); |
| 1174 return; |
| 1175 } |
| 1176 |
| 1177 hdcp_info.auth_status = BKSV_READ_DONE; |
| 1178 |
| 1179 HDCPPRINTK("authentication status : bksv is done (0x%08x)\n", |
| 1180 hdcp_info.auth_status); |
| 1181 } |
| 1182 |
| 1183 static void second_auth_start_bh(void) |
| 1184 { |
| 1185 u8 count = 0; |
| 1186 bool ret = false; |
| 1187 |
| 1188 int ret_err; |
| 1189 |
| 1190 u32 bcaps; |
| 1191 |
| 1192 HDCPPRINTK("HDCP_EVENT_SECOND_AUTH_START bh\n"); |
| 1193 |
| 1194 ret = read_bcaps(); |
| 1195 |
| 1196 if (!ret) { |
| 1197 |
| 1198 ret = try_read_receiver(); |
| 1199 |
| 1200 if (!ret) { |
| 1201 |
| 1202 HDCPPRINTK("Can't read bcaps!! retry failed!!\n" |
| 1203 "\t\t\t\thdcp ftn. will be stopped\n"); |
| 1204 |
| 1205 tv_stop_hdcp(); |
| 1206 return; |
| 1207 } |
| 1208 |
| 1209 } |
| 1210 |
| 1211 bcaps = readl(hdmi_base + S5P_HDCP_BCAPS); |
| 1212 bcaps &= (KSV_FIFO_READY); |
| 1213 |
| 1214 if (!bcaps) { |
| 1215 |
| 1216 HDCPPRINTK("ksv fifo is not ready\n"); |
| 1217 |
| 1218 do { |
| 1219 count++; |
| 1220 |
| 1221 ret = read_bcaps(); |
| 1222 |
| 1223 if (!ret) { |
| 1224 |
| 1225 ret = try_read_receiver(); |
| 1226 |
| 1227 if (!ret) |
| 1228 tv_stop_hdcp(); |
| 1229 |
| 1230 return; |
| 1231 |
| 1232 } |
| 1233 |
| 1234 bcaps = readl(hdmi_base + S5P_HDCP_BCAPS); |
| 1235 bcaps &= (KSV_FIFO_READY); |
| 1236 |
| 1237 if (bcaps) { |
| 1238 HDCPPRINTK("bcaps retries : %d\n", count); |
| 1239 break; |
| 1240 } |
| 1241 |
| 1242 mdelay(100); |
| 1243 |
| 1244 if (!hdcp_info.hdcp_enable) { |
| 1245 |
| 1246 tv_stop_hdcp(); |
| 1247 |
| 1248 return; |
| 1249 |
| 1250 } |
| 1251 |
| 1252 } while (count <= 50); |
| 1253 |
| 1254 /* wait times exceeded 5 seconds */ |
| 1255 if (count > 50) { |
| 1256 |
| 1257 hdcp_info.time_out = INFINITE; |
| 1258 |
| 1259 /* time-out (This bit is only available in a REPEATER) */ |
| 1260 writel(readl(hdmi_base + S5P_HDCP_CTRL1) | 0x1 << 2, |
| 1261 hdmi_base + S5P_HDCP_CTRL1); |
| 1262 |
| 1263 reset_authentication(); |
| 1264 |
| 1265 return; |
| 1266 } |
| 1267 } |
| 1268 |
| 1269 HDCPPRINTK("ksv fifo ready\n"); |
| 1270 |
| 1271 ret_err = check_repeater(); |
| 1272 |
| 1273 if (ret_err == true) { |
| 1274 u32 flag; |
| 1275 |
| 1276 hdcp_info.auth_status = SECOND_AUTHENTICATION_DONE; |
| 1277 HDCPPRINTK("second authentication done!!\n"); |
| 1278 |
| 1279 flag = readb(hdmi_base + S5P_STATUS); |
| 1280 HDCPPRINTK("hdcp state : %s authenticated!!\n", |
| 1281 flag & AUTHENTICATED ? "" : "not not"); |
| 1282 |
| 1283 start_encryption(); |
| 1284 } else if (ret_err == false) { |
| 1285 /* i2c error */ |
| 1286 HDCPPRINTK("repeater check error!!\n"); |
| 1287 reset_authentication(); |
| 1288 } else { |
| 1289 if (ret_err == REPEATER_ILLEGAL_DEVICE_ERROR) { |
| 1290 /* |
| 1291 * No need to start the HDCP |
| 1292 * in case of invalid KSV (revocation case) |
| 1293 */ |
| 1294 HDCPPRINTK("illegal dev. error!!\n"); |
| 1295 |
| 1296 tv_stop_hdcp(); |
| 1297 } else { |
| 1298 /* |
| 1299 * MAX_CASCADE_EXCEEDED_ERROR |
| 1300 * MAX_DEVS_EXCEEDED_ERROR |
| 1301 */ |
| 1302 HDCPPRINTK("repeater check error(MAX_EXCEEDED)!!\n"); |
| 1303 reset_authentication(); |
| 1304 } |
| 1305 } |
| 1306 } |
| 1307 |
| 1308 static bool write_aksv_start_bh(void) |
| 1309 { |
| 1310 bool ret = false; |
| 1311 |
| 1312 HDCPPRINTK("HDCP_EVENT_WRITE_AKSV_START bh\n"); |
| 1313 |
| 1314 if (hdcp_info.auth_status != BKSV_READ_DONE) { |
| 1315 HDCPPRINTK("bksv is not ready!!\n"); |
| 1316 return false; |
| 1317 } |
| 1318 |
| 1319 ret = write_ainfo(); |
| 1320 if (!ret) |
| 1321 return false; |
| 1322 |
| 1323 HDCPPRINTK("ainfo write done!!\n"); |
| 1324 |
| 1325 ret = write_an(); |
| 1326 if (!ret) |
| 1327 return false; |
| 1328 |
| 1329 hdcp_info.auth_status = AN_WRITE_DONE; |
| 1330 |
| 1331 HDCPPRINTK("an write done!!\n"); |
| 1332 |
| 1333 ret = write_aksv(); |
| 1334 if (!ret) |
| 1335 return false; |
| 1336 |
| 1337 /* |
| 1338 * Wait for 100ms. Transmitter must not read |
| 1339 * Ro' value sooner than 100ms after writing |
| 1340 * Aksv |
| 1341 */ |
| 1342 mdelay(100); |
| 1343 |
| 1344 hdcp_info.auth_status = AKSV_WRITE_DONE; |
| 1345 |
| 1346 HDCPPRINTK("aksv write done!!\n"); |
| 1347 |
| 1348 return ret; |
| 1349 } |
| 1350 |
| 1351 static bool check_ri_start_bh(void) |
| 1352 { |
| 1353 bool ret = false; |
| 1354 |
| 1355 |
| 1356 HDCPPRINTK("HDCP_EVENT_CHECK_RI_START bh\n"); |
| 1357 |
| 1358 if (hdcp_info.auth_status == AKSV_WRITE_DONE || |
| 1359 hdcp_info.auth_status == FIRST_AUTHENTICATION_DONE || |
| 1360 hdcp_info.auth_status == SECOND_AUTHENTICATION_DONE) { |
| 1361 |
| 1362 ret = compare_r_val(); |
| 1363 |
| 1364 if (ret) { |
| 1365 |
| 1366 if (hdcp_info.auth_status == AKSV_WRITE_DONE) { |
| 1367 /* |
| 1368 * Check whether HDMI receiver is |
| 1369 * repeater or not |
| 1370 */ |
| 1371 if (hdcp_info.is_repeater) |
| 1372 hdcp_info.auth_status |
| 1373 = SECOND_AUTHENTICATION_RDY; |
| 1374 else { |
| 1375 hdcp_info.auth_status |
| 1376 = FIRST_AUTHENTICATION_DONE; |
| 1377 start_encryption(); |
| 1378 } |
| 1379 } |
| 1380 |
| 1381 } else { |
| 1382 |
| 1383 HDCPPRINTK("authentication reset\n"); |
| 1384 reset_authentication(); |
| 1385 |
| 1386 } |
| 1387 |
| 1388 HDCPPRINTK("auth_status = 0x%08x\n", |
| 1389 hdcp_info.auth_status); |
| 1390 |
| 1391 |
| 1392 return true; |
| 1393 } |
| 1394 |
| 1395 HDCPPRINTK("aksv_write or first/second" |
| 1396 " authentication is not done\n"); |
| 1397 |
| 1398 return false; |
| 1399 } |
| 1400 |
| 1401 /* |
| 1402 * bottom half for hdmi interrupt |
| 1403 * |
| 1404 */ |
| 1405 static void hdcp_work(void *arg) |
| 1406 { |
| 1407 /* HDCPPRINTK("event : 0x%08x \n\r", hdcp_info.event); */ |
| 1408 |
| 1409 /* |
| 1410 * I2C int. was occurred |
| 1411 * for reading Bksv and Bcaps |
| 1412 */ |
| 1413 |
| 1414 if (hdcp_info.event & (1 << HDCP_EVENT_READ_BKSV_START)) { |
| 1415 |
| 1416 bksv_start_bh(); |
| 1417 |
| 1418 /* clear event */ |
| 1419 /* spin_lock_bh(&hdcp_info.lock); */ |
| 1420 hdcp_info.event &= ~(1 << HDCP_EVENT_READ_BKSV_START); |
| 1421 /* spin_unlock_bh(&hdcp_info.lock); */ |
| 1422 } |
| 1423 |
| 1424 /* |
| 1425 * Watchdog timer int. was occurred |
| 1426 * for checking repeater |
| 1427 */ |
| 1428 if (hdcp_info.event & (1 << HDCP_EVENT_SECOND_AUTH_START)) { |
| 1429 |
| 1430 second_auth_start_bh(); |
| 1431 |
| 1432 /* clear event */ |
| 1433 /* spin_lock_bh(&hdcp_info.lock); */ |
| 1434 hdcp_info.event &= ~(1 << HDCP_EVENT_SECOND_AUTH_START); |
| 1435 /* spin_unlock_bh(&hdcp_info.lock); */ |
| 1436 } |
| 1437 |
| 1438 /* |
| 1439 * An_Write int. was occurred |
| 1440 * for writing Ainfo, An and Aksv |
| 1441 */ |
| 1442 if (hdcp_info.event & (1 << HDCP_EVENT_WRITE_AKSV_START)) { |
| 1443 |
| 1444 write_aksv_start_bh(); |
| 1445 |
| 1446 /* clear event */ |
| 1447 /* spin_lock_bh(&hdcp_info.lock); */ |
| 1448 hdcp_info.event &= ~(1 << HDCP_EVENT_WRITE_AKSV_START); |
| 1449 /* spin_unlock_bh(&hdcp_info.lock); */ |
| 1450 } |
| 1451 |
| 1452 /* |
| 1453 * Ri int. was occurred |
| 1454 * for comparing Ri and Ri'(from HDMI sink) |
| 1455 */ |
| 1456 if (hdcp_info.event & (1 << HDCP_EVENT_CHECK_RI_START)) { |
| 1457 |
| 1458 |
| 1459 check_ri_start_bh(); |
| 1460 |
| 1461 /* clear event */ |
| 1462 /* spin_lock_bh(&hdcp_info.lock); */ |
| 1463 hdcp_info.event &= ~(1 << HDCP_EVENT_CHECK_RI_START); |
| 1464 /* spin_unlock_bh(&hdcp_info.lock); */ |
| 1465 } |
| 1466 |
| 1467 } |
| 1468 |
| 1469 irqreturn_t tv_hdcp_irq_handler(int irq, void *dev_id) |
| 1470 { |
| 1471 u32 event = 0; |
| 1472 u8 flag; |
| 1473 |
| 1474 event = 0; |
| 1475 /* check HDCP Status */ |
| 1476 flag = readb(hdmi_base + S5P_STATUS); |
| 1477 |
| 1478 HDCPPRINTK("irq_status : 0x%08x\n", readb(hdmi_base + S5P_STATUS)); |
| 1479 |
| 1480 HDCPPRINTK("hdcp state : %s authenticated!!\n", |
| 1481 flag & AUTHENTICATED ? "" : "not"); |
| 1482 |
| 1483 spin_lock_irq(&hdcp_info.lock); |
| 1484 |
| 1485 /* |
| 1486 * processing interrupt |
| 1487 * interrupt processing seq. is firstly set event for workqueue, |
| 1488 * and interrupt pending clear. 'flag|' was used for preventing |
| 1489 * to clear AUTHEN_ACK.- it caused many problem. be careful. |
| 1490 */ |
| 1491 /* I2C INT */ |
| 1492 if (flag & WTFORACTIVERX_INT_OCCURRED) { |
| 1493 event |= (1 << HDCP_EVENT_READ_BKSV_START); |
| 1494 writeb(flag | WTFORACTIVERX_INT_OCCURRED, |
| 1495 hdmi_base + S5P_STATUS); |
| 1496 writeb(0x0, hdmi_base + S5P_HDCP_I2C_INT); |
| 1497 } |
| 1498 |
| 1499 /* AN INT */ |
| 1500 if (flag & EXCHANGEKSV_INT_OCCURRED) { |
| 1501 event |= (1 << HDCP_EVENT_WRITE_AKSV_START); |
| 1502 writeb(flag | EXCHANGEKSV_INT_OCCURRED, |
| 1503 hdmi_base + S5P_STATUS); |
| 1504 writeb(0x0, hdmi_base + S5P_HDCP_AN_INT); |
| 1505 } |
| 1506 |
| 1507 /* RI INT */ |
| 1508 if (flag & UPDATE_RI_INT_OCCURRED) { |
| 1509 event |= (1 << HDCP_EVENT_CHECK_RI_START); |
| 1510 writeb(flag | UPDATE_RI_INT_OCCURRED, |
| 1511 hdmi_base + S5P_STATUS); |
| 1512 writeb(0x0, hdmi_base + S5P_HDCP_RI_INT); |
| 1513 } |
| 1514 |
| 1515 /* WATCHDOG INT */ |
| 1516 if (flag & WATCHDOG_INT_OCCURRED) { |
| 1517 event |= (1 << HDCP_EVENT_SECOND_AUTH_START); |
| 1518 writeb(flag | WATCHDOG_INT_OCCURRED, |
| 1519 hdmi_base + S5P_STATUS); |
| 1520 writeb(0x0, hdmi_base + S5P_HDCP_WDT_INT); |
| 1521 } |
| 1522 |
| 1523 if (!event) { |
| 1524 HDCPPRINTK("unknown irq.\n"); |
| 1525 return IRQ_HANDLED; |
| 1526 } |
| 1527 |
| 1528 hdcp_info.event |= event; |
| 1529 |
| 1530 schedule_work(&hdcp_info.work); |
| 1531 |
| 1532 spin_unlock_irq(&hdcp_info.lock); |
| 1533 |
| 1534 return IRQ_HANDLED; |
| 1535 } |
| 1536 |
| 1537 bool tv_set_hpd_detection(bool detection, bool hdcp_enabled, |
| 1538 struct i2c_client *client) |
| 1539 { |
| 1540 u32 hpd_reg_val = 0; |
| 1541 |
| 1542 if (detection) |
| 1543 hpd_reg_val = CABLE_PLUGGED; |
| 1544 else |
| 1545 hpd_reg_val = CABLE_UNPLUGGED; |
| 1546 |
| 1547 writel(hpd_reg_val, hdmi_base + S5P_HPD); |
| 1548 |
| 1549 HDCPPRINTK("HPD status :: 0x%08x\n\r", |
| 1550 readl(hdmi_base + S5P_HPD)); |
| 1551 |
| 1552 return true; |
| 1553 } |
| 1554 |
| 1555 int tv_hdcp_init(void) |
| 1556 { |
| 1557 /* for bh */ |
| 1558 INIT_WORK(&hdcp_info.work, (work_func_t)hdcp_work); |
| 1559 |
| 1560 init_waitqueue_head(&hdcp_info.waitq); |
| 1561 |
| 1562 /* for dev_dbg err. */ |
| 1563 spin_lock_init(&hdcp_info.lock); |
| 1564 |
| 1565 s5p_hdmi_register_isr((hdmi_isr)tv_hdcp_irq_handler, |
| 1566 (u8)HDMI_IRQ_HDCP); |
| 1567 |
| 1568 return 0; |
| 1569 } |
OLD | NEW |