upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / samsung / tvout / hw_if / hdcp.c
1 /* linux/drivers/media/video/samsung/tvout/hw_if/hdcp.c
2  *
3  * Copyright (c) 2009 Samsung Electronics
4  *              http://www.samsung.com/
5  *
6  * HDCP function 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 #include <linux/i2c.h>
13 #include <linux/io.h>
14 #include <linux/delay.h>
15
16 #include <mach/regs-hdmi.h>
17
18 #include "hw_if.h"
19 #include "../s5p_tvout_common_lib.h"
20
21 #undef tvout_dbg
22
23 #ifdef CONFIG_HDCP_DEBUG
24 #define tvout_dbg(fmt, ...)                                     \
25                 printk(KERN_INFO "\t\t[HDCP] %s(): " fmt,       \
26                         __func__, ##__VA_ARGS__)
27 #else
28 #define tvout_dbg(fmt, ...)
29 #endif
30
31 #define AN_SZ                   8
32 #define AKSV_SZ                 5
33 #define BKSV_SZ                 5
34 #define MAX_KEY_SZ              16
35
36 #define BKSV_RETRY_CNT          14
37 #define BKSV_DELAY              100
38
39 #define DDC_RETRY_CNT           400000
40 #define DDC_DELAY               25
41
42 #define KEY_LOAD_RETRY_CNT      1000
43 #define ENCRYPT_CHECK_CNT       10
44
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
49
50 #define BCAPS_SIZE              1
51 #define BSTATUS_SIZE            2
52 #define SHA_1_HASH_SIZE         20
53 #define HDCP_MAX_DEVS           128
54 #define HDCP_KSV_SIZE           5
55
56 #define HDCP_Bksv               0x00
57 #define HDCP_Ri                 0x08
58 #define HDCP_Aksv               0x10
59 #define HDCP_Ainfo              0x15
60 #define HDCP_An                 0x18
61 #define HDCP_SHA1               0x20
62 #define HDCP_Bcaps              0x40
63 #define HDCP_BStatus            0x41
64 #define HDCP_KSVFIFO            0x43
65
66 #define KSV_FIFO_READY                  (0x1 << 5)
67
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)
72
73 #define MAX_CASCADE_EXCEEDED            (0x1 << 3)
74 #define MAX_DEVS_EXCEEDED               (0x1 << 7)
75
76
77 #define DDC_BUF_SIZE            32
78
79 enum hdcp_event {
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
86 };
87
88 enum hdcp_state {
89         NOT_AUTHENTICATED,
90         RECEIVER_READ_READY,
91         BCAPS_READ_DONE,
92         BKSV_READ_DONE,
93         AN_WRITE_DONE,
94         AKSV_WRITE_DONE,
95         FIRST_AUTHENTICATION_DONE,
96         SECOND_AUTHENTICATION_RDY,
97         SECOND_AUTHENTICATION_DONE,
98 };
99
100 struct s5p_hdcp_info {
101         u8                      is_repeater;
102         u32                     hdcp_enable;
103
104         spinlock_t              reset_lock;
105
106         enum hdcp_event         event;
107         enum hdcp_state         auth_status;
108
109         struct work_struct      work;
110 };
111
112 struct i2c_client *ddc_port;
113
114 static bool sw_reset;
115
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,
121 };
122
123 /* start: external functions for HDMI */
124 extern void __iomem *hdmi_base;
125
126 /* end: external functions for HDMI */
127
128 /* ddc i2c */
129 static int s5p_ddc_read(u8 reg, int bytes, u8 *dest)
130 {
131         struct i2c_client *i2c = ddc_port;
132         u8 addr = reg;
133         int ret, cnt = 0;
134
135         struct i2c_msg msg[] = {
136                 [0] = {
137                         .addr = i2c->addr,
138                         .flags = 0,
139                         .len = 1,
140                         .buf = &addr
141                 },
142                 [1] = {
143                         .addr = i2c->addr,
144                         .flags = I2C_M_RD,
145                         .len = bytes,
146                         .buf = dest
147                 }
148         };
149
150         do {
151                 if (!s5p_hdmi_reg_get_hpd_status())
152                         goto ddc_read_err;
153
154                 ret = i2c_transfer(i2c->adapter, msg, 2);
155
156                 if (ret < 0 || ret != 2)
157                         tvout_dbg("ddc : can't read data, retry %d\n", cnt);
158                 else
159                         break;
160
161                 if (hdcp_info.auth_status == FIRST_AUTHENTICATION_DONE
162                         || hdcp_info.auth_status == SECOND_AUTHENTICATION_DONE)
163                         goto ddc_read_err;
164
165                 msleep(DDC_DELAY);
166                 cnt++;
167         } while (cnt < DDC_RETRY_CNT);
168
169         if (cnt == DDC_RETRY_CNT)
170                 goto ddc_read_err;
171
172         tvout_dbg("ddc : read data ok\n");
173
174         return 0;
175 ddc_read_err:
176         tvout_err("ddc : can't read data, timeout\n");
177         return -1;
178 }
179
180 static int s5p_ddc_write(u8 reg, int bytes, u8 *src)
181 {
182         struct i2c_client *i2c = ddc_port;
183         u8 msg[bytes + 1];
184         int ret, cnt = 0;
185
186         msg[0] = reg;
187         memcpy(&msg[1], src, bytes);
188
189         do {
190                 if (!s5p_hdmi_reg_get_hpd_status())
191                         goto ddc_write_err;
192
193                 ret = i2c_master_send(i2c, msg, bytes + 1);
194
195                 if (ret < 0 || ret < bytes + 1)
196                         tvout_dbg("ddc : can't write data, retry %d\n", cnt);
197                 else
198                         break;
199
200                 msleep(DDC_DELAY);
201                 cnt++;
202         } while (cnt < DDC_RETRY_CNT);
203
204         if (cnt == DDC_RETRY_CNT)
205                 goto ddc_write_err;
206
207         tvout_dbg("ddc : write data ok\n");
208         return 0;
209 ddc_write_err:
210         tvout_err("ddc : can't write data, timeout\n");
211         return -1;
212 }
213
214 static int __devinit s5p_ddc_probe(struct i2c_client *client,
215                         const struct i2c_device_id *dev_id)
216 {
217         int ret = 0;
218
219         ddc_port = client;
220
221         dev_info(&client->adapter->dev, "attached s5p_ddc "
222                 "into i2c adapter successfully\n");
223
224         return ret;
225 }
226
227 static int s5p_ddc_remove(struct i2c_client *client)
228 {
229         dev_info(&client->adapter->dev, "detached s5p_ddc "
230                 "from i2c adapter successfully\n");
231
232         return 0;
233 }
234
235 static int s5p_ddc_suspend(struct i2c_client *cl, pm_message_t mesg)
236 {
237         return 0;
238 };
239
240 static int s5p_ddc_resume(struct i2c_client *cl)
241 {
242         return 0;
243 };
244
245 static struct i2c_device_id ddc_idtable[] = {
246         {"s5p_ddc", 0},
247 };
248 MODULE_DEVICE_TABLE(i2c, ddc_idtable);
249
250 static struct i2c_driver ddc_driver = {
251         .driver = {
252                 .name = "s5p_ddc",
253                 .owner = THIS_MODULE,
254         },
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,
260 };
261
262 static int __init s5p_ddc_init(void)
263 {
264         return i2c_add_driver(&ddc_driver);
265 }
266
267 static void __exit s5p_ddc_exit(void)
268 {
269         i2c_del_driver(&ddc_driver);
270 }
271
272
273 module_init(s5p_ddc_init);
274 module_exit(s5p_ddc_exit);
275
276 /* hdcp */
277 static int s5p_hdcp_encryption(bool on)
278 {
279         u8 reg;
280
281         if (on)
282                 reg = S5P_HDMI_HDCP_ENC_ENABLE;
283         else
284                 reg = S5P_HDMI_HDCP_ENC_DISABLE;
285
286         writeb(reg, hdmi_base + S5P_HDMI_ENC_EN);
287         s5p_hdmi_reg_mute(!on);
288
289         return 0;
290 }
291
292 static int s5p_hdcp_write_key(int sz, int reg, int type)
293 {
294         u8 buff[MAX_KEY_SZ] = {0,};
295         int cnt = 0, zero = 0;
296
297         hdmi_read_l(buff, hdmi_base, reg, sz);
298
299         for (cnt = 0; cnt < sz; cnt++)
300                 if (buff[cnt] == 0)
301                         zero++;
302
303         if (zero == sz) {
304                 tvout_dbg("%s : null\n", type == HDCP_An ? "an" : "aksv");
305                 goto write_key_err;
306         }
307
308         if (s5p_ddc_write(type, sz, buff) < 0)
309                 goto write_key_err;
310
311 #ifdef CONFIG_HDCP_DEBUG
312         {
313                 u16 i = 0;
314
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]);
318         }
319 #endif
320
321         return 0;
322 write_key_err:
323         tvout_err("write %s : failed\n", type == HDCP_An ? "an" : "aksv");
324         return -1;
325 }
326
327 static int s5p_hdcp_read_bcaps(void)
328 {
329         u8 bcaps = 0;
330
331         if (s5p_ddc_read(HDCP_Bcaps, BCAPS_SIZE, &bcaps) < 0)
332                 goto bcaps_read_err;
333
334         writeb(bcaps, hdmi_base + S5P_HDMI_HDCP_BCAPS);
335
336         if (bcaps & S5P_HDMI_HDCP_BCAPS_REPEATER)
337                 hdcp_info.is_repeater = 1;
338         else
339                 hdcp_info.is_repeater = 0;
340
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));
345
346         return 0;
347
348 bcaps_read_err:
349         tvout_err("can't read bcaps : timeout\n");
350         return -1;
351 }
352
353 static int s5p_hdcp_read_bksv(void)
354 {
355         u8 bksv[BKSV_SZ] = {0, };
356         int i = 0, j = 0;
357         u32 one = 0, zero = 0, res = 0;
358         u32 cnt = 0;
359
360         do {
361                 if (s5p_ddc_read(HDCP_Bksv, BKSV_SZ, bksv) < 0)
362                         goto bksv_read_err;
363
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]);
367 #endif
368
369                 for (i = 0; i < BKSV_SZ; i++) {
370
371                         for (j = 0; j < 8; j++) {
372                                 res = bksv[i] & (0x1 << j);
373
374                                 if (res == 0)
375                                         zero++;
376                                 else
377                                         one++;
378                         }
379
380                 }
381
382                 if ((zero == 20) && (one == 20)) {
383                         hdmi_write_l(bksv, hdmi_base,
384                                 S5P_HDMI_HDCP_BKSV_0_0, BKSV_SZ);
385                         break;
386                 }
387                 tvout_dbg("invalid bksv, retry : %d\n", cnt);
388
389                 msleep(BKSV_DELAY);
390                 cnt++;
391         } while (cnt < BKSV_RETRY_CNT);
392
393         if (cnt == BKSV_RETRY_CNT)
394                 goto bksv_read_err;
395
396         tvout_dbg("bksv read OK, retry : %d\n", cnt);
397         return 0;
398
399 bksv_read_err:
400         tvout_err("can't read bksv : timeout\n");
401         return -1;
402 }
403
404 static int s5p_hdcp_read_ri(void)
405 {
406         u8 ri[2] = {0, 0};
407         u8 rj[2] = {0, 0};
408
409         ri[0] = readb(hdmi_base + S5P_HDMI_HDCP_Ri_0);
410         ri[1] = readb(hdmi_base + S5P_HDMI_HDCP_Ri_1);
411
412         if (s5p_ddc_read(HDCP_Ri, 2, rj) < 0)
413                 goto compare_err;
414
415         tvout_dbg("Rx(ddc) -> rj[0]: 0x%02x, rj[1]: 0x%02x\n",
416                 rj[0], rj[1]);
417         tvout_dbg("Tx(register) -> ri[0]: 0x%02x, ri[1]: 0x%02x\n",
418                 ri[0], ri[1]);
419
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);
423         else {
424                 writeb(S5P_HDMI_HDCP_Ri_MATCH_RESULT_N,
425                         hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
426                 goto compare_err;
427         }
428
429         ri[0] = 0;
430         ri[1] = 0;
431         rj[0] = 0;
432         rj[1] = 0;
433
434         tvout_dbg("ri, ri' : matched\n");
435
436         return 0;
437 compare_err:
438         hdcp_info.event         = HDCP_EVENT_STOP;
439         hdcp_info.auth_status   = NOT_AUTHENTICATED;
440         tvout_err("read ri : failed - missmatch\n");
441         msleep(10);
442         return -1;
443 }
444
445 static void s5p_hdcp_reset_sw(void)
446 {
447         u8 reg;
448
449         sw_reset = true;
450         reg = s5p_hdmi_reg_intc_get_enabled();
451
452         s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_PLUG, 0);
453         s5p_hdmi_reg_intc_enable(HDMI_IRQ_HPD_UNPLUG, 0);
454
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);
459
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);
464
465         sw_reset = false;
466 }
467
468 static void s5p_hdcp_reset_auth(void)
469 {
470         u8 reg;
471
472         spin_lock_irq(&hdcp_info.reset_lock);
473
474         hdcp_info.event         = HDCP_EVENT_STOP;
475         hdcp_info.auth_status   = NOT_AUTHENTICATED;
476
477         writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL1);
478         writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL2);
479         s5p_hdmi_reg_mute(true);
480
481         s5p_hdcp_encryption(false);
482
483         tvout_err("reset authentication\n");
484
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);
488
489         writeb(S5P_HDMI_HDCP_CLR_ALL_RESULTS,
490                                 hdmi_base + S5P_HDMI_HDCP_CHECK_RESULT);
491
492         /* need some delay (at least 1 frame) */
493         mdelay(16);
494
495         s5p_hdcp_reset_sw();
496
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);
504
505         spin_unlock_irq(&hdcp_info.reset_lock);
506 }
507
508 static int s5p_hdcp_loadkey(void)
509 {
510         u8 reg;
511         int cnt = 0;
512
513         writeb(S5P_HDMI_EFUSE_CTRL_HDCP_KEY_READ,
514                                 hdmi_base + S5P_HDMI_EFUSE_CTRL);
515
516         do {
517                 reg = readb(hdmi_base + S5P_HDMI_EFUSE_STATUS);
518                 if (reg & S5P_HDMI_EFUSE_ECC_DONE)
519                         break;
520                 cnt++;
521                 mdelay(1);
522         } while (cnt < KEY_LOAD_RETRY_CNT);
523
524         if (cnt == KEY_LOAD_RETRY_CNT)
525                 goto key_load_err;
526
527         reg = readb(hdmi_base + S5P_HDMI_EFUSE_STATUS);
528
529         if (reg & S5P_HDMI_EFUSE_ECC_FAIL)
530                 goto key_load_err;
531
532         tvout_dbg("load key : OK\n");
533         return 0;
534 key_load_err:
535         tvout_err("can't load key\n");
536         return -1;
537 }
538
539 static int s5p_hdmi_start_encryption(void)
540 {
541         u8 reg;
542         u32 cnt = 0;
543
544         do {
545                 reg = readb(hdmi_base + S5P_HDMI_SYS_STATUS);
546
547                 if (reg & S5P_HDMI_AUTHEN_ACK_AUTH) {
548                         s5p_hdcp_encryption(true);
549                         break;
550                 }
551
552                 mdelay(1);
553
554                 cnt++;
555         } while (cnt < ENCRYPT_CHECK_CNT);
556
557         if (cnt == ENCRYPT_CHECK_CNT)
558                 goto encrypt_err;
559
560
561         tvout_dbg("encrypt : start\n");
562         return 0;
563
564 encrypt_err:
565         s5p_hdcp_encryption(false);
566         tvout_err("encrypt : failed\n");
567         return -1;
568 }
569
570 static int s5p_hdmi_check_repeater(void)
571 {
572         int reg = 0;
573         int cnt = 0, cnt2 = 0;
574
575         u8 bcaps = 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};
579
580         u32 dev_cnt;
581
582         memset(rx_v, 0x0, SHA_1_HASH_SIZE);
583         memset(ksv_list, 0x0, HDCP_MAX_DEVS * HDCP_KSV_SIZE);
584
585         do {
586                 if (s5p_hdcp_read_bcaps() < 0)
587                         goto check_repeater_err;
588
589                 bcaps = readb(hdmi_base + S5P_HDMI_HDCP_BCAPS);
590
591                 if (bcaps & KSV_FIFO_READY) {
592                         tvout_dbg("repeater : ksv fifo not ready");
593                         tvout_dbg(", retries : %d\n", cnt);
594                         break;
595                 }
596
597                 msleep(KSV_FIFO_CHK_DELAY);
598
599                 cnt++;
600         } while (cnt < KSV_FIFO_RETRY_CNT);
601
602         if (cnt == KSV_FIFO_RETRY_CNT)
603                 return REPEATER_TIMEOUT_ERROR;
604
605         tvout_dbg("repeater : ksv fifo ready\n");
606
607
608         if (s5p_ddc_read(HDCP_BStatus, BSTATUS_SIZE, status) < 0)
609                 goto check_repeater_err;
610
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;
615
616         writeb(status[0], hdmi_base + S5P_HDMI_HDCP_BSTATUS_0);
617         writeb(status[1], hdmi_base + S5P_HDMI_HDCP_BSTATUS_1);
618
619         tvout_dbg("status[0] :0x%02x\n", status[0]);
620         tvout_dbg("status[1] :0x%02x\n", status[1]);
621
622         dev_cnt = status[0] & 0x7f;
623
624         tvout_dbg("repeater : dev cnt = %d\n", dev_cnt);
625
626         if (dev_cnt) {
627
628                 if (s5p_ddc_read(HDCP_KSVFIFO, dev_cnt * HDCP_KSV_SIZE,
629                                 ksv_list) < 0)
630                         goto check_repeater_err;
631
632                 cnt = 0;
633
634                 do {
635                         hdmi_write_l(&ksv_list[cnt*5], hdmi_base,
636                                 S5P_HDMI_HDCP_RX_KSV_0_0, HDCP_KSV_SIZE);
637
638                         reg = S5P_HDMI_HDCP_KSV_WRITE_DONE;
639
640                         if (cnt == dev_cnt - 1)
641                                 reg |= S5P_HDMI_HDCP_KSV_END;
642
643                         writeb(reg, hdmi_base + S5P_HDMI_HDCP_KSV_LIST_CON);
644
645                         if (cnt < dev_cnt - 1) {
646                                 cnt2 = 0;
647                                 do {
648                                         reg = readb(hdmi_base
649                                                 + S5P_HDMI_HDCP_KSV_LIST_CON);
650
651                                         if (reg & S5P_HDMI_HDCP_KSV_READ)
652                                                 break;
653                                         cnt2++;
654                                 } while (cnt2 < KSV_LIST_RETRY_CNT);
655
656                                 if (cnt2 == KSV_LIST_RETRY_CNT)
657                                         tvout_dbg("ksv list not readed\n");
658                         }
659                         cnt++;
660                 } while (cnt < dev_cnt);
661         } else {
662                 writeb(S5P_HDMI_HDCP_KSV_LIST_EMPTY,
663                         hdmi_base + S5P_HDMI_HDCP_KSV_LIST_CON);
664         }
665
666         if (s5p_ddc_read(HDCP_SHA1, SHA_1_HASH_SIZE, rx_v) < 0)
667                 goto check_repeater_err;
668
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]);
672 #endif
673
674         hdmi_write_l(rx_v, hdmi_base, S5P_HDMI_HDCP_RX_SHA1_0_0,
675                 SHA_1_HASH_SIZE);
676
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);
682                 } else {
683                         tvout_dbg("SHA-1 result : not vaild\n");
684                         writeb(0x0, hdmi_base + S5P_HDMI_HDCP_SHA_RESULT);
685                         goto check_repeater_err;
686                 }
687         } else {
688                 tvout_dbg("SHA-1 result : not ready\n");
689                 writeb(0x0, hdmi_base + S5P_HDMI_HDCP_SHA_RESULT);
690                 goto check_repeater_err;
691         }
692
693         tvout_dbg("check repeater : OK\n");
694         return 0;
695 check_repeater_err:
696         tvout_err("check repeater : failed\n");
697         return -1;
698 }
699
700 int s5p_hdcp_stop(void)
701 {
702         u32  sfr_val = 0;
703
704         tvout_dbg("HDCP ftn. Stop!!\n");
705
706         s5p_hdmi_reg_intc_enable(HDMI_IRQ_HDCP, 0);
707
708         hdcp_info.event         = HDCP_EVENT_STOP;
709         hdcp_info.auth_status   = NOT_AUTHENTICATED;
710         hdcp_info.hdcp_enable   = false;
711
712         writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL1);
713
714         s5p_hdmi_reg_sw_hpd_enable(false);
715
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);
719
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);
723
724         tvout_dbg("Stop Encryption by Stop!!\n");
725         s5p_hdcp_encryption(false);
726
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);
731
732         return 0;
733 }
734
735 int s5p_hdcp_start(void)
736 {
737         u32  sfr_val;
738
739         hdcp_info.event         = HDCP_EVENT_STOP;
740         hdcp_info.auth_status   = NOT_AUTHENTICATED;
741
742         tvout_dbg("HDCP ftn. Start\n");
743
744         s5p_hdcp_reset_sw();
745
746         tvout_dbg("Stop Encryption by Start\n");
747
748         s5p_hdcp_encryption(false);
749
750         if (s5p_hdcp_loadkey() < 0)
751                 return -1;
752
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);
755
756         sfr_val = S5P_HDMI_HDCP_CP_DESIRED_EN;
757         writeb(sfr_val, hdmi_base + S5P_HDMI_HDCP_CTRL1);
758
759         s5p_hdmi_reg_intc_enable(HDMI_IRQ_HDCP, 1);
760
761         hdcp_info.hdcp_enable = 1;
762
763         return 0;
764 }
765
766 static int s5p_hdcp_bksv(void)
767 {
768         tvout_dbg("bksv start : start\n");
769
770         hdcp_info.auth_status = RECEIVER_READ_READY;
771
772         if (s5p_hdcp_read_bcaps() < 0)
773                 goto bksv_start_err;
774
775         hdcp_info.auth_status = BCAPS_READ_DONE;
776
777         if (s5p_hdcp_read_bksv() < 0)
778                 goto bksv_start_err;
779
780         hdcp_info.auth_status = BKSV_READ_DONE;
781
782         tvout_dbg("bksv start : OK\n");
783
784         return 0;
785
786 bksv_start_err:
787         tvout_err("bksv start : failed\n");
788         msleep(100);
789         return -1;
790 }
791
792 static int s5p_hdcp_second_auth(void)
793 {
794         int reg = 0, ret = 0;
795
796         tvout_dbg("second auth : start\n");
797
798         if (!hdcp_info.hdcp_enable)
799                 goto second_auth_err;
800
801         ret = s5p_hdmi_check_repeater();
802
803         if (!ret) {
804                 hdcp_info.auth_status = SECOND_AUTHENTICATION_DONE;
805                 s5p_hdmi_start_encryption();
806         } else if (ret < 0)
807                 goto second_auth_err;
808         else {
809                 switch (ret) {
810
811                 case REPEATER_ILLEGAL_DEVICE_ERROR:
812                         writeb(0x01, hdmi_base + S5P_HDMI_HDCP_CTRL2);
813                         mdelay(1);
814                         writeb(0x0, hdmi_base + S5P_HDMI_HDCP_CTRL2);
815
816                         tvout_dbg("repeater : illegal device\n");
817                         break;
818                 case REPEATER_TIMEOUT_ERROR:
819                         reg = readb(hdmi_base + S5P_HDMI_HDCP_CTRL1);
820
821                         reg |= S5P_HDMI_HDCP_SET_REPEATER_TIMEOUT;
822                         writeb(reg, hdmi_base + S5P_HDMI_HDCP_CTRL1);
823
824                         reg &= ~S5P_HDMI_HDCP_SET_REPEATER_TIMEOUT;
825                         writeb(reg, hdmi_base + S5P_HDMI_HDCP_CTRL1);
826
827                         tvout_dbg("repeater : timeout\n");
828                         break;
829                 case MAX_CASCADE_EXCEEDED_ERROR:
830
831                         tvout_dbg("repeater : exceeded MAX_CASCADE\n");
832                         break;
833                 case MAX_DEVS_EXCEEDED_ERROR:
834
835                         tvout_dbg("repeater : exceeded MAX_DEVS\n");
836                         break;
837                 default:
838                         break;
839                 }
840
841                 hdcp_info.auth_status = NOT_AUTHENTICATED;
842
843                 goto second_auth_err;
844
845         }
846
847         tvout_dbg("second auth : OK\n");
848         return 0;
849
850 second_auth_err:
851         tvout_err("second auth : failed\n");
852         return -1;
853 }
854
855 static int s5p_hdcp_write_aksv(void)
856 {
857         tvout_dbg("aksv start : start\n");
858
859         if (hdcp_info.auth_status != BKSV_READ_DONE) {
860                 tvout_dbg("aksv start : bksv is not ready\n");
861                 goto aksv_write_err;
862         }
863
864         if (s5p_hdcp_write_key(AN_SZ, S5P_HDMI_HDCP_An_0_0, HDCP_An) < 0)
865                 goto aksv_write_err;
866
867         hdcp_info.auth_status = AN_WRITE_DONE;
868
869         tvout_dbg("write an : done\n");
870
871         if (s5p_hdcp_write_key(AKSV_SZ, S5P_HDMI_HDCP_AKSV_0_0, HDCP_Aksv) < 0)
872                 goto aksv_write_err;
873
874         msleep(100);
875
876         hdcp_info.auth_status = AKSV_WRITE_DONE;
877
878         tvout_dbg("write aksv : done\n");
879         tvout_dbg("aksv start : OK\n");
880         return 0;
881
882 aksv_write_err:
883         tvout_err("aksv start : failed\n");
884         return -1;
885 }
886
887 static int s5p_hdcp_check_ri(void)
888 {
889         tvout_dbg("ri check : start\n");
890
891         if (hdcp_info.auth_status < AKSV_WRITE_DONE) {
892                 tvout_dbg("ri check : not ready\n");
893                 goto check_ri_err;
894         }
895
896         if (s5p_hdcp_read_ri() < 0)
897                 goto check_ri_err;
898
899         if (hdcp_info.is_repeater)
900                 hdcp_info.auth_status
901                         = SECOND_AUTHENTICATION_RDY;
902         else {
903                 hdcp_info.auth_status
904                         = FIRST_AUTHENTICATION_DONE;
905                 s5p_hdmi_start_encryption();
906         }
907
908         tvout_dbg("ri check : OK\n");
909         return 0;
910
911 check_ri_err:
912         tvout_err("ri check : failed\n");
913         return -1;
914 }
915
916 static void s5p_hdcp_work(void *arg)
917 {
918         if (hdcp_info.event & HDCP_EVENT_READ_BKSV_START) {
919                 if (s5p_hdcp_bksv() < 0)
920                         goto work_err;
921                 else
922                         hdcp_info.event &= ~HDCP_EVENT_READ_BKSV_START;
923         }
924
925         if (hdcp_info.event & HDCP_EVENT_SECOND_AUTH_START) {
926                 if (s5p_hdcp_second_auth() < 0)
927                         goto work_err;
928                 else
929                         hdcp_info.event &= ~HDCP_EVENT_SECOND_AUTH_START;
930         }
931
932         if (hdcp_info.event & HDCP_EVENT_WRITE_AKSV_START) {
933                 if (s5p_hdcp_write_aksv() < 0)
934                         goto work_err;
935                 else
936                         hdcp_info.event  &= ~HDCP_EVENT_WRITE_AKSV_START;
937         }
938
939         if (hdcp_info.event & HDCP_EVENT_CHECK_RI_START) {
940                 if (s5p_hdcp_check_ri() < 0)
941                         goto work_err;
942                 else
943                         hdcp_info.event &= ~HDCP_EVENT_CHECK_RI_START;
944         }
945         return;
946 work_err:
947         s5p_hdcp_reset_auth();
948 }
949
950 irqreturn_t s5p_hdcp_irq_handler(int irq, void *dev_id)
951 {
952         u32 event = 0;
953         u8 flag;
954
955         event = 0;
956
957         flag = readb(hdmi_base + S5P_HDMI_SYS_STATUS);
958
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);
964         }
965
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);
971         }
972
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);
978         }
979
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);
985         }
986
987         if (!event) {
988                 tvout_dbg("unknown irq\n");
989                 return IRQ_HANDLED;
990         }
991
992         hdcp_info.event |= event;
993         schedule_work(&hdcp_info.work);
994
995         return IRQ_HANDLED;
996 }
997
998 int s5p_hdcp_init(void)
999 {
1000         INIT_WORK(&hdcp_info.work, (work_func_t) s5p_hdcp_work);
1001
1002         spin_lock_init(&hdcp_info.reset_lock);
1003
1004         s5p_hdmi_reg_intc_set_isr(s5p_hdcp_irq_handler,
1005                                         (u8) HDMI_IRQ_HDCP);
1006
1007         return 0;
1008 }
1009
1010 int s5p_hdcp_encrypt_stop(bool on)
1011 {
1012         u32 reg;
1013
1014         spin_lock_irq(&hdcp_info.reset_lock);
1015
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);
1021
1022                 s5p_hdcp_encryption(false);
1023
1024                 if (!sw_reset) {
1025                         reg = readb(hdmi_base + S5P_HDMI_HDCP_CTRL1);
1026
1027                         if (on) {
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);
1031                         } else {
1032                                 hdcp_info.event = HDCP_EVENT_STOP;
1033                                 hdcp_info.auth_status = NOT_AUTHENTICATED;
1034
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);
1038                         }
1039                 }
1040
1041                 tvout_dbg("stop encryption by HPD\n");
1042         }
1043
1044         spin_unlock_irq(&hdcp_info.reset_lock);
1045
1046         return 0;
1047 }