1 #include <linux/kernel.h>
2 #include <linux/delay.h>
3 #include <linux/module.h>
4 #include <linux/platform_device.h>
5 #include <linux/interrupt.h>
7 #include <linux/rockchip/grf.h>
8 #include <linux/rockchip/iomap.h>
9 #include <linux/mfd/syscon.h>
10 #if defined(CONFIG_DEBUG_FS)
11 #include <linux/uaccess.h>
13 #include <linux/debugfs.h>
14 #include <linux/seq_file.h>
17 #include "rockchip_hdmiv2.h"
18 #include "rockchip_hdmiv2_hw.h"
20 #define HDMI_SEL_LCDC(x) ((((x)&1)<<4)|(1<<20))
21 #define grf_writel(v, offset) writel_relaxed(v, RK_GRF_VIRT + offset)
23 static struct hdmi_dev *hdmi_dev;
25 static struct hdmi_property rk_hdmi_property = {
26 .videosrc = DISPLAY_SOURCE_LCDC0,
27 .display = DISPLAY_MAIN,
30 #if defined(CONFIG_DEBUG_FS)
31 static const struct rockchip_hdmiv2_reg_table hdmi_reg_table[] = {
32 {IDENTIFICATION_BASE, CONFIG3_ID},
33 {INTERRUPT_BASE, IH_MUTE},
34 {VIDEO_SAMPLER_BASE, TX_BCBDATA1},
35 {VIDEO_PACKETIZER_BASE, VP_MASK},
36 {FRAME_COMPOSER_BASE, FC_DBGTMDS2},
37 {HDMI_SOURCE_PHY_BASE, PHY_PLLCFGFREQ2},
38 {I2C_MASTER_PHY_BASE, PHY_I2CM_SDA_HOLD},
39 {AUDIO_SAMPLER_BASE, AHB_DMA_STPADDR_SET1_0},
40 {MAIN_CONTROLLER_BASE, MC_SWRSTZREQ_2},
41 {COLOR_SPACE_CONVERTER_BASE, CSC_SPARE_2},
42 {HDCP_ENCRYPTION_ENGINE_BASE, HDCP_REVOC_LIST},
43 {HDCP_BKSV_BASE, HDCPREG_BKSV4},
44 {HDCP_AN_BASE, HDCPREG_AN7},
45 {HDCP2REG_BASE, HDCP2REG_MUTE},
46 {ENCRYPTED_DPK_EMBEDDED_BASE, HDCPREG_DPK6},
47 {CEC_ENGINE_BASE, CEC_WKUPCTRL},
48 {I2C_MASTER_BASE, I2CM_SCDC_UPDATE1},
51 static int rockchip_hdmiv2_reg_show(struct seq_file *s, void *v)
56 seq_puts(s, "\n>>>hdmi_ctl reg ");
57 for (i = 0; i < 16; i++)
58 seq_printf(s, " %2x", i);
59 seq_puts(s, "\n-----------------------------------------------------------------");
61 for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
62 for (j = hdmi_reg_table[i].reg_base;
63 j <= hdmi_reg_table[i].reg_end; j++) {
64 val = hdmi_readl(hdmi_dev, j);
65 if ((j - hdmi_reg_table[i].reg_base)%16 == 0)
66 seq_printf(s, "\n>>>hdmi_ctl %04x:", j);
67 seq_printf(s, " %02x", val);
70 seq_puts(s, "\n-----------------------------------------------------------------\n");
72 /*rockchip_hdmiv2_dump_phy_regs(hdmi_dev);*/
76 static ssize_t rockchip_hdmiv2_reg_write(struct file *file,
77 const char __user *buf,
78 size_t count, loff_t *ppos)
84 if (copy_from_user(kbuf, buf, count))
86 if (sscanf(kbuf, "%x%x", ®, &val) == -1)
88 if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
89 dev_info(hdmi_dev->hdmi->dev, "it is no hdmi reg\n");
92 dev_info(hdmi_dev->hdmi->dev,
93 "/**********hdmi reg config******/");
94 dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
95 hdmi_writel(hdmi_dev, reg, val);
100 static int rockchip_hdmiv2_reg_open(struct inode *inode, struct file *file)
102 struct hdmi_dev *hdmi_dev = inode->i_private;
104 return single_open(file, rockchip_hdmiv2_reg_show, hdmi_dev);
107 static const struct file_operations rockchip_hdmiv2_reg_fops = {
108 .owner = THIS_MODULE,
109 .open = rockchip_hdmiv2_reg_open,
111 .write = rockchip_hdmiv2_reg_write,
113 .release = single_release,
117 #ifdef CONFIG_HAS_EARLYSUSPEND
118 static void rockchip_hdmiv2_early_suspend(struct early_suspend *h)
120 struct hdmi *hdmi = hdmi_dev->hdmi;
121 struct delay_work *delay_work;
122 struct pinctrl_state *gpio_state;
124 HDMIDBG("hdmi enter early suspend\n");
125 delay_work = hdmi_submit_work(hdmi, HDMI_SUSPEND_CTL, 0, NULL);
127 flush_delayed_work_sync(delay_work);
128 /* iomux to gpio and pull down when suspend */
129 gpio_state = pinctrl_lookup_state(hdmi_dev->dev->pins->p, "gpio");
130 pinctrl_select_state(hdmi_dev->dev->pins->p, gpio_state);
131 rockchip_hdmiv2_clk_disable(hdmi_dev);
134 static void rockchip_hdmiv2_early_resume(struct early_suspend *h)
136 struct hdmi *hdmi = hdmi_dev->hdmi;
138 HDMIDBG("hdmi exit early resume\n");
139 /* iomux to default state for hdmi use when resume */
140 pinctrl_select_state(hdmi_dev->dev->pins->p,
141 hdmi_dev->dev->pins->default_state);
142 rockchip_hdmiv2_clk_enable(hdmi_dev);
143 hdmi_dev_initial(hdmi_dev);
144 if (hdmi->ops->hdcp_power_on_cb)
145 hdmi->ops->hdcp_power_on_cb();
146 hdmi_submit_work(hdmi, HDMI_RESUME_CTL, 0, NULL);
150 #define HDMI_PD_ON (1 << 0)
151 #define HDMI_PCLK_ON (1 << 1)
152 #define HDMI_HDCPCLK_ON (1 << 2)
153 #define HDMI_CECCLK_ON (1 << 3)
155 static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
157 if ((hdmi_dev->clk_on & HDMI_PD_ON) &&
158 (hdmi_dev->clk_on & HDMI_PCLK_ON) &&
159 (hdmi_dev->clk_on & HDMI_HDCPCLK_ON))
162 if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0 &&
163 hdmi_dev->soctype == HDMI_SOC_RK3288) {
164 if (hdmi_dev->pd == NULL) {
165 hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
166 if (IS_ERR(hdmi_dev->pd)) {
167 dev_err(hdmi_dev->dev,
168 "Unable to get hdmi pd\n");
172 clk_prepare_enable(hdmi_dev->pd);
173 hdmi_dev->clk_on |= HDMI_PD_ON;
176 if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
177 if (hdmi_dev->pclk == NULL) {
179 devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
180 if (IS_ERR(hdmi_dev->pclk)) {
181 dev_err(hdmi_dev->dev,
182 "Unable to get hdmi pclk\n");
186 clk_prepare_enable(hdmi_dev->pclk);
187 hdmi_dev->clk_on |= HDMI_PCLK_ON;
190 if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
191 if (hdmi_dev->hdcp_clk == NULL) {
193 devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
194 if (IS_ERR(hdmi_dev->hdcp_clk)) {
195 dev_err(hdmi_dev->dev,
196 "Unable to get hdmi hdcp_clk\n");
200 clk_prepare_enable(hdmi_dev->hdcp_clk);
201 hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
204 if ((rk_hdmi_property.feature & SUPPORT_CEC) &&
205 (hdmi_dev->clk_on & HDMI_CECCLK_ON) == 0) {
206 if (hdmi_dev->cec_clk == NULL) {
208 devm_clk_get(hdmi_dev->dev, "cec_clk_hdmi");
209 if (IS_ERR(hdmi_dev->cec_clk)) {
210 dev_err(hdmi_dev->dev,
211 "Unable to get hdmi cec_clk\n");
215 clk_prepare_enable(hdmi_dev->cec_clk);
216 hdmi_dev->clk_on |= HDMI_CECCLK_ON;
221 static int rockchip_hdmiv2_clk_disable(struct hdmi_dev *hdmi_dev)
223 if (hdmi_dev->clk_on == 0)
226 if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->pd != NULL)) {
227 clk_disable_unprepare(hdmi_dev->pd);
228 hdmi_dev->clk_on &= ~HDMI_PD_ON;
231 if ((hdmi_dev->clk_on & HDMI_PCLK_ON) &&
232 (hdmi_dev->pclk != NULL)) {
233 clk_disable_unprepare(hdmi_dev->pclk);
234 hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
237 if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) &&
238 (hdmi_dev->hdcp_clk != NULL)) {
239 clk_disable_unprepare(hdmi_dev->hdcp_clk);
240 hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
246 static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
247 unsigned long action, void *data)
249 struct fb_event *event = data;
250 int blank_mode = *((int *)event->data);
251 struct hdmi *hdmi = hdmi_dev->hdmi;
252 struct delayed_work *delay_work;
254 if (action == FB_EARLY_EVENT_BLANK) {
255 switch (blank_mode) {
256 case FB_BLANK_UNBLANK:
259 HDMIDBG("suspend hdmi\n");
262 hdmi_submit_work(hdmi,
266 flush_delayed_work(delay_work);
267 rockchip_hdmiv2_clk_disable(hdmi_dev);
271 } else if (action == FB_EVENT_BLANK) {
272 switch (blank_mode) {
273 case FB_BLANK_UNBLANK:
274 HDMIDBG("resume hdmi\n");
276 rockchip_hdmiv2_clk_enable(hdmi_dev);
277 rockchip_hdmiv2_dev_initial(hdmi_dev);
278 if (hdmi->ops->hdcp_power_on_cb)
279 hdmi->ops->hdcp_power_on_cb();
280 hdmi_submit_work(hdmi, HDMI_RESUME_CTL,
291 static struct notifier_block rockchip_hdmiv2_fb_notifier = {
292 .notifier_call = rockchip_hdmiv2_fb_event_notify,
294 #ifdef HDMI_INT_USE_POLL
295 static void rockchip_hdmiv2_irq_work_func(struct work_struct *work)
297 if (hdmi_dev->enable) {
298 rockchip_hdmiv2_dev_irq(0, hdmi_dev);
299 queue_delayed_work(hdmi_dev->workqueue,
300 &(hdmi_dev->delay_work),
301 msecs_to_jiffies(50));
306 static struct hdmi_ops rk_hdmi_ops;
309 #if defined(CONFIG_OF)
310 static const struct of_device_id rk_hdmi_dt_ids[] = {
311 {.compatible = "rockchip,rk3288-hdmi",},
312 {.compatible = "rockchip,rk3368-hdmi",},
316 static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
319 struct device_node *np = hdmi_dev->dev->of_node;
320 const struct of_device_id *match;
322 match = of_match_node(rk_hdmi_dt_ids, np);
324 return PTR_ERR(match);
326 if (!strcmp(match->compatible, "rockchip,rk3288-hdmi")) {
327 hdmi_dev->soctype = HDMI_SOC_RK3288;
328 } else if (!strcmp(match->compatible, "rockchip,rk3368-hdmi")) {
329 hdmi_dev->soctype = HDMI_SOC_RK3368;
331 pr_err("It is not a valid rockchip soc!");
335 if (!of_property_read_u32(np, "rockchip,hdmi_video_source", &val))
336 rk_hdmi_property.videosrc = val;
338 if (!of_property_read_u32(np, "rockchip,hdmi_audio_source", &val))
339 hdmi_dev->audiosrc = val;
341 if (!of_property_read_u32(np, "rockchip,cec_enable", &val) &&
343 pr_info("hdmi support cec\n");
344 rk_hdmi_property.feature |= SUPPORT_CEC;
346 if (!of_property_read_u32(np, "rockchip,hdcp_enable", &val) &&
348 pr_info("hdmi support hdcp\n");
349 rk_hdmi_property.feature |= SUPPORT_HDCP;
351 #ifdef CONFIG_MFD_SYSCON
353 syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
359 static int rockchip_hdmiv2_probe(struct platform_device *pdev)
362 struct resource *res;
364 HDMIDBG("%s\n", __func__);
365 hdmi_dev = kmalloc(sizeof(*hdmi_dev), GFP_KERNEL);
367 dev_err(&pdev->dev, ">>rockchip hdmiv2 kmalloc fail!");
370 memset(hdmi_dev, 0, sizeof(struct hdmi_dev));
371 platform_set_drvdata(pdev, hdmi_dev);
372 hdmi_dev->dev = &pdev->dev;
374 rockchip_hdmiv2_parse_dt(hdmi_dev);
376 /*request and remap iomem*/
377 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
379 dev_err(&pdev->dev, "Unable to get register resource\n");
383 hdmi_dev->regbase_phy = res->start;
384 hdmi_dev->regsize_phy = resource_size(res);
385 hdmi_dev->regbase = devm_ioremap_resource(&pdev->dev, res);
386 if (IS_ERR(hdmi_dev->regbase)) {
387 ret = PTR_ERR(hdmi_dev->regbase);
389 "cannot ioremap registers,err=%d\n", ret);
393 /*enable pd and pclk and hdcp_clk*/
394 if (rockchip_hdmiv2_clk_enable(hdmi_dev) < 0) {
398 /*lcdc source select*/
399 if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
400 grf_writel(HDMI_SEL_LCDC(rk_hdmi_property.videosrc),
401 RK3288_GRF_SOC_CON6);
402 /* select GPIO7_C0 as cec pin */
403 grf_writel(((1 << 12) | (1 << 28)), RK3288_GRF_SOC_CON8);
405 rockchip_hdmiv2_dev_init_ops(&rk_hdmi_ops);
406 /* Register HDMI device */
407 rk_hdmi_property.name = (char *)pdev->name;
408 rk_hdmi_property.priv = hdmi_dev;
409 if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
410 /*rk_hdmi_property.feature |= SUPPORT_DEEP_10BIT;*/
411 if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
412 rk_hdmi_property.feature |=
415 } else if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
416 rk_hdmi_property.feature |=
422 rockchip_hdmi_register(&rk_hdmi_property, &rk_hdmi_ops);
423 if (hdmi_dev->hdmi == NULL) {
424 dev_err(&pdev->dev, "register hdmi device failed\n");
428 mutex_init(&hdmi_dev->ddc_lock);
429 hdmi_dev->hdmi->dev = &pdev->dev;
430 hdmi_dev->hdmi->soctype = hdmi_dev->soctype;
431 fb_register_client(&rockchip_hdmiv2_fb_notifier);
432 rockchip_hdmiv2_dev_initial(hdmi_dev);
433 pinctrl_select_state(hdmi_dev->dev->pins->p,
434 hdmi_dev->dev->pins->default_state);
435 #if defined(CONFIG_DEBUG_FS)
436 hdmi_dev->debugfs_dir = debugfs_create_dir("rockchip_hdmiv2", NULL);
437 if (IS_ERR(hdmi_dev->debugfs_dir))
438 dev_err(hdmi_dev->hdmi->dev,
439 "failed to create debugfs dir for rockchip hdmiv2!\n");
441 debugfs_create_file("hdmi", S_IRUSR,
442 hdmi_dev->debugfs_dir,
443 hdmi_dev, &rockchip_hdmiv2_reg_fops);
445 if (rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
446 rk_display_device_enable(hdmi_dev->hdmi->ddev);
448 #ifndef HDMI_INT_USE_POLL
449 /* get and request the IRQ */
450 hdmi_dev->irq = platform_get_irq(pdev, 0);
451 if (hdmi_dev->irq <= 0) {
452 dev_err(hdmi_dev->dev,
453 "failed to get hdmi irq resource (%d).\n",
460 devm_request_irq(hdmi_dev->dev, hdmi_dev->irq,
461 rockchip_hdmiv2_dev_irq,
463 dev_name(hdmi_dev->dev), hdmi_dev);
465 dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
469 hdmi_dev->workqueue =
470 create_singlethread_workqueue("rockchip hdmiv2 irq");
471 INIT_DELAYED_WORK(&(hdmi_dev->delay_work),
472 rockchip_hdmiv2_irq_work_func);
473 rockchip_hdmiv2_irq_work_func(NULL);
476 dev_info(&pdev->dev, "rockchip hdmiv2 probe sucess.\n");
480 rockchip_hdmi_unregister(hdmi_dev->hdmi);
484 dev_err(&pdev->dev, "rk3288 hdmi probe error.\n");
488 static int rockchip_hdmiv2_remove(struct platform_device *pdev)
490 dev_info(&pdev->dev, "rk3288 hdmi driver removed.\n");
494 static void rockchip_hdmiv2_shutdown(struct platform_device *pdev)
499 #ifdef CONFIG_HAS_EARLYSUSPEND
500 unregister_early_suspend(&hdmi_dev->early_suspend);
502 hdmi = hdmi_dev->hdmi;
503 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
505 hdmi->ops->setmute(hdmi, HDMI_VIDEO_MUTE);
509 static struct platform_driver rockchip_hdmiv2_driver = {
510 .probe = rockchip_hdmiv2_probe,
511 .remove = rockchip_hdmiv2_remove,
513 .name = "rockchip-hdmiv2",
514 .owner = THIS_MODULE,
515 #if defined(CONFIG_OF)
516 .of_match_table = of_match_ptr(rk_hdmi_dt_ids),
519 .shutdown = rockchip_hdmiv2_shutdown,
522 static int __init rockchip_hdmiv2_init(void)
524 return platform_driver_register(&rockchip_hdmiv2_driver);
527 static void __exit rockchip_hdmiv2_exit(void)
529 platform_driver_unregister(&rockchip_hdmiv2_driver);
532 module_init(rockchip_hdmiv2_init);
533 module_exit(rockchip_hdmiv2_exit);