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