31,6 → 31,7 |
#include <linux/delay.h> |
#include <linux/hdmi.h> |
#include <drm/drmP.h> |
#include <drm/drm_atomic_helper.h> |
#include <drm/drm_crtc.h> |
#include <drm/drm_edid.h> |
#include "intel_drv.h" |
112,17 → 113,18 |
} |
} |
|
static u32 hsw_infoframe_data_reg(enum hdmi_infoframe_type type, |
static u32 hsw_dip_data_reg(struct drm_i915_private *dev_priv, |
enum transcoder cpu_transcoder, |
struct drm_i915_private *dev_priv) |
enum hdmi_infoframe_type type, |
int i) |
{ |
switch (type) { |
case HDMI_INFOFRAME_TYPE_AVI: |
return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder); |
return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i); |
case HDMI_INFOFRAME_TYPE_SPD: |
return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder); |
return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i); |
case HDMI_INFOFRAME_TYPE_VENDOR: |
return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder); |
return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i); |
default: |
DRM_DEBUG_DRIVER("unknown info frame type %d\n", type); |
return 0; |
173,10 → 175,14 |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
u32 val = I915_READ(VIDEO_DIP_CTL); |
|
if (VIDEO_DIP_PORT(intel_dig_port->port) == (val & VIDEO_DIP_PORT_MASK)) |
return val & VIDEO_DIP_ENABLE; |
if ((val & VIDEO_DIP_ENABLE) == 0) |
return false; |
|
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->port)) |
return false; |
|
return val & (VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_SPD); |
} |
|
static void ibx_write_infoframe(struct drm_encoder *encoder, |
222,10 → 228,19 |
struct drm_device *dev = encoder->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
u32 val = I915_READ(reg); |
|
return val & VIDEO_DIP_ENABLE; |
if ((val & VIDEO_DIP_ENABLE) == 0) |
return false; |
|
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->port)) |
return false; |
|
return val & (VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
} |
|
static void cpt_write_infoframe(struct drm_encoder *encoder, |
277,7 → 292,12 |
int reg = TVIDEO_DIP_CTL(intel_crtc->pipe); |
u32 val = I915_READ(reg); |
|
return val & VIDEO_DIP_ENABLE; |
if ((val & VIDEO_DIP_ENABLE) == 0) |
return false; |
|
return val & (VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
} |
|
static void vlv_write_infoframe(struct drm_encoder *encoder, |
323,10 → 343,19 |
struct drm_device *dev = encoder->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); |
u32 val = I915_READ(reg); |
|
return val & VIDEO_DIP_ENABLE; |
if ((val & VIDEO_DIP_ENABLE) == 0) |
return false; |
|
if ((val & VIDEO_DIP_PORT_MASK) != VIDEO_DIP_PORT(intel_dig_port->port)) |
return false; |
|
return val & (VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
} |
|
static void hsw_write_infoframe(struct drm_encoder *encoder, |
337,14 → 366,13 |
struct drm_device *dev = encoder->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); |
u32 data_reg; |
int i; |
u32 val = I915_READ(ctl_reg); |
|
data_reg = hsw_infoframe_data_reg(type, |
intel_crtc->config.cpu_transcoder, |
dev_priv); |
data_reg = hsw_dip_data_reg(dev_priv, cpu_transcoder, type, 0); |
if (data_reg == 0) |
return; |
|
353,12 → 381,14 |
|
mmiowb(); |
for (i = 0; i < len; i += 4) { |
I915_WRITE(data_reg + i, *data); |
I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder, |
type, i >> 2), *data); |
data++; |
} |
/* Write every possible data byte to force correct ECC calculation. */ |
for (; i < VIDEO_DIP_DATA_SIZE; i += 4) |
I915_WRITE(data_reg + i, 0); |
I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder, |
type, i >> 2), 0); |
mmiowb(); |
|
val |= hsw_infoframe_enable(type); |
371,11 → 401,12 |
struct drm_device *dev = encoder->dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
u32 ctl_reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder); |
u32 val = I915_READ(ctl_reg); |
|
return val & (VIDEO_DIP_ENABLE_AVI_HSW | VIDEO_DIP_ENABLE_SPD_HSW | |
VIDEO_DIP_ENABLE_VS_HSW); |
return val & (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW | |
VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | |
VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW); |
} |
|
/* |
418,7 → 449,7 |
} |
|
static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
425,9 → 456,6 |
union hdmi_infoframe frame; |
int ret; |
|
/* Set user selected PAR to incoming mode's member */ |
adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio; |
|
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, |
adjusted_mode); |
if (ret < 0) { |
436,7 → 464,7 |
} |
|
if (intel_hdmi->rgb_quant_range_selectable) { |
if (intel_crtc->config.limited_color_range) |
if (intel_crtc->config->limited_color_range) |
frame.avi.quantization_range = |
HDMI_QUANTIZATION_RANGE_LIMITED; |
else |
465,7 → 493,7 |
|
static void |
intel_hdmi_set_hdmi_infoframe(struct drm_encoder *encoder, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
union hdmi_infoframe frame; |
int ret; |
480,7 → 508,7 |
|
static void g4x_set_infoframes(struct drm_encoder *encoder, |
bool enable, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
505,7 → 533,13 |
if (!enable) { |
if (!(val & VIDEO_DIP_ENABLE)) |
return; |
val &= ~VIDEO_DIP_ENABLE; |
if (port != (val & VIDEO_DIP_PORT_MASK)) { |
DRM_DEBUG_KMS("video DIP still enabled on port %c\n", |
(val & VIDEO_DIP_PORT_MASK) >> 29); |
return; |
} |
val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_SPD); |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
return; |
513,9 → 547,9 |
|
if (port != (val & VIDEO_DIP_PORT_MASK)) { |
if (val & VIDEO_DIP_ENABLE) { |
val &= ~VIDEO_DIP_ENABLE; |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
DRM_DEBUG_KMS("video DIP already enabled on port %c\n", |
(val & VIDEO_DIP_PORT_MASK) >> 29); |
return; |
} |
val &= ~VIDEO_DIP_PORT_MASK; |
val |= port; |
522,7 → 556,8 |
} |
|
val |= VIDEO_DIP_ENABLE; |
val &= ~VIDEO_DIP_ENABLE_VENDOR; |
val &= ~(VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_SPD); |
|
I915_WRITE(reg, val); |
POSTING_READ(reg); |
532,9 → 567,100 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
} |
|
static bool hdmi_sink_is_deep_color(struct drm_encoder *encoder) |
{ |
struct drm_device *dev = encoder->dev; |
struct drm_connector *connector; |
|
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
|
/* |
* HDMI cloning is only supported on g4x which doesn't |
* support deep color or GCP infoframes anyway so no |
* need to worry about multiple HDMI sinks here. |
*/ |
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
if (connector->encoder == encoder) |
return connector->display_info.bpc > 8; |
|
return false; |
} |
|
/* |
* Determine if default_phase=1 can be indicated in the GCP infoframe. |
* |
* From HDMI specification 1.4a: |
* - The first pixel of each Video Data Period shall always have a pixel packing phase of 0 |
* - The first pixel following each Video Data Period shall have a pixel packing phase of 0 |
* - The PP bits shall be constant for all GCPs and will be equal to the last packing phase |
* - The first pixel following every transition of HSYNC or VSYNC shall have a pixel packing |
* phase of 0 |
*/ |
static bool gcp_default_phase_possible(int pipe_bpp, |
const struct drm_display_mode *mode) |
{ |
unsigned int pixels_per_group; |
|
switch (pipe_bpp) { |
case 30: |
/* 4 pixels in 5 clocks */ |
pixels_per_group = 4; |
break; |
case 36: |
/* 2 pixels in 3 clocks */ |
pixels_per_group = 2; |
break; |
case 48: |
/* 1 pixel in 2 clocks */ |
pixels_per_group = 1; |
break; |
default: |
/* phase information not relevant for 8bpc */ |
return false; |
} |
|
return mode->crtc_hdisplay % pixels_per_group == 0 && |
mode->crtc_htotal % pixels_per_group == 0 && |
mode->crtc_hblank_start % pixels_per_group == 0 && |
mode->crtc_hblank_end % pixels_per_group == 0 && |
mode->crtc_hsync_start % pixels_per_group == 0 && |
mode->crtc_hsync_end % pixels_per_group == 0 && |
((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0 || |
mode->crtc_htotal/2 % pixels_per_group == 0); |
} |
|
static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder) |
{ |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); |
u32 reg, val = 0; |
|
if (HAS_DDI(dev_priv)) |
reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder); |
else if (IS_VALLEYVIEW(dev_priv)) |
reg = VLV_TVIDEO_DIP_GCP(crtc->pipe); |
else if (HAS_PCH_SPLIT(dev_priv->dev)) |
reg = TVIDEO_DIP_GCP(crtc->pipe); |
else |
return false; |
|
/* Indicate color depth whenever the sink supports deep color */ |
if (hdmi_sink_is_deep_color(encoder)) |
val |= GCP_COLOR_INDICATION; |
|
/* Enable default_phase whenever the display mode is suitably aligned */ |
if (gcp_default_phase_possible(crtc->config->pipe_bpp, |
&crtc->config->base.adjusted_mode)) |
val |= GCP_DEFAULT_PHASE_ENABLE; |
|
I915_WRITE(reg, val); |
|
return val != 0; |
} |
|
static void ibx_set_infoframes(struct drm_encoder *encoder, |
bool enable, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
552,7 → 678,9 |
if (!enable) { |
if (!(val & VIDEO_DIP_ENABLE)) |
return; |
val &= ~VIDEO_DIP_ENABLE; |
val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
return; |
559,19 → 687,21 |
} |
|
if (port != (val & VIDEO_DIP_PORT_MASK)) { |
if (val & VIDEO_DIP_ENABLE) { |
val &= ~VIDEO_DIP_ENABLE; |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
} |
WARN(val & VIDEO_DIP_ENABLE, |
"DIP already enabled on port %c\n", |
(val & VIDEO_DIP_PORT_MASK) >> 29); |
val &= ~VIDEO_DIP_PORT_MASK; |
val |= port; |
} |
|
val |= VIDEO_DIP_ENABLE; |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_GCP); |
val &= ~(VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
|
if (intel_hdmi_set_gcp_infoframe(encoder)) |
val |= VIDEO_DIP_ENABLE_GCP; |
|
I915_WRITE(reg, val); |
POSTING_READ(reg); |
|
582,7 → 712,7 |
|
static void cpt_set_infoframes(struct drm_encoder *encoder, |
bool enable, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
598,7 → 728,9 |
if (!enable) { |
if (!(val & VIDEO_DIP_ENABLE)) |
return; |
val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI); |
val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
return; |
607,8 → 739,11 |
/* Set both together, unset both together: see the spec. */ |
val |= VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI; |
val &= ~(VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_GCP); |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
|
if (intel_hdmi_set_gcp_infoframe(encoder)) |
val |= VIDEO_DIP_ENABLE_GCP; |
|
I915_WRITE(reg, val); |
POSTING_READ(reg); |
|
619,7 → 754,7 |
|
static void vlv_set_infoframes(struct drm_encoder *encoder, |
bool enable, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
637,7 → 772,9 |
if (!enable) { |
if (!(val & VIDEO_DIP_ENABLE)) |
return; |
val &= ~VIDEO_DIP_ENABLE; |
val &= ~(VIDEO_DIP_ENABLE | VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
return; |
644,19 → 781,21 |
} |
|
if (port != (val & VIDEO_DIP_PORT_MASK)) { |
if (val & VIDEO_DIP_ENABLE) { |
val &= ~VIDEO_DIP_ENABLE; |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
} |
WARN(val & VIDEO_DIP_ENABLE, |
"DIP already enabled on port %c\n", |
(val & VIDEO_DIP_PORT_MASK) >> 29); |
val &= ~VIDEO_DIP_PORT_MASK; |
val |= port; |
} |
|
val |= VIDEO_DIP_ENABLE; |
val &= ~(VIDEO_DIP_ENABLE_AVI | VIDEO_DIP_ENABLE_VENDOR | |
VIDEO_DIP_ENABLE_GAMUT | VIDEO_DIP_ENABLE_GCP); |
val &= ~(VIDEO_DIP_ENABLE_AVI | |
VIDEO_DIP_ENABLE_VENDOR | VIDEO_DIP_ENABLE_GAMUT | |
VIDEO_DIP_ENABLE_SPD | VIDEO_DIP_ENABLE_GCP); |
|
if (intel_hdmi_set_gcp_infoframe(encoder)) |
val |= VIDEO_DIP_ENABLE_GCP; |
|
I915_WRITE(reg, val); |
POSTING_READ(reg); |
|
667,24 → 806,28 |
|
static void hsw_set_infoframes(struct drm_encoder *encoder, |
bool enable, |
struct drm_display_mode *adjusted_mode) |
const struct drm_display_mode *adjusted_mode) |
{ |
struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); |
u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config.cpu_transcoder); |
u32 reg = HSW_TVIDEO_DIP_CTL(intel_crtc->config->cpu_transcoder); |
u32 val = I915_READ(reg); |
|
assert_hdmi_port_disabled(intel_hdmi); |
|
val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW | |
VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW | |
VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW); |
|
if (!enable) { |
I915_WRITE(reg, 0); |
I915_WRITE(reg, val); |
POSTING_READ(reg); |
return; |
} |
|
val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_GCP_HSW | |
VIDEO_DIP_ENABLE_VS_HSW | VIDEO_DIP_ENABLE_GMP_HSW); |
if (intel_hdmi_set_gcp_infoframe(encoder)) |
val |= VIDEO_DIP_ENABLE_GCP_HSW; |
|
I915_WRITE(reg, val); |
POSTING_READ(reg); |
700,23 → 843,23 |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; |
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
u32 hdmi_val; |
|
hdmi_val = SDVO_ENCODING_HDMI; |
if (!HAS_PCH_SPLIT(dev)) |
hdmi_val |= intel_hdmi->color_range; |
if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) |
hdmi_val |= HDMI_COLOR_RANGE_16_235; |
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
hdmi_val |= SDVO_HSYNC_ACTIVE_HIGH; |
|
if (crtc->config.pipe_bpp > 24) |
if (crtc->config->pipe_bpp > 24) |
hdmi_val |= HDMI_COLOR_FORMAT_12bpc; |
else |
hdmi_val |= SDVO_COLOR_FORMAT_8bpc; |
|
if (crtc->config.has_hdmi_sink) |
if (crtc->config->has_hdmi_sink) |
hdmi_val |= HDMI_MODE_SELECT_HDMI; |
|
if (HAS_PCH_CPT(dev)) |
759,7 → 902,7 |
} |
|
static void intel_hdmi_get_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
struct drm_device *dev = encoder->base.dev; |
792,7 → 935,7 |
tmp & HDMI_COLOR_RANGE_16_235) |
pipe_config->limited_color_range = true; |
|
pipe_config->adjusted_mode.flags |= flags; |
pipe_config->base.adjusted_mode.flags |= flags; |
|
if ((tmp & SDVO_COLOR_FORMAT_MASK) == HDMI_COLOR_FORMAT_12bpc) |
dotclock = pipe_config->port_clock * 2 / 3; |
799,59 → 942,147 |
else |
dotclock = pipe_config->port_clock; |
|
if (pipe_config->pixel_multiplier) |
dotclock /= pipe_config->pixel_multiplier; |
|
if (HAS_PCH_SPLIT(dev_priv->dev)) |
ironlake_check_encoder_dotclock(pipe_config, dotclock); |
|
pipe_config->adjusted_mode.crtc_clock = dotclock; |
pipe_config->base.adjusted_mode.crtc_clock = dotclock; |
} |
|
static void intel_enable_hdmi(struct intel_encoder *encoder) |
static void intel_enable_hdmi_audio(struct intel_encoder *encoder) |
{ |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
|
WARN_ON(!crtc->config->has_hdmi_sink); |
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", |
pipe_name(crtc->pipe)); |
intel_audio_codec_enable(encoder); |
} |
|
static void g4x_enable_hdmi(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
u32 temp; |
u32 enable_bits = SDVO_ENABLE; |
|
if (intel_crtc->config.has_audio) |
enable_bits |= SDVO_AUDIO_ENABLE; |
temp = I915_READ(intel_hdmi->hdmi_reg); |
|
temp |= SDVO_ENABLE; |
if (crtc->config->has_audio) |
temp |= SDVO_AUDIO_ENABLE; |
|
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
if (crtc->config->has_audio) |
intel_enable_hdmi_audio(encoder); |
} |
|
static void ibx_enable_hdmi(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
u32 temp; |
|
temp = I915_READ(intel_hdmi->hdmi_reg); |
|
/* HW workaround for IBX, we need to move the port to transcoder A |
* before disabling it, so restore the transcoder select bit here. */ |
if (HAS_PCH_IBX(dev)) |
enable_bits |= SDVO_PIPE_SEL(intel_crtc->pipe); |
temp |= SDVO_ENABLE; |
if (crtc->config->has_audio) |
temp |= SDVO_AUDIO_ENABLE; |
|
/* HW workaround, need to toggle enable bit off and on for 12bpc, but |
* we do this anyway which shows more stable in testing. |
/* |
* HW workaround, need to write this twice for issue |
* that may result in first write getting masked. |
*/ |
if (HAS_PCH_SPLIT(dev)) { |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
/* |
* HW workaround, need to toggle enable bit off and on |
* for 12bpc with pixel repeat. |
* |
* FIXME: BSpec says this should be done at the end of |
* of the modeset sequence, so not sure if this isn't too soon. |
*/ |
if (crtc->config->pipe_bpp > 24 && |
crtc->config->pixel_multiplier > 1) { |
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
/* |
* HW workaround, need to write this twice for issue |
* that may result in first write getting masked. |
*/ |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
} |
|
temp |= enable_bits; |
if (crtc->config->has_audio) |
intel_enable_hdmi_audio(encoder); |
} |
|
static void cpt_enable_hdmi(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
enum pipe pipe = crtc->pipe; |
u32 temp; |
|
temp = I915_READ(intel_hdmi->hdmi_reg); |
|
temp |= SDVO_ENABLE; |
if (crtc->config->has_audio) |
temp |= SDVO_AUDIO_ENABLE; |
|
/* |
* WaEnableHDMI8bpcBefore12bpc:snb,ivb |
* |
* The procedure for 12bpc is as follows: |
* 1. disable HDMI clock gating |
* 2. enable HDMI with 8bpc |
* 3. enable HDMI with 12bpc |
* 4. enable HDMI clock gating |
*/ |
|
if (crtc->config->pipe_bpp > 24) { |
I915_WRITE(TRANS_CHICKEN1(pipe), |
I915_READ(TRANS_CHICKEN1(pipe)) | |
TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE); |
|
temp &= ~SDVO_COLOR_FORMAT_MASK; |
temp |= SDVO_COLOR_FORMAT_8bpc; |
} |
|
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
/* HW workaround, need to write this twice for issue that may result |
* in first write getting masked. |
*/ |
if (HAS_PCH_SPLIT(dev)) { |
if (crtc->config->pipe_bpp > 24) { |
temp &= ~SDVO_COLOR_FORMAT_MASK; |
temp |= HDMI_COLOR_FORMAT_12bpc; |
|
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
I915_WRITE(TRANS_CHICKEN1(pipe), |
I915_READ(TRANS_CHICKEN1(pipe)) & |
~TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE); |
} |
|
if (intel_crtc->config.has_audio) { |
WARN_ON(!intel_crtc->config.has_hdmi_sink); |
DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n", |
pipe_name(intel_crtc->pipe)); |
intel_audio_codec_enable(encoder); |
if (crtc->config->has_audio) |
intel_enable_hdmi_audio(encoder); |
} |
} |
|
static void vlv_enable_hdmi(struct intel_encoder *encoder) |
{ |
864,61 → 1095,63 |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
u32 temp; |
u32 enable_bits = SDVO_ENABLE | SDVO_AUDIO_ENABLE; |
|
if (crtc->config.has_audio) |
intel_audio_codec_disable(encoder); |
|
temp = I915_READ(intel_hdmi->hdmi_reg); |
|
/* HW workaround for IBX, we need to move the port to transcoder A |
* before disabling it. */ |
if (HAS_PCH_IBX(dev)) { |
struct drm_crtc *crtc = encoder->base.crtc; |
int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; |
temp &= ~(SDVO_ENABLE | SDVO_AUDIO_ENABLE); |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
if (temp & SDVO_PIPE_B_SELECT) { |
/* |
* HW workaround for IBX, we need to move the port |
* to transcoder A after disabling it to allow the |
* matching DP port to be enabled on transcoder A. |
*/ |
if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) { |
temp &= ~SDVO_PIPE_B_SELECT; |
temp |= SDVO_ENABLE; |
/* |
* HW workaround, need to write this twice for issue |
* that may result in first write getting masked. |
*/ |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
/* Again we need to write this twice. */ |
temp &= ~SDVO_ENABLE; |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
|
/* Transcoder selection bits only update |
* effectively on vblank. */ |
if (crtc) |
intel_wait_for_vblank(dev, pipe); |
else |
msleep(50); |
} |
} |
|
/* HW workaround, need to toggle enable bit off and on for 12bpc, but |
* we do this anyway which shows more stable in testing. |
*/ |
if (HAS_PCH_SPLIT(dev)) { |
I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE); |
POSTING_READ(intel_hdmi->hdmi_reg); |
intel_hdmi->set_infoframes(&encoder->base, false, NULL); |
} |
|
temp &= ~enable_bits; |
static void g4x_disable_hdmi(struct intel_encoder *encoder) |
{ |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
|
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
if (crtc->config->has_audio) |
intel_audio_codec_disable(encoder); |
|
/* HW workaround, need to write this twice for issue that may result |
* in first write getting masked. |
*/ |
if (HAS_PCH_SPLIT(dev)) { |
I915_WRITE(intel_hdmi->hdmi_reg, temp); |
POSTING_READ(intel_hdmi->hdmi_reg); |
intel_disable_hdmi(encoder); |
} |
|
static void pch_disable_hdmi(struct intel_encoder *encoder) |
{ |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
|
if (crtc->config->has_audio) |
intel_audio_codec_disable(encoder); |
} |
|
static int hdmi_portclock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) |
static void pch_post_disable_hdmi(struct intel_encoder *encoder) |
{ |
intel_disable_hdmi(encoder); |
} |
|
static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) |
{ |
struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
|
if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev)) |
930,39 → 1163,74 |
} |
|
static enum drm_mode_status |
hdmi_port_clock_valid(struct intel_hdmi *hdmi, |
int clock, bool respect_dvi_limit) |
{ |
struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
|
if (clock < 25000) |
return MODE_CLOCK_LOW; |
if (clock > hdmi_port_clock_limit(hdmi, respect_dvi_limit)) |
return MODE_CLOCK_HIGH; |
|
/* BXT DPLL can't generate 223-240 MHz */ |
if (IS_BROXTON(dev) && clock > 223333 && clock < 240000) |
return MODE_CLOCK_RANGE; |
|
/* CHV DPLL can't generate 216-240 MHz */ |
if (IS_CHERRYVIEW(dev) && clock > 216000 && clock < 240000) |
return MODE_CLOCK_RANGE; |
|
return MODE_OK; |
} |
|
static enum drm_mode_status |
intel_hdmi_mode_valid(struct drm_connector *connector, |
struct drm_display_mode *mode) |
{ |
int clock = mode->clock; |
struct intel_hdmi *hdmi = intel_attached_hdmi(connector); |
struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
enum drm_mode_status status; |
int clock; |
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
return MODE_NO_DBLESCAN; |
|
clock = mode->clock; |
if (mode->flags & DRM_MODE_FLAG_DBLCLK) |
clock *= 2; |
|
if (clock > hdmi_portclock_limit(intel_attached_hdmi(connector), |
true)) |
return MODE_CLOCK_HIGH; |
if (clock < 20000) |
return MODE_CLOCK_LOW; |
/* check if we can do 8bpc */ |
status = hdmi_port_clock_valid(hdmi, clock, true); |
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
return MODE_NO_DBLESCAN; |
/* if we can't do 8bpc we may still be able to do 12bpc */ |
if (!HAS_GMCH_DISPLAY(dev) && status != MODE_OK) |
status = hdmi_port_clock_valid(hdmi, clock * 3 / 2, true); |
|
return MODE_OK; |
return status; |
} |
|
static bool hdmi_12bpc_possible(struct intel_crtc *crtc) |
static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) |
{ |
struct drm_device *dev = crtc->base.dev; |
struct drm_device *dev = crtc_state->base.crtc->dev; |
struct drm_atomic_state *state; |
struct intel_encoder *encoder; |
struct drm_connector *connector; |
struct drm_connector_state *connector_state; |
int count = 0, count_hdmi = 0; |
int i; |
|
if (HAS_GMCH_DISPLAY(dev)) |
return false; |
|
for_each_intel_encoder(dev, encoder) { |
if (encoder->new_crtc != crtc) |
state = crtc_state->base.state; |
|
for_each_connector_in_state(state, connector, connector_state, i) { |
if (connector_state->crtc != crtc_state->base.crtc) |
continue; |
|
encoder = to_intel_encoder(connector_state->best_encoder); |
|
count_hdmi += encoder->type == INTEL_OUTPUT_HDMI; |
count++; |
} |
975,13 → 1243,13 |
} |
|
bool intel_hdmi_compute_config(struct intel_encoder *encoder, |
struct intel_crtc_config *pipe_config) |
struct intel_crtc_state *pipe_config) |
{ |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
struct drm_device *dev = encoder->base.dev; |
struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode; |
int clock_12bpc = pipe_config->adjusted_mode.crtc_clock * 3 / 2; |
int portclock_limit = hdmi_portclock_limit(intel_hdmi, false); |
struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; |
int clock_12bpc = clock_8bpc * 3 / 2; |
int desired_bpp; |
|
pipe_config->has_hdmi_sink = intel_hdmi->has_hdmi_sink; |
991,20 → 1259,20 |
|
if (intel_hdmi->color_range_auto) { |
/* See CEA-861-E - 5.1 Default Encoding Parameters */ |
if (pipe_config->has_hdmi_sink && |
drm_match_cea_mode(adjusted_mode) > 1) |
intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; |
else |
intel_hdmi->color_range = 0; |
pipe_config->limited_color_range = |
pipe_config->has_hdmi_sink && |
drm_match_cea_mode(adjusted_mode) > 1; |
} else { |
pipe_config->limited_color_range = |
intel_hdmi->limited_color_range; |
} |
|
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK) { |
pipe_config->pixel_multiplier = 2; |
clock_8bpc *= 2; |
clock_12bpc *= 2; |
} |
|
if (intel_hdmi->color_range) |
pipe_config->limited_color_range = true; |
|
if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) |
pipe_config->has_pch_encoder = true; |
|
1018,8 → 1286,8 |
* within limits. |
*/ |
if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && |
clock_12bpc <= portclock_limit && |
hdmi_12bpc_possible(encoder->new_crtc)) { |
hdmi_port_clock_valid(intel_hdmi, clock_12bpc, false) == MODE_OK && |
hdmi_12bpc_possible(pipe_config)) { |
DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); |
desired_bpp = 12*3; |
|
1028,6 → 1296,8 |
} else { |
DRM_DEBUG_KMS("picking bpc to 8 for HDMI output\n"); |
desired_bpp = 8*3; |
|
pipe_config->port_clock = clock_8bpc; |
} |
|
if (!pipe_config->bw_constrained) { |
1035,11 → 1305,15 |
pipe_config->pipe_bpp = desired_bpp; |
} |
|
if (adjusted_mode->crtc_clock > portclock_limit) { |
DRM_DEBUG_KMS("too high HDMI clock, rejecting mode\n"); |
if (hdmi_port_clock_valid(intel_hdmi, pipe_config->port_clock, |
false) != MODE_OK) { |
DRM_DEBUG_KMS("unsupported HDMI clock, rejecting mode\n"); |
return false; |
} |
|
/* Set user selected PAR to incoming mode's member */ |
adjusted_mode->picture_aspect_ratio = intel_hdmi->aspect_ratio; |
|
return true; |
} |
|
1057,24 → 1331,21 |
} |
|
static bool |
intel_hdmi_set_edid(struct drm_connector *connector) |
intel_hdmi_set_edid(struct drm_connector *connector, bool force) |
{ |
struct drm_i915_private *dev_priv = to_i915(connector->dev); |
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
struct intel_encoder *intel_encoder = |
&hdmi_to_dig_port(intel_hdmi)->base; |
enum intel_display_power_domain power_domain; |
struct edid *edid; |
struct edid *edid = NULL; |
bool connected = false; |
|
power_domain = intel_display_port_power_domain(intel_encoder); |
intel_display_power_get(dev_priv, power_domain); |
intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); |
|
if (force) |
edid = drm_get_edid(connector, |
intel_gmbus_get_adapter(dev_priv, |
intel_hdmi->ddc_bus)); |
|
intel_display_power_put(dev_priv, power_domain); |
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); |
|
to_intel_connector(connector)->detect_edid = edid; |
if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { |
1100,13 → 1371,29 |
intel_hdmi_detect(struct drm_connector *connector, bool force) |
{ |
enum drm_connector_status status; |
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
struct drm_i915_private *dev_priv = to_i915(connector->dev); |
bool live_status = false; |
unsigned int try; |
|
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
connector->base.id, connector->name); |
|
intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); |
|
for (try = 0; !live_status && try < 9; try++) { |
if (try) |
msleep(10); |
live_status = intel_digital_port_connected(dev_priv, |
hdmi_to_dig_port(intel_hdmi)); |
} |
|
if (!live_status) |
DRM_DEBUG_KMS("Live status not up!"); |
|
intel_hdmi_unset_edid(connector); |
|
if (intel_hdmi_set_edid(connector)) { |
if (intel_hdmi_set_edid(connector, live_status)) { |
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); |
|
hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; |
1114,6 → 1401,8 |
} else |
status = connector_status_disconnected; |
|
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); |
|
return status; |
} |
|
1130,7 → 1419,7 |
if (connector->status != connector_status_connected) |
return; |
|
intel_hdmi_set_edid(connector); |
intel_hdmi_set_edid(connector, true); |
hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI; |
} |
|
1196,7 → 1485,7 |
|
if (property == dev_priv->broadcast_rgb_property) { |
bool old_auto = intel_hdmi->color_range_auto; |
uint32_t old_range = intel_hdmi->color_range; |
bool old_range = intel_hdmi->limited_color_range; |
|
switch (val) { |
case INTEL_BROADCAST_RGB_AUTO: |
1204,11 → 1493,11 |
break; |
case INTEL_BROADCAST_RGB_FULL: |
intel_hdmi->color_range_auto = false; |
intel_hdmi->color_range = 0; |
intel_hdmi->limited_color_range = false; |
break; |
case INTEL_BROADCAST_RGB_LIMITED: |
intel_hdmi->color_range_auto = false; |
intel_hdmi->color_range = HDMI_COLOR_RANGE_16_235; |
intel_hdmi->limited_color_range = true; |
break; |
default: |
return -EINVAL; |
1215,7 → 1504,7 |
} |
|
if (old_auto == intel_hdmi->color_range_auto && |
old_range == intel_hdmi->color_range) |
old_range == intel_hdmi->limited_color_range) |
return 0; |
|
goto done; |
1251,13 → 1540,12 |
{ |
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); |
struct drm_display_mode *adjusted_mode = |
&intel_crtc->config.adjusted_mode; |
const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; |
|
intel_hdmi_prepare(encoder); |
|
intel_hdmi->set_infoframes(&encoder->base, |
intel_crtc->config.has_hdmi_sink, |
intel_crtc->config->has_hdmi_sink, |
adjusted_mode); |
} |
|
1269,14 → 1557,13 |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = |
to_intel_crtc(encoder->base.crtc); |
struct drm_display_mode *adjusted_mode = |
&intel_crtc->config.adjusted_mode; |
const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; |
enum dpio_channel port = vlv_dport_to_channel(dport); |
int pipe = intel_crtc->pipe; |
u32 val; |
|
/* Enable clock channels for this port */ |
mutex_lock(&dev_priv->dpio_lock); |
mutex_lock(&dev_priv->sb_lock); |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); |
val = 0; |
if (pipe) |
1299,15 → 1586,15 |
/* Program lane clock */ |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); |
mutex_unlock(&dev_priv->dpio_lock); |
mutex_unlock(&dev_priv->sb_lock); |
|
intel_hdmi->set_infoframes(&encoder->base, |
intel_crtc->config.has_hdmi_sink, |
intel_crtc->config->has_hdmi_sink, |
adjusted_mode); |
|
intel_enable_hdmi(encoder); |
g4x_enable_hdmi(encoder); |
|
vlv_wait_port_ready(dev_priv, dport); |
vlv_wait_port_ready(dev_priv, dport, 0x0); |
} |
|
static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) |
1323,7 → 1610,7 |
intel_hdmi_prepare(encoder); |
|
/* Program Tx lane resets to default */ |
mutex_lock(&dev_priv->dpio_lock); |
mutex_lock(&dev_priv->sb_lock); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), |
DPIO_PCS_TX_LANE2_RESET | |
DPIO_PCS_TX_LANE1_RESET); |
1340,9 → 1627,53 |
|
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), 0x00002000); |
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN); |
mutex_unlock(&dev_priv->dpio_lock); |
mutex_unlock(&dev_priv->sb_lock); |
} |
|
static void chv_data_lane_soft_reset(struct intel_encoder *encoder, |
bool reset) |
{ |
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); |
struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); |
enum pipe pipe = crtc->pipe; |
uint32_t val; |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); |
if (reset) |
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
else |
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); |
|
if (crtc->config->lane_count > 2) { |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); |
if (reset) |
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
else |
val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); |
} |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
if (reset) |
val &= ~DPIO_PCS_CLK_SOFT_RESET; |
else |
val |= DPIO_PCS_CLK_SOFT_RESET; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); |
|
if (crtc->config->lane_count > 2) { |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
if (reset) |
val &= ~DPIO_PCS_CLK_SOFT_RESET; |
else |
val |= DPIO_PCS_CLK_SOFT_RESET; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); |
} |
} |
|
static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder) |
{ |
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
1356,8 → 1687,21 |
|
intel_hdmi_prepare(encoder); |
|
mutex_lock(&dev_priv->dpio_lock); |
/* |
* Must trick the second common lane into life. |
* Otherwise we can't even access the PLL. |
*/ |
if (ch == DPIO_CH0 && pipe == PIPE_B) |
dport->release_cl2_override = |
!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); |
|
chv_phy_powergate_lanes(encoder, true, 0x0); |
|
mutex_lock(&dev_priv->sb_lock); |
|
/* Assert data lane reset */ |
chv_data_lane_soft_reset(encoder, true); |
|
/* program left/right clock distribution */ |
if (pipe != PIPE_B) { |
val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); |
1406,9 → 1750,42 |
val |= CHV_CMN_USEDCLKCHANNEL; |
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val); |
|
mutex_unlock(&dev_priv->dpio_lock); |
mutex_unlock(&dev_priv->sb_lock); |
} |
|
static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder) |
{ |
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; |
u32 val; |
|
mutex_lock(&dev_priv->sb_lock); |
|
/* disable left/right clock distribution */ |
if (pipe != PIPE_B) { |
val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); |
val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); |
vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); |
} else { |
val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); |
val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); |
vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); |
} |
|
mutex_unlock(&dev_priv->sb_lock); |
|
/* |
* Leave the power down bit cleared for at least one |
* lane so that chv_powergate_phy_ch() will power |
* on something when the channel is otherwise unused. |
* When the port is off and the override is removed |
* the lanes power down anyway, so otherwise it doesn't |
* really matter what the state of power down bits is |
* after this. |
*/ |
chv_phy_powergate_lanes(encoder, false, 0x0); |
} |
|
static void vlv_hdmi_post_disable(struct intel_encoder *encoder) |
{ |
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
1419,43 → 1796,23 |
int pipe = intel_crtc->pipe; |
|
/* Reset lanes to avoid HDMI flicker (VLV w/a) */ |
mutex_lock(&dev_priv->dpio_lock); |
mutex_lock(&dev_priv->sb_lock); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060); |
mutex_unlock(&dev_priv->dpio_lock); |
mutex_unlock(&dev_priv->sb_lock); |
} |
|
static void chv_hdmi_post_disable(struct intel_encoder *encoder) |
{ |
struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); |
struct drm_device *dev = encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = |
to_intel_crtc(encoder->base.crtc); |
enum dpio_channel ch = vlv_dport_to_channel(dport); |
enum pipe pipe = intel_crtc->pipe; |
u32 val; |
|
mutex_lock(&dev_priv->dpio_lock); |
mutex_lock(&dev_priv->sb_lock); |
|
/* Propagate soft reset to data lane reset */ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); |
/* Assert data lane reset */ |
chv_data_lane_soft_reset(encoder, true); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); |
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); |
val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); |
|
mutex_unlock(&dev_priv->dpio_lock); |
mutex_unlock(&dev_priv->sb_lock); |
} |
|
static void chv_hdmi_pre_enable(struct intel_encoder *encoder) |
1466,14 → 1823,13 |
struct drm_i915_private *dev_priv = dev->dev_private; |
struct intel_crtc *intel_crtc = |
to_intel_crtc(encoder->base.crtc); |
struct drm_display_mode *adjusted_mode = |
&intel_crtc->config.adjusted_mode; |
const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode; |
enum dpio_channel ch = vlv_dport_to_channel(dport); |
int pipe = intel_crtc->pipe; |
int data, i; |
int data, i, stagger; |
u32 val; |
|
mutex_lock(&dev_priv->dpio_lock); |
mutex_lock(&dev_priv->sb_lock); |
|
/* allow hardware to manage TX FIFO reset source */ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); |
1484,30 → 1840,8 |
val &= ~DPIO_LANEDESKEW_STRAP_OVRD; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); |
|
/* Deassert soft data lane reset*/ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); |
val |= CHV_PCS_REQ_SOFTRESET_EN; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); |
val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); |
val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); |
|
/* Program Tx latency optimal setting */ |
for (i = 0; i < 4; i++) { |
/* Set the latency optimal bit */ |
data = (i == 1) ? 0x0 : 0x6; |
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW11(ch, i), |
data << DPIO_FRC_LATENCY_SHFIT); |
|
/* Set the upar bit */ |
data = (i == 1) ? 0x0 : 0x1; |
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW14(ch, i), |
1515,8 → 1849,42 |
} |
|
/* Data lane stagger programming */ |
/* FIXME: Fix up value only after power analysis */ |
if (intel_crtc->config->port_clock > 270000) |
stagger = 0x18; |
else if (intel_crtc->config->port_clock > 135000) |
stagger = 0xd; |
else if (intel_crtc->config->port_clock > 67500) |
stagger = 0x7; |
else if (intel_crtc->config->port_clock > 33750) |
stagger = 0x4; |
else |
stagger = 0x2; |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); |
val |= DPIO_TX2_STAGGER_MASK(0x1f); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); |
|
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); |
val |= DPIO_TX2_STAGGER_MASK(0x1f); |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); |
|
vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch), |
DPIO_LANESTAGGER_STRAP(stagger) | |
DPIO_LANESTAGGER_STRAP_OVRD | |
DPIO_TX1_STAGGER_MASK(0x1f) | |
DPIO_TX1_STAGGER_MULT(6) | |
DPIO_TX2_STAGGER_MULT(0)); |
|
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch), |
DPIO_LANESTAGGER_STRAP(stagger) | |
DPIO_LANESTAGGER_STRAP_OVRD | |
DPIO_TX1_STAGGER_MASK(0x1f) | |
DPIO_TX1_STAGGER_MULT(7) | |
DPIO_TX2_STAGGER_MULT(5)); |
|
/* Deassert data lane reset */ |
chv_data_lane_soft_reset(encoder, false); |
|
/* Clear calc init */ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); |
val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); |
1551,12 → 1919,27 |
|
for (i = 0; i < 4; i++) { |
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); |
|
val &= ~DPIO_SWING_MARGIN000_MASK; |
val |= 102 << DPIO_SWING_MARGIN000_SHIFT; |
|
/* |
* Supposedly this value shouldn't matter when unique transition |
* scale is disabled, but in fact it does matter. Let's just |
* always program the same value and hope it's OK. |
*/ |
val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); |
val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; |
|
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); |
} |
|
/* Disable unique transition scale */ |
/* |
* The document said it needs to set bit 27 for ch0 and bit 26 |
* for ch1. Might be a typo in the doc. |
* For now, for this unique transition scale selection, set bit |
* 27 for ch0 and ch1. |
*/ |
for (i = 0; i < 4; i++) { |
val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); |
val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; |
1563,19 → 1946,6 |
vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); |
} |
|
/* Additional steps for 1200mV-0dB */ |
#if 0 |
val = vlv_dpio_read(dev_priv, pipe, VLV_TX_DW3(ch)); |
if (ch) |
val |= DPIO_TX_UNIQ_TRANS_SCALE_CH1; |
else |
val |= DPIO_TX_UNIQ_TRANS_SCALE_CH0; |
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(ch), val); |
|
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(ch), |
vlv_dpio_read(dev_priv, pipe, VLV_TX_DW2(ch)) | |
(0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT)); |
#endif |
/* Start swing calculation */ |
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); |
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; |
1585,21 → 1955,22 |
val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; |
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); |
|
/* LRC Bypass */ |
val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30); |
val |= DPIO_LRC_BYPASS; |
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, val); |
mutex_unlock(&dev_priv->sb_lock); |
|
mutex_unlock(&dev_priv->dpio_lock); |
|
intel_hdmi->set_infoframes(&encoder->base, |
intel_crtc->config.has_hdmi_sink, |
intel_crtc->config->has_hdmi_sink, |
adjusted_mode); |
|
intel_enable_hdmi(encoder); |
g4x_enable_hdmi(encoder); |
|
vlv_wait_port_ready(dev_priv, dport); |
vlv_wait_port_ready(dev_priv, dport, 0x0); |
|
/* Second common lane will stay alive on its own now */ |
if (dport->release_cl2_override) { |
chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); |
dport->release_cl2_override = false; |
} |
} |
|
static void intel_hdmi_destroy(struct drm_connector *connector) |
{ |
1609,12 → 1980,15 |
} |
|
static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
.dpms = intel_connector_dpms, |
.dpms = drm_atomic_helper_connector_dpms, |
.detect = intel_hdmi_detect, |
.force = intel_hdmi_force, |
.fill_modes = drm_helper_probe_single_connector_modes, |
.set_property = intel_hdmi_set_property, |
.atomic_get_property = intel_connector_atomic_get_property, |
.destroy = intel_hdmi_destroy, |
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
}; |
|
static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs = { |
1628,15 → 2002,6 |
}; |
|
static void |
intel_attach_aspect_ratio_property(struct drm_connector *connector) |
{ |
if (!drm_mode_create_aspect_ratio_property(connector->dev)) |
drm_object_attach_property(&connector->base, |
connector->dev->mode_config.aspect_ratio_property, |
DRM_MODE_PICTURE_ASPECT_NONE); |
} |
|
static void |
intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *connector) |
{ |
intel_attach_force_audio_property(connector); |
1655,6 → 2020,7 |
struct drm_device *dev = intel_encoder->base.dev; |
struct drm_i915_private *dev_priv = dev->dev_private; |
enum port port = intel_dig_port->port; |
uint8_t alternate_ddc_pin; |
|
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
DRM_MODE_CONNECTOR_HDMIA); |
1666,20 → 2032,55 |
|
switch (port) { |
case PORT_B: |
intel_hdmi->ddc_bus = GMBUS_PORT_DPB; |
if (IS_BROXTON(dev_priv)) |
intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; |
else |
intel_hdmi->ddc_bus = GMBUS_PIN_DPB; |
/* |
* On BXT A0/A1, sw needs to activate DDIA HPD logic and |
* interrupts to check the external panel connection. |
*/ |
if (IS_BROXTON(dev_priv) && (INTEL_REVID(dev) < BXT_REVID_B0)) |
intel_encoder->hpd_pin = HPD_PORT_A; |
else |
intel_encoder->hpd_pin = HPD_PORT_B; |
break; |
case PORT_C: |
intel_hdmi->ddc_bus = GMBUS_PORT_DPC; |
if (IS_BROXTON(dev_priv)) |
intel_hdmi->ddc_bus = GMBUS_PIN_2_BXT; |
else |
intel_hdmi->ddc_bus = GMBUS_PIN_DPC; |
intel_encoder->hpd_pin = HPD_PORT_C; |
break; |
case PORT_D: |
if (IS_CHERRYVIEW(dev)) |
intel_hdmi->ddc_bus = GMBUS_PORT_DPD_CHV; |
if (WARN_ON(IS_BROXTON(dev_priv))) |
intel_hdmi->ddc_bus = GMBUS_PIN_DISABLED; |
else if (IS_CHERRYVIEW(dev_priv)) |
intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV; |
else |
intel_hdmi->ddc_bus = GMBUS_PORT_DPD; |
intel_hdmi->ddc_bus = GMBUS_PIN_DPD; |
intel_encoder->hpd_pin = HPD_PORT_D; |
break; |
case PORT_E: |
/* On SKL PORT E doesn't have seperate GMBUS pin |
* We rely on VBT to set a proper alternate GMBUS pin. */ |
alternate_ddc_pin = |
dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin; |
switch (alternate_ddc_pin) { |
case DDC_PIN_B: |
intel_hdmi->ddc_bus = GMBUS_PIN_DPB; |
break; |
case DDC_PIN_C: |
intel_hdmi->ddc_bus = GMBUS_PIN_DPC; |
break; |
case DDC_PIN_D: |
intel_hdmi->ddc_bus = GMBUS_PIN_DPD; |
break; |
default: |
MISSING_CASE(alternate_ddc_pin); |
} |
intel_encoder->hpd_pin = HPD_PORT_E; |
break; |
case PORT_A: |
intel_encoder->hpd_pin = HPD_PORT_A; |
/* Internal port only for eDP. */ |
1719,6 → 2120,7 |
|
intel_connector_attach_encoder(intel_connector, intel_encoder); |
drm_connector_register(connector); |
intel_hdmi->attached_connector = intel_connector; |
|
/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written |
* 0xd. Failure to do so will result in spurious interrupts being |
1740,7 → 2142,7 |
if (!intel_dig_port) |
return; |
|
intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); |
intel_connector = intel_connector_alloc(); |
if (!intel_connector) { |
kfree(intel_dig_port); |
return; |
1752,7 → 2154,12 |
DRM_MODE_ENCODER_TMDS); |
|
intel_encoder->compute_config = intel_hdmi_compute_config; |
intel_encoder->disable = intel_disable_hdmi; |
if (HAS_PCH_SPLIT(dev)) { |
intel_encoder->disable = pch_disable_hdmi; |
intel_encoder->post_disable = pch_post_disable_hdmi; |
} else { |
intel_encoder->disable = g4x_disable_hdmi; |
} |
intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
intel_encoder->get_config = intel_hdmi_get_config; |
if (IS_CHERRYVIEW(dev)) { |
1760,6 → 2167,7 |
intel_encoder->pre_enable = chv_hdmi_pre_enable; |
intel_encoder->enable = vlv_enable_hdmi; |
intel_encoder->post_disable = chv_hdmi_post_disable; |
intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; |
} else if (IS_VALLEYVIEW(dev)) { |
intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; |
intel_encoder->pre_enable = vlv_hdmi_pre_enable; |
1767,7 → 2175,12 |
intel_encoder->post_disable = vlv_hdmi_post_disable; |
} else { |
intel_encoder->pre_enable = intel_hdmi_pre_enable; |
intel_encoder->enable = intel_enable_hdmi; |
if (HAS_PCH_CPT(dev)) |
intel_encoder->enable = cpt_enable_hdmi; |
else if (HAS_PCH_IBX(dev)) |
intel_encoder->enable = ibx_enable_hdmi; |
else |
intel_encoder->enable = g4x_enable_hdmi; |
} |
|
intel_encoder->type = INTEL_OUTPUT_HDMI; |