[RFC PATCH 15/18] drm/i915: MEDIA_RR support in DSI DRRS module

Ramalingam C
2015-06-26T14:00:39Z

Content based DRRS support is implemented in
DSI DRRS module also.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
drivers/gpu/drm/i915/intel_dsi_drrs.c | 60 +++++++++++++++++++++++++++++++--
1 file changed, 58 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dsi_drrs.c b/drivers/gpu/drm/i915/intel_dsi_drrs.c
index d4bb70a..4ff06b8 100644
--- a/drivers/gpu/drm/i915/intel_dsi_drrs.c
+++ b/drivers/gpu/drm/i915/intel_dsi_drrs.c
@@ -19,6 +19,7 @@

#include "intel_drv.h"
#include "intel_dsi.h"
+#include "intel_drrs.h"

/*
* VLV and CHV platform code
@@ -50,9 +51,19 @@ static void intel_mipi_drrs_work_fn(struct work_struct *__work)
struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
struct dsi_mnp *dsi_mnp;
struct drm_display_mode *prev_mode = NULL;
+ bool resume_idleness_detection = false;
bool fallback_attempt = false;
int ret, retry_cnt = 3;

+ if (work->target_rr_type == DRRS_MEDIA_RR) {
+ ret = dsi_drrs->ops->mnp_calculate_for_mode(
+ intel_encoder, &dsi_drrs->mnp[DRRS_MEDIA_RR],
+ drrs->connector->panel.target_mode);
+ if (ret < 0) {
+ DRM_ERROR("mnp calculation failed\n");
+ goto out;
+ }
+ }
init:
dsi_mnp = &dsi_drrs->mnp[work->target_rr_type];
DRM_DEBUG("Refresh rate Type: %d-->%d\n",
@@ -60,6 +71,10 @@ init:
work->target_rr_type);
DRM_DEBUG("Target RR: %d\n", work->target_mode->vrefresh);

+ if (drrs->drrs_state.current_rr_type == DRRS_MEDIA_RR &&
+ work->target_rr_type == DRRS_HIGH_RR)
+ resume_idleness_detection = true;
+
retry:
if (!intel_crtc || !intel_crtc->active)
goto out;
@@ -87,6 +102,11 @@ retry:

/* TODO: Update drain ladency with watermark */

+ if (resume_idleness_detection) {
+ intel_disable_idleness_drrs(drrs);
+ intel_enable_idleness_drrs(drrs);
+ }
+
} else if (ret == -ETIMEDOUT && retry_cnt) {

/* Timed out. But still attempts are allowed */
@@ -111,10 +131,14 @@ retry:
work->target_rr_type = drrs->drrs_state.target_rr_type;
drm_mode_destroy(intel_encoder->base.dev, work->target_mode);

- if (work->target_rr_type == DRRS_HIGH_RR)
+ if (work->target_rr_type == DRRS_HIGH_RR) {
prev_mode = drrs->connector->panel.fixed_mode;
- else if (work->target_rr_type == DRRS_LOW_RR)
+ resume_idleness_detection = true;
+ } else if (work->target_rr_type == DRRS_LOW_RR) {
prev_mode = drrs->connector->panel.downclock_mode;
+ } else if (work->target_rr_type == DRRS_MEDIA_RR) {
+ prev_mode = drrs->connector->panel.target_mode;
+ }

work->target_mode = drm_mode_duplicate(intel_encoder->base.dev,
prev_mode);
@@ -137,6 +161,37 @@ out:
work->work_completed = true;
}

+/*
+ * As a part of Media playback request filtering
+ * we validate the incoming request wrt deferred works
+ * of MIPI PLL programming
+ */
+bool intel_dsi_is_mp_drrs_req(struct i915_drrs *drrs,
+ struct drm_display_mode *mode)
+{
+ struct intel_dsi *intel_dsi =
+ enc_to_intel_dsi(&drrs->connector->encoder->base);
+ struct dsi_drrs *dsi_drrs = &intel_dsi->dsi_drrs;
+ struct intel_mipi_drrs_work *work = dsi_drrs->mipi_drrs_work;
+ bool ret = false;
+
+ if (work_busy(&work->work.work)) {
+ if (work->target_mode->vrefresh != mode->vrefresh ||
+ drrs->drrs_state.current_rr_type != DRRS_MEDIA_RR)
+
+ /*
+ * First condition: Deferred work is in place to change
+ * the DRRS state. Hence this call is valid Media
+ * playback DRRS request.
+ *
+ * Second Condition: Might be same as deffered work but
+ * this is from media playback request. So honor it.
+ */
+ ret = true;
+ }
+ return ret;
+}
+
/* Whether DRRS_HR_STATE is pending in the dsi deferred work */
bool intel_dsi_is_drrs_hr_state_pending(struct i915_drrs *drrs)
{
@@ -350,6 +405,7 @@ struct drrs_encoder_ops drrs_dsi_ops = {
.exit = intel_dsi_drrs_exit,
.set_drrs_state = intel_dsi_set_drrs_state,
.is_drrs_hr_state_pending = intel_dsi_is_drrs_hr_state_pending,
+ .is_mp_drrs_req = intel_dsi_is_mp_drrs_req,
};

/* Call back Function for Intel_drrs module to get the dsi func ptr */