static enum drm_mode_status intel_dp_mst_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dp *intel_dp = intel_connector->mst_port; int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int max_rate, mode_rate, max_lanes, max_link_clock; if (drm_connector_is_unregistered(connector)) return MODE_ERROR; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; max_link_clock = intel_dp_max_link_rate(intel_dp); max_lanes = intel_dp_max_lane_count(intel_dp); max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes); mode_rate = intel_dp_link_required(mode->clock, 18); /* TODO - validate mode against available PBN for link */ if (mode->clock < 10000) return MODE_CLOCK_LOW; if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; if (mode_rate > max_rate || mode->clock > max_dotclk) return MODE_CLOCK_HIGH; return MODE_OK; }
static int intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_dp *intel_dp = &intel_mst->primary->dp; struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_digital_connector_state *intel_conn_state = to_intel_digital_connector_state(conn_state); const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; void *port = connector->port; struct link_config_limits limits; int ret; if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return -EINVAL; pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB; pipe_config->has_pch_encoder = false; if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO) pipe_config->has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, port); else pipe_config->has_audio = intel_conn_state->force_audio == HDMI_AUDIO_ON; /* * for MST we always configure max link bw - the spec doesn't * seem to suggest we should do otherwise. */ limits.min_clock = limits.max_clock = intel_dp_max_link_rate(intel_dp); limits.min_lane_count = limits.max_lane_count = intel_dp_max_lane_count(intel_dp); limits.min_bpp = intel_dp_min_bpp(pipe_config); limits.max_bpp = pipe_config->pipe_bpp; intel_dp_adjust_compliance_config(intel_dp, pipe_config, &limits); ret = intel_dp_mst_compute_link_config(encoder, pipe_config, conn_state, &limits); if (ret) return ret; pipe_config->limited_color_range = intel_dp_limited_color_range(pipe_config, conn_state); if (IS_GEN9_LP(dev_priv)) pipe_config->lane_lat_optim_mask = bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); return 0; }
static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base); struct intel_digital_port *intel_dig_port = intel_mst->primary; struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_connector *connector = to_intel_connector(conn_state->connector); struct drm_atomic_state *state = pipe_config->base.state; int bpp; int lane_count, slots; const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; int mst_pbn; bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_LIMITED_M_N); if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) return false; pipe_config->has_pch_encoder = false; bpp = 24; if (intel_dp->compliance.test_data.bpc) { bpp = intel_dp->compliance.test_data.bpc * 3; DRM_DEBUG_KMS("Setting pipe bpp to %d\n", bpp); } /* * for MST we always configure max link bw - the spec doesn't * seem to suggest we should do otherwise. */ lane_count = intel_dp_max_lane_count(intel_dp); pipe_config->lane_count = lane_count; pipe_config->pipe_bpp = bpp; pipe_config->port_clock = intel_dp_max_link_rate(intel_dp); if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, connector->port)) pipe_config->has_audio = true; mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, bpp); pipe_config->pbn = mst_pbn; slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, connector->port, mst_pbn); if (slots < 0) { DRM_DEBUG_KMS("failed finding vcpi slots:%d\n", slots); return false; } intel_link_compute_m_n(bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, &pipe_config->dp_m_n, reduce_m_n); pipe_config->dp_m_n.tu = slots; if (IS_GEN9_LP(dev_priv)) pipe_config->lane_lat_optim_mask = bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); intel_ddi_compute_min_voltage_level(dev_priv, pipe_config); return true; }