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;
13 struct hdmi_id_ref_info {
17 } ref_info[HDMI_MAX_ID];
20 static void hdmi_work_queue(struct work_struct *work);
22 struct delayed_work *hdmi_submit_work(struct hdmi *hdmi,
23 int event, int delay, void *data)
25 struct hdmi_delayed_work *work;
27 DBG("%s event %04x delay %d\n", __func__, event, delay);
29 work = kmalloc(sizeof(*work), GFP_ATOMIC);
32 INIT_DELAYED_WORK(&work->work, hdmi_work_queue);
36 queue_delayed_work(hdmi->workqueue,
38 msecs_to_jiffies(delay));
40 pr_warn("HDMI: Cannot allocate memory to create work\n");
47 static void hdmi_send_uevent(struct hdmi *hdmi, int uevent)
51 envp[0] = "INTERFACE=HDMI";
52 envp[1] = kmalloc(32, GFP_KERNEL);
55 sprintf(envp[1], "SCREEN=%d", hdmi->ddev->property);
57 kobject_uevent_env(&hdmi->ddev->dev->kobj, uevent, envp);
61 static inline void hdmi_wq_set_output(struct hdmi *hdmi, int mute)
63 DBG("%s mute %d\n", __func__, mute);
64 if (hdmi->ops->setmute)
65 hdmi->ops->setmute(hdmi, mute);
68 static inline void hdmi_wq_set_audio(struct hdmi *hdmi)
70 DBG("%s\n", __func__);
71 if (hdmi->ops->setaudio)
72 hdmi->ops->setaudio(hdmi, &hdmi->audio);
75 static void hdmi_wq_set_video(struct hdmi *hdmi)
77 struct hdmi_video video;
80 DBG("%s\n", __func__);
82 video.vic = hdmi->vic & HDMI_VIC_MASK;
83 video.sink_hdmi = hdmi->edid.sink_hdmi;
84 video.format_3d = hdmi->mode_3d;
85 video.colorimetry = hdmi->colorimetry;
86 /* For DVI, output RGB */
87 if (hdmi->edid.sink_hdmi == 0) {
88 video.color_output = HDMI_COLOR_RGB_0_255;
90 if (hdmi->colormode == HDMI_COLOR_AUTO) {
91 if (hdmi->edid.ycbcr444)
92 video.color_output = HDMI_COLOR_YCBCR444;
93 else if (hdmi->edid.ycbcr422)
94 video.color_output = HDMI_COLOR_YCBCR422;
96 video.color_output = HDMI_COLOR_RGB_16_235;
98 video.color_output = hdmi->colormode;
101 if (hdmi->vic & HDMI_VIDEO_YUV420) {
102 video.color_output = HDMI_COLOR_YCBCR420;
103 deepcolor = hdmi->edid.deepcolor_420;
105 deepcolor = hdmi->edid.deepcolor;
107 if ((hdmi->property->feature & SUPPORT_DEEP_10BIT) &&
108 (deepcolor & HDMI_DEEP_COLOR_30BITS)) {
109 if (hdmi->colordepth == HDMI_DEPP_COLOR_AUTO ||
110 hdmi->colordepth == 10)
111 video.color_output_depth = 10;
113 video.color_output_depth = 8;
116 pr_info("hdmi output corlor mode is %d\n", video.color_output);
117 video.color_input = HDMI_COLOR_RGB_0_255;
118 if (hdmi->property->feature & SUPPORT_YCBCR_INPUT) {
119 if (video.color_output == HDMI_COLOR_YCBCR444 ||
120 video.color_output == HDMI_COLOR_YCBCR422)
121 video.color_input = HDMI_COLOR_YCBCR444;
122 else if (video.color_output == HDMI_COLOR_YCBCR420)
123 video.color_input = HDMI_COLOR_YCBCR420;
125 hdmi->colormode_input = video.color_input;
127 if (hdmi->ops->setvideo)
128 hdmi->ops->setvideo(hdmi, &video);
131 static void hdmi_wq_parse_edid(struct hdmi *hdmi)
133 struct hdmi_edid *pedid;
135 int rc = HDMI_ERROR_SUCESS, extendblock = 0, i, trytimes;
140 DBG("%s\n", __func__);
142 pedid = &(hdmi->edid);
143 fb_destroy_modelist(&pedid->modelist);
144 memset(pedid, 0, sizeof(struct hdmi_edid));
145 INIT_LIST_HEAD(&pedid->modelist);
147 pedid->raw[0] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
148 if (pedid->raw[0] == NULL) {
150 "[%s] can not allocate memory for edid buff.\n",
152 rc = HDMI_ERROR_FALSE;
156 if (hdmi->ops->getedid == NULL) {
157 rc = HDMI_ERROR_FALSE;
161 /* Read base block edid.*/
162 for (trytimes = 0; trytimes < 3; trytimes++) {
165 memset(pedid->raw[0], 0 , HDMI_EDID_BLOCK_SIZE);
166 rc = hdmi->ops->getedid(hdmi, 0, pedid->raw[0]);
169 "[HDMI] read edid base block error\n");
173 rc = hdmi_edid_parse_base(pedid->raw[0], &extendblock, pedid);
176 "[HDMI] parse edid base block error\n");
185 for (i = 1; (i < extendblock + 1) && (i < HDMI_MAX_EDID_BLOCK); i++) {
186 pedid->raw[i] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
187 if (pedid->raw[i] == NULL) {
189 "[%s] can not allocate memory for edid buff.\n",
191 rc = HDMI_ERROR_FALSE;
194 for (trytimes = 0; trytimes < 3; trytimes++) {
197 memset(pedid->raw[i], 0 , HDMI_EDID_BLOCK_SIZE);
198 rc = hdmi->ops->getedid(hdmi, i, pedid->raw[i]);
201 "[HDMI] read edid block %d error\n",
206 rc = hdmi_edid_parse_extensions(pedid->raw[i], pedid);
209 "[HDMI] parse edid block %d error\n",
219 rc = hdmi_ouputmode_select(hdmi, rc);
222 static void hdmi_wq_insert(struct hdmi *hdmi)
224 DBG("%s\n", __func__);
225 if (hdmi->ops->insert)
226 hdmi->ops->insert(hdmi);
227 hdmi_wq_parse_edid(hdmi);
228 if (hdmi->property->feature & SUPPORT_CEC)
229 rockchip_hdmi_cec_set_pa(hdmi->edid.cecaddress);
230 hdmi_send_uevent(hdmi, KOBJ_ADD);
232 /*hdmi->autoset = 0;*/
233 hdmi_wq_set_video(hdmi);
235 switch_set_state(&(hdmi->switchdev), 1);
237 hdmi_wq_set_audio(hdmi);
238 hdmi_wq_set_output(hdmi, hdmi->mute);
239 hdmi_submit_work(hdmi, HDMI_ENABLE_HDCP, 100, NULL);
240 if (hdmi->ops->setcec)
241 hdmi->ops->setcec(hdmi);
247 static void hdmi_wq_remove(struct hdmi *hdmi)
249 struct list_head *pos, *n;
250 struct rk_screen screen;
253 DBG("%s\n", __func__);
254 if (hdmi->ops->remove)
255 hdmi->ops->remove(hdmi);
256 if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
257 screen.type = SCREEN_HDMI;
258 rk_fb_switch_screen(&screen, 0, hdmi->lcdc->id);
261 switch_set_state(&(hdmi->switchdev), 0);
263 mutex_lock(&hdmi->ddev->lock);
264 list_for_each_safe(pos, n, &hdmi->edid.modelist) {
268 mutex_unlock(&hdmi->ddev->lock);
269 for (i = 0; i < HDMI_MAX_EDID_BLOCK; i++)
270 kfree(hdmi->edid.raw[i]);
271 kfree(hdmi->edid.audio);
272 if (hdmi->edid.specs) {
273 kfree(hdmi->edid.specs->modedb);
274 kfree(hdmi->edid.specs);
276 memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
277 hdmi_init_modelist(hdmi);
278 hdmi->mute = HDMI_AV_UNMUTE;
279 hdmi->mode_3d = HDMI_3D_NONE;
281 hdmi->hotplug = HDMI_HPD_REMOVED;
282 hdmi_send_uevent(hdmi, KOBJ_REMOVE);
285 static void hdmi_work_queue(struct work_struct *work)
287 struct hdmi_delayed_work *hdmi_w =
288 container_of(work, struct hdmi_delayed_work, work.work);
289 struct hdmi *hdmi = hdmi_w->hdmi;
290 int event = hdmi_w->event;
291 int hpd = HDMI_HPD_REMOVED;
293 mutex_lock(&hdmi->lock);
295 DBG("\nhdmi_work_queue() - evt= %x %d\n",
296 (event & 0xFF00) >> 8,
300 case HDMI_ENABLE_CTL:
304 if (hdmi->ops->enable)
305 hdmi->ops->enable(hdmi);
306 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
307 hdmi_wq_insert(hdmi);
311 case HDMI_RESUME_CTL:
313 if (hdmi->ops->enable)
314 hdmi->ops->enable(hdmi);
318 case HDMI_DISABLE_CTL:
320 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
321 hdmi_wq_set_output(hdmi,
325 if (hdmi->ops->disable)
326 hdmi->ops->disable(hdmi);
327 hdmi_wq_remove(hdmi);
332 case HDMI_SUSPEND_CTL:
334 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
335 hdmi_wq_set_output(hdmi,
338 if (hdmi->ops->disable)
339 hdmi->ops->disable(hdmi);
341 hdmi_wq_remove(hdmi);
345 case HDMI_HPD_CHANGE:
346 if (hdmi->ops->getstatus)
347 hpd = hdmi->ops->getstatus(hdmi);
348 DBG("hdmi_work_queue() - hpd is %d hotplug is %d\n",
350 if (hpd != hdmi->hotplug) {
351 if (hpd == HDMI_HPD_ACTIVED) {
353 hdmi_wq_insert(hdmi);
354 } else if (hdmi->hotplug == HDMI_HPD_ACTIVED) {
355 hdmi_wq_remove(hdmi);
361 if (hdmi->enable && !hdmi->sleep) {
362 hdmi_wq_set_output(hdmi,
363 HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
364 if (rk_fb_get_display_policy() == DISPLAY_POLICY_BOX)
368 hdmi_wq_set_video(hdmi);
369 hdmi_send_uevent(hdmi, KOBJ_CHANGE);
370 hdmi_wq_set_audio(hdmi);
371 hdmi_wq_set_output(hdmi, hdmi->mute);
372 if (hdmi->ops->hdcp_cb)
373 hdmi->ops->hdcp_cb(hdmi);
377 if ((hdmi->mute & HDMI_AUDIO_MUTE) == 0 &&
378 hdmi->enable && !hdmi->sleep) {
379 hdmi_wq_set_output(hdmi, HDMI_AUDIO_MUTE);
380 hdmi_wq_set_audio(hdmi);
381 hdmi_wq_set_output(hdmi, hdmi->mute);
384 case HDMI_MUTE_AUDIO:
385 case HDMI_UNMUTE_AUDIO:
386 if (hdmi->mute & HDMI_AUDIO_MUTE ||
387 !hdmi->enable || hdmi->sleep ||
388 hdmi->hotplug != HDMI_HPD_ACTIVED)
390 if (event == HDMI_MUTE_AUDIO)
391 hdmi_wq_set_output(hdmi, hdmi->mute |
394 hdmi_wq_set_output(hdmi,
395 hdmi->mute & (~HDMI_AUDIO_MUTE));
398 if (hdmi->ops->setvsi) {
399 if (hdmi->mode_3d != HDMI_3D_NONE)
400 hdmi->ops->setvsi(hdmi, hdmi->mode_3d,
401 HDMI_VIDEO_FORMAT_3D);
402 else if ((hdmi->vic & HDMI_TYPE_MASK) == 0)
403 hdmi->ops->setvsi(hdmi, hdmi->vic,
404 HDMI_VIDEO_FORMAT_NORMAL);
408 hdmi_wq_set_output(hdmi,
409 HDMI_VIDEO_MUTE | HDMI_AUDIO_MUTE);
411 hdmi_wq_set_video(hdmi);
412 hdmi_wq_set_output(hdmi, hdmi->mute);
414 case HDMI_ENABLE_HDCP:
415 if (hdmi->hotplug == HDMI_HPD_ACTIVED && hdmi->ops->hdcp_cb)
416 hdmi->ops->hdcp_cb(hdmi);
418 case HDMI_HDCP_AUTH_2ND:
419 if (hdmi->hotplug == HDMI_HPD_ACTIVED &&
420 hdmi->ops->hdcp_auth2nd)
421 hdmi->ops->hdcp_auth2nd(hdmi);
424 pr_err("HDMI: hdmi_work_queue() unkown event\n");
431 DBG("\nhdmi_work_queue() - exit evt= %x %d\n",
432 (event & 0xFF00) >> 8,
434 mutex_unlock(&hdmi->lock);
437 struct hdmi *rockchip_hdmi_register(struct hdmi_property *property,
438 struct hdmi_ops *ops)
444 if (property == NULL || ops == NULL) {
445 pr_err("HDMI: %s invalid parameter\n", __func__);
449 for (i = 0; i < HDMI_MAX_ID; i++) {
450 if (ref_info[i].ref == 0)
453 if (i == HDMI_MAX_ID)
456 DBG("hdmi_register() - video source %d display %d\n",
457 property->videosrc, property->display);
459 hdmi = kmalloc(sizeof(*hdmi), GFP_KERNEL);
461 pr_err("HDMI: no memory to allocate hdmi device.\n");
464 memset(hdmi, 0, sizeof(struct hdmi));
465 mutex_init(&hdmi->lock);
467 hdmi->property = property;
469 hdmi->enable = false;
470 hdmi->mute = HDMI_AV_UNMUTE;
471 hdmi->hotplug = HDMI_HPD_REMOVED;
472 hdmi->autoset = HDMI_AUTO_CONFIG;
474 hdmi->vic = uboot_vic;
477 } else if (hdmi->autoset) {
480 hdmi->vic = hdmi->property->defaultmode;
482 hdmi->colormode = HDMI_VIDEO_DEFAULT_COLORMODE;
483 hdmi->colordepth = HDMI_DEPP_COLOR_AUTO;
484 hdmi->colorimetry = HDMI_COLORIMETRY_NO_DATA;
485 hdmi->mode_3d = HDMI_3D_NONE;
486 hdmi->audio.type = HDMI_AUDIO_DEFAULT_TYPE;
487 hdmi->audio.channel = HDMI_AUDIO_DEFAULT_CHANNEL;
488 hdmi->audio.rate = HDMI_AUDIO_DEFAULT_RATE;
489 hdmi->audio.word_length = HDMI_AUDIO_DEFAULT_WORDLENGTH;
492 hdmi_init_modelist(hdmi);
494 if (hdmi->property->videosrc == DISPLAY_SOURCE_LCDC0)
495 hdmi->lcdc = rk_get_lcdc_drv("lcdc0");
497 hdmi->lcdc = rk_get_lcdc_drv("lcdc1");
499 if (hdmi->lcdc->prop == EXTEND)
500 hdmi->property->display = DISPLAY_AUX;
502 hdmi->property->display = DISPLAY_MAIN;
504 sprintf(name, "hdmi-%s", hdmi->property->name);
505 hdmi->workqueue = create_singlethread_workqueue(name);
506 if (hdmi->workqueue == NULL) {
507 pr_err("HDMI,: create workqueue failed.\n");
510 hdmi->ddev = hdmi_register_display_sysfs(hdmi, NULL);
511 if (hdmi->ddev == NULL) {
512 pr_err("HDMI : register display sysfs failed.\n");
513 goto err_register_display;
518 hdmi->switchdev.name = "hdmi";
520 hdmi->switchdev.name = kzalloc(32, GFP_KERNEL);
521 memset((char *)hdmi->switchdev.name, 0, 32);
522 sprintf((char *)hdmi->switchdev.name, "hdmi%d", hdmi->id);
524 switch_dev_register(&(hdmi->switchdev));
527 ref_info[i].hdmi = hdmi;
531 err_register_display:
532 destroy_workqueue(hdmi->workqueue);
538 void rockchip_hdmi_unregister(struct hdmi *hdmi)
541 flush_workqueue(hdmi->workqueue);
542 destroy_workqueue(hdmi->workqueue);
544 switch_dev_unregister(&(hdmi->switchdev));
546 hdmi_unregister_display_sysfs(hdmi);
547 fb_destroy_modelist(&hdmi->edid.modelist);
548 kfree(hdmi->edid.audio);
549 if (hdmi->edid.specs) {
550 kfree(hdmi->edid.specs->modedb);
551 kfree(hdmi->edid.specs);
555 ref_info[hdmi->id].ref = 0;
556 ref_info[hdmi->id].hdmi = NULL;
562 int hdmi_get_hotplug(void)
564 if (ref_info[0].hdmi)
565 return ref_info[0].hdmi->hotplug;
567 return HDMI_HPD_REMOVED;
570 int hdmi_config_audio(struct hdmi_audio *audio)
576 return HDMI_ERROR_FALSE;
578 for (i = 0; i < HDMI_MAX_ID; i++) {
579 if (ref_info[i].ref == 0)
581 hdmi = ref_info[i].hdmi;
584 if (memcmp(audio, &hdmi->audio, sizeof(struct hdmi_audio)) == 0)
587 /*for (j = 0; j < hdmi->edid.audio_num; j++) {
588 if (audio->type == hdmi->edid.audio_num)
592 /*if ( (j == hdmi->edid.audio_num) ||
593 (audio->channel > hdmi->edid.audio[j].channel) ||
594 ((audio->rate & hdmi->edid.audio[j].rate) == 0)||
595 ((audio->type == HDMI_AUDIO_LPCM) &&
596 ((audio->word_length &
597 hdmi->edid.audio[j].word_length) == 0)) ) {
598 pr_warn("[%s] warning : input audio type
599 not supported in hdmi sink\n", __func__);
602 memcpy(&hdmi->audio, audio, sizeof(struct hdmi_audio));
603 if (hdmi->hotplug == HDMI_HPD_ACTIVED)
604 hdmi_submit_work(hdmi, HDMI_SET_AUDIO, 0, NULL);
609 int snd_config_hdmi_audio(struct snd_pcm_hw_params *params)
611 struct hdmi_audio audio_cfg;
614 switch (params_rate(params)) {
616 rate = HDMI_AUDIO_FS_32000;
619 rate = HDMI_AUDIO_FS_44100;
622 rate = HDMI_AUDIO_FS_48000;
625 rate = HDMI_AUDIO_FS_88200;
628 rate = HDMI_AUDIO_FS_96000;
631 rate = HDMI_AUDIO_FS_176400;
634 rate = HDMI_AUDIO_FS_192000;
637 pr_err("rate %d unsupport.\n", params_rate(params));
638 rate = HDMI_AUDIO_FS_44100;
641 audio_cfg.rate = rate;
643 if (HW_PARAMS_FLAG_NLPCM == params->flags)
644 audio_cfg.type = HDMI_AUDIO_NLPCM;
646 audio_cfg.type = HDMI_AUDIO_LPCM;
648 audio_cfg.channel = params_channels(params);
649 audio_cfg.word_length = HDMI_AUDIO_WORD_LENGTH_16bit;
651 return hdmi_config_audio(&audio_cfg);
653 EXPORT_SYMBOL(snd_config_hdmi_audio);
655 void hdmi_audio_mute(int mute)
660 for (i = 0; i < HDMI_MAX_ID; i++) {
661 if (ref_info[i].ref == 0)
663 hdmi = ref_info[i].hdmi;
666 hdmi_submit_work(hdmi, HDMI_MUTE_AUDIO, 0, NULL);
668 hdmi_submit_work(hdmi, HDMI_UNMUTE_AUDIO, 0, NULL);
672 static int __init bootloader_setup(char *str)
675 pr_info("hdmi init vic is %s\n", str);
676 if (kstrtoint(str, 0, &uboot_vic) < 0)
682 early_param("hdmi.vic", bootloader_setup);
684 static int __init hdmi_class_init(void)
688 for (i = 0; i < HDMI_MAX_ID; i++) {
691 ref_info[i].hdmi = NULL;
693 pr_info("Rockchip hdmi driver version 2.0\n.");
697 subsys_initcall(hdmi_class_init);