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