1 #include <linux/delay.h>
2 #include <sound/pcm_params.h>
3 #include "rockchip-hdmi.h"
4 #include "rockchip-hdmi-cec.h"
6 struct hdmi_delayed_work {
7 struct delayed_work work;
14 struct hdmi_id_ref_info {
18 } ref_info[HDMI_MAX_ID];
21 static void hdmi_work_queue(struct work_struct *work);
23 void hdmi_submit_work(struct hdmi *hdmi,
24 int event, int delay, int sync)
26 struct hdmi_delayed_work *work;
28 DBG("%s event %04x delay %d sync %d\n",
29 __func__, event, delay, sync);
31 work = kmalloc(sizeof(*work), GFP_ATOMIC);
34 INIT_DELAYED_WORK(&work->work, hdmi_work_queue);
39 queue_delayed_work(hdmi->workqueue,
41 msecs_to_jiffies(delay));
43 flush_delayed_work(&work->work);
47 pr_warn("HDMI: Cannot allocate memory to create work\n");
51 static void hdmi_send_uevent(struct hdmi *hdmi, int uevent)
55 envp[0] = "INTERFACE=HDMI";
56 envp[1] = kmalloc(32, GFP_KERNEL);
59 sprintf(envp[1], "SCREEN=%d", hdmi->ddev->property);
61 kobject_uevent_env(&hdmi->ddev->dev->kobj, uevent, envp);
65 static inline void hdmi_wq_set_output(struct hdmi *hdmi, int mute)
67 DBG("%s mute %d\n", __func__, mute);
68 if (hdmi->ops->setmute)
69 hdmi->ops->setmute(hdmi, mute);
72 static inline void hdmi_wq_set_audio(struct hdmi *hdmi)
74 DBG("%s\n", __func__);
75 if (hdmi->ops->setaudio)
76 hdmi->ops->setaudio(hdmi, &hdmi->audio);
79 static void hdmi_wq_set_video(struct hdmi *hdmi)
81 struct hdmi_video *video = &hdmi->video;
84 DBG("%s\n", __func__);
86 video->sink_hdmi = hdmi->edid.sink_hdmi;
87 video->format_3d = hdmi->mode_3d;
88 video->colorimetry = hdmi->colorimetry;
89 video->color_output_depth = 8;
91 hdmi->vic = hdmi_find_best_mode(hdmi, 0);
93 hdmi->vic = hdmi_find_best_mode(hdmi, hdmi->vic);
96 hdmi->vic = hdmi->property->defaultmode;
98 /* For DVI, output RGB */
99 if (video->sink_hdmi == 0) {
100 video->color_output = HDMI_COLOR_RGB_0_255;
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;
108 video->color_output = HDMI_COLOR_RGB_16_235;
110 video->color_output = hdmi->colormode;
112 if (hdmi->vic & HDMI_VIDEO_YUV420) {
113 video->color_output = HDMI_COLOR_YCBCR420;
114 deepcolor = hdmi->edid.deepcolor_420;
116 deepcolor = hdmi->edid.deepcolor;
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;
124 pr_info("hdmi output corlor mode is %d\n", video->color_output);
125 if ((hdmi->property->feature & SUPPORT_YCBCR_INPUT) &&
126 (video->color_output == HDMI_COLOR_YCBCR444 ||
127 video->color_output == HDMI_COLOR_YCBCR422))
128 video->color_input = HDMI_COLOR_YCBCR444;
129 else if (video->color_output == HDMI_COLOR_YCBCR420)
130 video->color_input = HDMI_COLOR_YCBCR420;
132 video->color_input = HDMI_COLOR_RGB_0_255;
134 if ((hdmi->vic & HDMI_VIDEO_DMT) || (hdmi->vic & HDMI_VIDEO_DISCRETE_VR)) {
135 if (hdmi->edid_auto_support) {
136 if (hdmi->prop.value.vic)
137 video->vic = hdmi->prop.value.vic;
139 video->vic = hdmi->vic;
141 video->vic = hdmi->vic;
143 video->color_output_depth = 8;
145 video->vic = hdmi->vic & HDMI_VIC_MASK;
148 if (hdmi->ops->setvideo)
149 hdmi->ops->setvideo(hdmi, video);
152 static void hdmi_wq_parse_edid(struct hdmi *hdmi)
154 struct hdmi_edid *pedid;
156 int rc = HDMI_ERROR_SUCCESS, extendblock = 0, i, trytimes;
161 DBG("%s\n", __func__);
164 fb_destroy_modelist(&pedid->modelist);
165 memset(pedid, 0, sizeof(struct hdmi_edid));
166 INIT_LIST_HEAD(&pedid->modelist);
168 pedid->raw[0] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
169 if (!pedid->raw[0]) {
170 rc = HDMI_ERROR_FALSE;
174 if (!hdmi->ops->getedid) {
175 rc = HDMI_ERROR_FALSE;
179 /* Read base block edid.*/
180 for (trytimes = 0; trytimes < 3; trytimes++) {
183 memset(pedid->raw[0], 0, HDMI_EDID_BLOCK_SIZE);
184 rc = hdmi->ops->getedid(hdmi, 0, pedid->raw[0]);
187 "[HDMI] read edid base block error\n");
191 rc = hdmi_edid_parse_base(hdmi,
192 pedid->raw[0], &extendblock, pedid);
195 "[HDMI] parse edid base block error\n");
204 for (i = 1; (i < extendblock + 1) && (i < HDMI_MAX_EDID_BLOCK); i++) {
205 pedid->raw[i] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
206 if (!pedid->raw[i]) {
208 "[%s] can not allocate memory for edid buff.\n",
210 rc = HDMI_ERROR_FALSE;
213 for (trytimes = 0; trytimes < 3; trytimes++) {
216 memset(pedid->raw[i], 0, HDMI_EDID_BLOCK_SIZE);
217 rc = hdmi->ops->getedid(hdmi, i, pedid->raw[i]);
220 "[HDMI] read edid block %d error\n",
225 rc = hdmi_edid_parse_extensions(pedid->raw[i], pedid);
228 "[HDMI] parse edid block %d error\n",
238 rc = hdmi_ouputmode_select(hdmi, rc);
241 static void hdmi_wq_insert(struct hdmi *hdmi)
243 DBG("%s\n", __func__);
244 if (hdmi->ops->insert)
245 hdmi->ops->insert(hdmi);
246 hdmi_wq_parse_edid(hdmi);
247 if (hdmi->property->feature & SUPPORT_CEC)
248 rockchip_hdmi_cec_set_pa(hdmi->edid.cecaddress);
249 hdmi_send_uevent(hdmi, KOBJ_ADD);
251 /*hdmi->autoset = 0;*/
252 hdmi_wq_set_video(hdmi);
254 switch_set_state(&hdmi->switchdev, 1);
256 hdmi_wq_set_audio(hdmi);
257 hdmi_wq_set_output(hdmi, hdmi->mute);
258 hdmi_submit_work(hdmi, HDMI_ENABLE_HDCP, 100, 0);
259 if (hdmi->ops->setcec)
260 hdmi->ops->setcec(hdmi);
266 static void hdmi_wq_remove(struct hdmi *hdmi)
268 struct list_head *pos, *n;
269 struct rk_screen screen;
272 DBG("%s\n", __func__);
273 if (hdmi->ops->remove)
274 hdmi->ops->remove(hdmi);
275 if (hdmi->property->feature & SUPPORT_CEC)
276 rockchip_hdmi_cec_set_pa(0);
277 if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
278 screen.type = SCREEN_HDMI;
279 rk_fb_switch_screen(&screen, 0, hdmi->lcdc->id);
282 switch_set_state(&hdmi->switchdev, 0);
284 list_for_each_safe(pos, n, &hdmi->edid.modelist) {
288 for (i = 0; i < HDMI_MAX_EDID_BLOCK; i++)
289 kfree(hdmi->edid.raw[i]);
290 kfree(hdmi->edid.audio);
291 if (hdmi->edid.specs) {
292 kfree(hdmi->edid.specs->modedb);
293 kfree(hdmi->edid.specs);
295 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
296 hdmi_init_modelist(hdmi);
297 hdmi->mute = HDMI_AV_UNMUTE;
298 hdmi->mode_3d = HDMI_3D_NONE;
300 hdmi->hotplug = HDMI_HPD_REMOVED;
301 hdmi_send_uevent(hdmi, KOBJ_REMOVE);
304 static void hdmi_work_queue(struct work_struct *work)
306 struct hdmi_delayed_work *hdmi_w =
307 container_of(work, struct hdmi_delayed_work, work.work);
308 struct hdmi *hdmi = hdmi_w->hdmi;
309 int event = hdmi_w->event;
310 int hpd = HDMI_HPD_REMOVED;
312 mutex_lock(&hdmi->ddev->lock);
314 DBG("\nhdmi_work_queue() - evt= %x %d\n",
315 (event & 0xFF00) >> 8,
318 if ((!hdmi->enable || hdmi->sleep) &&
319 (event != HDMI_ENABLE_CTL) &&
320 (event != HDMI_RESUME_CTL) &&
321 (event != HDMI_DISABLE_CTL) &&
322 (event != HDMI_SUSPEND_CTL))
326 case HDMI_ENABLE_CTL:
330 if (hdmi->ops->enable)
331 hdmi->ops->enable(hdmi);
332 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
333 hdmi_wq_insert(hdmi);
337 case HDMI_RESUME_CTL:
339 if (hdmi->ops->enable)
340 hdmi->ops->enable(hdmi);
344 case HDMI_DISABLE_CTL:
346 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
347 hdmi_wq_set_output(hdmi,
351 if (hdmi->ops->disable)
352 hdmi->ops->disable(hdmi);
353 hdmi_wq_remove(hdmi);
358 case HDMI_SUSPEND_CTL:
360 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
361 hdmi_wq_set_output(hdmi,
364 if (hdmi->ops->disable)
365 hdmi->ops->disable(hdmi);
367 hdmi_wq_remove(hdmi);
371 case HDMI_HPD_CHANGE:
372 if (hdmi->ops->getstatus)
373 hpd = hdmi->ops->getstatus(hdmi);
374 DBG("hdmi_work_queue() - hpd is %d hotplug is %d\n",
376 if (hpd != hdmi->hotplug) {
377 if (hpd == HDMI_HPD_ACTIVED) {
379 hdmi_wq_insert(hdmi);
380 } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
381 hdmi_wq_remove(hdmi);
387 hdmi_wq_set_output(hdmi,
388 HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
389 if (rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
393 hdmi_wq_set_video(hdmi);
394 hdmi_send_uevent(hdmi, KOBJ_CHANGE);
395 hdmi_wq_set_audio(hdmi);
396 hdmi_wq_set_output(hdmi, hdmi->mute);
397 if (hdmi->ops->hdcp_cb)
398 hdmi->ops->hdcp_cb(hdmi);
401 if ((hdmi->mute & HDMI_AUDIO_MUTE) == 0) {
402 hdmi_wq_set_output(hdmi, HDMI_AUDIO_MUTE);
403 hdmi_wq_set_audio(hdmi);
404 hdmi_wq_set_output(hdmi, hdmi->mute);
407 case HDMI_MUTE_AUDIO:
408 case HDMI_UNMUTE_AUDIO:
409 if (hdmi->mute & HDMI_AUDIO_MUTE ||
410 hdmi->hotplug != HDMI_HPD_ACTIVED)
412 if (event == HDMI_MUTE_AUDIO)
413 hdmi_wq_set_output(hdmi, hdmi->mute |
416 hdmi_wq_set_output(hdmi,
417 hdmi->mute & (~HDMI_AUDIO_MUTE));
420 if (hdmi->ops->setvsi && hdmi->edid.sink_hdmi) {
421 if (hdmi->mode_3d == HDMI_3D_FRAME_PACKING ||
422 hdmi->video.format_3d ==
423 HDMI_3D_FRAME_PACKING) {
424 hdmi_wq_set_output(hdmi,
428 hdmi_wq_set_video(hdmi);
429 hdmi_wq_set_audio(hdmi);
430 hdmi_wq_set_output(hdmi, hdmi->mute);
431 } else if (hdmi->mode_3d != HDMI_3D_NONE) {
432 hdmi->ops->setvsi(hdmi, hdmi->mode_3d,
433 HDMI_VIDEO_FORMAT_3D);
434 } else if ((hdmi->vic & HDMI_TYPE_MASK) == 0) {
435 hdmi->ops->setvsi(hdmi, hdmi->vic,
436 HDMI_VIDEO_FORMAT_NORMAL);
441 hdmi_wq_set_output(hdmi,
442 HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
444 hdmi_wq_set_video(hdmi);
445 hdmi_wq_set_output(hdmi, hdmi->mute);
447 case HDMI_ENABLE_HDCP:
448 if (hdmi->hotplug == HDMI_HPD_ACTIVED && hdmi->ops->hdcp_cb)
449 hdmi->ops->hdcp_cb(hdmi);
451 case HDMI_HDCP_AUTH_2ND:
452 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
453 hdmi->ops->hdcp_auth2nd)
454 hdmi->ops->hdcp_auth2nd(hdmi);
464 DBG("\nhdmi_work_queue() - exit evt= %x %d\n",
465 (event & 0xFF00) >> 8,
467 mutex_unlock(&hdmi->ddev->lock);
470 struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
471 struct hdmi_ops *ops)
477 if (!property || !ops) {
478 pr_err("HDMI: %s invalid parameter\n", __func__);
482 for (i = 0; i < HDMI_MAX_ID; i++) {
483 if (ref_info[i].ref == 0)
486 if (i == HDMI_MAX_ID)
489 DBG("hdmi_register() - video source %d display %d\n",
490 property->videosrc, property->display);
492 hdmi = kmalloc(sizeof(*hdmi), GFP_KERNEL);
496 memset(hdmi, 0, sizeof(struct hdmi));
497 mutex_init(&hdmi->lock);
498 mutex_init(&hdmi->pclk_lock);
500 hdmi->property = property;
502 hdmi->enable = false;
503 hdmi->mute = HDMI_AV_UNMUTE;
504 hdmi->hotplug = HDMI_HPD_REMOVED;
505 hdmi->autoset = HDMI_AUTO_CONFIG;
507 hdmi->vic = uboot_vic & HDMI_UBOOT_VIC_MASK;
508 if (uboot_vic & HDMI_UBOOT_NOT_INIT)
513 } else if (hdmi->autoset) {
516 hdmi->vic = hdmi->property->defaultmode;
518 hdmi->colormode = HDMI_VIDEO_DEFAULT_COLORMODE;
519 hdmi->colordepth = HDMI_VIDEO_DEFAULT_COLORDEPTH;
520 hdmi->colorimetry = HDMI_COLORIMETRY_NO_DATA;
521 hdmi->mode_3d = HDMI_3D_NONE;
522 hdmi->audio.type = HDMI_AUDIO_DEFAULT_TYPE;
523 hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
524 hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
525 hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORDLENGTH;
529 if (hdmi->property->videosrc == DISPLAY_SOURCE_LCDC0)
530 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
532 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
535 if (hdmi->lcdc->prop == EXTEND)
536 hdmi->property->display = DISPLAY_AUX;
538 hdmi->property->display = DISPLAY_MAIN;
540 sprintf(name, "hdmi-%s", hdmi->property->name);
541 hdmi->workqueue = create_singlethread_workqueue(name);
542 if (!hdmi->workqueue) {
543 pr_err("HDMI,: create workqueue failed.\n");
546 hdmi->ddev = hdmi_register_display_sysfs(hdmi, NULL);
548 pr_err("HDMI : register display sysfs failed.\n");
549 goto err_register_display;
552 hdmi_init_modelist(hdmi);
555 hdmi->switchdev.name = "hdmi";
557 hdmi->switchdev.name = kzalloc(32, GFP_KERNEL);
558 memset((char *)hdmi->switchdev.name, 0, 32);
559 sprintf((char *)hdmi->switchdev.name, "hdmi%d", hdmi->id);
561 switch_dev_register(&hdmi->switchdev);
564 ref_info[i].hdmi = hdmi;
568 err_register_display:
569 destroy_workqueue(hdmi->workqueue);
575 void rockchip_hdmi_unregister(struct hdmi *hdmi)
578 flush_workqueue(hdmi->workqueue);
579 destroy_workqueue(hdmi->workqueue);
581 switch_dev_unregister(&hdmi->switchdev);
583 hdmi_unregister_display_sysfs(hdmi);
584 fb_destroy_modelist(&hdmi->edid.modelist);
585 kfree(hdmi->edid.audio);
586 if (hdmi->edid.specs) {
587 kfree(hdmi->edid.specs->modedb);
588 kfree(hdmi->edid.specs);
592 ref_info[hdmi->id].ref = 0;
593 ref_info[hdmi->id].hdmi = NULL;
599 int hdmi_get_hotplug(void)
601 if (ref_info[0].hdmi)
602 return ref_info[0].hdmi->hotplug;
604 return HDMI_HPD_REMOVED;
607 int hdmi_config_audio(struct hdmi_audio *audio)
613 return HDMI_ERROR_FALSE;
615 for (i = 0; i < HDMI_MAX_ID; i++) {
616 if (ref_info[i].ref == 0)
618 hdmi = ref_info[i].hdmi;
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);
626 int snd_config_hdmi_audio(struct snd_pcm_hw_params *params)
628 struct hdmi_audio audio_cfg;
631 switch (params_rate(params)) {
633 rate = HDMI_AUDIO_FS_32000;
636 rate = HDMI_AUDIO_FS_44100;
639 rate = HDMI_AUDIO_FS_48000;
642 rate = HDMI_AUDIO_FS_88200;
645 rate = HDMI_AUDIO_FS_96000;
648 rate = HDMI_AUDIO_FS_176400;
651 rate = HDMI_AUDIO_FS_192000;
654 pr_err("rate %d unsupport.\n", params_rate(params));
655 rate = HDMI_AUDIO_FS_44100;
658 audio_cfg.rate = rate;
661 *if (params->flags == HW_PARAMS_FLAG_NLPCM)
662 * audio_cfg.type = HDMI_AUDIO_NLPCM;
665 audio_cfg.type = HDMI_AUDIO_LPCM;
667 audio_cfg.channel = params_channels(params);
668 audio_cfg.word_length = HDMI_AUDIO_WORD_LENGTH_16bit;
670 return hdmi_config_audio(&audio_cfg);
672 EXPORT_SYMBOL(snd_config_hdmi_audio);
674 void hdmi_audio_mute(int mute)
679 for (i = 0; i < HDMI_MAX_ID; i++) {
680 if (ref_info[i].ref == 0)
682 hdmi = ref_info[i].hdmi;
685 hdmi_submit_work(hdmi, HDMI_MUTE_AUDIO, 0, 0);
687 hdmi_submit_work(hdmi, HDMI_UNMUTE_AUDIO, 0, 0);
691 static int __init bootloader_setup(char *str)
694 pr_info("hdmi init vic is %s\n", str);
695 if (kstrtoint(str, 0, &uboot_vic) < 0)
701 early_param("hdmi.vic", bootloader_setup);
703 static int __init hdmi_class_init(void)
707 for (i = 0; i < HDMI_MAX_ID; i++) {
710 ref_info[i].hdmi = NULL;
712 pr_info("Rockchip hdmi driver version 2.0\n.");
716 subsys_initcall(hdmi_class_init);