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