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