eaf27b9bb3a5ef6a33f4cd8570feae91930b45cb
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmiv2 / rockchip_hdmiv2_hdcp.c
1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/errno.h>
4 #include <linux/string.h>
5 #include <linux/miscdevice.h>
6 #include <linux/workqueue.h>
7 #include <linux/firmware.h>
8 #include "rockchip_hdmiv2.h"
9 #include "rockchip_hdmiv2_hw.h"
10
11 #define HDCP_KEY_SIZE           308
12 #define HDCP_PRIVATE_KEY_SIZE   280
13 #define HDCP_KEY_SHA_SIZE       20
14 #define HDCP_KEY_SEED_SIZE      2
15
16 struct hdcp_keys {
17         u8 KSV[8];
18         u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
19         u8 sha1[HDCP_KEY_SHA_SIZE];
20 };
21
22 struct hdcp {
23         struct hdmi             *hdmi;
24         int                     enable;
25         int                     retry_times;
26         struct hdcp_keys        *keys;
27         char                    *seeds;
28         int                     invalidkey;
29         char                    *invalidkeys;
30 };
31
32 static struct miscdevice mdev;
33 static struct hdcp *hdcp;
34
35 static void hdcp_load_key(struct hdmi *hdmi, struct hdcp_keys *key)
36 {
37         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
38         int i, value;
39
40         /* Disable decryption logic */
41         hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 0);
42         /* Poll untile DPK write is allowed */
43         do {
44                 value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
45         } while ((value & m_DPK_WR_OK_STS) == 0);
46
47         /* write unencryped AKSV */
48         hdmi_writel(hdmi_dev, HDCPREG_DPK6, 0);
49         hdmi_writel(hdmi_dev, HDCPREG_DPK5, 0);
50         hdmi_writel(hdmi_dev, HDCPREG_DPK4, key->KSV[4]);
51         hdmi_writel(hdmi_dev, HDCPREG_DPK3, key->KSV[3]);
52         hdmi_writel(hdmi_dev, HDCPREG_DPK2, key->KSV[2]);
53         hdmi_writel(hdmi_dev, HDCPREG_DPK1, key->KSV[1]);
54         hdmi_writel(hdmi_dev, HDCPREG_DPK0, key->KSV[0]);
55         /* Poll untile DPK write is allowed */
56         do {
57                 value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
58         } while ((value & m_DPK_WR_OK_STS) == 0);
59
60         if (hdcp->seeds != NULL) {
61                 hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 1);
62                 hdmi_writel(hdmi_dev, HDCPREG_SEED1, hdcp->seeds[0]);
63                 hdmi_writel(hdmi_dev, HDCPREG_SEED0, hdcp->seeds[1]);
64         } else {
65                 hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 0);
66         }
67
68         /* write private key */
69         for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i += 7) {
70                 hdmi_writel(hdmi_dev, HDCPREG_DPK6, key->devicekey[i + 6]);
71                 hdmi_writel(hdmi_dev, HDCPREG_DPK5, key->devicekey[i + 5]);
72                 hdmi_writel(hdmi_dev, HDCPREG_DPK4, key->devicekey[i + 4]);
73                 hdmi_writel(hdmi_dev, HDCPREG_DPK3, key->devicekey[i + 3]);
74                 hdmi_writel(hdmi_dev, HDCPREG_DPK2, key->devicekey[i + 2]);
75                 hdmi_writel(hdmi_dev, HDCPREG_DPK1, key->devicekey[i + 1]);
76                 hdmi_writel(hdmi_dev, HDCPREG_DPK0, key->devicekey[i]);
77
78                 do {
79                         value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
80                 } while ((value & m_DPK_WR_OK_STS) == 0);
81         }
82
83         pr_info("%s success\n", __func__);
84 }
85
86 static void hdcp_load_keys_cb(const struct firmware *fw,
87                               void *context)
88 {
89         struct hdmi *hdmi = (struct hdmi *)context;
90
91         if (fw == NULL) {
92                 pr_info("HDCP: firmware is not loaded\n");
93                 return;
94         }
95         if (fw->size < HDCP_KEY_SIZE) {
96                 pr_err("HDCP: firmware wrong size %d\n", (int)fw->size);
97                 return;
98         }
99         hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
100         memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
101
102         if (fw->size > HDCP_KEY_SIZE) {
103                 if ((fw->size - HDCP_KEY_SIZE) < HDCP_KEY_SEED_SIZE) {
104                         pr_err("HDCP: invalid seed key size\n");
105                         return;
106                 }
107                 hdcp->seeds = kmalloc(HDCP_KEY_SEED_SIZE, GFP_KERNEL);
108                 if (hdcp->seeds == NULL) {
109                         pr_err("HDCP: can't allocated space for seed keys\n");
110                         return;
111                 }
112                 memcpy(hdcp->seeds, fw->data + HDCP_KEY_SIZE,
113                        HDCP_KEY_SEED_SIZE);
114         }
115         hdcp_load_key(hdmi, hdcp->keys);
116 }
117
118 void rockchip_hdmiv2_hdcp2_enable(int enable)
119 {
120         struct hdmi_dev *hdmi_dev;
121
122         if (!hdcp) {
123                 pr_err("rockchip hdmiv2 hdcp is not exist\n");
124                 return;
125         }
126         hdmi_dev = hdcp->hdmi->property->priv;
127         if (hdmi_dev->soctype == HDMI_SOC_RK3368 &&
128             hdmi_dev->hdcp2_enable != enable) {
129                 hdmi_dev->hdcp2_enable = enable;
130                 if (hdmi_dev->hdcp2_enable == 0) {
131                         hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
132                                      m_HDCP2_OVR_EN | m_HDCP2_FORCE,
133                                      v_HDCP2_OVR_EN(1) | v_HDCP2_FORCE(0));
134                         hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0xff);
135                         hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0xff);
136                 } else {
137                         hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
138                                      m_HDCP2_OVR_EN | m_HDCP2_FORCE,
139                                      v_HDCP2_OVR_EN(0) | v_HDCP2_FORCE(0));
140                         hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0x00);
141                         hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0x00);
142                 }
143         }
144 }
145 EXPORT_SYMBOL(rockchip_hdmiv2_hdcp2_enable);
146
147 void rockchip_hdmiv2_hdcp2_init(void (*hdcp2_enble)(int),
148                                 void (*hdcp2_reset)(void),
149                                 void (*hdcp2_start)(void))
150 {
151         struct hdmi_dev *hdmi_dev;
152
153         if (!hdcp) {
154                 pr_err("rockchip hdmiv2 hdcp is not exist\n");
155                 return;
156         }
157         hdmi_dev = hdcp->hdmi->property->priv;
158         hdmi_dev->hdcp2_en = hdcp2_enble;
159         hdmi_dev->hdcp2_reset = hdcp2_reset;
160         hdmi_dev->hdcp2_start = hdcp2_start;
161 }
162 EXPORT_SYMBOL(rockchip_hdmiv2_hdcp2_init);
163
164 static void rockchip_hdmiv2_hdcp_start(struct hdmi *hdmi)
165 {
166         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
167
168         if (!hdcp->enable)
169                 return;
170         if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
171                 if (hdmi_dev->hdcp2_enable == 0) {
172                         hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
173                                      m_HDCP2_OVR_EN | m_HDCP2_FORCE,
174                                      v_HDCP2_OVR_EN(1) | v_HDCP2_FORCE(0));
175                         hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0xff);
176                         hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0xff);
177                 } else {
178                         hdmi_msk_reg(hdmi_dev, HDCP2REG_CTRL,
179                                      m_HDCP2_OVR_EN | m_HDCP2_FORCE,
180                                      v_HDCP2_OVR_EN(0) | v_HDCP2_FORCE(0));
181                         hdmi_writel(hdmi_dev, HDCP2REG_MASK, 0x00);
182                         hdmi_writel(hdmi_dev, HDCP2REG_MUTE, 0x00);
183                 }
184         }
185
186         hdmi_msk_reg(hdmi_dev, FC_INVIDCONF,
187                      m_FC_HDCP_KEEPOUT, v_FC_HDCP_KEEPOUT(1));
188         hdmi_msk_reg(hdmi_dev, A_HDCPCFG0,
189                      m_HDMI_DVI, v_HDMI_DVI(hdmi->edid.sink_hdmi));
190         hdmi_writel(hdmi_dev, A_OESSWCFG, 0x40);
191         hdmi_msk_reg(hdmi_dev, A_HDCPCFG0,
192                      m_ENCRYPT_BYPASS | m_FEATURE11_EN | m_SYNC_RI_CHECK,
193                      v_ENCRYPT_BYPASS(0) | v_FEATURE11_EN(0) |
194                      v_SYNC_RI_CHECK(1));
195         hdmi_msk_reg(hdmi_dev, A_HDCPCFG1,
196                      m_ENCRYPT_DISBALE | m_PH2UPSHFTENC,
197                      v_ENCRYPT_DISBALE(0) | v_PH2UPSHFTENC(1));
198         /* Reset HDCP Engine */
199         if (hdmi_readl(hdmi_dev, MC_CLKDIS) & m_HDCPCLK_DISABLE)
200                 hdmi_msk_reg(hdmi_dev, A_HDCPCFG1,
201                              m_HDCP_SW_RST, v_HDCP_SW_RST(0));
202
203         hdmi_writel(hdmi_dev, A_APIINTMSK, 0x00);
204         hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
205
206         hdmi_msk_reg(hdmi_dev, MC_CLKDIS,
207                      m_HDCPCLK_DISABLE, v_HDCPCLK_DISABLE(0));
208         if (hdmi_dev->hdcp2_start)
209                 hdmi_dev->hdcp2_start();
210         pr_info("%s success\n", __func__);
211 }
212
213 static void rockchip_hdmiv2_hdcp_stop(struct hdmi *hdmi)
214 {
215         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
216
217         if (!hdcp->enable)
218                 return;
219
220         hdmi_msk_reg(hdmi_dev, MC_CLKDIS,
221                      m_HDCPCLK_DISABLE, v_HDCPCLK_DISABLE(1));
222         hdmi_writel(hdmi_dev, A_APIINTMSK, 0xff);
223         hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(0));
224         rockchip_hdmiv2_hdcp2_enable(0);
225 }
226
227 static ssize_t hdcp_enable_read(struct device *device,
228                                 struct device_attribute *attr, char *buf)
229 {
230         int enable = 0;
231
232         if (hdcp)
233                 enable = hdcp->enable;
234
235         return snprintf(buf, PAGE_SIZE, "%d\n", enable);
236 }
237
238 static ssize_t hdcp_enable_write(struct device *device,
239                                  struct device_attribute *attr,
240                                  const char *buf, size_t count)
241 {
242         int enable;
243
244         if (hdcp == NULL)
245                 return -EINVAL;
246         if (hdcp->keys == NULL) {
247                 pr_err("HDCP: key is not loaded\n");
248                 return -EINVAL;
249         }
250         if (kstrtoint(buf, 0, &enable))
251                 return -EINVAL;
252
253         if (hdcp->enable != enable) {
254                 if (!hdcp->enable)
255                         hdmi_submit_work(hdcp->hdmi, HDMI_ENABLE_HDCP, 0, NULL);
256                 else
257                         rockchip_hdmiv2_hdcp_stop(hdcp->hdmi);
258                 hdcp->enable =  enable;
259         }
260
261         return count;
262 }
263 static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
264                    hdcp_enable_read, hdcp_enable_write);
265
266 static ssize_t hdcp_trytimes_read(struct device *device,
267                                   struct device_attribute *attr, char *buf)
268 {
269         int trytimes = 0;
270
271         if (hdcp)
272                 trytimes = hdcp->retry_times;
273
274         return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
275 }
276
277 static ssize_t hdcp_trytimes_wrtie(struct device *device,
278                                    struct device_attribute *attr,
279                                    const char *buf, size_t count)
280 {
281         int trytimes;
282
283         if (hdcp == NULL)
284                 return -EINVAL;
285
286         if (kstrtoint(buf, 0, &trytimes))
287                 return -EINVAL;
288
289         if (hdcp->retry_times != trytimes)
290                 hdcp->retry_times = trytimes;
291
292         return count;
293 }
294 static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR,
295                    hdcp_trytimes_read, hdcp_trytimes_wrtie);
296
297 static int hdcp_init(struct hdmi *hdmi)
298 {
299         int ret;
300         struct hdmi_dev *hdmi_dev = hdmi->property->priv;
301
302         mdev.minor = MISC_DYNAMIC_MINOR;
303         mdev.name = "hdcp";
304         mdev.mode = 0666;
305         hdcp = kmalloc(sizeof(*hdcp), GFP_KERNEL);
306         if (!hdcp) {
307                 pr_err("HDCP: kmalloc fail!\n");
308                 ret = -ENOMEM;
309                 goto error0;
310         }
311         memset(hdcp, 0, sizeof(struct hdcp));
312         hdcp->hdmi = hdmi;
313         if (misc_register(&mdev)) {
314                 pr_err("HDCP: Could not add character driver\n");
315                 ret = HDMI_ERROR_FALSE;
316                 goto error1;
317         }
318         ret = device_create_file(mdev.this_device, &dev_attr_enable);
319         if (ret) {
320                 pr_err("HDCP: Could not add sys file enable\n");
321                 ret = -EINVAL;
322                 goto error2;
323         }
324         ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
325         if (ret) {
326                 pr_err("HDCP: Could not add sys file enable\n");
327                 ret = -EINVAL;
328                 goto error3;
329         }
330
331         ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
332                                       "hdcp", mdev.this_device, GFP_KERNEL,
333                                       hdmi, hdcp_load_keys_cb);
334
335         if (ret < 0) {
336                 pr_err("HDCP: request_firmware_nowait failed: %d\n", ret);
337                 goto error4;
338         }
339         if ((hdmi_readl(hdmi_dev, MC_CLKDIS) & m_HDCPCLK_DISABLE) == 0)
340                 hdcp->enable = 1;
341         hdmi->ops->hdcp_cb = rockchip_hdmiv2_hdcp_start;
342         return 0;
343
344 error4:
345         device_remove_file(mdev.this_device, &dev_attr_trytimes);
346 error3:
347         device_remove_file(mdev.this_device, &dev_attr_enable);
348 error2:
349         misc_deregister(&mdev);
350 error1:
351         kfree(hdcp->keys);
352         kfree(hdcp->invalidkeys);
353         kfree(hdcp);
354 error0:
355         return ret;
356 }
357
358 void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi)
359 {
360         pr_info("%s", __func__);
361         if (hdcp == NULL)
362                 hdcp_init(hdmi);
363         else
364                 hdcp_load_key(hdmi, hdcp->keys);
365 }