836,6 → 836,22 |
intel_hdmi_set_hdmi_infoframe(encoder, adjusted_mode); |
} |
|
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable) |
{ |
struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); |
struct i2c_adapter *adapter = |
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); |
|
if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI) |
return; |
|
DRM_DEBUG_KMS("%s DP dual mode adaptor TMDS output\n", |
enable ? "Enabling" : "Disabling"); |
|
drm_dp_dual_mode_set_tmds_output(hdmi->dp_dual_mode.type, |
adapter, enable); |
} |
|
static void intel_hdmi_prepare(struct intel_encoder *encoder) |
{ |
struct drm_device *dev = encoder->base.dev; |
845,6 → 861,8 |
const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
u32 hdmi_val; |
|
intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); |
|
hdmi_val = SDVO_ENCODING_HDMI; |
if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) |
hdmi_val |= HDMI_COLOR_RANGE_16_235; |
1143,6 → 1161,8 |
} |
|
intel_hdmi->set_infoframes(&encoder->base, false, NULL); |
|
intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); |
} |
|
static void g4x_disable_hdmi(struct intel_encoder *encoder) |
1168,27 → 1188,42 |
intel_disable_hdmi(encoder); |
} |
|
static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, bool respect_dvi_limit) |
static int intel_hdmi_source_max_tmds_clock(struct drm_i915_private *dev_priv) |
{ |
struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
|
if ((respect_dvi_limit && !hdmi->has_hdmi_sink) || IS_G4X(dev)) |
if (IS_G4X(dev_priv)) |
return 165000; |
else if (IS_HASWELL(dev) || INTEL_INFO(dev)->gen >= 8) |
else if (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8) |
return 300000; |
else |
return 225000; |
} |
|
static int hdmi_port_clock_limit(struct intel_hdmi *hdmi, |
bool respect_downstream_limits) |
{ |
struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev)); |
|
if (respect_downstream_limits) { |
if (hdmi->dp_dual_mode.max_tmds_clock) |
max_tmds_clock = min(max_tmds_clock, |
hdmi->dp_dual_mode.max_tmds_clock); |
if (!hdmi->has_hdmi_sink) |
max_tmds_clock = min(max_tmds_clock, 165000); |
} |
|
return max_tmds_clock; |
} |
|
static enum drm_mode_status |
hdmi_port_clock_valid(struct intel_hdmi *hdmi, |
int clock, bool respect_dvi_limit) |
int clock, bool respect_downstream_limits) |
{ |
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)) |
if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits)) |
return MODE_CLOCK_HIGH; |
|
/* BXT DPLL can't generate 223-240 MHz */ |
1210,11 → 1245,19 |
struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
enum drm_mode_status status; |
int clock; |
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; |
|
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
return MODE_NO_DBLESCAN; |
|
clock = mode->clock; |
|
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING) |
clock *= 2; |
|
if (clock > max_dotclk) |
return MODE_CLOCK_HIGH; |
|
if (mode->flags & DRM_MODE_FLAG_DBLCLK) |
clock *= 2; |
|
1304,7 → 1347,7 |
* within limits. |
*/ |
if (pipe_config->pipe_bpp > 8*3 && pipe_config->has_hdmi_sink && |
hdmi_port_clock_valid(intel_hdmi, clock_12bpc, false) == MODE_OK && |
hdmi_port_clock_valid(intel_hdmi, clock_12bpc, true) == MODE_OK && |
hdmi_12bpc_possible(pipe_config)) { |
DRM_DEBUG_KMS("picking bpc to 12 for HDMI output\n"); |
desired_bpp = 12*3; |
1344,10 → 1387,35 |
intel_hdmi->has_audio = false; |
intel_hdmi->rgb_quant_range_selectable = false; |
|
intel_hdmi->dp_dual_mode.type = DRM_DP_DUAL_MODE_NONE; |
intel_hdmi->dp_dual_mode.max_tmds_clock = 0; |
|
kfree(to_intel_connector(connector)->detect_edid); |
to_intel_connector(connector)->detect_edid = NULL; |
} |
|
static void |
intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector) |
{ |
struct drm_i915_private *dev_priv = to_i915(connector->dev); |
struct intel_hdmi *hdmi = intel_attached_hdmi(connector); |
struct i2c_adapter *adapter = |
intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus); |
enum drm_dp_dual_mode_type type = drm_dp_dual_mode_detect(adapter); |
|
if (type == DRM_DP_DUAL_MODE_NONE || |
type == DRM_DP_DUAL_MODE_UNKNOWN) |
return; |
|
hdmi->dp_dual_mode.type = type; |
hdmi->dp_dual_mode.max_tmds_clock = |
drm_dp_dual_mode_max_tmds_clock(type, adapter); |
|
DRM_DEBUG_KMS("DP dual mode adaptor (%s) detected (max TMDS clock: %d kHz)\n", |
drm_dp_get_dual_mode_type_name(type), |
hdmi->dp_dual_mode.max_tmds_clock); |
} |
|
static bool |
intel_hdmi_set_edid(struct drm_connector *connector, bool force) |
{ |
1363,6 → 1431,8 |
intel_gmbus_get_adapter(dev_priv, |
intel_hdmi->ddc_bus)); |
|
intel_hdmi_dp_dual_mode_detect(connector); |
|
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS); |
} |
|
2049,6 → 2119,11 |
enum port port = intel_dig_port->port; |
uint8_t alternate_ddc_pin; |
|
if (WARN(intel_dig_port->max_lanes < 4, |
"Not enough lanes (%d) for HDMI on port %c\n", |
intel_dig_port->max_lanes, port_name(port))) |
return; |
|
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, |
DRM_MODE_CONNECTOR_HDMIA); |
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs); |
2232,6 → 2307,7 |
intel_dig_port->port = port; |
intel_dig_port->hdmi.hdmi_reg = hdmi_reg; |
intel_dig_port->dp.output_reg = INVALID_MMIO_REG; |
intel_dig_port->max_lanes = 4; |
|
intel_hdmi_init_connector(intel_dig_port, intel_connector); |
} |