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