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);
}