HDMI: support show edid status.
[firefly-linux-kernel-4.4.55.git] / drivers / video / rockchip / hdmi / rockchip-hdmi-core.c
1 #include <linux/delay.h>
2 #include "rockchip-hdmi.h"
3 #include "rockchip-hdmi-cec.h"
4
5 struct hdmi_delayed_work {
6         struct delayed_work work;
7         struct hdmi *hdmi;
8         int event;
9         void *data;
10 };
11
12 struct hdmi_id_ref_info {
13         struct hdmi *hdmi;
14         int id;
15         int ref;
16 } ref_info[HDMI_MAX_ID];
17
18 static int uboot_vic;
19 static void hdmi_work_queue(struct work_struct *work);
20
21 struct delayed_work *hdmi_submit_work(struct hdmi *hdmi,
22                                       int event, int delay, void *data)
23 {
24         struct hdmi_delayed_work *work;
25
26         DBG("%s event %04x delay %d", __func__, event, delay);
27
28         work = kmalloc(sizeof(*work), GFP_ATOMIC);
29
30         if (work) {
31                 INIT_DELAYED_WORK(&work->work, hdmi_work_queue);
32                 work->hdmi = hdmi;
33                 work->event = event;
34                 work->data = data;
35                 queue_delayed_work(hdmi->workqueue,
36                                    &work->work,
37                                    msecs_to_jiffies(delay));
38         } else {
39                 pr_warn("HDMI: Cannot allocate memory to create work\n");
40                 return 0;
41         }
42
43         return &work->work;
44 }
45
46 static void hdmi_send_uevent(struct hdmi *hdmi, int uevent)
47 {
48         char *envp[3];
49
50         envp[0] = "INTERFACE=HDMI";
51         envp[1] = kmalloc(32, GFP_KERNEL);
52         if (envp[1] == NULL)
53                 return;
54         sprintf(envp[1], "SCREEN=%d", hdmi->ddev->property);
55         envp[2] = NULL;
56         kobject_uevent_env(&hdmi->ddev->dev->kobj, uevent, envp);
57         kfree(envp[1]);
58 }
59
60 static inline void hdmi_wq_set_output(struct hdmi *hdmi, int mute)
61 {
62         DBG("%s mute %d", __func__, mute);
63         if (hdmi->ops->setmute)
64                 hdmi->ops->setmute(hdmi, mute);
65 }
66
67 static inline void hdmi_wq_set_audio(struct hdmi *hdmi)
68 {
69         DBG("%s", __func__);
70         if (hdmi->ops->setaudio)
71                 hdmi->ops->setaudio(hdmi, &hdmi->audio);
72 }
73
74 static void hdmi_wq_set_video(struct hdmi *hdmi)
75 {
76         struct hdmi_video       video;
77
78         DBG("%s", __func__);
79
80         video.vic = hdmi->vic & HDMI_VIC_MASK;
81         video.sink_hdmi = hdmi->edid.sink_hdmi;
82         video.format_3d = hdmi->mode_3d;
83         /* For DVI, output RGB */
84         if (hdmi->edid.sink_hdmi == 0) {
85                 video.color_output = HDMI_COLOR_RGB_0_255;
86         } else {
87                 if (hdmi->colormode == HDMI_COLOR_AUTO) {
88                         if (hdmi->edid.ycbcr444)
89                                 video.color_output = HDMI_COLOR_YCBCR444;
90                         else if (hdmi->edid.ycbcr422)
91                                 video.color_output = HDMI_COLOR_YCBCR422;
92                         else
93                                 video.color_output = HDMI_COLOR_RGB_16_235;
94                 } else {
95                         video.color_output = hdmi->colormode;
96                 }
97         }
98         if ((hdmi->property->feature & SUPPORT_DEEP_10BIT) &&
99             (hdmi->edid.deepcolor & HDMI_DEEP_COLOR_30BITS)) {
100                 if (hdmi->colordepth == HDMI_DEPP_COLOR_AUTO ||
101                     hdmi->colordepth == 10)
102                         video.color_output_depth = 10;
103         } else {
104                 video.color_output_depth = 8;
105         }
106         if (hdmi->vic & HDMI_VIDEO_YUV420)
107                 video.color_output = HDMI_COLOR_YCBCR420;
108         pr_info("hdmi output corlor mode is %d\n", video.color_output);
109         video.color_input = HDMI_COLOR_RGB_0_255;
110         if (hdmi->property->feature & SUPPORT_YCBCR_INPUT) {
111                 if (video.color_output == HDMI_COLOR_YCBCR444 ||
112                     video.color_output == HDMI_COLOR_YCBCR422)
113                         video.color_input = HDMI_COLOR_YCBCR444;
114                 else if (video.color_output == HDMI_COLOR_YCBCR420)
115                         video.color_input = HDMI_COLOR_YCBCR420;
116         }
117         hdmi->colormode_input = video.color_input;
118         hdmi_set_lcdc(hdmi);
119         if (hdmi->ops->setvideo)
120                 hdmi->ops->setvideo(hdmi, &video);
121 }
122
123 static void hdmi_wq_parse_edid(struct hdmi *hdmi)
124 {
125         struct hdmi_edid *pedid;
126
127         int rc = HDMI_ERROR_SUCESS, extendblock = 0, i, trytimes;
128
129         if (hdmi == NULL)
130                 return;
131
132         DBG("%s", __func__);
133
134         pedid = &(hdmi->edid);
135         fb_destroy_modelist(&pedid->modelist);
136         memset(pedid, 0, sizeof(struct hdmi_edid));
137         INIT_LIST_HEAD(&pedid->modelist);
138
139         pedid->raw[0] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
140         if (pedid->raw[0] == NULL) {
141                 dev_err(hdmi->dev,
142                         "[%s] can not allocate memory for edid buff.\n",
143                         __func__);
144                 rc = HDMI_ERROR_FALSE;
145                 goto out;
146         }
147
148         if (hdmi->ops->getedid == NULL) {
149                 rc = HDMI_ERROR_FALSE;
150                 goto out;
151         }
152
153         /* Read base block edid.*/
154         for (trytimes = 0; trytimes < 3; trytimes++) {
155                 if (trytimes)
156                         msleep(50);
157                 memset(pedid->raw[0], 0 , HDMI_EDID_BLOCK_SIZE);
158                 rc = hdmi->ops->getedid(hdmi, 0, pedid->raw[0]);
159                 if (rc) {
160                         dev_err(hdmi->dev,
161                                 "[HDMI] read edid base block error\n");
162                         continue;
163                 }
164
165                 rc = hdmi_edid_parse_base(pedid->raw[0], &extendblock, pedid);
166                 if (rc) {
167                         dev_err(hdmi->dev,
168                                 "[HDMI] parse edid base block error\n");
169                         continue;
170                 }
171                 if (!rc)
172                         break;
173         }
174         if (rc)
175                 goto out;
176
177         for (i = 1; (i < extendblock + 1) && (i < HDMI_MAX_EDID_BLOCK); i++) {
178                 pedid->raw[i] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
179                 if (pedid->raw[i] == NULL) {
180                         dev_err(hdmi->dev,
181                                 "[%s] can not allocate memory for edid buff.\n",
182                                 __func__);
183                         rc = HDMI_ERROR_FALSE;
184                         goto out;
185                 }
186                 for (trytimes = 0; trytimes < 3; trytimes++) {
187                         if (trytimes)
188                                 msleep(20);
189                         memset(pedid->raw[i], 0 , HDMI_EDID_BLOCK_SIZE);
190                         rc = hdmi->ops->getedid(hdmi, i, pedid->raw[i]);
191                         if (rc) {
192                                 dev_err(hdmi->dev,
193                                         "[HDMI] read edid block %d error\n",
194                                         i);
195                                 continue;
196                         }
197
198                         rc = hdmi_edid_parse_extensions(pedid->raw[i], pedid);
199                         if (rc) {
200                                 dev_err(hdmi->dev,
201                                         "[HDMI] parse edid block %d error\n",
202                                         i);
203                                 continue;
204                         }
205
206                         if (!rc)
207                                 break;
208                 }
209         }
210 out:
211         rc = hdmi_ouputmode_select(hdmi, rc);
212 }
213
214 static void hdmi_wq_insert(struct hdmi *hdmi)
215 {
216         DBG("%s", __func__);
217         if (hdmi->ops->insert)
218                 hdmi->ops->insert(hdmi);
219         hdmi_wq_parse_edid(hdmi);
220         if (hdmi->property->feature & SUPPORT_CEC)
221                 rockchip_hdmi_cec_set_pa(hdmi->edid.cecaddress);
222         hdmi_send_uevent(hdmi, KOBJ_ADD);
223         if (hdmi->enable) {
224                 /*hdmi->autoset = 0;*/
225                 hdmi_wq_set_video(hdmi);
226                 #ifdef CONFIG_SWITCH
227                 switch_set_state(&(hdmi->switchdev), 1);
228                 #endif
229                 hdmi_wq_set_audio(hdmi);
230                 hdmi_wq_set_output(hdmi, hdmi->mute);
231                 if (hdmi->ops->hdcp_cb)
232                         hdmi->ops->hdcp_cb(hdmi);
233                 if (hdmi->ops->setcec)
234                         hdmi->ops->setcec(hdmi);
235         }
236         if (hdmi->uboot)
237                 hdmi->uboot = 0;
238 }
239
240 static void hdmi_wq_remove(struct hdmi *hdmi)
241 {
242         struct list_head *pos, *n;
243         struct rk_screen screen;
244         int i;
245
246         DBG("%s", __func__);
247         if (hdmi->ops->remove)
248                 hdmi->ops->remove(hdmi);
249         if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
250                 screen.type = SCREEN_HDMI;
251                 rk_fb_switch_screen(&screen, 0, hdmi->lcdc->id);
252         }
253         #ifdef CONFIG_SWITCH
254         switch_set_state(&(hdmi->switchdev), 0);
255         #endif
256         list_for_each_safe(pos, n, &hdmi->edid.modelist) {
257                 list_del(pos);
258                 kfree(pos);
259         }
260         for (i = 0; i < HDMI_MAX_EDID_BLOCK; i++)
261                 kfree(hdmi->edid.raw[i]);
262         kfree(hdmi->edid.audio);
263         if (hdmi->edid.specs) {
264                 kfree(hdmi->edid.specs->modedb);
265                 kfree(hdmi->edid.specs);
266         }
267         memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
268         hdmi_init_modelist(hdmi);
269         hdmi->mute      = HDMI_AV_UNMUTE;
270         hdmi->mode_3d = HDMI_3D_NONE;
271         hdmi->uboot = 0;
272         hdmi->hotplug = HDMI_HPD_REMOVED;
273         hdmi_send_uevent(hdmi, KOBJ_REMOVE);
274 }
275
276 static void hdmi_work_queue(struct work_struct *work)
277 {
278         struct hdmi_delayed_work *hdmi_w =
279                 container_of(work, struct hdmi_delayed_work, work.work);
280         struct hdmi *hdmi = hdmi_w->hdmi;
281         int event = hdmi_w->event;
282         int hpd = HDMI_HPD_REMOVED;
283
284         mutex_lock(&hdmi->lock);
285
286         DBG("\nhdmi_work_queue() - evt= %x %d\n",
287             (event & 0xFF00) >> 8,
288             event & 0xFF);
289
290         switch (event) {
291         case HDMI_ENABLE_CTL:
292                 if (!hdmi->enable) {
293                         hdmi->enable = 1;
294                         if (!hdmi->sleep) {
295                                 if (hdmi->ops->enable)
296                                         hdmi->ops->enable(hdmi);
297                                 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
298                                         hdmi_wq_insert(hdmi);
299                         }
300                 }
301                 break;
302         case HDMI_RESUME_CTL:
303                 if (hdmi->sleep) {
304                         if (hdmi->ops->enable)
305                                 hdmi->ops->enable(hdmi);
306                         hdmi->sleep = 0;
307                 }
308                 break;
309         case HDMI_DISABLE_CTL:
310                 if (hdmi->enable) {
311                         if (!hdmi->sleep) {
312                                 if (hdmi->ops->disable)
313                                         hdmi->ops->disable(hdmi);
314                                 hdmi_wq_remove(hdmi);
315                         }
316                         hdmi->enable = 0;
317                 }
318                 break;
319         case HDMI_SUSPEND_CTL:
320                 if (!hdmi->sleep) {
321                         hdmi_wq_set_output(hdmi,
322                                            HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
323                         if (hdmi->ops->disable)
324                                 hdmi->ops->disable(hdmi);
325                         if (hdmi->enable)
326                                 hdmi_wq_remove(hdmi);
327                         hdmi->sleep = 1;
328                 }
329                 break;
330         case HDMI_HPD_CHANGE:
331                 if (hdmi->ops->getstatus)
332                         hpd = hdmi->ops->getstatus(hdmi);
333                 DBG("hdmi_work_queue() - hpd is %d hotplug is %d",
334                     hpd, hdmi->hotplug);
335                 if (hpd != hdmi->hotplug) {
336                         if (hpd == HDMI_HPD_ACTIVED) {
337                                 hdmi->hotplug = hpd;
338                                 hdmi_wq_insert(hdmi);
339                         } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
340                                 hdmi_wq_remove(hdmi);
341                         }
342                         hdmi->hotplug = hpd;
343                 }
344                 break;
345         case HDMI_SET_VIDEO:
346                 if (hdmi->enable && !hdmi->sleep) {
347                         hdmi_wq_set_output(hdmi,
348                                            HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
349                         if (rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
350                                 msleep(2000);
351                         else
352                                 msleep(1000);
353                         hdmi_wq_set_video(hdmi);
354                         hdmi_send_uevent(hdmi, KOBJ_CHANGE);
355                         hdmi_wq_set_audio(hdmi);
356                         hdmi_wq_set_output(hdmi, hdmi->mute);
357                         if (hdmi->ops->hdcp_cb)
358                                 hdmi->ops->hdcp_cb(hdmi);
359                 }
360                 break;
361         case HDMI_SET_AUDIO:
362                 if ((hdmi->mute & HDMI_AUDIO_MUTE) == 0 &&
363                     hdmi->enable && !hdmi->sleep) {
364                         hdmi_wq_set_output(hdmi, HDMI_AUDIO_MUTE);
365                         hdmi_wq_set_audio(hdmi);
366                         hdmi_wq_set_output(hdmi, hdmi->mute);
367                 }
368                 break;
369         case HDMI_MUTE_AUDIO:
370         case HDMI_UNMUTE_AUDIO:
371                 if (hdmi->mute & HDMI_AUDIO_MUTE ||
372                     !hdmi->enable || hdmi->sleep ||
373                     hdmi->hotplug != HDMI_HPD_ACTIVED)
374                         break;
375                 if (event == HDMI_MUTE_AUDIO)
376                         hdmi_wq_set_output(hdmi, hdmi->mute |
377                                            HDMI_AUDIO_MUTE);
378                 else
379                         hdmi_wq_set_output(hdmi,
380                                            hdmi->mute & (~HDMI_AUDIO_MUTE));
381                 break;
382         case HDMI_SET_3D:
383                 if (hdmi->ops->setvsi) {
384                         if (hdmi->mode_3d != HDMI_3D_NONE)
385                                 hdmi->ops->setvsi(hdmi, hdmi->mode_3d,
386                                                   HDMI_VIDEO_FORMAT_3D);
387                         else if ((hdmi->vic & HDMI_TYPE_MASK) == 0)
388                                 hdmi->ops->setvsi(hdmi, hdmi->vic,
389                                                   HDMI_VIDEO_FORMAT_NORMAL);
390                 }
391                 break;
392         case HDMI_SET_COLOR:
393                 hdmi_wq_set_output(hdmi,
394                                    HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
395                 msleep(100);
396                 hdmi_wq_set_video(hdmi);
397                 hdmi_wq_set_output(hdmi, hdmi->mute);
398                 break;
399         case HDMI_ENABLE_HDCP:
400                 if (hdmi->hotplug == HDMI_HPD_ACTIVED && hdmi->ops->hdcp_cb)
401                         hdmi->ops->hdcp_cb(hdmi);
402                 break;
403         default:
404                 pr_err("HDMI: hdmi_work_queue() unkown event\n");
405                 break;
406         }
407
408         kfree(hdmi_w->data);
409         kfree(hdmi_w);
410
411         DBG("\nhdmi_work_queue() - exit evt= %x %d\n",
412             (event & 0xFF00) >> 8,
413             event & 0xFF);
414         mutex_unlock(&hdmi->lock);
415 }
416
417 struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
418                                     struct hdmi_ops *ops)
419 {
420         struct hdmi *hdmi;
421         char name[32];
422         int i;
423
424         if (property == NULL || ops == NULL) {
425                 pr_err("HDMI: %s invalid parameter\n", __func__);
426                 return NULL;
427         }
428
429         for (i = 0; i < HDMI_MAX_ID; i++) {
430                 if (ref_info[i].ref == 0)
431                         break;
432         }
433         if (i == HDMI_MAX_ID)
434                 return NULL;
435
436         DBG("hdmi_register() - video source %d display %d",
437             property->videosrc,  property->display);
438
439         hdmi = kmalloc(sizeof(*hdmi), GFP_KERNEL);
440         if (!hdmi) {
441                 pr_err("HDMI: no memory to allocate hdmi device.\n");
442                 return NULL;
443         }
444         memset(hdmi, 0, sizeof(struct hdmi));
445         mutex_init(&hdmi->lock);
446
447         hdmi->property = property;
448         hdmi->ops = ops;
449         hdmi->enable = false;
450         hdmi->mute = HDMI_AV_UNMUTE;
451         hdmi->hotplug = HDMI_HPD_REMOVED;
452         hdmi->autoset = HDMI_AUTO_CONFIG;
453         if (uboot_vic > 0) {
454                 hdmi->vic = uboot_vic;
455                 hdmi->uboot = 1;
456                 hdmi->autoset = 0;
457         } else if (hdmi->autoset) {
458                 hdmi->vic = 0;
459         } else {
460                 hdmi->vic = hdmi->property->defaultmode;
461         }
462         hdmi->colormode = HDMI_VIDEO_DEFAULT_COLORMODE;
463         hdmi->colordepth = HDMI_DEPP_COLOR_AUTO;
464         hdmi->mode_3d = HDMI_3D_NONE;
465         hdmi->audio.type = HDMI_AUDIO_DEFAULT_TYPE;
466         hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
467         hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
468         hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORDLENGTH;
469         hdmi->xscale = 100;
470         hdmi->yscale = 100;
471         hdmi_init_modelist(hdmi);
472
473 #ifndef CONFIG_ARCH_RK29
474         if (hdmi->property->videosrc == DISPLAY_SOURCE_LCDC0)
475                 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
476         else
477                 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
478 #endif
479         memset(name, 0, 32);
480         sprintf(name, "hdmi-%s", hdmi->property->name);
481         hdmi->workqueue = create_singlethread_workqueue(name);
482         if (hdmi->workqueue == NULL) {
483                 pr_err("HDMI,: create workqueue failed.\n");
484                 goto err_create_wq;
485         }
486         hdmi->ddev = hdmi_register_display_sysfs(hdmi, NULL);
487         if (hdmi->ddev == NULL) {
488                 pr_err("HDMI : register display sysfs failed.\n");
489                 goto err_register_display;
490         }
491         hdmi->id = i;
492         #ifdef CONFIG_SWITCH
493         if (hdmi->id == 0) {
494                 hdmi->switchdev.name = "hdmi";
495         } else {
496                 hdmi->switchdev.name = kzalloc(32, GFP_KERNEL);
497                 memset((char *)hdmi->switchdev.name, 0, 32);
498                 sprintf((char *)hdmi->switchdev.name, "hdmi%d", hdmi->id);
499         }
500         switch_dev_register(&(hdmi->switchdev));
501         #endif
502
503         ref_info[i].hdmi = hdmi;
504         ref_info[i].ref = 1;
505         return hdmi;
506
507 err_register_display:
508         destroy_workqueue(hdmi->workqueue);
509 err_create_wq:
510         kfree(hdmi);
511         return NULL;
512 }
513
514 void rockchip_hdmi_unregister(struct hdmi *hdmi)
515 {
516         if (hdmi) {
517                 flush_workqueue(hdmi->workqueue);
518                 destroy_workqueue(hdmi->workqueue);
519                 #ifdef CONFIG_SWITCH
520                 switch_dev_unregister(&(hdmi->switchdev));
521                 #endif
522                 hdmi_unregister_display_sysfs(hdmi);
523                 fb_destroy_modelist(&hdmi->edid.modelist);
524                 kfree(hdmi->edid.audio);
525                 if (hdmi->edid.specs) {
526                         kfree(hdmi->edid.specs->modedb);
527                         kfree(hdmi->edid.specs);
528                 }
529                 kfree(hdmi);
530
531                 ref_info[hdmi->id].ref = 0;
532                 ref_info[hdmi->id].hdmi = NULL;
533
534                 hdmi = NULL;
535         }
536 }
537
538 int hdmi_get_hotplug(void)
539 {
540         if (ref_info[0].hdmi)
541                 return ref_info[0].hdmi->hotplug;
542         else
543                 return HDMI_HPD_REMOVED;
544 }
545
546 int hdmi_config_audio(struct hdmi_audio *audio)
547 {
548         int i;
549         struct hdmi *hdmi;
550
551         if (audio == NULL)
552                 return HDMI_ERROR_FALSE;
553
554         for (i = 0; i < HDMI_MAX_ID; i++) {
555                 if (ref_info[i].ref == 0)
556                         continue;
557                 hdmi = ref_info[i].hdmi;
558
559                 /*
560                 if (memcmp(audio, &hdmi->audio, sizeof(struct hdmi_audio)) == 0)
561                         continue;
562                 */
563                 /*for (j = 0; j < hdmi->edid.audio_num; j++) {
564                         if (audio->type == hdmi->edid.audio_num)
565                                 break;
566                 }*/
567
568                 /*if ( (j == hdmi->edid.audio_num) ||
569                         (audio->channel > hdmi->edid.audio[j].channel) ||
570                         ((audio->rate & hdmi->edid.audio[j].rate) == 0)||
571                         ((audio->type == HDMI_AUDIO_LPCM) &&
572                         ((audio->word_length &
573                           hdmi->edid.audio[j].word_length) == 0)) ) {
574                         pr_warn("[%s] warning : input audio type
575                                 not supported in hdmi sink\n", __func__);
576                         continue;
577                 }*/
578                 memcpy(&hdmi->audio, audio, sizeof(struct hdmi_audio));
579                 hdmi_submit_work(hdmi, HDMI_SET_AUDIO, 0, NULL);
580         }
581         return 0;
582 }
583
584 void hdmi_audio_mute(int mute)
585 {
586         int i;
587         struct hdmi *hdmi;
588
589         for (i = 0; i < HDMI_MAX_ID; i++) {
590                 if (ref_info[i].ref == 0)
591                         continue;
592                 hdmi = ref_info[i].hdmi;
593
594                 if (mute)
595                         hdmi_submit_work(hdmi, HDMI_MUTE_AUDIO, 0, NULL);
596                 else
597                         hdmi_submit_work(hdmi, HDMI_UNMUTE_AUDIO, 0, NULL);
598         }
599 }
600
601 static int __init bootloader_setup(char *str)
602 {
603         if (str) {
604                 pr_info("hdmi init vic is %s\n", str);
605                 if (kstrtoint(str, 0, &uboot_vic) < 0)
606                         uboot_vic = 0;
607         }
608         return 0;
609 }
610
611 early_param("hdmi.vic", bootloader_setup);
612
613 static int __init hdmi_class_init(void)
614 {
615         int i;
616
617         for (i = 0; i < HDMI_MAX_ID; i++) {
618                 ref_info[i].id = i;
619                 ref_info[i].ref = 0;
620                 ref_info[i].hdmi = NULL;
621         }
622         pr_info("Rockchip hdmi driver version 2.0\n.");
623         return 0;
624 }
625
626 subsys_initcall(hdmi_class_init);