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"
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
18 u8 devicekey[HDCP_PRIVATE_KEY_SIZE];
19 u8 sha1[HDCP_KEY_SHA_SIZE];
26 struct hdcp_keys *keys;
32 static struct miscdevice mdev;
33 static struct hdcp *hdcp;
35 static void hdcp_load_key(struct hdmi *hdmi, struct hdcp_keys *key)
37 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
40 /* Disable decryption logic */
41 hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 0);
42 /* Poll untile DPK write is allowed */
44 value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
45 } while ((value & m_DPK_WR_OK_STS) == 0);
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 */
57 value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
58 } while ((value & m_DPK_WR_OK_STS) == 0);
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]);
65 hdmi_writel(hdmi_dev, HDCPREG_RMCTL, 0);
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]);
79 value = hdmi_readl(hdmi_dev, HDCPREG_RMSTS);
80 } while ((value & m_DPK_WR_OK_STS) == 0);
83 pr_info("%s success\n", __func__);
86 static void hdcp_load_keys_cb(const struct firmware *fw,
89 struct hdmi *hdmi = (struct hdmi *)context;
92 pr_info("HDCP: firmware is not loaded\n");
95 if (fw->size < HDCP_KEY_SIZE) {
96 pr_err("HDCP: firmware wrong size %d\n", (int)fw->size);
99 hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
100 memcpy(hdcp->keys, fw->data, HDCP_KEY_SIZE);
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");
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");
112 memcpy(hdcp->seeds, fw->data + HDCP_KEY_SIZE,
115 hdcp_load_key(hdmi, hdcp->keys);
118 void rockchip_hdmiv2_hdcp2_enable(int enable)
120 struct hdmi_dev *hdmi_dev;
123 pr_err("rockchip hdmiv2 hdcp is not exist\n");
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);
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);
145 EXPORT_SYMBOL(rockchip_hdmiv2_hdcp2_enable);
147 void rockchip_hdmiv2_hdcp2_init(void (*hdcp2_enble)(int),
148 void (*hdcp2_reset)(void),
149 void (*hdcp2_start)(void))
151 struct hdmi_dev *hdmi_dev;
154 pr_err("rockchip hdmiv2 hdcp is not exist\n");
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;
162 EXPORT_SYMBOL(rockchip_hdmiv2_hdcp2_init);
164 static void rockchip_hdmiv2_hdcp_start(struct hdmi *hdmi)
166 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
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);
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);
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) |
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));
203 hdmi_writel(hdmi_dev, A_APIINTMSK, 0x00);
204 hdmi_msk_reg(hdmi_dev, A_HDCPCFG0, m_RX_DETECT, v_RX_DETECT(1));
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__);
213 static void rockchip_hdmiv2_hdcp_stop(struct hdmi *hdmi)
215 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
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);
227 static ssize_t hdcp_enable_read(struct device *device,
228 struct device_attribute *attr, char *buf)
233 enable = hdcp->enable;
235 return snprintf(buf, PAGE_SIZE, "%d\n", enable);
238 static ssize_t hdcp_enable_write(struct device *device,
239 struct device_attribute *attr,
240 const char *buf, size_t count)
246 if (hdcp->keys == NULL) {
247 pr_err("HDCP: key is not loaded\n");
250 if (kstrtoint(buf, 0, &enable))
253 if (hdcp->enable != enable) {
255 hdmi_submit_work(hdcp->hdmi, HDMI_ENABLE_HDCP, 0, NULL);
257 rockchip_hdmiv2_hdcp_stop(hdcp->hdmi);
258 hdcp->enable = enable;
263 static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR,
264 hdcp_enable_read, hdcp_enable_write);
266 static ssize_t hdcp_trytimes_read(struct device *device,
267 struct device_attribute *attr, char *buf)
272 trytimes = hdcp->retry_times;
274 return snprintf(buf, PAGE_SIZE, "%d\n", trytimes);
277 static ssize_t hdcp_trytimes_wrtie(struct device *device,
278 struct device_attribute *attr,
279 const char *buf, size_t count)
286 if (kstrtoint(buf, 0, &trytimes))
289 if (hdcp->retry_times != trytimes)
290 hdcp->retry_times = trytimes;
294 static DEVICE_ATTR(trytimes, S_IRUGO|S_IWUSR,
295 hdcp_trytimes_read, hdcp_trytimes_wrtie);
297 static int hdcp_init(struct hdmi *hdmi)
300 struct hdmi_dev *hdmi_dev = hdmi->property->priv;
302 mdev.minor = MISC_DYNAMIC_MINOR;
305 hdcp = kmalloc(sizeof(*hdcp), GFP_KERNEL);
307 pr_err("HDCP: kmalloc fail!\n");
311 memset(hdcp, 0, sizeof(struct hdcp));
313 if (misc_register(&mdev)) {
314 pr_err("HDCP: Could not add character driver\n");
315 ret = HDMI_ERROR_FALSE;
318 ret = device_create_file(mdev.this_device, &dev_attr_enable);
320 pr_err("HDCP: Could not add sys file enable\n");
324 ret = device_create_file(mdev.this_device, &dev_attr_trytimes);
326 pr_err("HDCP: Could not add sys file enable\n");
331 ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
332 "hdcp", mdev.this_device, GFP_KERNEL,
333 hdmi, hdcp_load_keys_cb);
336 pr_err("HDCP: request_firmware_nowait failed: %d\n", ret);
339 if ((hdmi_readl(hdmi_dev, MC_CLKDIS) & m_HDCPCLK_DISABLE) == 0)
341 hdmi->ops->hdcp_cb = rockchip_hdmiv2_hdcp_start;
345 device_remove_file(mdev.this_device, &dev_attr_trytimes);
347 device_remove_file(mdev.this_device, &dev_attr_enable);
349 misc_deregister(&mdev);
352 kfree(hdcp->invalidkeys);
358 void rockchip_hdmiv2_hdcp_init(struct hdmi *hdmi)
360 pr_info("%s", __func__);
364 hdcp_load_key(hdmi, hdcp->keys);