int intel_configure_dsi_pll(struct intel_dsi *intel_dsi, struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = intel_dsi->base.base.dev->dev_private; struct drm_encoder *encoder = &(intel_dsi->base.base); struct intel_connector *intel_connector = intel_dsi->attached_connector; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_crtc_config *config = &intel_crtc->config; int ret; DRM_DEBUG_KMS("\n"); ret = intel_calculate_dsi_pll_mnp(intel_dsi, mode, &config->dsi_mnp, intel_dsi->dsi_clock_freq); if (ret < 0) return ret; /* In case of DRRS, Calculating the divider values for downclock_mode */ if (intel_connector->panel.downclock_avail && dev_priv->drrs_state.type >= SEAMLESS_DRRS_SUPPORT) { ret = intel_calculate_dsi_pll_mnp(intel_dsi, intel_connector->panel.downclock_mode, &config->dsi_mnp2, 0); if (ret < 0) return ret; } intel_configure_dsi_pll_reg(dev_priv, &config->dsi_mnp, intel_dsi, false); return 0; }
static void intel_mipi_drrs_work_fn(struct work_struct *__work) { struct intel_mipi_drrs_work *work = container_of(to_delayed_work(__work), struct intel_mipi_drrs_work, work); struct intel_encoder *intel_encoder = work->intel_encoder; struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private; struct intel_dsi_mnp *intel_dsi_mnp; struct intel_dsi *intel_dsi = NULL; struct intel_crtc *intel_crtc = NULL; struct drm_display_mode *prev_mode = NULL; bool resume_idleness_detection = false, fallback_attempt = false; int ret, retry_cnt = 3; intel_dsi = enc_to_intel_dsi(&intel_encoder->base); intel_crtc = intel_encoder->new_crtc; init: if (work->target_rr_type == DRRS_HIGH_RR) { intel_dsi_mnp = &intel_crtc->config.dsi_mnp; } else if (work->target_rr_type == DRRS_LOW_RR) { intel_dsi_mnp = &intel_crtc->config.dsi_mnp2; } else if (work->target_rr_type == DRRS_MEDIA_RR) { if (intel_calculate_dsi_pll_mnp(intel_dsi, work->target_mode, &intel_crtc->config.dsi_mnp3, 0) < 0) return; intel_dsi_mnp = &intel_crtc->config.dsi_mnp3; } else { DRM_ERROR("Unknown refreshrate_type\n"); return; } if (dev_priv->drrs_state.refresh_rate_type == DRRS_MEDIA_RR && work->target_rr_type == DRRS_HIGH_RR) resume_idleness_detection = true; retry: ret = intel_drrs_configure_dsi_pll(intel_dsi, intel_dsi_mnp); if (ret == 0) { DRM_DEBUG_KMS("cur_rr_type: %d, cur_rr: %d, target_rr_type: %d, target_rr: %d\n", dev_priv->drrs_state.refresh_rate_type, intel_crtc->base.mode.vrefresh, work->target_rr_type, work->target_mode->vrefresh); mutex_lock(&dev_priv->drrs_state.mutex); dev_priv->drrs_state.refresh_rate_type = work->target_rr_type; mutex_unlock(&dev_priv->drrs_state.mutex); DRM_INFO("Refresh Rate set to : %dHz\n", work->target_mode->vrefresh); intel_crtc->base.mode.vrefresh = work->target_mode->vrefresh; intel_crtc->base.mode.clock = work->target_mode->clock; if (resume_idleness_detection) intel_update_drrs(intel_encoder->base.dev); } else if (ret == -ETIMEDOUT && retry_cnt) { retry_cnt--; DRM_DEBUG_KMS("Retry left ... <%d>\n", retry_cnt); goto retry; } else if (ret == -EACCES && !fallback_attempt) { DRM_ERROR("Falling back to the previous DRRS state. %d->%d\n", work->target_rr_type, dev_priv->drrs_state.refresh_rate_type); mutex_lock(&dev_priv->drrs_state.mutex); dev_priv->drrs_state.target_rr_type = dev_priv->drrs_state.refresh_rate_type; mutex_unlock(&dev_priv->drrs_state.mutex); work->target_rr_type = dev_priv->drrs_state.target_rr_type; drm_mode_destroy(intel_encoder->base.dev, work->target_mode); if (work->target_rr_type == DRRS_HIGH_RR) { prev_mode = dev_priv->drrs.connector->panel.fixed_mode; resume_idleness_detection = true; } else if (work->target_rr_type == DRRS_LOW_RR) { prev_mode = dev_priv->drrs.connector->panel.downclock_mode; } else if (work->target_rr_type == DRRS_MEDIA_RR) { prev_mode = dev_priv->drrs.connector->panel.target_mode; } work->target_mode = drm_mode_duplicate(intel_encoder->base.dev, prev_mode); if (!work->target_mode) { DRM_ERROR("target mode creation failed\n"); return; } fallback_attempt = true; goto init; } else { if (fallback_attempt) DRM_ERROR("DRRS State Fallback attempt failed\n"); if (ret == -ETIMEDOUT) DRM_ERROR("TIMEDOUT in all retry attempt\n"); } drm_mode_destroy(intel_encoder->base.dev, work->target_mode); }