22,10 → 22,12 |
*/ |
|
#include <linux/kernel.h> |
#include <linux/component.h> |
#include <drm/i915_component.h> |
#include "intel_drv.h" |
|
#include <drm/drmP.h> |
#include <drm/drm_edid.h> |
#include "intel_drv.h" |
#include "i915_drv.h" |
|
/** |
39,7 → 41,8 |
* |
* The disable sequences must be performed before disabling the transcoder or |
* port. The enable sequences may only be performed after enabling the |
* transcoder and port, and after completed link training. |
* transcoder and port, and after completed link training. Therefore the audio |
* enable/disable sequences are part of the modeset sequence. |
* |
* The codec and controller sequences could be done either parallel or serial, |
* but generally the ELDV/PD change in the codec sequence indicates to the audio |
47,6 → 50,11 |
* co-operation between the graphics and audio drivers is handled via audio |
* related registers. (The notable exception is the power management, not |
* covered here.) |
* |
* The struct i915_audio_component is used to interact between the graphics |
* and audio drivers. The struct i915_audio_component_ops *ops in it is |
* defined in graphics driver and called in audio driver. The |
* struct i915_audio_component_audio_ops *audio_ops is called from i915 driver. |
*/ |
|
static const struct { |
53,30 → 61,56 |
int clock; |
u32 config; |
} hdmi_audio_clock[] = { |
{ DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, |
{ 25175, AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, |
{ 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ |
{ 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, |
{ 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, |
{ 27027, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, |
{ 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, |
{ 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, |
{ DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, |
{ 54054, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, |
{ 74176, AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, |
{ 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, |
{ DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, |
{ 148352, AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, |
{ 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, |
}; |
|
/* HDMI N/CTS table */ |
#define TMDS_297M 297000 |
#define TMDS_296M 296703 |
static const struct { |
int sample_rate; |
int clock; |
int n; |
int cts; |
} aud_ncts[] = { |
{ 44100, TMDS_296M, 4459, 234375 }, |
{ 44100, TMDS_297M, 4704, 247500 }, |
{ 48000, TMDS_296M, 5824, 281250 }, |
{ 48000, TMDS_297M, 5120, 247500 }, |
{ 32000, TMDS_296M, 5824, 421875 }, |
{ 32000, TMDS_297M, 3072, 222750 }, |
{ 88200, TMDS_296M, 8918, 234375 }, |
{ 88200, TMDS_297M, 9408, 247500 }, |
{ 96000, TMDS_296M, 11648, 281250 }, |
{ 96000, TMDS_297M, 10240, 247500 }, |
{ 176400, TMDS_296M, 17836, 234375 }, |
{ 176400, TMDS_297M, 18816, 247500 }, |
{ 192000, TMDS_296M, 23296, 281250 }, |
{ 192000, TMDS_297M, 20480, 247500 }, |
}; |
|
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ |
static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) |
static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted_mode) |
{ |
int i; |
|
for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { |
if (mode->clock == hdmi_audio_clock[i].clock) |
if (adjusted_mode->crtc_clock == hdmi_audio_clock[i].clock) |
break; |
} |
|
if (i == ARRAY_SIZE(hdmi_audio_clock)) { |
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); |
DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", |
adjusted_mode->crtc_clock); |
i = 1; |
} |
|
87,6 → 121,45 |
return hdmi_audio_clock[i].config; |
} |
|
static int audio_config_get_n(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; |
} |
} |
return 0; |
} |
|
static uint32_t audio_config_setup_n_reg(int n, uint32_t val) |
{ |
int n_low, n_up; |
uint32_t tmp = val; |
|
n_low = n & 0xfff; |
n_up = (n >> 12) & 0xff; |
tmp &= ~(AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK); |
tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) | |
(n_low << AUD_CONFIG_LOWER_N_SHIFT) | |
AUD_CONFIG_N_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) |
{ |
if (((mode->clock == TMDS_297M) || |
(mode->clock == TMDS_296M)) && |
intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) |
return true; |
else |
return false; |
} |
|
static bool intel_eld_uptodate(struct drm_connector *connector, |
int reg_eldv, uint32_t bits_eldv, |
int reg_elda, uint32_t bits_elda, |
135,7 → 208,7 |
|
static void g4x_audio_codec_enable(struct drm_connector *connector, |
struct intel_encoder *encoder, |
struct drm_display_mode *mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
uint8_t *eld = connector->eld; |
181,6 → 254,8 |
|
DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe)); |
|
mutex_lock(&dev_priv->av_mutex); |
|
/* Disable timestamps */ |
tmp = I915_READ(HSW_AUD_CFG(pipe)); |
tmp &= ~AUD_CONFIG_N_VALUE_INDEX; |
196,22 → 271,31 |
tmp &= ~AUDIO_ELD_VALID(pipe); |
tmp &= ~AUDIO_OUTPUT_ENABLE(pipe); |
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
|
mutex_unlock(&dev_priv->av_mutex); |
} |
|
static void hsw_audio_codec_enable(struct drm_connector *connector, |
struct intel_encoder *encoder, |
struct drm_display_mode *mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
enum pipe pipe = intel_crtc->pipe; |
struct i915_audio_component *acomp = dev_priv->audio_component; |
const uint8_t *eld = connector->eld; |
struct intel_digital_port *intel_dig_port = |
enc_to_dig_port(&encoder->base); |
enum port port = intel_dig_port->port; |
uint32_t tmp; |
int len, i; |
int n, rate; |
|
DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n", |
pipe_name(pipe), drm_eld_size(eld)); |
|
mutex_lock(&dev_priv->av_mutex); |
|
/* Enable audio presence detect, invalidate ELD */ |
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD); |
tmp |= AUDIO_OUTPUT_ENABLE(pipe); |
243,13 → 327,32 |
/* Enable timestamps */ |
tmp = I915_READ(HSW_AUD_CFG(pipe)); |
tmp &= ~AUD_CONFIG_N_VALUE_INDEX; |
tmp &= ~AUD_CONFIG_N_PROG_ENABLE; |
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; |
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) |
tmp |= AUD_CONFIG_N_VALUE_INDEX; |
else |
tmp |= audio_config_hdmi_pixel_clock(mode); |
tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); |
|
tmp &= ~AUD_CONFIG_N_PROG_ENABLE; |
if (audio_rate_need_prog(intel_crtc, adjusted_mode)) { |
if (!acomp) |
rate = 0; |
else if (port >= PORT_A && port <= PORT_E) |
rate = acomp->aud_sample_rate[port]; |
else { |
DRM_ERROR("invalid port: %d\n", port); |
rate = 0; |
} |
n = audio_config_get_n(adjusted_mode, rate); |
if (n != 0) |
tmp = audio_config_setup_n_reg(n, tmp); |
else |
DRM_DEBUG_KMS("no suitable N value is found\n"); |
} |
|
I915_WRITE(HSW_AUD_CFG(pipe), tmp); |
|
mutex_unlock(&dev_priv->av_mutex); |
} |
|
static void ilk_audio_codec_disable(struct intel_encoder *encoder) |
267,6 → 370,9 |
DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n", |
port_name(port), pipe_name(pipe)); |
|
if (WARN_ON(port == PORT_A)) |
return; |
|
if (HAS_PCH_IBX(dev_priv->dev)) { |
aud_config = IBX_AUD_CFG(pipe); |
aud_cntrl_st2 = IBX_AUD_CNTL_ST2; |
288,12 → 394,7 |
tmp |= AUD_CONFIG_N_VALUE_INDEX; |
I915_WRITE(aud_config, tmp); |
|
if (WARN_ON(!port)) { |
eldv = IBX_ELD_VALID(PORT_B) | IBX_ELD_VALID(PORT_C) | |
IBX_ELD_VALID(PORT_D); |
} else { |
eldv = IBX_ELD_VALID(port); |
} |
|
/* Invalidate ELD */ |
tmp = I915_READ(aud_cntrl_st2); |
303,7 → 404,7 |
|
static void ilk_audio_codec_enable(struct drm_connector *connector, |
struct intel_encoder *encoder, |
struct drm_display_mode *mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = connector->dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
323,6 → 424,9 |
DRM_DEBUG_KMS("Enable audio codec on port %c, pipe %c, %u bytes ELD\n", |
port_name(port), pipe_name(pipe), drm_eld_size(eld)); |
|
if (WARN_ON(port == PORT_A)) |
return; |
|
/* |
* FIXME: We're supposed to wait for vblank here, but we have vblanks |
* disabled during the mode set. The proper fix would be to push the |
347,12 → 451,7 |
aud_cntrl_st2 = CPT_AUD_CNTRL_ST2; |
} |
|
if (WARN_ON(!port)) { |
eldv = IBX_ELD_VALID(PORT_B) | IBX_ELD_VALID(PORT_C) | |
IBX_ELD_VALID(PORT_D); |
} else { |
eldv = IBX_ELD_VALID(port); |
} |
|
/* Invalidate ELD */ |
tmp = I915_READ(aud_cntrl_st2); |
382,7 → 481,7 |
if (intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DISPLAYPORT)) |
tmp |= AUD_CONFIG_N_VALUE_INDEX; |
else |
tmp |= audio_config_hdmi_pixel_clock(mode); |
tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); |
I915_WRITE(aud_config, tmp); |
} |
|
397,12 → 496,15 |
{ |
struct drm_encoder *encoder = &intel_encoder->base; |
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); |
struct drm_display_mode *mode = &crtc->config.adjusted_mode; |
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
struct drm_connector *connector; |
struct drm_device *dev = encoder->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct i915_audio_component *acomp = dev_priv->audio_component; |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
enum port port = intel_dig_port->port; |
|
connector = drm_select_eld(encoder, mode); |
connector = drm_select_eld(encoder); |
if (!connector) |
return; |
|
417,26 → 519,37 |
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) |
connector->eld[5] |= (1 << 2); |
|
connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; |
connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; |
|
if (dev_priv->display.audio_codec_enable) |
dev_priv->display.audio_codec_enable(connector, intel_encoder, mode); |
dev_priv->display.audio_codec_enable(connector, intel_encoder, |
adjusted_mode); |
|
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) |
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); |
} |
|
/** |
* intel_audio_codec_disable - Disable the audio codec for HD audio |
* @encoder: encoder on which to disable audio |
* @intel_encoder: encoder on which to disable audio |
* |
* The disable sequences must be performed before disabling the transcoder or |
* port. |
*/ |
void intel_audio_codec_disable(struct intel_encoder *encoder) |
void intel_audio_codec_disable(struct intel_encoder *intel_encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_encoder *encoder = &intel_encoder->base; |
struct drm_device *dev = encoder->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct i915_audio_component *acomp = dev_priv->audio_component; |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
enum port port = intel_dig_port->port; |
|
if (dev_priv->display.audio_codec_disable) |
dev_priv->display.audio_codec_disable(encoder); |
dev_priv->display.audio_codec_disable(intel_encoder); |
|
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) |
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); |
} |
|
/** |
461,3 → 574,214 |
dev_priv->display.audio_codec_disable = ilk_audio_codec_disable; |
} |
} |
|
static void i915_audio_component_get_power(struct device *dev) |
{ |
intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO); |
} |
|
static void i915_audio_component_put_power(struct device *dev) |
{ |
intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO); |
} |
|
static void i915_audio_component_codec_wake_override(struct device *dev, |
bool enable) |
{ |
struct drm_i915_private *dev_priv = dev_to_i915(dev); |
u32 tmp; |
|
if (!IS_SKYLAKE(dev_priv)) |
return; |
|
/* |
* Enable/disable generating the codec wake signal, overriding the |
* internal logic to generate the codec wake to controller. |
*/ |
tmp = I915_READ(HSW_AUD_CHICKENBIT); |
tmp &= ~SKL_AUD_CODEC_WAKE_SIGNAL; |
I915_WRITE(HSW_AUD_CHICKENBIT, tmp); |
usleep_range(1000, 1500); |
|
if (enable) { |
tmp = I915_READ(HSW_AUD_CHICKENBIT); |
tmp |= SKL_AUD_CODEC_WAKE_SIGNAL; |
I915_WRITE(HSW_AUD_CHICKENBIT, tmp); |
usleep_range(1000, 1500); |
} |
} |
|
/* Get CDCLK in kHz */ |
static int i915_audio_component_get_cdclk_freq(struct device *dev) |
{ |
struct drm_i915_private *dev_priv = dev_to_i915(dev); |
int ret; |
|
if (WARN_ON_ONCE(!HAS_DDI(dev_priv))) |
return -ENODEV; |
|
intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); |
ret = dev_priv->display.get_display_clock_speed(dev_priv->dev); |
|
intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); |
|
return ret; |
} |
|
static int i915_audio_component_sync_audio_rate(struct device *dev, |
int port, int rate) |
{ |
struct drm_i915_private *dev_priv = dev_to_i915(dev); |
struct drm_device *drm_dev = dev_priv->dev; |
struct intel_encoder *intel_encoder; |
struct intel_digital_port *intel_dig_port; |
struct intel_crtc *crtc; |
struct drm_display_mode *mode; |
struct i915_audio_component *acomp = dev_priv->audio_component; |
enum pipe pipe = -1; |
u32 tmp; |
int n; |
|
/* HSW, BDW SKL need this fix */ |
if (!IS_SKYLAKE(dev_priv) && |
!IS_BROADWELL(dev_priv) && |
!IS_HASWELL(dev_priv)) |
return 0; |
|
mutex_lock(&dev_priv->av_mutex); |
/* 1. get the pipe */ |
for_each_intel_encoder(drm_dev, intel_encoder) { |
if (intel_encoder->type != INTEL_OUTPUT_HDMI) |
continue; |
intel_dig_port = enc_to_dig_port(&intel_encoder->base); |
if (port == intel_dig_port->port) { |
crtc = to_intel_crtc(intel_encoder->base.crtc); |
if (!crtc) { |
DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__); |
continue; |
} |
pipe = crtc->pipe; |
break; |
} |
} |
|
if (pipe == INVALID_PIPE) { |
DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port)); |
mutex_unlock(&dev_priv->av_mutex); |
return -ENODEV; |
} |
DRM_DEBUG_KMS("pipe %c connects port %c\n", |
pipe_name(pipe), port_name(port)); |
mode = &crtc->config->base.adjusted_mode; |
|
/* port must be valid now, otherwise the pipe will be invalid */ |
acomp->aud_sample_rate[port] = rate; |
|
/* 2. check whether to set the N/CTS/M manually or not */ |
if (!audio_rate_need_prog(crtc, mode)) { |
tmp = I915_READ(HSW_AUD_CFG(pipe)); |
tmp &= ~AUD_CONFIG_N_PROG_ENABLE; |
I915_WRITE(HSW_AUD_CFG(pipe), tmp); |
mutex_unlock(&dev_priv->av_mutex); |
return 0; |
} |
|
n = audio_config_get_n(mode, rate); |
if (n == 0) { |
DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n", |
port_name(port)); |
tmp = I915_READ(HSW_AUD_CFG(pipe)); |
tmp &= ~AUD_CONFIG_N_PROG_ENABLE; |
I915_WRITE(HSW_AUD_CFG(pipe), tmp); |
mutex_unlock(&dev_priv->av_mutex); |
return 0; |
} |
|
/* 3. set the N/CTS/M */ |
tmp = I915_READ(HSW_AUD_CFG(pipe)); |
tmp = audio_config_setup_n_reg(n, tmp); |
I915_WRITE(HSW_AUD_CFG(pipe), tmp); |
|
mutex_unlock(&dev_priv->av_mutex); |
return 0; |
} |
|
static const struct i915_audio_component_ops i915_audio_component_ops = { |
.owner = THIS_MODULE, |
.get_power = i915_audio_component_get_power, |
.put_power = i915_audio_component_put_power, |
.codec_wake_override = i915_audio_component_codec_wake_override, |
.get_cdclk_freq = i915_audio_component_get_cdclk_freq, |
.sync_audio_rate = i915_audio_component_sync_audio_rate, |
}; |
|
static int i915_audio_component_bind(struct device *i915_dev, |
struct device *hda_dev, void *data) |
{ |
struct i915_audio_component *acomp = data; |
struct drm_i915_private *dev_priv = dev_to_i915(i915_dev); |
int i; |
|
if (WARN_ON(acomp->ops || acomp->dev)) |
return -EEXIST; |
|
drm_modeset_lock_all(dev_priv->dev); |
acomp->ops = &i915_audio_component_ops; |
acomp->dev = i915_dev; |
BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS); |
for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++) |
acomp->aud_sample_rate[i] = 0; |
dev_priv->audio_component = acomp; |
drm_modeset_unlock_all(dev_priv->dev); |
|
return 0; |
} |
|
static void i915_audio_component_unbind(struct device *i915_dev, |
struct device *hda_dev, void *data) |
{ |
struct i915_audio_component *acomp = data; |
struct drm_i915_private *dev_priv = dev_to_i915(i915_dev); |
|
drm_modeset_lock_all(dev_priv->dev); |
acomp->ops = NULL; |
acomp->dev = NULL; |
dev_priv->audio_component = NULL; |
drm_modeset_unlock_all(dev_priv->dev); |
} |
|
static const struct component_ops i915_audio_component_bind_ops = { |
.bind = i915_audio_component_bind, |
.unbind = i915_audio_component_unbind, |
}; |
|
/** |
* i915_audio_component_init - initialize and register the audio component |
* @dev_priv: i915 device instance |
* |
* This will register with the component framework a child component which |
* will bind dynamically to the snd_hda_intel driver's corresponding master |
* component when the latter is registered. During binding the child |
* initializes an instance of struct i915_audio_component which it receives |
* from the master. The master can then start to use the interface defined by |
* this struct. Each side can break the binding at any point by deregistering |
* its own component after which each side's component unbind callback is |
* called. |
* |
* We ignore any error during registration and continue with reduced |
* functionality (i.e. without HDMI audio). |
*/ |
void i915_audio_component_init(struct drm_i915_private *dev_priv) |
{ |
} |
|
/** |
* i915_audio_component_cleanup - deregister the audio component |
* @dev_priv: i915 device instance |
* |
* Deregisters the audio component, breaking any existing binding to the |
* corresponding snd_hda_intel driver's master component. |
*/ |
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv) |
{ |
} |