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 /* For DVI, output RGB */
90 if (hdmi->edid.sink_hdmi == 0) {
91 video->color_output = HDMI_COLOR_RGB_0_255;
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;
99 video->color_output = HDMI_COLOR_RGB_16_235;
101 video->color_output = hdmi->colormode;
103 if (hdmi->vic & HDMI_VIDEO_YUV420) {
104 video->color_output = HDMI_COLOR_YCBCR420;
105 deepcolor = hdmi->edid.deepcolor_420;
107 deepcolor = hdmi->edid.deepcolor;
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;
115 video->color_output_depth = 8;
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;
128 video->vic = hdmi->vic & HDMI_VIC_MASK;
129 if (hdmi->ops->setvideo)
130 hdmi->ops->setvideo(hdmi, video);
133 static void hdmi_wq_parse_edid(struct hdmi *hdmi)
135 struct hdmi_edid *pedid;
137 int rc = HDMI_ERROR_SUCESS, extendblock = 0, i, trytimes;
142 DBG("%s\n", __func__);
144 pedid = &(hdmi->edid);
145 fb_destroy_modelist(&pedid->modelist);
146 memset(pedid, 0, sizeof(struct hdmi_edid));
147 INIT_LIST_HEAD(&pedid->modelist);
149 pedid->raw[0] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
150 if (pedid->raw[0] == NULL) {
152 "[%s] can not allocate memory for edid buff.\n",
154 rc = HDMI_ERROR_FALSE;
158 if (hdmi->ops->getedid == NULL) {
159 rc = HDMI_ERROR_FALSE;
163 /* Read base block edid.*/
164 for (trytimes = 0; trytimes < 3; trytimes++) {
167 memset(pedid->raw[0], 0 , HDMI_EDID_BLOCK_SIZE);
168 rc = hdmi->ops->getedid(hdmi, 0, pedid->raw[0]);
171 "[HDMI] read edid base block error\n");
175 rc = hdmi_edid_parse_base(pedid->raw[0], &extendblock, pedid);
178 "[HDMI] parse edid base block error\n");
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) {
191 "[%s] can not allocate memory for edid buff.\n",
193 rc = HDMI_ERROR_FALSE;
196 for (trytimes = 0; trytimes < 3; trytimes++) {
199 memset(pedid->raw[i], 0 , HDMI_EDID_BLOCK_SIZE);
200 rc = hdmi->ops->getedid(hdmi, i, pedid->raw[i]);
203 "[HDMI] read edid block %d error\n",
208 rc = hdmi_edid_parse_extensions(pedid->raw[i], pedid);
211 "[HDMI] parse edid block %d error\n",
221 rc = hdmi_ouputmode_select(hdmi, rc);
224 static void hdmi_wq_insert(struct hdmi *hdmi)
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);
234 /*hdmi->autoset = 0;*/
235 hdmi_wq_set_video(hdmi);
237 switch_set_state(&(hdmi->switchdev), 1);
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);
249 static void hdmi_wq_remove(struct hdmi *hdmi)
251 struct list_head *pos, *n;
252 struct rk_screen screen;
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);
265 switch_set_state(&(hdmi->switchdev), 0);
267 list_for_each_safe(pos, n, &hdmi->edid.modelist) {
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);
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;
283 hdmi->hotplug = HDMI_HPD_REMOVED;
284 hdmi_send_uevent(hdmi, KOBJ_REMOVE);
287 static void hdmi_work_queue(struct work_struct *work)
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;
295 mutex_lock(&hdmi->ddev->lock);
297 DBG("\nhdmi_work_queue() - evt= %x %d\n",
298 (event & 0xFF00) >> 8,
302 case HDMI_ENABLE_CTL:
306 if (hdmi->ops->enable)
307 hdmi->ops->enable(hdmi);
308 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
309 hdmi_wq_insert(hdmi);
313 case HDMI_RESUME_CTL:
315 if (hdmi->ops->enable)
316 hdmi->ops->enable(hdmi);
320 case HDMI_DISABLE_CTL:
322 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
323 hdmi_wq_set_output(hdmi,
327 if (hdmi->ops->disable)
328 hdmi->ops->disable(hdmi);
329 hdmi_wq_remove(hdmi);
334 case HDMI_SUSPEND_CTL:
336 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
337 hdmi_wq_set_output(hdmi,
340 if (hdmi->ops->disable)
341 hdmi->ops->disable(hdmi);
343 hdmi_wq_remove(hdmi);
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",
352 if (hpd != hdmi->hotplug) {
353 if (hpd == HDMI_HPD_ACTIVED) {
355 hdmi_wq_insert(hdmi);
356 } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
357 hdmi_wq_remove(hdmi);
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)
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);
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);
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)
392 if (event == HDMI_MUTE_AUDIO)
393 hdmi_wq_set_output(hdmi, hdmi->mute |
396 hdmi_wq_set_output(hdmi,
397 hdmi->mute & (~HDMI_AUDIO_MUTE));
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,
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);
421 hdmi_wq_set_output(hdmi,
422 HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
424 hdmi_wq_set_video(hdmi);
425 hdmi_wq_set_output(hdmi, hdmi->mute);
427 case HDMI_ENABLE_HDCP:
428 if (hdmi->hotplug == HDMI_HPD_ACTIVED && hdmi->ops->hdcp_cb)
429 hdmi->ops->hdcp_cb(hdmi);
431 case HDMI_HDCP_AUTH_2ND:
432 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
433 hdmi->ops->hdcp_auth2nd)
434 hdmi->ops->hdcp_auth2nd(hdmi);
437 pr_err("HDMI: hdmi_work_queue() unkown event\n");
445 DBG("\nhdmi_work_queue() - exit evt= %x %d\n",
446 (event & 0xFF00) >> 8,
448 mutex_unlock(&hdmi->ddev->lock);
451 struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
452 struct hdmi_ops *ops)
458 if (property == NULL || ops == NULL) {
459 pr_err("HDMI: %s invalid parameter\n", __func__);
463 for (i = 0; i < HDMI_MAX_ID; i++) {
464 if (ref_info[i].ref == 0)
467 if (i == HDMI_MAX_ID)
470 DBG("hdmi_register() - video source %d display %d\n",
471 property->videosrc, property->display);
473 hdmi = kmalloc(sizeof(*hdmi), GFP_KERNEL);
475 pr_err("HDMI: no memory to allocate hdmi device.\n");
478 memset(hdmi, 0, sizeof(struct hdmi));
479 mutex_init(&hdmi->lock);
481 hdmi->property = property;
483 hdmi->enable = false;
484 hdmi->mute = HDMI_AV_UNMUTE;
485 hdmi->hotplug = HDMI_HPD_REMOVED;
486 hdmi->autoset = HDMI_AUTO_CONFIG;
488 hdmi->vic = uboot_vic;
491 } else if (hdmi->autoset) {
494 hdmi->vic = hdmi->property->defaultmode;
496 hdmi->colormode = HDMI_VIDEO_DEFAULT_COLORMODE;
497 hdmi->colordepth = HDMI_DEPP_COLOR_AUTO;
498 hdmi->colorimetry = HDMI_COLORIMETRY_NO_DATA;
499 hdmi->mode_3d = HDMI_3D_NONE;
500 hdmi->audio.type = HDMI_AUDIO_DEFAULT_TYPE;
501 hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
502 hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
503 hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORDLENGTH;
506 hdmi_init_modelist(hdmi);
508 if (hdmi->property->videosrc == DISPLAY_SOURCE_LCDC0)
509 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
511 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
513 if (hdmi->lcdc->prop == EXTEND)
514 hdmi->property->display = DISPLAY_AUX;
516 hdmi->property->display = DISPLAY_MAIN;
518 sprintf(name, "hdmi-%s", hdmi->property->name);
519 hdmi->workqueue = create_singlethread_workqueue(name);
520 if (hdmi->workqueue == NULL) {
521 pr_err("HDMI,: create workqueue failed.\n");
524 hdmi->ddev = hdmi_register_display_sysfs(hdmi, NULL);
525 if (hdmi->ddev == NULL) {
526 pr_err("HDMI : register display sysfs failed.\n");
527 goto err_register_display;
532 hdmi->switchdev.name = "hdmi";
534 hdmi->switchdev.name = kzalloc(32, GFP_KERNEL);
535 memset((char *)hdmi->switchdev.name, 0, 32);
536 sprintf((char *)hdmi->switchdev.name, "hdmi%d", hdmi->id);
538 switch_dev_register(&(hdmi->switchdev));
541 ref_info[i].hdmi = hdmi;
545 err_register_display:
546 destroy_workqueue(hdmi->workqueue);
552 void rockchip_hdmi_unregister(struct hdmi *hdmi)
555 flush_workqueue(hdmi->workqueue);
556 destroy_workqueue(hdmi->workqueue);
558 switch_dev_unregister(&(hdmi->switchdev));
560 hdmi_unregister_display_sysfs(hdmi);
561 fb_destroy_modelist(&hdmi->edid.modelist);
562 kfree(hdmi->edid.audio);
563 if (hdmi->edid.specs) {
564 kfree(hdmi->edid.specs->modedb);
565 kfree(hdmi->edid.specs);
569 ref_info[hdmi->id].ref = 0;
570 ref_info[hdmi->id].hdmi = NULL;
576 int hdmi_get_hotplug(void)
578 if (ref_info[0].hdmi)
579 return ref_info[0].hdmi->hotplug;
581 return HDMI_HPD_REMOVED;
584 int hdmi_config_audio(struct hdmi_audio *audio)
590 return HDMI_ERROR_FALSE;
592 for (i = 0; i < HDMI_MAX_ID; i++) {
593 if (ref_info[i].ref == 0)
595 hdmi = ref_info[i].hdmi;
598 if (memcmp(audio, &hdmi->audio, sizeof(struct hdmi_audio)) == 0)
601 /*for (j = 0; j < hdmi->edid.audio_num; j++) {
602 if (audio->type == hdmi->edid.audio_num)
606 /*if ( (j == hdmi->edid.audio_num) ||
607 (audio->channel > hdmi->edid.audio[j].channel) ||
608 ((audio->rate & hdmi->edid.audio[j].rate) == 0)||
609 ((audio->type == HDMI_AUDIO_LPCM) &&
610 ((audio->word_length &
611 hdmi->edid.audio[j].word_length) == 0)) ) {
612 pr_warn("[%s] warning : input audio type
613 not supported in hdmi sink\n", __func__);
616 memcpy(&hdmi->audio, audio, sizeof(struct hdmi_audio));
617 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
618 hdmi_submit_work(hdmi, HDMI_SET_AUDIO, 0, 0);
623 int snd_config_hdmi_audio(struct snd_pcm_hw_params *params)
625 struct hdmi_audio audio_cfg;
628 switch (params_rate(params)) {
630 rate = HDMI_AUDIO_FS_32000;
633 rate = HDMI_AUDIO_FS_44100;
636 rate = HDMI_AUDIO_FS_48000;
639 rate = HDMI_AUDIO_FS_88200;
642 rate = HDMI_AUDIO_FS_96000;
645 rate = HDMI_AUDIO_FS_176400;
648 rate = HDMI_AUDIO_FS_192000;
651 pr_err("rate %d unsupport.\n", params_rate(params));
652 rate = HDMI_AUDIO_FS_44100;
655 audio_cfg.rate = rate;
657 if (HW_PARAMS_FLAG_NLPCM == params->flags)
658 audio_cfg.type = HDMI_AUDIO_NLPCM;
660 audio_cfg.type = HDMI_AUDIO_LPCM;
662 audio_cfg.channel = params_channels(params);
663 audio_cfg.word_length = HDMI_AUDIO_WORD_LENGTH_16bit;
665 return hdmi_config_audio(&audio_cfg);
667 EXPORT_SYMBOL(snd_config_hdmi_audio);
669 void hdmi_audio_mute(int mute)
674 for (i = 0; i < HDMI_MAX_ID; i++) {
675 if (ref_info[i].ref == 0)
677 hdmi = ref_info[i].hdmi;
680 hdmi_submit_work(hdmi, HDMI_MUTE_AUDIO, 0, 0);
682 hdmi_submit_work(hdmi, HDMI_UNMUTE_AUDIO, 0, 0);
686 static int __init bootloader_setup(char *str)
689 pr_info("hdmi init vic is %s\n", str);
690 if (kstrtoint(str, 0, &uboot_vic) < 0)
696 early_param("hdmi.vic", bootloader_setup);
698 static int __init hdmi_class_init(void)
702 for (i = 0; i < HDMI_MAX_ID; i++) {
705 ref_info[i].hdmi = NULL;
707 pr_info("Rockchip hdmi driver version 2.0\n.");
711 subsys_initcall(hdmi_class_init);