1 /* linux/drivers/media/video/samsung/tvout/hw_if/hdcp.c
3 * Copyright (c) 2009 Samsung Electronics
4 * http://www.samsung.com/
6 * HDCP function for Samsung TVOUT driver
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.
12 #include <linux/i2c.h>
14 #include <linux/delay.h>
16 #include <mach/regs-hdmi.h>
19 #include "../s5p_tvout_common_lib.h"
23 #ifdef CONFIG_HDCP_DEBUG
24 #define tvout_dbg(fmt, ...) \
25 printk(KERN_INFO "\t\t[HDCP] %s(): " fmt, \
26 __func__, ##__VA_ARGS__)
28 #define tvout_dbg(fmt, ...)
36 #define BKSV_RETRY_CNT 14
37 #define BKSV_DELAY 100
39 #define DDC_RETRY_CNT 400000
42 #define KEY_LOAD_RETRY_CNT 1000
43 #define ENCRYPT_CHECK_CNT 10
45 #define KSV_FIFO_RETRY_CNT 50
46 #define KSV_FIFO_CHK_DELAY 100 /* ms */
47 #define KSV_LIST_RETRY_CNT 10000
48 #define SHA_1_RETRY_CNT 4
51 #define BSTATUS_SIZE 2
52 #define SHA_1_HASH_SIZE 20
53 #define HDCP_MAX_DEVS 128
54 #define HDCP_KSV_SIZE 5
56 #define HDCP_Bksv 0x00
58 #define HDCP_Aksv 0x10
59 #define HDCP_Ainfo 0x15
61 #define HDCP_SHA1 0x20
62 #define HDCP_Bcaps 0x40
63 #define HDCP_BStatus 0x41
64 #define HDCP_KSVFIFO 0x43
66 #define KSV_FIFO_READY (0x1 << 5)
68 #define MAX_CASCADE_EXCEEDED_ERROR (-2)
69 #define MAX_DEVS_EXCEEDED_ERROR (-3)
70 #define REPEATER_ILLEGAL_DEVICE_ERROR (-4)
71 #define REPEATER_TIMEOUT_ERROR (-5)
73 #define MAX_CASCADE_EXCEEDED (0x1 << 3)
74 #define MAX_DEVS_EXCEEDED (0x1 << 7)
77 #define DDC_BUF_SIZE 32
80 HDCP_EVENT_STOP = 1 << 0,
81 HDCP_EVENT_START = 1 << 1,
82 HDCP_EVENT_READ_BKSV_START = 1 << 2,
83 HDCP_EVENT_WRITE_AKSV_START = 1 << 4,
84 HDCP_EVENT_CHECK_RI_START = 1 << 8,
85 HDCP_EVENT_SECOND_AUTH_START = 1 << 16
95 FIRST_AUTHENTICATION_DONE,
96 SECOND_AUTHENTICATION_RDY,
97 SECOND_AUTHENTICATION_DONE,
100 struct s5p_hdcp_info {
104 spinlock_t reset_lock;
106 enum hdcp_event event;
107 enum hdcp_state auth_status;
109 struct work_struct work;
112 struct i2c_client *ddc_port;
114 static bool sw_reset;
116 static struct s5p_hdcp_info hdcp_info = {
117 .is_repeater = false,
118 .hdcp_enable = false,
119 .event = HDCP_EVENT_STOP,
120 .auth_status = NOT_AUTHENTICATED,
123 /* start: external functions for HDMI */
124 extern void __iomem *hdmi_base;
126 /* end: external functions for HDMI */
129 static int s5p_ddc_read(u8 reg, int bytes, u8 *dest)
131 struct i2c_client *i2c = ddc_port;
135 struct i2c_msg msg[] = {
151 if (!s5p_hdmi_reg_get_hpd_status())
154 ret = i2c_transfer(i2c->adapter, msg, 2);
156 if (ret < 0 || ret != 2)
157 tvout_dbg("ddc : can't read data, retry %d\n", cnt);
161 if (hdcp_info.auth_status == FIRST_AUTHENTICATION_DONE
162 || hdcp_info.auth_status == SECOND_AUTHENTICATION_DONE)
167 } while (cnt < DDC_RETRY_CNT);
169 if (cnt == DDC_RETRY_CNT)
172 tvout_dbg("ddc : read data ok\n");
176 tvout_err("ddc : can't read data, timeout\n");
180 static int s5p_ddc_write(u8 reg, int bytes, u8 *src)
182 struct i2c_client *i2c = ddc_port;
187 memcpy(&msg[1], src, bytes);
190 if (!s5p_hdmi_reg_get_hpd_status())
193 ret = i2c_master_send(i2c, msg, bytes + 1);
195 if (ret < 0 || ret < bytes + 1)
196 tvout_dbg("ddc : can't write data, retry %d\n", cnt);
202 } while (cnt < DDC_RETRY_CNT);
204 if (cnt == DDC_RETRY_CNT)
207 tvout_dbg("ddc : write data ok\n");
210 tvout_err("ddc : can't write data, timeout\n");
214 static int __devinit s5p_ddc_probe(struct i2c_client *client,
215 const struct i2c_device_id *dev_id)
221 dev_info(&client->adapter->dev, "attached s5p_ddc "
222 "into i2c adapter successfully\n");
227 static int s5p_ddc_remove(struct i2c_client *client)
229 dev_info(&client->adapter->dev, "detached s5p_ddc "
230 "from i2c adapter successfully\n");
235 static int s5p_ddc_suspend(struct i2c_client *cl, pm_message_t mesg)
240 static int s5p_ddc_resume(struct i2c_client *cl)
245 static struct i2c_device_id ddc_idtable[] = {
248 MODULE_DEVICE_TABLE(i2c, ddc_idtable);
250 static struct i2c_driver ddc_driver = {
253 .owner = THIS_MODULE,
255 .id_table = ddc_idtable,
256 .probe = s5p_ddc_probe,
257 .remove = __devexit_p(s5p_ddc_remove),
258 .suspend = s5p_ddc_suspend,
259 .resume = s5p_ddc_resume,
262 static int __init s5p_ddc_init(void)
264 return i2c_add_driver(&ddc_driver);
267 static void __exit s5p_ddc_exit(void)
269 i2c_del_driver(&ddc_driver);
273 module_init(s5p_ddc_init);
274 module_exit(s5p_ddc_exit);
277 static int s5p_hdcp_encryption(bool on)
282 reg = S5P_HDMI_HDCP_ENC_ENABLE;
284 reg = S5P_HDMI_HDCP_ENC_DISABLE;
286 writeb(reg, hdmi_base + S5P_HDMI_ENC_EN);
287 s5p_hdmi_reg_mute(!on);
292 static int s5p_hdcp_write_key(int sz, int reg, int type)
294 u8 buff[MAX_KEY_SZ] = {0,};
295 int cnt = 0, zero = 0;
297 hdmi_read_l(buff, hdmi_base, reg, sz);
299 for (cnt = 0; cnt < sz; cnt++)
304 tvout_dbg("%s : null\n", type == HDCP_An ? "an" : "aksv");
308 if (s5p_ddc_write(type, sz, buff) < 0)
311 #ifdef CONFIG_HDCP_DEBUG
315 for (i = 1; i < sz + 1; i++)
316 tvout_dbg("%s[%d] : 0x%02x\n",
317 type == HDCP_An ? "an" : "aksv", i, buff[i]);
323 tvout_err("write %s : failed\n", type == HDCP_An ? "an" : "aksv");
327 static int s5p_hdcp_read_bcaps(void)
331 if (s5p_ddc_read(HDCP_Bcaps, BCAPS_SIZE, &bcaps) < 0)
334 writeb(bcaps, hdmi_base + S5P_HDMI_HDCP_BCAPS);
336 if (bcaps & S5P_HDMI_HDCP_BCAPS_REPEATER)
337 hdcp_info.is_repeater = 1;
339 hdcp_info.is_repeater = 0;
341 tvout_dbg("device : %s\n", hdcp_info.is_repeater ? "REPEAT" : "SINK");
342 tvout_dbg("[i2c] bcaps : 0x%02x\n", bcaps);
343 tvout_dbg("[sfr] bcaps : 0x%02x\n",
344 readb(hdmi_base + S5P_HDMI_HDCP_BCAPS));
349 tvout_err("can't read bcaps : timeout\n");
353 static int s5p_hdcp_read_bksv(void)
355 u8 bksv[BKSV_SZ] = {0, };
357 u32 one = 0, zero = 0, res = 0;
361 if (s5p_ddc_read(HDCP_Bksv, BKSV_SZ, bksv) < 0)
364 #ifdef CONFIG_HDCP_DEBUG
365 for (i = 0; i < BKSV_SZ; i++)
366 tvout_dbg("i2c read : bksv[%d]: 0x%x\n", i, bksv[i]);
369 for (i = 0; i < BKSV_SZ; i++) {
371 for (j = 0; j < 8; j++) {
372 res = bksv[i] & (0x1 << j);
382 if ((zero == 20) && (one == 20)) {
383 hdmi_write_l(bksv, hdmi_base,
384 S5P_HDMI_HDCP_BKSV_0_0, BKSV_SZ);
387 tvout_dbg("invalid bksv, retry : %d\n", cnt);
391 } while (cnt < BKSV_RETRY_CNT);
393 if (cnt == BKSV_RETRY_CNT)
396 tvout_dbg("bksv read OK, retry : %d\n", cnt);
400 tvout_err("can't read bksv : timeout\n");
404 static int s5p_hdcp_read_ri(void)
409 ri[0] = readb(hdmi_base + S5P_HDMI_HDCP_Ri_0);
410 ri[1] = readb(hdmi_base + S5P_HDMI_HDCP_Ri_1);
412 if (s5p_ddc_read(HDCP_Ri, 2, rj) < 0)
415 tvout_dbg("Rx(ddc) -> rj[0]: 0x%02x, rj[1]: 0x%02x\n",
417 tvout_dbg("Tx(register) -> ri[0]: 0x%02x, ri[1]: 0x%02x\n",
420 if ((ri[0] == rj[0]) && (ri[1] == rj[1]) && (ri[0] | ri[1]))
421 writeb(S5P_HDMI_HDCP_Ri_MATCH_RESULT_Y,
422 hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
424 writeb(S5P_HDMI_HDCP_Ri_MATCH_RESULT_N,
425 hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
434 tvout_dbg("ri, ri' : matched\n");
438 hdcp_info.event = HDCP_EVENT_STOP;
439 hdcp_info.auth_status = NOT_AUTHENTICATED;
440 tvout_err("read ri : failed - missmatch\n");
445 static void s5p_hdcp_reset_sw(void)
450 reg = s5p_hdmi_reg_intc_get_enabled();
452 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0);
453 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0);
455 s5p_hdmi_reg_sw_hpd_enable(true);
456 s5p_hdmi_reg_set_hpd_onoff(false);
457 s5p_hdmi_reg_set_hpd_onoff(true);
458 s5p_hdmi_reg_sw_hpd_enable(false);
460 if (reg & 1<<HDMI_IRQ_HPD_PLUG)
461 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 1);
462 if (reg & 1<<HDMI_IRQ_HPD_UNPLUG)
463 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 1);
468 static void s5p_hdcp_reset_auth(void)
472 spin_lock_irq(&hdcp_info.reset_lock);
474 hdcp_info.event = HDCP_EVENT_STOP;
475 hdcp_info.auth_status = NOT_AUTHENTICATED;
477 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL1);
478 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL2);
479 s5p_hdmi_reg_mute(true);
481 s5p_hdcp_encryption(false);
483 tvout_err("reset authentication\n");
485 reg = readb(hdmi_base + S5P_HDMI_STATUS_EN);
486 reg &= S5P_HDMI_INT_DIS_ALL;
487 writeb(reg, hdmi_base + S5P_HDMI_STATUS_EN);
489 writeb(S5P_HDMI_HDCP_CLR_ALL_RESULTS,
490 hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
492 /* need some delay (at least 1 frame) */
497 reg = readb(hdmi_base + S5P_HDMI_STATUS_EN);
498 reg |= S5P_HDMI_WTFORACTIVERX_INT_OCC |
499 S5P_HDMI_WATCHDOG_INT_OCC |
500 S5P_HDMI_WRITE_INT_OCC |
501 S5P_HDMI_UPDATE_RI_INT_OCC;
502 writeb(reg, hdmi_base + S5P_HDMI_STATUS_EN);
503 writeb(S5P_HDMI_HDCP_CP_DESIRED_EN, hdmi_base + S5P_HDMI_HDCP_CTRL1);
505 spin_unlock_irq(&hdcp_info.reset_lock);
508 static int s5p_hdcp_loadkey(void)
513 writeb(S5P_HDMI_EFUSE_CTRL_HDCP_KEY_READ,
514 hdmi_base + S5P_HDMI_EFUSE_CTRL);
517 reg = readb(hdmi_base + S5P_HDMI_EFUSE_STATUS);
518 if (reg & S5P_HDMI_EFUSE_ECC_DONE)
522 } while (cnt < KEY_LOAD_RETRY_CNT);
524 if (cnt == KEY_LOAD_RETRY_CNT)
527 reg = readb(hdmi_base + S5P_HDMI_EFUSE_STATUS);
529 if (reg & S5P_HDMI_EFUSE_ECC_FAIL)
532 tvout_dbg("load key : OK\n");
535 tvout_err("can't load key\n");
539 static int s5p_hdmi_start_encryption(void)
545 reg = readb(hdmi_base + S5P_HDMI_SYS_STATUS);
547 if (reg & S5P_HDMI_AUTHEN_ACK_AUTH) {
548 s5p_hdcp_encryption(true);
555 } while (cnt < ENCRYPT_CHECK_CNT);
557 if (cnt == ENCRYPT_CHECK_CNT)
561 tvout_dbg("encrypt : start\n");
565 s5p_hdcp_encryption(false);
566 tvout_err("encrypt : failed\n");
570 static int s5p_hdmi_check_repeater(void)
573 int cnt = 0, cnt2 = 0;
576 u8 status[BSTATUS_SIZE] = {0, 0};
577 u8 rx_v[SHA_1_HASH_SIZE] = {0};
578 u8 ksv_list[HDCP_MAX_DEVS * HDCP_KSV_SIZE] = {0};
582 memset(rx_v, 0x0, SHA_1_HASH_SIZE);
583 memset(ksv_list, 0x0, HDCP_MAX_DEVS * HDCP_KSV_SIZE);
586 if (s5p_hdcp_read_bcaps() < 0)
587 goto check_repeater_err;
589 bcaps = readb(hdmi_base + S5P_HDMI_HDCP_BCAPS);
591 if (bcaps & KSV_FIFO_READY) {
592 tvout_dbg("repeater : ksv fifo not ready");
593 tvout_dbg(", retries : %d\n", cnt);
597 msleep(KSV_FIFO_CHK_DELAY);
600 } while (cnt < KSV_FIFO_RETRY_CNT);
602 if (cnt == KSV_FIFO_RETRY_CNT)
603 return REPEATER_TIMEOUT_ERROR;
605 tvout_dbg("repeater : ksv fifo ready\n");
608 if (s5p_ddc_read(HDCP_BStatus, BSTATUS_SIZE, status) < 0)
609 goto check_repeater_err;
611 if (status[1] & MAX_CASCADE_EXCEEDED)
612 return MAX_CASCADE_EXCEEDED_ERROR;
613 else if (status[0] & MAX_DEVS_EXCEEDED)
614 return MAX_DEVS_EXCEEDED_ERROR;
616 writeb(status[0], hdmi_base + S5P_HDMI_HDCP_BSTATUS_0);
617 writeb(status[1], hdmi_base + S5P_HDMI_HDCP_BSTATUS_1);
619 tvout_dbg("status[0] :0x%02x\n", status[0]);
620 tvout_dbg("status[1] :0x%02x\n", status[1]);
622 dev_cnt = status[0] & 0x7f;
624 tvout_dbg("repeater : dev cnt = %d\n", dev_cnt);
628 if (s5p_ddc_read(HDCP_KSVFIFO, dev_cnt * HDCP_KSV_SIZE,
630 goto check_repeater_err;
635 hdmi_write_l(&ksv_list[cnt*5], hdmi_base,
636 S5P_HDMI_HDCP_RX_KSV_0_0, HDCP_KSV_SIZE);
638 reg = S5P_HDMI_HDCP_KSV_WRITE_DONE;
640 if (cnt == dev_cnt - 1)
641 reg |= S5P_HDMI_HDCP_KSV_END;
643 writeb(reg, hdmi_base + S5P_HDMI_HDCP_KSV_LIST_CON);
645 if (cnt < dev_cnt - 1) {
648 reg = readb(hdmi_base
649 + S5P_HDMI_HDCP_KSV_LIST_CON);
651 if (reg & S5P_HDMI_HDCP_KSV_READ)
654 } while (cnt2 < KSV_LIST_RETRY_CNT);
656 if (cnt2 == KSV_LIST_RETRY_CNT)
657 tvout_dbg("ksv list not readed\n");
660 } while (cnt < dev_cnt);
662 writeb(S5P_HDMI_HDCP_KSV_LIST_EMPTY,
663 hdmi_base + S5P_HDMI_HDCP_KSV_LIST_CON);
666 if (s5p_ddc_read(HDCP_SHA1, SHA_1_HASH_SIZE, rx_v) < 0)
667 goto check_repeater_err;
669 #ifdef S5P_HDCP_DEBUG
670 for (i = 0; i < SHA_1_HASH_SIZE; i++)
671 tvout_dbg("[i2c] SHA-1 rx :: %02x\n", rx_v[i]);
674 hdmi_write_l(rx_v, hdmi_base, S5P_HDMI_HDCP_RX_SHA1_0_0,
677 reg = readb(hdmi_base + S5P_HDMI_HDCP_SHA_RESULT);
678 if (reg & S5P_HDMI_HDCP_SHA_VALID_RD) {
679 if (reg & S5P_HDMI_HDCP_SHA_VALID) {
680 tvout_dbg("SHA-1 result : OK\n");
681 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_SHA_RESULT);
683 tvout_dbg("SHA-1 result : not vaild\n");
684 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_SHA_RESULT);
685 goto check_repeater_err;
688 tvout_dbg("SHA-1 result : not ready\n");
689 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_SHA_RESULT);
690 goto check_repeater_err;
693 tvout_dbg("check repeater : OK\n");
696 tvout_err("check repeater : failed\n");
700 int s5p_hdcp_stop(void)
704 tvout_dbg("HDCP ftn. Stop!!\n");
706 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HDCP, 0);
708 hdcp_info.event = HDCP_EVENT_STOP;
709 hdcp_info.auth_status = NOT_AUTHENTICATED;
710 hdcp_info.hdcp_enable = false;
712 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL1);
714 s5p_hdmi_reg_sw_hpd_enable(false);
716 sfr_val = readb(hdmi_base + S5P_HDMI_STATUS_EN);
717 sfr_val &= S5P_HDMI_INT_DIS_ALL;
718 writeb(sfr_val, hdmi_base + S5P_HDMI_STATUS_EN);
720 sfr_val = readb(hdmi_base + S5P_HDMI_SYS_STATUS);
721 sfr_val |= S5P_HDMI_INT_EN_ALL;
722 writeb(sfr_val, hdmi_base + S5P_HDMI_SYS_STATUS);
724 tvout_dbg("Stop Encryption by Stop!!\n");
725 s5p_hdcp_encryption(false);
727 writeb(S5P_HDMI_HDCP_Ri_MATCH_RESULT_N,
728 hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
729 writeb(S5P_HDMI_HDCP_CLR_ALL_RESULTS,
730 hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
735 int s5p_hdcp_start(void)
739 hdcp_info.event = HDCP_EVENT_STOP;
740 hdcp_info.auth_status = NOT_AUTHENTICATED;
742 tvout_dbg("HDCP ftn. Start\n");
746 tvout_dbg("Stop Encryption by Start\n");
748 s5p_hdcp_encryption(false);
750 if (s5p_hdcp_loadkey() < 0)
753 writeb(S5P_HDMI_GCP_CON_NO_TRAN, hdmi_base + S5P_HDMI_GCP_CON);
754 writeb(S5P_HDMI_INT_EN_ALL, hdmi_base + S5P_HDMI_STATUS_EN);
756 sfr_val = S5P_HDMI_HDCP_CP_DESIRED_EN;
757 writeb(sfr_val, hdmi_base + S5P_HDMI_HDCP_CTRL1);
759 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HDCP, 1);
761 hdcp_info.hdcp_enable = 1;
766 static int s5p_hdcp_bksv(void)
768 tvout_dbg("bksv start : start\n");
770 hdcp_info.auth_status = RECEIVER_READ_READY;
772 if (s5p_hdcp_read_bcaps() < 0)
775 hdcp_info.auth_status = BCAPS_READ_DONE;
777 if (s5p_hdcp_read_bksv() < 0)
780 hdcp_info.auth_status = BKSV_READ_DONE;
782 tvout_dbg("bksv start : OK\n");
787 tvout_err("bksv start : failed\n");
792 static int s5p_hdcp_second_auth(void)
794 int reg = 0, ret = 0;
796 tvout_dbg("second auth : start\n");
798 if (!hdcp_info.hdcp_enable)
799 goto second_auth_err;
801 ret = s5p_hdmi_check_repeater();
804 hdcp_info.auth_status = SECOND_AUTHENTICATION_DONE;
805 s5p_hdmi_start_encryption();
807 goto second_auth_err;
811 case REPEATER_ILLEGAL_DEVICE_ERROR:
812 writeb(0x01, hdmi_base + S5P_HDMI_HDCP_CTRL2);
814 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL2);
816 tvout_dbg("repeater : illegal device\n");
818 case REPEATER_TIMEOUT_ERROR:
819 reg = readb(hdmi_base + S5P_HDMI_HDCP_CTRL1);
821 reg |= S5P_HDMI_HDCP_SET_REPEATER_TIMEOUT;
822 writeb(reg, hdmi_base + S5P_HDMI_HDCP_CTRL1);
824 reg &= ~S5P_HDMI_HDCP_SET_REPEATER_TIMEOUT;
825 writeb(reg, hdmi_base + S5P_HDMI_HDCP_CTRL1);
827 tvout_dbg("repeater : timeout\n");
829 case MAX_CASCADE_EXCEEDED_ERROR:
831 tvout_dbg("repeater : exceeded MAX_CASCADE\n");
833 case MAX_DEVS_EXCEEDED_ERROR:
835 tvout_dbg("repeater : exceeded MAX_DEVS\n");
841 hdcp_info.auth_status = NOT_AUTHENTICATED;
843 goto second_auth_err;
847 tvout_dbg("second auth : OK\n");
851 tvout_err("second auth : failed\n");
855 static int s5p_hdcp_write_aksv(void)
857 tvout_dbg("aksv start : start\n");
859 if (hdcp_info.auth_status != BKSV_READ_DONE) {
860 tvout_dbg("aksv start : bksv is not ready\n");
864 if (s5p_hdcp_write_key(AN_SZ, S5P_HDMI_HDCP_An_0_0, HDCP_An) < 0)
867 hdcp_info.auth_status = AN_WRITE_DONE;
869 tvout_dbg("write an : done\n");
871 if (s5p_hdcp_write_key(AKSV_SZ, S5P_HDMI_HDCP_AKSV_0_0, HDCP_Aksv) < 0)
876 hdcp_info.auth_status = AKSV_WRITE_DONE;
878 tvout_dbg("write aksv : done\n");
879 tvout_dbg("aksv start : OK\n");
883 tvout_err("aksv start : failed\n");
887 static int s5p_hdcp_check_ri(void)
889 tvout_dbg("ri check : start\n");
891 if (hdcp_info.auth_status < AKSV_WRITE_DONE) {
892 tvout_dbg("ri check : not ready\n");
896 if (s5p_hdcp_read_ri() < 0)
899 if (hdcp_info.is_repeater)
900 hdcp_info.auth_status
901 = SECOND_AUTHENTICATION_RDY;
903 hdcp_info.auth_status
904 = FIRST_AUTHENTICATION_DONE;
905 s5p_hdmi_start_encryption();
908 tvout_dbg("ri check : OK\n");
912 tvout_err("ri check : failed\n");
916 static void s5p_hdcp_work(void *arg)
918 if (hdcp_info.event & HDCP_EVENT_READ_BKSV_START) {
919 if (s5p_hdcp_bksv() < 0)
922 hdcp_info.event &= ~HDCP_EVENT_READ_BKSV_START;
925 if (hdcp_info.event & HDCP_EVENT_SECOND_AUTH_START) {
926 if (s5p_hdcp_second_auth() < 0)
929 hdcp_info.event &= ~HDCP_EVENT_SECOND_AUTH_START;
932 if (hdcp_info.event & HDCP_EVENT_WRITE_AKSV_START) {
933 if (s5p_hdcp_write_aksv() < 0)
936 hdcp_info.event &= ~HDCP_EVENT_WRITE_AKSV_START;
939 if (hdcp_info.event & HDCP_EVENT_CHECK_RI_START) {
940 if (s5p_hdcp_check_ri() < 0)
943 hdcp_info.event &= ~HDCP_EVENT_CHECK_RI_START;
947 s5p_hdcp_reset_auth();
950 irqreturn_t s5p_hdcp_irq_handler(int irq, void *dev_id)
957 flag = readb(hdmi_base + S5P_HDMI_SYS_STATUS);
959 if (flag & S5P_HDMI_WTFORACTIVERX_INT_OCC) {
960 event |= HDCP_EVENT_READ_BKSV_START;
961 writeb(flag | S5P_HDMI_WTFORACTIVERX_INT_OCC,
962 hdmi_base + S5P_HDMI_SYS_STATUS);
963 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_I2C_INT);
966 if (flag & S5P_HDMI_WRITE_INT_OCC) {
967 event |= HDCP_EVENT_WRITE_AKSV_START;
968 writeb(flag | S5P_HDMI_WRITE_INT_OCC,
969 hdmi_base + S5P_HDMI_SYS_STATUS);
970 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_AN_INT);
973 if (flag & S5P_HDMI_UPDATE_RI_INT_OCC) {
974 event |= HDCP_EVENT_CHECK_RI_START;
975 writeb(flag | S5P_HDMI_UPDATE_RI_INT_OCC,
976 hdmi_base + S5P_HDMI_SYS_STATUS);
977 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_RI_INT);
980 if (flag & S5P_HDMI_WATCHDOG_INT_OCC) {
981 event |= HDCP_EVENT_SECOND_AUTH_START;
982 writeb(flag | S5P_HDMI_WATCHDOG_INT_OCC,
983 hdmi_base + S5P_HDMI_SYS_STATUS);
984 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_WDT_INT);
988 tvout_dbg("unknown irq\n");
992 hdcp_info.event |= event;
993 schedule_work(&hdcp_info.work);
998 int s5p_hdcp_init(void)
1000 INIT_WORK(&hdcp_info.work, (work_func_t) s5p_hdcp_work);
1002 spin_lock_init(&hdcp_info.reset_lock);
1004 s5p_hdmi_reg_intc_set_isr(s5p_hdcp_irq_handler,
1005 (u8) HDMI_IRQ_HDCP);
1010 int s5p_hdcp_encrypt_stop(bool on)
1014 spin_lock_irq(&hdcp_info.reset_lock);
1016 if (hdcp_info.hdcp_enable) {
1017 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_I2C_INT);
1018 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_AN_INT);
1019 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_RI_INT);
1020 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_WDT_INT);
1022 s5p_hdcp_encryption(false);
1025 reg = readb(hdmi_base + S5P_HDMI_HDCP_CTRL1);
1028 writeb(reg | S5P_HDMI_HDCP_CP_DESIRED_EN,
1029 hdmi_base + S5P_HDMI_HDCP_CTRL1);
1030 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HDCP, 1);
1032 hdcp_info.event = HDCP_EVENT_STOP;
1033 hdcp_info.auth_status = NOT_AUTHENTICATED;
1035 writeb(reg & ~S5P_HDMI_HDCP_CP_DESIRED_EN,
1036 hdmi_base + S5P_HDMI_HDCP_CTRL1);
1037 s5p_hdmi_reg_intc_enable(HDMI_IRQ_HDCP, 0);
1041 tvout_dbg("stop encryption by HPD\n");
1044 spin_unlock_irq(&hdcp_info.reset_lock);