Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+233 -174
+217 -170
drivers/gpu/drm/bridge/dw_hdmi.c
··· 18 18 #include <linux/hdmi.h> 19 19 #include <linux/mutex.h> 20 20 #include <linux/of_device.h> 21 + #include <linux/spinlock.h> 21 22 22 23 #include <drm/drm_of.h> 23 24 #include <drm/drmP.h> ··· 82 81 }; 83 82 84 83 struct hdmi_vmode { 85 - bool mdvi; 86 - bool mhsyncpolarity; 87 - bool mvsyncpolarity; 88 - bool minterlaced; 89 84 bool mdataenablepolarity; 90 85 91 86 unsigned int mpixelclock; ··· 120 123 bool phy_enabled; 121 124 struct drm_display_mode previous_mode; 122 125 123 - struct regmap *regmap; 124 126 struct i2c_adapter *ddc; 125 127 void __iomem *regs; 128 + bool sink_is_hdmi; 129 + bool sink_has_audio; 126 130 131 + struct mutex mutex; /* for state below and previous_mode */ 132 + bool disabled; /* DRM has disabled our bridge */ 133 + 134 + spinlock_t audio_lock; 127 135 struct mutex audio_mutex; 128 136 unsigned int sample_rate; 137 + unsigned int audio_cts; 138 + unsigned int audio_n; 139 + bool audio_enable; 129 140 int ratio; 130 141 131 142 void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); ··· 340 335 } 341 336 342 337 static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, 343 - unsigned long pixel_clk) 338 + unsigned long pixel_clk, unsigned int sample_rate, unsigned int ratio) 344 339 { 345 - unsigned int clk_n, clk_cts; 340 + unsigned int n, cts; 346 341 347 - clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk, 348 - hdmi->ratio); 349 - clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk, 350 - hdmi->ratio); 351 - 352 - if (!clk_cts) { 353 - dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", 354 - __func__, pixel_clk); 355 - return; 342 + n = hdmi_compute_n(sample_rate, pixel_clk, ratio); 343 + cts = hdmi_compute_cts(sample_rate, pixel_clk, ratio); 344 + if (!cts) { 345 + dev_err(hdmi->dev, 346 + "%s: pixel clock/sample rate not supported: %luMHz / %ukHz\n", 347 + __func__, pixel_clk, sample_rate); 356 348 } 357 349 358 - dev_dbg(hdmi->dev, "%s: samplerate=%d ratio=%d pixelclk=%lu N=%d cts=%d\n", 359 - __func__, hdmi->sample_rate, hdmi->ratio, 360 - pixel_clk, clk_n, clk_cts); 350 + dev_dbg(hdmi->dev, "%s: samplerate=%ukHz ratio=%d pixelclk=%luMHz N=%d cts=%d\n", 351 + __func__, sample_rate, ratio, pixel_clk, n, cts); 361 352 362 - hdmi_set_cts_n(hdmi, clk_cts, clk_n); 353 + spin_lock_irq(&hdmi->audio_lock); 354 + hdmi->audio_n = n; 355 + hdmi->audio_cts = cts; 356 + hdmi_set_cts_n(hdmi, cts, hdmi->audio_enable ? n : 0); 357 + spin_unlock_irq(&hdmi->audio_lock); 363 358 } 364 359 365 360 static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) 366 361 { 367 362 mutex_lock(&hdmi->audio_mutex); 368 - hdmi_set_clk_regenerator(hdmi, 74250000); 363 + hdmi_set_clk_regenerator(hdmi, 74250000, hdmi->sample_rate, 364 + hdmi->ratio); 369 365 mutex_unlock(&hdmi->audio_mutex); 370 366 } 371 367 372 368 static void hdmi_clk_regenerator_update_pixel_clock(struct dw_hdmi *hdmi) 373 369 { 374 370 mutex_lock(&hdmi->audio_mutex); 375 - hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock); 371 + hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, 372 + hdmi->sample_rate, hdmi->ratio); 376 373 mutex_unlock(&hdmi->audio_mutex); 377 374 } 375 + 376 + void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) 377 + { 378 + mutex_lock(&hdmi->audio_mutex); 379 + hdmi->sample_rate = rate; 380 + hdmi_set_clk_regenerator(hdmi, hdmi->hdmi_data.video_mode.mpixelclock, 381 + hdmi->sample_rate, hdmi->ratio); 382 + mutex_unlock(&hdmi->audio_mutex); 383 + } 384 + EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); 385 + 386 + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi) 387 + { 388 + unsigned long flags; 389 + 390 + spin_lock_irqsave(&hdmi->audio_lock, flags); 391 + hdmi->audio_enable = true; 392 + hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n); 393 + spin_unlock_irqrestore(&hdmi->audio_lock, flags); 394 + } 395 + EXPORT_SYMBOL_GPL(dw_hdmi_audio_enable); 396 + 397 + void dw_hdmi_audio_disable(struct dw_hdmi *hdmi) 398 + { 399 + unsigned long flags; 400 + 401 + spin_lock_irqsave(&hdmi->audio_lock, flags); 402 + hdmi->audio_enable = false; 403 + hdmi_set_cts_n(hdmi, hdmi->audio_cts, 0); 404 + spin_unlock_irqrestore(&hdmi->audio_lock, flags); 405 + } 406 + EXPORT_SYMBOL_GPL(dw_hdmi_audio_disable); 378 407 379 408 /* 380 409 * this submodule is responsible for the video data synchronization. ··· 740 701 return 0; 741 702 } 742 703 743 - static void dw_hdmi_phy_enable_power(struct dw_hdmi *hdmi, u8 enable) 704 + static void dw_hdmi_phy_enable_powerdown(struct dw_hdmi *hdmi, bool enable) 744 705 { 745 - hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, 706 + hdmi_mask_writeb(hdmi, !enable, HDMI_PHY_CONF0, 746 707 HDMI_PHY_CONF0_PDZ_OFFSET, 747 708 HDMI_PHY_CONF0_PDZ_MASK); 748 709 } ··· 792 753 static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, 793 754 unsigned char res, int cscon) 794 755 { 795 - unsigned res_idx, i; 756 + unsigned res_idx; 796 757 u8 val, msec; 797 - const struct dw_hdmi_plat_data *plat_data = hdmi->plat_data; 798 - const struct dw_hdmi_mpll_config *mpll_config = plat_data->mpll_cfg; 799 - const struct dw_hdmi_curr_ctrl *curr_ctrl = plat_data->cur_ctr; 800 - const struct dw_hdmi_phy_config *phy_config = plat_data->phy_config; 758 + const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; 759 + const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; 760 + const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; 761 + const struct dw_hdmi_phy_config *phy_config = pdata->phy_config; 801 762 802 763 if (prep) 803 764 return -EINVAL; ··· 814 775 res_idx = DW_HDMI_RES_12; 815 776 break; 816 777 default: 778 + return -EINVAL; 779 + } 780 + 781 + /* PLL/MPLL Cfg - always match on final entry */ 782 + for (; mpll_config->mpixelclock != ~0UL; mpll_config++) 783 + if (hdmi->hdmi_data.video_mode.mpixelclock <= 784 + mpll_config->mpixelclock) 785 + break; 786 + 787 + for (; curr_ctrl->mpixelclock != ~0UL; curr_ctrl++) 788 + if (hdmi->hdmi_data.video_mode.mpixelclock <= 789 + curr_ctrl->mpixelclock) 790 + break; 791 + 792 + for (; phy_config->mpixelclock != ~0UL; phy_config++) 793 + if (hdmi->hdmi_data.video_mode.mpixelclock <= 794 + phy_config->mpixelclock) 795 + break; 796 + 797 + if (mpll_config->mpixelclock == ~0UL || 798 + curr_ctrl->mpixelclock == ~0UL || 799 + phy_config->mpixelclock == ~0UL) { 800 + dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", 801 + hdmi->hdmi_data.video_mode.mpixelclock); 817 802 return -EINVAL; 818 803 } 819 804 ··· 866 803 HDMI_PHY_I2CM_SLAVE_ADDR); 867 804 hdmi_phy_test_clear(hdmi, 0); 868 805 869 - /* PLL/MPLL Cfg - always match on final entry */ 870 - for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++) 871 - if (hdmi->hdmi_data.video_mode.mpixelclock <= 872 - mpll_config[i].mpixelclock) 873 - break; 874 - 875 - hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06); 876 - hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15); 877 - 878 - for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++) 879 - if (hdmi->hdmi_data.video_mode.mpixelclock <= 880 - curr_ctrl[i].mpixelclock) 881 - break; 882 - 883 - if (curr_ctrl[i].mpixelclock == (~0UL)) { 884 - dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n", 885 - hdmi->hdmi_data.video_mode.mpixelclock); 886 - return -EINVAL; 887 - } 806 + hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06); 807 + hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15); 888 808 889 809 /* CURRCTRL */ 890 - hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10); 810 + hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10); 891 811 892 812 hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */ 893 813 hdmi_phy_i2c_write(hdmi, 0x0006, 0x17); 894 814 895 - for (i = 0; phy_config[i].mpixelclock != (~0UL); i++) 896 - if (hdmi->hdmi_data.video_mode.mpixelclock <= 897 - phy_config[i].mpixelclock) 898 - break; 899 - 900 - /* RESISTANCE TERM 133Ohm Cfg */ 901 - hdmi_phy_i2c_write(hdmi, phy_config[i].term, 0x19); /* TXTERM */ 902 - /* PREEMP Cgf 0.00 */ 903 - hdmi_phy_i2c_write(hdmi, phy_config[i].sym_ctr, 0x09); /* CKSYMTXCTRL */ 904 - /* TX/CK LVL 10 */ 905 - hdmi_phy_i2c_write(hdmi, phy_config[i].vlev_ctr, 0x0E); /* VLEVCTRL */ 815 + hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19); /* TXTERM */ 816 + hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */ 817 + hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */ 906 818 907 819 /* REMOVE CLK TERM */ 908 820 hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ 909 821 910 - dw_hdmi_phy_enable_power(hdmi, 1); 822 + dw_hdmi_phy_enable_powerdown(hdmi, false); 911 823 912 824 /* toggle TMDS enable */ 913 825 dw_hdmi_phy_enable_tmds(hdmi, 0); ··· 917 879 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) 918 880 { 919 881 int i, ret; 920 - bool cscon = false; 882 + bool cscon; 921 883 922 884 /*check csc whether needed activated in HDMI mode */ 923 - cscon = (is_color_space_conversion(hdmi) && 924 - !hdmi->hdmi_data.video_mode.mdvi); 885 + cscon = hdmi->sink_is_hdmi && is_color_space_conversion(hdmi); 925 886 926 887 /* HDMI Phy spec says to do the phy initialization sequence twice */ 927 888 for (i = 0; i < 2; i++) { 928 889 dw_hdmi_phy_sel_data_en_pol(hdmi, 1); 929 890 dw_hdmi_phy_sel_interface_control(hdmi, 0); 930 891 dw_hdmi_phy_enable_tmds(hdmi, 0); 931 - dw_hdmi_phy_enable_power(hdmi, 0); 892 + dw_hdmi_phy_enable_powerdown(hdmi, true); 932 893 933 894 /* Enable CSC */ 934 895 ret = hdmi_phy_configure(hdmi, 0, 8, cscon); ··· 958 921 HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); 959 922 } 960 923 961 - static void hdmi_config_AVI(struct dw_hdmi *hdmi) 924 + static void hdmi_config_AVI(struct dw_hdmi *hdmi, struct drm_display_mode *mode) 962 925 { 963 - u8 val, pix_fmt, under_scan; 964 - u8 act_ratio, coded_ratio, colorimetry, ext_colorimetry; 965 - bool aspect_16_9; 926 + struct hdmi_avi_infoframe frame; 927 + u8 val; 966 928 967 - aspect_16_9 = false; /* FIXME */ 929 + /* Initialise info frame from DRM mode */ 930 + drm_hdmi_avi_infoframe_from_display_mode(&frame, mode); 968 931 969 - /* AVI Data Byte 1 */ 970 932 if (hdmi->hdmi_data.enc_out_format == YCBCR444) 971 - pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR444; 933 + frame.colorspace = HDMI_COLORSPACE_YUV444; 972 934 else if (hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) 973 - pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_YCBCR422; 935 + frame.colorspace = HDMI_COLORSPACE_YUV422; 974 936 else 975 - pix_fmt = HDMI_FC_AVICONF0_PIX_FMT_RGB; 976 - 977 - under_scan = HDMI_FC_AVICONF0_SCAN_INFO_NODATA; 978 - 979 - /* 980 - * Active format identification data is present in the AVI InfoFrame. 981 - * Under scan info, no bar data 982 - */ 983 - val = pix_fmt | under_scan | 984 - HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT | 985 - HDMI_FC_AVICONF0_BAR_DATA_NO_DATA; 986 - 987 - hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0); 988 - 989 - /* AVI Data Byte 2 -Set the Aspect Ratio */ 990 - if (aspect_16_9) { 991 - act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9; 992 - coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9; 993 - } else { 994 - act_ratio = HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3; 995 - coded_ratio = HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3; 996 - } 937 + frame.colorspace = HDMI_COLORSPACE_RGB; 997 938 998 939 /* Set up colorimetry */ 999 940 if (hdmi->hdmi_data.enc_out_format == XVYCC444) { 1000 - colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO; 941 + frame.colorimetry = HDMI_COLORIMETRY_EXTENDED; 1001 942 if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) 1002 - ext_colorimetry = 1003 - HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; 943 + frame.extended_colorimetry = 944 + HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1004 945 else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ 1005 - ext_colorimetry = 1006 - HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709; 946 + frame.extended_colorimetry = 947 + HDMI_EXTENDED_COLORIMETRY_XV_YCC_709; 1007 948 } else if (hdmi->hdmi_data.enc_out_format != RGB) { 1008 - if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) 1009 - colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_SMPTE; 1010 - else /*hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_709*/ 1011 - colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_ITUR; 1012 - ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; 949 + frame.colorimetry = hdmi->hdmi_data.colorimetry; 950 + frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1013 951 } else { /* Carries no data */ 1014 - colorimetry = HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA; 1015 - ext_colorimetry = HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601; 952 + frame.colorimetry = HDMI_COLORIMETRY_NONE; 953 + frame.extended_colorimetry = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601; 1016 954 } 1017 955 1018 - val = colorimetry | coded_ratio | act_ratio; 956 + frame.scan_mode = HDMI_SCAN_MODE_NONE; 957 + 958 + /* 959 + * The Designware IP uses a different byte format from standard 960 + * AVI info frames, though generally the bits are in the correct 961 + * bytes. 962 + */ 963 + 964 + /* 965 + * AVI data byte 1 differences: Colorspace in bits 4,5 rather than 5,6, 966 + * active aspect present in bit 6 rather than 4. 967 + */ 968 + val = (frame.colorspace & 3) << 4 | (frame.scan_mode & 0x3); 969 + if (frame.active_aspect & 15) 970 + val |= HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT; 971 + if (frame.top_bar || frame.bottom_bar) 972 + val |= HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR; 973 + if (frame.left_bar || frame.right_bar) 974 + val |= HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR; 975 + hdmi_writeb(hdmi, val, HDMI_FC_AVICONF0); 976 + 977 + /* AVI data byte 2 differences: none */ 978 + val = ((frame.colorimetry & 0x3) << 6) | 979 + ((frame.picture_aspect & 0x3) << 4) | 980 + (frame.active_aspect & 0xf); 1019 981 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF1); 1020 982 1021 - /* AVI Data Byte 3 */ 1022 - val = HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA | ext_colorimetry | 1023 - HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT | 1024 - HDMI_FC_AVICONF2_SCALING_NONE; 983 + /* AVI data byte 3 differences: none */ 984 + val = ((frame.extended_colorimetry & 0x7) << 4) | 985 + ((frame.quantization_range & 0x3) << 2) | 986 + (frame.nups & 0x3); 987 + if (frame.itc) 988 + val |= HDMI_FC_AVICONF2_IT_CONTENT_VALID; 1025 989 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF2); 1026 990 1027 - /* AVI Data Byte 4 */ 1028 - hdmi_writeb(hdmi, hdmi->vic, HDMI_FC_AVIVID); 991 + /* AVI data byte 4 differences: none */ 992 + val = frame.video_code & 0x7f; 993 + hdmi_writeb(hdmi, val, HDMI_FC_AVIVID); 1029 994 1030 995 /* AVI Data Byte 5- set up input and output pixel repetition */ 1031 996 val = (((hdmi->hdmi_data.video_mode.mpixelrepetitioninput + 1) << ··· 1038 999 HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK); 1039 1000 hdmi_writeb(hdmi, val, HDMI_FC_PRCONF); 1040 1001 1041 - /* IT Content and quantization range = don't care */ 1042 - val = HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS | 1043 - HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED; 1002 + /* 1003 + * AVI data byte 5 differences: content type in 0,1 rather than 4,5, 1004 + * ycc range in bits 2,3 rather than 6,7 1005 + */ 1006 + val = ((frame.ycc_quantization_range & 0x3) << 2) | 1007 + (frame.content_type & 0x3); 1044 1008 hdmi_writeb(hdmi, val, HDMI_FC_AVICONF3); 1045 1009 1046 1010 /* AVI Data Bytes 6-13 */ 1047 - hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB0); 1048 - hdmi_writeb(hdmi, 0, HDMI_FC_AVIETB1); 1049 - hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB0); 1050 - hdmi_writeb(hdmi, 0, HDMI_FC_AVISBB1); 1051 - hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB0); 1052 - hdmi_writeb(hdmi, 0, HDMI_FC_AVIELB1); 1053 - hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB0); 1054 - hdmi_writeb(hdmi, 0, HDMI_FC_AVISRB1); 1011 + hdmi_writeb(hdmi, frame.top_bar & 0xff, HDMI_FC_AVIETB0); 1012 + hdmi_writeb(hdmi, (frame.top_bar >> 8) & 0xff, HDMI_FC_AVIETB1); 1013 + hdmi_writeb(hdmi, frame.bottom_bar & 0xff, HDMI_FC_AVISBB0); 1014 + hdmi_writeb(hdmi, (frame.bottom_bar >> 8) & 0xff, HDMI_FC_AVISBB1); 1015 + hdmi_writeb(hdmi, frame.left_bar & 0xff, HDMI_FC_AVIELB0); 1016 + hdmi_writeb(hdmi, (frame.left_bar >> 8) & 0xff, HDMI_FC_AVIELB1); 1017 + hdmi_writeb(hdmi, frame.right_bar & 0xff, HDMI_FC_AVISRB0); 1018 + hdmi_writeb(hdmi, (frame.right_bar >> 8) & 0xff, HDMI_FC_AVISRB1); 1055 1019 } 1056 1020 1057 1021 static void hdmi_av_composer(struct dw_hdmi *hdmi, ··· 1064 1022 struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; 1065 1023 int hblank, vblank, h_de_hs, v_de_vs, hsync_len, vsync_len; 1066 1024 1067 - vmode->mhsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC); 1068 - vmode->mvsyncpolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC); 1069 - vmode->minterlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); 1070 1025 vmode->mpixelclock = mode->clock * 1000; 1071 1026 1072 1027 dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); ··· 1073 1034 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : 1074 1035 HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); 1075 1036 1076 - inv_val |= (vmode->mvsyncpolarity ? 1037 + inv_val |= mode->flags & DRM_MODE_FLAG_PVSYNC ? 1077 1038 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : 1078 - HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW); 1039 + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW; 1079 1040 1080 - inv_val |= (vmode->mhsyncpolarity ? 1041 + inv_val |= mode->flags & DRM_MODE_FLAG_PHSYNC ? 1081 1042 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : 1082 - HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW); 1043 + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW; 1083 1044 1084 1045 inv_val |= (vmode->mdataenablepolarity ? 1085 1046 HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : ··· 1088 1049 if (hdmi->vic == 39) 1089 1050 inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH; 1090 1051 else 1091 - inv_val |= (vmode->minterlaced ? 1052 + inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ? 1092 1053 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH : 1093 - HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW); 1054 + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW; 1094 1055 1095 - inv_val |= (vmode->minterlaced ? 1056 + inv_val |= mode->flags & DRM_MODE_FLAG_INTERLACE ? 1096 1057 HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : 1097 - HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE); 1058 + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE; 1098 1059 1099 - inv_val |= (vmode->mdvi ? 1100 - HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE : 1101 - HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE); 1060 + inv_val |= hdmi->sink_is_hdmi ? 1061 + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE : 1062 + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE; 1102 1063 1103 1064 hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); 1104 1065 ··· 1144 1105 return; 1145 1106 1146 1107 dw_hdmi_phy_enable_tmds(hdmi, 0); 1147 - dw_hdmi_phy_enable_power(hdmi, 0); 1108 + dw_hdmi_phy_enable_powerdown(hdmi, true); 1148 1109 1149 1110 hdmi->phy_enabled = false; 1150 1111 } ··· 1225 1186 1226 1187 if (!hdmi->vic) { 1227 1188 dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); 1228 - hdmi->hdmi_data.video_mode.mdvi = true; 1229 1189 } else { 1230 1190 dev_dbg(hdmi->dev, "CEA mode used vic=%d\n", hdmi->vic); 1231 - hdmi->hdmi_data.video_mode.mdvi = false; 1232 1191 } 1233 1192 1234 1193 if ((hdmi->vic == 6) || (hdmi->vic == 7) || ··· 1237 1200 else 1238 1201 hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709; 1239 1202 1240 - if ((hdmi->vic == 10) || (hdmi->vic == 11) || 1241 - (hdmi->vic == 12) || (hdmi->vic == 13) || 1242 - (hdmi->vic == 14) || (hdmi->vic == 15) || 1243 - (hdmi->vic == 25) || (hdmi->vic == 26) || 1244 - (hdmi->vic == 27) || (hdmi->vic == 28) || 1245 - (hdmi->vic == 29) || (hdmi->vic == 30) || 1246 - (hdmi->vic == 35) || (hdmi->vic == 36) || 1247 - (hdmi->vic == 37) || (hdmi->vic == 38)) 1248 - hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 1; 1249 - else 1250 - hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; 1251 - 1203 + hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0; 1252 1204 hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0; 1253 1205 1254 1206 /* TODO: Get input format from IPU (via FB driver interface) */ ··· 1261 1235 /* HDMI Initialization Step B.3 */ 1262 1236 dw_hdmi_enable_video_path(hdmi); 1263 1237 1264 - /* not for DVI mode */ 1265 - if (hdmi->hdmi_data.video_mode.mdvi) { 1266 - dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); 1267 - } else { 1268 - dev_dbg(hdmi->dev, "%s CEA mode\n", __func__); 1238 + if (hdmi->sink_has_audio) { 1239 + dev_dbg(hdmi->dev, "sink has audio support\n"); 1269 1240 1270 1241 /* HDMI Initialization Step E - Configure audio */ 1271 1242 hdmi_clk_regenerator_update_pixel_clock(hdmi); 1272 1243 hdmi_enable_audio_clk(hdmi); 1244 + } 1245 + 1246 + /* not for DVI mode */ 1247 + if (hdmi->sink_is_hdmi) { 1248 + dev_dbg(hdmi->dev, "%s HDMI mode\n", __func__); 1273 1249 1274 1250 /* HDMI Initialization Step F - Configure AVI InfoFrame */ 1275 - hdmi_config_AVI(hdmi); 1251 + hdmi_config_AVI(hdmi, mode); 1252 + } else { 1253 + dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); 1276 1254 } 1277 1255 1278 1256 hdmi_video_packetize(hdmi); ··· 1285 1255 hdmi_tx_hdcp_config(hdmi); 1286 1256 1287 1257 dw_hdmi_clear_overflow(hdmi); 1288 - if (hdmi->cable_plugin && !hdmi->hdmi_data.video_mode.mdvi) 1258 + if (hdmi->cable_plugin && hdmi->sink_is_hdmi) 1289 1259 hdmi_enable_overflow_interrupts(hdmi); 1290 1260 1291 1261 return 0; ··· 1378 1348 { 1379 1349 struct dw_hdmi *hdmi = bridge->driver_private; 1380 1350 1381 - dw_hdmi_setup(hdmi, mode); 1351 + mutex_lock(&hdmi->mutex); 1382 1352 1383 1353 /* Store the display mode for plugin/DKMS poweron events */ 1384 1354 memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); 1355 + 1356 + mutex_unlock(&hdmi->mutex); 1385 1357 } 1386 1358 1387 1359 static bool dw_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, ··· 1397 1365 { 1398 1366 struct dw_hdmi *hdmi = bridge->driver_private; 1399 1367 1368 + mutex_lock(&hdmi->mutex); 1369 + hdmi->disabled = true; 1400 1370 dw_hdmi_poweroff(hdmi); 1371 + mutex_unlock(&hdmi->mutex); 1401 1372 } 1402 1373 1403 1374 static void dw_hdmi_bridge_enable(struct drm_bridge *bridge) 1404 1375 { 1405 1376 struct dw_hdmi *hdmi = bridge->driver_private; 1406 1377 1378 + mutex_lock(&hdmi->mutex); 1407 1379 dw_hdmi_poweron(hdmi); 1380 + hdmi->disabled = false; 1381 + mutex_unlock(&hdmi->mutex); 1408 1382 } 1409 1383 1410 1384 static void dw_hdmi_bridge_nop(struct drm_bridge *bridge) ··· 1443 1405 dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", 1444 1406 edid->width_cm, edid->height_cm); 1445 1407 1408 + hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); 1409 + hdmi->sink_has_audio = drm_detect_monitor_audio(edid); 1446 1410 drm_mode_connector_update_edid_property(connector, edid); 1447 1411 ret = drm_add_edid_modes(connector, edid); 1448 1412 kfree(edid); ··· 1462 1422 struct dw_hdmi *hdmi = container_of(connector, 1463 1423 struct dw_hdmi, connector); 1464 1424 enum drm_mode_status mode_status = MODE_OK; 1425 + 1426 + /* We don't support double-clocked modes */ 1427 + if (mode->flags & DRM_MODE_FLAG_DBLCLK) 1428 + return MODE_BAD; 1465 1429 1466 1430 if (hdmi->plat_data->mode_valid) 1467 1431 mode_status = hdmi->plat_data->mode_valid(connector, mode); ··· 1533 1489 phy_int_pol = hdmi_readb(hdmi, HDMI_PHY_POL0); 1534 1490 1535 1491 if (intr_stat & HDMI_IH_PHY_STAT0_HPD) { 1492 + hdmi_modb(hdmi, ~phy_int_pol, HDMI_PHY_HPD, HDMI_PHY_POL0); 1493 + mutex_lock(&hdmi->mutex); 1536 1494 if (phy_int_pol & HDMI_PHY_HPD) { 1537 1495 dev_dbg(hdmi->dev, "EVENT=plugin\n"); 1538 1496 1539 - hdmi_modb(hdmi, 0, HDMI_PHY_HPD, HDMI_PHY_POL0); 1540 - 1541 - dw_hdmi_poweron(hdmi); 1497 + if (!hdmi->disabled) 1498 + dw_hdmi_poweron(hdmi); 1542 1499 } else { 1543 1500 dev_dbg(hdmi->dev, "EVENT=plugout\n"); 1544 1501 1545 - hdmi_modb(hdmi, HDMI_PHY_HPD, HDMI_PHY_HPD, 1546 - HDMI_PHY_POL0); 1547 - 1548 - dw_hdmi_poweroff(hdmi); 1502 + if (!hdmi->disabled) 1503 + dw_hdmi_poweroff(hdmi); 1549 1504 } 1550 - drm_helper_hpd_irq_event(hdmi->connector.dev); 1505 + mutex_unlock(&hdmi->mutex); 1506 + drm_helper_hpd_irq_event(hdmi->bridge->dev); 1551 1507 } 1552 1508 1553 1509 hdmi_writeb(hdmi, intr_stat, HDMI_IH_PHY_STAT0); ··· 1614 1570 hdmi->sample_rate = 48000; 1615 1571 hdmi->ratio = 100; 1616 1572 hdmi->encoder = encoder; 1573 + hdmi->disabled = true; 1617 1574 1575 + mutex_init(&hdmi->mutex); 1618 1576 mutex_init(&hdmi->audio_mutex); 1577 + spin_lock_init(&hdmi->audio_lock); 1619 1578 1620 1579 of_property_read_u32(np, "reg-io-width", &val); 1621 1580
+4 -4
drivers/gpu/drm/bridge/dw_hdmi.h
··· 7 7 * (at your option) any later version. 8 8 */ 9 9 10 - #ifndef __IMX_HDMI_H__ 11 - #define __IMX_HDMI_H__ 10 + #ifndef __DW_HDMI_H__ 11 + #define __DW_HDMI_H__ 12 12 13 13 /* Identification Registers */ 14 14 #define HDMI_DESIGN_ID 0x0000 ··· 525 525 526 526 /* I2C Master Registers (E-DDC) */ 527 527 #define HDMI_I2CM_SLAVE 0x7E00 528 - #define HDMI_I2CMESS 0x7E01 528 + #define HDMI_I2CM_ADDRESS 0x7E01 529 529 #define HDMI_I2CM_DATAO 0x7E02 530 530 #define HDMI_I2CM_DATAI 0x7E03 531 531 #define HDMI_I2CM_OPERATION 0x7E04 ··· 1031 1031 HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0, 1032 1032 }; 1033 1033 1034 - #endif /* __IMX_HDMI_H__ */ 1034 + #endif /* __DW_HDMI_H__ */
+5
drivers/gpu/drm/imx/dw_hdmi-imx.c
··· 75 75 }, 76 76 }; 77 77 78 + /* 79 + * Resistance term 133Ohm Cfg 80 + * PREEMP config 0.00 81 + * TX/CK level 10 82 + */ 78 83 static const struct dw_hdmi_phy_config imx_phy_config[] = { 79 84 /*pixelclk symbol term vlev */ 80 85 { 148500000, 0x800d, 0x0005, 0x01ad},
+7
include/drm/bridge/dw_hdmi.h
··· 12 12 13 13 #include <drm/drmP.h> 14 14 15 + struct dw_hdmi; 16 + 15 17 enum { 16 18 DW_HDMI_RES_8, 17 19 DW_HDMI_RES_10, ··· 61 59 void *data, struct drm_encoder *encoder, 62 60 struct resource *iores, int irq, 63 61 const struct dw_hdmi_plat_data *plat_data); 62 + 63 + void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); 64 + void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); 65 + void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); 66 + 64 67 #endif /* __IMX_HDMI_H__ */