aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2015-08-26 23:01:57 -0400
committerDave Airlie <airlied@redhat.com>2015-08-26 23:01:57 -0400
commitd7b273685fedba5359a4ba0ae4f542e3ece28153 (patch)
tree6d4ad284a40820492b73a0790e760ca34644e0da
parent31607793ee81da3f1024df9560f0dec49abde37f (diff)
parent6dc2e1bf8e0025db2ff8a35ee3e0bd88203d4402 (diff)
Merge branch 'drm-dwhdmi-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into drm-next
Here are some development updates for the Synopsis Designware HDMI driver, which clean up some of the code, and start preparing to add audio support to the driver. This series of patches are based on a couple of dependent commits from the ALSA tree. Briefly, the updates are: - move comments which should have moved with the phy values to the IMX part of the driver. - clean up the phy configuration: to all lookups before starting to program the phy. - clean up the HDMI clock regenerator code - use the drm_hdmi_avi_infoframe_from_display_mode() helper which allows the code to be subsequently simplified - remove the unused 'regmap' pointer in struct dw_hdmi - use the bridge drm device rather than the connector (we're the bridge code) - remove private hsync/vsync/interlaced flags, getting them from the DRM mode structure instead. - implement interface functions to support audio - setting the audio sample rate, and enabling the audio clocks. - removal of broken pixel repetition support - cleanup DVI vs HDMI sink handling - enable audio only if connected device supports audio - avoid double-enabling bridge in the sink path (once in mode_set, and again in commit) - rename mis-named dw_hdmi_phy_enable_power() - fix bridge enable/disable handing, so a plug-in event doesn't reconfigure the bridge if DRM has disabled the output - fix from Vladimir Zapolskiy for the I2CM_ADDRESS macro name These are primerily preparitory patches for the AHB audio driver and the I2S audio driver (from Rockchip) for this IP. * 'drm-dwhdmi-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: drm: bridge/dw_hdmi: fix register I2CM_ADDRESS register name drm: bridge/dw_hdmi: fix phy enable/disable handling drm: bridge/dw_hdmi: rename dw_hdmi_phy_enable_power() drm: bridge/dw_hdmi: avoid enabling interface in mode_set drm: bridge/dw_hdmi: enable audio only if sink supports audio drm: bridge/dw_hdmi: clean up HDMI vs DVI mode handling drm: bridge/dw_hdmi: don't support any pixel doubled modes drm: bridge/dw_hdmi: remove pixel repetition setting for all VICs drm: bridge/dw_hdmi: introduce interfaces to enable and disable audio drm: bridge/dw_hdmi: introduce interface to setting sample rate drm: bridge/dw_hdmi: remove mhsyncpolarity/mvsyncpolarity/minterlaced drm: bridge/dw_hdmi: use our own drm_device drm: bridge/dw_hdmi: remove unused 'regmap' struct member drm: bridge/dw_hdmi: simplify hdmi_config_AVI() a little drm: bridge/dw_hdmi: use drm_hdmi_avi_infoframe_from_display_mode() drm: bridge/dw_hdmi: clean up hdmi_set_clk_regenerator() drm: bridge/dw_hdmi: clean up phy configuration drm: imx/dw_hdmi: move phy comments drm/edid: add function to help find SADs
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.c387
-rw-r--r--drivers/gpu/drm/bridge/dw_hdmi.h8
-rw-r--r--drivers/gpu/drm/imx/dw_hdmi-imx.c5
-rw-r--r--include/drm/bridge/dw_hdmi.h7
4 files changed, 233 insertions, 174 deletions
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.c b/drivers/gpu/drm/bridge/dw_hdmi.c
index 816d104ca4da..0083d4e7e7e2 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.c
+++ b/drivers/gpu/drm/bridge/dw_hdmi.c
@@ -18,6 +18,7 @@
18#include <linux/hdmi.h> 18#include <linux/hdmi.h>
19#include <linux/mutex.h> 19#include <linux/mutex.h>
20#include <linux/of_device.h> 20#include <linux/of_device.h>
21#include <linux/spinlock.h>
21 22
22#include <drm/drm_of.h> 23#include <drm/drm_of.h>
23#include <drm/drmP.h> 24#include <drm/drmP.h>
@@ -81,10 +82,6 @@ static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
81}; 82};
82 83
83struct hdmi_vmode { 84struct hdmi_vmode {
84 bool mdvi;
85 bool mhsyncpolarity;
86 bool mvsyncpolarity;
87 bool minterlaced;
88 bool mdataenablepolarity; 85 bool mdataenablepolarity;
89 86
90 unsigned int mpixelclock; 87 unsigned int mpixelclock;
@@ -123,12 +120,20 @@ struct dw_hdmi {
123 bool phy_enabled; 120 bool phy_enabled;
124 struct drm_display_mode previous_mode; 121 struct drm_display_mode previous_mode;
125 122
126 struct regmap *regmap;
127 struct i2c_adapter *ddc; 123 struct i2c_adapter *ddc;
128 void __iomem *regs; 124 void __iomem *regs;
125 bool sink_is_hdmi;
126 bool sink_has_audio;
129 127
128 struct mutex mutex; /* for state below and previous_mode */
129 bool disabled; /* DRM has disabled our bridge */
130
131 spinlock_t audio_lock;
130 struct mutex audio_mutex; 132 struct mutex audio_mutex;
131 unsigned int sample_rate; 133 unsigned int sample_rate;
134 unsigned int audio_cts;
135 unsigned int audio_n;
136 bool audio_enable;
132 int ratio; 137 int ratio;
133 138
134 void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); 139 void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
@@ -335,42 +340,76 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
335} 340}
336 341
337static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, 342static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi,
338 unsigned long pixel_clk) 343 unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio)
339{ 344{
340 unsigned int clk_n, clk_cts; 345 unsigned int n, cts;
341
342 clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
343 hdmi->ratio);
344 clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
345 hdmi->ratio);
346 346
347 if (!clk_cts) { 347 n = hdmi_compute_n(sample_rate, pixel_clk, ratio);
348 dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", 348 cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio);
349 __func__, pixel_clk); 349 if (!cts) {
350 return; 350 dev_err(hdmi->dev,
351 "%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n",
352 __func__, pixel_clk, sample_rate);
351 } 353 }
352 354
353 dev_dbg(hdmi->dev, "%s: samplerate=%d ratio=%d pixelclk=%lu N=%d cts=%d\n", 355 dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n",
354 __func__, hdmi->sample_rate, hdmi->ratio, 356 __func__, sample_rate, ratio, pixel_clk, n, cts);
355 pixel_clk, clk_n, clk_cts);
356 357
357 hdmi_set_cts_n(hdmi, clk_cts, clk_n); 358 spin_lock_irq(&hdmi->audio_lock);
359 hdmi->audio_n = n;
360 hdmi->audio_cts = cts;
361 hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0);
362 spin_unlock_irq(&hdmi->audio_lock);
358} 363}
359 364
360static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) 365static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi)
361{ 366{
362 mutex_lock(&hdmi->audio_mutex); 367 mutex_lock(&hdmi->audio_mutex);
363 hdmi_set_clk_regenerator(hdmi, 74250000); 368 hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate,
369 hdmi->ratio);
364 mutex_unlock(&hdmi->audio_mutex); 370 mutex_unlock(&hdmi->audio_mutex);
365} 371}
366 372
367static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) 373static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi)
368{ 374{
369 mutex_lock(&hdmi->audio_mutex); 375 mutex_lock(&hdmi->audio_mutex);
370 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock); 376 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
377 hdmi->sample_rate, hdmi->ratio);
371 mutex_unlock(&hdmi->audio_mutex); 378 mutex_unlock(&hdmi->audio_mutex);
372} 379}
373 380
381void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate)
382{
383 mutex_lock(&hdmi->audio_mutex);
384 hdmi->sample_rate = rate;
385 hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock,
386 hdmi->sample_rate, hdmi->ratio);
387 mutex_unlock(&hdmi->audio_mutex);
388}
389EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate);
390
391void dw_hdmi_audio_enable(struct dw_hdmi *hdmi)
392{
393 unsigned long flags;
394
395 spin_lock_irqsave(&hdmi->audio_lock, flags);
396 hdmi->audio_enable = true;
397 hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
398 spin_unlock_irqrestore(&hdmi->audio_lock, flags);
399}
400EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable);
401
402void dw_hdmi_audio_disable(struct dw_hdmi *hdmi)
403{
404 unsigned long flags;
405
406 spin_lock_irqsave(&hdmi->audio_lock, flags);
407 hdmi->audio_enable = false;
408 hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0);
409 spin_unlock_irqrestore(&hdmi->audio_lock, flags);
410}
411EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable);
412
374/* 413/*
375 * this submodule is responsible for the video data synchronization. 414 * this submodule is responsible for the video data synchronization.
376 * for example, for RGB 4:4:4 input, the data map is defined as 415 * for example, for RGB 4:4:4 input, the data map is defined as
@@ -701,9 +740,9 @@ static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data,
701 return 0; 740 return 0;
702} 741}
703 742
704static void dw_hdmi_phy_enable_power(struct dw_hdmi *hdmi, u8 enable) 743static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable)
705{ 744{
706 hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 745 hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0,
707 HDMI_PHY_CONF0_PDZ_OFFSET, 746 HDMI_PHY_CONF0_PDZ_OFFSET,
708 HDMI_PHY_CONF0_PDZ_MASK); 747 HDMI_PHY_CONF0_PDZ_MASK);
709} 748}
@@ -753,12 +792,12 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable)
753static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, 792static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
754 unsigned char res, int cscon) 793 unsigned char res, int cscon)
755{ 794{
756 unsigned res_idx, i; 795 unsigned res_idx;
757 u8 val, msec; 796 u8 val, msec;
758 const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data; 797 const struct dw_hdmi_plat_data *pdata = hdmi->plat_data;
759 const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg; 798 const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
760 const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr; 799 const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
761 const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config; 800 const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
762 801
763 if (prep) 802 if (prep)
764 return -EINVAL; 803 return -EINVAL;
@@ -778,6 +817,30 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
778 return -EINVAL; 817 return -EINVAL;
779 } 818 }
780 819
820 /* PLL/MPLL Cfg - always match on final entry */
821 for (; mpll_config->mpixelclock != ~0UL; mpll_config++)
822 if (hdmi->hdmi_data.video_mode.mpixelclock <=
823 mpll_config->mpixelclock)
824 break;
825
826 for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++)
827 if (hdmi->hdmi_data.video_mode.mpixelclock <=
828 curr_ctrl->mpixelclock)
829 break;
830
831 for (; phy_config->mpixelclock != ~0UL; phy_config++)
832 if (hdmi->hdmi_data.video_mode.mpixelclock <=
833 phy_config->mpixelclock)
834 break;
835
836 if (mpll_config->mpixelclock == ~0UL ||
837 curr_ctrl->mpixelclock == ~0UL ||
838 phy_config->mpixelclock == ~0UL) {
839 dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
840 hdmi->hdmi_data.video_mode.mpixelclock);
841 return -EINVAL;
842 }
843
781 /* Enable csc path */ 844 /* Enable csc path */
782 if (cscon) 845 if (cscon)
783 val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH; 846 val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
@@ -803,48 +866,23 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
803 HDMI_PHY_I2CM_SLAVE_ADDR); 866 HDMI_PHY_I2CM_SLAVE_ADDR);
804 hdmi_phy_test_clear(hdmi, 0); 867 hdmi_phy_test_clear(hdmi, 0);
805 868
806 /* PLL/MPLL Cfg - always match on final entry */ 869 hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
807 for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++) 870 hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
808 if (hdmi->hdmi_data.video_mode.mpixelclock <=
809 mpll_config[i].mpixelclock)
810 break;
811
812 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
813 hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
814
815 for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++)
816 if (hdmi->hdmi_data.video_mode.mpixelclock <=
817 curr_ctrl[i].mpixelclock)
818 break;
819
820 if (curr_ctrl[i].mpixelclock == (~0UL)) {
821 dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
822 hdmi->hdmi_data.video_mode.mpixelclock);
823 return -EINVAL;
824 }
825 871
826 /* CURRCTRL */ 872 /* CURRCTRL */
827 hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10); 873 hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
828 874
829 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ 875 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
830 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); 876 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
831 877
832 for (i = 0; phy_config[i].mpixelclock != (~0UL); i++) 878 hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19); /* TXTERM */
833 if (hdmi->hdmi_data.video_mode.mpixelclock <= 879 hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
834 phy_config[i].mpixelclock) 880 hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
835 break;
836
837 /* RESISTANCE TERM 133Ohm Cfg */
838 hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19); /* TXTERM */
839 /* PREEMP Cgf 0.00 */
840 hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
841 /* TX/CK LVL 10 */
842 hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */
843 881
844 /* REMOVE CLK TERM */ 882 /* REMOVE CLK TERM */
845 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ 883 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
846 884
847 dw_hdmi_phy_enable_power(hdmi, 1); 885 dw_hdmi_phy_enable_powerdown(hdmi, false);
848 886
849 /* toggle TMDS enable */ 887 /* toggle TMDS enable */
850 dw_hdmi_phy_enable_tmds(hdmi, 0); 888 dw_hdmi_phy_enable_tmds(hdmi, 0);
@@ -879,18 +917,17 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
879static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) 917static int dw_hdmi_phy_init(struct dw_hdmi *hdmi)
880{ 918{
881 int i, ret; 919 int i, ret;
882 bool cscon = false; 920 bool cscon;
883 921
884 /*check csc whether needed activated in HDMI mode */ 922 /*check csc whether needed activated in HDMI mode */
885 cscon = (is_color_space_conversion(hdmi) && 923 cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi);
886 !hdmi->hdmi_data.video_mode.mdvi);
887 924
888 /* HDMI Phy spec says to do the phy initialization sequence twice */ 925 /* HDMI Phy spec says to do the phy initialization sequence twice */
889 for (i = 0; i < 2; i++) { 926 for (i = 0; i < 2; i++) {
890 dw_hdmi_phy_sel_data_en_pol(hdmi, 1); 927 dw_hdmi_phy_sel_data_en_pol(hdmi, 1);
891 dw_hdmi_phy_sel_interface_control(hdmi, 0); 928 dw_hdmi_phy_sel_interface_control(hdmi, 0);
892 dw_hdmi_phy_enable_tmds(hdmi, 0); 929 dw_hdmi_phy_enable_tmds(hdmi, 0);
893 dw_hdmi_phy_enable_power(hdmi, 0); 930 dw_hdmi_phy_enable_powerdown(hdmi, true);
894 931
895 /* Enable CSC */ 932 /* Enable CSC */
896 ret = hdmi_phy_configure(hdmi, 0, 8, cscon); 933 ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
@@ -921,74 +958,76 @@ static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi)
921 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); 958 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
922} 959}
923 960
924static void hdmi_config_AVI(struct dw_hdmi *hdmi) 961static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
925{ 962{
926 u8 val, pix_fmt, under_scan; 963 struct hdmi_avi_infoframe frame;
927 u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry; 964 u8 val;
928 bool aspect_16_9;
929 965
930 aspect_16_9 = false; /* FIXME */ 966 /* Initialise info frame from DRM mode */
967 drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
931 968
932 /* AVI Data Byte 1 */
933 if (hdmi->hdmi_data.enc_out_format == YCBCR444) 969 if (hdmi->hdmi_data.enc_out_format == YCBCR444)
934 pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444; 970 frame.colorspace = HDMI_COLORSPACE_YUV444;
935 else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) 971 else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS)
936 pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422; 972 frame.colorspace = HDMI_COLORSPACE_YUV422;
937 else 973 else
938 pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB; 974 frame.colorspace = HDMI_COLORSPACE_RGB;
939
940 under_scan = HDMI_FC_AVICONF0_SCAN_INFO_NODATA;
941
942 /*
943 * Active format identification data is present in the AVI InfoFrame.
944 * Under scan info, no bar data
945 */
946 val = pix_fmt | under_scan |
947 HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT |
948 HDMI_FC_AVICONF0_BAR_DATA_NO_DATA;
949
950 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
951
952 /* AVI Data Byte 2 -Set the Aspect Ratio */
953 if (aspect_16_9) {
954 act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9;
955 coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9;
956 } else {
957 act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3;
958 coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3;
959 }
960 975
961 /* Set up colorimetry */ 976 /* Set up colorimetry */
962 if (hdmi->hdmi_data.enc_out_format == XVYCC444) { 977 if (hdmi->hdmi_data.enc_out_format == XVYCC444) {
963 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO; 978 frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
964 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) 979 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
965 ext_colorimetry = 980 frame.extended_colorimetry =
966 HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; 981 HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
967 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ 982 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
968 ext_colorimetry = 983 frame.extended_colorimetry =
969 HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709; 984 HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
970 } else if (hdmi->hdmi_data.enc_out_format != RGB) { 985 } else if (hdmi->hdmi_data.enc_out_format != RGB) {
971 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) 986 frame.colorimetry = hdmi->hdmi_data.colorimetry;
972 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE; 987 frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
973 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/
974 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR;
975 ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601;
976 } else { /* Carries no data */ 988 } else { /* Carries no data */
977 colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA; 989 frame.colorimetry = HDMI_COLORIMETRY_NONE;
978 ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; 990 frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
979 } 991 }
980 992
981 val = colorimetry | coded_ratio | act_ratio; 993 frame.scan_mode = HDMI_SCAN_MODE_NONE;
994
995 /*
996 * The Designware IP uses a different byte format from standard
997 * AVI info frames, though generally the bits are in the correct
998 * bytes.
999 */
1000
1001 /*
1002 * AVI data byte 1 differences: Colorspace in bits 4,5 rather than 5,6,
1003 * active aspect present in bit 6 rather than 4.
1004 */
1005 val = (frame.colorspace & 3) << 4 | (frame.scan_mode & 0x3);
1006 if (frame.active_aspect & 15)
1007 val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT;
1008 if (frame.top_bar || frame.bottom_bar)
1009 val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR;
1010 if (frame.left_bar || frame.right_bar)
1011 val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR;
1012 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0);
1013
1014 /* AVI data byte 2 differences: none */
1015 val = ((frame.colorimetry & 0x3) << 6) |
1016 ((frame.picture_aspect & 0x3) << 4) |
1017 (frame.active_aspect & 0xf);
982 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1); 1018 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1);
983 1019
984 /* AVI Data Byte 3 */ 1020 /* AVI data byte 3 differences: none */
985 val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry | 1021 val = ((frame.extended_colorimetry & 0x7) << 4) |
986 HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT | 1022 ((frame.quantization_range & 0x3) << 2) |
987 HDMI_FC_AVICONF2_SCALING_NONE; 1023 (frame.nups & 0x3);
1024 if (frame.itc)
1025 val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID;
988 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2); 1026 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2);
989 1027
990 /* AVI Data Byte 4 */ 1028 /* AVI data byte 4 differences: none */
991 hdmi_writeb(hdmi, hdmi->vic, HDMI_FC_AVIVID); 1029 val = frame.video_code & 0x7f;
1030 hdmi_writeb(hdmi, val, HDMI_FC_AVIVID);
992 1031
993 /* AVI Data Byte 5- set up input and output pixel repetition */ 1032 /* AVI Data Byte 5- set up input and output pixel repetition */
994 val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) << 1033 val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) <<
@@ -999,20 +1038,23 @@ static void hdmi_config_AVI(struct dw_hdmi *hdmi)
999 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK); 1038 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK);
1000 hdmi_writeb(hdmi, val, HDMI_FC_PRCONF); 1039 hdmi_writeb(hdmi, val, HDMI_FC_PRCONF);
1001 1040
1002 /* IT Content and quantization range = don't care */ 1041 /*
1003 val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS | 1042 * AVI data byte 5 differences: content type in 0,1 rather than 4,5,
1004 HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED; 1043 * ycc range in bits 2,3 rather than 6,7
1044 */
1045 val = ((frame.ycc_quantization_range & 0x3) << 2) |
1046 (frame.content_type & 0x3);
1005 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3); 1047 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3);
1006 1048
1007 /* AVI Data Bytes 6-13 */ 1049 /* AVI Data Bytes 6-13 */
1008 hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB0); 1050 hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0);
1009 hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB1); 1051 hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1);
1010 hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB0); 1052 hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0);
1011 hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB1); 1053 hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1);
1012 hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB0); 1054 hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0);
1013 hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB1); 1055 hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1);
1014 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB0); 1056 hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0);
1015 hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1); 1057 hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1);
1016} 1058}
1017 1059
1018static void hdmi_av_composer(struct dw_hdmi *hdmi, 1060static void hdmi_av_composer(struct dw_hdmi *hdmi,
@@ -1022,9 +1064,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
1022 struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; 1064 struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode;
1023 int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; 1065 int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len;
1024 1066
1025 vmode->mhsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC);
1026 vmode->mvsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC);
1027 vmode->minterlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
1028 vmode->mpixelclock = mode->clock * 1000; 1067 vmode->mpixelclock = mode->clock * 1000;
1029 1068
1030 dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); 1069 dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock);
@@ -1034,13 +1073,13 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
1034 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : 1073 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE :
1035 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); 1074 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE);
1036 1075
1037 inv_val |= (vmode->mvsyncpolarity ? 1076 inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
1038 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : 1077 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
1039 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW); 1078 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW;
1040 1079
1041 inv_val |= (vmode->mhsyncpolarity ? 1080 inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
1042 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : 1081 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
1043 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW); 1082 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW;
1044 1083
1045 inv_val |= (vmode->mdataenablepolarity ? 1084 inv_val |= (vmode->mdataenablepolarity ?
1046 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : 1085 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
@@ -1049,17 +1088,17 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
1049 if (hdmi->vic == 39) 1088 if (hdmi->vic == 39)
1050 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH; 1089 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH;
1051 else 1090 else
1052 inv_val |= (vmode->minterlaced ? 1091 inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
1053 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH : 1092 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH :
1054 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW); 1093 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
1055 1094
1056 inv_val |= (vmode->minterlaced ? 1095 inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
1057 HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : 1096 HDMI_FC_INVIDCONF_IN_I_P_INTERLACED :
1058 HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE); 1097 HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
1059 1098
1060 inv_val |= (vmode->mdvi ? 1099 inv_val |= hdmi->sink_is_hdmi ?
1061 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE : 1100 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
1062 HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE); 1101 HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE;
1063 1102
1064 hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); 1103 hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF);
1065 1104
@@ -1105,7 +1144,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi)
1105 return; 1144 return;
1106 1145
1107 dw_hdmi_phy_enable_tmds(hdmi, 0); 1146 dw_hdmi_phy_enable_tmds(hdmi, 0);
1108 dw_hdmi_phy_enable_power(hdmi, 0); 1147 dw_hdmi_phy_enable_powerdown(hdmi, true);
1109 1148
1110 hdmi->phy_enabled = false; 1149 hdmi->phy_enabled = false;
1111} 1150}
@@ -1186,10 +1225,8 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
1186 1225
1187 if (!hdmi->vic) { 1226 if (!hdmi->vic) {
1188 dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); 1227 dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
1189 hdmi->hdmi_data.video_mode.mdvi = true;
1190 } else { 1228 } else {
1191 dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); 1229 dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic);
1192 hdmi->hdmi_data.video_mode.mdvi = false;
1193 } 1230 }
1194 1231
1195 if ((hdmi->vic == 6) || (hdmi->vic == 7) || 1232 if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
@@ -1200,18 +1237,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
1200 else 1237 else
1201 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; 1238 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
1202 1239
1203 if ((hdmi->vic == 10) || (hdmi->vic == 11) || 1240 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
1204 (hdmi->vic == 12) || (hdmi->vic == 13) ||
1205 (hdmi->vic == 14) || (hdmi->vic == 15) ||
1206 (hdmi->vic == 25) || (hdmi->vic == 26) ||
1207 (hdmi->vic == 27) || (hdmi->vic == 28) ||
1208 (hdmi->vic == 29) || (hdmi->vic == 30) ||
1209 (hdmi->vic == 35) || (hdmi->vic == 36) ||
1210 (hdmi->vic == 37) || (hdmi->vic == 38))
1211 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1;
1212 else
1213 hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
1214
1215 hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; 1241 hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
1216 1242
1217 /* TODO: Get input format from IPU (via FB driver interface) */ 1243 /* TODO: Get input format from IPU (via FB driver interface) */
@@ -1235,18 +1261,22 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
1235 /* HDMI Initialization Step B.3 */ 1261 /* HDMI Initialization Step B.3 */
1236 dw_hdmi_enable_video_path(hdmi); 1262 dw_hdmi_enable_video_path(hdmi);
1237 1263
1238 /* not for DVI mode */ 1264 if (hdmi->sink_has_audio) {
1239 if (hdmi->hdmi_data.video_mode.mdvi) { 1265 dev_dbg(hdmi->dev, "sink has audio support\n");
1240 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
1241 } else {
1242 dev_dbg(hdmi->dev, "%s CEA mode\n", __func__);
1243 1266
1244 /* HDMI Initialization Step E - Configure audio */ 1267 /* HDMI Initialization Step E - Configure audio */
1245 hdmi_clk_regenerator_update_pixel_clock(hdmi); 1268 hdmi_clk_regenerator_update_pixel_clock(hdmi);
1246 hdmi_enable_audio_clk(hdmi); 1269 hdmi_enable_audio_clk(hdmi);
1270 }
1271
1272 /* not for DVI mode */
1273 if (hdmi->sink_is_hdmi) {
1274 dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__);
1247 1275
1248 /* HDMI Initialization Step F - Configure AVI InfoFrame */ 1276 /* HDMI Initialization Step F - Configure AVI InfoFrame */
1249 hdmi_config_AVI(hdmi); 1277 hdmi_config_AVI(hdmi, mode);
1278 } else {
1279 dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
1250 } 1280 }
1251 1281
1252 hdmi_video_packetize(hdmi); 1282 hdmi_video_packetize(hdmi);
@@ -1255,7 +1285,7 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode)
1255 hdmi_tx_hdcp_config(hdmi); 1285 hdmi_tx_hdcp_config(hdmi);
1256 1286
1257 dw_hdmi_clear_overflow(hdmi); 1287 dw_hdmi_clear_overflow(hdmi);
1258 if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi) 1288 if (hdmi->cable_plugin && hdmi->sink_is_hdmi)
1259 hdmi_enable_overflow_interrupts(hdmi); 1289 hdmi_enable_overflow_interrupts(hdmi);
1260 1290
1261 return 0; 1291 return 0;
@@ -1348,10 +1378,12 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
1348{ 1378{
1349 struct dw_hdmi *hdmi = bridge->driver_private; 1379 struct dw_hdmi *hdmi = bridge->driver_private;
1350 1380
1351 dw_hdmi_setup(hdmi, mode); 1381 mutex_lock(&hdmi->mutex);
1352 1382
1353 /* Store the display mode for plugin/DKMS poweron events */ 1383 /* Store the display mode for plugin/DKMS poweron events */
1354 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); 1384 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
1385
1386 mutex_unlock(&hdmi->mutex);
1355} 1387}
1356 1388
1357static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, 1389static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
@@ -1365,14 +1397,20 @@ static void dw_hdmi_bridge_disable(struct drm_bridge *bridge)
1365{ 1397{
1366 struct dw_hdmi *hdmi = bridge->driver_private; 1398 struct dw_hdmi *hdmi = bridge->driver_private;
1367 1399
1400 mutex_lock(&hdmi->mutex);
1401 hdmi->disabled = true;
1368 dw_hdmi_poweroff(hdmi); 1402 dw_hdmi_poweroff(hdmi);
1403 mutex_unlock(&hdmi->mutex);
1369} 1404}
1370 1405
1371static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) 1406static void dw_hdmi_bridge_enable(struct drm_bridge *bridge)
1372{ 1407{
1373 struct dw_hdmi *hdmi = bridge->driver_private; 1408 struct dw_hdmi *hdmi = bridge->driver_private;
1374 1409
1410 mutex_lock(&hdmi->mutex);
1375 dw_hdmi_poweron(hdmi); 1411 dw_hdmi_poweron(hdmi);
1412 hdmi->disabled = false;
1413 mutex_unlock(&hdmi->mutex);
1376} 1414}
1377 1415
1378static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) 1416static void dw_hdmi_bridge_nop(struct drm_bridge *bridge)
@@ -1405,6 +1443,8 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
1405 dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", 1443 dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",
1406 edid->width_cm, edid->height_cm); 1444 edid->width_cm, edid->height_cm);
1407 1445
1446 hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
1447 hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
1408 drm_mode_connector_update_edid_property(connector, edid); 1448 drm_mode_connector_update_edid_property(connector, edid);
1409 ret = drm_add_edid_modes(connector, edid); 1449 ret = drm_add_edid_modes(connector, edid);
1410 kfree(edid); 1450 kfree(edid);
@@ -1423,6 +1463,10 @@ dw_hdmi_connector_mode_valid(struct drm_connector *connector,
1423 struct dw_hdmi, connector); 1463 struct dw_hdmi, connector);
1424 enum drm_mode_status mode_status = MODE_OK; 1464 enum drm_mode_status mode_status = MODE_OK;
1425 1465
1466 /* We don't support double-clocked modes */
1467 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
1468 return MODE_BAD;
1469
1426 if (hdmi->plat_data->mode_valid) 1470 if (hdmi->plat_data->mode_valid)
1427 mode_status = hdmi->plat_data->mode_valid(connector, mode); 1471 mode_status = hdmi->plat_data->mode_valid(connector, mode);
1428 1472
@@ -1489,21 +1533,21 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
1489 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); 1533 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0);
1490 1534
1491 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { 1535 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) {
1536 hdmi_modb(hdmi, ~phy_int_pol, HDMI_PHY_HPD, HDMI_PHY_POL0);
1537 mutex_lock(&hdmi->mutex);
1492 if (phy_int_pol & HDMI_PHY_HPD) { 1538 if (phy_int_pol & HDMI_PHY_HPD) {
1493 dev_dbg(hdmi->dev, "EVENT=plugin\n"); 1539 dev_dbg(hdmi->dev, "EVENT=plugin\n");
1494 1540
1495 hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0); 1541 if (!hdmi->disabled)
1496 1542 dw_hdmi_poweron(hdmi);
1497 dw_hdmi_poweron(hdmi);
1498 } else { 1543 } else {
1499 dev_dbg(hdmi->dev, "EVENT=plugout\n"); 1544 dev_dbg(hdmi->dev, "EVENT=plugout\n");
1500 1545
1501 hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, 1546 if (!hdmi->disabled)
1502 HDMI_PHY_POL0); 1547 dw_hdmi_poweroff(hdmi);
1503
1504 dw_hdmi_poweroff(hdmi);
1505 } 1548 }
1506 drm_helper_hpd_irq_event(hdmi->connector.dev); 1549 mutex_unlock(&hdmi->mutex);
1550 drm_helper_hpd_irq_event(hdmi->bridge->dev);
1507 } 1551 }
1508 1552
1509 hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); 1553 hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0);
@@ -1570,8 +1614,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
1570 hdmi->sample_rate = 48000; 1614 hdmi->sample_rate = 48000;
1571 hdmi->ratio = 100; 1615 hdmi->ratio = 100;
1572 hdmi->encoder = encoder; 1616 hdmi->encoder = encoder;
1617 hdmi->disabled = true;
1573 1618
1619 mutex_init(&hdmi->mutex);
1574 mutex_init(&hdmi->audio_mutex); 1620 mutex_init(&hdmi->audio_mutex);
1621 spin_lock_init(&hdmi->audio_lock);
1575 1622
1576 of_property_read_u32(np, "reg-io-width", &val); 1623 of_property_read_u32(np, "reg-io-width", &val);
1577 1624
diff --git a/drivers/gpu/drm/bridge/dw_hdmi.h b/drivers/gpu/drm/bridge/dw_hdmi.h
index 175dbc89a824..ee7f7ed2ab12 100644
--- a/drivers/gpu/drm/bridge/dw_hdmi.h
+++ b/drivers/gpu/drm/bridge/dw_hdmi.h
@@ -7,8 +7,8 @@
7 * (at your option) any later version. 7 * (at your option) any later version.
8 */ 8 */
9 9
10#ifndef __IMX_HDMI_H__ 10#ifndef __DW_HDMI_H__
11#define __IMX_HDMI_H__ 11#define __DW_HDMI_H__
12 12
13/* Identification Registers */ 13/* Identification Registers */
14#define HDMI_DESIGN_ID 0x0000 14#define HDMI_DESIGN_ID 0x0000
@@ -525,7 +525,7 @@
525 525
526/* I2C Master Registers (E-DDC) */ 526/* I2C Master Registers (E-DDC) */
527#define HDMI_I2CM_SLAVE 0x7E00 527#define HDMI_I2CM_SLAVE 0x7E00
528#define HDMI_I2CMESS 0x7E01 528#define HDMI_I2CM_ADDRESS 0x7E01
529#define HDMI_I2CM_DATAO 0x7E02 529#define HDMI_I2CM_DATAO 0x7E02
530#define HDMI_I2CM_DATAI 0x7E03 530#define HDMI_I2CM_DATAI 0x7E03
531#define HDMI_I2CM_OPERATION 0x7E04 531#define HDMI_I2CM_OPERATION 0x7E04
@@ -1031,4 +1031,4 @@ enum {
1031 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, 1031 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
1032}; 1032};
1033 1033
1034#endif /* __IMX_HDMI_H__ */ 1034#endif /* __DW_HDMI_H__ */
diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c
index a3ecf1069b76..644edf65dbe0 100644
--- a/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -75,6 +75,11 @@ static const struct dw_hdmi_curr_ctrl imx_cur_ctr[] = {
75 }, 75 },
76}; 76};
77 77
78/*
79 * Resistance term 133Ohm Cfg
80 * PREEMP config 0.00
81 * TX/CK level 10
82 */
78static const struct dw_hdmi_phy_config imx_phy_config[] = { 83static const struct dw_hdmi_phy_config imx_phy_config[] = {
79 /*pixelclk symbol term vlev */ 84 /*pixelclk symbol term vlev */
80 { 148500000, 0x800d, 0x0005, 0x01ad}, 85 { 148500000, 0x800d, 0x0005, 0x01ad},
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index de13bfc35634..bae79f3c4d28 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -12,6 +12,8 @@
12 12
13#include <drm/drmP.h> 13#include <drm/drmP.h>
14 14
15struct dw_hdmi;
16
15enum { 17enum {
16 DW_HDMI_RES_8, 18 DW_HDMI_RES_8,
17 DW_HDMI_RES_10, 19 DW_HDMI_RES_10,
@@ -59,4 +61,9 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
59 void *data, struct drm_encoder *encoder, 61 void *data, struct drm_encoder *encoder,
60 struct resource *iores, int irq, 62 struct resource *iores, int irq,
61 const struct dw_hdmi_plat_data *plat_data); 63 const struct dw_hdmi_plat_data *plat_data);
64
65void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate);
66void dw_hdmi_audio_enable(struct dw_hdmi *hdmi);
67void dw_hdmi_audio_disable(struct dw_hdmi *hdmi);
68
62#endif /* __IMX_HDMI_H__ */ 69#endif /* __IMX_HDMI_H__ */