2 * drivers/video/rockchip/hdmi/chips/rk3288/rk3188_hdmi.c
4 * Copyright (C) 2014 ROCKCHIP, Inc.
5 *Author:zwl<zwl@rock-chips.com>
6 *This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/delay.h>
17 #include <linux/interrupt.h>
18 #include <linux/clk.h>
19 #include <linux/uaccess.h>
20 #include <linux/rockchip/grf.h>
21 #include <linux/rockchip/iomap.h>
22 #if defined(CONFIG_OF)
24 #include <linux/of_device.h>
26 #if defined(CONFIG_DEBUG_FS)
28 #include <linux/debugfs.h>
29 #include <linux/seq_file.h>
32 #include "rk3288_hdmi_hw.h"
33 #include "rk3288_hdmi.h"
35 #define grf_readl(offset) readl_relaxed(RK_GRF_VIRT + offset)
36 #define grf_writel(v, offset) \
38 writel_relaxed(v, RK_GRF_VIRT + offset); \
41 #define HDMI_PD_ON (1 << 0)
42 #define HDMI_PCLK_ON (1 << 1)
43 #define HDMI_HDCPCLK_ON (1 << 2)
46 static struct rk3288_hdmi_device *hdmi_dev;
48 #if defined(CONFIG_DEBUG_FS)
49 static const struct rk3288_hdmi_reg_table hdmi_reg_table[] = {
50 {IDENTIFICATION_BASE, CONFIG3_ID},
51 {INTERRUPT_BASE, IH_MUTE},
52 {VIDEO_SAMPLER_BASE, TX_BCBDATA1},
53 {VIDEO_PACKETIZER_BASE, VP_MASK},
54 {FRAME_COMPOSER_BASE, FC_DBGTMDS2},
55 {HDMI_SOURCE_PHY_BASE, PHY_PLLCFGFREQ2},
56 {I2C_MASTER_PHY_BASE, PHY_I2CM_SDA_HOLD},
57 {AUDIO_SAMPLER_BASE, AHB_DMA_STPADDR_SET1_0},
58 {MAIN_CONTROLLER_BASE, MC_SWRSTZREQ_2},
59 {COLOR_SPACE_CONVERTER_BASE, CSC_SPARE_2},
60 {HDCP_ENCRYPTION_ENGINE_BASE, HDCP_REVOC_LIST},
61 {HDCP_BKSV_BASE, HDCPREG_BKSV4},
62 {HDCP_AN_BASE, HDCPREG_AN7},
63 {ENCRYPTED_DPK_EMBEDDED_BASE, HDCPREG_DPK6},
64 {CEC_ENGINE_BASE, CEC_WKUPCTRL},
65 {I2C_MASTER_BASE, I2CM_SCDC_UPDATE1},
68 static int rk3288_hdmi_reg_show(struct seq_file *s, void *v)
73 seq_puts(s, "\n>>>hdmi_ctl reg");
74 for (i = 0; i < 16; i++)
75 seq_printf(s, " %2x", i);
78 "\n-----------------------------------------------------------------");
80 for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
81 for (j = hdmi_reg_table[i].reg_base;
82 j <= hdmi_reg_table[i].reg_end; j++) {
83 val = hdmi_readl(hdmi_dev, j);
84 if ((j - hdmi_reg_table[i].reg_base) % 16 == 0)
85 seq_printf(s, "\n>>>hdmi_ctl %2x:", j);
86 seq_printf(s, " %02x", val);
91 "\n-----------------------------------------------------------------\n");
96 static ssize_t rk3288_hdmi_reg_write(struct file *file, const char __user *buf,
97 size_t count, loff_t *ppos)
103 if (copy_from_user(kbuf, buf, count))
105 sscanf(kbuf, "%x%x", ®, &val);
106 if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
107 dev_info(hdmi_dev->dev, "it is no hdmi reg\n");
110 dev_info(hdmi_dev->dev, "/**********rk3288 hdmi reg config******/");
111 dev_info(hdmi_dev->dev, "\n reg=%x val=%x\n", reg, val);
112 hdmi_writel(hdmi_dev, reg, val);
117 static int rk3288_hdmi_reg_open(struct inode *inode, struct file *file)
119 struct rk3288_hdmi_device *hdmi_dev = inode->i_private;
121 return single_open(file, rk3288_hdmi_reg_show, hdmi_dev);
124 static const struct file_operations rk3288_hdmi_reg_fops = {
125 .owner = THIS_MODULE,
126 .open = rk3288_hdmi_reg_open,
128 .write = rk3288_hdmi_reg_write,
130 .release = single_release,
134 struct hdmi *rk3288_hdmi_register_hdcp_callbacks(void (*hdcp_cb) (void),
135 void (*hdcp_irq_cb) (int status),
136 int (*hdcp_power_on_cb) (void),
137 void (*hdcp_power_off_cb) (void))
139 struct hdmi *hdmi_drv = NULL;
141 if (hdmi_dev == NULL)
144 hdmi_drv = &hdmi_dev->driver;
145 hdmi_drv->hdcp_cb = hdcp_cb;
146 hdmi_drv->hdcp_irq_cb = hdcp_irq_cb;
147 hdmi_drv->hdcp_power_on_cb = hdcp_power_on_cb;
148 hdmi_drv->hdcp_power_off_cb = hdcp_power_off_cb;
153 #ifdef HDMI_INT_USE_POLL
154 #define HDMI_POLL_MDELAY 100
155 static void rk3288_poll_delay_work(struct work_struct *work)
157 struct hdmi *hdmi_drv = &hdmi_dev->driver;
159 if (hdmi_drv->suspend == 0) {
160 if (hdmi_drv->enable == 1)
161 hdmi_irq(0, hdmi_drv);
163 if (hdmi_dev->irq == 0)
164 queue_delayed_work(hdmi_drv->workqueue,
165 &hdmi_dev->delay_work,
166 msecs_to_jiffies(HDMI_POLL_MDELAY));
171 static int rk3288_hdmi_clk_enable(struct rk3288_hdmi_device *hdmi_dev)
173 if ((hdmi_dev->clk_on & HDMI_PD_ON) && (hdmi_dev->clk_on & HDMI_PCLK_ON)
174 && (hdmi_dev->clk_on & HDMI_HDCPCLK_ON))
177 if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0) {
178 if (hdmi_dev->pd == NULL) {
179 hdmi_dev->pd = devm_clk_get(hdmi_dev->dev, "pd_hdmi");
180 if (IS_ERR(hdmi_dev->pd)) {
181 dev_err(hdmi_dev->dev,
182 "Unable to get hdmi pd\n");
186 clk_prepare_enable(hdmi_dev->pd);
187 hdmi_dev->clk_on |= HDMI_PD_ON;
190 if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
191 if (hdmi_dev->pclk == NULL) {
193 devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
194 if (IS_ERR(hdmi_dev->pclk)) {
195 dev_err(hdmi_dev->dev,
196 "Unable to get hdmi pclk\n");
200 clk_prepare_enable(hdmi_dev->pclk);
201 hdmi_dev->clk_on |= HDMI_PCLK_ON;
204 if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
205 if (hdmi_dev->hdcp_clk == NULL) {
207 devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
208 if (IS_ERR(hdmi_dev->hdcp_clk)) {
209 dev_err(hdmi_dev->dev,
210 "Unable to get hdmi hdcp_clk\n");
214 clk_prepare_enable(hdmi_dev->hdcp_clk);
215 hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
221 static int rk3288_hdmi_clk_disable(struct rk3288_hdmi_device *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) && (hdmi_dev->pclk != NULL)) {
232 clk_disable_unprepare(hdmi_dev->pclk);
233 hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
236 if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON)
237 && (hdmi_dev->hdcp_clk != NULL)) {
238 clk_disable_unprepare(hdmi_dev->hdcp_clk);
239 hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
245 static int rk3288_hdmi_drv_init(struct hdmi *hdmi_drv)
248 struct rk_screen screen;
250 rk_fb_get_prmry_screen(&screen);
252 /* hdmi is extend as default,TODO modify if hdmi is primary */
253 hdmi_dev->lcdc_id = (screen.lcdc_id == 0) ? 1 : 0;
254 /* lcdc source select */
255 grf_writel(HDMI_SEL_LCDC(hdmi_dev->lcdc_id), RK3288_GRF_SOC_CON6);
256 if (hdmi_dev->lcdc_id == 0)
257 hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc0");
259 hdmi_drv->lcdc = rk_get_lcdc_drv("lcdc1");
260 if (IS_ERR(hdmi_drv->lcdc)) {
261 dev_err(hdmi_drv->dev,
262 "can not connect to video source lcdc\n");
267 hdmi_drv->xscale = 100;
268 hdmi_drv->yscale = 100;
270 spin_lock_init(&hdmi_drv->irq_lock);
271 mutex_init(&hdmi_drv->enable_mutex);
273 rk3288_hdmi_initial(hdmi_drv);
274 hdmi_sys_init(hdmi_drv);
275 hdmi_drv_register(hdmi_drv);
280 static void rk3288_hdmi_early_suspend(void)
282 struct hdmi *hdmi_drv = &hdmi_dev->driver;
284 if (hdmi_drv->suspend)
287 hdmi_dbg(hdmi_drv->dev, "hdmi enter early suspend pwr %d state %d\n",
288 hdmi_drv->pwr_mode, hdmi_drv->state);
289 flush_delayed_work(&hdmi_drv->delay_work);
290 mutex_lock(&hdmi_drv->enable_mutex);
291 hdmi_drv->suspend = 1;
292 if (!hdmi_drv->enable) {
293 mutex_unlock(&hdmi_drv->enable_mutex);
296 disable_irq(hdmi_drv->irq);
297 mutex_unlock(&hdmi_drv->enable_mutex);
298 hdmi_drv->command = HDMI_CONFIG_ENABLE;
299 init_completion(&hdmi_drv->complete);
301 queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work, 0);
302 wait_for_completion_interruptible_timeout(&hdmi_drv->complete,
303 msecs_to_jiffies(5000));
304 flush_delayed_work(&hdmi_drv->delay_work);
306 /* iomux to gpio and pull down when suspend */
307 pinctrl_select_state(hdmi_dev->dev->pins->p,
308 hdmi_dev->dev->pins->sleep_state);
309 rk3288_hdmi_clk_disable(hdmi_dev);
313 static void rk3288_hdmi_early_resume(void)
315 struct hdmi *hdmi_drv = &hdmi_dev->driver;
317 if (!hdmi_drv->suspend)
320 hdmi_dbg(hdmi_drv->dev, "hdmi enter early resume\n");
321 /* iomux to default state for hdmi use when resume */
322 pinctrl_select_state(hdmi_dev->dev->pins->p,
323 hdmi_dev->dev->pins->default_state);
324 rk3288_hdmi_clk_enable(hdmi_dev);
325 mutex_lock(&hdmi_drv->enable_mutex);
326 hdmi_drv->suspend = 0;
327 rk3288_hdmi_initial(hdmi_drv);
328 if (hdmi_dev->irq == 0) {
329 #ifdef HDMI_INT_USE_POLL
330 queue_delayed_work(hdmi_drv->workqueue, &hdmi_dev->delay_work,
331 msecs_to_jiffies(5));
333 } else if (hdmi_drv->enable) {
334 enable_irq(hdmi_drv->irq);
336 queue_delayed_work(hdmi_drv->workqueue, &hdmi_drv->delay_work,
337 msecs_to_jiffies(10));
338 mutex_unlock(&hdmi_drv->enable_mutex);
342 static int rk3288_hdmi_fb_event_notify(struct notifier_block *self,
343 unsigned long action, void *data)
345 struct fb_event *event = data;
346 int blank_mode = *((int *)event->data);
348 if (action == FB_EARLY_EVENT_BLANK) {
349 switch (blank_mode) {
350 case FB_BLANK_UNBLANK:
353 rk3288_hdmi_early_suspend();
356 } else if (action == FB_EVENT_BLANK) {
357 switch (blank_mode) {
358 case FB_BLANK_UNBLANK:
359 rk3288_hdmi_early_resume();
369 static struct notifier_block rk3288_hdmi_fb_notifier = {
370 .notifier_call = rk3288_hdmi_fb_event_notify,
373 #if defined(CONFIG_OF)
374 static int rk3288_hdmi_parse_dt(struct rk3288_hdmi_device *hdmi_dev)
377 struct device_node *np = hdmi_dev->dev->of_node;
379 if (!of_property_read_u32(np, "rockchips,hdmi_audio_source", &val))
380 hdmi_dev->driver.audio.type = val;
385 static const struct of_device_id rk3288_hdmi_dt_ids[] = {
386 {.compatible = "rockchip,rk3288-hdmi",},
391 static int rk3288_hdmi_probe(struct platform_device *pdev)
394 struct resource *res;
395 struct hdmi *dev_drv = NULL;
397 hdmi_dev = kzalloc(sizeof(struct rk3288_hdmi_device), GFP_KERNEL);
399 dev_err(&pdev->dev, ">>rk3288_hdmi_device kzalloc fail!");
403 hdmi_dev->dev = &pdev->dev;
404 platform_set_drvdata(pdev, hdmi_dev);
405 mutex_init(&hdmi_dev->int_mutex);
407 rk3288_hdmi_parse_dt(hdmi_dev);
408 /* TODO Daisen wait to add cec iomux */
410 /* enable pd and pclk and hdcp_clk */
411 if (rk3288_hdmi_clk_enable(hdmi_dev) < 0)
414 /* request and remap iomem */
415 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
417 dev_err(hdmi_dev->dev, "Unable to get register resource\n");
421 hdmi_dev->regbase_phy = res->start;
422 hdmi_dev->regsize_phy = resource_size(res);
423 hdmi_dev->regbase = devm_ioremap_resource(hdmi_dev->dev, res);
424 if (IS_ERR(hdmi_dev->regbase)) {
425 ret = PTR_ERR(hdmi_dev->regbase);
426 dev_err(hdmi_dev->dev, "cannot ioremap registers,err=%d\n",
431 /*init hdmi driver */
432 dev_drv = &hdmi_dev->driver;
433 dev_drv->dev = &pdev->dev;
434 if (rk3288_hdmi_drv_init(dev_drv))
437 dev_drv->workqueue = create_singlethread_workqueue("hdmi");
438 INIT_DELAYED_WORK(&(dev_drv->delay_work), hdmi_work);
440 hdmi_register_display_sysfs(dev_drv, NULL);
443 dev_drv->switch_hdmi.name = "hdmi";
444 switch_dev_register(&(dev_drv->switch_hdmi));
447 fb_register_client(&rk3288_hdmi_fb_notifier);
449 #ifndef HDMI_INT_USE_POLL
450 /* get and request the IRQ */
451 dev_drv->irq = platform_get_irq(pdev, 0);
452 if (dev_drv->irq <= 0) {
453 dev_err(hdmi_dev->dev,
454 "failed to get hdmi irq resource (%d).\n",
461 devm_request_irq(hdmi_dev->dev, dev_drv->irq, hdmi_irq, 0,
462 dev_name(hdmi_dev->dev), dev_drv);
464 dev_err(hdmi_dev->dev, "hdmi request_irq failed (%d).\n", ret);
469 INIT_DELAYED_WORK(&hdmi_dev->delay_work, rk3288_poll_delay_work);
470 queue_delayed_work(dev_drv->workqueue, &hdmi_dev->delay_work,
471 msecs_to_jiffies(1));
474 #if defined(CONFIG_DEBUG_FS)
475 hdmi_dev->debugfs_dir = debugfs_create_dir("rk3288-hdmi", NULL);
476 if (IS_ERR(hdmi_dev->debugfs_dir)) {
477 dev_err(hdmi_dev->dev,
478 "failed to create debugfs dir for rk3288 hdmi!\n");
480 debugfs_create_file("hdmi", S_IRUSR, hdmi_dev->debugfs_dir,
481 hdmi_dev, &rk3288_hdmi_reg_fops);
485 dev_info(hdmi_dev->dev, "rk3288 hdmi probe sucess.\n");
488 #ifndef HDMI_INT_USE_POLL
491 fb_unregister_client(&rk3288_hdmi_fb_notifier);
493 switch_dev_unregister(&(dev_drv->switch_hdmi));
495 hdmi_unregister_display_sysfs(dev_drv);
498 iounmap((void*)hdmi_dev->regbase);
499 release_mem_region(res->start, hdmi_dev->regsize_phy);
502 rk3288_hdmi_clk_disable(hdmi_dev);
503 dev_info(hdmi_dev->dev, "rk3288 hdmi probe error.\n");
509 static int rk3288_hdmi_remove(struct platform_device *pdev)
511 struct rk3288_hdmi_device *hdmi_dev = platform_get_drvdata(pdev);
512 struct hdmi *hdmi_drv = NULL;
515 hdmi_drv = &hdmi_dev->driver;
516 mutex_lock(&hdmi_drv->enable_mutex);
517 if (!hdmi_drv->suspend && hdmi_drv->enable)
518 disable_irq(hdmi_drv->irq);
519 mutex_unlock(&hdmi_drv->enable_mutex);
520 free_irq(hdmi_drv->irq, NULL);
522 flush_workqueue(hdmi_drv->workqueue);
523 destroy_workqueue(hdmi_drv->workqueue);
525 fb_unregister_client(&rk3288_hdmi_fb_notifier);
528 switch_dev_unregister(&(hdmi_drv->switch_hdmi));
530 hdmi_unregister_display_sysfs(hdmi_drv);
533 iounmap((void*)hdmi_drv->regbase);
534 release_mem_region(hdmi_drv->regbase_phy,
535 hdmi_drv->regsize_phy);
537 rk3288_hdmi_clk_disable(hdmi_dev);
538 fb_destroy_modelist(&hdmi_drv->edid.modelist);
539 kfree(hdmi_drv->edid.audio);
540 if (hdmi_drv->edid.specs) {
541 kfree(hdmi_drv->edid.specs->modedb);
542 kfree(hdmi_drv->edid.specs);
548 dev_info(hdmi_dev->dev, "rk3288 hdmi removed.\n");
552 static void rk3288_hdmi_shutdown(struct platform_device *pdev)
557 static struct platform_driver rk3288_hdmi_driver = {
558 .probe = rk3288_hdmi_probe,
559 .remove = rk3288_hdmi_remove,
561 .name = "rk3288-hdmi",
562 .owner = THIS_MODULE,
563 .of_match_table = of_match_ptr(rk3288_hdmi_dt_ids),
565 .shutdown = rk3288_hdmi_shutdown,
568 static int __init rk3288_hdmi_init(void)
570 return platform_driver_register(&rk3288_hdmi_driver);
573 static void __exit rk3288_hdmi_exit(void)
575 platform_driver_unregister(&rk3288_hdmi_driver);
578 device_initcall_sync(rk3288_hdmi_init);
579 module_exit(rk3288_hdmi_exit);