[RFC PATCH 07/18] drm/i915: Generic eDP DRRS implementation

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

This patch Implements the generic eDP DRRS functions and registers
them with Generic DRRS state machine.

Platform specific eDP DRRS functions will be implemented and
registered with this generic eDP DRRS implementation. Hence
extending the eDP DRRS to new platform is made simple.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
drivers/gpu/drm/i915/Makefile | 1 +
drivers/gpu/drm/i915/intel_dp.c | 6 +++
drivers/gpu/drm/i915/intel_drrs.c | 2 +
drivers/gpu/drm/i915/intel_drv.h | 3 ++
drivers/gpu/drm/i915/intel_edp_drrs.c | 95 +++++++++++++++++++++++++++++++++
drivers/gpu/drm/i915/intel_edp_drrs.h | 29 ++++++++++
6 files changed, 136 insertions(+)
create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.c
create mode 100644 drivers/gpu/drm/i915/intel_edp_drrs.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4f77fb2..9a3c43f 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -56,6 +56,7 @@ i915-y += intel_audio.o \
intel_psr.o \
intel_drrs.o \
intel_dsi_drrs.o \
+ intel_edp_drrs.o \
intel_sideband.o \
intel_sprite.o
i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 738e98e..9ded4d1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1483,6 +1483,12 @@ found:
pipe_config->port_clock,
&pipe_config->dp_m_n);

+ if (intel_connector->panel.downclock_mode)
+ intel_link_compute_m_n(bpp, lane_count,
+ intel_connector->panel.downclock_mode->clock,
+ pipe_config->port_clock,
+ &pipe_config->dp_m2_n2);
+
if (IS_SKYLAKE(dev) && is_edp(intel_dp))
skl_edp_set_pll_config(pipe_config, common_rates[clock]);
else if (IS_BROXTON(dev))
diff --git a/drivers/gpu/drm/i915/intel_drrs.c b/drivers/gpu/drm/i915/intel_drrs.c
index 2a776d2..e5d8bcd 100644
--- a/drivers/gpu/drm/i915/intel_drrs.c
+++ b/drivers/gpu/drm/i915/intel_drrs.c
@@ -388,6 +388,8 @@ int intel_drrs_init(struct drm_device *dev,

if (intel_encoder->type == INTEL_OUTPUT_DSI) {
drrs->encoder_ops = get_intel_dsi_drrs_ops();
+ } else if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+ drrs->encoder_ops = get_intel_edp_drrs_ops();
} else {
DRM_ERROR("DRRS: Unsupported Encoder\n");
ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 726c31d..d5354f3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -38,6 +38,7 @@
#include <drm/drm_atomic.h>

#include "intel_drrs.h"
+#include "intel_edp_drrs.h"

/**
* _wait_for - magic (register) wait macro
@@ -758,6 +759,8 @@ struct intel_dp {
unsigned long compliance_test_type;
unsigned long compliance_test_data;
bool compliance_test_active;
+
+ struct edp_drrs_platform_ops *drrs_ops;
};

struct intel_digital_port {
diff --git a/drivers/gpu/drm/i915/intel_edp_drrs.c b/drivers/gpu/drm/i915/intel_edp_drrs.c
new file mode 100644
index 0000000..606271b
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_edp_drrs.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Authors:
+ * Ramalingam C <ramalingam.c@intel.com>
+ * Durgadoss R <durgadoss.r@intel.com>
+ */
+
+#include <linux/delay.h>
+#include <drm/i915_drm.h>
+
+#include "i915_drv.h"
+
+void intel_edp_set_drrs_state(struct i915_drrs *drrs)
+{
+ struct intel_encoder *intel_encoder = drrs->connector->encoder;
+ struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+ intel_dp->drrs_ops->set_drrs_state(intel_encoder,
+ drrs->drrs_state.target_rr_type);
+}
+
+int intel_edp_drrs_init(struct i915_drrs *drrs,
+ struct drm_display_mode *fixed_mode)
+{
+ struct intel_encoder *intel_encoder = drrs->connector->encoder;
+ struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+ struct drm_display_mode *downclock_mode;
+ int ret = -EINVAL;
+
+ if (!intel_dp->drrs_ops ||
+ !intel_dp->drrs_ops->set_drrs_state) {
+ DRM_ERROR("Required platform ops are NULL\n");
+ return ret;
+ }
+
+ if (fixed_mode->vrefresh == 0)
+ fixed_mode->vrefresh = drm_mode_vrefresh(fixed_mode);
+
+ downclock_mode = intel_find_panel_downclock(intel_encoder->base.dev,
+ fixed_mode, &drrs->connector->base);
+ if (!downclock_mode) {
+ DRM_DEBUG("No Downclock mode is found\n");
+ return ret;
+ }
+
+ if (intel_dp->drrs_ops->init) {
+ ret = intel_dp->drrs_ops->init(intel_encoder);
+ if (ret < 0)
+ return ret;
+ }
+
+ DRM_DEBUG("eDP DRRS modes:\n");
+ drm_mode_debug_printmodeline(fixed_mode);
+ drm_mode_debug_printmodeline(downclock_mode);
+
+ /* We are good to go .. */
+ intel_panel_init(&drrs->connector->panel, fixed_mode, downclock_mode);
+ drrs->connector->panel.target_mode = NULL;
+
+ drrs->drrs_state.type = SEAMLESS_DRRS_SUPPORT;
+ return ret;
+}
+
+void intel_edp_drrs_exit(struct i915_drrs *drrs)
+{
+ struct intel_encoder *intel_encoder = drrs->connector->encoder;
+ struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+ if (intel_dp->drrs_ops->exit)
+ intel_dp->drrs_ops->exit(intel_encoder);
+
+ drrs->drrs_state.type = DRRS_NOT_SUPPORTED;
+}
+
+struct drrs_encoder_ops edp_drrs_ops = {
+ .init = intel_edp_drrs_init,
+ .exit = intel_edp_drrs_exit,
+ .set_drrs_state = intel_edp_set_drrs_state,
+};
+
+/* Called by intel_drrs_init() to get ->ops for edp panel */
+struct drrs_encoder_ops *get_intel_edp_drrs_ops(void)
+{
+ return &edp_drrs_ops;
+}
diff --git a/drivers/gpu/drm/i915/intel_edp_drrs.h b/drivers/gpu/drm/i915/intel_edp_drrs.h
new file mode 100644
index 0000000..5a23f004
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_edp_drrs.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015, Intel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Author:
+ * Ramalingam C <ramalingam.c@intel.com>
+ */
+
+#ifndef INTEL_EDP_DRRS_H
+#define INTEL_EDP_DRRS_H
+
+struct intel_encoder;
+struct edp_drrs_platform_ops {
+ int (*init)(struct intel_encoder *encoder);
+ void (*exit)(struct intel_encoder *encoder);
+ int (*set_drrs_state)(struct intel_encoder *encoder,
+ enum drrs_refresh_rate_type target_rr_type);
+};
+
+extern inline struct drrs_encoder_ops *get_intel_edp_drrs_ops(void);
+#endif /* INTEL_EDP_DRRS_H */