* [PATCH] drm/i915: set proper N/M in modeset
@ 2016-07-14 7:06 libin.yang
2016-07-28 6:44 ` Yang, Libin
2016-07-28 7:41 ` Ville Syrjälä
0 siblings, 2 replies; 23+ messages in thread
From: libin.yang @ 2016-07-14 7:06 UTC (permalink / raw)
To: intel-gfx, jani.nikula, ville.syrjala, daniel.vetter, tiwai; +Cc: Libin Yang
From: Libin Yang <libin.yang@linux.intel.com>
When modeset occurs and the LS_CLK is set to some
special values in DP mode, the N/M need to be set
manually if audio is playing.
Also, the patch applies
commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset")
to APL platform.
Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 6 ++
drivers/gpu/drm/i915/intel_audio.c | 116 ++++++++++++++++++++++++++++++++-----
2 files changed, 108 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8bfde75..2f9d00e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7351,6 +7351,12 @@ enum {
#define _HSW_AUD_CONFIG_B 0x65100
#define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
+#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
+#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
+#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
+#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
+#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
+
#define _HSW_AUD_MISC_CTRL_A 0x65010
#define _HSW_AUD_MISC_CTRL_B 0x65110
#define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 6700a7b..e2e4d4b 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -98,6 +98,22 @@ static const struct {
{ 192000, TMDS_297M, 20480, 247500 },
};
+#define LC_533M 533250
+#define LC_148M 148500
+static const struct {
+ int sample_rate;
+ int clock;
+ int n;
+ int m;
+} aud_nm[] = {
+ {48000, LC_533M, 88875, 4096},
+ {44100, LC_533M, 148125, 6272},
+ {32000, LC_533M, 266625, 8192},
+ {48000, LC_148M, 12375, 2048},
+ {44100, LC_148M, 20625, 3136},
+ {32000, LC_148M, 37125, 4096},
+};
+
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode)
{
@@ -121,20 +137,50 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
return hdmi_audio_clock[i].config;
}
-static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
+static int audio_config_get_n(struct intel_crtc *crtc,
+ const struct drm_display_mode *mode, int rate)
+{
+ int i;
+
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
+ for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
+ if ((rate == aud_ncts[i].sample_rate) &&
+ (mode->clock == aud_ncts[i].clock)) {
+ return aud_ncts[i].n;
+ }
+ }
+ }
+
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
+ for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
+ if ((rate == aud_nm[i].sample_rate) &&
+ (mode->clock == aud_nm[i].clock)) {
+ return aud_nm[i].n;
+ }
+ }
+ }
+ return 0;
+}
+
+static int audio_config_get_m(struct intel_crtc *crtc,
+ const struct drm_display_mode *mode, int rate)
{
int i;
- for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
- if ((rate == aud_ncts[i].sample_rate) &&
- (mode->clock == aud_ncts[i].clock)) {
- return aud_ncts[i].n;
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
+ for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
+ if ((rate == aud_nm[i].sample_rate) &&
+ (mode->clock == aud_nm[i].clock)) {
+ return aud_nm[i].m;
+ }
}
}
+
return 0;
}
-static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
+static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
+ int n, uint32_t val)
{
int n_low, n_up;
uint32_t tmp = val;
@@ -145,6 +191,23 @@ static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
(n_low << AUD_CONFIG_LOWER_N_SHIFT) |
AUD_CONFIG_N_PROG_ENABLE);
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
+ tmp |= AUD_CONFIG_N_VALUE_INDEX;
+ return tmp;
+}
+
+static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
+ int m, uint32_t val)
+{
+ uint32_t tmp = val;
+
+ if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
+ return 0;
+
+ tmp |= m;
+ tmp |= AUD_M_CTS_M_VALUE_INDEX;
+ tmp |= AUD_M_CTS_M_PROG_ENABLE;
+
return tmp;
}
@@ -156,6 +219,10 @@ static bool audio_rate_need_prog(struct intel_crtc *crtc,
(mode->clock == TMDS_296M)) &&
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
return true;
+ else if (((mode->clock == LC_533M) ||
+ (mode->clock == LC_148M)) &&
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
+ return true;
else
return false;
}
@@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
struct intel_digital_port *intel_dig_port =
enc_to_dig_port(&encoder->base);
enum port port = intel_dig_port->port;
- uint32_t tmp;
+ uint32_t tmp, m;
int len, i;
int n, rate;
@@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
DRM_ERROR("invalid port: %d\n", port);
rate = 0;
}
- n = audio_config_get_n(adjusted_mode, rate);
+ n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
if (n != 0)
- tmp = audio_config_setup_n_reg(n, tmp);
+ tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
else
DRM_DEBUG_KMS("no suitable N value is found\n");
}
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ /* setup m value for DP */
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
+ m = audio_config_get_m(intel_crtc, adjusted_mode, rate);
+ if (m != 0) {
+ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+ tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
+ I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+ }
+ }
+
mutex_unlock(&dev_priv->av_mutex);
}
@@ -637,7 +714,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
struct drm_display_mode *mode;
struct i915_audio_component *acomp = dev_priv->audio_component;
enum pipe pipe = INVALID_PIPE;
- u32 tmp;
+ u32 tmp, m;
int n;
int err = 0;
@@ -645,7 +722,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
if (!IS_SKYLAKE(dev_priv) &&
!IS_KABYLAKE(dev_priv) &&
!IS_BROADWELL(dev_priv) &&
- !IS_HASWELL(dev_priv))
+ !IS_HASWELL(dev_priv) &&
+ !IS_BROXTON(dev_priv))
return 0;
mutex_lock(&dev_priv->av_mutex);
@@ -653,7 +731,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
intel_encoder = dev_priv->dig_port_map[port];
/* intel_encoder might be NULL for DP MST */
if (!intel_encoder || !intel_encoder->base.crtc ||
- intel_encoder->type != INTEL_OUTPUT_HDMI) {
+ ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
+ (intel_encoder->type != INTEL_OUTPUT_DP))) {
DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
err = -ENODEV;
goto unlock;
@@ -681,7 +760,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
goto unlock;
}
- n = audio_config_get_n(mode, rate);
+ n = audio_config_get_n(crtc, mode, rate);
if (n == 0) {
DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n",
port_name(port));
@@ -693,8 +772,17 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
/* 3. set the N/CTS/M */
tmp = I915_READ(HSW_AUD_CFG(pipe));
- tmp = audio_config_setup_n_reg(n, tmp);
+ tmp = audio_config_setup_n_reg(crtc, n, tmp);
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ /* setup m value for DP */
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
+ m = audio_config_get_m(crtc, mode, rate);
+ if (m == 0)
+ goto unlock;
+ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+ tmp = audio_config_setup_m_reg(crtc, m, tmp);
+ I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+ }
unlock:
mutex_unlock(&dev_priv->av_mutex);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-07-14 7:06 [PATCH] drm/i915: set proper N/M in modeset libin.yang
@ 2016-07-28 6:44 ` Yang, Libin
2016-07-28 7:41 ` Ville Syrjälä
1 sibling, 0 replies; 23+ messages in thread
From: Yang, Libin @ 2016-07-28 6:44 UTC (permalink / raw)
To: libin.yang@linux.intel.com, intel-gfx@lists.freedesktop.org,
jani.nikula@linux.intel.com, ville.syrjala@linux.intel.com,
Vetter, Daniel, tiwai@suse.de
Cc: Zhao, Juan J
Hi all,
Is there anyone can help review this patch? This patch is set N/M for audio in DP 4k resolution. Thanks.
I calculate these values based on the DP1.2 spec chapter 6.6 on page 469:
Maud / Naud = 512 * fs / f_LS_Clk
Regards,
Libin
> -----Original Message-----
> From: libin.yang@linux.intel.com [mailto:libin.yang@linux.intel.com]
> Sent: Thursday, July 14, 2016 3:06 PM
> To: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> ville.syrjala@linux.intel.com; Vetter, Daniel <daniel.vetter@intel.com>;
> tiwai@suse.de
> Cc: Yang, Libin <libin.yang@intel.com>; Libin Yang
> <libin.yang@linux.intel.com>
> Subject: [PATCH] drm/i915: set proper N/M in modeset
>
> From: Libin Yang <libin.yang@linux.intel.com>
>
> When modeset occurs and the LS_CLK is set to some special values in DP
> mode, the N/M need to be set manually if audio is playing.
>
> Also, the patch applies
> commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> platform.
>
> Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_reg.h | 6 ++
> drivers/gpu/drm/i915/intel_audio.c | 116
> ++++++++++++++++++++++++++++++++-----
> 2 files changed, 108 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h
> b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -7351,6 +7351,12 @@ enum {
> #define _HSW_AUD_CONFIG_B 0x65100
> #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
>
> +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> +
> #define _HSW_AUD_MISC_CTRL_A 0x65010
> #define _HSW_AUD_MISC_CTRL_B 0x65110
> #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> diff --git a/drivers/gpu/drm/i915/intel_audio.c
> b/drivers/gpu/drm/i915/intel_audio.c
> index 6700a7b..e2e4d4b 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -98,6 +98,22 @@ static const struct {
> { 192000, TMDS_297M, 20480, 247500 },
> };
>
> +#define LC_533M 533250
> +#define LC_148M 148500
> +static const struct {
> + int sample_rate;
> + int clock;
> + int n;
> + int m;
> +} aud_nm[] = {
> + {48000, LC_533M, 88875, 4096},
> + {44100, LC_533M, 148125, 6272},
> + {32000, LC_533M, 266625, 8192},
> + {48000, LC_148M, 12375, 2048},
> + {44100, LC_148M, 20625, 3136},
> + {32000, LC_148M, 37125, 4096},
> +};
> +
> /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> audio_config_hdmi_pixel_clock(const struct drm_display_mode
> *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> return hdmi_audio_clock[i].config;
> }
>
> -static int audio_config_get_n(const struct drm_display_mode *mode, int
> rate)
> +static int audio_config_get_n(struct intel_crtc *crtc,
> + const struct drm_display_mode *mode, int rate) {
> + int i;
> +
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> + if ((rate == aud_ncts[i].sample_rate) &&
> + (mode->clock == aud_ncts[i].clock)) {
> + return aud_ncts[i].n;
> + }
> + }
> + }
> +
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> + if ((rate == aud_nm[i].sample_rate) &&
> + (mode->clock == aud_nm[i].clock)) {
> + return aud_nm[i].n;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +static int audio_config_get_m(struct intel_crtc *crtc,
> + const struct drm_display_mode *mode, int rate)
> {
> int i;
>
> - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> - if ((rate == aud_ncts[i].sample_rate) &&
> - (mode->clock == aud_ncts[i].clock)) {
> - return aud_ncts[i].n;
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> + if ((rate == aud_nm[i].sample_rate) &&
> + (mode->clock == aud_nm[i].clock)) {
> + return aud_nm[i].m;
> + }
> }
> }
> +
> return 0;
> }
>
> -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> + int n, uint32_t val)
> {
> int n_low, n_up;
> uint32_t tmp = val;
> @@ -145,6 +191,23 @@ static uint32_t audio_config_setup_n_reg(int n,
> uint32_t val)
> tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> AUD_CONFIG_N_PROG_ENABLE);
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> + return tmp;
> +}
> +
> +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> + int m, uint32_t val)
> +{
> + uint32_t tmp = val;
> +
> + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + return 0;
> +
> + tmp |= m;
> + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> +
> return tmp;
> }
>
> @@ -156,6 +219,10 @@ static bool audio_rate_need_prog(struct intel_crtc
> *crtc,
> (mode->clock == TMDS_296M)) &&
> intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> return true;
> + else if (((mode->clock == LC_533M) ||
> + (mode->clock == LC_148M)) &&
> + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + return true;
> else
> return false;
> }
> @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> drm_connector *connector,
> struct intel_digital_port *intel_dig_port =
> enc_to_dig_port(&encoder->base);
> enum port port = intel_dig_port->port;
> - uint32_t tmp;
> + uint32_t tmp, m;
> int len, i;
> int n, rate;
>
> @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> drm_connector *connector,
> DRM_ERROR("invalid port: %d\n", port);
> rate = 0;
> }
> - n = audio_config_get_n(adjusted_mode, rate);
> + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> if (n != 0)
> - tmp = audio_config_setup_n_reg(n, tmp);
> + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> else
> DRM_DEBUG_KMS("no suitable N value is found\n");
> }
>
> I915_WRITE(HSW_AUD_CFG(pipe), tmp);
>
> + /* setup m value for DP */
> + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> + m = audio_config_get_m(intel_crtc, adjusted_mode, rate);
> + if (m != 0) {
> + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> + }
> + }
> +
> mutex_unlock(&dev_priv->av_mutex);
> }
>
> @@ -637,7 +714,7 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> struct drm_display_mode *mode;
> struct i915_audio_component *acomp = dev_priv-
> >audio_component;
> enum pipe pipe = INVALID_PIPE;
> - u32 tmp;
> + u32 tmp, m;
> int n;
> int err = 0;
>
> @@ -645,7 +722,8 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> if (!IS_SKYLAKE(dev_priv) &&
> !IS_KABYLAKE(dev_priv) &&
> !IS_BROADWELL(dev_priv) &&
> - !IS_HASWELL(dev_priv))
> + !IS_HASWELL(dev_priv) &&
> + !IS_BROXTON(dev_priv))
> return 0;
>
> mutex_lock(&dev_priv->av_mutex);
> @@ -653,7 +731,8 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> intel_encoder = dev_priv->dig_port_map[port];
> /* intel_encoder might be NULL for DP MST */
> if (!intel_encoder || !intel_encoder->base.crtc ||
> - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> err = -ENODEV;
> goto unlock;
> @@ -681,7 +760,7 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> goto unlock;
> }
>
> - n = audio_config_get_n(mode, rate);
> + n = audio_config_get_n(crtc, mode, rate);
> if (n == 0) {
> DRM_DEBUG_KMS("Using automatic mode for N value on
> port %c\n",
> port_name(port));
> @@ -693,8 +772,17 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
>
> /* 3. set the N/CTS/M */
> tmp = I915_READ(HSW_AUD_CFG(pipe));
> - tmp = audio_config_setup_n_reg(n, tmp);
> + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> + /* setup m value for DP */
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + m = audio_config_get_m(crtc, mode, rate);
> + if (m == 0)
> + goto unlock;
> + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> + }
>
> unlock:
> mutex_unlock(&dev_priv->av_mutex);
> --
> 1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-07-14 7:06 [PATCH] drm/i915: set proper N/M in modeset libin.yang
2016-07-28 6:44 ` Yang, Libin
@ 2016-07-28 7:41 ` Ville Syrjälä
2016-07-29 5:54 ` Yang, Libin
1 sibling, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-07-28 7:41 UTC (permalink / raw)
To: libin.yang; +Cc: tiwai, daniel.vetter, intel-gfx
On Thu, Jul 14, 2016 at 03:06:21PM +0800, libin.yang@linux.intel.com wrote:
> From: Libin Yang <libin.yang@linux.intel.com>
>
> When modeset occurs and the LS_CLK is set to some
> special values in DP mode, the N/M need to be set
> manually if audio is playing.
>
> Also, the patch applies
> commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset")
> to APL platform.
>
> Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_reg.h | 6 ++
> drivers/gpu/drm/i915/intel_audio.c | 116 ++++++++++++++++++++++++++++++++-----
> 2 files changed, 108 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8bfde75..2f9d00e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -7351,6 +7351,12 @@ enum {
> #define _HSW_AUD_CONFIG_B 0x65100
> #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
>
> +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> +
> #define _HSW_AUD_MISC_CTRL_A 0x65010
> #define _HSW_AUD_MISC_CTRL_B 0x65110
> #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index 6700a7b..e2e4d4b 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -98,6 +98,22 @@ static const struct {
> { 192000, TMDS_297M, 20480, 247500 },
> };
>
> +#define LC_533M 533250
> +#define LC_148M 148500
> +static const struct {
> + int sample_rate;
> + int clock;
> + int n;
> + int m;
> +} aud_nm[] = {
> + {48000, LC_533M, 88875, 4096},
> + {44100, LC_533M, 148125, 6272},
> + {32000, LC_533M, 266625, 8192},
> + {48000, LC_148M, 12375, 2048},
> + {44100, LC_148M, 20625, 3136},
> + {32000, LC_148M, 37125, 4096},
> +};
> +
> /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
> static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode)
> {
> @@ -121,20 +137,50 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> return hdmi_audio_clock[i].config;
> }
>
> -static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
> +static int audio_config_get_n(struct intel_crtc *crtc,
> + const struct drm_display_mode *mode, int rate)
> +{
> + int i;
> +
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> + if ((rate == aud_ncts[i].sample_rate) &&
> + (mode->clock == aud_ncts[i].clock)) {
> + return aud_ncts[i].n;
> + }
> + }
> + }
> +
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> + if ((rate == aud_nm[i].sample_rate) &&
> + (mode->clock == aud_nm[i].clock)) {
So the spec says we should have "Maud / Naud = 512 * fs / f_LS_Clk",
where fs is the audio sample rate, and f_LS_CLK is the link symbol clock.
With that in mind this should not be looking at mode->clock but
crtc->config->port_clock.
So I don't actually understand why you say LS_CLK has "special" values.
It shouldn't. It's always either 162, 270, or 540 MHz.
Actually even the HDMI case is wrong in the code, it should be
looking at mode->crtc_clock instead of mode->clock. Or perhaps even
port_clock, if my reading of the HDMI spec is correct, but I never got
any sane answer from any hw folks to my questions about this :(
> + return aud_nm[i].n;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +static int audio_config_get_m(struct intel_crtc *crtc,
> + const struct drm_display_mode *mode, int rate)
> {
> int i;
>
> - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> - if ((rate == aud_ncts[i].sample_rate) &&
> - (mode->clock == aud_ncts[i].clock)) {
> - return aud_ncts[i].n;
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> + if ((rate == aud_nm[i].sample_rate) &&
> + (mode->clock == aud_nm[i].clock)) {
> + return aud_nm[i].m;
> + }
> }
> }
> +
> return 0;
> }
>
> -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> + int n, uint32_t val)
> {
> int n_low, n_up;
> uint32_t tmp = val;
> @@ -145,6 +191,23 @@ static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> AUD_CONFIG_N_PROG_ENABLE);
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> + return tmp;
> +}
> +
> +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> + int m, uint32_t val)
> +{
> + uint32_t tmp = val;
> +
> + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + return 0;
> +
> + tmp |= m;
> + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> +
> return tmp;
> }
>
> @@ -156,6 +219,10 @@ static bool audio_rate_need_prog(struct intel_crtc *crtc,
> (mode->clock == TMDS_296M)) &&
> intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> return true;
> + else if (((mode->clock == LC_533M) ||
> + (mode->clock == LC_148M)) &&
> + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + return true;
> else
> return false;
> }
> @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
> struct intel_digital_port *intel_dig_port =
> enc_to_dig_port(&encoder->base);
> enum port port = intel_dig_port->port;
> - uint32_t tmp;
> + uint32_t tmp, m;
> int len, i;
> int n, rate;
>
> @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
> DRM_ERROR("invalid port: %d\n", port);
> rate = 0;
> }
> - n = audio_config_get_n(adjusted_mode, rate);
> + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> if (n != 0)
> - tmp = audio_config_setup_n_reg(n, tmp);
> + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> else
> DRM_DEBUG_KMS("no suitable N value is found\n");
> }
>
> I915_WRITE(HSW_AUD_CFG(pipe), tmp);
>
> + /* setup m value for DP */
> + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> + m = audio_config_get_m(intel_crtc, adjusted_mode, rate);
> + if (m != 0) {
> + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> + }
> + }
> +
> mutex_unlock(&dev_priv->av_mutex);
> }
>
> @@ -637,7 +714,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> struct drm_display_mode *mode;
> struct i915_audio_component *acomp = dev_priv->audio_component;
> enum pipe pipe = INVALID_PIPE;
> - u32 tmp;
> + u32 tmp, m;
> int n;
> int err = 0;
>
> @@ -645,7 +722,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> if (!IS_SKYLAKE(dev_priv) &&
> !IS_KABYLAKE(dev_priv) &&
> !IS_BROADWELL(dev_priv) &&
> - !IS_HASWELL(dev_priv))
> + !IS_HASWELL(dev_priv) &&
> + !IS_BROXTON(dev_priv))
> return 0;
>
> mutex_lock(&dev_priv->av_mutex);
> @@ -653,7 +731,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> intel_encoder = dev_priv->dig_port_map[port];
> /* intel_encoder might be NULL for DP MST */
> if (!intel_encoder || !intel_encoder->base.crtc ||
> - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> err = -ENODEV;
> goto unlock;
> @@ -681,7 +760,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> goto unlock;
> }
>
> - n = audio_config_get_n(mode, rate);
> + n = audio_config_get_n(crtc, mode, rate);
> if (n == 0) {
> DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n",
> port_name(port));
> @@ -693,8 +772,17 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
>
> /* 3. set the N/CTS/M */
> tmp = I915_READ(HSW_AUD_CFG(pipe));
> - tmp = audio_config_setup_n_reg(n, tmp);
> + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> + /* setup m value for DP */
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + m = audio_config_get_m(crtc, mode, rate);
> + if (m == 0)
> + goto unlock;
> + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> + }
>
> unlock:
> mutex_unlock(&dev_priv->av_mutex);
> --
> 1.9.1
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-07-28 7:41 ` Ville Syrjälä
@ 2016-07-29 5:54 ` Yang, Libin
2016-07-29 9:47 ` Ville Syrjälä
0 siblings, 1 reply; 23+ messages in thread
From: Yang, Libin @ 2016-07-29 5:54 UTC (permalink / raw)
To: Ville Syrjälä, libin.yang@linux.intel.com
Cc: tiwai@suse.de, Vetter, Daniel, intel-gfx@lists.freedesktop.org
Hi Ville,
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Thursday, July 28, 2016 3:42 PM
> To: libin.yang@linux.intel.com
> Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com; Vetter,
> Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> <libin.yang@intel.com>
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Thu, Jul 14, 2016 at 03:06:21PM +0800, libin.yang@linux.intel.com wrote:
> > From: Libin Yang <libin.yang@linux.intel.com>
> >
> > When modeset occurs and the LS_CLK is set to some special values in DP
> > mode, the N/M need to be set manually if audio is playing.
> >
> > Also, the patch applies
> > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > platform.
> >
> > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > drivers/gpu/drm/i915/intel_audio.c | 116
> > ++++++++++++++++++++++++++++++++-----
> > 2 files changed, 108 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -7351,6 +7351,12 @@ enum {
> > #define _HSW_AUD_CONFIG_B 0x65100
> > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> >
> > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > +
> > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > b/drivers/gpu/drm/i915/intel_audio.c
> > index 6700a7b..e2e4d4b 100644
> > --- a/drivers/gpu/drm/i915/intel_audio.c
> > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > @@ -98,6 +98,22 @@ static const struct {
> > { 192000, TMDS_297M, 20480, 247500 }, };
> >
> > +#define LC_533M 533250
> > +#define LC_148M 148500
> > +static const struct {
> > + int sample_rate;
> > + int clock;
> > + int n;
> > + int m;
> > +} aud_nm[] = {
> > + {48000, LC_533M, 88875, 4096},
> > + {44100, LC_533M, 148125, 6272},
> > + {32000, LC_533M, 266625, 8192},
> > + {48000, LC_148M, 12375, 2048},
> > + {44100, LC_148M, 20625, 3136},
> > + {32000, LC_148M, 37125, 4096},
> > +};
> > +
> > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> > return hdmi_audio_clock[i].config;
> > }
> >
> > -static int audio_config_get_n(const struct drm_display_mode *mode,
> > int rate)
> > +static int audio_config_get_n(struct intel_crtc *crtc,
> > + const struct drm_display_mode *mode, int rate) {
> > + int i;
> > +
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > + if ((rate == aud_ncts[i].sample_rate) &&
> > + (mode->clock == aud_ncts[i].clock)) {
> > + return aud_ncts[i].n;
> > + }
> > + }
> > + }
> > +
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > + if ((rate == aud_nm[i].sample_rate) &&
> > + (mode->clock == aud_nm[i].clock)) {
>
> So the spec says we should have "Maud / Naud = 512 * fs / f_LS_Clk", where
> fs is the audio sample rate, and f_LS_CLK is the link symbol clock.
> With that in mind this should not be looking at mode->clock but
> crtc->config->port_clock.
>
> So I don't actually understand why you say LS_CLK has "special" values.
> It shouldn't. It's always either 162, 270, or 540 MHz.
Thanks for the correction. I will use crtc->config->port_clock.
>
> Actually even the HDMI case is wrong in the code, it should be looking at
> mode->crtc_clock instead of mode->clock. Or perhaps even port_clock, if my
> reading of the HDMI spec is correct, but I never got any sane answer from
> any hw folks to my questions about this :(
I will try mode->crtc_clock later for HDMI. Thanks.
Regards,
Libin
>
> > + return aud_nm[i].n;
> > + }
> > + }
> > + }
> > + return 0;
> > +}
> > +
> > +static int audio_config_get_m(struct intel_crtc *crtc,
> > + const struct drm_display_mode *mode, int rate)
> > {
> > int i;
> >
> > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > - if ((rate == aud_ncts[i].sample_rate) &&
> > - (mode->clock == aud_ncts[i].clock)) {
> > - return aud_ncts[i].n;
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > + if ((rate == aud_nm[i].sample_rate) &&
> > + (mode->clock == aud_nm[i].clock)) {
> > + return aud_nm[i].m;
> > + }
> > }
> > }
> > +
> > return 0;
> > }
> >
> > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > + int n, uint32_t val)
> > {
> > int n_low, n_up;
> > uint32_t tmp = val;
> > @@ -145,6 +191,23 @@ static uint32_t audio_config_setup_n_reg(int n,
> uint32_t val)
> > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > AUD_CONFIG_N_PROG_ENABLE);
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > + return tmp;
> > +}
> > +
> > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > + int m, uint32_t val)
> > +{
> > + uint32_t tmp = val;
> > +
> > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > + return 0;
> > +
> > + tmp |= m;
> > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > +
> > return tmp;
> > }
> >
> > @@ -156,6 +219,10 @@ static bool audio_rate_need_prog(struct intel_crtc
> *crtc,
> > (mode->clock == TMDS_296M)) &&
> > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > return true;
> > + else if (((mode->clock == LC_533M) ||
> > + (mode->clock == LC_148M)) &&
> > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > + return true;
> > else
> > return false;
> > }
> > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> drm_connector *connector,
> > struct intel_digital_port *intel_dig_port =
> > enc_to_dig_port(&encoder->base);
> > enum port port = intel_dig_port->port;
> > - uint32_t tmp;
> > + uint32_t tmp, m;
> > int len, i;
> > int n, rate;
> >
> > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> drm_connector *connector,
> > DRM_ERROR("invalid port: %d\n", port);
> > rate = 0;
> > }
> > - n = audio_config_get_n(adjusted_mode, rate);
> > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > if (n != 0)
> > - tmp = audio_config_setup_n_reg(n, tmp);
> > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > else
> > DRM_DEBUG_KMS("no suitable N value is found\n");
> > }
> >
> > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> >
> > + /* setup m value for DP */
> > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > + m = audio_config_get_m(intel_crtc, adjusted_mode, rate);
> > + if (m != 0) {
> > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > + }
> > + }
> > +
> > mutex_unlock(&dev_priv->av_mutex);
> > }
> >
> > @@ -637,7 +714,7 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > struct drm_display_mode *mode;
> > struct i915_audio_component *acomp = dev_priv-
> >audio_component;
> > enum pipe pipe = INVALID_PIPE;
> > - u32 tmp;
> > + u32 tmp, m;
> > int n;
> > int err = 0;
> >
> > @@ -645,7 +722,8 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > if (!IS_SKYLAKE(dev_priv) &&
> > !IS_KABYLAKE(dev_priv) &&
> > !IS_BROADWELL(dev_priv) &&
> > - !IS_HASWELL(dev_priv))
> > + !IS_HASWELL(dev_priv) &&
> > + !IS_BROXTON(dev_priv))
> > return 0;
> >
> > mutex_lock(&dev_priv->av_mutex);
> > @@ -653,7 +731,8 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > intel_encoder = dev_priv->dig_port_map[port];
> > /* intel_encoder might be NULL for DP MST */
> > if (!intel_encoder || !intel_encoder->base.crtc ||
> > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > err = -ENODEV;
> > goto unlock;
> > @@ -681,7 +760,7 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > goto unlock;
> > }
> >
> > - n = audio_config_get_n(mode, rate);
> > + n = audio_config_get_n(crtc, mode, rate);
> > if (n == 0) {
> > DRM_DEBUG_KMS("Using automatic mode for N value on
> port %c\n",
> > port_name(port));
> > @@ -693,8 +772,17 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> >
> > /* 3. set the N/CTS/M */
> > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > - tmp = audio_config_setup_n_reg(n, tmp);
> > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > + /* setup m value for DP */
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > + m = audio_config_get_m(crtc, mode, rate);
> > + if (m == 0)
> > + goto unlock;
> > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > + }
> >
> > unlock:
> > mutex_unlock(&dev_priv->av_mutex);
> > --
> > 1.9.1
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-07-29 5:54 ` Yang, Libin
@ 2016-07-29 9:47 ` Ville Syrjälä
2016-08-01 1:31 ` Yang, Libin
0 siblings, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-07-29 9:47 UTC (permalink / raw)
To: Yang, Libin
Cc: tiwai@suse.de, Vetter, Daniel, libin.yang@linux.intel.com,
intel-gfx@lists.freedesktop.org
On Fri, Jul 29, 2016 at 05:54:23AM +0000, Yang, Libin wrote:
> Hi Ville,
>
> > -----Original Message-----
> > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > Sent: Thursday, July 28, 2016 3:42 PM
> > To: libin.yang@linux.intel.com
> > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com; Vetter,
> > Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > <libin.yang@intel.com>
> > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> >
> > On Thu, Jul 14, 2016 at 03:06:21PM +0800, libin.yang@linux.intel.com wrote:
> > > From: Libin Yang <libin.yang@linux.intel.com>
> > >
> > > When modeset occurs and the LS_CLK is set to some special values in DP
> > > mode, the N/M need to be set manually if audio is playing.
> > >
> > > Also, the patch applies
> > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > > platform.
> > >
> > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > ---
> > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > drivers/gpu/drm/i915/intel_audio.c | 116
> > > ++++++++++++++++++++++++++++++++-----
> > > 2 files changed, 108 insertions(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -7351,6 +7351,12 @@ enum {
> > > #define _HSW_AUD_CONFIG_B 0x65100
> > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > >
> > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > +
> > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > b/drivers/gpu/drm/i915/intel_audio.c
> > > index 6700a7b..e2e4d4b 100644
> > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > @@ -98,6 +98,22 @@ static const struct {
> > > { 192000, TMDS_297M, 20480, 247500 }, };
> > >
> > > +#define LC_533M 533250
> > > +#define LC_148M 148500
> > > +static const struct {
> > > + int sample_rate;
> > > + int clock;
> > > + int n;
> > > + int m;
> > > +} aud_nm[] = {
> > > + {48000, LC_533M, 88875, 4096},
> > > + {44100, LC_533M, 148125, 6272},
> > > + {32000, LC_533M, 266625, 8192},
> > > + {48000, LC_148M, 12375, 2048},
> > > + {44100, LC_148M, 20625, 3136},
> > > + {32000, LC_148M, 37125, 4096},
> > > +};
> > > +
> > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> > > return hdmi_audio_clock[i].config;
> > > }
> > >
> > > -static int audio_config_get_n(const struct drm_display_mode *mode,
> > > int rate)
> > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > + const struct drm_display_mode *mode, int rate) {
> > > + int i;
> > > +
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > + (mode->clock == aud_ncts[i].clock)) {
> > > + return aud_ncts[i].n;
> > > + }
> > > + }
> > > + }
> > > +
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > + if ((rate == aud_nm[i].sample_rate) &&
> > > + (mode->clock == aud_nm[i].clock)) {
> >
> > So the spec says we should have "Maud / Naud = 512 * fs / f_LS_Clk", where
> > fs is the audio sample rate, and f_LS_CLK is the link symbol clock.
> > With that in mind this should not be looking at mode->clock but
> > crtc->config->port_clock.
> >
> > So I don't actually understand why you say LS_CLK has "special" values.
> > It shouldn't. It's always either 162, 270, or 540 MHz.
>
> Thanks for the correction. I will use crtc->config->port_clock.
But why do you need to do it at all? The hardware can't deal with one of
the standard link rates on its own?
>
> >
> > Actually even the HDMI case is wrong in the code, it should be looking at
> > mode->crtc_clock instead of mode->clock. Or perhaps even port_clock, if my
> > reading of the HDMI spec is correct, but I never got any sane answer from
> > any hw folks to my questions about this :(
>
> I will try mode->crtc_clock later for HDMI. Thanks.
While you're at it, can you pls do s/mode/adjusted_mode/ ? A while back
I unified our naming convention for these things, but looks like the
audio code has since gone back to the inconsisten old way.
>
> Regards,
> Libin
>
> >
> > > + return aud_nm[i].n;
> > > + }
> > > + }
> > > + }
> > > + return 0;
> > > +}
> > > +
> > > +static int audio_config_get_m(struct intel_crtc *crtc,
> > > + const struct drm_display_mode *mode, int rate)
> > > {
> > > int i;
> > >
> > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > - (mode->clock == aud_ncts[i].clock)) {
> > > - return aud_ncts[i].n;
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > + if ((rate == aud_nm[i].sample_rate) &&
> > > + (mode->clock == aud_nm[i].clock)) {
> > > + return aud_nm[i].m;
> > > + }
> > > }
> > > }
> > > +
> > > return 0;
> > > }
> > >
> > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > + int n, uint32_t val)
> > > {
> > > int n_low, n_up;
> > > uint32_t tmp = val;
> > > @@ -145,6 +191,23 @@ static uint32_t audio_config_setup_n_reg(int n,
> > uint32_t val)
> > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > AUD_CONFIG_N_PROG_ENABLE);
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > + return tmp;
> > > +}
> > > +
> > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > + int m, uint32_t val)
> > > +{
> > > + uint32_t tmp = val;
> > > +
> > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + return 0;
> > > +
> > > + tmp |= m;
> > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > +
> > > return tmp;
> > > }
> > >
> > > @@ -156,6 +219,10 @@ static bool audio_rate_need_prog(struct intel_crtc
> > *crtc,
> > > (mode->clock == TMDS_296M)) &&
> > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > return true;
> > > + else if (((mode->clock == LC_533M) ||
> > > + (mode->clock == LC_148M)) &&
> > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + return true;
> > > else
> > > return false;
> > > }
> > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > drm_connector *connector,
> > > struct intel_digital_port *intel_dig_port =
> > > enc_to_dig_port(&encoder->base);
> > > enum port port = intel_dig_port->port;
> > > - uint32_t tmp;
> > > + uint32_t tmp, m;
> > > int len, i;
> > > int n, rate;
> > >
> > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > drm_connector *connector,
> > > DRM_ERROR("invalid port: %d\n", port);
> > > rate = 0;
> > > }
> > > - n = audio_config_get_n(adjusted_mode, rate);
> > > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > > if (n != 0)
> > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > > else
> > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > }
> > >
> > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > >
> > > + /* setup m value for DP */
> > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > > + m = audio_config_get_m(intel_crtc, adjusted_mode, rate);
> > > + if (m != 0) {
> > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > + }
> > > + }
> > > +
> > > mutex_unlock(&dev_priv->av_mutex);
> > > }
> > >
> > > @@ -637,7 +714,7 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > struct drm_display_mode *mode;
> > > struct i915_audio_component *acomp = dev_priv-
> > >audio_component;
> > > enum pipe pipe = INVALID_PIPE;
> > > - u32 tmp;
> > > + u32 tmp, m;
> > > int n;
> > > int err = 0;
> > >
> > > @@ -645,7 +722,8 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > if (!IS_SKYLAKE(dev_priv) &&
> > > !IS_KABYLAKE(dev_priv) &&
> > > !IS_BROADWELL(dev_priv) &&
> > > - !IS_HASWELL(dev_priv))
> > > + !IS_HASWELL(dev_priv) &&
> > > + !IS_BROXTON(dev_priv))
> > > return 0;
> > >
> > > mutex_lock(&dev_priv->av_mutex);
> > > @@ -653,7 +731,8 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > intel_encoder = dev_priv->dig_port_map[port];
> > > /* intel_encoder might be NULL for DP MST */
> > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > > err = -ENODEV;
> > > goto unlock;
> > > @@ -681,7 +760,7 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > goto unlock;
> > > }
> > >
> > > - n = audio_config_get_n(mode, rate);
> > > + n = audio_config_get_n(crtc, mode, rate);
> > > if (n == 0) {
> > > DRM_DEBUG_KMS("Using automatic mode for N value on
> > port %c\n",
> > > port_name(port));
> > > @@ -693,8 +772,17 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > >
> > > /* 3. set the N/CTS/M */
> > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > + /* setup m value for DP */
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + m = audio_config_get_m(crtc, mode, rate);
> > > + if (m == 0)
> > > + goto unlock;
> > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > + }
> > >
> > > unlock:
> > > mutex_unlock(&dev_priv->av_mutex);
> > > --
> > > 1.9.1
> >
> > --
> > Ville Syrjälä
> > Intel OTC
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-07-29 9:47 ` Ville Syrjälä
@ 2016-08-01 1:31 ` Yang, Libin
0 siblings, 0 replies; 23+ messages in thread
From: Yang, Libin @ 2016-08-01 1:31 UTC (permalink / raw)
To: Ville Syrjälä
Cc: tiwai@suse.de, Vetter, Daniel, libin.yang@linux.intel.com,
intel-gfx@lists.freedesktop.org
Hi Ville,
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Friday, July 29, 2016 5:47 PM
> To: Yang, Libin <libin.yang@intel.com>
> Cc: libin.yang@linux.intel.com; intel-gfx@lists.freedesktop.org;
> jani.nikula@linux.intel.com; Vetter, Daniel <daniel.vetter@intel.com>;
> tiwai@suse.de
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Fri, Jul 29, 2016 at 05:54:23AM +0000, Yang, Libin wrote:
> > Hi Ville,
> >
> > > -----Original Message-----
> > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > Sent: Thursday, July 28, 2016 3:42 PM
> > > To: libin.yang@linux.intel.com
> > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > <libin.yang@intel.com>
> > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > >
> > > On Thu, Jul 14, 2016 at 03:06:21PM +0800, libin.yang@linux.intel.com
> wrote:
> > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > >
> > > > When modeset occurs and the LS_CLK is set to some special values
> > > > in DP mode, the N/M need to be set manually if audio is playing.
> > > >
> > > > Also, the patch applies
> > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to
> > > > APL platform.
> > > >
> > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > ---
> > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > drivers/gpu/drm/i915/intel_audio.c | 116
> > > > ++++++++++++++++++++++++++++++++-----
> > > > 2 files changed, 108 insertions(+), 14 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > @@ -7351,6 +7351,12 @@ enum {
> > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > >
> > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> _MMIO_PIPE(pipe,
> > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > +
> > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > index 6700a7b..e2e4d4b 100644
> > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > @@ -98,6 +98,22 @@ static const struct {
> > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > >
> > > > +#define LC_533M 533250
> > > > +#define LC_148M 148500
> > > > +static const struct {
> > > > + int sample_rate;
> > > > + int clock;
> > > > + int n;
> > > > + int m;
> > > > +} aud_nm[] = {
> > > > + {48000, LC_533M, 88875, 4096},
> > > > + {44100, LC_533M, 148125, 6272},
> > > > + {32000, LC_533M, 266625, 8192},
> > > > + {48000, LC_148M, 12375, 2048},
> > > > + {44100, LC_148M, 20625, 3136},
> > > > + {32000, LC_148M, 37125, 4096},
> > > > +};
> > > > +
> > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static
> > > > u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> *adjusted
> > > > return hdmi_audio_clock[i].config; }
> > > >
> > > > -static int audio_config_get_n(const struct drm_display_mode
> > > > *mode, int rate)
> > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > + const struct drm_display_mode *mode, int rate) {
> > > > + int i;
> > > > +
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > + (mode->clock == aud_ncts[i].clock)) {
> > > > + return aud_ncts[i].n;
> > > > + }
> > > > + }
> > > > + }
> > > > +
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > + (mode->clock == aud_nm[i].clock)) {
> > >
> > > So the spec says we should have "Maud / Naud = 512 * fs / f_LS_Clk",
> > > where fs is the audio sample rate, and f_LS_CLK is the link symbol clock.
> > > With that in mind this should not be looking at mode->clock but
> > > crtc->config->port_clock.
> > >
> > > So I don't actually understand why you say LS_CLK has "special" values.
> > > It shouldn't. It's always either 162, 270, or 540 MHz.
> >
> > Thanks for the correction. I will use crtc->config->port_clock.
>
> But why do you need to do it at all? The hardware can't deal with one of the
> standard link rates on its own?
Yes, we found that the HW can't set the N/M automatically. This will cause
there is several seconds of silence at the beginning of audio playback.
>
> >
> > >
> > > Actually even the HDMI case is wrong in the code, it should be
> > > looking at
> > > mode->crtc_clock instead of mode->clock. Or perhaps even port_clock,
> > > mode->if my
> > > reading of the HDMI spec is correct, but I never got any sane answer
> > > from any hw folks to my questions about this :(
> >
> > I will try mode->crtc_clock later for HDMI. Thanks.
>
> While you're at it, can you pls do s/mode/adjusted_mode/ ? A while back I
> unified our naming convention for these things, but looks like the audio code
> has since gone back to the inconsisten old way.
Yes, I will do it, replace mode with adjusted_mode.
Regards,
Libin
>
> >
> > Regards,
> > Libin
> >
> > >
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH] drm/i915: set proper N/M in modeset
@ 2016-08-02 1:35 libin.yang
2016-08-02 5:30 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev2) Patchwork
` (3 more replies)
0 siblings, 4 replies; 23+ messages in thread
From: libin.yang @ 2016-08-02 1:35 UTC (permalink / raw)
To: intel-gfx, jani.nikula, ville.syrjala, daniel.vetter, tiwai; +Cc: Libin Yang
From: Libin Yang <libin.yang@linux.intel.com>
When modeset occurs and the LS_CLK is set to some
special values in DP mode, the N/M need to be set
manually if audio is playing.
The relationship of Maud and Naud is expressed in
the following equation:
Maud/Naud = 512 * fs / f_LS_Clk
Please refer VESA DisplayPort Standard spec for details.
Also, the patch applies
commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset")
to APL platform.
Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
---
drivers/gpu/drm/i915/i915_reg.h | 6 ++
drivers/gpu/drm/i915/intel_audio.c | 122 +++++++++++++++++++++++++++++++------
2 files changed, 111 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8bfde75..2f9d00e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7351,6 +7351,12 @@ enum {
#define _HSW_AUD_CONFIG_B 0x65100
#define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
+#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
+#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
+#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
+#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
+#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
+
#define _HSW_AUD_MISC_CTRL_A 0x65010
#define _HSW_AUD_MISC_CTRL_B 0x65110
#define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 6700a7b..de55ecf 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -98,6 +98,22 @@ static const struct {
{ 192000, TMDS_297M, 20480, 247500 },
};
+#define LC_540M 540000
+#define LC_162M 162000
+static const struct {
+ int sample_rate;
+ int clock;
+ int n;
+ int m;
+} aud_nm[] = {
+ {48000, LC_540M, 5625, 256},
+ {44100, LC_540M, 9375, 392},
+ {32000, LC_540M, 16875, 512},
+ {48000, LC_162M, 3375, 512},
+ {44100, LC_162M, 5625, 784},
+ {32000, LC_162M, 10125, 1024},
+};
+
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode)
{
@@ -121,20 +137,50 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
return hdmi_audio_clock[i].config;
}
-static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
+static int audio_config_get_n(struct intel_crtc *crtc,
+ const struct drm_display_mode *adjusted_mode,
+ int rate)
+{
+ int i;
+
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
+ for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
+ if ((rate == aud_ncts[i].sample_rate) &&
+ (adjusted_mode->clock == aud_ncts[i].clock)) {
+ return aud_ncts[i].n;
+ }
+ }
+ }
+
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
+ for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
+ if ((rate == aud_nm[i].sample_rate) &&
+ (crtc->config->port_clock == aud_nm[i].clock)) {
+ return aud_nm[i].n;
+ }
+ }
+ }
+ return 0;
+}
+
+static int audio_config_get_m(struct intel_crtc *crtc, int rate)
{
int i;
- for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
- if ((rate == aud_ncts[i].sample_rate) &&
- (mode->clock == aud_ncts[i].clock)) {
- return aud_ncts[i].n;
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
+ for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
+ if ((rate == aud_nm[i].sample_rate) &&
+ (crtc->config->port_clock == aud_nm[i].clock)) {
+ return aud_nm[i].m;
+ }
}
}
+
return 0;
}
-static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
+static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
+ int n, uint32_t val)
{
int n_low, n_up;
uint32_t tmp = val;
@@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
(n_low << AUD_CONFIG_LOWER_N_SHIFT) |
AUD_CONFIG_N_PROG_ENABLE);
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
+ tmp |= AUD_CONFIG_N_VALUE_INDEX;
+ return tmp;
+}
+
+static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
+ int m, uint32_t val)
+{
+ uint32_t tmp = val;
+
+ if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
+ return 0;
+
+ tmp |= m;
+ tmp |= AUD_M_CTS_M_VALUE_INDEX;
+ tmp |= AUD_M_CTS_M_PROG_ENABLE;
+
return tmp;
}
/* check whether N/CTS/M need be set manually */
static bool audio_rate_need_prog(struct intel_crtc *crtc,
- const struct drm_display_mode *mode)
+ const struct drm_display_mode *adjusted_mode)
{
- if (((mode->clock == TMDS_297M) ||
- (mode->clock == TMDS_296M)) &&
+ if (((adjusted_mode->clock == TMDS_297M) ||
+ (adjusted_mode->clock == TMDS_296M)) &&
intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
return true;
+ else if (((crtc->config->port_clock == LC_540M) ||
+ (crtc->config->port_clock == LC_162M)) &&
+ intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
+ return true;
else
return false;
}
@@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
struct intel_digital_port *intel_dig_port =
enc_to_dig_port(&encoder->base);
enum port port = intel_dig_port->port;
- uint32_t tmp;
+ uint32_t tmp, m;
int len, i;
int n, rate;
@@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
DRM_ERROR("invalid port: %d\n", port);
rate = 0;
}
- n = audio_config_get_n(adjusted_mode, rate);
+ n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
if (n != 0)
- tmp = audio_config_setup_n_reg(n, tmp);
+ tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
else
DRM_DEBUG_KMS("no suitable N value is found\n");
}
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ /* setup m value for DP */
+ if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
+ m = audio_config_get_m(intel_crtc, rate);
+ if (m != 0) {
+ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+ tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
+ I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+ }
+ }
+
mutex_unlock(&dev_priv->av_mutex);
}
@@ -637,7 +714,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
struct drm_display_mode *mode;
struct i915_audio_component *acomp = dev_priv->audio_component;
enum pipe pipe = INVALID_PIPE;
- u32 tmp;
+ u32 tmp, m;
int n;
int err = 0;
@@ -645,7 +722,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
if (!IS_SKYLAKE(dev_priv) &&
!IS_KABYLAKE(dev_priv) &&
!IS_BROADWELL(dev_priv) &&
- !IS_HASWELL(dev_priv))
+ !IS_HASWELL(dev_priv) &&
+ !IS_BROXTON(dev_priv))
return 0;
mutex_lock(&dev_priv->av_mutex);
@@ -653,7 +731,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
intel_encoder = dev_priv->dig_port_map[port];
/* intel_encoder might be NULL for DP MST */
if (!intel_encoder || !intel_encoder->base.crtc ||
- intel_encoder->type != INTEL_OUTPUT_HDMI) {
+ ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
+ (intel_encoder->type != INTEL_OUTPUT_DP))) {
DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
err = -ENODEV;
goto unlock;
@@ -681,7 +760,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
goto unlock;
}
- n = audio_config_get_n(mode, rate);
+ n = audio_config_get_n(crtc, mode, rate);
if (n == 0) {
DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n",
port_name(port));
@@ -693,8 +772,17 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
/* 3. set the N/CTS/M */
tmp = I915_READ(HSW_AUD_CFG(pipe));
- tmp = audio_config_setup_n_reg(n, tmp);
+ tmp = audio_config_setup_n_reg(crtc, n, tmp);
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+ /* setup m value for DP */
+ if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
+ m = audio_config_get_m(crtc, rate);
+ if (m == 0)
+ goto unlock;
+ tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+ tmp = audio_config_setup_m_reg(crtc, m, tmp);
+ I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+ }
unlock:
mutex_unlock(&dev_priv->av_mutex);
--
1.9.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 23+ messages in thread
* ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev2)
2016-08-02 1:35 [PATCH] drm/i915: set proper N/M in modeset libin.yang
@ 2016-08-02 5:30 ` Patchwork
2016-08-02 10:47 ` [PATCH] drm/i915: set proper N/M in modeset Ville Syrjälä
` (2 subsequent siblings)
3 siblings, 0 replies; 23+ messages in thread
From: Patchwork @ 2016-08-02 5:30 UTC (permalink / raw)
To: libin.yang; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: set proper N/M in modeset (rev2)
URL : https://patchwork.freedesktop.org/series/9857/
State : failure
== Summary ==
Series 9857v2 drm/i915: set proper N/M in modeset
http://patchwork.freedesktop.org/api/1.0/series/9857/revisions/2/mbox
Test gem_exec_gttfill:
Subgroup basic:
pass -> SKIP (fi-snb-i7-2600)
Test kms_cursor_legacy:
Subgroup basic-cursor-vs-flip-legacy:
fail -> PASS (ro-ilk1-i5-650)
Subgroup basic-flip-vs-cursor-legacy:
fail -> PASS (fi-hsw-i7-4770k)
pass -> FAIL (ro-bdw-i5-5250u)
Subgroup basic-flip-vs-cursor-varying-size:
fail -> PASS (ro-hsw-i7-4770r)
fail -> PASS (ro-bdw-i5-5250u)
Test kms_pipe_crc_basic:
Subgroup suspend-read-crc-pipe-b:
pass -> INCOMPLETE (fi-hsw-i7-4770k)
fi-hsw-i7-4770k total:207 pass:186 dwarn:0 dfail:0 fail:0 skip:20
fi-kbl-qkkr total:240 pass:181 dwarn:30 dfail:0 fail:2 skip:27
fi-skl-i5-6260u total:240 pass:224 dwarn:0 dfail:0 fail:2 skip:14
fi-skl-i7-6700k total:240 pass:208 dwarn:0 dfail:0 fail:4 skip:28
fi-snb-i7-2600 total:240 pass:197 dwarn:0 dfail:0 fail:0 skip:43
ro-bdw-i5-5250u total:240 pass:219 dwarn:4 dfail:0 fail:1 skip:16
ro-bdw-i7-5600u total:240 pass:207 dwarn:0 dfail:0 fail:1 skip:32
ro-bsw-n3050 total:240 pass:194 dwarn:0 dfail:0 fail:4 skip:42
ro-byt-n2820 total:240 pass:197 dwarn:0 dfail:0 fail:3 skip:40
ro-hsw-i3-4010u total:240 pass:214 dwarn:0 dfail:0 fail:0 skip:26
ro-hsw-i7-4770r total:240 pass:214 dwarn:0 dfail:0 fail:0 skip:26
ro-ilk-i7-620lm total:240 pass:173 dwarn:1 dfail:0 fail:1 skip:65
ro-ilk1-i5-650 total:235 pass:174 dwarn:0 dfail:0 fail:1 skip:60
ro-ivb-i7-3770 total:240 pass:205 dwarn:0 dfail:0 fail:0 skip:35
ro-ivb2-i7-3770 total:240 pass:209 dwarn:0 dfail:0 fail:0 skip:31
ro-skl3-i5-6260u total:240 pass:222 dwarn:0 dfail:0 fail:4 skip:14
ro-snb-i7-2620M total:240 pass:198 dwarn:0 dfail:0 fail:1 skip:41
ro-bdw-i7-5557U failed to connect after reboot
Results at /archive/results/CI_IGT_test/RO_Patchwork_1660/
6f87e85 drm-intel-nightly: 2016y-08m-01d-14h-53m-17s UTC integration manifest
1608e48 drm/i915: set proper N/M in modeset
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 1:35 [PATCH] drm/i915: set proper N/M in modeset libin.yang
2016-08-02 5:30 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev2) Patchwork
@ 2016-08-02 10:47 ` Ville Syrjälä
2016-08-02 13:58 ` Yang, Libin
2016-08-02 10:52 ` Jani Nikula
2016-08-04 6:29 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev3) Patchwork
3 siblings, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-08-02 10:47 UTC (permalink / raw)
To: libin.yang; +Cc: tiwai, daniel.vetter, intel-gfx
On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com wrote:
> From: Libin Yang <libin.yang@linux.intel.com>
>
> When modeset occurs and the LS_CLK is set to some
> special values in DP mode, the N/M need to be set
> manually if audio is playing.
>
> The relationship of Maud and Naud is expressed in
> the following equation:
> Maud/Naud = 512 * fs / f_LS_Clk
>
> Please refer VESA DisplayPort Standard spec for details.
>
> Also, the patch applies
> commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset")
> to APL platform.
>
> Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> ---
> drivers/gpu/drm/i915/i915_reg.h | 6 ++
> drivers/gpu/drm/i915/intel_audio.c | 122 +++++++++++++++++++++++++++++++------
> 2 files changed, 111 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8bfde75..2f9d00e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -7351,6 +7351,12 @@ enum {
> #define _HSW_AUD_CONFIG_B 0x65100
> #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe, _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
>
> +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> +
> #define _HSW_AUD_MISC_CTRL_A 0x65010
> #define _HSW_AUD_MISC_CTRL_B 0x65110
> #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
> index 6700a7b..de55ecf 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -98,6 +98,22 @@ static const struct {
> { 192000, TMDS_297M, 20480, 247500 },
> };
>
> +#define LC_540M 540000
> +#define LC_162M 162000
Do we have some explanation why 2.7 doesn't need M/N programming,
but 1.62 and 5.4 do?
And I see you're only doing this on HSW+. Earlier platforms don't need
this?
> +static const struct {
> + int sample_rate;
> + int clock;
> + int n;
> + int m;
Can save a bit of space by using u16 for m and n.
> +} aud_nm[] = {
> + {48000, LC_540M, 5625, 256},`
> + {44100, LC_540M, 9375, 392},
> + {32000, LC_540M, 16875, 512},
> + {48000, LC_162M, 3375, 512},
> + {44100, LC_162M, 5625, 784},
> + {32000, LC_162M, 10125, 1024
> +};
The numbers look good, but what about other sample rates? For HDMI we go
up to 192kHz, why not for DP?
> +
> /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
> static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode)
> {
> @@ -121,20 +137,50 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> return hdmi_audio_clock[i].config;
> }
>
> -static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
> +static int audio_config_get_n(struct intel_crtc *crtc,
> + const struct drm_display_mode *adjusted_mode,
> + int rate)
> +{
> + int i;
> +
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> + if ((rate == aud_ncts[i].sample_rate) &&
> + (adjusted_mode->clock == aud_ncts[i].clock)) {
> + return aud_ncts[i].n;
> + }
> + }
> + }
> +
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> + if ((rate == aud_nm[i].sample_rate) &&
> + (crtc->config->port_clock == aud_nm[i].clock)) {
> + return aud_nm[i].n;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +static int audio_config_get_m(struct intel_crtc *crtc, int rate)
> {
> int i;
>
> - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> - if ((rate == aud_ncts[i].sample_rate) &&
> - (mode->clock == aud_ncts[i].clock)) {
> - return aud_ncts[i].n;
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> + if ((rate == aud_nm[i].sample_rate) &&
> + (crtc->config->port_clock == aud_nm[i].clock)) {
> + return aud_nm[i].m;
> + }
> }
> }
> +
> return 0;
> }
>
> -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> + int n, uint32_t val)
> {
> int n_low, n_up;
> uint32_t tmp = val;
> @@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> AUD_CONFIG_N_PROG_ENABLE);
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> + return tmp;
> +}
> +
> +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> + int m, uint32_t val)
> +{
> + uint32_t tmp = val;
> +
> + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + return 0;
> +
> + tmp |= m;
> + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> +
> return tmp;
> }
>
> /* check whether N/CTS/M need be set manually */
> static bool audio_rate_need_prog(struct intel_crtc *crtc,
> - const struct drm_display_mode *mode)
> + const struct drm_display_mode *adjusted_mode)
> {
> - if (((mode->clock == TMDS_297M) ||
> - (mode->clock == TMDS_296M)) &&
> + if (((adjusted_mode->clock == TMDS_297M) ||
> + (adjusted_mode->clock == TMDS_296M)) &&
> intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> return true;
> + else if (((crtc->config->port_clock == LC_540M) ||
> + (crtc->config->port_clock == LC_162M)) &&
> + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> + return true;
> else
> return false;
> }
> @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
> struct intel_digital_port *intel_dig_port =
> enc_to_dig_port(&encoder->base);
> enum port port = intel_dig_port->port;
> - uint32_t tmp;
> + uint32_t tmp, m;
> int len, i;
> int n, rate;
>
> @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct drm_connector *connector,
> DRM_ERROR("invalid port: %d\n", port);
> rate = 0;
> }
> - n = audio_config_get_n(adjusted_mode, rate);
> + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> if (n != 0)
> - tmp = audio_config_setup_n_reg(n, tmp);
> + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> else
> DRM_DEBUG_KMS("no suitable N value is found\n");
> }
>
> I915_WRITE(HSW_AUD_CFG(pipe), tmp);
>
> + /* setup m value for DP */
> + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> + m = audio_config_get_m(intel_crtc, rate);
> + if (m != 0) {
> + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> + }
> + }
> +
> mutex_unlock(&dev_priv->av_mutex);
> }
>
> @@ -637,7 +714,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> struct drm_display_mode *mode;
> struct i915_audio_component *acomp = dev_priv->audio_component;
> enum pipe pipe = INVALID_PIPE;
> - u32 tmp;
> + u32 tmp, m;
> int n;
> int err = 0;
>
> @@ -645,7 +722,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> if (!IS_SKYLAKE(dev_priv) &&
> !IS_KABYLAKE(dev_priv) &&
> !IS_BROADWELL(dev_priv) &&
> - !IS_HASWELL(dev_priv))
> + !IS_HASWELL(dev_priv) &&
> + !IS_BROXTON(dev_priv))
> return 0;
HAS_DDI perhaps?
>
> mutex_lock(&dev_priv->av_mutex);
> @@ -653,7 +731,8 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> intel_encoder = dev_priv->dig_port_map[port];
> /* intel_encoder might be NULL for DP MST */
> if (!intel_encoder || !intel_encoder->base.crtc ||
> - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> err = -ENODEV;
> goto unlock;
> @@ -681,7 +760,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
> goto unlock;
> }
>
> - n = audio_config_get_n(mode, rate);
> + n = audio_config_get_n(crtc, mode, rate);
> if (n == 0) {
> DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n",
> port_name(port));
> @@ -693,8 +772,17 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
>
> /* 3. set the N/CTS/M */
> tmp = I915_READ(HSW_AUD_CFG(pipe));
> - tmp = audio_config_setup_n_reg(n, tmp);
> + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> + /* setup m value for DP */
> + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> + m = audio_config_get_m(crtc, rate);
> + if (m == 0)
> + goto unlock;
> + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> + }
>
> unlock:
> mutex_unlock(&dev_priv->av_mutex);
> --
> 1.9.1
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 1:35 [PATCH] drm/i915: set proper N/M in modeset libin.yang
2016-08-02 5:30 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev2) Patchwork
2016-08-02 10:47 ` [PATCH] drm/i915: set proper N/M in modeset Ville Syrjälä
@ 2016-08-02 10:52 ` Jani Nikula
2016-08-02 14:00 ` Yang, Libin
2016-08-04 6:29 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev3) Patchwork
3 siblings, 1 reply; 23+ messages in thread
From: Jani Nikula @ 2016-08-02 10:52 UTC (permalink / raw)
To: intel-gfx, ville.syrjala, daniel.vetter, tiwai; +Cc: Libin Yang
On Tue, 02 Aug 2016, libin.yang@linux.intel.com wrote:
> From: Libin Yang <libin.yang@linux.intel.com>
>
> When modeset occurs and the LS_CLK is set to some
> special values in DP mode, the N/M need to be set
> manually if audio is playing.
>
> The relationship of Maud and Naud is expressed in
> the following equation:
> Maud/Naud = 512 * fs / f_LS_Clk
>
> Please refer VESA DisplayPort Standard spec for details.
>
> Also, the patch applies
> commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset")
> to APL platform.
Whenever a commit message says "also", it makes me think the patch
should probably be split to several patches. And that is certainly true
here.
--
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 10:47 ` [PATCH] drm/i915: set proper N/M in modeset Ville Syrjälä
@ 2016-08-02 13:58 ` Yang, Libin
2016-08-02 16:59 ` Ville Syrjälä
2016-08-04 2:48 ` Yang, Libin
0 siblings, 2 replies; 23+ messages in thread
From: Yang, Libin @ 2016-08-02 13:58 UTC (permalink / raw)
To: Ville Syrjälä, libin.yang@linux.intel.com
Cc: tiwai@suse.de, Vetter, Daniel, intel-gfx@lists.freedesktop.org
Hi Ville
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Tuesday, August 2, 2016 6:47 PM
> To: libin.yang@linux.intel.com
> Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com; Vetter, Daniel
> <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin <libin.yang@intel.com>
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com wrote:
> > From: Libin Yang <libin.yang@linux.intel.com>
> >
> > When modeset occurs and the LS_CLK is set to some special values in DP
> > mode, the N/M need to be set manually if audio is playing.
> >
> > The relationship of Maud and Naud is expressed in the following
> > equation:
> > Maud/Naud = 512 * fs / f_LS_Clk
> >
> > Please refer VESA DisplayPort Standard spec for details.
> >
> > Also, the patch applies
> > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > platform.
> >
> > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > ---
> > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > drivers/gpu/drm/i915/intel_audio.c | 122
> > +++++++++++++++++++++++++++++++------
> > 2 files changed, 111 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -7351,6 +7351,12 @@ enum {
> > #define _HSW_AUD_CONFIG_B 0x65100
> > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> >
> > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > +
> > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > b/drivers/gpu/drm/i915/intel_audio.c
> > index 6700a7b..de55ecf 100644
> > --- a/drivers/gpu/drm/i915/intel_audio.c
> > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > @@ -98,6 +98,22 @@ static const struct {
> > { 192000, TMDS_297M, 20480, 247500 }, };
> >
> > +#define LC_540M 540000
> > +#define LC_162M 162000
>
> Do we have some explanation why 2.7 doesn't need M/N programming, but
> 1.62 and 5.4 do?
I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the test.
5.4 is for 4K and 1.62 is for 1080p.
>
> And I see you're only doing this on HSW+. Earlier platforms don't need this?
We are not supporting earlier platforms and I'm not sure whether the
old platforms supports 4K DP or not.
>
> > +static const struct {
> > + int sample_rate;
> > + int clock;
> > + int n;
> > + int m;
>
> Can save a bit of space by using u16 for m and n.
OK, I will do it in next version.
>
> > +} aud_nm[] = {
> > + {48000, LC_540M, 5625, 256},`
> > + {44100, LC_540M, 9375, 392},
> > + {32000, LC_540M, 16875, 512},
> > + {48000, LC_162M, 3375, 512},
> > + {44100, LC_162M, 5625, 784},
> > + {32000, LC_162M, 10125, 1024
> > +};
>
> The numbers look good, but what about other sample rates? For HDMI we go
> up to 192kHz, why not for DP?
Our test only includes 32K, 44.1K and 48K :)
I will add the support if you think we should.
>
> > +
> > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> > return hdmi_audio_clock[i].config;
> > }
> >
> > -static int audio_config_get_n(const struct drm_display_mode *mode,
> > int rate)
> > +static int audio_config_get_n(struct intel_crtc *crtc,
> > + const struct drm_display_mode *adjusted_mode,
> > + int rate)
> > +{
> > + int i;
> > +
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > + if ((rate == aud_ncts[i].sample_rate) &&
> > + (adjusted_mode->clock == aud_ncts[i].clock)) {
> > + return aud_ncts[i].n;
> > + }
> > + }
> > + }
> > +
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > + if ((rate == aud_nm[i].sample_rate) &&
> > + (crtc->config->port_clock == aud_nm[i].clock))
> {
> > + return aud_nm[i].n;
> > + }
> > + }
> > + }
> > + return 0;
> > +}
> > +
> > +static int audio_config_get_m(struct intel_crtc *crtc, int rate)
> > {
> > int i;
> >
> > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > - if ((rate == aud_ncts[i].sample_rate) &&
> > - (mode->clock == aud_ncts[i].clock)) {
> > - return aud_ncts[i].n;
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > + if ((rate == aud_nm[i].sample_rate) &&
> > + (crtc->config->port_clock == aud_nm[i].clock))
> {
> > + return aud_nm[i].m;
> > + }
> > }
> > }
> > +
> > return 0;
> > }
> >
> > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > + int n, uint32_t val)
> > {
> > int n_low, n_up;
> > uint32_t tmp = val;
> > @@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int n,
> uint32_t val)
> > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > AUD_CONFIG_N_PROG_ENABLE);
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > + return tmp;
> > +}
> > +
> > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > + int m, uint32_t val)
> > +{
> > + uint32_t tmp = val;
> > +
> > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > + return 0;
> > +
> > + tmp |= m;
> > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > +
> > return tmp;
> > }
> >
> > /* check whether N/CTS/M need be set manually */ static bool
> > audio_rate_need_prog(struct intel_crtc *crtc,
> > - const struct drm_display_mode *mode)
> > + const struct drm_display_mode
> *adjusted_mode)
> > {
> > - if (((mode->clock == TMDS_297M) ||
> > - (mode->clock == TMDS_296M)) &&
> > + if (((adjusted_mode->clock == TMDS_297M) ||
> > + (adjusted_mode->clock == TMDS_296M)) &&
> > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > return true;
> > + else if (((crtc->config->port_clock == LC_540M) ||
> > + (crtc->config->port_clock == LC_162M)) &&
> > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > + return true;
> > else
> > return false;
> > }
> > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> drm_connector *connector,
> > struct intel_digital_port *intel_dig_port =
> > enc_to_dig_port(&encoder->base);
> > enum port port = intel_dig_port->port;
> > - uint32_t tmp;
> > + uint32_t tmp, m;
> > int len, i;
> > int n, rate;
> >
> > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> drm_connector *connector,
> > DRM_ERROR("invalid port: %d\n", port);
> > rate = 0;
> > }
> > - n = audio_config_get_n(adjusted_mode, rate);
> > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > if (n != 0)
> > - tmp = audio_config_setup_n_reg(n, tmp);
> > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > else
> > DRM_DEBUG_KMS("no suitable N value is found\n");
> > }
> >
> > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> >
> > + /* setup m value for DP */
> > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > + m = audio_config_get_m(intel_crtc, rate);
> > + if (m != 0) {
> > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > + }
> > + }
> > +
> > mutex_unlock(&dev_priv->av_mutex);
> > }
> >
> > @@ -637,7 +714,7 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > struct drm_display_mode *mode;
> > struct i915_audio_component *acomp = dev_priv->audio_component;
> > enum pipe pipe = INVALID_PIPE;
> > - u32 tmp;
> > + u32 tmp, m;
> > int n;
> > int err = 0;
> >
> > @@ -645,7 +722,8 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > if (!IS_SKYLAKE(dev_priv) &&
> > !IS_KABYLAKE(dev_priv) &&
> > !IS_BROADWELL(dev_priv) &&
> > - !IS_HASWELL(dev_priv))
> > + !IS_HASWELL(dev_priv) &&
> > + !IS_BROXTON(dev_priv))
> > return 0;
>
> HAS_DDI perhaps?
Do you mean we should add "&& HAS_DDI"?
Could you please give me more details?
Regards,
Libin
>
> >
> > mutex_lock(&dev_priv->av_mutex);
> > @@ -653,7 +731,8 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > intel_encoder = dev_priv->dig_port_map[port];
> > /* intel_encoder might be NULL for DP MST */
> > if (!intel_encoder || !intel_encoder->base.crtc ||
> > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > err = -ENODEV;
> > goto unlock;
> > @@ -681,7 +760,7 @@ static int
> i915_audio_component_sync_audio_rate(struct device *dev,
> > goto unlock;
> > }
> >
> > - n = audio_config_get_n(mode, rate);
> > + n = audio_config_get_n(crtc, mode, rate);
> > if (n == 0) {
> > DRM_DEBUG_KMS("Using automatic mode for N value on
> port %c\n",
> > port_name(port));
> > @@ -693,8 +772,17 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> >
> > /* 3. set the N/CTS/M */
> > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > - tmp = audio_config_setup_n_reg(n, tmp);
> > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > + /* setup m value for DP */
> > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > + m = audio_config_get_m(crtc, rate);
> > + if (m == 0)
> > + goto unlock;
> > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > + }
> >
> > unlock:
> > mutex_unlock(&dev_priv->av_mutex);
> > --
> > 1.9.1
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 10:52 ` Jani Nikula
@ 2016-08-02 14:00 ` Yang, Libin
0 siblings, 0 replies; 23+ messages in thread
From: Yang, Libin @ 2016-08-02 14:00 UTC (permalink / raw)
To: Jani Nikula, intel-gfx@lists.freedesktop.org,
ville.syrjala@linux.intel.com, Vetter, Daniel, tiwai@suse.de
Cc: Libin Yang
Hi Jani,
> -----Original Message-----
> From: Jani Nikula [mailto:jani.nikula@linux.intel.com]
> Sent: Tuesday, August 2, 2016 6:53 PM
> To: libin.yang@linux.intel.com; intel-gfx@lists.freedesktop.org;
> ville.syrjala@linux.intel.com; Vetter, Daniel <daniel.vetter@intel.com>;
> tiwai@suse.de
> Cc: Yang, Libin <libin.yang@intel.com>; Libin Yang
> <libin.yang@linux.intel.com>
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Tue, 02 Aug 2016, libin.yang@linux.intel.com wrote:
> > From: Libin Yang <libin.yang@linux.intel.com>
> >
> > When modeset occurs and the LS_CLK is set to some special values in DP
> > mode, the N/M need to be set manually if audio is playing.
> >
> > The relationship of Maud and Naud is expressed in the following
> > equation:
> > Maud/Naud = 512 * fs / f_LS_Clk
> >
> > Please refer VESA DisplayPort Standard spec for details.
> >
> > Also, the patch applies
> > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > platform.
>
> Whenever a commit message says "also", it makes me think the patch should
> probably be split to several patches. And that is certainly true here.
I will split the patch in next version.
Regards,
Libin
>
>
> --
> Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 13:58 ` Yang, Libin
@ 2016-08-02 16:59 ` Ville Syrjälä
2016-08-04 5:46 ` Yang, Libin
2016-08-04 2:48 ` Yang, Libin
1 sibling, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-08-02 16:59 UTC (permalink / raw)
To: Yang, Libin
Cc: tiwai@suse.de, Vetter, Daniel, libin.yang@linux.intel.com,
intel-gfx@lists.freedesktop.org
On Tue, Aug 02, 2016 at 01:58:51PM +0000, Yang, Libin wrote:
> Hi Ville
>
> > -----Original Message-----
> > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > Sent: Tuesday, August 2, 2016 6:47 PM
> > To: libin.yang@linux.intel.com
> > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com; Vetter, Daniel
> > <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin <libin.yang@intel.com>
> > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> >
> > On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com wrote:
> > > From: Libin Yang <libin.yang@linux.intel.com>
> > >
> > > When modeset occurs and the LS_CLK is set to some special values in DP
> > > mode, the N/M need to be set manually if audio is playing.
> > >
> > > The relationship of Maud and Naud is expressed in the following
> > > equation:
> > > Maud/Naud = 512 * fs / f_LS_Clk
> > >
> > > Please refer VESA DisplayPort Standard spec for details.
> > >
> > > Also, the patch applies
> > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > > platform.
> > >
> > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > ---
> > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > +++++++++++++++++++++++++++++++------
> > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -7351,6 +7351,12 @@ enum {
> > > #define _HSW_AUD_CONFIG_B 0x65100
> > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > >
> > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > +
> > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > b/drivers/gpu/drm/i915/intel_audio.c
> > > index 6700a7b..de55ecf 100644
> > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > @@ -98,6 +98,22 @@ static const struct {
> > > { 192000, TMDS_297M, 20480, 247500 }, };
> > >
> > > +#define LC_540M 540000
> > > +#define LC_162M 162000
> >
> > Do we have some explanation why 2.7 doesn't need M/N programming, but
> > 1.62 and 5.4 do?
>
> I didn't use 2.7 because I can't find a mode using 2.7.
Hmm. Maybe we should add some knobs to force a specific bpc/link rate/number
of lanes to help with this kind of testing. Currently you just get what
you get, which isn't so nice when you want to test all variations.
...
OK, so I just went ahead and did that. Here's a branch:
git://github.com/vsyrjala/linux.git modparam_clock_bpp_limit
For your DP testing just setting
i915.max_port_clock=162000 or i915.max_port_clock=270000 and then
forcing a modeset should do the trick.
> So I can't do the test.
> 5.4 is for 4K and 1.62 is for 1080p.
>
> >
> > And I see you're only doing this on HSW+. Earlier platforms don't need this?
>
> We are not supporting earlier platforms and I'm not sure whether the
> old platforms supports 4K DP or not.
SNB-IVB dotclock can go up to 360Mhz, ILK up to 405 Mhz. At least in
theory. The DP link is limited to 4 x 2.7 for all. From the those the
dotclock limit is the one you should hit first since DP can always fall
back to 6bpc and that should be correspond to a dotclock of 480 MHz.
Anyways, 360MHz is plenty for 4k@30.
The question really is why we need to do this in the first place.
There's nothing in the spec telling is it's really required. All I can
find in the DP spec is "Maud value is set to 2^15 (=32,768) when the
audio clock is asynchronous to the LS_Clk.", and then
Thinking about it a bit more, on HSW+ we do drive DP ports with the
LCPLL, which is also reponsible for cdclk, and there are some vague
hints that audio may be clocked via cdclk. So if the DDI clock and the
audio clock are coming from the same reference, I suppose they are
considered synchronous, which may explain why this is needed. It's all
very poorly documented though, so I can't be sure.
As for the older platforms, the clocks are even less well documented.
The audio stuff is in the PCH, which is also where the DPLLs live, but
I have no idea where any audio clocks come from.
>
> >
> > > +static const struct {
> > > + int sample_rate;
> > > + int clock;
> > > + int n;
> > > + int m;
> >
> > Can save a bit of space by using u16 for m and n.
>
> OK, I will do it in next version.
>
> >
> > > +} aud_nm[] = {
> > > + {48000, LC_540M, 5625, 256},`
> > > + {44100, LC_540M, 9375, 392},
> > > + {32000, LC_540M, 16875, 512},
> > > + {48000, LC_162M, 3375, 512},
> > > + {44100, LC_162M, 5625, 784},
> > > + {32000, LC_162M, 10125, 1024
> > > +};
> >
> > The numbers look good, but what about other sample rates? For HDMI we go
> > up to 192kHz, why not for DP?
>
> Our test only includes 32K, 44.1K and 48K :)
> I will add the support if you think we should.
What sample rates can the user select? That should be the only
relevant question here.
>
> >
> > > +
> > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> > > return hdmi_audio_clock[i].config;
> > > }
> > >
> > > -static int audio_config_get_n(const struct drm_display_mode *mode,
> > > int rate)
> > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > + const struct drm_display_mode *adjusted_mode,
> > > + int rate)
> > > +{
> > > + int i;
> > > +
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > + (adjusted_mode->clock == aud_ncts[i].clock)) {
> > > + return aud_ncts[i].n;
> > > + }
> > > + }
> > > + }
> > > +
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > + if ((rate == aud_nm[i].sample_rate) &&
> > > + (crtc->config->port_clock == aud_nm[i].clock))
> > {
> > > + return aud_nm[i].n;
> > > + }
> > > + }
> > > + }
> > > + return 0;
> > > +}
> > > +
> > > +static int audio_config_get_m(struct intel_crtc *crtc, int rate)
> > > {
> > > int i;
> > >
> > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > - (mode->clock == aud_ncts[i].clock)) {
> > > - return aud_ncts[i].n;
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > + if ((rate == aud_nm[i].sample_rate) &&
> > > + (crtc->config->port_clock == aud_nm[i].clock))
> > {
> > > + return aud_nm[i].m;
> > > + }
> > > }
> > > }
> > > +
> > > return 0;
> > > }
> > >
> > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > + int n, uint32_t val)
> > > {
> > > int n_low, n_up;
> > > uint32_t tmp = val;
> > > @@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int n,
> > uint32_t val)
> > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > AUD_CONFIG_N_PROG_ENABLE);
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > + return tmp;
> > > +}
> > > +
> > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > + int m, uint32_t val)
> > > +{
> > > + uint32_t tmp = val;
> > > +
> > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + return 0;
> > > +
> > > + tmp |= m;
> > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > +
> > > return tmp;
> > > }
> > >
> > > /* check whether N/CTS/M need be set manually */ static bool
> > > audio_rate_need_prog(struct intel_crtc *crtc,
> > > - const struct drm_display_mode *mode)
> > > + const struct drm_display_mode
> > *adjusted_mode)
> > > {
> > > - if (((mode->clock == TMDS_297M) ||
> > > - (mode->clock == TMDS_296M)) &&
> > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > return true;
> > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > + (crtc->config->port_clock == LC_162M)) &&
> > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + return true;
> > > else
> > > return false;
> > > }
> > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > drm_connector *connector,
> > > struct intel_digital_port *intel_dig_port =
> > > enc_to_dig_port(&encoder->base);
> > > enum port port = intel_dig_port->port;
> > > - uint32_t tmp;
> > > + uint32_t tmp, m;
> > > int len, i;
> > > int n, rate;
> > >
> > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > drm_connector *connector,
> > > DRM_ERROR("invalid port: %d\n", port);
> > > rate = 0;
> > > }
> > > - n = audio_config_get_n(adjusted_mode, rate);
> > > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > > if (n != 0)
> > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > > else
> > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > }
> > >
> > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > >
> > > + /* setup m value for DP */
> > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > > + m = audio_config_get_m(intel_crtc, rate);
> > > + if (m != 0) {
> > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > + }
> > > + }
> > > +
> > > mutex_unlock(&dev_priv->av_mutex);
> > > }
> > >
> > > @@ -637,7 +714,7 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > struct drm_display_mode *mode;
> > > struct i915_audio_component *acomp = dev_priv->audio_component;
> > > enum pipe pipe = INVALID_PIPE;
> > > - u32 tmp;
> > > + u32 tmp, m;
> > > int n;
> > > int err = 0;
> > >
> > > @@ -645,7 +722,8 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > if (!IS_SKYLAKE(dev_priv) &&
> > > !IS_KABYLAKE(dev_priv) &&
> > > !IS_BROADWELL(dev_priv) &&
> > > - !IS_HASWELL(dev_priv))
> > > + !IS_HASWELL(dev_priv) &&
> > > + !IS_BROXTON(dev_priv))
> > > return 0;
> >
> > HAS_DDI perhaps?
>
> Do you mean we should add "&& HAS_DDI"?
> Could you please give me more details?
HAS_DDI alone should be enough.
>
> Regards,
> Libin
>
> >
> > >
> > > mutex_lock(&dev_priv->av_mutex);
> > > @@ -653,7 +731,8 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > intel_encoder = dev_priv->dig_port_map[port];
> > > /* intel_encoder might be NULL for DP MST */
> > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > > err = -ENODEV;
> > > goto unlock;
> > > @@ -681,7 +760,7 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > goto unlock;
> > > }
> > >
> > > - n = audio_config_get_n(mode, rate);
> > > + n = audio_config_get_n(crtc, mode, rate);
> > > if (n == 0) {
> > > DRM_DEBUG_KMS("Using automatic mode for N value on
> > port %c\n",
> > > port_name(port));
> > > @@ -693,8 +772,17 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > >
> > > /* 3. set the N/CTS/M */
> > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > + /* setup m value for DP */
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + m = audio_config_get_m(crtc, rate);
> > > + if (m == 0)
> > > + goto unlock;
> > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > + }
> > >
> > > unlock:
> > > mutex_unlock(&dev_priv->av_mutex);
> > > --
> > > 1.9.1
> >
> > --
> > Ville Syrjälä
> > Intel OTC
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 13:58 ` Yang, Libin
2016-08-02 16:59 ` Ville Syrjälä
@ 2016-08-04 2:48 ` Yang, Libin
2016-08-04 5:39 ` Ville Syrjälä
1 sibling, 1 reply; 23+ messages in thread
From: Yang, Libin @ 2016-08-04 2:48 UTC (permalink / raw)
To: 'Ville Syrjälä',
'libin.yang@linux.intel.com'
Cc: 'tiwai@suse.de', Vetter, Daniel,
'intel-gfx@lists.freedesktop.org'
Hi Ville,
> -----Original Message-----
> From: Yang, Libin
> Sent: Tuesday, August 2, 2016 9:59 PM
> To: Ville Syrjälä <ville.syrjala@linux.intel.com>; libin.yang@linux.intel.com
> Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com; Vetter, Daniel
> <daniel.vetter@intel.com>; tiwai@suse.de
> Subject: RE: [PATCH] drm/i915: set proper N/M in modeset
>
> Hi Ville
>
> > -----Original Message-----
> > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > Sent: Tuesday, August 2, 2016 6:47 PM
> > To: libin.yang@linux.intel.com
> > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > <libin.yang@intel.com>
> > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> >
> > On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com
> wrote:
> > > From: Libin Yang <libin.yang@linux.intel.com>
> > >
> > > When modeset occurs and the LS_CLK is set to some special values in
> > > DP mode, the N/M need to be set manually if audio is playing.
> > >
> > > The relationship of Maud and Naud is expressed in the following
> > > equation:
> > > Maud/Naud = 512 * fs / f_LS_Clk
> > >
> > > Please refer VESA DisplayPort Standard spec for details.
> > >
> > > Also, the patch applies
> > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > > platform.
> > >
> > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > ---
> > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > +++++++++++++++++++++++++++++++------
> > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -7351,6 +7351,12 @@ enum {
> > > #define _HSW_AUD_CONFIG_B 0x65100
> > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > >
> > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > +
> > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > b/drivers/gpu/drm/i915/intel_audio.c
> > > index 6700a7b..de55ecf 100644
> > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > @@ -98,6 +98,22 @@ static const struct {
> > > { 192000, TMDS_297M, 20480, 247500 }, };
> > >
> > > +#define LC_540M 540000
> > > +#define LC_162M 162000
> >
> > Do we have some explanation why 2.7 doesn't need M/N programming, but
> > 1.62 and 5.4 do?
>
> I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the test.
> 5.4 is for 4K and 1.62 is for 1080p.
>
> >
> > And I see you're only doing this on HSW+. Earlier platforms don't need this?
>
> We are not supporting earlier platforms and I'm not sure whether the old
> platforms supports 4K DP or not.
>
> >
> > > +static const struct {
> > > + int sample_rate;
> > > + int clock;
> > > + int n;
> > > + int m;
> >
> > Can save a bit of space by using u16 for m and n.
>
> OK, I will do it in next version.
>
> >
> > > +} aud_nm[] = {
> > > + {48000, LC_540M, 5625, 256},`
> > > + {44100, LC_540M, 9375, 392},
> > > + {32000, LC_540M, 16875, 512},
> > > + {48000, LC_162M, 3375, 512},
> > > + {44100, LC_162M, 5625, 784},
> > > + {32000, LC_162M, 10125, 1024
> > > +};
> >
> > The numbers look good, but what about other sample rates? For HDMI we
> > go up to 192kHz, why not for DP?
>
> Our test only includes 32K, 44.1K and 48K :) I will add the support if you think
> we should.
I will not add 192KHz, 96KHz and etc rate support as based on my test
these rate will be not used in DP. It will be converted to 48KHz.
>
> >
> > > +
> > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> > > return hdmi_audio_clock[i].config; }
> > >
> > > -static int audio_config_get_n(const struct drm_display_mode *mode,
> > > int rate)
> > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > + const struct drm_display_mode *adjusted_mode,
> > > + int rate)
> > > +{
> > > + int i;
> > > +
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > + (adjusted_mode->clock == aud_ncts[i].clock)) {
> > > + return aud_ncts[i].n;
> > > + }
> > > + }
> > > + }
> > > +
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > + if ((rate == aud_nm[i].sample_rate) &&
> > > + (crtc->config->port_clock == aud_nm[i].clock))
> > {
> > > + return aud_nm[i].n;
> > > + }
> > > + }
> > > + }
> > > + return 0;
> > > +}
> > > +
> > > +static int audio_config_get_m(struct intel_crtc *crtc, int rate)
> > > {
> > > int i;
> > >
> > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > - (mode->clock == aud_ncts[i].clock)) {
> > > - return aud_ncts[i].n;
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > + if ((rate == aud_nm[i].sample_rate) &&
> > > + (crtc->config->port_clock == aud_nm[i].clock))
> > {
> > > + return aud_nm[i].m;
> > > + }
> > > }
> > > }
> > > +
> > > return 0;
> > > }
> > >
> > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > + int n, uint32_t val)
> > > {
> > > int n_low, n_up;
> > > uint32_t tmp = val;
> > > @@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int
> > > n,
> > uint32_t val)
> > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > AUD_CONFIG_N_PROG_ENABLE);
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > + return tmp;
> > > +}
> > > +
> > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > + int m, uint32_t val)
> > > +{
> > > + uint32_t tmp = val;
> > > +
> > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + return 0;
> > > +
> > > + tmp |= m;
> > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > +
> > > return tmp;
> > > }
> > >
> > > /* check whether N/CTS/M need be set manually */ static bool
> > > audio_rate_need_prog(struct intel_crtc *crtc,
> > > - const struct drm_display_mode *mode)
> > > + const struct drm_display_mode
> > *adjusted_mode)
> > > {
> > > - if (((mode->clock == TMDS_297M) ||
> > > - (mode->clock == TMDS_296M)) &&
> > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > return true;
> > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > + (crtc->config->port_clock == LC_162M)) &&
> > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > + return true;
> > > else
> > > return false;
> > > }
> > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > drm_connector *connector,
> > > struct intel_digital_port *intel_dig_port =
> > > enc_to_dig_port(&encoder->base);
> > > enum port port = intel_dig_port->port;
> > > - uint32_t tmp;
> > > + uint32_t tmp, m;
> > > int len, i;
> > > int n, rate;
> > >
> > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > drm_connector *connector,
> > > DRM_ERROR("invalid port: %d\n", port);
> > > rate = 0;
> > > }
> > > - n = audio_config_get_n(adjusted_mode, rate);
> > > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > > if (n != 0)
> > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > > else
> > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > }
> > >
> > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > >
> > > + /* setup m value for DP */
> > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > > + m = audio_config_get_m(intel_crtc, rate);
> > > + if (m != 0) {
> > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > + }
> > > + }
> > > +
> > > mutex_unlock(&dev_priv->av_mutex);
> > > }
> > >
> > > @@ -637,7 +714,7 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > struct drm_display_mode *mode;
> > > struct i915_audio_component *acomp = dev_priv->audio_component;
> > > enum pipe pipe = INVALID_PIPE;
> > > - u32 tmp;
> > > + u32 tmp, m;
> > > int n;
> > > int err = 0;
> > >
> > > @@ -645,7 +722,8 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > if (!IS_SKYLAKE(dev_priv) &&
> > > !IS_KABYLAKE(dev_priv) &&
> > > !IS_BROADWELL(dev_priv) &&
> > > - !IS_HASWELL(dev_priv))
> > > + !IS_HASWELL(dev_priv) &&
> > > + !IS_BROXTON(dev_priv))
> > > return 0;
> >
> > HAS_DDI perhaps?
>
> Do you mean we should add "&& HAS_DDI"?
> Could you please give me more details?
>
> Regards,
> Libin
>
> >
> > >
> > > mutex_lock(&dev_priv->av_mutex);
> > > @@ -653,7 +731,8 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > intel_encoder = dev_priv->dig_port_map[port];
> > > /* intel_encoder might be NULL for DP MST */
> > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > > err = -ENODEV;
> > > goto unlock;
> > > @@ -681,7 +760,7 @@ static int
> > i915_audio_component_sync_audio_rate(struct device *dev,
> > > goto unlock;
> > > }
> > >
> > > - n = audio_config_get_n(mode, rate);
> > > + n = audio_config_get_n(crtc, mode, rate);
> > > if (n == 0) {
> > > DRM_DEBUG_KMS("Using automatic mode for N value on
> > port %c\n",
> > > port_name(port));
> > > @@ -693,8 +772,17 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > >
> > > /* 3. set the N/CTS/M */
> > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > + /* setup m value for DP */
> > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > + m = audio_config_get_m(crtc, rate);
> > > + if (m == 0)
> > > + goto unlock;
> > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > + }
> > >
> > > unlock:
> > > mutex_unlock(&dev_priv->av_mutex);
> > > --
> > > 1.9.1
> >
> > --
> > Ville Syrjälä
> > Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 2:48 ` Yang, Libin
@ 2016-08-04 5:39 ` Ville Syrjälä
2016-08-04 6:04 ` Yang, Libin
0 siblings, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-08-04 5:39 UTC (permalink / raw)
To: Yang, Libin
Cc: 'tiwai@suse.de', Vetter, Daniel,
'libin.yang@linux.intel.com',
'intel-gfx@lists.freedesktop.org'
On Thu, Aug 04, 2016 at 02:48:54AM +0000, Yang, Libin wrote:
> Hi Ville,
>
> > -----Original Message-----
> > From: Yang, Libin
> > Sent: Tuesday, August 2, 2016 9:59 PM
> > To: Ville Syrjälä <ville.syrjala@linux.intel.com>; libin.yang@linux.intel.com
> > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com; Vetter, Daniel
> > <daniel.vetter@intel.com>; tiwai@suse.de
> > Subject: RE: [PATCH] drm/i915: set proper N/M in modeset
> >
> > Hi Ville
> >
> > > -----Original Message-----
> > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > To: libin.yang@linux.intel.com
> > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > <libin.yang@intel.com>
> > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > >
> > > On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com
> > wrote:
> > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > >
> > > > When modeset occurs and the LS_CLK is set to some special values in
> > > > DP mode, the N/M need to be set manually if audio is playing.
> > > >
> > > > The relationship of Maud and Naud is expressed in the following
> > > > equation:
> > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > >
> > > > Please refer VESA DisplayPort Standard spec for details.
> > > >
> > > > Also, the patch applies
> > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to APL
> > > > platform.
> > > >
> > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > ---
> > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > +++++++++++++++++++++++++++++++------
> > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > @@ -7351,6 +7351,12 @@ enum {
> > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > >
> > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > +#define HSW_AUD_M_CTS_ENABLE(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > +
> > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > index 6700a7b..de55ecf 100644
> > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > @@ -98,6 +98,22 @@ static const struct {
> > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > >
> > > > +#define LC_540M 540000
> > > > +#define LC_162M 162000
> > >
> > > Do we have some explanation why 2.7 doesn't need M/N programming, but
> > > 1.62 and 5.4 do?
> >
> > I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the test.
> > 5.4 is for 4K and 1.62 is for 1080p.
> >
> > >
> > > And I see you're only doing this on HSW+. Earlier platforms don't need this?
> >
> > We are not supporting earlier platforms and I'm not sure whether the old
> > platforms supports 4K DP or not.
> >
> > >
> > > > +static const struct {
> > > > + int sample_rate;
> > > > + int clock;
> > > > + int n;
> > > > + int m;
> > >
> > > Can save a bit of space by using u16 for m and n.
> >
> > OK, I will do it in next version.
> >
> > >
> > > > +} aud_nm[] = {
> > > > + {48000, LC_540M, 5625, 256},`
> > > > + {44100, LC_540M, 9375, 392},
> > > > + {32000, LC_540M, 16875, 512},
> > > > + {48000, LC_162M, 3375, 512},
> > > > + {44100, LC_162M, 5625, 784},
> > > > + {32000, LC_162M, 10125, 1024
> > > > +};
> > >
> > > The numbers look good, but what about other sample rates? For HDMI we
> > > go up to 192kHz, why not for DP?
> >
> > Our test only includes 32K, 44.1K and 48K :) I will add the support if you think
> > we should.
>
> I will not add 192KHz, 96KHz and etc rate support as based on my test
> these rate will be not used in DP. It will be converted to 48KHz.
How about basing that decision on what's actually allowed by the driver?
I can do 96kHz DP audio on my HSW just fine here. So clearly if the
display supports it, there is nothing on the ALSA side that would prevent
it from being used.
>
> >
> > >
> > > > +
> > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static u32
> > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted
> > > > return hdmi_audio_clock[i].config; }
> > > >
> > > > -static int audio_config_get_n(const struct drm_display_mode *mode,
> > > > int rate)
> > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > + const struct drm_display_mode *adjusted_mode,
> > > > + int rate)
> > > > +{
> > > > + int i;
> > > > +
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > + (adjusted_mode->clock == aud_ncts[i].clock)) {
> > > > + return aud_ncts[i].n;
> > > > + }
> > > > + }
> > > > + }
> > > > +
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > + (crtc->config->port_clock == aud_nm[i].clock))
> > > {
> > > > + return aud_nm[i].n;
> > > > + }
> > > > + }
> > > > + }
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int audio_config_get_m(struct intel_crtc *crtc, int rate)
> > > > {
> > > > int i;
> > > >
> > > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > > - (mode->clock == aud_ncts[i].clock)) {
> > > > - return aud_ncts[i].n;
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > + (crtc->config->port_clock == aud_nm[i].clock))
> > > {
> > > > + return aud_nm[i].m;
> > > > + }
> > > > }
> > > > }
> > > > +
> > > > return 0;
> > > > }
> > > >
> > > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > > + int n, uint32_t val)
> > > > {
> > > > int n_low, n_up;
> > > > uint32_t tmp = val;
> > > > @@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int
> > > > n,
> > > uint32_t val)
> > > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > > AUD_CONFIG_N_PROG_ENABLE);
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > > + return tmp;
> > > > +}
> > > > +
> > > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > > + int m, uint32_t val)
> > > > +{
> > > > + uint32_t tmp = val;
> > > > +
> > > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > + return 0;
> > > > +
> > > > + tmp |= m;
> > > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > > +
> > > > return tmp;
> > > > }
> > > >
> > > > /* check whether N/CTS/M need be set manually */ static bool
> > > > audio_rate_need_prog(struct intel_crtc *crtc,
> > > > - const struct drm_display_mode *mode)
> > > > + const struct drm_display_mode
> > > *adjusted_mode)
> > > > {
> > > > - if (((mode->clock == TMDS_297M) ||
> > > > - (mode->clock == TMDS_296M)) &&
> > > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > > return true;
> > > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > > + (crtc->config->port_clock == LC_162M)) &&
> > > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > + return true;
> > > > else
> > > > return false;
> > > > }
> > > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > > drm_connector *connector,
> > > > struct intel_digital_port *intel_dig_port =
> > > > enc_to_dig_port(&encoder->base);
> > > > enum port port = intel_dig_port->port;
> > > > - uint32_t tmp;
> > > > + uint32_t tmp, m;
> > > > int len, i;
> > > > int n, rate;
> > > >
> > > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > > drm_connector *connector,
> > > > DRM_ERROR("invalid port: %d\n", port);
> > > > rate = 0;
> > > > }
> > > > - n = audio_config_get_n(adjusted_mode, rate);
> > > > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > > > if (n != 0)
> > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > > > else
> > > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > > }
> > > >
> > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > >
> > > > + /* setup m value for DP */
> > > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > > > + m = audio_config_get_m(intel_crtc, rate);
> > > > + if (m != 0) {
> > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > + }
> > > > + }
> > > > +
> > > > mutex_unlock(&dev_priv->av_mutex);
> > > > }
> > > >
> > > > @@ -637,7 +714,7 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > struct drm_display_mode *mode;
> > > > struct i915_audio_component *acomp = dev_priv->audio_component;
> > > > enum pipe pipe = INVALID_PIPE;
> > > > - u32 tmp;
> > > > + u32 tmp, m;
> > > > int n;
> > > > int err = 0;
> > > >
> > > > @@ -645,7 +722,8 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > if (!IS_SKYLAKE(dev_priv) &&
> > > > !IS_KABYLAKE(dev_priv) &&
> > > > !IS_BROADWELL(dev_priv) &&
> > > > - !IS_HASWELL(dev_priv))
> > > > + !IS_HASWELL(dev_priv) &&
> > > > + !IS_BROXTON(dev_priv))
> > > > return 0;
> > >
> > > HAS_DDI perhaps?
> >
> > Do you mean we should add "&& HAS_DDI"?
> > Could you please give me more details?
> >
> > Regards,
> > Libin
> >
> > >
> > > >
> > > > mutex_lock(&dev_priv->av_mutex);
> > > > @@ -653,7 +731,8 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > intel_encoder = dev_priv->dig_port_map[port];
> > > > /* intel_encoder might be NULL for DP MST */
> > > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > > > err = -ENODEV;
> > > > goto unlock;
> > > > @@ -681,7 +760,7 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > goto unlock;
> > > > }
> > > >
> > > > - n = audio_config_get_n(mode, rate);
> > > > + n = audio_config_get_n(crtc, mode, rate);
> > > > if (n == 0) {
> > > > DRM_DEBUG_KMS("Using automatic mode for N value on
> > > port %c\n",
> > > > port_name(port));
> > > > @@ -693,8 +772,17 @@ static int
> > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > >
> > > > /* 3. set the N/CTS/M */
> > > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > + /* setup m value for DP */
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > + m = audio_config_get_m(crtc, rate);
> > > > + if (m == 0)
> > > > + goto unlock;
> > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > + }
> > > >
> > > > unlock:
> > > > mutex_unlock(&dev_priv->av_mutex);
> > > > --
> > > > 1.9.1
> > >
> > > --
> > > Ville Syrjälä
> > > Intel OTC
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-02 16:59 ` Ville Syrjälä
@ 2016-08-04 5:46 ` Yang, Libin
2016-08-04 6:06 ` Ville Syrjälä
0 siblings, 1 reply; 23+ messages in thread
From: Yang, Libin @ 2016-08-04 5:46 UTC (permalink / raw)
To: Ville Syrjälä
Cc: tiwai@suse.de, Vetter, Daniel, libin.yang@linux.intel.com,
intel-gfx@lists.freedesktop.org
Hi Ville,
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Wednesday, August 3, 2016 12:59 AM
> To: Yang, Libin <libin.yang@intel.com>
> Cc: libin.yang@linux.intel.com; intel-gfx@lists.freedesktop.org;
> jani.nikula@linux.intel.com; Vetter, Daniel <daniel.vetter@intel.com>;
> tiwai@suse.de
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Tue, Aug 02, 2016 at 01:58:51PM +0000, Yang, Libin wrote:
> > Hi Ville
> >
> > > -----Original Message-----
> > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > To: libin.yang@linux.intel.com
> > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > <libin.yang@intel.com>
> > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > >
> > > On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com
> wrote:
> > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > >
> > > > When modeset occurs and the LS_CLK is set to some special values
> > > > in DP mode, the N/M need to be set manually if audio is playing.
> > > >
> > > > The relationship of Maud and Naud is expressed in the following
> > > > equation:
> > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > >
> > > > Please refer VESA DisplayPort Standard spec for details.
> > > >
> > > > Also, the patch applies
> > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to
> > > > APL platform.
> > > >
> > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > ---
> > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > +++++++++++++++++++++++++++++++------
> > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > @@ -7351,6 +7351,12 @@ enum {
> > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > >
> > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> _MMIO_PIPE(pipe,
> > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > +
> > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > index 6700a7b..de55ecf 100644
> > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > @@ -98,6 +98,22 @@ static const struct {
> > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > >
> > > > +#define LC_540M 540000
> > > > +#define LC_162M 162000
> > >
> > > Do we have some explanation why 2.7 doesn't need M/N programming,
> > > but
> > > 1.62 and 5.4 do?
> >
> > I didn't use 2.7 because I can't find a mode using 2.7.
>
> Hmm. Maybe we should add some knobs to force a specific bpc/link
> rate/number of lanes to help with this kind of testing. Currently you just get
> what you get, which isn't so nice when you want to test all variations.
> ...
> OK, so I just went ahead and did that. Here's a branch:
>
> git://github.com/vsyrjala/linux.git modparam_clock_bpp_limit
>
> For your DP testing just setting
> i915.max_port_clock=162000 or i915.max_port_clock=270000 and then
> forcing a modeset should do the trick.
Thanks for the new branch. It seems download is very slow, less than
10Kib/s. So I will submit the new patches firstly and then do the test.
Fortunately, I found there is recommended data for 340MHz in the spec.
I copied the data to the patch and suppose the data should be accurate.
>
> > So I can't do the test.
> > 5.4 is for 4K and 1.62 is for 1080p.
> >
> > >
> > > And I see you're only doing this on HSW+. Earlier platforms don't need this?
> >
> > We are not supporting earlier platforms and I'm not sure whether the
> > old platforms supports 4K DP or not.
>
> SNB-IVB dotclock can go up to 360Mhz, ILK up to 405 Mhz. At least in theory.
> The DP link is limited to 4 x 2.7 for all. From the those the dotclock limit is the
> one you should hit first since DP can always fall back to 6bpc and that should
> be correspond to a dotclock of 480 MHz.
> Anyways, 360MHz is plenty for 4k@30.
>
>
> The question really is why we need to do this in the first place.
> There's nothing in the spec telling is it's really required. All I can find in the DP
> spec is "Maud value is set to 2^15 (=32,768) when the audio clock is
> asynchronous to the LS_Clk.", and then
We made the patch because we found the HW can't calculate the value this
will cause there is several seconds silence at the beginning of audio playback.
With this patch, the silence is much shorter than before and is acceptable.
>
> Thinking about it a bit more, on HSW+ we do drive DP ports with the LCPLL,
> which is also reponsible for cdclk, and there are some vague hints that audio
> may be clocked via cdclk. So if the DDI clock and the audio clock are coming
> from the same reference, I suppose they are considered synchronous, which
> may explain why this is needed. It's all very poorly documented though, so I
> can't be sure.
Yes, audio is using cdclk. Changing the cdclk will impact audio function.
However N/M, N/CTS is used to recover the audio clock in monitor.
Monitor's PLL will use these values, together with the clock transferred
by the lanes, to recover the clock for audio.
>
> As for the older platforms, the clocks are even less well documented.
> The audio stuff is in the PCH, which is also where the DPLLs live, but I have no
> idea where any audio clocks come from.
>
> >
> > >
> > > > +static const struct {
> > > > + int sample_rate;
> > > > + int clock;
> > > > + int n;
> > > > + int m;
> > >
> > > Can save a bit of space by using u16 for m and n.
> >
> > OK, I will do it in next version.
> >
> > >
> > > > +} aud_nm[] = {
> > > > + {48000, LC_540M, 5625, 256},`
> > > > + {44100, LC_540M, 9375, 392},
> > > > + {32000, LC_540M, 16875, 512},
> > > > + {48000, LC_162M, 3375, 512},
> > > > + {44100, LC_162M, 5625, 784},
> > > > + {32000, LC_162M, 10125, 1024
> > > > +};
> > >
> > > The numbers look good, but what about other sample rates? For HDMI
> > > we go up to 192kHz, why not for DP?
> >
> > Our test only includes 32K, 44.1K and 48K :) I will add the support if
> > you think we should.
>
> What sample rates can the user select? That should be the only relevant
> question here.
I have tested, other sample rates is not valid on DP.
>
> >
> > >
> > > > +
> > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static
> > > > u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> *adjusted
> > > > return hdmi_audio_clock[i].config; }
> > > >
> > > > -static int audio_config_get_n(const struct drm_display_mode
> > > > *mode, int rate)
> > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > + const struct drm_display_mode *adjusted_mode,
> > > > + int rate)
> > > > +{
> > > > + int i;
> > > > +
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > + (adjusted_mode->clock == aud_ncts[i].clock)) {
> > > > + return aud_ncts[i].n;
> > > > + }
> > > > + }
> > > > + }
> > > > +
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > + (crtc->config->port_clock == aud_nm[i].clock))
> > > {
> > > > + return aud_nm[i].n;
> > > > + }
> > > > + }
> > > > + }
> > > > + return 0;
> > > > +}
> > > > +
> > > > +static int audio_config_get_m(struct intel_crtc *crtc, int rate)
> > > > {
> > > > int i;
> > > >
> > > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > > - (mode->clock == aud_ncts[i].clock)) {
> > > > - return aud_ncts[i].n;
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > + (crtc->config->port_clock == aud_nm[i].clock))
> > > {
> > > > + return aud_nm[i].m;
> > > > + }
> > > > }
> > > > }
> > > > +
> > > > return 0;
> > > > }
> > > >
> > > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > > + int n, uint32_t val)
> > > > {
> > > > int n_low, n_up;
> > > > uint32_t tmp = val;
> > > > @@ -145,17 +191,38 @@ static uint32_t audio_config_setup_n_reg(int
> > > > n,
> > > uint32_t val)
> > > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > > AUD_CONFIG_N_PROG_ENABLE);
> > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > > + return tmp;
> > > > +}
> > > > +
> > > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > > + int m, uint32_t val)
> > > > +{
> > > > + uint32_t tmp = val;
> > > > +
> > > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > + return 0;
> > > > +
> > > > + tmp |= m;
> > > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > > +
> > > > return tmp;
> > > > }
> > > >
> > > > /* check whether N/CTS/M need be set manually */ static bool
> > > > audio_rate_need_prog(struct intel_crtc *crtc,
> > > > - const struct drm_display_mode *mode)
> > > > + const struct drm_display_mode
> > > *adjusted_mode)
> > > > {
> > > > - if (((mode->clock == TMDS_297M) ||
> > > > - (mode->clock == TMDS_296M)) &&
> > > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > > return true;
> > > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > > + (crtc->config->port_clock == LC_162M)) &&
> > > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > + return true;
> > > > else
> > > > return false;
> > > > }
> > > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > > drm_connector *connector,
> > > > struct intel_digital_port *intel_dig_port =
> > > > enc_to_dig_port(&encoder->base);
> > > > enum port port = intel_dig_port->port;
> > > > - uint32_t tmp;
> > > > + uint32_t tmp, m;
> > > > int len, i;
> > > > int n, rate;
> > > >
> > > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > > drm_connector *connector,
> > > > DRM_ERROR("invalid port: %d\n", port);
> > > > rate = 0;
> > > > }
> > > > - n = audio_config_get_n(adjusted_mode, rate);
> > > > + n = audio_config_get_n(intel_crtc, adjusted_mode, rate);
> > > > if (n != 0)
> > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > + tmp = audio_config_setup_n_reg(intel_crtc, n, tmp);
> > > > else
> > > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > > }
> > > >
> > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > >
> > > > + /* setup m value for DP */
> > > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP)) {
> > > > + m = audio_config_get_m(intel_crtc, rate);
> > > > + if (m != 0) {
> > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > + tmp = audio_config_setup_m_reg(intel_crtc, m, tmp);
> > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > + }
> > > > + }
> > > > +
> > > > mutex_unlock(&dev_priv->av_mutex);
> > > > }
> > > >
> > > > @@ -637,7 +714,7 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > struct drm_display_mode *mode;
> > > > struct i915_audio_component *acomp = dev_priv->audio_component;
> > > > enum pipe pipe = INVALID_PIPE;
> > > > - u32 tmp;
> > > > + u32 tmp, m;
> > > > int n;
> > > > int err = 0;
> > > >
> > > > @@ -645,7 +722,8 @@ static int
> > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > if (!IS_SKYLAKE(dev_priv) &&
> > > > !IS_KABYLAKE(dev_priv) &&
> > > > !IS_BROADWELL(dev_priv) &&
> > > > - !IS_HASWELL(dev_priv))
> > > > + !IS_HASWELL(dev_priv) &&
> > > > + !IS_BROXTON(dev_priv))
> > > > return 0;
> > >
> > > HAS_DDI perhaps?
> >
> > Do you mean we should add "&& HAS_DDI"?
> > Could you please give me more details?
>
> HAS_DDI alone should be enough.
Get it. Thanks.
Regards,
Libin
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 5:39 ` Ville Syrjälä
@ 2016-08-04 6:04 ` Yang, Libin
2016-08-04 6:23 ` Ville Syrjälä
0 siblings, 1 reply; 23+ messages in thread
From: Yang, Libin @ 2016-08-04 6:04 UTC (permalink / raw)
To: Ville Syrjälä
Cc: 'tiwai@suse.de', Vetter, Daniel,
'libin.yang@linux.intel.com',
'intel-gfx@lists.freedesktop.org'
Hi Ville,
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Thursday, August 4, 2016 1:39 PM
> To: Yang, Libin <libin.yang@intel.com>
> Cc: 'libin.yang@linux.intel.com' <libin.yang@linux.intel.com>; 'intel-
> gfx@lists.freedesktop.org' <intel-gfx@lists.freedesktop.org>;
> 'jani.nikula@linux.intel.com' <jani.nikula@linux.intel.com>; Vetter, Daniel
> <daniel.vetter@intel.com>; 'tiwai@suse.de' <tiwai@suse.de>
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Thu, Aug 04, 2016 at 02:48:54AM +0000, Yang, Libin wrote:
> > Hi Ville,
> >
> > > -----Original Message-----
> > > From: Yang, Libin
> > > Sent: Tuesday, August 2, 2016 9:59 PM
> > > To: Ville Syrjälä <ville.syrjala@linux.intel.com>;
> > > libin.yang@linux.intel.com
> > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de
> > > Subject: RE: [PATCH] drm/i915: set proper N/M in modeset
> > >
> > > Hi Ville
> > >
> > > > -----Original Message-----
> > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > > To: libin.yang@linux.intel.com
> > > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang,
> > > > Libin <libin.yang@intel.com>
> > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > >
> > > > On Tue, Aug 02, 2016 at 09:35:10AM +0800,
> > > > libin.yang@linux.intel.com
> > > wrote:
> > > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > > >
> > > > > When modeset occurs and the LS_CLK is set to some special values
> > > > > in DP mode, the N/M need to be set manually if audio is playing.
> > > > >
> > > > > The relationship of Maud and Naud is expressed in the following
> > > > > equation:
> > > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > > >
> > > > > Please refer VESA DisplayPort Standard spec for details.
> > > > >
> > > > > Also, the patch applies
> > > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to
> > > > > APL platform.
> > > > >
> > > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > > ---
> > > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > > +++++++++++++++++++++++++++++++------
> > > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > @@ -7351,6 +7351,12 @@ enum {
> > > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > > >
> > > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> _MMIO_PIPE(pipe,
> > > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > > +
> > > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > > index 6700a7b..de55ecf 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > > @@ -98,6 +98,22 @@ static const struct {
> > > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > > >
> > > > > +#define LC_540M 540000
> > > > > +#define LC_162M 162000
> > > >
> > > > Do we have some explanation why 2.7 doesn't need M/N programming,
> > > > but
> > > > 1.62 and 5.4 do?
> > >
> > > I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the test.
> > > 5.4 is for 4K and 1.62 is for 1080p.
> > >
> > > >
> > > > And I see you're only doing this on HSW+. Earlier platforms don't need
> this?
> > >
> > > We are not supporting earlier platforms and I'm not sure whether the
> > > old platforms supports 4K DP or not.
> > >
> > > >
> > > > > +static const struct {
> > > > > + int sample_rate;
> > > > > + int clock;
> > > > > + int n;
> > > > > + int m;
> > > >
> > > > Can save a bit of space by using u16 for m and n.
> > >
> > > OK, I will do it in next version.
> > >
> > > >
> > > > > +} aud_nm[] = {
> > > > > + {48000, LC_540M, 5625, 256},`
> > > > > + {44100, LC_540M, 9375, 392},
> > > > > + {32000, LC_540M, 16875, 512},
> > > > > + {48000, LC_162M, 3375, 512},
> > > > > + {44100, LC_162M, 5625, 784},
> > > > > + {32000, LC_162M, 10125, 1024
> > > > > +};
> > > >
> > > > The numbers look good, but what about other sample rates? For HDMI
> > > > we go up to 192kHz, why not for DP?
> > >
> > > Our test only includes 32K, 44.1K and 48K :) I will add the support
> > > if you think we should.
> >
> > I will not add 192KHz, 96KHz and etc rate support as based on my test
> > these rate will be not used in DP. It will be converted to 48KHz.
>
> How about basing that decision on what's actually allowed by the driver?
> I can do 96kHz DP audio on my HSW just fine here. So clearly if the display
> supports it, there is nothing on the ALSA side that would prevent it from being
> used.
For 96KHz, audio will convert to 48KHz. You can try to print the sample rate
in i915_audio_component_sync_audio_rate(). So we can't test it for the real
96kHz.
In DP spec, table 2-50 only says 48kHz, 32kHz, 44.1kHz, 384kHz and 768kHz.
However, the latter two sample rates is not supported in audio driver and
can't be tested so far. 88kHz, 96kHz and 192kHz cannot be tested, either.
Regards,
Libin
>
> >
> > >
> > > >
> > > > > +
> > > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static
> > > > > u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> *adjusted
> > > > > return hdmi_audio_clock[i].config; }
> > > > >
> > > > > -static int audio_config_get_n(const struct drm_display_mode
> > > > > *mode, int rate)
> > > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > > + const struct drm_display_mode
> *adjusted_mode,
> > > > > + int rate)
> > > > > +{
> > > > > + int i;
> > > > > +
> > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > > + (adjusted_mode->clock ==
> aud_ncts[i].clock)) {
> > > > > + return aud_ncts[i].n;
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > +
> > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > + (crtc->config->port_clock ==
> aud_nm[i].clock))
> > > > {
> > > > > + return aud_nm[i].n;
> > > > > + }
> > > > > + }
> > > > > + }
> > > > > + return 0;
> > > > > +}
> > > > > +
> > > > > +static int audio_config_get_m(struct intel_crtc *crtc, int
> > > > > +rate)
> > > > > {
> > > > > int i;
> > > > >
> > > > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > > > - (mode->clock == aud_ncts[i].clock)) {
> > > > > - return aud_ncts[i].n;
> > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > + (crtc->config->port_clock ==
> aud_nm[i].clock))
> > > > {
> > > > > + return aud_nm[i].m;
> > > > > + }
> > > > > }
> > > > > }
> > > > > +
> > > > > return 0;
> > > > > }
> > > > >
> > > > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > > > + int n, uint32_t val)
> > > > > {
> > > > > int n_low, n_up;
> > > > > uint32_t tmp = val;
> > > > > @@ -145,17 +191,38 @@ static uint32_t
> > > > > audio_config_setup_n_reg(int n,
> > > > uint32_t val)
> > > > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > > > AUD_CONFIG_N_PROG_ENABLE);
> > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > > > + return tmp;
> > > > > +}
> > > > > +
> > > > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > > > + int m, uint32_t val)
> > > > > +{
> > > > > + uint32_t tmp = val;
> > > > > +
> > > > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > + return 0;
> > > > > +
> > > > > + tmp |= m;
> > > > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > > > +
> > > > > return tmp;
> > > > > }
> > > > >
> > > > > /* check whether N/CTS/M need be set manually */ static bool
> > > > > audio_rate_need_prog(struct intel_crtc *crtc,
> > > > > - const struct drm_display_mode *mode)
> > > > > + const struct drm_display_mode
> > > > *adjusted_mode)
> > > > > {
> > > > > - if (((mode->clock == TMDS_297M) ||
> > > > > - (mode->clock == TMDS_296M)) &&
> > > > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > > > return true;
> > > > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > > > + (crtc->config->port_clock == LC_162M)) &&
> > > > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > + return true;
> > > > > else
> > > > > return false;
> > > > > }
> > > > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > > > drm_connector *connector,
> > > > > struct intel_digital_port *intel_dig_port =
> > > > > enc_to_dig_port(&encoder->base);
> > > > > enum port port = intel_dig_port->port;
> > > > > - uint32_t tmp;
> > > > > + uint32_t tmp, m;
> > > > > int len, i;
> > > > > int n, rate;
> > > > >
> > > > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > > > drm_connector *connector,
> > > > > DRM_ERROR("invalid port: %d\n", port);
> > > > > rate = 0;
> > > > > }
> > > > > - n = audio_config_get_n(adjusted_mode, rate);
> > > > > + n = audio_config_get_n(intel_crtc, adjusted_mode,
> rate);
> > > > > if (n != 0)
> > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > + tmp = audio_config_setup_n_reg(intel_crtc, n,
> tmp);
> > > > > else
> > > > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > > > }
> > > > >
> > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > >
> > > > > + /* setup m value for DP */
> > > > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP))
> {
> > > > > + m = audio_config_get_m(intel_crtc, rate);
> > > > > + if (m != 0) {
> > > > > + tmp =
> I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > + tmp = audio_config_setup_m_reg(intel_crtc,
> m, tmp);
> > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe),
> tmp);
> > > > > + }
> > > > > + }
> > > > > +
> > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > }
> > > > >
> > > > > @@ -637,7 +714,7 @@ static int
> > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > struct drm_display_mode *mode;
> > > > > struct i915_audio_component *acomp = dev_priv->audio_component;
> > > > > enum pipe pipe = INVALID_PIPE;
> > > > > - u32 tmp;
> > > > > + u32 tmp, m;
> > > > > int n;
> > > > > int err = 0;
> > > > >
> > > > > @@ -645,7 +722,8 @@ static int
> > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > if (!IS_SKYLAKE(dev_priv) &&
> > > > > !IS_KABYLAKE(dev_priv) &&
> > > > > !IS_BROADWELL(dev_priv) &&
> > > > > - !IS_HASWELL(dev_priv))
> > > > > + !IS_HASWELL(dev_priv) &&
> > > > > + !IS_BROXTON(dev_priv))
> > > > > return 0;
> > > >
> > > > HAS_DDI perhaps?
> > >
> > > Do you mean we should add "&& HAS_DDI"?
> > > Could you please give me more details?
> > >
> > > Regards,
> > > Libin
> > >
> > > >
> > > > >
> > > > > mutex_lock(&dev_priv->av_mutex); @@ -653,7 +731,8 @@ static
> > > > > int
> > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > intel_encoder = dev_priv->dig_port_map[port];
> > > > > /* intel_encoder might be NULL for DP MST */
> > > > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > > > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > > > > err = -ENODEV;
> > > > > goto unlock;
> > > > > @@ -681,7 +760,7 @@ static int
> > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > goto unlock;
> > > > > }
> > > > >
> > > > > - n = audio_config_get_n(mode, rate);
> > > > > + n = audio_config_get_n(crtc, mode, rate);
> > > > > if (n == 0) {
> > > > > DRM_DEBUG_KMS("Using automatic mode for N value on
> > > > port %c\n",
> > > > > port_name(port));
> > > > > @@ -693,8 +772,17 @@ static int
> > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > >
> > > > > /* 3. set the N/CTS/M */
> > > > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > + /* setup m value for DP */
> > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > + m = audio_config_get_m(crtc, rate);
> > > > > + if (m == 0)
> > > > > + goto unlock;
> > > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > > + }
> > > > >
> > > > > unlock:
> > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > --
> > > > > 1.9.1
> > > >
> > > > --
> > > > Ville Syrjälä
> > > > Intel OTC
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 5:46 ` Yang, Libin
@ 2016-08-04 6:06 ` Ville Syrjälä
2016-08-04 6:12 ` Yang, Libin
0 siblings, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-08-04 6:06 UTC (permalink / raw)
To: Yang, Libin
Cc: tiwai@suse.de, Vetter, Daniel, libin.yang@linux.intel.com,
intel-gfx@lists.freedesktop.org
[-- Attachment #1: Type: text/plain, Size: 6304 bytes --]
On Thu, Aug 04, 2016 at 05:46:01AM +0000, Yang, Libin wrote:
> Hi Ville,
>
> > -----Original Message-----
> > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > Sent: Wednesday, August 3, 2016 12:59 AM
> > To: Yang, Libin <libin.yang@intel.com>
> > Cc: libin.yang@linux.intel.com; intel-gfx@lists.freedesktop.org;
> > jani.nikula@linux.intel.com; Vetter, Daniel <daniel.vetter@intel.com>;
> > tiwai@suse.de
> > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> >
> > On Tue, Aug 02, 2016 at 01:58:51PM +0000, Yang, Libin wrote:
> > > Hi Ville
> > >
> > > > -----Original Message-----
> > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > > To: libin.yang@linux.intel.com
> > > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > > <libin.yang@intel.com>
> > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > >
> > > > On Tue, Aug 02, 2016 at 09:35:10AM +0800, libin.yang@linux.intel.com
> > wrote:
> > > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > > >
> > > > > When modeset occurs and the LS_CLK is set to some special values
> > > > > in DP mode, the N/M need to be set manually if audio is playing.
> > > > >
> > > > > The relationship of Maud and Naud is expressed in the following
> > > > > equation:
> > > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > > >
> > > > > Please refer VESA DisplayPort Standard spec for details.
> > > > >
> > > > > Also, the patch applies
> > > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to
> > > > > APL platform.
> > > > >
> > > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > > ---
> > > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > > +++++++++++++++++++++++++++++++------
> > > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > @@ -7351,6 +7351,12 @@ enum {
> > > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > > >
> > > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> > _MMIO_PIPE(pipe,
> > > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > > +
> > > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > > index 6700a7b..de55ecf 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > > @@ -98,6 +98,22 @@ static const struct {
> > > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > > >
> > > > > +#define LC_540M 540000
> > > > > +#define LC_162M 162000
> > > >
> > > > Do we have some explanation why 2.7 doesn't need M/N programming,
> > > > but
> > > > 1.62 and 5.4 do?
> > >
> > > I didn't use 2.7 because I can't find a mode using 2.7.
> >
> > Hmm. Maybe we should add some knobs to force a specific bpc/link
> > rate/number of lanes to help with this kind of testing. Currently you just get
> > what you get, which isn't so nice when you want to test all variations.
> > ...
> > OK, so I just went ahead and did that. Here's a branch:
> >
> > git://github.com/vsyrjala/linux.git modparam_clock_bpp_limit
> >
> > For your DP testing just setting
> > i915.max_port_clock=162000 or i915.max_port_clock=270000 and then
> > forcing a modeset should do the trick.
>
> Thanks for the new branch. It seems download is very slow, less than
> 10Kib/s.
github that slow for you? Weird.
And I can't see a way to grab the raw patches from the github web
interface :( so I've attached the patches to this mail in case you
can't finish the git fetch in reasonable time.
> So I will submit the new patches firstly and then do the test.
> Fortunately, I found there is recommended data for 340MHz in the spec.
340 MHz? There's no such link rate for DP. I'm not sure what you're
saying here...
> I copied the data to the patch and suppose the data should be accurate.
>
> >
> > > So I can't do the test.
> > > 5.4 is for 4K and 1.62 is for 1080p.
> > >
> > > >
> > > > And I see you're only doing this on HSW+. Earlier platforms don't need this?
> > >
> > > We are not supporting earlier platforms and I'm not sure whether the
> > > old platforms supports 4K DP or not.
> >
> > SNB-IVB dotclock can go up to 360Mhz, ILK up to 405 Mhz. At least in theory.
> > The DP link is limited to 4 x 2.7 for all. From the those the dotclock limit is the
> > one you should hit first since DP can always fall back to 6bpc and that should
> > be correspond to a dotclock of 480 MHz.
> > Anyways, 360MHz is plenty for 4k@30.
> >
> >
> > The question really is why we need to do this in the first place.
> > There's nothing in the spec telling is it's really required. All I can find in the DP
> > spec is "Maud value is set to 2^15 (=32,768) when the audio clock is
> > asynchronous to the LS_Clk.", and then
>
> We made the patch because we found the HW can't calculate the value this
> will cause there is several seconds silence at the beginning of audio playback.
> With this patch, the silence is much shorter than before and is acceptable.
I see. Must be sink specific since at least my current monitor (ASUS
PB278) has no apparent delays with the current code. I guess some sinks are
just slower in clock recovery than others, and starting out with better
M/N values can speed it up a bit.
Anyways, please specify this reason for the change in the commit message,
otherwise no one can figure out why it's needed.
--
Ville Syrjälä
Intel OTC
[-- Attachment #2: 0001-drm-i915-Remove-useless-rate_to_index-usage.patch --]
[-- Type: text/x-diff, Size: 1301 bytes --]
>From 4416baa8ef415e9aa760309fc864aad8fb2ab807 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Wed, 27 Jul 2016 17:21:21 +0300
Subject: [PATCH 1/3] drm/i915: Remove useless rate_to_index() usage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
No need to iterate the rates array in intel_dp_max_link_rate(). We know
the max rate will be the last entry, and we already know the size.
Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 001f74fc0ce5..ae3dc15fe95a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1447,7 +1447,7 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
if (WARN_ON(len <= 0))
return 162000;
- return rates[rate_to_index(0, rates) - 1];
+ return rates[len - 1];
}
int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
--
2.7.4
[-- Attachment #3: 0002-drm-i915-Allow-rate_to_index-to-return-non-exact-mat.patch --]
[-- Type: text/x-diff, Size: 1415 bytes --]
>From 6b99092b0dce3edd3567da4b29ad0d5d36240f38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Wed, 27 Jul 2016 17:19:16 +0300
Subject: [PATCH 2/3] drm/i915: Allow rate_to_index() to return non-exact
matches
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Let's make rate_to_index() return the highest rate available that's
less than or equal to the rate requested by the caller. The function
can then be used to filter out rates higher than a certain maximum
rate.
Cc: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Cc: Jim Bride <jim.bride@linux.intel.com>
Cc: Manasi D Navare <manasi.d.navare@intel.com>
Cc: Durgadoss R <durgadoss.r@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ae3dc15fe95a..331e0c9d1783 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1431,10 +1431,13 @@ static int rate_to_index(int find, const int *rates)
int i = 0;
for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
- if (find == rates[i])
+ if (find < rates[i])
break;
- return i;
+ if (WARN_ON(i == 0))
+ return 0;
+
+ return i - 1;
}
int
--
2.7.4
[-- Attachment #4: 0003-drm-i915-Add-max_pipe_bpp-max_dot_clock-max_port_clo.patch --]
[-- Type: text/x-diff, Size: 10807 bytes --]
>From 4bc405c7b5fb1dcabd668bfcd50e67baae456353 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com>
Date: Tue, 2 Aug 2016 18:16:32 +0300
Subject: [PATCH 3/3] drm/i915: Add
max_pipe_bpp,max_dot_clock,max_port_clock,max_lanes modparams
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Eg.
limit DP to 2.7G link rate by setting max_port_clock=270000
limit DP to use at most 2 lanes by setting set max_lanes=2
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
drivers/gpu/drm/i915/i915_params.c | 13 ++++++++++++
drivers/gpu/drm/i915/i915_params.h | 4 ++++
drivers/gpu/drm/i915/intel_crt.c | 3 +++
drivers/gpu/drm/i915/intel_display.c | 13 ++++++++++++
drivers/gpu/drm/i915/intel_dp.c | 41 ++++++++++++++++++++++--------------
drivers/gpu/drm/i915/intel_dp_mst.c | 3 +++
drivers/gpu/drm/i915/intel_dsi.c | 3 +++
drivers/gpu/drm/i915/intel_dvo.c | 3 +++
drivers/gpu/drm/i915/intel_hdmi.c | 6 ++++++
drivers/gpu/drm/i915/intel_lvds.c | 3 +++
drivers/gpu/drm/i915/intel_sdvo.c | 3 +++
drivers/gpu/drm/i915/intel_tv.c | 3 +++
12 files changed, 82 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index b6e404c91eed..f9dbd308dfb6 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -63,6 +63,19 @@ struct i915_params i915 __read_mostly = {
.enable_gvt = false,
};
+module_param_named_unsafe(max_lanes, i915.max_lanes, int, 0600);
+MODULE_PARM_DESC(max_lanes,
+ "Maximum DP lanes (0=default, 1,2,4)");
+module_param_named_unsafe(max_port_clock, i915.max_port_clock, int, 0600);
+MODULE_PARM_DESC(max_port_clock,
+ "Maximum port clock limit (0=default, eg. 270000)");
+module_param_named_unsafe(max_dot_clock, i915.max_dot_clock, int, 0600);
+MODULE_PARM_DESC(max_dot_clock,
+ "Maximum dot clock limit (0=default, eg. 148500)");
+module_param_named_unsafe(max_pipe_bpp, i915.max_pipe_bpp, int, 0600);
+MODULE_PARM_DESC(max_pipe_bpp,
+ "Maximum pipe bpp used (0=default, 18,24,30,36)");
+
module_param_named(modeset, i915.modeset, int, 0400);
MODULE_PARM_DESC(modeset,
"Use kernel modesetting [KMS] (0=disable, "
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
index 0ad020b4a925..014e821578e2 100644
--- a/drivers/gpu/drm/i915/i915_params.h
+++ b/drivers/gpu/drm/i915/i915_params.h
@@ -52,6 +52,10 @@ struct i915_params {
int mmio_debug;
int edp_vswing;
unsigned int inject_load_failure;
+ int max_lanes;
+ int max_port_clock;
+ int max_dot_clock;
+ int max_pipe_bpp;
/* leave bools at the end to not create holes */
bool enable_hangcheck;
bool fastboot;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 827b6ef4e9ae..d665a022f9dd 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -220,6 +220,9 @@ intel_crt_mode_valid(struct drm_connector *connector,
int max_dotclk = to_i915(dev)->max_dotclk_freq;
int max_clock;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a8e8cc8dfae9..f284f1050aef 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6618,6 +6618,9 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
}
}
+ if (i915.max_dot_clock)
+ clock_limit = min(i915.max_dot_clock, clock_limit);
+
if (adjusted_mode->crtc_clock > clock_limit) {
DRM_DEBUG_KMS("requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n",
adjusted_mode->crtc_clock, clock_limit,
@@ -12139,6 +12142,16 @@ compute_baseline_pipe_bpp(struct intel_crtc *crtc,
else
bpp = 8*3;
+ switch (i915.max_pipe_bpp) {
+ case 12*3:
+ case 10*3:
+ case 8*3:
+ case 6*3:
+ bpp = min(i915.max_pipe_bpp, bpp);
+ break;
+ default:
+ break;
+ }
pipe_config->pipe_bpp = bpp;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 331e0c9d1783..5a4bc09437f5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -150,14 +150,17 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp)
return max_link_bw;
}
-static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp)
+static int intel_dp_max_lane_count(struct intel_dp *intel_dp)
{
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
- u8 source_max, sink_max;
+ int source_max, sink_max;
source_max = intel_dig_port->max_lanes;
sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
+ if (i915.max_lanes > 0)
+ source_max = min(i915.max_lanes, source_max);
+
return min(source_max, sink_max);
}
@@ -201,6 +204,9 @@ intel_dp_mode_valid(struct drm_connector *connector,
int max_rate, mode_rate, max_lanes, max_link_clock;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
if (is_edp(intel_dp) && fixed_mode) {
if (mode->hdisplay > fixed_mode->hdisplay)
return MODE_PANEL;
@@ -1373,6 +1379,20 @@ static int intersect_rates(const int *source_rates, int source_len,
return k;
}
+static int rate_to_index(int find, const int *rates)
+{
+ int i = 0;
+
+ for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
+ if (find < rates[i])
+ break;
+
+ if (WARN_ON(i == 0))
+ return 0;
+
+ return i - 1;
+}
+
static int intel_dp_common_rates(struct intel_dp *intel_dp,
int *common_rates)
{
@@ -1382,6 +1402,9 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp,
sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
source_len = intel_dp_source_rates(intel_dp, &source_rates);
+ if (i915.max_port_clock > 0)
+ source_len = rate_to_index(i915.max_port_clock, source_rates) + 1;
+
return intersect_rates(source_rates, source_len,
sink_rates, sink_len,
common_rates);
@@ -1426,20 +1449,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
DRM_DEBUG_KMS("common rates: %s\n", str);
}
-static int rate_to_index(int find, const int *rates)
-{
- int i = 0;
-
- for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
- if (find < rates[i])
- break;
-
- if (WARN_ON(i == 0))
- return 0;
-
- return i - 1;
-}
-
int
intel_dp_max_link_rate(struct intel_dp *intel_dp)
{
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 629337dbca3d..7fe169ed3e49 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -354,6 +354,9 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
{
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
/* TODO - validate mode against available PBN for link */
if (mode->clock < 10000)
return MODE_CLOCK_LOW;
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index de8e9fb51595..3f4abac8ea4c 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -985,6 +985,9 @@ intel_dsi_mode_valid(struct drm_connector *connector,
const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
DRM_DEBUG_KMS("\n");
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) {
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index 47bdf9dad0d3..6cec78957be0 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -214,6 +214,9 @@ intel_dvo_mode_valid(struct drm_connector *connector,
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
int target_clock = mode->clock;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 4df9f384910c..74ec74a084fc 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1203,6 +1203,9 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi,
struct drm_device *dev = intel_hdmi_to_dev(hdmi);
int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
+ if (i915.max_port_clock)
+ max_tmds_clock = min(i915.max_port_clock, max_tmds_clock);
+
if (respect_downstream_limits) {
if (hdmi->dp_dual_mode.max_tmds_clock)
max_tmds_clock = min(max_tmds_clock,
@@ -1246,6 +1249,9 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
int clock;
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 49550470483e..4df7a53d27db 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -293,6 +293,9 @@ intel_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_pixclk = min(i915.max_dot_clock, max_pixclk);
+
if (mode->hdisplay > fixed_mode->hdisplay)
return MODE_PANEL;
if (mode->vdisplay > fixed_mode->vdisplay)
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index e378f35365a2..4f5af6ff1f42 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1527,6 +1527,9 @@ intel_sdvo_mode_valid(struct drm_connector *connector,
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 49136ad5473e..f282a7c3633d 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -887,6 +887,9 @@ intel_tv_mode_valid(struct drm_connector *connector,
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (i915.max_dot_clock)
+ max_dotclk = min(i915.max_dot_clock, max_dotclk);
+
if (mode->clock > max_dotclk)
return MODE_CLOCK_HIGH;
--
2.7.4
[-- Attachment #5: Type: text/plain, Size: 160 bytes --]
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 6:06 ` Ville Syrjälä
@ 2016-08-04 6:12 ` Yang, Libin
0 siblings, 0 replies; 23+ messages in thread
From: Yang, Libin @ 2016-08-04 6:12 UTC (permalink / raw)
To: Ville Syrjälä
Cc: tiwai@suse.de, Vetter, Daniel, libin.yang@linux.intel.com,
intel-gfx@lists.freedesktop.org
Hi Ville,
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Thursday, August 4, 2016 2:06 PM
> To: Yang, Libin <libin.yang@intel.com>
> Cc: libin.yang@linux.intel.com; intel-gfx@lists.freedesktop.org;
> jani.nikula@linux.intel.com; Vetter, Daniel <daniel.vetter@intel.com>;
> tiwai@suse.de
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Thu, Aug 04, 2016 at 05:46:01AM +0000, Yang, Libin wrote:
> > Hi Ville,
> >
> > > -----Original Message-----
> > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > Sent: Wednesday, August 3, 2016 12:59 AM
> > > To: Yang, Libin <libin.yang@intel.com>
> > > Cc: libin.yang@linux.intel.com; intel-gfx@lists.freedesktop.org;
> > > jani.nikula@linux.intel.com; Vetter, Daniel
> > > <daniel.vetter@intel.com>; tiwai@suse.de
> > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > >
> > > On Tue, Aug 02, 2016 at 01:58:51PM +0000, Yang, Libin wrote:
> > > > Hi Ville
> > > >
> > > > > -----Original Message-----
> > > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > > > To: libin.yang@linux.intel.com
> > > > > Cc: intel-gfx@lists.freedesktop.org;
> > > > > jani.nikula@linux.intel.com; Vetter, Daniel
> > > > > <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > > > <libin.yang@intel.com>
> > > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > > >
> > > > > On Tue, Aug 02, 2016 at 09:35:10AM +0800,
> > > > > libin.yang@linux.intel.com
> > > wrote:
> > > > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > > > >
> > > > > > When modeset occurs and the LS_CLK is set to some special
> > > > > > values in DP mode, the N/M need to be set manually if audio is
> playing.
> > > > > >
> > > > > > The relationship of Maud and Naud is expressed in the
> > > > > > following
> > > > > > equation:
> > > > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > > > >
> > > > > > Please refer VESA DisplayPort Standard spec for details.
> > > > > >
> > > > > > Also, the patch applies
> > > > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset")
> > > > > > to APL platform.
> > > > > >
> > > > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > > > ---
> > > > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > > > +++++++++++++++++++++++++++++++------
> > > > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e
> > > > > > 100644
> > > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > > @@ -7351,6 +7351,12 @@ enum {
> > > > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > > > >
> > > > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> > > _MMIO_PIPE(pipe,
> > > > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > > > +
> > > > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > index 6700a7b..de55ecf 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > @@ -98,6 +98,22 @@ static const struct {
> > > > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > > > >
> > > > > > +#define LC_540M 540000
> > > > > > +#define LC_162M 162000
> > > > >
> > > > > Do we have some explanation why 2.7 doesn't need M/N
> > > > > programming, but
> > > > > 1.62 and 5.4 do?
> > > >
> > > > I didn't use 2.7 because I can't find a mode using 2.7.
> > >
> > > Hmm. Maybe we should add some knobs to force a specific bpc/link
> > > rate/number of lanes to help with this kind of testing. Currently
> > > you just get what you get, which isn't so nice when you want to test all
> variations.
> > > ...
> > > OK, so I just went ahead and did that. Here's a branch:
> > >
> > > git://github.com/vsyrjala/linux.git modparam_clock_bpp_limit
> > >
> > > For your DP testing just setting
> > > i915.max_port_clock=162000 or i915.max_port_clock=270000 and then
> > > forcing a modeset should do the trick.
> >
> > Thanks for the new branch. It seems download is very slow, less than
> > 10Kib/s.
>
> github that slow for you? Weird.
>
> And I can't see a way to grab the raw patches from the github web
> interface :( so I've attached the patches to this mail in case you can't finish the
> git fetch in reasonable time.
>
> > So I will submit the new patches firstly and then do the test.
> > Fortunately, I found there is recommended data for 340MHz in the spec.
>
> 340 MHz? There's no such link rate for DP. I'm not sure what you're saying
> here...
>
> > I copied the data to the patch and suppose the data should be accurate.
Thanks for the patch. Sorry, I mean 270MHz, not 340MHz.
> >
> > >
> > > > So I can't do the test.
> > > > 5.4 is for 4K and 1.62 is for 1080p.
> > > >
> > > > >
> > > > > And I see you're only doing this on HSW+. Earlier platforms don't need
> this?
> > > >
> > > > We are not supporting earlier platforms and I'm not sure whether
> > > > the old platforms supports 4K DP or not.
> > >
> > > SNB-IVB dotclock can go up to 360Mhz, ILK up to 405 Mhz. At least in
> theory.
> > > The DP link is limited to 4 x 2.7 for all. From the those the
> > > dotclock limit is the one you should hit first since DP can always
> > > fall back to 6bpc and that should be correspond to a dotclock of 480 MHz.
> > > Anyways, 360MHz is plenty for 4k@30.
> > >
> > >
> > > The question really is why we need to do this in the first place.
> > > There's nothing in the spec telling is it's really required. All I
> > > can find in the DP spec is "Maud value is set to 2^15 (=32,768) when
> > > the audio clock is asynchronous to the LS_Clk.", and then
> >
> > We made the patch because we found the HW can't calculate the value
> > this will cause there is several seconds silence at the beginning of audio
> playback.
> > With this patch, the silence is much shorter than before and is acceptable.
>
> I see. Must be sink specific since at least my current monitor (ASUS
> PB278) has no apparent delays with the current code. I guess some sinks are
> just slower in clock recovery than others, and starting out with better M/N
> values can speed it up a bit.
Yes, behaviors are different between different monitors.
>
> Anyways, please specify this reason for the change in the commit message,
> otherwise no one can figure out why it's needed.
Get it. I will add it.
Regards,
Libin
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 6:04 ` Yang, Libin
@ 2016-08-04 6:23 ` Ville Syrjälä
2016-08-04 6:31 ` Yang, Libin
0 siblings, 1 reply; 23+ messages in thread
From: Ville Syrjälä @ 2016-08-04 6:23 UTC (permalink / raw)
To: Yang, Libin
Cc: 'tiwai@suse.de', Vetter, Daniel,
'libin.yang@linux.intel.com',
'intel-gfx@lists.freedesktop.org'
On Thu, Aug 04, 2016 at 06:04:10AM +0000, Yang, Libin wrote:
> Hi Ville,
>
> > -----Original Message-----
> > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > Sent: Thursday, August 4, 2016 1:39 PM
> > To: Yang, Libin <libin.yang@intel.com>
> > Cc: 'libin.yang@linux.intel.com' <libin.yang@linux.intel.com>; 'intel-
> > gfx@lists.freedesktop.org' <intel-gfx@lists.freedesktop.org>;
> > 'jani.nikula@linux.intel.com' <jani.nikula@linux.intel.com>; Vetter, Daniel
> > <daniel.vetter@intel.com>; 'tiwai@suse.de' <tiwai@suse.de>
> > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> >
> > On Thu, Aug 04, 2016 at 02:48:54AM +0000, Yang, Libin wrote:
> > > Hi Ville,
> > >
> > > > -----Original Message-----
> > > > From: Yang, Libin
> > > > Sent: Tuesday, August 2, 2016 9:59 PM
> > > > To: Ville Syrjälä <ville.syrjala@linux.intel.com>;
> > > > libin.yang@linux.intel.com
> > > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de
> > > > Subject: RE: [PATCH] drm/i915: set proper N/M in modeset
> > > >
> > > > Hi Ville
> > > >
> > > > > -----Original Message-----
> > > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > > > To: libin.yang@linux.intel.com
> > > > > Cc: intel-gfx@lists.freedesktop.org; jani.nikula@linux.intel.com;
> > > > > Vetter, Daniel <daniel.vetter@intel.com>; tiwai@suse.de; Yang,
> > > > > Libin <libin.yang@intel.com>
> > > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > > >
> > > > > On Tue, Aug 02, 2016 at 09:35:10AM +0800,
> > > > > libin.yang@linux.intel.com
> > > > wrote:
> > > > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > > > >
> > > > > > When modeset occurs and the LS_CLK is set to some special values
> > > > > > in DP mode, the N/M need to be set manually if audio is playing.
> > > > > >
> > > > > > The relationship of Maud and Naud is expressed in the following
> > > > > > equation:
> > > > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > > > >
> > > > > > Please refer VESA DisplayPort Standard spec for details.
> > > > > >
> > > > > > Also, the patch applies
> > > > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in modeset") to
> > > > > > APL platform.
> > > > > >
> > > > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > > > ---
> > > > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > > > +++++++++++++++++++++++++++++++------
> > > > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e 100644
> > > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > > @@ -7351,6 +7351,12 @@ enum {
> > > > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > > > >
> > > > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> > _MMIO_PIPE(pipe,
> > > > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > > > +
> > > > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > index 6700a7b..de55ecf 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > @@ -98,6 +98,22 @@ static const struct {
> > > > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > > > >
> > > > > > +#define LC_540M 540000
> > > > > > +#define LC_162M 162000
> > > > >
> > > > > Do we have some explanation why 2.7 doesn't need M/N programming,
> > > > > but
> > > > > 1.62 and 5.4 do?
> > > >
> > > > I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the test.
> > > > 5.4 is for 4K and 1.62 is for 1080p.
> > > >
> > > > >
> > > > > And I see you're only doing this on HSW+. Earlier platforms don't need
> > this?
> > > >
> > > > We are not supporting earlier platforms and I'm not sure whether the
> > > > old platforms supports 4K DP or not.
> > > >
> > > > >
> > > > > > +static const struct {
> > > > > > + int sample_rate;
> > > > > > + int clock;
> > > > > > + int n;
> > > > > > + int m;
> > > > >
> > > > > Can save a bit of space by using u16 for m and n.
> > > >
> > > > OK, I will do it in next version.
> > > >
> > > > >
> > > > > > +} aud_nm[] = {
> > > > > > + {48000, LC_540M, 5625, 256},`
> > > > > > + {44100, LC_540M, 9375, 392},
> > > > > > + {32000, LC_540M, 16875, 512},
> > > > > > + {48000, LC_162M, 3375, 512},
> > > > > > + {44100, LC_162M, 5625, 784},
> > > > > > + {32000, LC_162M, 10125, 1024
> > > > > > +};
> > > > >
> > > > > The numbers look good, but what about other sample rates? For HDMI
> > > > > we go up to 192kHz, why not for DP?
> > > >
> > > > Our test only includes 32K, 44.1K and 48K :) I will add the support
> > > > if you think we should.
> > >
> > > I will not add 192KHz, 96KHz and etc rate support as based on my test
> > > these rate will be not used in DP. It will be converted to 48KHz.
> >
> > How about basing that decision on what's actually allowed by the driver?
> > I can do 96kHz DP audio on my HSW just fine here. So clearly if the display
> > supports it, there is nothing on the ALSA side that would prevent it from being
> > used.
>
> For 96KHz, audio will convert to 48KHz. You can try to print the sample rate
> in i915_audio_component_sync_audio_rate(). So we can't test it for the real
> 96kHz.
Wrong.
# grep rate /proc/asound/HDMI/eld#0.0
sad0_rates [0x4e0] 32000 44100 48000 96000
# grep rate /proc/asound/HDMI/pcm3p/sub0/hw_params
rate: 96000 (96000/1)
[drm:i915_audio_component_sync_audio_rate] sample rate 96000 kHz
>
> In DP spec, table 2-50 only says 48kHz, 32kHz, 44.1kHz, 384kHz and 768kHz.
That table is just for informative purposes. The values are the ones you
get from the formula. And the ELD can contain exactly the same SADs as
with HDMI, so all the same sample rates can be used.
> However, the latter two sample rates is not supported in audio driver and
> can't be tested so far. 88kHz, 96kHz and 192kHz cannot be tested, either.
>
> Regards,
> Libin
>
> >
> > >
> > > >
> > > > >
> > > > > > +
> > > > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ static
> > > > > > u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > *adjusted
> > > > > > return hdmi_audio_clock[i].config; }
> > > > > >
> > > > > > -static int audio_config_get_n(const struct drm_display_mode
> > > > > > *mode, int rate)
> > > > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > > > + const struct drm_display_mode
> > *adjusted_mode,
> > > > > > + int rate)
> > > > > > +{
> > > > > > + int i;
> > > > > > +
> > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > > > + (adjusted_mode->clock ==
> > aud_ncts[i].clock)) {
> > > > > > + return aud_ncts[i].n;
> > > > > > + }
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > > + (crtc->config->port_clock ==
> > aud_nm[i].clock))
> > > > > {
> > > > > > + return aud_nm[i].n;
> > > > > > + }
> > > > > > + }
> > > > > > + }
> > > > > > + return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static int audio_config_get_m(struct intel_crtc *crtc, int
> > > > > > +rate)
> > > > > > {
> > > > > > int i;
> > > > > >
> > > > > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > > > > - (mode->clock == aud_ncts[i].clock)) {
> > > > > > - return aud_ncts[i].n;
> > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > > + (crtc->config->port_clock ==
> > aud_nm[i].clock))
> > > > > {
> > > > > > + return aud_nm[i].m;
> > > > > > + }
> > > > > > }
> > > > > > }
> > > > > > +
> > > > > > return 0;
> > > > > > }
> > > > > >
> > > > > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
> > > > > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > > > > + int n, uint32_t val)
> > > > > > {
> > > > > > int n_low, n_up;
> > > > > > uint32_t tmp = val;
> > > > > > @@ -145,17 +191,38 @@ static uint32_t
> > > > > > audio_config_setup_n_reg(int n,
> > > > > uint32_t val)
> > > > > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > > > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > > > > AUD_CONFIG_N_PROG_ENABLE);
> > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > > > > + return tmp;
> > > > > > +}
> > > > > > +
> > > > > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > > > > + int m, uint32_t val)
> > > > > > +{
> > > > > > + uint32_t tmp = val;
> > > > > > +
> > > > > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > + return 0;
> > > > > > +
> > > > > > + tmp |= m;
> > > > > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > > > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > > > > +
> > > > > > return tmp;
> > > > > > }
> > > > > >
> > > > > > /* check whether N/CTS/M need be set manually */ static bool
> > > > > > audio_rate_need_prog(struct intel_crtc *crtc,
> > > > > > - const struct drm_display_mode *mode)
> > > > > > + const struct drm_display_mode
> > > > > *adjusted_mode)
> > > > > > {
> > > > > > - if (((mode->clock == TMDS_297M) ||
> > > > > > - (mode->clock == TMDS_296M)) &&
> > > > > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > > > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > > > > intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
> > > > > > return true;
> > > > > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > > > > + (crtc->config->port_clock == LC_162M)) &&
> > > > > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > + return true;
> > > > > > else
> > > > > > return false;
> > > > > > }
> > > > > > @@ -287,7 +354,7 @@ static void hsw_audio_codec_enable(struct
> > > > > drm_connector *connector,
> > > > > > struct intel_digital_port *intel_dig_port =
> > > > > > enc_to_dig_port(&encoder->base);
> > > > > > enum port port = intel_dig_port->port;
> > > > > > - uint32_t tmp;
> > > > > > + uint32_t tmp, m;
> > > > > > int len, i;
> > > > > > int n, rate;
> > > > > >
> > > > > > @@ -343,15 +410,25 @@ static void hsw_audio_codec_enable(struct
> > > > > drm_connector *connector,
> > > > > > DRM_ERROR("invalid port: %d\n", port);
> > > > > > rate = 0;
> > > > > > }
> > > > > > - n = audio_config_get_n(adjusted_mode, rate);
> > > > > > + n = audio_config_get_n(intel_crtc, adjusted_mode,
> > rate);
> > > > > > if (n != 0)
> > > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > > + tmp = audio_config_setup_n_reg(intel_crtc, n,
> > tmp);
> > > > > > else
> > > > > > DRM_DEBUG_KMS("no suitable N value is found\n");
> > > > > > }
> > > > > >
> > > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > >
> > > > > > + /* setup m value for DP */
> > > > > > + if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP))
> > {
> > > > > > + m = audio_config_get_m(intel_crtc, rate);
> > > > > > + if (m != 0) {
> > > > > > + tmp =
> > I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > > + tmp = audio_config_setup_m_reg(intel_crtc,
> > m, tmp);
> > > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe),
> > tmp);
> > > > > > + }
> > > > > > + }
> > > > > > +
> > > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > > }
> > > > > >
> > > > > > @@ -637,7 +714,7 @@ static int
> > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > struct drm_display_mode *mode;
> > > > > > struct i915_audio_component *acomp = dev_priv->audio_component;
> > > > > > enum pipe pipe = INVALID_PIPE;
> > > > > > - u32 tmp;
> > > > > > + u32 tmp, m;
> > > > > > int n;
> > > > > > int err = 0;
> > > > > >
> > > > > > @@ -645,7 +722,8 @@ static int
> > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > if (!IS_SKYLAKE(dev_priv) &&
> > > > > > !IS_KABYLAKE(dev_priv) &&
> > > > > > !IS_BROADWELL(dev_priv) &&
> > > > > > - !IS_HASWELL(dev_priv))
> > > > > > + !IS_HASWELL(dev_priv) &&
> > > > > > + !IS_BROXTON(dev_priv))
> > > > > > return 0;
> > > > >
> > > > > HAS_DDI perhaps?
> > > >
> > > > Do you mean we should add "&& HAS_DDI"?
> > > > Could you please give me more details?
> > > >
> > > > Regards,
> > > > Libin
> > > >
> > > > >
> > > > > >
> > > > > > mutex_lock(&dev_priv->av_mutex); @@ -653,7 +731,8 @@ static
> > > > > > int
> > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > intel_encoder = dev_priv->dig_port_map[port];
> > > > > > /* intel_encoder might be NULL for DP MST */
> > > > > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > > > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > > > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > > > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > > > > DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
> > > > > > err = -ENODEV;
> > > > > > goto unlock;
> > > > > > @@ -681,7 +760,7 @@ static int
> > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > goto unlock;
> > > > > > }
> > > > > >
> > > > > > - n = audio_config_get_n(mode, rate);
> > > > > > + n = audio_config_get_n(crtc, mode, rate);
> > > > > > if (n == 0) {
> > > > > > DRM_DEBUG_KMS("Using automatic mode for N value on
> > > > > port %c\n",
> > > > > > port_name(port));
> > > > > > @@ -693,8 +772,17 @@ static int
> > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > >
> > > > > > /* 3. set the N/CTS/M */
> > > > > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > > + /* setup m value for DP */
> > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > + m = audio_config_get_m(crtc, rate);
> > > > > > + if (m == 0)
> > > > > > + goto unlock;
> > > > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > > > + }
> > > > > >
> > > > > > unlock:
> > > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > > --
> > > > > > 1.9.1
> > > > >
> > > > > --
> > > > > Ville Syrjälä
> > > > > Intel OTC
> >
> > --
> > Ville Syrjälä
> > Intel OTC
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev3)
2016-08-02 1:35 [PATCH] drm/i915: set proper N/M in modeset libin.yang
` (2 preceding siblings ...)
2016-08-02 10:52 ` Jani Nikula
@ 2016-08-04 6:29 ` Patchwork
3 siblings, 0 replies; 23+ messages in thread
From: Patchwork @ 2016-08-04 6:29 UTC (permalink / raw)
To: ville.syrjala; +Cc: intel-gfx
== Series Details ==
Series: drm/i915: set proper N/M in modeset (rev3)
URL : https://patchwork.freedesktop.org/series/9857/
State : failure
== Summary ==
Applying: drm/i915: set proper N/M in modeset
fatal: sha1 information is lacking or useless (drivers/gpu/drm/i915/intel_dp.c).
error: could not build fake ancestor
Patch failed at 0001 drm/i915: set proper N/M in modeset
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 6:23 ` Ville Syrjälä
@ 2016-08-04 6:31 ` Yang, Libin
2016-08-04 6:36 ` Ville Syrjälä
0 siblings, 1 reply; 23+ messages in thread
From: Yang, Libin @ 2016-08-04 6:31 UTC (permalink / raw)
To: Ville Syrjälä
Cc: 'tiwai@suse.de', Vetter, Daniel,
'libin.yang@linux.intel.com',
'intel-gfx@lists.freedesktop.org'
Hi Ville,
> -----Original Message-----
> From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> Sent: Thursday, August 4, 2016 2:24 PM
> To: Yang, Libin <libin.yang@intel.com>
> Cc: 'libin.yang@linux.intel.com' <libin.yang@linux.intel.com>; 'intel-
> gfx@lists.freedesktop.org' <intel-gfx@lists.freedesktop.org>;
> 'jani.nikula@linux.intel.com' <jani.nikula@linux.intel.com>; Vetter, Daniel
> <daniel.vetter@intel.com>; 'tiwai@suse.de' <tiwai@suse.de>
> Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
>
> On Thu, Aug 04, 2016 at 06:04:10AM +0000, Yang, Libin wrote:
> > Hi Ville,
> >
> > > -----Original Message-----
> > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > Sent: Thursday, August 4, 2016 1:39 PM
> > > To: Yang, Libin <libin.yang@intel.com>
> > > Cc: 'libin.yang@linux.intel.com' <libin.yang@linux.intel.com>;
> > > 'intel- gfx@lists.freedesktop.org'
> > > <intel-gfx@lists.freedesktop.org>;
> > > 'jani.nikula@linux.intel.com' <jani.nikula@linux.intel.com>; Vetter,
> > > Daniel <daniel.vetter@intel.com>; 'tiwai@suse.de' <tiwai@suse.de>
> > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > >
> > > On Thu, Aug 04, 2016 at 02:48:54AM +0000, Yang, Libin wrote:
> > > > Hi Ville,
> > > >
> > > > > -----Original Message-----
> > > > > From: Yang, Libin
> > > > > Sent: Tuesday, August 2, 2016 9:59 PM
> > > > > To: Ville Syrjälä <ville.syrjala@linux.intel.com>;
> > > > > libin.yang@linux.intel.com
> > > > > Cc: intel-gfx@lists.freedesktop.org;
> > > > > jani.nikula@linux.intel.com; Vetter, Daniel
> > > > > <daniel.vetter@intel.com>; tiwai@suse.de
> > > > > Subject: RE: [PATCH] drm/i915: set proper N/M in modeset
> > > > >
> > > > > Hi Ville
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > > > > To: libin.yang@linux.intel.com
> > > > > > Cc: intel-gfx@lists.freedesktop.org;
> > > > > > jani.nikula@linux.intel.com; Vetter, Daniel
> > > > > > <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > > > > <libin.yang@intel.com>
> > > > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > > > >
> > > > > > On Tue, Aug 02, 2016 at 09:35:10AM +0800,
> > > > > > libin.yang@linux.intel.com
> > > > > wrote:
> > > > > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > > > > >
> > > > > > > When modeset occurs and the LS_CLK is set to some special
> > > > > > > values in DP mode, the N/M need to be set manually if audio is
> playing.
> > > > > > >
> > > > > > > The relationship of Maud and Naud is expressed in the
> > > > > > > following
> > > > > > > equation:
> > > > > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > > > > >
> > > > > > > Please refer VESA DisplayPort Standard spec for details.
> > > > > > >
> > > > > > > Also, the patch applies
> > > > > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in
> > > > > > > modeset") to APL platform.
> > > > > > >
> > > > > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > > > > ---
> > > > > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > > > > +++++++++++++++++++++++++++++++------
> > > > > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e
> > > > > > > 100644
> > > > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > > > @@ -7351,6 +7351,12 @@ enum {
> > > > > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > > > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > > > > >
> > > > > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> > > _MMIO_PIPE(pipe,
> > > > > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > > > > +
> > > > > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > > > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > index 6700a7b..de55ecf 100644
> > > > > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > @@ -98,6 +98,22 @@ static const struct {
> > > > > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > > > > >
> > > > > > > +#define LC_540M 540000
> > > > > > > +#define LC_162M 162000
> > > > > >
> > > > > > Do we have some explanation why 2.7 doesn't need M/N
> > > > > > programming, but
> > > > > > 1.62 and 5.4 do?
> > > > >
> > > > > I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the
> test.
> > > > > 5.4 is for 4K and 1.62 is for 1080p.
> > > > >
> > > > > >
> > > > > > And I see you're only doing this on HSW+. Earlier platforms
> > > > > > don't need
> > > this?
> > > > >
> > > > > We are not supporting earlier platforms and I'm not sure whether
> > > > > the old platforms supports 4K DP or not.
> > > > >
> > > > > >
> > > > > > > +static const struct {
> > > > > > > + int sample_rate;
> > > > > > > + int clock;
> > > > > > > + int n;
> > > > > > > + int m;
> > > > > >
> > > > > > Can save a bit of space by using u16 for m and n.
> > > > >
> > > > > OK, I will do it in next version.
> > > > >
> > > > > >
> > > > > > > +} aud_nm[] = {
> > > > > > > + {48000, LC_540M, 5625, 256},`
> > > > > > > + {44100, LC_540M, 9375, 392},
> > > > > > > + {32000, LC_540M, 16875, 512},
> > > > > > > + {48000, LC_162M, 3375, 512},
> > > > > > > + {44100, LC_162M, 5625, 784},
> > > > > > > + {32000, LC_162M, 10125, 1024 };
> > > > > >
> > > > > > The numbers look good, but what about other sample rates? For
> > > > > > HDMI we go up to 192kHz, why not for DP?
> > > > >
> > > > > Our test only includes 32K, 44.1K and 48K :) I will add the
> > > > > support if you think we should.
> > > >
> > > > I will not add 192KHz, 96KHz and etc rate support as based on my
> > > > test these rate will be not used in DP. It will be converted to 48KHz.
> > >
> > > How about basing that decision on what's actually allowed by the driver?
> > > I can do 96kHz DP audio on my HSW just fine here. So clearly if the
> > > display supports it, there is nothing on the ALSA side that would
> > > prevent it from being used.
> >
> > For 96KHz, audio will convert to 48KHz. You can try to print the
> > sample rate in i915_audio_component_sync_audio_rate(). So we can't
> > test it for the real 96kHz.
>
> Wrong.
>
> # grep rate /proc/asound/HDMI/eld#0.0
> sad0_rates [0x4e0] 32000 44100 48000 96000
>
> # grep rate /proc/asound/HDMI/pcm3p/sub0/hw_params
> rate: 96000 (96000/1)
>
> [drm:i915_audio_component_sync_audio_rate] sample rate 96000 kHz
Interesting, maybe my monitor doesn't support. And my driver will convert
it to 48KHz.
>
> >
> > In DP spec, table 2-50 only says 48kHz, 32kHz, 44.1kHz, 384kHz and 768kHz.
>
> That table is just for informative purposes. The values are the ones you get
> from the formula. And the ELD can contain exactly the same SADs as with
> HDMI, so all the same sample rates can be used.
Yes. I will add the other sample rates support. But these date will not be
test as I can't play 96KHz audio with hardware support here.
Regards,
Libin
>
> > However, the latter two sample rates is not supported in audio driver
> > and can't be tested so far. 88kHz, 96kHz and 192kHz cannot be tested, either.
> >
> > Regards,
> > Libin
> >
> > >
> > > >
> > > > >
> > > > > >
> > > > > > > +
> > > > > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
> > > > > > > static
> > > > > > > u32 audio_config_hdmi_pixel_clock(const struct
> > > > > > > drm_display_mode
> > > > > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > *adjusted
> > > > > > > return hdmi_audio_clock[i].config; }
> > > > > > >
> > > > > > > -static int audio_config_get_n(const struct drm_display_mode
> > > > > > > *mode, int rate)
> > > > > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > > > > + const struct drm_display_mode
> > > *adjusted_mode,
> > > > > > > + int rate)
> > > > > > > +{
> > > > > > > + int i;
> > > > > > > +
> > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > > > > + (adjusted_mode->clock ==
> > > aud_ncts[i].clock)) {
> > > > > > > + return aud_ncts[i].n;
> > > > > > > + }
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > > > + (crtc->config->port_clock ==
> > > aud_nm[i].clock))
> > > > > > {
> > > > > > > + return aud_nm[i].n;
> > > > > > > + }
> > > > > > > + }
> > > > > > > + }
> > > > > > > + return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static int audio_config_get_m(struct intel_crtc *crtc, int
> > > > > > > +rate)
> > > > > > > {
> > > > > > > int i;
> > > > > > >
> > > > > > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > > > > > - (mode->clock == aud_ncts[i].clock)) {
> > > > > > > - return aud_ncts[i].n;
> > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > > > + (crtc->config->port_clock ==
> > > aud_nm[i].clock))
> > > > > > {
> > > > > > > + return aud_nm[i].m;
> > > > > > > + }
> > > > > > > }
> > > > > > > }
> > > > > > > +
> > > > > > > return 0;
> > > > > > > }
> > > > > > >
> > > > > > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t
> > > > > > > val)
> > > > > > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > > > > > + int n, uint32_t val)
> > > > > > > {
> > > > > > > int n_low, n_up;
> > > > > > > uint32_t tmp = val;
> > > > > > > @@ -145,17 +191,38 @@ static uint32_t
> > > > > > > audio_config_setup_n_reg(int n,
> > > > > > uint32_t val)
> > > > > > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > > > > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > > > > > AUD_CONFIG_N_PROG_ENABLE);
> > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > > > > > + return tmp;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > > > > > + int m, uint32_t val)
> > > > > > > +{
> > > > > > > + uint32_t tmp = val;
> > > > > > > +
> > > > > > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > > + return 0;
> > > > > > > +
> > > > > > > + tmp |= m;
> > > > > > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > > > > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > > > > > +
> > > > > > > return tmp;
> > > > > > > }
> > > > > > >
> > > > > > > /* check whether N/CTS/M need be set manually */ static
> > > > > > > bool audio_rate_need_prog(struct intel_crtc *crtc,
> > > > > > > - const struct drm_display_mode
> *mode)
> > > > > > > + const struct drm_display_mode
> > > > > > *adjusted_mode)
> > > > > > > {
> > > > > > > - if (((mode->clock == TMDS_297M) ||
> > > > > > > - (mode->clock == TMDS_296M)) &&
> > > > > > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > > > > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > > > > > intel_crtc_has_type(crtc->config,
> INTEL_OUTPUT_HDMI))
> > > > > > > return true;
> > > > > > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > > > > > + (crtc->config->port_clock == LC_162M)) &&
> > > > > > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > > + return true;
> > > > > > > else
> > > > > > > return false;
> > > > > > > }
> > > > > > > @@ -287,7 +354,7 @@ static void
> > > > > > > hsw_audio_codec_enable(struct
> > > > > > drm_connector *connector,
> > > > > > > struct intel_digital_port *intel_dig_port =
> > > > > > > enc_to_dig_port(&encoder->base);
> > > > > > > enum port port = intel_dig_port->port;
> > > > > > > - uint32_t tmp;
> > > > > > > + uint32_t tmp, m;
> > > > > > > int len, i;
> > > > > > > int n, rate;
> > > > > > >
> > > > > > > @@ -343,15 +410,25 @@ static void
> > > > > > > hsw_audio_codec_enable(struct
> > > > > > drm_connector *connector,
> > > > > > > DRM_ERROR("invalid port: %d\n", port);
> > > > > > > rate = 0;
> > > > > > > }
> > > > > > > - n = audio_config_get_n(adjusted_mode, rate);
> > > > > > > + n = audio_config_get_n(intel_crtc, adjusted_mode,
> > > rate);
> > > > > > > if (n != 0)
> > > > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > > > + tmp = audio_config_setup_n_reg(intel_crtc, n,
> > > tmp);
> > > > > > > else
> > > > > > > DRM_DEBUG_KMS("no suitable N value is
> found\n");
> > > > > > > }
> > > > > > >
> > > > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > > >
> > > > > > > + /* setup m value for DP */
> > > > > > > + if (intel_crtc_has_type(intel_crtc->config,
> > > > > > > +INTEL_OUTPUT_DP))
> > > {
> > > > > > > + m = audio_config_get_m(intel_crtc, rate);
> > > > > > > + if (m != 0) {
> > > > > > > + tmp =
> > > I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > > > + tmp = audio_config_setup_m_reg(intel_crtc,
> > > m, tmp);
> > > > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe),
> > > tmp);
> > > > > > > + }
> > > > > > > + }
> > > > > > > +
> > > > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > > > }
> > > > > > >
> > > > > > > @@ -637,7 +714,7 @@ static int
> > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > struct drm_display_mode *mode;
> > > > > > > struct i915_audio_component *acomp = dev_priv-
> >audio_component;
> > > > > > > enum pipe pipe = INVALID_PIPE;
> > > > > > > - u32 tmp;
> > > > > > > + u32 tmp, m;
> > > > > > > int n;
> > > > > > > int err = 0;
> > > > > > >
> > > > > > > @@ -645,7 +722,8 @@ static int
> > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > if (!IS_SKYLAKE(dev_priv) &&
> > > > > > > !IS_KABYLAKE(dev_priv) &&
> > > > > > > !IS_BROADWELL(dev_priv) &&
> > > > > > > - !IS_HASWELL(dev_priv))
> > > > > > > + !IS_HASWELL(dev_priv) &&
> > > > > > > + !IS_BROXTON(dev_priv))
> > > > > > > return 0;
> > > > > >
> > > > > > HAS_DDI perhaps?
> > > > >
> > > > > Do you mean we should add "&& HAS_DDI"?
> > > > > Could you please give me more details?
> > > > >
> > > > > Regards,
> > > > > Libin
> > > > >
> > > > > >
> > > > > > >
> > > > > > > mutex_lock(&dev_priv->av_mutex); @@ -653,7 +731,8 @@
> > > > > > > static int
> > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > intel_encoder = dev_priv->dig_port_map[port];
> > > > > > > /* intel_encoder might be NULL for DP MST */
> > > > > > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > > > > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > > > > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > > > > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > > > > > DRM_DEBUG_KMS("no valid port %c\n",
> port_name(port));
> > > > > > > err = -ENODEV;
> > > > > > > goto unlock;
> > > > > > > @@ -681,7 +760,7 @@ static int
> > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > goto unlock;
> > > > > > > }
> > > > > > >
> > > > > > > - n = audio_config_get_n(mode, rate);
> > > > > > > + n = audio_config_get_n(crtc, mode, rate);
> > > > > > > if (n == 0) {
> > > > > > > DRM_DEBUG_KMS("Using automatic mode for N
> value on
> > > > > > port %c\n",
> > > > > > > port_name(port));
> > > > > > > @@ -693,8 +772,17 @@ static int
> > > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > >
> > > > > > > /* 3. set the N/CTS/M */
> > > > > > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > > > + /* setup m value for DP */
> > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > > + m = audio_config_get_m(crtc, rate);
> > > > > > > + if (m == 0)
> > > > > > > + goto unlock;
> > > > > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > > > > + }
> > > > > > >
> > > > > > > unlock:
> > > > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > > > --
> > > > > > > 1.9.1
> > > > > >
> > > > > > --
> > > > > > Ville Syrjälä
> > > > > > Intel OTC
> > >
> > > --
> > > Ville Syrjälä
> > > Intel OTC
>
> --
> Ville Syrjälä
> Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH] drm/i915: set proper N/M in modeset
2016-08-04 6:31 ` Yang, Libin
@ 2016-08-04 6:36 ` Ville Syrjälä
0 siblings, 0 replies; 23+ messages in thread
From: Ville Syrjälä @ 2016-08-04 6:36 UTC (permalink / raw)
To: Yang, Libin
Cc: 'tiwai@suse.de', Vetter, Daniel,
'libin.yang@linux.intel.com',
'intel-gfx@lists.freedesktop.org'
On Thu, Aug 04, 2016 at 06:31:19AM +0000, Yang, Libin wrote:
> Hi Ville,
>
> > -----Original Message-----
> > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > Sent: Thursday, August 4, 2016 2:24 PM
> > To: Yang, Libin <libin.yang@intel.com>
> > Cc: 'libin.yang@linux.intel.com' <libin.yang@linux.intel.com>; 'intel-
> > gfx@lists.freedesktop.org' <intel-gfx@lists.freedesktop.org>;
> > 'jani.nikula@linux.intel.com' <jani.nikula@linux.intel.com>; Vetter, Daniel
> > <daniel.vetter@intel.com>; 'tiwai@suse.de' <tiwai@suse.de>
> > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> >
> > On Thu, Aug 04, 2016 at 06:04:10AM +0000, Yang, Libin wrote:
> > > Hi Ville,
> > >
> > > > -----Original Message-----
> > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > Sent: Thursday, August 4, 2016 1:39 PM
> > > > To: Yang, Libin <libin.yang@intel.com>
> > > > Cc: 'libin.yang@linux.intel.com' <libin.yang@linux.intel.com>;
> > > > 'intel- gfx@lists.freedesktop.org'
> > > > <intel-gfx@lists.freedesktop.org>;
> > > > 'jani.nikula@linux.intel.com' <jani.nikula@linux.intel.com>; Vetter,
> > > > Daniel <daniel.vetter@intel.com>; 'tiwai@suse.de' <tiwai@suse.de>
> > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > >
> > > > On Thu, Aug 04, 2016 at 02:48:54AM +0000, Yang, Libin wrote:
> > > > > Hi Ville,
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Yang, Libin
> > > > > > Sent: Tuesday, August 2, 2016 9:59 PM
> > > > > > To: Ville Syrjälä <ville.syrjala@linux.intel.com>;
> > > > > > libin.yang@linux.intel.com
> > > > > > Cc: intel-gfx@lists.freedesktop.org;
> > > > > > jani.nikula@linux.intel.com; Vetter, Daniel
> > > > > > <daniel.vetter@intel.com>; tiwai@suse.de
> > > > > > Subject: RE: [PATCH] drm/i915: set proper N/M in modeset
> > > > > >
> > > > > > Hi Ville
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > > > > Sent: Tuesday, August 2, 2016 6:47 PM
> > > > > > > To: libin.yang@linux.intel.com
> > > > > > > Cc: intel-gfx@lists.freedesktop.org;
> > > > > > > jani.nikula@linux.intel.com; Vetter, Daniel
> > > > > > > <daniel.vetter@intel.com>; tiwai@suse.de; Yang, Libin
> > > > > > > <libin.yang@intel.com>
> > > > > > > Subject: Re: [PATCH] drm/i915: set proper N/M in modeset
> > > > > > >
> > > > > > > On Tue, Aug 02, 2016 at 09:35:10AM +0800,
> > > > > > > libin.yang@linux.intel.com
> > > > > > wrote:
> > > > > > > > From: Libin Yang <libin.yang@linux.intel.com>
> > > > > > > >
> > > > > > > > When modeset occurs and the LS_CLK is set to some special
> > > > > > > > values in DP mode, the N/M need to be set manually if audio is
> > playing.
> > > > > > > >
> > > > > > > > The relationship of Maud and Naud is expressed in the
> > > > > > > > following
> > > > > > > > equation:
> > > > > > > > Maud/Naud = 512 * fs / f_LS_Clk
> > > > > > > >
> > > > > > > > Please refer VESA DisplayPort Standard spec for details.
> > > > > > > >
> > > > > > > > Also, the patch applies
> > > > > > > > commit 7e8275c2f2bb ("drm/i915: set proper N/CTS in
> > > > > > > > modeset") to APL platform.
> > > > > > > >
> > > > > > > > Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
> > > > > > > > ---
> > > > > > > > drivers/gpu/drm/i915/i915_reg.h | 6 ++
> > > > > > > > drivers/gpu/drm/i915/intel_audio.c | 122
> > > > > > > > +++++++++++++++++++++++++++++++------
> > > > > > > > 2 files changed, 111 insertions(+), 17 deletions(-)
> > > > > > > >
> > > > > > > > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > > > b/drivers/gpu/drm/i915/i915_reg.h index 8bfde75..2f9d00e
> > > > > > > > 100644
> > > > > > > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > > > > > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > > > > > > @@ -7351,6 +7351,12 @@ enum {
> > > > > > > > #define _HSW_AUD_CONFIG_B 0x65100
> > > > > > > > #define HSW_AUD_CFG(pipe) _MMIO_PIPE(pipe,
> > > > > > > _HSW_AUD_CONFIG_A, _HSW_AUD_CONFIG_B)
> > > > > > > >
> > > > > > > > +#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
> > > > > > > > +#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
> > > > > > > > +#define HSW_AUD_M_CTS_ENABLE(pipe)
> > > > _MMIO_PIPE(pipe,
> > > > > > > _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
> > > > > > > > +#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
> > > > > > > > +#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
> > > > > > > > +
> > > > > > > > #define _HSW_AUD_MISC_CTRL_A 0x65010
> > > > > > > > #define _HSW_AUD_MISC_CTRL_B 0x65110
> > > > > > > > #define HSW_AUD_MISC_CTRL(pipe) _MMIO_PIPE(pipe,
> > > > > > > _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
> > > > > > > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > > b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > > index 6700a7b..de55ecf 100644
> > > > > > > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > > > > > > @@ -98,6 +98,22 @@ static const struct {
> > > > > > > > { 192000, TMDS_297M, 20480, 247500 }, };
> > > > > > > >
> > > > > > > > +#define LC_540M 540000
> > > > > > > > +#define LC_162M 162000
> > > > > > >
> > > > > > > Do we have some explanation why 2.7 doesn't need M/N
> > > > > > > programming, but
> > > > > > > 1.62 and 5.4 do?
> > > > > >
> > > > > > I didn't use 2.7 because I can't find a mode using 2.7. So I can't do the
> > test.
> > > > > > 5.4 is for 4K and 1.62 is for 1080p.
> > > > > >
> > > > > > >
> > > > > > > And I see you're only doing this on HSW+. Earlier platforms
> > > > > > > don't need
> > > > this?
> > > > > >
> > > > > > We are not supporting earlier platforms and I'm not sure whether
> > > > > > the old platforms supports 4K DP or not.
> > > > > >
> > > > > > >
> > > > > > > > +static const struct {
> > > > > > > > + int sample_rate;
> > > > > > > > + int clock;
> > > > > > > > + int n;
> > > > > > > > + int m;
> > > > > > >
> > > > > > > Can save a bit of space by using u16 for m and n.
> > > > > >
> > > > > > OK, I will do it in next version.
> > > > > >
> > > > > > >
> > > > > > > > +} aud_nm[] = {
> > > > > > > > + {48000, LC_540M, 5625, 256},`
> > > > > > > > + {44100, LC_540M, 9375, 392},
> > > > > > > > + {32000, LC_540M, 16875, 512},
> > > > > > > > + {48000, LC_162M, 3375, 512},
> > > > > > > > + {44100, LC_162M, 5625, 784},
> > > > > > > > + {32000, LC_162M, 10125, 1024 };
> > > > > > >
> > > > > > > The numbers look good, but what about other sample rates? For
> > > > > > > HDMI we go up to 192kHz, why not for DP?
> > > > > >
> > > > > > Our test only includes 32K, 44.1K and 48K :) I will add the
> > > > > > support if you think we should.
> > > > >
> > > > > I will not add 192KHz, 96KHz and etc rate support as based on my
> > > > > test these rate will be not used in DP. It will be converted to 48KHz.
> > > >
> > > > How about basing that decision on what's actually allowed by the driver?
> > > > I can do 96kHz DP audio on my HSW just fine here. So clearly if the
> > > > display supports it, there is nothing on the ALSA side that would
> > > > prevent it from being used.
> > >
> > > For 96KHz, audio will convert to 48KHz. You can try to print the
> > > sample rate in i915_audio_component_sync_audio_rate(). So we can't
> > > test it for the real 96kHz.
> >
> > Wrong.
> >
> > # grep rate /proc/asound/HDMI/eld#0.0
> > sad0_rates [0x4e0] 32000 44100 48000 96000
> >
> > # grep rate /proc/asound/HDMI/pcm3p/sub0/hw_params
> > rate: 96000 (96000/1)
> >
> > [drm:i915_audio_component_sync_audio_rate] sample rate 96000 kHz
>
> Interesting, maybe my monitor doesn't support. And my driver will convert
> it to 48KHz.
>
> >
> > >
> > > In DP spec, table 2-50 only says 48kHz, 32kHz, 44.1kHz, 384kHz and 768kHz.
> >
> > That table is just for informative purposes. The values are the ones you get
> > from the formula. And the ELD can contain exactly the same SADs as with
> > HDMI, so all the same sample rates can be used.
>
> Yes. I will add the other sample rates support. But these date will not be
> test as I can't play 96KHz audio with hardware support here.
Yeah, we can't always test all the combinations. Just have to go on
faith that it works out ;)
>
> Regards,
> Libin
>
> >
> > > However, the latter two sample rates is not supported in audio driver
> > > and can't be tested so far. 88kHz, 96kHz and 192kHz cannot be tested, either.
> > >
> > > Regards,
> > > Libin
> > >
> > > >
> > > > >
> > > > > >
> > > > > > >
> > > > > > > > +
> > > > > > > > /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
> > > > > > > > static
> > > > > > > > u32 audio_config_hdmi_pixel_clock(const struct
> > > > > > > > drm_display_mode
> > > > > > > > *adjusted_mode) { @@ -121,20 +137,50 @@ static u32
> > > > > > > > audio_config_hdmi_pixel_clock(const struct drm_display_mode
> > > > *adjusted
> > > > > > > > return hdmi_audio_clock[i].config; }
> > > > > > > >
> > > > > > > > -static int audio_config_get_n(const struct drm_display_mode
> > > > > > > > *mode, int rate)
> > > > > > > > +static int audio_config_get_n(struct intel_crtc *crtc,
> > > > > > > > + const struct drm_display_mode
> > > > *adjusted_mode,
> > > > > > > > + int rate)
> > > > > > > > +{
> > > > > > > > + int i;
> > > > > > > > +
> > > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
> > > > > > > > + for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > > > > + if ((rate == aud_ncts[i].sample_rate) &&
> > > > > > > > + (adjusted_mode->clock ==
> > > > aud_ncts[i].clock)) {
> > > > > > > > + return aud_ncts[i].n;
> > > > > > > > + }
> > > > > > > > + }
> > > > > > > > + }
> > > > > > > > +
> > > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > > > > + (crtc->config->port_clock ==
> > > > aud_nm[i].clock))
> > > > > > > {
> > > > > > > > + return aud_nm[i].n;
> > > > > > > > + }
> > > > > > > > + }
> > > > > > > > + }
> > > > > > > > + return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static int audio_config_get_m(struct intel_crtc *crtc, int
> > > > > > > > +rate)
> > > > > > > > {
> > > > > > > > int i;
> > > > > > > >
> > > > > > > > - for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
> > > > > > > > - if ((rate == aud_ncts[i].sample_rate) &&
> > > > > > > > - (mode->clock == aud_ncts[i].clock)) {
> > > > > > > > - return aud_ncts[i].n;
> > > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > > > + for (i = 0; i < ARRAY_SIZE(aud_nm); i++) {
> > > > > > > > + if ((rate == aud_nm[i].sample_rate) &&
> > > > > > > > + (crtc->config->port_clock ==
> > > > aud_nm[i].clock))
> > > > > > > {
> > > > > > > > + return aud_nm[i].m;
> > > > > > > > + }
> > > > > > > > }
> > > > > > > > }
> > > > > > > > +
> > > > > > > > return 0;
> > > > > > > > }
> > > > > > > >
> > > > > > > > -static uint32_t audio_config_setup_n_reg(int n, uint32_t
> > > > > > > > val)
> > > > > > > > +static uint32_t audio_config_setup_n_reg(struct intel_crtc *crtc,
> > > > > > > > + int n, uint32_t val)
> > > > > > > > {
> > > > > > > > int n_low, n_up;
> > > > > > > > uint32_t tmp = val;
> > > > > > > > @@ -145,17 +191,38 @@ static uint32_t
> > > > > > > > audio_config_setup_n_reg(int n,
> > > > > > > uint32_t val)
> > > > > > > > tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
> > > > > > > > (n_low << AUD_CONFIG_LOWER_N_SHIFT) |
> > > > > > > > AUD_CONFIG_N_PROG_ENABLE);
> > > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > > > + tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > > > > > > > + return tmp;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static uint32_t audio_config_setup_m_reg(struct intel_crtc *crtc,
> > > > > > > > + int m, uint32_t val)
> > > > > > > > +{
> > > > > > > > + uint32_t tmp = val;
> > > > > > > > +
> > > > > > > > + if (!intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > > > + return 0;
> > > > > > > > +
> > > > > > > > + tmp |= m;
> > > > > > > > + tmp |= AUD_M_CTS_M_VALUE_INDEX;
> > > > > > > > + tmp |= AUD_M_CTS_M_PROG_ENABLE;
> > > > > > > > +
> > > > > > > > return tmp;
> > > > > > > > }
> > > > > > > >
> > > > > > > > /* check whether N/CTS/M need be set manually */ static
> > > > > > > > bool audio_rate_need_prog(struct intel_crtc *crtc,
> > > > > > > > - const struct drm_display_mode
> > *mode)
> > > > > > > > + const struct drm_display_mode
> > > > > > > *adjusted_mode)
> > > > > > > > {
> > > > > > > > - if (((mode->clock == TMDS_297M) ||
> > > > > > > > - (mode->clock == TMDS_296M)) &&
> > > > > > > > + if (((adjusted_mode->clock == TMDS_297M) ||
> > > > > > > > + (adjusted_mode->clock == TMDS_296M)) &&
> > > > > > > > intel_crtc_has_type(crtc->config,
> > INTEL_OUTPUT_HDMI))
> > > > > > > > return true;
> > > > > > > > + else if (((crtc->config->port_clock == LC_540M) ||
> > > > > > > > + (crtc->config->port_clock == LC_162M)) &&
> > > > > > > > + intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP))
> > > > > > > > + return true;
> > > > > > > > else
> > > > > > > > return false;
> > > > > > > > }
> > > > > > > > @@ -287,7 +354,7 @@ static void
> > > > > > > > hsw_audio_codec_enable(struct
> > > > > > > drm_connector *connector,
> > > > > > > > struct intel_digital_port *intel_dig_port =
> > > > > > > > enc_to_dig_port(&encoder->base);
> > > > > > > > enum port port = intel_dig_port->port;
> > > > > > > > - uint32_t tmp;
> > > > > > > > + uint32_t tmp, m;
> > > > > > > > int len, i;
> > > > > > > > int n, rate;
> > > > > > > >
> > > > > > > > @@ -343,15 +410,25 @@ static void
> > > > > > > > hsw_audio_codec_enable(struct
> > > > > > > drm_connector *connector,
> > > > > > > > DRM_ERROR("invalid port: %d\n", port);
> > > > > > > > rate = 0;
> > > > > > > > }
> > > > > > > > - n = audio_config_get_n(adjusted_mode, rate);
> > > > > > > > + n = audio_config_get_n(intel_crtc, adjusted_mode,
> > > > rate);
> > > > > > > > if (n != 0)
> > > > > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > > > > + tmp = audio_config_setup_n_reg(intel_crtc, n,
> > > > tmp);
> > > > > > > > else
> > > > > > > > DRM_DEBUG_KMS("no suitable N value is
> > found\n");
> > > > > > > > }
> > > > > > > >
> > > > > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > > > >
> > > > > > > > + /* setup m value for DP */
> > > > > > > > + if (intel_crtc_has_type(intel_crtc->config,
> > > > > > > > +INTEL_OUTPUT_DP))
> > > > {
> > > > > > > > + m = audio_config_get_m(intel_crtc, rate);
> > > > > > > > + if (m != 0) {
> > > > > > > > + tmp =
> > > > I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > > > > + tmp = audio_config_setup_m_reg(intel_crtc,
> > > > m, tmp);
> > > > > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe),
> > > > tmp);
> > > > > > > > + }
> > > > > > > > + }
> > > > > > > > +
> > > > > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > > > > }
> > > > > > > >
> > > > > > > > @@ -637,7 +714,7 @@ static int
> > > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > > struct drm_display_mode *mode;
> > > > > > > > struct i915_audio_component *acomp = dev_priv-
> > >audio_component;
> > > > > > > > enum pipe pipe = INVALID_PIPE;
> > > > > > > > - u32 tmp;
> > > > > > > > + u32 tmp, m;
> > > > > > > > int n;
> > > > > > > > int err = 0;
> > > > > > > >
> > > > > > > > @@ -645,7 +722,8 @@ static int
> > > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > > if (!IS_SKYLAKE(dev_priv) &&
> > > > > > > > !IS_KABYLAKE(dev_priv) &&
> > > > > > > > !IS_BROADWELL(dev_priv) &&
> > > > > > > > - !IS_HASWELL(dev_priv))
> > > > > > > > + !IS_HASWELL(dev_priv) &&
> > > > > > > > + !IS_BROXTON(dev_priv))
> > > > > > > > return 0;
> > > > > > >
> > > > > > > HAS_DDI perhaps?
> > > > > >
> > > > > > Do you mean we should add "&& HAS_DDI"?
> > > > > > Could you please give me more details?
> > > > > >
> > > > > > Regards,
> > > > > > Libin
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > mutex_lock(&dev_priv->av_mutex); @@ -653,7 +731,8 @@
> > > > > > > > static int
> > > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > > intel_encoder = dev_priv->dig_port_map[port];
> > > > > > > > /* intel_encoder might be NULL for DP MST */
> > > > > > > > if (!intel_encoder || !intel_encoder->base.crtc ||
> > > > > > > > - intel_encoder->type != INTEL_OUTPUT_HDMI) {
> > > > > > > > + ((intel_encoder->type != INTEL_OUTPUT_HDMI) &&
> > > > > > > > + (intel_encoder->type != INTEL_OUTPUT_DP))) {
> > > > > > > > DRM_DEBUG_KMS("no valid port %c\n",
> > port_name(port));
> > > > > > > > err = -ENODEV;
> > > > > > > > goto unlock;
> > > > > > > > @@ -681,7 +760,7 @@ static int
> > > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > > goto unlock;
> > > > > > > > }
> > > > > > > >
> > > > > > > > - n = audio_config_get_n(mode, rate);
> > > > > > > > + n = audio_config_get_n(crtc, mode, rate);
> > > > > > > > if (n == 0) {
> > > > > > > > DRM_DEBUG_KMS("Using automatic mode for N
> > value on
> > > > > > > port %c\n",
> > > > > > > > port_name(port));
> > > > > > > > @@ -693,8 +772,17 @@ static int
> > > > > > > > i915_audio_component_sync_audio_rate(struct device *dev,
> > > > > > > >
> > > > > > > > /* 3. set the N/CTS/M */
> > > > > > > > tmp = I915_READ(HSW_AUD_CFG(pipe));
> > > > > > > > - tmp = audio_config_setup_n_reg(n, tmp);
> > > > > > > > + tmp = audio_config_setup_n_reg(crtc, n, tmp);
> > > > > > > > I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > > > > > > > + /* setup m value for DP */
> > > > > > > > + if (intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DP)) {
> > > > > > > > + m = audio_config_get_m(crtc, rate);
> > > > > > > > + if (m == 0)
> > > > > > > > + goto unlock;
> > > > > > > > + tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
> > > > > > > > + tmp = audio_config_setup_m_reg(crtc, m, tmp);
> > > > > > > > + I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
> > > > > > > > + }
> > > > > > > >
> > > > > > > > unlock:
> > > > > > > > mutex_unlock(&dev_priv->av_mutex);
> > > > > > > > --
> > > > > > > > 1.9.1
> > > > > > >
> > > > > > > --
> > > > > > > Ville Syrjälä
> > > > > > > Intel OTC
> > > >
> > > > --
> > > > Ville Syrjälä
> > > > Intel OTC
> >
> > --
> > Ville Syrjälä
> > Intel OTC
--
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2016-08-04 6:36 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-02 1:35 [PATCH] drm/i915: set proper N/M in modeset libin.yang
2016-08-02 5:30 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev2) Patchwork
2016-08-02 10:47 ` [PATCH] drm/i915: set proper N/M in modeset Ville Syrjälä
2016-08-02 13:58 ` Yang, Libin
2016-08-02 16:59 ` Ville Syrjälä
2016-08-04 5:46 ` Yang, Libin
2016-08-04 6:06 ` Ville Syrjälä
2016-08-04 6:12 ` Yang, Libin
2016-08-04 2:48 ` Yang, Libin
2016-08-04 5:39 ` Ville Syrjälä
2016-08-04 6:04 ` Yang, Libin
2016-08-04 6:23 ` Ville Syrjälä
2016-08-04 6:31 ` Yang, Libin
2016-08-04 6:36 ` Ville Syrjälä
2016-08-02 10:52 ` Jani Nikula
2016-08-02 14:00 ` Yang, Libin
2016-08-04 6:29 ` ✗ Ro.CI.BAT: failure for drm/i915: set proper N/M in modeset (rev3) Patchwork
-- strict thread matches above, loose matches on Subject: below --
2016-07-14 7:06 [PATCH] drm/i915: set proper N/M in modeset libin.yang
2016-07-28 6:44 ` Yang, Libin
2016-07-28 7:41 ` Ville Syrjälä
2016-07-29 5:54 ` Yang, Libin
2016-07-29 9:47 ` Ville Syrjälä
2016-08-01 1:31 ` Yang, Libin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox