video: rockchip: add auto dp support for vr product
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmiv2 / rockchip_hdmiv2.c
1 #include <linux/kernel.h>
2 #include <linux/delay.h>
3 #include <linux/module.h>
4 #include <linux/platform_device.h>
5 #include <linux/pm_runtime.h>
6 #include <linux/interrupt.h>
7 #include <linux/clk.h>
8 #include <linux/of_gpio.h>
9 #include <linux/rockchip/cpu.h>
10 #include <linux/rockchip/grf.h>
11 #include <linux/rockchip/iomap.h>
12 #include <linux/mfd/syscon.h>
13 #if defined(CONFIG_DEBUG_FS)
14 #include <linux/uaccess.h>
15 #include <linux/fs.h>
16 #include <linux/debugfs.h>
17 #include <linux/seq_file.h>
18 #endif
19
20 #include "rockchip_hdmiv2.h"
21 #include "rockchip_hdmiv2_hw.h"
22
23 static struct hdmi_dev *hdmi_dev;
24
25 static struct hdmi_property rk_hdmi_property = {
26         .videosrc = DISPLAY_SOURCE_LCDC0,
27         .display = DISPLAY_MAIN,
28 };
29
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},
49 };
50
51 static int hdmi_regs_ctrl_show(struct seq_file *s, void *v)
52 {
53         u32 i = 0, j = 0, val = 0;
54
55         seq_puts(s, "\n>>>hdmi_ctl reg ");
56         for (i = 0; i < 16; i++)
57                 seq_printf(s, " %2x", i);
58         seq_puts(s, "\n-----------------------------------------------------------------");
59
60         for (i = 0; i < ARRAY_SIZE(hdmi_reg_table); i++) {
61                 for (j = hdmi_reg_table[i].reg_base;
62                      j <= hdmi_reg_table[i].reg_end; j++) {
63                         val = hdmi_readl(hdmi_dev, j);
64                         if ((j - hdmi_reg_table[i].reg_base) % 16 == 0)
65                                 seq_printf(s, "\n>>>hdmi_ctl %04x:", j);
66                         seq_printf(s, " %02x", val);
67                 }
68         }
69         seq_puts(s, "\n-----------------------------------------------------------------\n");
70
71         return 0;
72 }
73
74 static ssize_t hdmi_regs_ctrl_write(struct file *file,
75                                     const char __user *buf,
76                                     size_t count, loff_t *ppos)
77 {
78         u32 reg, val;
79         char kbuf[25];
80
81         if (copy_from_user(kbuf, buf, count))
82                 return -EFAULT;
83         if (sscanf(kbuf, "%x%x", &reg, &val) == -1)
84                 return -EFAULT;
85         if ((reg < 0) || (reg > I2CM_SCDC_UPDATE1)) {
86                 dev_info(hdmi_dev->hdmi->dev, "it is no hdmi reg\n");
87                 return count;
88         }
89         dev_info(hdmi_dev->hdmi->dev,
90                  "/**********hdmi reg config******/");
91         dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
92         hdmi_writel(hdmi_dev, reg, val);
93
94         return count;
95 }
96
97 static int hdmi_regs_phy_show(struct seq_file *s, void *v)
98 {
99         u32 i, count;
100
101         if (hdmi_dev->soctype == HDMI_SOC_RK322X)
102                 count = 0xff;
103         else
104                 count = 0x28;
105         seq_puts(s, "\n>>>hdmi_phy reg ");
106         for (i = 0; i < count; i++)
107                 seq_printf(s, "regs %02x val %04x\n",
108                            i, rockchip_hdmiv2_read_phy(hdmi_dev, i));
109         return 0;
110 }
111
112 static ssize_t hdmi_regs_phy_write(struct file *file,
113                                    const char __user *buf,
114                                    size_t count, loff_t *ppos)
115 {
116         u32 reg, val;
117         char kbuf[25];
118
119         if (copy_from_user(kbuf, buf, count))
120                 return -EFAULT;
121         if (sscanf(kbuf, "%x%x", &reg, &val) == -1)
122                 return -EFAULT;
123         dev_info(hdmi_dev->hdmi->dev,
124                  "/**********hdmi reg phy config******/");
125         dev_info(hdmi_dev->hdmi->dev, "\n reg=%x val=%x\n", reg, val);
126         rockchip_hdmiv2_write_phy(hdmi_dev, reg, val);
127         return count;
128 }
129
130 #define HDMI_DEBUG_ENTRY(name) \
131 static int hdmi_##name##_open(struct inode *inode, struct file *file) \
132 { \
133         return single_open(file, hdmi_##name##_show, inode->i_private); \
134 } \
135 \
136 static const struct file_operations hdmi_##name##_fops = { \
137         .owner = THIS_MODULE, \
138         .open = hdmi_##name##_open, \
139         .read = seq_read, \
140         .write = hdmi_##name##_write,   \
141         .llseek = seq_lseek, \
142         .release = single_release, \
143 }
144
145 HDMI_DEBUG_ENTRY(regs_phy);
146 HDMI_DEBUG_ENTRY(regs_ctrl);
147 #endif
148
149 #ifdef CONFIG_HAS_EARLYSUSPEND
150 static void rockchip_hdmiv2_early_suspend(struct early_suspend *h)
151 {
152         struct hdmi *hdmi = hdmi_dev->hdmi;
153         struct pinctrl_state *gpio_state;
154
155         HDMIDBG("hdmi enter early suspend\n");
156         hdmi_submit_work(hdmi, HDMI_SUSPEND_CTL, 0, 1);
157         /* iomux to gpio and pull down when suspend */
158         gpio_state = pinctrl_lookup_state(hdmi_dev->dev->pins->p, "gpio");
159         pinctrl_select_state(hdmi_dev->dev->pins->p, gpio_state);
160         rockchip_hdmiv2_clk_disable(hdmi_dev);
161 }
162
163 static void rockchip_hdmiv2_early_resume(struct early_suspend *h)
164 {
165         struct hdmi *hdmi = hdmi_dev->hdmi;
166
167         HDMIDBG("hdmi exit early resume\n");
168         /* iomux to default state for hdmi use when resume */
169         pinctrl_select_state(hdmi_dev->dev->pins->p,
170                              hdmi_dev->dev->pins->default_state);
171         rockchip_hdmiv2_clk_enable(hdmi_dev);
172         hdmi_dev_initial(hdmi_dev);
173         if (hdmi->ops->hdcp_power_on_cb)
174                 hdmi->ops->hdcp_power_on_cb();
175         hdmi_submit_work(hdmi, HDMI_RESUME_CTL, 0, 0);
176 }
177 #endif
178
179 void ext_pll_set_27m_out(void)
180 {
181         if (!hdmi_dev || hdmi_dev->soctype != HDMI_SOC_RK322X)
182                 return;
183         /* PHY PLL VCO is 1080MHz, output pclk is 27MHz */
184         rockchip_hdmiv2_write_phy(hdmi_dev,
185                                   EXT_PHY_PLL_PRE_DIVIDER,
186                                   1);
187         rockchip_hdmiv2_write_phy(hdmi_dev,
188                                   EXT_PHY_PLL_FB_DIVIDER,
189                                   45);
190         rockchip_hdmiv2_write_phy(hdmi_dev,
191                                   EXT_PHY_PCLK_DIVIDER1,
192                                   0x61);
193         rockchip_hdmiv2_write_phy(hdmi_dev,
194                                   EXT_PHY_PCLK_DIVIDER2,
195                                   0x64);
196         rockchip_hdmiv2_write_phy(hdmi_dev,
197                                   EXT_PHY_TMDSCLK_DIVIDER,
198                                   0x1d);
199 }
200
201 static int rockchip_hdmiv2_clk_enable(struct hdmi_dev *hdmi_dev)
202 {
203         if ((hdmi_dev->clk_on & HDMI_PD_ON) == 0) {
204                 pm_runtime_get_sync(hdmi_dev->dev);
205                 hdmi_dev->clk_on |= HDMI_PD_ON;
206         }
207
208         if (hdmi_dev->soctype == HDMI_SOC_RK322X ||
209             hdmi_dev->soctype == HDMI_SOC_RK3366 ||
210             hdmi_dev->soctype == HDMI_SOC_RK3399) {
211                 if ((hdmi_dev->clk_on & HDMI_EXT_PHY_CLK_ON) == 0) {
212                         if (!hdmi_dev->pclk_phy) {
213                                 if (hdmi_dev->soctype == HDMI_SOC_RK322X)
214                                         hdmi_dev->pclk_phy =
215                                                 devm_clk_get(hdmi_dev->dev,
216                                                              "pclk_hdmi_phy");
217                                 else
218                                         hdmi_dev->pclk_phy =
219                                                 devm_clk_get(hdmi_dev->dev,
220                                                              "dclk_hdmi_phy");
221                                 if (IS_ERR(hdmi_dev->pclk_phy)) {
222                                         dev_err(hdmi_dev->dev,
223                                                 "get hdmi phy pclk error\n");
224                                         return -1;
225                                 }
226                         }
227                         clk_prepare_enable(hdmi_dev->pclk_phy);
228                         hdmi_dev->clk_on |= HDMI_EXT_PHY_CLK_ON;
229                 }
230         }
231         if ((hdmi_dev->clk_on & HDMI_PCLK_ON) == 0) {
232                 if (!hdmi_dev->pclk) {
233                         hdmi_dev->pclk =
234                                 devm_clk_get(hdmi_dev->dev, "pclk_hdmi");
235                         if (IS_ERR(hdmi_dev->pclk)) {
236                                 dev_err(hdmi_dev->dev,
237                                         "Unable to get hdmi pclk\n");
238                                 return -1;
239                         }
240                 }
241                 clk_prepare_enable(hdmi_dev->pclk);
242                 hdmi_dev->clk_on |= HDMI_PCLK_ON;
243         }
244
245         if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) == 0) {
246                 if (!hdmi_dev->hdcp_clk) {
247                         hdmi_dev->hdcp_clk =
248                                 devm_clk_get(hdmi_dev->dev, "hdcp_clk_hdmi");
249                         if (IS_ERR(hdmi_dev->hdcp_clk)) {
250                                 dev_err(hdmi_dev->dev,
251                                         "Unable to get hdmi hdcp_clk\n");
252                                 return -1;
253                         }
254                 }
255                 clk_prepare_enable(hdmi_dev->hdcp_clk);
256                 hdmi_dev->clk_on |= HDMI_HDCPCLK_ON;
257         }
258
259         if ((rk_hdmi_property.feature & SUPPORT_CEC) &&
260             (hdmi_dev->clk_on & HDMI_CECCLK_ON) == 0) {
261                 if (!hdmi_dev->cec_clk) {
262                         hdmi_dev->cec_clk =
263                                 devm_clk_get(hdmi_dev->dev, "cec_clk_hdmi");
264                         if (IS_ERR(hdmi_dev->cec_clk)) {
265                                 dev_err(hdmi_dev->dev,
266                                         "Unable to get hdmi cec_clk\n");
267                                 return -1;
268                         }
269                 }
270                 clk_prepare_enable(hdmi_dev->cec_clk);
271                 hdmi_dev->clk_on |= HDMI_CECCLK_ON;
272         }
273
274         if ((hdmi_dev->clk_on & HDMI_SFRCLK_ON) == 0) {
275                 if (!hdmi_dev->sfr_clk) {
276                         hdmi_dev->sfr_clk =
277                                 devm_clk_get(hdmi_dev->dev, "sclk_hdmi_sfr");
278                         if (IS_ERR(hdmi_dev->sfr_clk)) {
279                                 dev_err(hdmi_dev->dev,
280                                         "Unable to get hdmi sfr_clk\n");
281                                 return -1;
282                         }
283                 }
284                 clk_prepare_enable(hdmi_dev->sfr_clk);
285                 hdmi_dev->clk_on |= HDMI_SFRCLK_ON;
286         }
287
288         return 0;
289 }
290
291 static int rockchip_hdmiv2_clk_disable(struct hdmi_dev *hdmi_dev)
292 {
293         if (hdmi_dev->clk_on == 0)
294                 return 0;
295
296         if ((hdmi_dev->clk_on & HDMI_PD_ON)) {
297                 pm_runtime_put(hdmi_dev->dev);
298                 hdmi_dev->clk_on &= ~HDMI_PD_ON;
299         }
300
301         if ((hdmi_dev->clk_on & HDMI_PCLK_ON) &&
302             (hdmi_dev->pclk)) {
303                 clk_disable_unprepare(hdmi_dev->pclk);
304                 hdmi_dev->clk_on &= ~HDMI_PCLK_ON;
305         }
306
307         if ((hdmi_dev->clk_on & HDMI_HDCPCLK_ON) &&
308             (hdmi_dev->hdcp_clk)) {
309                 clk_disable_unprepare(hdmi_dev->hdcp_clk);
310                 hdmi_dev->clk_on &= ~HDMI_HDCPCLK_ON;
311         }
312
313         if ((hdmi_dev->clk_on & HDMI_EXT_PHY_CLK_ON) &&
314             hdmi_dev->pclk_phy) {
315                 clk_disable_unprepare(hdmi_dev->pclk_phy);
316                 hdmi_dev->clk_on &= ~HDMI_EXT_PHY_CLK_ON;
317         }
318
319         if ((hdmi_dev->clk_on & HDMI_SFRCLK_ON) &&
320             (hdmi_dev->sfr_clk)) {
321                 clk_disable_unprepare(hdmi_dev->sfr_clk);
322                 hdmi_dev->clk_on &= ~HDMI_SFRCLK_ON;
323         }
324
325
326         return 0;
327 }
328
329 static int rockchip_hdmiv2_fb_event_notify(struct notifier_block *self,
330                                            unsigned long action, void *data)
331 {
332         struct fb_event *event = data;
333         struct hdmi *hdmi = hdmi_dev->hdmi;
334         struct pinctrl_state *gpio_state;
335 #ifdef CONFIG_PINCTRL
336         struct dev_pin_info *pins = hdmi_dev->dev->pins;
337 #endif
338
339         if (action == FB_EARLY_EVENT_BLANK) {
340                 switch (*((int *)event->data)) {
341                 case FB_BLANK_UNBLANK:
342                         break;
343                 default:
344                         HDMIDBG("suspend hdmi\n");
345                         if (!hdmi->sleep) {
346                                 hdmi_submit_work(hdmi,
347                                                  HDMI_SUSPEND_CTL,
348                                                  0, 1);
349                                 if (hdmi_dev->hdcp2_en)
350                                         hdmi_dev->hdcp2_en(0);
351                                 mutex_lock(&hdmi->pclk_lock);
352                                 rockchip_hdmiv2_clk_disable(hdmi_dev);
353                                 mutex_unlock(&hdmi->pclk_lock);
354                                 #ifdef CONFIG_PINCTRL
355                                 if (hdmi_dev->soctype == HDMI_SOC_RK3288)
356                                         gpio_state =
357                                         pinctrl_lookup_state(pins->p,
358                                                              "sleep");
359                                 else
360                                         gpio_state =
361                                         pinctrl_lookup_state(pins->p,
362                                                              "gpio");
363                                 pinctrl_select_state(pins->p,
364                                                      gpio_state);
365                                 #endif
366                         }
367                         break;
368                 }
369         } else if (action == FB_EVENT_BLANK) {
370                 switch (*((int *)event->data)) {
371                 case FB_BLANK_UNBLANK:
372                         HDMIDBG("resume hdmi\n");
373                         if (hdmi->sleep) {
374                                 #ifdef CONFIG_PINCTRL
375                                 pinctrl_select_state(pins->p,
376                                                      pins->default_state);
377                                 #endif
378                                 mutex_lock(&hdmi->pclk_lock);
379                                 rockchip_hdmiv2_clk_enable(hdmi_dev);
380                                 mutex_unlock(&hdmi->pclk_lock);
381                                 rockchip_hdmiv2_dev_initial(hdmi_dev);
382                                 if (hdmi->ops->hdcp_power_on_cb)
383                                         hdmi->ops->hdcp_power_on_cb();
384                                 if (hdmi_dev->hdcp2_reset)
385                                         hdmi_dev->hdcp2_reset();
386                                 if (hdmi_dev->hdcp2_en)
387                                         hdmi_dev->hdcp2_en(1);
388                                 hdmi_submit_work(hdmi, HDMI_RESUME_CTL,
389                                                  0, 0);
390                         }
391                         break;
392                 default:
393                         break;
394                 }
395         }
396         return NOTIFY_OK;
397 }
398
399 static struct notifier_block rockchip_hdmiv2_fb_notifier = {
400         .notifier_call = rockchip_hdmiv2_fb_event_notify,
401 };
402
403 #ifdef HDMI_INT_USE_POLL
404 static void rockchip_hdmiv2_irq_work_func(struct work_struct *work)
405 {
406         if (hdmi_dev->enable) {
407                 rockchip_hdmiv2_dev_irq(0, hdmi_dev);
408                 queue_delayed_work(hdmi_dev->workqueue,
409                                    &hdmi_dev->delay_work,
410                                    msecs_to_jiffies(50));
411         }
412 }
413 #endif
414
415 static struct hdmi_ops rk_hdmi_ops;
416
417 #if defined(CONFIG_OF)
418 static const struct of_device_id rk_hdmi_dt_ids[] = {
419         {.compatible = "rockchip,rk322x-hdmi",},
420         {.compatible = "rockchip,rk3288-hdmi",},
421         {.compatible = "rockchip,rk3366-hdmi",},
422         {.compatible = "rockchip,rk3368-hdmi",},
423         {.compatible = "rockchip,rk3399-hdmi",},
424         {}
425 };
426
427 static int hdmi_get_prop_dts(struct hdmi *hdmi, struct device_node *np)
428 {
429         const struct property *prop;
430         int i = 0, nstates = 0;
431         const __be32 *val;
432         int value;
433         struct edid_prop_value *pval = NULL;
434
435         if (!hdmi || !np) {
436                 pr_info("%s:line=%d hdmi or np is null\n", __func__, __LINE__);
437                 return -1;
438         }
439
440         if (!of_property_read_u32(np, "hdmi_edid_auto_support", &value))
441                 hdmi->edid_auto_support = value;
442
443         prop = of_find_property(np, "hdmi_edid_prop_value", NULL);
444         if (!prop || !prop->value) {
445                 pr_info("%s:No edid-prop-value, %d\n", __func__, !prop);
446                 return -1;
447         }
448
449         nstates = (prop->length / sizeof(struct edid_prop_value));
450         pval = kcalloc(nstates, sizeof(struct edid_prop_value), GFP_NOWAIT);
451
452         for (i = 0, val = prop->value; i < nstates; i++) {
453                 pval[i].vid = be32_to_cpup(val++);
454                 pval[i].pid = be32_to_cpup(val++);
455                 pval[i].sn = be32_to_cpup(val++);
456                 pval[i].xres = be32_to_cpup(val++);
457                 pval[i].yres = be32_to_cpup(val++);
458                 pval[i].vic = be32_to_cpup(val++);
459                 pval[i].width = be32_to_cpup(val++);
460                 pval[i].height = be32_to_cpup(val++);
461                 pval[i].x_w = be32_to_cpup(val++);
462                 pval[i].x_h = be32_to_cpup(val++);
463                 pval[i].hwrotation = be32_to_cpup(val++);
464                 pval[i].einit = be32_to_cpup(val++);
465                 pval[i].vsync = be32_to_cpup(val++);
466                 pval[i].panel = be32_to_cpup(val++);
467                 pval[i].scan = be32_to_cpup(val++);
468
469                 pr_info("%s: 0x%x 0x%x 0x%x %d %d %d %d %d %d %d %d %d %d %d %d\n",
470                         __func__, pval[i].vid, pval[i].pid, pval[i].sn,
471                         pval[i].width, pval[i].height, pval[i].xres,
472                         pval[i].yres, pval[i].vic, pval[i].x_w,
473                         pval[i].x_h, pval[i].hwrotation, pval[i].einit,
474                         pval[i].vsync, pval[i].panel, pval[i].scan);
475         }
476
477         hdmi->pvalue = pval;
478         hdmi->nstates = nstates;
479
480         return 0;
481 }
482
483 static int rockchip_hdmiv2_parse_dt(struct hdmi_dev *hdmi_dev)
484 {
485         int val = 0;
486         struct device_node *np = hdmi_dev->dev->of_node;
487         const struct of_device_id *match;
488
489         match = of_match_node(rk_hdmi_dt_ids, np);
490         if (!match)
491                 return PTR_ERR(match);
492
493         if (!strcmp(match->compatible, "rockchip,rk3288-hdmi")) {
494                 hdmi_dev->soctype = HDMI_SOC_RK3288;
495         } else if (!strcmp(match->compatible, "rockchip,rk3368-hdmi")) {
496                 hdmi_dev->soctype = HDMI_SOC_RK3368;
497         } else if (!strcmp(match->compatible, "rockchip,rk322x-hdmi")) {
498                 hdmi_dev->soctype = HDMI_SOC_RK322X;
499         } else if (!strcmp(match->compatible, "rockchip,rk3366-hdmi")) {
500                 hdmi_dev->soctype = HDMI_SOC_RK3366;
501         } else if (!strcmp(match->compatible, "rockchip,rk3399-hdmi")) {
502                 hdmi_dev->soctype = HDMI_SOC_RK3399;
503         } else {
504                 pr_err("It is not a valid rockchip soc!");
505                 return -ENOMEM;
506         }
507
508         if (!of_property_read_u32(np, "rockchip,hdmi_video_source", &val))
509                 rk_hdmi_property.videosrc = val;
510
511         if (!of_property_read_u32(np, "rockchip,hdmi_audio_source", &val))
512                 hdmi_dev->audiosrc = val;
513
514         if (!of_property_read_u32(np, "rockchip,cec_enable", &val) &&
515             (val == 1)) {
516                 pr_debug("hdmi support cec\n");
517                 rk_hdmi_property.feature |= SUPPORT_CEC;
518         }
519         if (!of_property_read_u32(np, "rockchip,hdcp_enable", &val) &&
520             (val == 1)) {
521                 pr_debug("hdmi support hdcp\n");
522                 rk_hdmi_property.feature |= SUPPORT_HDCP;
523         }
524         if (!of_property_read_u32(np, "rockchip,defaultmode", &val) &&
525             (val > 0)) {
526                 pr_debug("default mode is %d\n", val);
527                 rk_hdmi_property.defaultmode = val;
528         } else {
529                 rk_hdmi_property.defaultmode = HDMI_VIDEO_DEFAULT_MODE;
530         }
531         if (of_get_property(np, "rockchip,phy_table", &val)) {
532                 hdmi_dev->phy_table = kmalloc(val, GFP_KERNEL);
533                 if (!hdmi_dev->phy_table) {
534                         pr_err("kmalloc phy table %d error\n", val);
535                         return -ENOMEM;
536                 }
537                 hdmi_dev->phy_table_size =
538                                 val / sizeof(struct hdmi_dev_phy_para);
539                 of_property_read_u32_array(np, "rockchip,phy_table",
540                                            (u32 *)hdmi_dev->phy_table,
541                                            val / sizeof(u32));
542         } else {
543                 pr_info("hdmi phy_table not exist\n");
544         }
545
546         of_property_read_string(np, "rockchip,vendor",
547                                 &hdmi_dev->vendor_name);
548         of_property_read_string(np, "rockchip,product",
549                                 &hdmi_dev->product_name);
550         if (!of_property_read_u32(np, "rockchip,deviceinfo", &val))
551                 hdmi_dev->deviceinfo = val & 0xff;
552
553         #ifdef CONFIG_MFD_SYSCON
554         hdmi_dev->grf_base =
555                 syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
556         if (IS_ERR(hdmi_dev->grf_base)) {
557                 hdmi_dev->grf_base = NULL;
558         }
559         #endif
560         return 0;
561 }
562 #endif
563
564 static int rockchip_hdmiv2_probe(struct platform_device *pdev)
565 {
566         int ret = -1;
567         struct resource *res;
568
569         HDMIDBG("%s\n", __func__);
570         hdmi_dev = kmalloc(sizeof(*hdmi_dev), GFP_KERNEL);
571         if (!hdmi_dev) {
572                 dev_err(&pdev->dev, ">>rockchip hdmiv2 kmalloc fail!");
573                 return -ENOMEM;
574         }
575         memset(hdmi_dev, 0, sizeof(struct hdmi_dev));
576         platform_set_drvdata(pdev, hdmi_dev);
577         hdmi_dev->dev = &pdev->dev;
578
579         if (rockchip_hdmiv2_parse_dt(hdmi_dev))
580                 goto failed;
581
582         /*request and remap iomem*/
583         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
584         if (!res) {
585                 dev_err(&pdev->dev, "Unable to get register resource\n");
586                 ret = -ENXIO;
587                 goto failed;
588         }
589         hdmi_dev->regbase = devm_ioremap_resource(&pdev->dev, res);
590         if (IS_ERR(hdmi_dev->regbase)) {
591                 ret = PTR_ERR(hdmi_dev->regbase);
592                 dev_err(&pdev->dev,
593                         "cannot ioremap registers,err=%d\n", ret);
594                 goto failed;
595         }
596         if (hdmi_dev->soctype == HDMI_SOC_RK322X) {
597                 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
598                 if (!res) {
599                         dev_err(&pdev->dev,
600                                 "Unable to get phy register resource\n");
601                         ret = -ENXIO;
602                         goto failed;
603                 }
604                 hdmi_dev->phybase = devm_ioremap_resource(&pdev->dev, res);
605                 if (IS_ERR(hdmi_dev->phybase)) {
606                         ret = PTR_ERR(hdmi_dev->phybase);
607                         dev_err(&pdev->dev,
608                                 "cannot ioremap registers,err=%d\n", ret);
609                         goto failed;
610                 }
611         }
612
613         hdmi_dev->reset = devm_reset_control_get(&pdev->dev, "hdmi");
614         if (IS_ERR(hdmi_dev->reset) &&
615             hdmi_dev->soctype != HDMI_SOC_RK3288) {
616                 ret = PTR_ERR(hdmi_dev->reset);
617                 dev_err(&pdev->dev, "failed to get hdmi reset: %d\n", ret);
618                 goto failed;
619         }
620         pm_runtime_enable(hdmi_dev->dev);
621         /*enable pd and clk*/
622         if (rockchip_hdmiv2_clk_enable(hdmi_dev) < 0) {
623                 dev_err(&pdev->dev, "failed to enable hdmi clk\n");
624                 ret = -ENXIO;
625                 goto failed1;
626         }
627         rockchip_hdmiv2_dev_init_ops(&rk_hdmi_ops);
628         /* Register HDMI device */
629         rk_hdmi_property.name = (char *)pdev->name;
630         rk_hdmi_property.priv = hdmi_dev;
631         if (hdmi_dev->soctype == HDMI_SOC_RK3288) {
632                 rk_hdmi_property.feature |= SUPPORT_DEEP_10BIT;
633                 if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
634                         rk_hdmi_property.feature |=
635                                                 SUPPORT_4K |
636                                                 SUPPORT_TMDS_600M;
637         } else if (hdmi_dev->soctype == HDMI_SOC_RK3368) {
638                 rk_hdmi_property.feature |=
639                                 SUPPORT_4K |
640                                 SUPPORT_4K_4096 |
641                                 SUPPORT_YUV420 |
642                                 SUPPORT_YCBCR_INPUT |
643                                 SUPPORT_VESA_DMT;
644         } else if (hdmi_dev->soctype == HDMI_SOC_RK322X) {
645                 rk_hdmi_property.feature |=
646                                 SUPPORT_4K |
647                                 SUPPORT_4K_4096 |
648                                 SUPPORT_YCBCR_INPUT |
649                                 SUPPORT_1080I |
650                                 SUPPORT_480I_576I;
651                 /*
652                  *if (rockchip_get_cpu_version())
653                  *      rk_hdmi_property.feature |=
654                  *              SUPPORT_YUV420 |
655                  *              SUPPORT_DEEP_10BIT;
656                  */
657         } else if (hdmi_dev->soctype == HDMI_SOC_RK3366) {
658                 rk_hdmi_property.feature |=
659                                 SUPPORT_YCBCR_INPUT |
660                                 SUPPORT_1080I |
661                                 SUPPORT_480I_576I;
662                 if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
663                         rk_hdmi_property.feature |=
664                                                 SUPPORT_4K |
665                                                 SUPPORT_4K_4096 |
666                                                 SUPPORT_YUV420 |
667                                                 SUPPORT_YCBCR_INPUT |
668                                                 SUPPORT_TMDS_600M;
669         } else if (hdmi_dev->soctype == HDMI_SOC_RK3399) {
670                 rk_hdmi_property.feature |=
671                                 SUPPORT_DEEP_10BIT |
672                                 SUPPORT_YCBCR_INPUT |
673                                 SUPPORT_1080I |
674                                 SUPPORT_480I_576I |
675                                 SUPPORT_VESA_DMT |
676                                 SUPPORT_RK_DISCRETE_VR;
677                 if (rk_hdmi_property.videosrc == DISPLAY_SOURCE_LCDC0)
678                         rk_hdmi_property.feature |=
679                                                 SUPPORT_4K |
680                                                 SUPPORT_4K_4096 |
681                                                 SUPPORT_YUV420 |
682                                                 SUPPORT_YCBCR_INPUT |
683                                                 SUPPORT_TMDS_600M;
684         } else {
685                 ret = -ENXIO;
686                 goto failed1;
687         }
688         hdmi_dev->hdmi =
689                 rockchip_hdmi_register(&rk_hdmi_property, &rk_hdmi_ops);
690         if (!hdmi_dev->hdmi) {
691                 dev_err(&pdev->dev, "register hdmi device failed\n");
692                 ret = -ENOMEM;
693                 goto failed1;
694         }
695
696         hdmi_get_prop_dts(hdmi_dev->hdmi, hdmi_dev->dev->of_node);
697         mutex_init(&hdmi_dev->ddc_lock);
698         hdmi_dev->hdmi->dev = &pdev->dev;
699         hdmi_dev->hdmi->soctype = hdmi_dev->soctype;
700         fb_register_client(&rockchip_hdmiv2_fb_notifier);
701         rockchip_hdmiv2_dev_initial(hdmi_dev);
702         pinctrl_select_state(hdmi_dev->dev->pins->p,
703                              hdmi_dev->dev->pins->default_state);
704 #if defined(CONFIG_DEBUG_FS)
705         hdmi_dev->debugfs_dir = debugfs_create_dir("rockchip_hdmiv2", NULL);
706         if (IS_ERR(hdmi_dev->debugfs_dir))
707                 dev_err(hdmi_dev->hdmi->dev,
708                         "failed to create debugfs dir for rockchip hdmiv2!\n");
709         else {
710                 debugfs_create_file("regs_ctrl", S_IRUSR,
711                                     hdmi_dev->debugfs_dir,
712                                     hdmi_dev, &hdmi_regs_ctrl_fops);
713                 debugfs_create_file("regs_phy", S_IRUSR,
714                                     hdmi_dev->debugfs_dir,
715                                     hdmi_dev, &hdmi_regs_phy_fops);
716         }
717 #endif
718
719 #ifndef HDMI_INT_USE_POLL
720         /* get and request the IRQ */
721         hdmi_dev->irq = platform_get_irq(pdev, 0);
722         if (hdmi_dev->irq <= 0) {
723                 dev_err(hdmi_dev->dev,
724                         "failed to get hdmi irq resource (%d).\n",
725                         hdmi_dev->irq);
726                 ret = -ENXIO;
727                 goto failed1;
728         }
729
730         ret = devm_request_irq(hdmi_dev->dev, hdmi_dev->irq,
731                                rockchip_hdmiv2_dev_irq,
732                                IRQF_TRIGGER_HIGH,
733                                dev_name(hdmi_dev->dev), hdmi_dev);
734         if (ret) {
735                 dev_err(hdmi_dev->dev,
736                         "hdmi request_irq failed (%d).\n",
737                         ret);
738                 goto failed1;
739         }
740 #else
741         hdmi_dev->workqueue =
742                 create_singlethread_workqueue("rockchip hdmiv2 irq");
743         INIT_DELAYED_WORK(&hdmi_dev->delay_work,
744                           rockchip_hdmiv2_irq_work_func);
745         rockchip_hdmiv2_irq_work_func(NULL);
746
747 #endif
748         rk_display_device_enable(hdmi_dev->hdmi->ddev);
749         dev_info(&pdev->dev, "rockchip hdmiv2 probe success.\n");
750         return 0;
751
752 failed1:
753         rockchip_hdmi_unregister(hdmi_dev->hdmi);
754 failed:
755         kfree(hdmi_dev->phy_table);
756         kfree(hdmi_dev);
757         hdmi_dev = NULL;
758         dev_err(&pdev->dev, "rockchip hdmiv2 probe error.\n");
759         return ret;
760 }
761
762 static int rockchip_hdmiv2_suspend(struct platform_device *pdev,
763                                    pm_message_t state)
764 {
765         if (hdmi_dev &&
766             hdmi_dev->grf_base &&
767             hdmi_dev->soctype == HDMI_SOC_RK322X) {
768                 regmap_write(hdmi_dev->grf_base,
769                              RK322X_GRF_SOC_CON2,
770                              RK322X_PLL_POWER_DOWN);
771         }
772         return 0;
773 }
774
775 static int rockchip_hdmiv2_resume(struct platform_device *pdev)
776 {
777         if (hdmi_dev &&
778             hdmi_dev->grf_base &&
779             hdmi_dev->soctype == HDMI_SOC_RK322X) {
780                 regmap_write(hdmi_dev->grf_base,
781                              RK322X_GRF_SOC_CON2,
782                              RK322X_PLL_POWER_UP);
783         }
784         return 0;
785 }
786
787 static int rockchip_hdmiv2_remove(struct platform_device *pdev)
788 {
789         dev_info(&pdev->dev, "rk3288 hdmi driver removed.\n");
790         return 0;
791 }
792
793 static void rockchip_hdmiv2_shutdown(struct platform_device *pdev)
794 {
795         struct hdmi *hdmi;
796
797         if (hdmi_dev) {
798                 #ifdef CONFIG_HAS_EARLYSUSPEND
799                 unregister_early_suspend(&hdmi_dev->early_suspend);
800                 #endif
801                 hdmi = hdmi_dev->hdmi;
802                 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
803                     hdmi->ops->setmute)
804                         hdmi->ops->setmute(hdmi, HDMI_VIDEO_MUTE);
805         }
806         pm_runtime_disable(hdmi_dev->dev);
807 }
808
809 static struct platform_driver rockchip_hdmiv2_driver = {
810         .probe          = rockchip_hdmiv2_probe,
811         .remove         = rockchip_hdmiv2_remove,
812         .driver         = {
813                 .name   = "rockchip-hdmiv2",
814                 .owner  = THIS_MODULE,
815                 #if defined(CONFIG_OF)
816                 .of_match_table = of_match_ptr(rk_hdmi_dt_ids),
817                 #endif
818         },
819         .suspend        = rockchip_hdmiv2_suspend,
820         .resume         = rockchip_hdmiv2_resume,
821         .shutdown       = rockchip_hdmiv2_shutdown,
822 };
823
824 static int __init rockchip_hdmiv2_init(void)
825 {
826         return platform_driver_register(&rockchip_hdmiv2_driver);
827 }
828
829 static void __exit rockchip_hdmiv2_exit(void)
830 {
831         platform_driver_unregister(&rockchip_hdmiv2_driver);
832 }
833
834 module_init(rockchip_hdmiv2_init);
835 module_exit(rockchip_hdmiv2_exit);