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