aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/sh_mobile_hdmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sh_mobile_hdmi.c')
-rw-r--r--drivers/video/sh_mobile_hdmi.c629
1 files changed, 405 insertions, 224 deletions
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index ef989d94511c..55b3077ff6ff 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -28,6 +28,8 @@
28#include <video/sh_mobile_hdmi.h> 28#include <video/sh_mobile_hdmi.h>
29#include <video/sh_mobile_lcdc.h> 29#include <video/sh_mobile_lcdc.h>
30 30
31#include "sh_mobile_lcdcfb.h"
32
31#define HDMI_SYSTEM_CTRL 0x00 /* System control */ 33#define HDMI_SYSTEM_CTRL 0x00 /* System control */
32#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control, 34#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
33 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */ 35 bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
@@ -206,12 +208,15 @@ enum hotplug_state {
206 208
207struct sh_hdmi { 209struct sh_hdmi {
208 void __iomem *base; 210 void __iomem *base;
209 enum hotplug_state hp_state; 211 enum hotplug_state hp_state; /* hot-plug status */
212 bool preprogrammed_mode; /* use a pre-programmed VIC or the external mode */
210 struct clk *hdmi_clk; 213 struct clk *hdmi_clk;
211 struct device *dev; 214 struct device *dev;
212 struct fb_info *info; 215 struct fb_info *info;
216 struct mutex mutex; /* Protect the info pointer */
213 struct delayed_work edid_work; 217 struct delayed_work edid_work;
214 struct fb_var_screeninfo var; 218 struct fb_var_screeninfo var;
219 struct fb_monspecs monspec;
215}; 220};
216 221
217static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg) 222static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
@@ -277,7 +282,7 @@ static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
277 */ 282 */
278 283
279/* External video parameter settings */ 284/* External video parameter settings */
280static void hdmi_external_video_param(struct sh_hdmi *hdmi) 285static void sh_hdmi_external_video_param(struct sh_hdmi *hdmi)
281{ 286{
282 struct fb_var_screeninfo *var = &hdmi->var; 287 struct fb_var_screeninfo *var = &hdmi->var;
283 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset; 288 u16 htotal, hblank, hdelay, vtotal, vblank, vdelay, voffset;
@@ -309,9 +314,9 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
309 if (var->sync & FB_SYNC_VERT_HIGH_ACT) 314 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
310 sync |= 8; 315 sync |= 8;
311 316
312 pr_debug("H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n", 317 dev_dbg(hdmi->dev, "H: %u, %u, %u, %u; V: %u, %u, %u, %u; sync 0x%x\n",
313 htotal, hblank, hdelay, var->hsync_len, 318 htotal, hblank, hdelay, var->hsync_len,
314 vtotal, vblank, vdelay, var->vsync_len, sync); 319 vtotal, vblank, vdelay, var->vsync_len, sync);
315 320
316 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS); 321 hdmi_write(hdmi, sync | (voffset << 4), HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
317 322
@@ -336,7 +341,10 @@ static void hdmi_external_video_param(struct sh_hdmi *hdmi)
336 341
337 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION); 342 hdmi_write(hdmi, var->vsync_len, HDMI_EXTERNAL_V_DURATION);
338 343
339 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for manual mode */ 344 /* Set bit 0 of HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS here for external mode */
345 if (!hdmi->preprogrammed_mode)
346 hdmi_write(hdmi, sync | 1 | (voffset << 4),
347 HDMI_EXTERNAL_VIDEO_PARAM_SETTINGS);
340} 348}
341 349
342/** 350/**
@@ -454,21 +462,61 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
454} 462}
455 463
456/** 464/**
457 * sh_hdmi_phy_config() 465 * sh_hdmi_phy_config() - configure the HDMI PHY for the used video mode
458 */ 466 */
459static void sh_hdmi_phy_config(struct sh_hdmi *hdmi) 467static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
460{ 468{
461 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */ 469 if (hdmi->var.yres > 480) {
462 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1); 470 /* 720p, 8bit, 74.25MHz. Might need to be adjusted for other formats */
463 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2); 471 /*
464 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3); 472 * [1:0] Speed_A
465 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */ 473 * [3:2] Speed_B
466 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5); 474 * [4] PLLA_Bypass
467 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6); 475 * [6] DRV_TEST_EN
468 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7); 476 * [7] DRV_TEST_IN
469 hdmi_write(hdmi, 0x0E, HDMI_SLIPHDMIT_PARAM_SETTINGS_8); 477 */
470 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9); 478 hdmi_write(hdmi, 0x0f, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
471 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10); 479 /* PLLB_CONFIG[17], PLLA_CONFIG[17] - not in PHY datasheet */
480 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
481 /*
482 * [2:0] BGR_I_OFFSET
483 * [6:4] BGR_V_OFFSET
484 */
485 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
486 /* PLLA_CONFIG[7:0]: VCO gain, VCO offset, LPF resistance[0] */
487 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
488 /*
489 * PLLA_CONFIG[15:8]: regulator voltage[0], CP current,
490 * LPF capacitance, LPF resistance[1]
491 */
492 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
493 /* PLLB_CONFIG[7:0]: LPF resistance[0], VCO offset, VCO gain */
494 hdmi_write(hdmi, 0x4A, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
495 /*
496 * PLLB_CONFIG[15:8]: regulator voltage[0], CP current,
497 * LPF capacitance, LPF resistance[1]
498 */
499 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
500 /* DRV_CONFIG, PE_CONFIG */
501 hdmi_write(hdmi, 0x25, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
502 /*
503 * [2:0] AMON_SEL (4 == LPF voltage)
504 * [4] PLLA_CONFIG[16]
505 * [5] PLLB_CONFIG[16]
506 */
507 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
508 } else {
509 /* for 480p8bit 27MHz */
510 hdmi_write(hdmi, 0x19, HDMI_SLIPHDMIT_PARAM_SETTINGS_1);
511 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_2);
512 hdmi_write(hdmi, 0x00, HDMI_SLIPHDMIT_PARAM_SETTINGS_3);
513 hdmi_write(hdmi, 0x44, HDMI_SLIPHDMIT_PARAM_SETTINGS_5);
514 hdmi_write(hdmi, 0x32, HDMI_SLIPHDMIT_PARAM_SETTINGS_6);
515 hdmi_write(hdmi, 0x48, HDMI_SLIPHDMIT_PARAM_SETTINGS_7);
516 hdmi_write(hdmi, 0x0F, HDMI_SLIPHDMIT_PARAM_SETTINGS_8);
517 hdmi_write(hdmi, 0x20, HDMI_SLIPHDMIT_PARAM_SETTINGS_9);
518 hdmi_write(hdmi, 0x04, HDMI_SLIPHDMIT_PARAM_SETTINGS_10);
519 }
472} 520}
473 521
474/** 522/**
@@ -476,6 +524,8 @@ static void sh_hdmi_phy_config(struct sh_hdmi *hdmi)
476 */ 524 */
477static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi) 525static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
478{ 526{
527 u8 vic;
528
479 /* AVI InfoFrame */ 529 /* AVI InfoFrame */
480 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX); 530 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_INDEX);
481 531
@@ -500,9 +550,9 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
500 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1); 550 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB1);
501 551
502 /* 552 /*
503 * C = No Data 553 * [7:6] C = Colorimetry: no data
504 * M = 16:9 Picture Aspect Ratio 554 * [5:4] M = 2: 16:9, 1: 4:3 Picture Aspect Ratio
505 * R = Same as picture aspect ratio 555 * [3:0] R = 8: Active Frame Aspect Ratio: same as picture aspect ratio
506 */ 556 */
507 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2); 557 hdmi_write(hdmi, 0x28, HDMI_CTRL_PKT_BUF_ACCESS_PB2);
508 558
@@ -516,9 +566,15 @@ static void sh_hdmi_avi_infoframe_setup(struct sh_hdmi *hdmi)
516 566
517 /* 567 /*
518 * VIC = 1280 x 720p: ignored if external config is used 568 * VIC = 1280 x 720p: ignored if external config is used
519 * Send 2 for 720 x 480p, 16 for 1080p 569 * Send 2 for 720 x 480p, 16 for 1080p, ignored in external mode
520 */ 570 */
521 hdmi_write(hdmi, 4, HDMI_CTRL_PKT_BUF_ACCESS_PB4); 571 if (hdmi->var.yres == 1080 && hdmi->var.xres == 1920)
572 vic = 16;
573 else if (hdmi->var.yres == 480 && hdmi->var.xres == 720)
574 vic = 2;
575 else
576 vic = 4;
577 hdmi_write(hdmi, vic, HDMI_CTRL_PKT_BUF_ACCESS_PB4);
522 578
523 /* PR = No Repetition */ 579 /* PR = No Repetition */
524 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5); 580 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB5);
@@ -592,100 +648,6 @@ static void sh_hdmi_audio_infoframe_setup(struct sh_hdmi *hdmi)
592} 648}
593 649
594/** 650/**
595 * sh_hdmi_gamut_metadata_setup() - Gamut Metadata Packet of CONTROL PACKET
596 */
597static void sh_hdmi_gamut_metadata_setup(struct sh_hdmi *hdmi)
598{
599 int i;
600
601 /* Gamut Metadata Packet */
602 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_INDEX);
603
604 /* Packet Type = 0x0A */
605 hdmi_write(hdmi, 0x0A, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
606 /* Gamut Packet is not used, so default value */
607 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
608 /* Gamut Packet is not used, so default value */
609 hdmi_write(hdmi, 0x10, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
610
611 /* GBD bytes 0 through 27 */
612 for (i = 0; i <= 27; i++)
613 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0_63H - PB27_7EH */
614 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
615}
616
617/**
618 * sh_hdmi_acp_setup() - Audio Content Protection Packet (ACP)
619 */
620static void sh_hdmi_acp_setup(struct sh_hdmi *hdmi)
621{
622 int i;
623
624 /* Audio Content Protection Packet (ACP) */
625 hdmi_write(hdmi, 0x01, HDMI_CTRL_PKT_BUF_INDEX);
626
627 /* Packet Type = 0x04 */
628 hdmi_write(hdmi, 0x04, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
629 /* ACP_Type */
630 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
631 /* Reserved (0) */
632 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
633
634 /* GBD bytes 0 through 27 */
635 for (i = 0; i <= 27; i++)
636 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
637 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
638}
639
640/**
641 * sh_hdmi_isrc1_setup() - ISRC1 Packet
642 */
643static void sh_hdmi_isrc1_setup(struct sh_hdmi *hdmi)
644{
645 int i;
646
647 /* ISRC1 Packet */
648 hdmi_write(hdmi, 0x02, HDMI_CTRL_PKT_BUF_INDEX);
649
650 /* Packet Type = 0x05 */
651 hdmi_write(hdmi, 0x05, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
652 /* ISRC_Cont, ISRC_Valid, Reserved (0), ISRC_Status */
653 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
654 /* Reserved (0) */
655 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
656
657 /* PB0 UPC_EAN_ISRC_0-15 */
658 /* Bytes PB16-PB27 shall be set to a value of 0. */
659 for (i = 0; i <= 27; i++)
660 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
661 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
662}
663
664/**
665 * sh_hdmi_isrc2_setup() - ISRC2 Packet
666 */
667static void sh_hdmi_isrc2_setup(struct sh_hdmi *hdmi)
668{
669 int i;
670
671 /* ISRC2 Packet */
672 hdmi_write(hdmi, 0x03, HDMI_CTRL_PKT_BUF_INDEX);
673
674 /* HB0 Packet Type = 0x06 */
675 hdmi_write(hdmi, 0x06, HDMI_CTRL_PKT_BUF_ACCESS_HB0);
676 /* Reserved (0) */
677 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB1);
678 /* Reserved (0) */
679 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_HB2);
680
681 /* PB0 UPC_EAN_ISRC_16-31 */
682 /* Bytes PB16-PB27 shall be set to a value of 0. */
683 for (i = 0; i <= 27; i++)
684 /* HDMI_CTRL_PKT_BUF_ACCESS_PB0 - PB27 */
685 hdmi_write(hdmi, 0x00, HDMI_CTRL_PKT_BUF_ACCESS_PB0 + i);
686}
687
688/**
689 * sh_hdmi_configure() - Initialise HDMI for output 651 * sh_hdmi_configure() - Initialise HDMI for output
690 */ 652 */
691static void sh_hdmi_configure(struct sh_hdmi *hdmi) 653static void sh_hdmi_configure(struct sh_hdmi *hdmi)
@@ -705,18 +667,6 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
705 /* Audio InfoFrame */ 667 /* Audio InfoFrame */
706 sh_hdmi_audio_infoframe_setup(hdmi); 668 sh_hdmi_audio_infoframe_setup(hdmi);
707 669
708 /* Gamut Metadata packet */
709 sh_hdmi_gamut_metadata_setup(hdmi);
710
711 /* Audio Content Protection (ACP) Packet */
712 sh_hdmi_acp_setup(hdmi);
713
714 /* ISRC1 Packet */
715 sh_hdmi_isrc1_setup(hdmi);
716
717 /* ISRC2 Packet */
718 sh_hdmi_isrc2_setup(hdmi);
719
720 /* 670 /*
721 * Control packet auto send with VSYNC control: auto send 671 * Control packet auto send with VSYNC control: auto send
722 * General control, Gamut metadata, ISRC, and ACP packets 672 * General control, Gamut metadata, ISRC, and ACP packets
@@ -734,17 +684,42 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
734 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL); 684 hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
735} 685}
736 686
737static void sh_hdmi_read_edid(struct sh_hdmi *hdmi) 687static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
688 const struct fb_videomode *mode)
738{ 689{
739 struct fb_var_screeninfo *var = &hdmi->var; 690 long target = PICOS2KHZ(mode->pixclock) * 1000,
740 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 691 rate = clk_round_rate(hdmi->hdmi_clk, target);
741 struct fb_videomode *lcd_cfg = &pdata->lcd_chan->lcd_cfg; 692 unsigned long rate_error = rate > 0 ? abs(rate - target) : ULONG_MAX;
742 unsigned long height = var->height, width = var->width; 693
743 int i; 694 dev_dbg(hdmi->dev, "%u-%u-%u-%u x %u-%u-%u-%u\n",
695 mode->left_margin, mode->xres,
696 mode->right_margin, mode->hsync_len,
697 mode->upper_margin, mode->yres,
698 mode->lower_margin, mode->vsync_len);
699
700 dev_dbg(hdmi->dev, "\t@%lu(+/-%lu)Hz, e=%lu / 1000, r=%uHz\n", target,
701 rate_error, rate_error ? 10000 / (10 * target / rate_error) : 0,
702 mode->refresh);
703
704 return rate_error;
705}
706
707static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
708{
709 struct fb_var_screeninfo tmpvar;
710 struct fb_var_screeninfo *var = &tmpvar;
711 const struct fb_videomode *mode, *found = NULL;
712 struct fb_info *info = hdmi->info;
713 struct fb_modelist *modelist = NULL;
714 unsigned int f_width = 0, f_height = 0, f_refresh = 0;
715 unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */
716 bool exact_match = false;
744 u8 edid[128]; 717 u8 edid[128];
718 char *forced;
719 int i;
745 720
746 /* Read EDID */ 721 /* Read EDID */
747 pr_debug("Read back EDID code:"); 722 dev_dbg(hdmi->dev, "Read back EDID code:");
748 for (i = 0; i < 128; i++) { 723 for (i = 0; i < 128; i++) {
749 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW); 724 edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
750#ifdef DEBUG 725#ifdef DEBUG
@@ -759,29 +734,97 @@ static void sh_hdmi_read_edid(struct sh_hdmi *hdmi)
759#ifdef DEBUG 734#ifdef DEBUG
760 printk(KERN_CONT "\n"); 735 printk(KERN_CONT "\n");
761#endif 736#endif
762 fb_parse_edid(edid, var); 737
763 pr_debug("%u-%u-%u-%u x %u-%u-%u-%u @ %lu kHz monitor detected\n", 738 fb_edid_to_monspecs(edid, &hdmi->monspec);
764 var->left_margin, var->xres, var->right_margin, var->hsync_len, 739
765 var->upper_margin, var->yres, var->lower_margin, var->vsync_len, 740 fb_get_options("sh_mobile_lcdc", &forced);
766 PICOS2KHZ(var->pixclock)); 741 if (forced && *forced) {
767 742 /* Only primitive parsing so far */
768 /* FIXME: Use user-provided configuration instead of EDID */ 743 i = sscanf(forced, "%ux%u@%u",
769 var->width = width; 744 &f_width, &f_height, &f_refresh);
770 var->xres = lcd_cfg->xres; 745 if (i < 2) {
771 var->xres_virtual = lcd_cfg->xres; 746 f_width = 0;
772 var->left_margin = lcd_cfg->left_margin; 747 f_height = 0;
773 var->right_margin = lcd_cfg->right_margin; 748 }
774 var->hsync_len = lcd_cfg->hsync_len; 749 dev_dbg(hdmi->dev, "Forced mode %ux%u@%uHz\n",
775 var->height = height; 750 f_width, f_height, f_refresh);
776 var->yres = lcd_cfg->yres; 751 }
777 var->yres_virtual = lcd_cfg->yres * 2; 752
778 var->upper_margin = lcd_cfg->upper_margin; 753 /* Walk monitor modes to find the best or the exact match */
779 var->lower_margin = lcd_cfg->lower_margin; 754 for (i = 0, mode = hdmi->monspec.modedb;
780 var->vsync_len = lcd_cfg->vsync_len; 755 f_width && f_height && i < hdmi->monspec.modedb_len && !exact_match;
781 var->sync = lcd_cfg->sync; 756 i++, mode++) {
782 var->pixclock = lcd_cfg->pixclock; 757 unsigned long rate_error = sh_hdmi_rate_error(hdmi, mode);
783 758
784 hdmi_external_video_param(hdmi); 759 /* No interest in unmatching modes */
760 if (f_width != mode->xres || f_height != mode->yres)
761 continue;
762 if (f_refresh == mode->refresh || (!f_refresh && !rate_error))
763 /*
764 * Exact match if either the refresh rate matches or it
765 * hasn't been specified and we've found a mode, for
766 * which we can configure the clock precisely
767 */
768 exact_match = true;
769 else if (found && found_rate_error <= rate_error)
770 /*
771 * We otherwise search for the closest matching clock
772 * rate - either if no refresh rate has been specified
773 * or we cannot find an exactly matching one
774 */
775 continue;
776
777 /* Check if supported: sufficient fb memory, supported clock-rate */
778 fb_videomode_to_var(var, mode);
779
780 if (info && info->fbops->fb_check_var &&
781 info->fbops->fb_check_var(var, info)) {
782 exact_match = false;
783 continue;
784 }
785
786 found = mode;
787 found_rate_error = rate_error;
788 }
789
790 /*
791 * TODO 1: if no ->info is present, postpone running the config until
792 * after ->info first gets registered.
793 * TODO 2: consider registering the HDMI platform device from the LCDC
794 * driver, and passing ->info with HDMI platform data.
795 */
796 if (info && !found) {
797 modelist = hdmi->info->modelist.next &&
798 !list_empty(&hdmi->info->modelist) ?
799 list_entry(hdmi->info->modelist.next,
800 struct fb_modelist, list) :
801 NULL;
802
803 if (modelist) {
804 found = &modelist->mode;
805 found_rate_error = sh_hdmi_rate_error(hdmi, found);
806 }
807 }
808
809 /* No cookie today */
810 if (!found)
811 return -ENXIO;
812
813 dev_info(hdmi->dev, "Using %s mode %ux%u@%uHz (%luHz), clock error %luHz\n",
814 modelist ? "default" : "EDID", found->xres, found->yres,
815 found->refresh, PICOS2KHZ(found->pixclock) * 1000, found_rate_error);
816
817 if ((found->xres == 720 && found->yres == 480) ||
818 (found->xres == 1280 && found->yres == 720) ||
819 (found->xres == 1920 && found->yres == 1080))
820 hdmi->preprogrammed_mode = true;
821 else
822 hdmi->preprogrammed_mode = false;
823
824 fb_videomode_to_var(&hdmi->var, found);
825 sh_hdmi_external_video_param(hdmi);
826
827 return 0;
785} 828}
786 829
787static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id) 830static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
@@ -809,8 +852,8 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
809 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2); 852 hdmi_write(hdmi, 0xFF, HDMI_INTERRUPT_STATUS_2);
810 853
811 if (printk_ratelimit()) 854 if (printk_ratelimit())
812 pr_debug("IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n", 855 dev_dbg(hdmi->dev, "IRQ #%d: Status #1: 0x%x & 0x%x, #2: 0x%x & 0x%x\n",
813 irq, status1, mask1, status2, mask2); 856 irq, status1, mask1, status2, mask2);
814 857
815 if (!((status1 & mask1) | (status2 & mask2))) { 858 if (!((status1 & mask1) | (status2 & mask2))) {
816 return IRQ_NONE; 859 return IRQ_NONE;
@@ -821,7 +864,7 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
821 udelay(500); 864 udelay(500);
822 865
823 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS); 866 msens = hdmi_read(hdmi, HDMI_HOT_PLUG_MSENS_STATUS);
824 pr_debug("MSENS 0x%x\n", msens); 867 dev_dbg(hdmi->dev, "MSENS 0x%x\n", msens);
825 /* Check, if hot plug & MSENS pin status are both high */ 868 /* Check, if hot plug & MSENS pin status are both high */
826 if ((msens & 0xC0) == 0xC0) { 869 if ((msens & 0xC0) == 0xC0) {
827 /* Display plug in */ 870 /* Display plug in */
@@ -857,83 +900,176 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
857 return IRQ_HANDLED; 900 return IRQ_HANDLED;
858} 901}
859 902
860static void hdmi_display_on(void *arg, struct fb_info *info) 903/* locking: called with info->lock held, or before register_framebuffer() */
904static void sh_hdmi_display_on(void *arg, struct fb_info *info)
861{ 905{
906 /*
907 * info is guaranteed to be valid, when we are called, because our
908 * FB_EVENT_FB_UNBIND notify is also called with info->lock held
909 */
862 struct sh_hdmi *hdmi = arg; 910 struct sh_hdmi *hdmi = arg;
863 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 911 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
912 struct sh_mobile_lcdc_chan *ch = info->par;
864 913
865 if (info->var.xres != 1280 || info->var.yres != 720) { 914 dev_dbg(hdmi->dev, "%s(%p): state %x\n", __func__,
866 dev_warn(info->device, "Unsupported framebuffer geometry %ux%u\n", 915 pdata->lcd_dev, info->state);
867 info->var.xres, info->var.yres); 916
868 return; 917 /* No need to lock */
869 } 918 hdmi->info = info;
870 919
871 pr_debug("%s(%p): state %x\n", __func__, pdata->lcd_dev, info->state);
872 /* 920 /*
873 * FIXME: not a good place to store fb_info. And we cannot nullify it 921 * hp_state can be set to
874 * even on monitor disconnect. What should the lifecycle be? 922 * HDMI_HOTPLUG_DISCONNECTED: on monitor unplug
923 * HDMI_HOTPLUG_CONNECTED: on monitor plug-in
924 * HDMI_HOTPLUG_EDID_DONE: on EDID read completion
875 */ 925 */
876 hdmi->info = info;
877 switch (hdmi->hp_state) { 926 switch (hdmi->hp_state) {
878 case HDMI_HOTPLUG_EDID_DONE: 927 case HDMI_HOTPLUG_EDID_DONE:
879 /* PS mode d->e. All functions are active */ 928 /* PS mode d->e. All functions are active */
880 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL); 929 hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
881 pr_debug("HDMI running\n"); 930 dev_dbg(hdmi->dev, "HDMI running\n");
882 break; 931 break;
883 case HDMI_HOTPLUG_DISCONNECTED: 932 case HDMI_HOTPLUG_DISCONNECTED:
884 info->state = FBINFO_STATE_SUSPENDED; 933 info->state = FBINFO_STATE_SUSPENDED;
885 default: 934 default:
886 hdmi->var = info->var; 935 hdmi->var = ch->display_var;
887 } 936 }
888} 937}
889 938
890static void hdmi_display_off(void *arg) 939/* locking: called with info->lock held */
940static void sh_hdmi_display_off(void *arg)
891{ 941{
892 struct sh_hdmi *hdmi = arg; 942 struct sh_hdmi *hdmi = arg;
893 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 943 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
894 944
895 pr_debug("%s(%p)\n", __func__, pdata->lcd_dev); 945 dev_dbg(hdmi->dev, "%s(%p)\n", __func__, pdata->lcd_dev);
896 /* PS mode e->a */ 946 /* PS mode e->a */
897 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL); 947 hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
898} 948}
899 949
950static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
951{
952 struct fb_info *info = hdmi->info;
953 struct sh_mobile_lcdc_chan *ch = info->par;
954 struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var;
955 struct fb_videomode mode1, mode2;
956
957 fb_var_to_videomode(&mode1, old_var);
958 fb_var_to_videomode(&mode2, new_var);
959
960 dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
961 mode1.xres, mode1.yres, mode2.xres, mode2.yres);
962
963 if (fb_mode_is_equal(&mode1, &mode2))
964 return false;
965
966 dev_dbg(info->dev, "Switching %u -> %u lines\n",
967 mode1.yres, mode2.yres);
968 *old_var = *new_var;
969
970 return true;
971}
972
973/**
974 * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock
975 * @hdmi: driver context
976 * @pixclock: pixel clock period in picoseconds
977 * return: configured positive rate if successful
978 * 0 if couldn't set the rate, but managed to enable the clock
979 * negative error, if couldn't enable the clock
980 */
981static long sh_hdmi_clk_configure(struct sh_hdmi *hdmi, unsigned long pixclock)
982{
983 long rate;
984 int ret;
985
986 rate = PICOS2KHZ(pixclock) * 1000;
987 rate = clk_round_rate(hdmi->hdmi_clk, rate);
988 if (rate > 0) {
989 ret = clk_set_rate(hdmi->hdmi_clk, rate);
990 if (ret < 0) {
991 dev_warn(hdmi->dev, "Cannot set rate %ld: %d\n", rate, ret);
992 rate = 0;
993 } else {
994 dev_dbg(hdmi->dev, "HDMI set frequency %lu\n", rate);
995 }
996 } else {
997 rate = 0;
998 dev_warn(hdmi->dev, "Cannot get suitable rate: %ld\n", rate);
999 }
1000
1001 ret = clk_enable(hdmi->hdmi_clk);
1002 if (ret < 0) {
1003 dev_err(hdmi->dev, "Cannot enable clock: %d\n", ret);
1004 return ret;
1005 }
1006
1007 return rate;
1008}
1009
900/* Hotplug interrupt occurred, read EDID */ 1010/* Hotplug interrupt occurred, read EDID */
901static void edid_work_fn(struct work_struct *work) 1011static void sh_hdmi_edid_work_fn(struct work_struct *work)
902{ 1012{
903 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); 1013 struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work);
904 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data; 1014 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
1015 struct sh_mobile_lcdc_chan *ch;
1016 int ret;
905 1017
906 pr_debug("%s(%p): begin, hotplug status %d\n", __func__, 1018 dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__,
907 pdata->lcd_dev, hdmi->hp_state); 1019 pdata->lcd_dev, hdmi->hp_state);
908 1020
909 if (!pdata->lcd_dev) 1021 if (!pdata->lcd_dev)
910 return; 1022 return;
911 1023
1024 mutex_lock(&hdmi->mutex);
1025
912 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) { 1026 if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
913 pm_runtime_get_sync(hdmi->dev);
914 /* A device has been plugged in */ 1027 /* A device has been plugged in */
915 sh_hdmi_read_edid(hdmi); 1028 pm_runtime_get_sync(hdmi->dev);
1029
1030 ret = sh_hdmi_read_edid(hdmi);
1031 if (ret < 0)
1032 goto out;
1033
1034 /* Reconfigure the clock */
1035 clk_disable(hdmi->hdmi_clk);
1036 ret = sh_hdmi_clk_configure(hdmi, hdmi->var.pixclock);
1037 if (ret < 0)
1038 goto out;
1039
916 msleep(10); 1040 msleep(10);
917 sh_hdmi_configure(hdmi); 1041 sh_hdmi_configure(hdmi);
918 /* Switched to another (d) power-save mode */ 1042 /* Switched to another (d) power-save mode */
919 msleep(10); 1043 msleep(10);
920 1044
921 if (!hdmi->info) 1045 if (!hdmi->info)
922 return; 1046 goto out;
1047
1048 ch = hdmi->info->par;
923 1049
924 acquire_console_sem(); 1050 acquire_console_sem();
925 1051
926 /* HDMI plug in */ 1052 /* HDMI plug in */
927 hdmi->info->var = hdmi->var; 1053 if (!sh_hdmi_must_reconfigure(hdmi) &&
928 if (hdmi->info->state != FBINFO_STATE_RUNNING) 1054 hdmi->info->state == FBINFO_STATE_RUNNING) {
1055 /*
1056 * First activation with the default monitor - just turn
1057 * on, if we run a resume here, the logo disappears
1058 */
1059 if (lock_fb_info(hdmi->info)) {
1060 sh_hdmi_display_on(hdmi, hdmi->info);
1061 unlock_fb_info(hdmi->info);
1062 }
1063 } else {
1064 /* New monitor or have to wake up */
929 fb_set_suspend(hdmi->info, 0); 1065 fb_set_suspend(hdmi->info, 0);
930 else 1066 }
931 hdmi_display_on(hdmi, hdmi->info);
932 1067
933 release_console_sem(); 1068 release_console_sem();
934 } else { 1069 } else {
1070 ret = 0;
935 if (!hdmi->info) 1071 if (!hdmi->info)
936 return; 1072 goto out;
937 1073
938 acquire_console_sem(); 1074 acquire_console_sem();
939 1075
@@ -942,15 +1078,67 @@ static void edid_work_fn(struct work_struct *work)
942 1078
943 release_console_sem(); 1079 release_console_sem();
944 pm_runtime_put(hdmi->dev); 1080 pm_runtime_put(hdmi->dev);
1081 fb_destroy_modedb(hdmi->monspec.modedb);
945 } 1082 }
946 1083
947 pr_debug("%s(%p): end\n", __func__, pdata->lcd_dev); 1084out:
1085 if (ret < 0)
1086 hdmi->hp_state = HDMI_HOTPLUG_DISCONNECTED;
1087 mutex_unlock(&hdmi->mutex);
1088
1089 dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, pdata->lcd_dev);
1090}
1091
1092static int sh_hdmi_notify(struct notifier_block *nb,
1093 unsigned long action, void *data);
1094
1095static struct notifier_block sh_hdmi_notifier = {
1096 .notifier_call = sh_hdmi_notify,
1097};
1098
1099static int sh_hdmi_notify(struct notifier_block *nb,
1100 unsigned long action, void *data)
1101{
1102 struct fb_event *event = data;
1103 struct fb_info *info = event->info;
1104 struct sh_mobile_lcdc_chan *ch = info->par;
1105 struct sh_mobile_lcdc_board_cfg *board_cfg = &ch->cfg.board_cfg;
1106 struct sh_hdmi *hdmi = board_cfg->board_data;
1107
1108 if (nb != &sh_hdmi_notifier || !hdmi || hdmi->info != info)
1109 return NOTIFY_DONE;
1110
1111 switch(action) {
1112 case FB_EVENT_FB_REGISTERED:
1113 /* Unneeded, activation taken care by sh_hdmi_display_on() */
1114 break;
1115 case FB_EVENT_FB_UNREGISTERED:
1116 /*
1117 * We are called from unregister_framebuffer() with the
1118 * info->lock held. This is bad for us, because we can race with
1119 * the scheduled work, which has to call fb_set_suspend(), which
1120 * takes info->lock internally, so, sh_hdmi_edid_work_fn()
1121 * cannot take and hold info->lock for the whole function
1122 * duration. Using an additional lock creates a classical AB-BA
1123 * lock up. Therefore, we have to release the info->lock
1124 * temporarily, synchronise with the work queue and re-acquire
1125 * the info->lock.
1126 */
1127 unlock_fb_info(hdmi->info);
1128 mutex_lock(&hdmi->mutex);
1129 hdmi->info = NULL;
1130 mutex_unlock(&hdmi->mutex);
1131 lock_fb_info(hdmi->info);
1132 return NOTIFY_OK;
1133 }
1134 return NOTIFY_DONE;
948} 1135}
949 1136
950static int __init sh_hdmi_probe(struct platform_device *pdev) 1137static int __init sh_hdmi_probe(struct platform_device *pdev)
951{ 1138{
952 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1139 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
953 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1140 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1141 struct sh_mobile_lcdc_board_cfg *board_cfg;
954 int irq = platform_get_irq(pdev, 0), ret; 1142 int irq = platform_get_irq(pdev, 0), ret;
955 struct sh_hdmi *hdmi; 1143 struct sh_hdmi *hdmi;
956 long rate; 1144 long rate;
@@ -964,10 +1152,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
964 return -ENOMEM; 1152 return -ENOMEM;
965 } 1153 }
966 1154
967 ret = snd_soc_register_codec(&pdev->dev, 1155 mutex_init(&hdmi->mutex);
968 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
969 if (ret < 0)
970 goto esndreg;
971 1156
972 hdmi->dev = &pdev->dev; 1157 hdmi->dev = &pdev->dev;
973 1158
@@ -978,30 +1163,14 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
978 goto egetclk; 1163 goto egetclk;
979 } 1164 }
980 1165
981 rate = PICOS2KHZ(pdata->lcd_chan->lcd_cfg.pixclock) * 1000; 1166 /* Some arbitrary relaxed pixclock just to get things started */
982 1167 rate = sh_hdmi_clk_configure(hdmi, 37037);
983 rate = clk_round_rate(hdmi->hdmi_clk, rate);
984 if (rate < 0) { 1168 if (rate < 0) {
985 ret = rate; 1169 ret = rate;
986 dev_err(&pdev->dev, "Cannot get suitable rate: %ld\n", rate);
987 goto erate; 1170 goto erate;
988 } 1171 }
989 1172
990 ret = clk_set_rate(hdmi->hdmi_clk, rate); 1173 dev_dbg(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
991 if (ret < 0) {
992 dev_err(&pdev->dev, "Cannot set rate %ld: %d\n", rate, ret);
993 goto erate;
994 }
995
996 pr_debug("HDMI set frequency %lu\n", rate);
997
998 ret = clk_enable(hdmi->hdmi_clk);
999 if (ret < 0) {
1000 dev_err(&pdev->dev, "Cannot enable clock: %d\n", ret);
1001 goto eclkenable;
1002 }
1003
1004 dev_info(&pdev->dev, "Enabled HDMI clock at %luHz\n", rate);
1005 1174
1006 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) { 1175 if (!request_mem_region(res->start, resource_size(res), dev_name(&pdev->dev))) {
1007 dev_err(&pdev->dev, "HDMI register region already claimed\n"); 1176 dev_err(&pdev->dev, "HDMI register region already claimed\n");
@@ -1018,18 +1187,18 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1018 1187
1019 platform_set_drvdata(pdev, hdmi); 1188 platform_set_drvdata(pdev, hdmi);
1020 1189
1021#if 1
1022 /* Product and revision IDs are 0 in sh-mobile version */ 1190 /* Product and revision IDs are 0 in sh-mobile version */
1023 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n", 1191 dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
1024 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID)); 1192 hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
1025#endif
1026 1193
1027 /* Set up LCDC callbacks */ 1194 /* Set up LCDC callbacks */
1028 pdata->lcd_chan->board_cfg.board_data = hdmi; 1195 board_cfg = &pdata->lcd_chan->board_cfg;
1029 pdata->lcd_chan->board_cfg.display_on = hdmi_display_on; 1196 board_cfg->owner = THIS_MODULE;
1030 pdata->lcd_chan->board_cfg.display_off = hdmi_display_off; 1197 board_cfg->board_data = hdmi;
1198 board_cfg->display_on = sh_hdmi_display_on;
1199 board_cfg->display_off = sh_hdmi_display_off;
1031 1200
1032 INIT_DELAYED_WORK(&hdmi->edid_work, edid_work_fn); 1201 INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
1033 1202
1034 pm_runtime_enable(&pdev->dev); 1203 pm_runtime_enable(&pdev->dev);
1035 pm_runtime_resume(&pdev->dev); 1204 pm_runtime_resume(&pdev->dev);
@@ -1041,8 +1210,17 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
1041 goto ereqirq; 1210 goto ereqirq;
1042 } 1211 }
1043 1212
1213 ret = snd_soc_register_codec(&pdev->dev,
1214 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
1215 if (ret < 0) {
1216 dev_err(&pdev->dev, "codec registration failed\n");
1217 goto ecodec;
1218 }
1219
1044 return 0; 1220 return 0;
1045 1221
1222ecodec:
1223 free_irq(irq, hdmi);
1046ereqirq: 1224ereqirq:
1047 pm_runtime_disable(&pdev->dev); 1225 pm_runtime_disable(&pdev->dev);
1048 iounmap(hdmi->base); 1226 iounmap(hdmi->base);
@@ -1050,12 +1228,10 @@ emap:
1050 release_mem_region(res->start, resource_size(res)); 1228 release_mem_region(res->start, resource_size(res));
1051ereqreg: 1229ereqreg:
1052 clk_disable(hdmi->hdmi_clk); 1230 clk_disable(hdmi->hdmi_clk);
1053eclkenable:
1054erate: 1231erate:
1055 clk_put(hdmi->hdmi_clk); 1232 clk_put(hdmi->hdmi_clk);
1056egetclk: 1233egetclk:
1057 snd_soc_unregister_codec(&pdev->dev); 1234 mutex_destroy(&hdmi->mutex);
1058esndreg:
1059 kfree(hdmi); 1235 kfree(hdmi);
1060 1236
1061 return ret; 1237 return ret;
@@ -1066,21 +1242,26 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
1066 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data; 1242 struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
1067 struct sh_hdmi *hdmi = platform_get_drvdata(pdev); 1243 struct sh_hdmi *hdmi = platform_get_drvdata(pdev);
1068 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1244 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1245 struct sh_mobile_lcdc_board_cfg *board_cfg = &pdata->lcd_chan->board_cfg;
1069 int irq = platform_get_irq(pdev, 0); 1246 int irq = platform_get_irq(pdev, 0);
1070 1247
1071 snd_soc_unregister_codec(&pdev->dev); 1248 snd_soc_unregister_codec(&pdev->dev);
1072 1249
1073 pdata->lcd_chan->board_cfg.display_on = NULL; 1250 board_cfg->display_on = NULL;
1074 pdata->lcd_chan->board_cfg.display_off = NULL; 1251 board_cfg->display_off = NULL;
1075 pdata->lcd_chan->board_cfg.board_data = NULL; 1252 board_cfg->board_data = NULL;
1253 board_cfg->owner = NULL;
1076 1254
1255 /* No new work will be scheduled, wait for running ISR */
1077 free_irq(irq, hdmi); 1256 free_irq(irq, hdmi);
1078 pm_runtime_disable(&pdev->dev); 1257 /* Wait for already scheduled work */
1079 cancel_delayed_work_sync(&hdmi->edid_work); 1258 cancel_delayed_work_sync(&hdmi->edid_work);
1259 pm_runtime_disable(&pdev->dev);
1080 clk_disable(hdmi->hdmi_clk); 1260 clk_disable(hdmi->hdmi_clk);
1081 clk_put(hdmi->hdmi_clk); 1261 clk_put(hdmi->hdmi_clk);
1082 iounmap(hdmi->base); 1262 iounmap(hdmi->base);
1083 release_mem_region(res->start, resource_size(res)); 1263 release_mem_region(res->start, resource_size(res));
1264 mutex_destroy(&hdmi->mutex);
1084 kfree(hdmi); 1265 kfree(hdmi);
1085 1266
1086 return 0; 1267 return 0;