All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/21 v2] Adding support for skylake shared scalers
@ 2015-03-21  0:04 Chandra Konduru
  2015-03-21  0:04 ` [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index() Chandra Konduru
                   ` (20 more replies)
  0 siblings, 21 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This patch enables skylake display scalers in atomic framework.
Version 2 of patch series addresses comments from Daniel and Matt.
see below for full details and also individual patch headers.
Though changes aren't big, but they trickled down into multiple
patches. So I'm sending the whole series for completeness and
also to go through round of PRTS testing.

Performed several basic test scenarios covering both panel
fitting and plane scaling scenarios. plane scaling requires
switching planes from transitional helpers to full atomic helpers
which is currently reverted in nightly. Even without full atomic
helpers, existing plane capability continues to works. Will be
sending the corresponding i-g-t tests seperately.

v2:
    -removed nested loop in drm_plane_from_index (Daniel)
    -populate crtc scaler state from hw state (Daniel)
    -added scaler id check to intel_pipe_config_compare (Daniel)
    -use single copy of scaler limits (Matt)
    -do gen checks before calling a helper (Matt)
    -use skylake_pfit_update to control skylake panel fitter(me)
	-rebased on top of Ander's v3 patch series (me)

Chandra Konduru (21):
  drm/i915: Adding drm helper function drm_plane_from_index().
  drm/i915: Register definitions for skylake scalers
  drm/i915: Enable get_colorkey functions for primary plane.
  drm/i915: skylake scaler structure definitions
  drm/i915: Initialize skylake scalers
  drm/i915: Dump scaler_state too as part of dumping crtc_state
  drm/i915: Helper function to update skylake scaling ratio.
  drm/i915: Add helper function to update scaler_users in crtc_state
  drm/i915: Add atomic function to setup scalers scalers for a crtc.
  drm/i915: Helper function to detach a scaler from a plane or crtc
  drm/i915: Ensure planes begin with no scaler.
  drm/i915: Ensure colorkey and scaling aren't enabled at same time
  drm/i915: Preserve scaler state when clearing crtc_state
  drm/i915: use current scaler state during readout_hw_state.
  drm/i915: Update scaling ratio as part of crtc_compute_config
  drm/i915: Ensure setting up scalers into staged crtc_state
  drm/i915: copy staged scaler state from drm state to crtc->config.
  drm/i915: stage panel fitting scaler request for fixed mode panel
  drm/i915: Enable skylake panel fitting using skylake shared scalers
  drm/i915: Enable skylake primary plane scaling using shared scalers
  drm/i915: Enable skylake sprite plane scaling using shared scalers

 drivers/gpu/drm/drm_crtc.c           |   22 ++
 drivers/gpu/drm/i915/i915_reg.h      |  115 ++++++++
 drivers/gpu/drm/i915/intel_atomic.c  |  161 +++++++++++
 drivers/gpu/drm/i915/intel_display.c |  490 +++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_dp.c      |    8 +
 drivers/gpu/drm/i915/intel_drv.h     |  109 ++++++++
 drivers/gpu/drm/i915/intel_sprite.c  |   95 +++++--
 include/drm/drm_crtc.h               |    1 +
 8 files changed, 942 insertions(+), 59 deletions(-)

--
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index().
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-23  9:32   ` Daniel Vetter
  2015-03-21  0:04 ` [PATCH 02/21 v2] drm/i915: Register definitions for skylake scalers Chandra Konduru
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Adding drm helper function to return plane pointer from index where
index is a returned by drm_plane_index.

v2:
-avoided nested loop by adding loop count (Daniel)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/drm_crtc.c |   22 ++++++++++++++++++++++
 include/drm/drm_crtc.h     |    1 +
 2 files changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9f970c2..b6703f4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1286,6 +1286,28 @@ unsigned int drm_plane_index(struct drm_plane *plane)
 EXPORT_SYMBOL(drm_plane_index);
 
 /**
+ * drm_plane_from_index - find the registered plane at an index
+ * @idx: index of registered plane to find for
+ *
+ * Given a plane index, return the registered plane from DRM device's
+ * list of planes with matching index.
+ */
+struct drm_plane *
+drm_plane_from_index(struct drm_device *dev, int idx)
+{
+	struct drm_plane *plane;
+	unsigned int i = 0;
+
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		if (i == idx)
+			return plane;
+		i++;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(drm_plane_from_index);
+
+/**
  * drm_plane_force_disable - Forcibly disable a plane
  * @plane: plane to disable
  *
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 7b5c661..6b30036 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1264,6 +1264,7 @@ extern int drm_plane_init(struct drm_device *dev,
 			  bool is_primary);
 extern void drm_plane_cleanup(struct drm_plane *plane);
 extern unsigned int drm_plane_index(struct drm_plane *plane);
+extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
 extern void drm_plane_force_disable(struct drm_plane *plane);
 extern int drm_plane_check_pixel_format(const struct drm_plane *plane,
 					u32 format);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 02/21 v2] drm/i915: Register definitions for skylake scalers
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
  2015-03-21  0:04 ` [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index() Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 03/21 v2] drm/i915: Enable get_colorkey functions for primary plane Chandra Konduru
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Adding register definitions for skylake scalers.
v2:
-add #define for plane selection mask (me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h |  115 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cc8ebab..6e9e58a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5094,6 +5094,121 @@ enum skl_disp_power_wells {
 #define PS_WIN_SZ(pipe)		_PIPE(pipe, _PSA_WIN_SZ, _PSB_WIN_SZ)
 #define PS_WIN_POS(pipe)	_PIPE(pipe, _PSA_WIN_POS, _PSB_WIN_POS)
 
+/*
+ * Skylake scalers
+ */
+#define _PS_1A_CTRL      0x68180
+#define _PS_2A_CTRL      0x68280
+#define _PS_1B_CTRL      0x68980
+#define _PS_2B_CTRL      0x68A80
+#define _PS_1C_CTRL      0x69180
+#define PS_SCALER_EN        (1 << 31)
+#define PS_SCALER_MODE_MASK (3 << 28)
+#define PS_SCALER_MODE_DYN  (0 << 28)
+#define PS_SCALER_MODE_HQ  (1 << 28)
+#define PS_PLANE_SEL_MASK  (7 << 25)
+#define PS_PLANE_SEL(plane) ((plane + 1) << 25)
+#define PS_FILTER_MASK         (3 << 23)
+#define PS_FILTER_MEDIUM       (0 << 23)
+#define PS_FILTER_EDGE_ENHANCE (2 << 23)
+#define PS_FILTER_BILINEAR     (3 << 23)
+#define PS_VERT3TAP            (1 << 21)
+#define PS_VERT_INT_INVERT_FIELD1 (0 << 20)
+#define PS_VERT_INT_INVERT_FIELD0 (1 << 20)
+#define PS_PWRUP_PROGRESS         (1 << 17)
+#define PS_V_FILTER_BYPASS        (1 << 8)
+#define PS_VADAPT_EN              (1 << 7)
+#define PS_VADAPT_MODE_MASK        (3 << 5)
+#define PS_VADAPT_MODE_LEAST_ADAPT (0 << 5)
+#define PS_VADAPT_MODE_MOD_ADAPT   (1 << 5)
+#define PS_VADAPT_MODE_MOST_ADAPT  (3 << 5)
+
+#define _PS_PWR_GATE_1A     0x68160
+#define _PS_PWR_GATE_2A     0x68260
+#define _PS_PWR_GATE_1B     0x68960
+#define _PS_PWR_GATE_2B     0x68A60
+#define _PS_PWR_GATE_1C     0x69160
+#define PS_PWR_GATE_DIS_OVERRIDE       (1 << 31)
+#define PS_PWR_GATE_SETTLING_TIME_32   (0 << 3)
+#define PS_PWR_GATE_SETTLING_TIME_64   (1 << 3)
+#define PS_PWR_GATE_SETTLING_TIME_96   (2 << 3)
+#define PS_PWR_GATE_SETTLING_TIME_128  (3 << 3)
+#define PS_PWR_GATE_SLPEN_8             0
+#define PS_PWR_GATE_SLPEN_16            1
+#define PS_PWR_GATE_SLPEN_24            2
+#define PS_PWR_GATE_SLPEN_32            3
+
+#define _PS_WIN_POS_1A      0x68170
+#define _PS_WIN_POS_2A      0x68270
+#define _PS_WIN_POS_1B      0x68970
+#define _PS_WIN_POS_2B      0x68A70
+#define _PS_WIN_POS_1C      0x69170
+
+#define _PS_WIN_SZ_1A       0x68174
+#define _PS_WIN_SZ_2A       0x68274
+#define _PS_WIN_SZ_1B       0x68974
+#define _PS_WIN_SZ_2B       0x68A74
+#define _PS_WIN_SZ_1C       0x69174
+
+#define _PS_VSCALE_1A       0x68184
+#define _PS_VSCALE_2A       0x68284
+#define _PS_VSCALE_1B       0x68984
+#define _PS_VSCALE_2B       0x68A84
+#define _PS_VSCALE_1C       0x69184
+
+#define _PS_HSCALE_1A       0x68190
+#define _PS_HSCALE_2A       0x68290
+#define _PS_HSCALE_1B       0x68990
+#define _PS_HSCALE_2B       0x68A90
+#define _PS_HSCALE_1C       0x69190
+
+#define _PS_VPHASE_1A       0x68188
+#define _PS_VPHASE_2A       0x68288
+#define _PS_VPHASE_1B       0x68988
+#define _PS_VPHASE_2B       0x68A88
+#define _PS_VPHASE_1C       0x69188
+
+#define _PS_HPHASE_1A       0x68194
+#define _PS_HPHASE_2A       0x68294
+#define _PS_HPHASE_1B       0x68994
+#define _PS_HPHASE_2B       0x68A94
+#define _PS_HPHASE_1C       0x69194
+
+#define _PS_ECC_STAT_1A     0x681D0
+#define _PS_ECC_STAT_2A     0x682D0
+#define _PS_ECC_STAT_1B     0x689D0
+#define _PS_ECC_STAT_2B     0x68AD0
+#define _PS_ECC_STAT_1C     0x691D0
+
+#define _ID(id, a, b) ((a) + (id)*((b)-(a)))
+#define SKL_PS_CTRL(pipe, id) _PIPE(pipe,        \
+			_ID(id, _PS_1A_CTRL, _PS_2A_CTRL),       \
+			_ID(id, _PS_1B_CTRL, _PS_2B_CTRL))
+#define SKL_PS_PWR_GATE(pipe, id) _PIPE(pipe,    \
+			_ID(id, _PS_PWR_GATE_1A, _PS_PWR_GATE_2A), \
+			_ID(id, _PS_PWR_GATE_1B, _PS_PWR_GATE_2B))
+#define SKL_PS_WIN_POS(pipe, id) _PIPE(pipe,     \
+			_ID(id, _PS_WIN_POS_1A, _PS_WIN_POS_2A), \
+			_ID(id, _PS_WIN_POS_1B, _PS_WIN_POS_2B))
+#define SKL_PS_WIN_SZ(pipe, id)  _PIPE(pipe,     \
+			_ID(id, _PS_WIN_SZ_1A, _PS_WIN_SZ_2A),   \
+			_ID(id, _PS_WIN_SZ_1B, _PS_WIN_SZ_2B))
+#define SKL_PS_VSCALE(pipe, id)  _PIPE(pipe,     \
+			_ID(id, _PS_VSCALE_1A, _PS_VSCALE_2A),   \
+			_ID(id, _PS_VSCALE_1B, _PS_VSCALE_2B))
+#define SKL_PS_HSCALE(pipe, id)  _PIPE(pipe,     \
+			_ID(id, _PS_HSCALE_1A, _PS_HSCALE_2A),   \
+			_ID(id, _PS_HSCALE_1B, _PS_HSCALE_2B))
+#define SKL_PS_VPHASE(pipe, id)  _PIPE(pipe,     \
+			_ID(id, _PS_VPHASE_1A, _PS_VPHASE_2A),   \
+			_ID(id, _PS_VPHASE_1B, _PS_VPHASE_2B))
+#define SKL_PS_HPHASE(pipe, id)  _PIPE(pipe,     \
+			_ID(id, _PS_HPHASE_1A, _PS_HPHASE_2A),   \
+			_ID(id, _PS_HPHASE_1B, _PS_HPHASE_2B))
+#define SKL_PS_ECC_STAT(pipe, id)  _PIPE(pipe,     \
+			_ID(id, _PS_ECC_STAT_1A, _PS_ECC_STAT_2A),   \
+			_ID(id, _PS_ECC_STAT_1B, _PS_ECC_STAT_2B)
+
 /* legacy palette */
 #define _LGC_PALETTE_A           0x4a000
 #define _LGC_PALETTE_B           0x4a800
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 03/21 v2] drm/i915: Enable get_colorkey functions for primary plane.
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
  2015-03-21  0:04 ` [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index() Chandra Konduru
  2015-03-21  0:04 ` [PATCH 02/21 v2] drm/i915: Register definitions for skylake scalers Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions Chandra Konduru
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Made intel_colorkey_enabled and skl_get_colorkey functions
available for primary plane.

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h    |    3 +++
 drivers/gpu/drm/i915/intel_sprite.c |    9 +++++----
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ec99046..3f7d05e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1263,6 +1263,9 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
 int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
+bool intel_colorkey_enabled(struct intel_plane *intel_plane);
+void skl_get_colorkey(struct drm_plane *drm_plane,
+                struct drm_intel_sprite_colorkey *key);
 bool intel_pipe_update_start(struct intel_crtc *crtc,
 			     uint32_t *start_vbl_count);
 void intel_pipe_update_end(struct intel_crtc *crtc, u32 start_vbl_count);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index a828736..9ee12d0 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -336,7 +336,7 @@ skl_update_colorkey(struct drm_plane *drm_plane,
 	return 0;
 }
 
-static void
+void
 skl_get_colorkey(struct drm_plane *drm_plane,
 		 struct drm_intel_sprite_colorkey *key)
 {
@@ -1068,11 +1068,12 @@ ilk_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 		key->flags = I915_SET_COLORKEY_NONE;
 }
 
-static bool colorkey_enabled(struct intel_plane *intel_plane)
+bool intel_colorkey_enabled(struct intel_plane *intel_plane)
 {
 	struct drm_intel_sprite_colorkey key;
 
-	intel_plane->get_colorkey(&intel_plane->base, &key);
+	if (intel_plane->get_colorkey)
+		intel_plane->get_colorkey(&intel_plane->base, &key);
 
 	return key.flags != I915_SET_COLORKEY_NONE;
 }
@@ -1241,7 +1242,7 @@ finish:
 	 * we can disable the primary and save power.
 	 */
 	state->hides_primary = fb != NULL && drm_rect_equals(dst, clip) &&
-		!colorkey_enabled(intel_plane);
+		!intel_colorkey_enabled(intel_plane);
 	WARN_ON(state->hides_primary && !state->visible && intel_crtc->active);
 
 	if (intel_crtc->active) {
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (2 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 03/21 v2] drm/i915: Enable get_colorkey functions for primary plane Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:13   ` Matt Roper
  2015-03-21  0:04 ` [PATCH 05/21 v2] drm/i915: Initialize skylake scalers Chandra Konduru
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

skylake scaler structure definitions. scalers live in crtc_state as
they are pipe resources. They can be used either as plane scaler or
panel fitter.

scaler assigned to either plane (for plane scaling) or crtc (for panel
fitting) is saved in scaler_id in plane_state or crtc_state respectively.

scaler_id is used instead of scaler pointer in plane or crtc state
to avoid updating scaler pointer everytime a new crtc_state is created.

v2:
-made single copy of min/max values for scalers (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h |   99 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3f7d05e..1da5087 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -256,6 +256,35 @@ struct intel_plane_state {
 	 * enable/disable the primary plane
 	 */
 	bool hides_primary;
+
+	/*
+	 * scaler_id
+	 *    = -1 : not using a scaler
+	 *    >=  0 : using a scalers
+	 *
+	 * plane requiring a scaler:
+	 *   - During check_plane, its bit is set in
+	 *     crtc_state->scaler_state.scaler_users by calling helper function
+	 *     update_scaler_users.
+	 *   - scaler_id indicates the scaler it got assigned.
+	 *
+	 * plane doesn't require a scaler:
+	 *   - this can happen when scaling is no more required or plane simply
+	 *     got disabled.
+	 *   - During check_plane, corresponding bit is reset in
+	 *     crtc_state->scaler_state.scaler_users by calling helper function
+	 *     update_scaler_users.
+	 *
+	 *   There are two scenarios:
+	 *   1. the freed up scaler is assigned to crtc or some other plane
+	 *      In this case, as part of plane programming scaler_id will be set
+	 *      to -1 using helper function detach_scalers
+	 *   2. the freed up scaler is not assigned to anyone
+	 *      In this case, as part of plane programming scaler registers will
+	 *      be reset and scaler_id will also be reset to -1 using the same
+	 *      helper function detach_scalers
+	 */
+	int scaler_id;
 };
 
 struct intel_initial_plane_config {
@@ -265,6 +294,74 @@ struct intel_initial_plane_config {
 	u32 base;
 };
 
+struct intel_scaler {
+	int id;
+	int in_use;
+	uint32_t mode;
+	uint32_t filter;
+};
+
+struct intel_crtc_scaler_state {
+#define INTEL_MAX_SCALERS 2
+#define SKL_NUM_SCALERS INTEL_MAX_SCALERS
+	/* scalers available on this crtc */
+	int num_scalers;
+	struct intel_scaler scalers[INTEL_MAX_SCALERS];
+
+	/*
+	 * scaler_users: keeps track of users requesting scalers on this crtc.
+	 *
+	 *     If a bit is set, a user is using a scaler.
+	 *     Here user can be a plane or crtc as defined below:
+	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
+	 *       bit 31    - crtc
+	 *
+	 * Instead of creating a new index to cover planes and crtc, using
+	 * existing drm_plane_index for planes which is well less than 31
+	 * planes and bit 31 for crtc. This should be fine to cover all
+	 * our platforms.
+	 *
+	 * intel_atomic_setup_scalers will setup available scalers to users
+	 * requesting scalers. It will gracefully fail if request exceeds
+	 * avilability.
+	 */
+#define SKL_CRTC_INDEX 31
+	unsigned scaler_users;
+
+	/* scaler used by crtc for panel fitting purpose */
+	int scaler_id;
+
+	/*
+	 * Supported scaling ratio is represented as a range in [min max]
+	 * variables. This range covers both up and downscaling
+	 * where scaling ratio = (dst * 100)/src.
+	 * In above range any value:
+	 *    < 100 represents downscaling coverage
+	 *    > 100 represents upscaling coverage
+	 *    = 100 represents no-scaling (i.e., 1:1)
+	 * e.g., a min value = 50 means -> supports upto 50% of original image
+	 *       a max value = 200 means -> supports upto 200% of original image
+	 *
+	 * if incoming flip requires scaling in the supported [min max] range
+	 * then requested scaling will be performed.
+	 */
+	uint32_t min_hsr;
+	uint32_t max_hsr;
+	uint32_t min_vsr;
+	uint32_t max_vsr;
+	uint32_t min_hvsr;
+	uint32_t max_hvsr;
+
+	uint32_t min_src_w;
+	uint32_t max_src_w;
+	uint32_t min_src_h;
+	uint32_t max_src_h;
+	uint32_t min_dst_w;
+	uint32_t max_dst_w;
+	uint32_t min_dst_h;
+	uint32_t max_dst_h;
+};
+
 struct intel_crtc_state {
 	struct drm_crtc_state base;
 
@@ -391,6 +488,8 @@ struct intel_crtc_state {
 
 	bool dp_encoder_is_mst;
 	int pbn;
+
+	struct intel_crtc_scaler_state scaler_state;
 };
 
 struct intel_pipe_wm {
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 05/21 v2] drm/i915: Initialize skylake scalers
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (3 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:14   ` Matt Roper
  2015-03-25 23:21   ` [PATCH 05/21 v3] " Chandra Konduru
  2015-03-21  0:04 ` [PATCH 06/21 v2] drm/i915: Dump scaler_state too as part of dumping crtc_state Chandra Konduru
                   ` (15 subsequent siblings)
  20 siblings, 2 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Initializing scalers with supported values during crtc init.

v2:
-initialize single copy of min/max values (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   53 ++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 89299b6..e6ea9e0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -103,6 +103,8 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
 			    const struct intel_crtc_state *pipe_config);
 static void intel_begin_crtc_commit(struct drm_crtc *crtc);
 static void intel_finish_crtc_commit(struct drm_crtc *crtc);
+static void skl_init_scalers(struct drm_device *dev, int pipe,
+	struct intel_crtc_state *crtc_state);
 
 static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
 {
@@ -12750,6 +12752,54 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
 	return &cursor->base;
 }
 
+static void skl_init_scalers(struct drm_device *dev, int pipe,
+	struct intel_crtc_state *crtc_state)
+{
+	int i;
+	struct intel_scaler *intel_scaler;
+	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+	if (INTEL_INFO(dev)->gen < 9)
+		return;
+
+	scaler_state->num_scalers = SKL_NUM_SCALERS;
+	for (i = 0; i < SKL_NUM_SCALERS; i++) {
+		intel_scaler = &scaler_state->scalers[i];
+		intel_scaler->in_use = 0;
+		intel_scaler->id = i;
+
+		intel_scaler->mode = PS_SCALER_MODE_DYN;
+		intel_scaler->filter = PS_FILTER_MEDIUM;
+	}
+
+	/* down scaling ratio: 2.99 --> 1, i.e., 34% of original */
+	scaler_state->min_hsr = 34;
+	scaler_state->min_vsr = 34;
+	scaler_state->max_hsr = 500;
+	scaler_state->max_vsr = 500;
+
+	/* down scaling ratio: 2.99x2.99 --> 1x1, i.e., 12% of original */
+	scaler_state->min_hvsr = 12;
+	scaler_state->max_hvsr = 2500;
+
+	/* src_w & dst_w range 8 - 4096 */
+	scaler_state->min_src_w = 8;
+	scaler_state->max_src_w = 4096;
+	scaler_state->min_dst_w = 8;
+	scaler_state->max_dst_w = 4096;
+
+	/* src_h & dst_h range 8 - 2304 */
+	scaler_state->min_src_h = 8;
+	scaler_state->max_src_h = 2304;
+	scaler_state->min_dst_h = 8;
+	scaler_state->max_dst_h = 2304;
+
+	/* pipe C has one scaler */
+	if (pipe == PIPE_C) {
+		scaler_state->num_scalers = 1;
+	}
+	scaler_state->scaler_id = -1;
+}
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -12769,6 +12819,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	intel_crtc_set_state(intel_crtc, crtc_state);
 	crtc_state->base.crtc = &intel_crtc->base;
 
+	/* initialize shared scalers */
+	skl_init_scalers(dev, pipe, crtc_state);
+
 	primary = intel_primary_plane_create(dev, pipe);
 	if (!primary)
 		goto fail;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 06/21 v2] drm/i915: Dump scaler_state too as part of dumping crtc_state
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (4 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 05/21 v2] drm/i915: Initialize skylake scalers Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio Chandra Konduru
                   ` (14 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Dumps scaler state as part of dumping crtc_state.

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   47 ++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e6ea9e0..20f13c8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10376,8 +10376,14 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 				   struct intel_crtc_state *pipe_config,
 				   const char *context)
 {
-	DRM_DEBUG_KMS("[CRTC:%d]%s config for pipe %c\n", crtc->base.base.id,
-		      context, pipe_name(crtc->pipe));
+	struct drm_device *dev = crtc->base.dev;
+	struct drm_plane *plane;
+	struct intel_plane *intel_plane;
+	struct intel_plane_state *state;
+	struct drm_framebuffer *fb;
+
+	DRM_DEBUG_KMS("[CRTC:%d]%s config %p for pipe %c\n", crtc->base.base.id,
+		      context, pipe_config, pipe_name(crtc->pipe));
 
 	DRM_DEBUG_KMS("cpu_transcoder: %c\n", transcoder_name(pipe_config->cpu_transcoder));
 	DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
@@ -10414,6 +10420,9 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 	DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock);
 	DRM_DEBUG_KMS("pipe src size: %dx%d\n",
 		      pipe_config->pipe_src_w, pipe_config->pipe_src_h);
+	DRM_DEBUG_KMS("num_scalers: %d\n", pipe_config->scaler_state.num_scalers);
+	DRM_DEBUG_KMS("scaler_users: 0x%x\n", pipe_config->scaler_state.scaler_users);
+	DRM_DEBUG_KMS("scaler id: %d\n", pipe_config->scaler_state.scaler_id);
 	DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
 		      pipe_config->gmch_pfit.control,
 		      pipe_config->gmch_pfit.pgm_ratios,
@@ -10424,6 +10433,40 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 		      pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
 	DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
 	DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
+
+	DRM_DEBUG_KMS("planes on this crtc\n");
+	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
+		intel_plane = to_intel_plane(plane);
+		if (intel_plane->pipe != crtc->pipe)
+			continue;
+
+		state = to_intel_plane_state(plane->state);
+		fb = state->base.fb;
+		if (!fb) {
+			DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d "
+				"disabled, scaler_id = %d\n",
+				plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD",
+				plane->base.id, intel_plane->pipe,
+				(crtc->base.primary == plane) ? 0 : intel_plane->plane + 1,
+				drm_plane_index(plane), state->scaler_id);
+			continue;
+		}
+
+		DRM_DEBUG_KMS("%s PLANE:%d plane: %u.%u idx: %d enabled",
+			plane->type == DRM_PLANE_TYPE_CURSOR ? "CURSOR" : "STANDARD",
+			plane->base.id, intel_plane->pipe,
+			crtc->base.primary == plane ? 0 : intel_plane->plane + 1,
+			drm_plane_index(plane));
+		DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = 0x%x",
+			fb->base.id, fb->width, fb->height, fb->pixel_format);
+		DRM_DEBUG_KMS("\tscaler:%d src (%u, %u) %ux%u dst (%u, %u) %ux%u\n",
+			state->scaler_id,
+			state->src.x1, state->src.y1,
+			drm_rect_width(&state->src) >> 16,
+			drm_rect_height(&state->src) >> 16,
+			state->dst.x1, state->dst.y1,
+			drm_rect_width(&state->dst), drm_rect_height(&state->dst));
+	}
 }
 
 static bool encoders_cloneable(const struct intel_encoder *a,
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio.
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (5 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 06/21 v2] drm/i915: Dump scaler_state too as part of dumping crtc_state Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:14   ` Matt Roper
  2015-03-25 23:21   ` [PATCH 07/21 v3] " Chandra Konduru
  2015-03-21  0:04 ` [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state Chandra Konduru
                   ` (13 subsequent siblings)
  20 siblings, 2 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Helper function updates supported scaling ratios based on cdclk and
crtc clocks.

v2:
-update single copy of scaling ratios (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 20f13c8..890d372 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4513,6 +4513,31 @@ static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
 	intel_wait_for_vblank(dev, other_active_crtc->pipe);
 }
 
+static void skl_update_scaling_ratio(struct drm_device *dev,
+	struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t crtc_clock, cdclk;
+	struct intel_crtc_scaler_state *scaler_state;
+
+	if (!crtc_state)
+		return;
+
+	crtc_clock = (uint32_t) crtc_state->base.adjusted_mode.crtc_clock;
+	cdclk = (uint32_t) intel_ddi_get_cdclk_freq(dev_priv);
+
+	if (!crtc_clock || !cdclk)
+		return;
+
+	scaler_state = &crtc_state->scaler_state;
+	scaler_state->min_hsr = max(scaler_state->min_hsr, (crtc_clock * 100)/cdclk);
+	scaler_state->min_vsr = max(scaler_state->min_hsr, (crtc_clock * 100)/cdclk);
+	scaler_state->min_hvsr = max(scaler_state->min_hsr, (crtc_clock * 100)/cdclk);
+
+	DRM_DEBUG_KMS("for crtc_state = %p crtc_clock = %d cdclk = %d\n", crtc_state,
+		crtc_clock, cdclk);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (6 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:15   ` Matt Roper
  2015-03-25 23:21   ` [PATCH 08/21 v3] " Chandra Konduru
  2015-03-21  0:04 ` [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc Chandra Konduru
                   ` (12 subsequent siblings)
  20 siblings, 2 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This helper function stages a scaler request for a plane/crtc into
crtc_state->scaler_users (which is a bit field). It also performs
required checks before staging any change into scaler_state.

v2:
-updates to use single copy of scaler limits (Matt)
-added force detach parameter for pfit disable purpose (me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |  143 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    3 +
 2 files changed, 146 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 890d372..976bfb1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12387,6 +12387,149 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
 	}
 }
 
+/*
+ * Update crtc_state->scaler_users for requested plane or crtc based on state.
+ *
+ * plane (in)
+ *     NULL - for crtc
+ *     not NULL - for plane
+ * force_detach (in)
+ *     unconditionally scaler will be staged for detachment from crtc/plane
+ * Return
+ *     0 - scaler_usage updated successfully
+ *    error - requested scaling cannot be supported or other error condition
+ */
+int
+skl_update_scaler_users(
+	struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state,
+	struct intel_plane *intel_plane, struct intel_plane_state *plane_state,
+	int force_detach)
+{
+	int need_scaling;
+	int idx;
+	int src_w, src_h, dst_w, dst_h;
+	int scaler_id;
+	struct drm_framebuffer *fb;
+	struct intel_crtc_scaler_state *scaler_state;
+
+	if (!intel_crtc || !crtc_state ||
+		(intel_plane && intel_plane->base.type == DRM_PLANE_TYPE_CURSOR))
+		return 0;
+
+	scaler_state = &crtc_state->scaler_state;
+
+	if (!scaler_state->num_scalers) {
+		DRM_DEBUG_KMS("crtc_state = %p, num_scalers = %d\n", crtc_state,
+			scaler_state->num_scalers);
+		return 0;
+	}
+
+	idx = intel_plane ? drm_plane_index(&intel_plane->base) : SKL_CRTC_INDEX;
+	fb = intel_plane ? plane_state->base.fb : NULL;
+
+	if (intel_plane) {
+		src_w = drm_rect_width(&plane_state->src) >> 16;
+		src_h = drm_rect_height(&plane_state->src) >> 16;
+		dst_w = drm_rect_width(&plane_state->dst);
+		dst_h = drm_rect_height(&plane_state->dst);
+		scaler_id = plane_state->scaler_id;
+	} else {
+		struct drm_display_mode *adjusted_mode =
+			&crtc_state->base.adjusted_mode;
+		src_w = crtc_state->pipe_src_w;
+		src_h = crtc_state->pipe_src_h;
+		dst_w = adjusted_mode->hdisplay;
+		dst_h = adjusted_mode->vdisplay;
+		scaler_id = scaler_state->scaler_id;
+	}
+	need_scaling = (src_w != dst_w || src_h != dst_h);
+
+	/*
+	 * if plane is being disabled or scaler is no more required or force detach
+	 *  - free scaler binded to this plane/crtc
+	 *  - in order to do this, update crtc->scaler_usage
+	 *
+	 * Here scaler state in crtc_state is set free so that
+	 * scaler can be assigned to other user. Actual register
+	 * update to free the scaler is done in plane/panel-fit programming.
+	 * For this purpose crtc/plane_state->scaler_id isn't reset here.
+	 */
+	if (force_detach || !need_scaling || (intel_plane &&
+		(!fb || !plane_state->visible))) {
+		if (scaler_id >= 0) {
+			scaler_state->scaler_users &= ~(1 << idx);
+			scaler_state->scalers[scaler_id].in_use = 0;
+
+			DRM_DEBUG_KMS("Staged freeing scaler id %u.%u from %s:%d "
+				"crtc_state = %p scaler_users = 0x%x\n",
+				intel_crtc->pipe, scaler_id, intel_plane ? "PLANE" : "CRTC",
+				intel_plane ? intel_plane->base.base.id :
+				intel_crtc->base.base.id, crtc_state,
+				scaler_state->scaler_users);
+		}
+		return 0;
+	}
+
+	/*
+	 * check for rect size:
+	 *     min sizes in case of scaling involved
+	 *     max sizes in all cases
+	 */
+	if ((need_scaling &&
+		(src_w < scaler_state->min_src_w || src_h < scaler_state->min_src_h ||
+		 dst_w < scaler_state->min_dst_w || dst_h < scaler_state->min_dst_h)) ||
+
+		 src_w > scaler_state->max_src_w || src_h > scaler_state->max_src_h ||
+		 dst_w > scaler_state->max_dst_w || dst_h > scaler_state->max_dst_h) {
+		DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u dst %ux%u "
+			"size is out of scaler range\n",
+			intel_plane ? "PLANE" : "CRTC",
+			intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
+			intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h);
+		return -EINVAL;
+	}
+
+	/* check colorkey */
+	if (intel_plane && need_scaling && intel_colorkey_enabled(intel_plane)) {
+		DRM_DEBUG_KMS("PLANE:%d scaling with color key not allowed",
+			intel_plane->base.base.id);
+		return -EINVAL;
+	}
+
+	/* Check src format */
+	if (intel_plane && need_scaling) {
+		switch (fb->pixel_format) {
+		case DRM_FORMAT_RGB565:
+		case DRM_FORMAT_XBGR8888:
+		case DRM_FORMAT_XRGB8888:
+		case DRM_FORMAT_ABGR8888:
+		case DRM_FORMAT_ARGB8888:
+		case DRM_FORMAT_XRGB2101010:
+		case DRM_FORMAT_ARGB2101010:
+		case DRM_FORMAT_XBGR2101010:
+		case DRM_FORMAT_ABGR2101010:
+		case DRM_FORMAT_YUYV:
+		case DRM_FORMAT_YVYU:
+		case DRM_FORMAT_UYVY:
+		case DRM_FORMAT_VYUY:
+			break;
+		default:
+			DRM_DEBUG_KMS("PLANE:%d FB:%d format 0x%x not supported\n",
+				intel_plane->base.base.id, fb->base.id, fb->pixel_format);
+			return -EINVAL;
+		}
+	}
+
+	/* mark this plane as a scaler user in crtc_state */
+	scaler_state->scaler_users |= (1 << idx);
+	DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u "
+		"crtc_state = %p scaler_users = 0x%x\n",
+		intel_plane ? "PLANE" : "CRTC",
+		intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
+		src_w, src_h, dst_w, dst_h, crtc_state, scaler_state->scaler_users);
+	return 0;
+}
+
 static int
 intel_check_primary_plane(struct drm_plane *plane,
 			  struct intel_plane_state *state)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1da5087..f5d53c9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1138,6 +1138,9 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_state *pipe_config);
 void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
 void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
+int skl_update_scaler_users(struct intel_crtc *intel_crtc,
+	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
+	struct intel_plane_state *plane_state, int force_detach);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc.
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (7 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:15   ` Matt Roper
  2015-03-25 23:21   ` [PATCH 09/21 v3] " Chandra Konduru
  2015-03-21  0:04 ` [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc Chandra Konduru
                   ` (11 subsequent siblings)
  20 siblings, 2 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

intel_atomic_setup_scalers sets up scalers based on staged scaling
requests coming from a crtc and its planes. This function should be
called from crtc level check path.

If staged requests are supportable, function assigns scalers to
requested planes and crtc. This function also takes into account
the current planes using scalers but not being part of this
atomic state for optimal operation of scalers. Note that the scaler
assignement itself is staged into crtc_state and respective
plane_states for later commit after all checks have been done.

overall high level flow:
 - scaler requests are staged into crtc_state by planes/crtc
 - check whether staged scaling requests can be supported
 - add planes using scalers that aren't in current transaction
 - assign scalers to requested users
 - as part of plane commit, scalers will be committed
   (i.e., either attached or detached) to respective planes in hw
 - as part of crtc_commit, scaler will be either attached or detached
   to crtc in hw

v2:
-removed a log message (me)
-changed input parameter to crtc_state (me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  138 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h    |    3 +
 2 files changed, 141 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 3903b90..407516a 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -241,3 +241,141 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
 {
 	drm_atomic_helper_crtc_destroy_state(crtc, state);
 }
+
+/**
+ * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
+ * @dev: DRM device
+ * @crtc: intel crtc
+ * @crtc_state: incoming crtc_state to validate and setup scalers
+ *
+ * This function setups up scalers based on staged scaling requests for
+ * a @crtc and its planes. It is called from crtc level check path. If request
+ * is a supportable request, it attaches scalers to requested planes and crtc.
+ *
+ * This function takes into account the current scaler(s) in use by any planes
+ * not being part of this atomic state
+ *
+ *  Returns:
+ *         0 - scalers were setup succesfully
+ *         error code - otherwise
+ */
+int intel_atomic_setup_scalers(struct drm_device *dev,
+	struct intel_crtc *intel_crtc,
+	struct intel_crtc_state *crtc_state)
+{
+	struct drm_plane *plane = NULL;
+	struct intel_plane *intel_plane;
+	struct intel_plane_state *plane_state = NULL;
+	struct intel_crtc_scaler_state *scaler_state;
+	struct drm_atomic_state *drm_state;
+	int num_scalers_need;
+	int i, j;
+
+	if (INTEL_INFO(dev)->gen < 9 || !intel_crtc || !crtc_state)
+		return 0;
+
+	scaler_state = &crtc_state->scaler_state;
+	drm_state = crtc_state->base.state;
+
+	num_scalers_need = hweight32(scaler_state->scaler_users);
+	DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n",
+		crtc_state, num_scalers_need, scaler_state->num_scalers,
+		scaler_state->scaler_users);
+
+	/* if there is no change in scaler configuration, return */
+	if (scaler_state->scaler_users ==
+		intel_crtc->config->scaler_state.scaler_users)
+		return 0;
+
+	/*
+	 * High level flow:
+	 * - staged scaler requests are already in scaler_state->scaler_users
+	 * - check whether staged scaling requests can be supported
+	 * - add planes using scalers that aren't in current transaction
+	 * - assign scalers to requested users
+	 * - as part of plane commit, scalers will be committed
+	 *   (i.e., either attached or detached) to respective planes in hw
+	 * - as part of crtc_commit, scaler will be either attached or detached
+	 *   to crtc in hw
+	 */
+
+	/* fail if required scalers > available scalers */
+	if (num_scalers_need > scaler_state->num_scalers){
+		DRM_DEBUG_KMS("Too many scaling requests %d > %d\n",
+			num_scalers_need, scaler_state->num_scalers);
+		return -EINVAL;
+	}
+
+	/* walkthrough scaler_users bits and start assigning scalers */
+	for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
+		int *scaler_id;
+
+		/* skip if scaler not required */
+		if (!(scaler_state->scaler_users & (1 << i)))
+			continue;
+
+		if (i == SKL_CRTC_INDEX) {
+			/* panel fitter case: assign as a crtc scaler */
+			scaler_id = &scaler_state->scaler_id;
+		} else {
+			if (!drm_state)
+				continue;
+
+			/* plane scaler case: assign as a plane scaler */
+			/* find the plane that set the bit as scaler_user */
+			plane = drm_state->planes[i];
+
+			/*
+			 * to enable/disable hq mode, add planes that are using scaler
+			 * into this transaction
+			 */
+			if (!plane) {
+				plane = drm_plane_from_index(dev, i);
+				drm_state->planes[i] = plane;
+				drm_state->plane_states[i] =
+					drm_atomic_get_plane_state(drm_state, plane);
+			}
+
+			intel_plane = to_intel_plane(plane);
+
+			/* plane on different crtc cannot be a scaler user of this crtc */
+			if (WARN_ON(intel_plane->pipe != intel_crtc->pipe)) {
+				continue;
+			}
+
+			plane_state = to_intel_plane_state(drm_state->plane_states[i]);
+			scaler_id = &plane_state->scaler_id;
+		}
+
+		if (*scaler_id < 0) {
+			/* find a free scaler */
+			for (j = 0; j < scaler_state->num_scalers; j++) {
+				if (!scaler_state->scalers[j].in_use) {
+					scaler_state->scalers[j].in_use = 1;
+					*scaler_id = scaler_state->scalers[j].id;
+					DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n",
+						intel_crtc->pipe,
+						i == SKL_CRTC_INDEX ? scaler_state->scaler_id :
+							plane_state->scaler_id,
+						i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
+						i == SKL_CRTC_INDEX ?  intel_crtc->base.base.id :
+						plane->base.id);
+					break;
+				}
+			}
+		}
+
+		if (WARN_ON(*scaler_id < 0)) {
+			DRM_DEBUG_KMS("Cannot find scaler for %s:%d\n",
+				i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
+				i == SKL_CRTC_INDEX ? intel_crtc->base.base.id:plane->base.id);
+			continue;
+		}
+
+		/* set scaler mode */
+		scaler_state->scalers[*scaler_id].mode = (num_scalers_need == 1) ?
+			PS_SCALER_MODE_HQ : PS_SCALER_MODE_DYN;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f5d53c9..a9d787d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1401,6 +1401,9 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
 
 	return to_intel_crtc_state(crtc_state);
 }
+int intel_atomic_setup_scalers(struct drm_device *dev,
+	struct intel_crtc *intel_crtc,
+	struct intel_crtc_state *crtc_state);
 
 /* intel_atomic_plane.c */
 struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (8 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:15   ` Matt Roper
  2015-03-25 23:21   ` [PATCH 10/21 v3] " Chandra Konduru
  2015-03-21  0:04 ` [PATCH 11/21 v2] drm/i915: Ensure planes begin with no scaler Chandra Konduru
                   ` (10 subsequent siblings)
  20 siblings, 2 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This function is called from commit path of a plane or crtc.
It programs scaler registers to detach (aka. unbinds) scaler
from requested plane or crtc if it isn't in use. It also resets
scaler_id in crtc/plane state.

v2:
-improved a log message (me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   39 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 2 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 976bfb1..7150c33 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
 	}
 }
 
+/*
+ * This function detaches (aka. unbinds) a scaler from plane or crtc
+ * if scaler is not in use.
+ * It resets scaler_id in plane or crtc
+ * To request detach a scaler from crtc, call plane as NULL
+ */
+void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc_state *crtc_state;
+	struct intel_crtc *intel_crtc;
+	struct intel_plane *intel_plane;
+	struct intel_plane_state *plane_state;
+	int *scaler_id;
+
+	intel_crtc = to_intel_crtc(crtc);
+	intel_plane = plane ? to_intel_plane(plane) : NULL;
+	crtc_state = intel_crtc->config;
+	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
+
+	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
+		&crtc_state->scaler_state.scaler_id;
+
+	if (!scaler_id || (scaler_id && *scaler_id < 0))
+		return;
+
+	/* if scaler is not in use, free */
+	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
+		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
+		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)), 0);
+		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
+		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u from %s:%d\n",
+			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
+			plane ? plane->base.id : crtc->base.id);
+		*scaler_id = -1;
+	}
+}
+
 static void skylake_update_primary_plane(struct drm_crtc *crtc,
 					 struct drm_framebuffer *fb,
 					 int x, int y)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a9d787d..f25d14d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1141,6 +1141,7 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
 int skl_update_scaler_users(struct intel_crtc *intel_crtc,
 	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
 	struct intel_plane_state *plane_state, int force_detach);
+void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 11/21 v2] drm/i915: Ensure planes begin with no scaler.
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (9 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25  5:17   ` Matt Roper
  2015-03-21  0:04 ` [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time Chandra Konduru
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    2 ++
 drivers/gpu/drm/i915/intel_sprite.c  |    1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7150c33..ffaed7b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12819,6 +12819,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
 
 	primary->can_scale = false;
 	primary->max_downscale = 1;
+	state->scaler_id = -1;
 	primary->pipe = pipe;
 	primary->plane = pipe;
 	primary->check_plane = intel_check_primary_plane;
@@ -12976,6 +12977,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
 	cursor->max_downscale = 1;
 	cursor->pipe = pipe;
 	cursor->plane = pipe;
+	state->scaler_id = -1;
 	cursor->check_plane = intel_check_cursor_plane;
 	cursor->commit_plane = intel_commit_cursor_plane;
 
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 9ee12d0..c010528 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1497,6 +1497,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 		intel_plane->disable_plane = skl_disable_plane;
 		intel_plane->update_colorkey = skl_update_colorkey;
 		intel_plane->get_colorkey = skl_get_colorkey;
+		state->scaler_id = -1;
 
 		plane_formats = skl_plane_formats;
 		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (10 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 11/21 v2] drm/i915: Ensure planes begin with no scaler Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25 17:21   ` Matt Roper
  2015-03-21  0:04 ` [PATCH 13/21 v2] drm/i915: Preserve scaler state when clearing crtc_state Chandra Konduru
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Plane scaling and colorkey are mutually exclusive. Ensure scaling
isn't active at the time of enabling colorkey.

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index c010528..0194390 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -319,6 +319,12 @@ skl_update_colorkey(struct drm_plane *drm_plane,
 	const int plane = intel_plane->plane;
 	u32 plane_ctl;
 
+	/* plane scaling and colorkey are mutually exclusive */
+	if (to_intel_plane_state(drm_plane->state)->scaler_id >= 0) {
+		DRM_ERROR("colorkey not allowed with scaler\n");
+		return -EINVAL;
+	}
+
 	I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
 	I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
 	I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 13/21 v2] drm/i915: Preserve scaler state when clearing crtc_state
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (11 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 14/21 v2] drm/i915: use current scaler state during readout_hw_state Chandra Konduru
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

crtc_state is cleared during mode set which wipes out complete
scaler state too. This is causing issues. To fix, ensure scaler
state is preserved because it contains not only crtc
scaler usage, but also planes using scalers on this crtc.

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ffaed7b..46acf87 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -10619,11 +10619,14 @@ static void
 clear_intel_crtc_state(struct intel_crtc_state *crtc_state)
 {
 	struct drm_crtc_state tmp_state;
+	struct intel_crtc_scaler_state scaler_state;
 
-	/* Clear only the intel specific part of the crtc state */
+	/* Clear only the intel specific part of the crtc state excluding scalers */
 	tmp_state = crtc_state->base;
+	scaler_state = crtc_state->scaler_state;
 	memset(crtc_state, 0, sizeof *crtc_state);
 	crtc_state->base = tmp_state;
+	crtc_state->scaler_state = scaler_state;
 }
 
 static struct intel_crtc_state *
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 14/21 v2] drm/i915: use current scaler state during readout_hw_state.
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (12 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 13/21 v2] drm/i915: Preserve scaler state when clearing crtc_state Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 15/21 v2] drm/i915: Update scaling ratio as part of crtc_compute_config Chandra Konduru
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

During readout_hw_state, rebuild crtc scaler_state from hw state:
 - crtc scaler id
 - scaler users
 - scaling ratios

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 46acf87..dfd24ed 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8585,6 +8585,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 
 	intel_get_pipe_timings(crtc, pipe_config);
 
+	if (INTEL_INFO(dev)->gen >= 9) {
+		skl_init_scalers(dev, crtc->pipe, pipe_config);
+		skl_update_scaling_ratio(dev, pipe_config);
+	}
+
 	pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
 	if (intel_display_power_is_enabled(dev_priv, pfit_domain)) {
 		if (IS_SKYLAKE(dev))
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 15/21 v2] drm/i915: Update scaling ratio as part of crtc_compute_config
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (13 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 14/21 v2] drm/i915: use current scaler state during readout_hw_state Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state Chandra Konduru
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Based on computed crtc config, stage any updates to scaling ratios.

Also call intel_atomic_setup_scalers() to stage scaler assignments
if crtc compute config staged any changes to its scaler needs.

Above actions should be moved to atomic crtc once it is available.

v2:
-moved gen comparision check to caller (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index dfd24ed..c393480 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5790,6 +5790,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
+	int ret;
 
 	/* FIXME should check pixel clock limits on all platforms */
 	if (INTEL_INFO(dev)->gen < 4) {
@@ -5844,7 +5845,17 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc,
 	if (pipe_config->has_pch_encoder)
 		return ironlake_fdi_compute_config(crtc, pipe_config);
 
-	return 0;
+	if (INTEL_INFO(dev)->gen >= 9)
+		skl_update_scaling_ratio(dev, pipe_config);
+
+	/* FIXME: remove below call once atomic mode set is place and all crtc
+	 * related checks called from atomic_crtc_check function */
+	ret = 0;
+	DRM_DEBUG_KMS("intel_crtc = %p drm_state (pipe_config->base.state) = %p\n",
+		crtc, pipe_config->base.state);
+	ret = intel_atomic_setup_scalers(dev, crtc, pipe_config);
+
+	return ret;
 }
 
 static int valleyview_get_display_clock_speed(struct drm_device *dev)
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (14 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 15/21 v2] drm/i915: Update scaling ratio as part of crtc_compute_config Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25 17:21   ` Matt Roper
  2015-03-21  0:04 ` [PATCH 17/21 v2] drm/i915: copy staged scaler state from drm state to crtc->config Chandra Konduru
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

From intel_atomic_check, call intel_atomic_setup_scalers() to
assign scalers based on staged scaling requests. Fail the
transaction if setup returns error.

Setting up of scalers should be moved to atomic crtc check  once
atomic crtc is ready.

v2:
-updated parameter passing to setup_scalers (me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 407516a..73e94c4 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -48,6 +48,8 @@ int intel_atomic_check(struct drm_device *dev,
 	int ncrtcs = dev->mode_config.num_crtc;
 	int nconnectors = dev->mode_config.num_connector;
 	enum pipe nuclear_pipe = INVALID_PIPE;
+	struct intel_crtc *nuclear_crtc = NULL;
+	struct intel_crtc_state *crtc_state = NULL;
 	int ret;
 	int i;
 	bool not_nuclear = false;
@@ -78,6 +80,10 @@ int intel_atomic_check(struct drm_device *dev,
 		struct intel_crtc *crtc = to_intel_crtc(state->crtcs[i]);
 		if (crtc && crtc->pipe != nuclear_pipe)
 			not_nuclear = true;
+		if (crtc && crtc->pipe == nuclear_pipe) {
+			nuclear_crtc = crtc;
+			crtc_state = to_intel_crtc_state(state->crtc_states[i]);
+		}
 	}
 	for (i = 0; i < nconnectors; i++)
 		if (state->connectors[i] != NULL)
@@ -92,6 +98,11 @@ int intel_atomic_check(struct drm_device *dev,
 	if (ret)
 		return ret;
 
+	/* FIXME: move to crtc atomic check function once it is ready */
+	ret = intel_atomic_setup_scalers(dev, nuclear_crtc, crtc_state);
+	if (ret)
+		return ret;
+
 	return ret;
 }
 
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 17/21 v2] drm/i915: copy staged scaler state from drm state to crtc->config.
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (15 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 18/21 v2] drm/i915: stage panel fitting scaler request for fixed mode panel Chandra Konduru
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This is required for commit to perform as per staged assignment
of scalers until atomic crtc commit function is available.

As a place holder doing this copy from intel_atomic_commit for
scaling to operate correctly.

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 73e94c4..5046316 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -166,6 +166,18 @@ int intel_atomic_commit(struct drm_device *dev,
 		swap(state->plane_states[i], plane->state);
 		plane->state->state = NULL;
 	}
+
+	/* swap crtc_state */
+	for (i = 0; i < dev->mode_config.num_crtc; i++) {
+		struct drm_crtc *crtc = state->crtcs[i];
+		if (!crtc) {
+			continue;
+		}
+
+		to_intel_crtc(crtc)->config->scaler_state =
+			to_intel_crtc_state(state->crtc_states[i])->scaler_state;
+	}
+
 	drm_atomic_helper_commit_planes(dev, state);
 	drm_atomic_helper_wait_for_vblanks(dev, state);
 	drm_atomic_helper_cleanup_planes(dev, state);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 18/21 v2] drm/i915: stage panel fitting scaler request for fixed mode panel
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (16 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 17/21 v2] drm/i915: copy staged scaler state from drm state to crtc->config Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 19/21 v2] drm/i915: Enable skylake panel fitting using skylake shared scalers Chandra Konduru
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This patch calls skl_update_scaler_users() to stage a panel fitting
request for fixed mode panel.

v2:
-move gen check to caller (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c |    8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 22bf6f2..ae1aa27 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1305,6 +1305,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
 		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
 				       adjusted_mode);
+
+		if (INTEL_INFO(dev)->gen >= 9) {
+			int ret;
+			ret = skl_update_scaler_users(intel_crtc, pipe_config, NULL, NULL, 0);
+			if (ret)
+				return ret;
+		}
+
 		if (!HAS_PCH_SPLIT(dev))
 			intel_gmch_panel_fitting(intel_crtc, pipe_config,
 						 intel_connector->panel.fitting_mode);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 19/21 v2] drm/i915: Enable skylake panel fitting using skylake shared scalers
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (17 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 18/21 v2] drm/i915: stage panel fitting scaler request for fixed mode panel Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 20/21 v2] drm/i915: Enable skylake primary plane scaling using " Chandra Konduru
  2015-03-21  0:04 ` [PATCH 21/21 v2] drm/i915: Enable skylake sprite " Chandra Konduru
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Modify skylake panel fitting implementation to use shared scalers.

v2:
-added log message in pfit enable/disable (me)
-read crtc scaler state from hw state (Daniel)
-replaced both skylake_pfit_enable and disable with skylake_pfit_update (me)
-added scaler id check to intel_pipe_config_compare (Daniel)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   81 ++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c393480..16dcd31 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4189,16 +4189,39 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
 	}
 }
 
-static void skylake_pfit_enable(struct intel_crtc *crtc)
+static void skylake_pfit_update(struct intel_crtc *crtc, int enable)
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int pipe = crtc->pipe;
+	struct intel_crtc_scaler_state *scaler_state =
+		&crtc->config->scaler_state;
+
+	DRM_DEBUG_KMS("for crtc_state = %p\n", crtc->config);
+
+	/* To update pfit, first update scaler state */
+	skl_update_scaler_users(crtc, crtc->config, NULL, NULL, !enable);
+	intel_atomic_setup_scalers(crtc->base.dev, crtc, crtc->config);
+	skl_detach_scaler(&crtc->base, NULL);
+	if (!enable)
+		return;
 
 	if (crtc->config->pch_pfit.enabled) {
-		I915_WRITE(PS_CTL(pipe), PS_ENABLE);
-		I915_WRITE(PS_WIN_POS(pipe), crtc->config->pch_pfit.pos);
-		I915_WRITE(PS_WIN_SZ(pipe), crtc->config->pch_pfit.size);
+		int id;
+
+		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0)) {
+			DRM_ERROR("Requesting pfit without getting a scaler first\n");
+			return;
+		}
+
+		id = scaler_state->scaler_id;
+		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
+			scaler_state->scalers[id].mode |
+			scaler_state->scalers[id].filter);
+		I915_WRITE(SKL_PS_WIN_POS(pipe, id), crtc->config->pch_pfit.pos);
+		I915_WRITE(SKL_PS_WIN_SZ(pipe, id), crtc->config->pch_pfit.size);
+
+		DRM_DEBUG_KMS("for crtc_state = %p scaler_id = %d\n", crtc->config, id);
 	}
 }
 
@@ -4628,7 +4651,7 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_ddi_enable_pipe_clock(intel_crtc);
 
 	if (IS_SKYLAKE(dev))
-		skylake_pfit_enable(intel_crtc);
+		skylake_pfit_update(intel_crtc, 1);
 	else
 		ironlake_pfit_enable(intel_crtc);
 
@@ -4664,21 +4687,6 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc_enable_planes(crtc);
 }
 
-static void skylake_pfit_disable(struct intel_crtc *crtc)
-{
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipe = crtc->pipe;
-
-	/* To avoid upsetting the power well on haswell only disable the pfit if
-	 * it's in use. The hw state code will make sure we get this right. */
-	if (crtc->config->pch_pfit.enabled) {
-		I915_WRITE(PS_CTL(pipe), 0);
-		I915_WRITE(PS_WIN_POS(pipe), 0);
-		I915_WRITE(PS_WIN_SZ(pipe), 0);
-	}
-}
-
 static void ironlake_pfit_disable(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
@@ -4791,7 +4799,7 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 	intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
 	if (IS_SKYLAKE(dev))
-		skylake_pfit_disable(intel_crtc);
+		skylake_pfit_update(intel_crtc, 0);
 	else
 		ironlake_pfit_disable(intel_crtc);
 
@@ -7955,14 +7963,28 @@ static void skylake_get_pfit_config(struct intel_crtc *crtc,
 {
 	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t tmp;
+	struct intel_crtc_scaler_state *scaler_state = &pipe_config->scaler_state;
+	uint32_t ps_ctrl = 0;
+	int id = -1;
+	int i;
 
-	tmp = I915_READ(PS_CTL(crtc->pipe));
+	/* find scaler attached to this pipe */
+	for (i = 0; i < scaler_state->num_scalers; i++) {
+		ps_ctrl = I915_READ(SKL_PS_CTRL(crtc->pipe, i));
+		if (ps_ctrl & PS_SCALER_EN && !(ps_ctrl & PS_PLANE_SEL_MASK)) {
+			id = i;
+			pipe_config->pch_pfit.enabled = true;
+			pipe_config->pch_pfit.pos = I915_READ(SKL_PS_WIN_POS(crtc->pipe, i));
+			pipe_config->pch_pfit.size = I915_READ(SKL_PS_WIN_SZ(crtc->pipe, i));
+			break;
+		}
+	}
 
-	if (tmp & PS_ENABLE) {
-		pipe_config->pch_pfit.enabled = true;
-		pipe_config->pch_pfit.pos = I915_READ(PS_WIN_POS(crtc->pipe));
-		pipe_config->pch_pfit.size = I915_READ(PS_WIN_SZ(crtc->pipe));
+	scaler_state->scaler_id = id;
+	if (id >= 0) {
+		scaler_state->scaler_users |= (1 << SKL_CRTC_INDEX);
+	} else {
+		scaler_state->scaler_users &= ~(1 << SKL_CRTC_INDEX);
 	}
 }
 
@@ -8607,6 +8629,9 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 			skylake_get_pfit_config(crtc, pipe_config);
 		else
 			ironlake_get_pfit_config(crtc, pipe_config);
+	} else {
+		pipe_config->scaler_state.scaler_id = -1;
+		pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
 	}
 
 	if (IS_HASWELL(dev))
@@ -11112,6 +11137,8 @@ intel_pipe_config_compare(struct drm_device *dev,
 		PIPE_CONF_CHECK_I(pch_pfit.size);
 	}
 
+	PIPE_CONF_CHECK_I(scaler_state.scaler_id);
+
 	/* BDW+ don't expose a synchronous way to read the state */
 	if (IS_HASWELL(dev))
 		PIPE_CONF_CHECK_I(ips_enabled);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 20/21 v2] drm/i915: Enable skylake primary plane scaling using shared scalers
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (18 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 19/21 v2] drm/i915: Enable skylake panel fitting using skylake shared scalers Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-21  0:04 ` [PATCH 21/21 v2] drm/i915: Enable skylake sprite " Chandra Konduru
  20 siblings, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This patch enables skylake primary plane display scaling using shared
scalers atomic desgin.

v2:
-use single copy of scaler limits (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   77 +++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 16dcd31..965859f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2885,6 +2885,16 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	struct drm_i915_gem_object *obj;
 	int pipe = intel_crtc->pipe;
 	u32 plane_ctl, stride_div;
+	struct intel_crtc_state *crtc_state = intel_crtc->config;
+	struct intel_plane_state *plane_state;
+	int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
+	int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
+	int scaler_id = -1;
+
+	plane_state = crtc->primary ?
+		to_intel_plane_state(crtc->primary->state) : NULL;
+
+	skl_detach_scaler(crtc, crtc->primary);
 
 	if (!intel_crtc->primary_enabled) {
 		I915_WRITE(PLANE_CTL(pipe, 0), 0);
@@ -2952,13 +2962,42 @@ static void skylake_update_primary_plane(struct drm_crtc *crtc,
 	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
 					       fb->pixel_format);
 
+	if (plane_state) {
+		scaler_id = plane_state->scaler_id;
+		src_x = plane_state->src.x1 >> 16;
+		src_y = plane_state->src.y1 >> 16;
+		src_w = drm_rect_width(&plane_state->src) >> 16;
+		src_h = drm_rect_height(&plane_state->src) >> 16;
+		dst_x = plane_state->dst.x1;
+		dst_y = plane_state->dst.y1;
+		dst_w = drm_rect_width(&plane_state->dst);
+		dst_h = drm_rect_height(&plane_state->dst);
+	}
+
 	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
 
-	I915_WRITE(PLANE_POS(pipe, 0), 0);
+	if (src_w && src_h && dst_w && dst_h && scaler_id >= 0) {
+		uint32_t ps_ctrl = 0;
+
+		WARN_ON(x != src_x || y != src_y);
+		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(0) |
+			crtc_state->scaler_state.scalers[scaler_id].mode |
+			crtc_state->scaler_state.scalers[scaler_id].filter;
+		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
+		I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
+		I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (dst_x << 16) | dst_y);
+		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id), (dst_w << 16) | dst_h);
+
+		I915_WRITE(PLANE_POS(pipe, 0), 0);
+		I915_WRITE(PLANE_SIZE(pipe, 0), ((src_h - 1) << 16) | (src_w - 1));
+	} else {
+		I915_WRITE(PLANE_POS(pipe, 0), 0);
+		I915_WRITE(PLANE_SIZE(pipe, 0),
+			(intel_crtc->config->pipe_src_h - 1) << 16 |
+			(intel_crtc->config->pipe_src_w - 1));
+	}
+
 	I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
-	I915_WRITE(PLANE_SIZE(pipe, 0),
-		   (intel_crtc->config->pipe_src_h - 1) << 16 |
-		   (intel_crtc->config->pipe_src_w - 1));
 	I915_WRITE(PLANE_STRIDE(pipe, 0), fb->pitches[0] / stride_div);
 	I915_WRITE(PLANE_SURF(pipe, 0), i915_gem_obj_ggtt_offset(obj));
 
@@ -12623,19 +12662,33 @@ intel_check_primary_plane(struct drm_plane *plane,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = state->base.crtc;
 	struct intel_crtc *intel_crtc;
+	struct intel_crtc_state *crtc_state;
 	struct drm_framebuffer *fb = state->base.fb;
 	struct drm_rect *dest = &state->dst;
 	struct drm_rect *src = &state->src;
 	const struct drm_rect *clip = &state->clip;
+	struct intel_crtc_scaler_state *scaler_state;
+	int max_scale = DRM_PLANE_HELPER_NO_SCALING;
+	int min_scale = DRM_PLANE_HELPER_NO_SCALING;
 	int ret;
 
 	crtc = crtc ? crtc : plane->crtc;
 	intel_crtc = to_intel_crtc(crtc);
+	crtc_state = state->base.state ?
+		intel_atomic_get_crtc_state(state->base.state, intel_crtc) : NULL;
+	scaler_state = crtc_state ? &crtc_state->scaler_state : NULL;
+
+	if (INTEL_INFO(dev)->gen >= 9) {
+		if (scaler_state && scaler_state->num_scalers) {
+			min_scale = 1;
+			max_scale = (100 << 16) / scaler_state->min_hsr;
+		}
+	}
 
 	ret = drm_plane_helper_check_update(plane, crtc, fb,
 					    src, dest, clip,
-					    DRM_PLANE_HELPER_NO_SCALING,
-					    DRM_PLANE_HELPER_NO_SCALING,
+					    min_scale,
+					    max_scale,
 					    false, true, &state->visible);
 	if (ret)
 		return ret;
@@ -12682,6 +12735,13 @@ intel_check_primary_plane(struct drm_plane *plane,
 			intel_crtc->atomic.update_wm = true;
 	}
 
+	if (INTEL_INFO(dev)->gen >= 9) {
+		ret = skl_update_scaler_users(intel_crtc, crtc_state,
+			to_intel_plane(plane), state, 0);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -12865,6 +12925,11 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
 
 	primary->can_scale = false;
 	primary->max_downscale = 1;
+	if (INTEL_INFO(dev)->gen >= 9) {
+		primary->can_scale = true;
+		primary->max_downscale = 2; /* updated later */
+		primary->get_colorkey = skl_get_colorkey;
+	}
 	state->scaler_id = -1;
 	primary->pipe = pipe;
 	primary->plane = pipe;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 21/21 v2] drm/i915: Enable skylake sprite plane scaling using shared scalers
  2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
                   ` (19 preceding siblings ...)
  2015-03-21  0:04 ` [PATCH 20/21 v2] drm/i915: Enable skylake primary plane scaling using " Chandra Konduru
@ 2015-03-21  0:04 ` Chandra Konduru
  2015-03-25 21:29   ` Matt Roper
  20 siblings, 1 reply; 56+ messages in thread
From: Chandra Konduru @ 2015-03-21  0:04 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This patch enables skylake sprite plane display scaling using shared
scalers atomic desgin.

v2:
-use single copy of scaler limits (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_sprite.c |   79 +++++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 0194390..b4452bc 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -33,6 +33,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_plane_helper.h>
 #include "intel_drv.h"
 #include <drm/i915_drm.h>
@@ -191,6 +192,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	const int plane = intel_plane->plane + 1;
 	u32 plane_ctl, stride_div;
 	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
+	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
+	int scaler_id;
 
 	plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
 
@@ -274,16 +277,39 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
 	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
 					       fb->pixel_format);
 
+	skl_detach_scaler(crtc, drm_plane);
+	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
 	crtc_w--;
 	crtc_h--;
 
+	/* program plane scaler */
+	if (scaler_id >= 0) {
+		uint32_t ps_ctrl = 0;
+
+		DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane,
+			PS_PLANE_SEL(plane));
+		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) |
+			crtc_state->scaler_state.scalers[scaler_id].mode |
+			crtc_state->scaler_state.scalers[scaler_id].filter;
+		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
+		I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
+		I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
+		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id),
+			((crtc_w + 1) << 16)|(crtc_h + 1));
+
+		I915_WRITE(PLANE_POS(pipe, plane), 0);
+		I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
+	} else {
+		I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
+		I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
+	}
+
 	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
 	I915_WRITE(PLANE_STRIDE(pipe, plane), fb->pitches[0] / stride_div);
-	I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
-	I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
 	I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
 	POSTING_READ(PLANE_SURF(pipe, plane));
@@ -305,6 +331,8 @@ skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
 	I915_WRITE(PLANE_CTL(pipe, plane), 0);
 	POSTING_READ(PLANE_CTL(pipe, plane));
 
+	skl_detach_scaler(crtc, drm_plane);
+
 	intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false, false);
 }
 
@@ -1088,7 +1116,9 @@ static int
 intel_check_sprite_plane(struct drm_plane *plane,
 			 struct intel_plane_state *state)
 {
+	struct drm_device *dev = plane->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
+	struct intel_crtc_state *crtc_state;
 	struct intel_plane *intel_plane = to_intel_plane(plane);
 	struct drm_framebuffer *fb = state->base.fb;
 	int crtc_x, crtc_y;
@@ -1097,11 +1127,16 @@ intel_check_sprite_plane(struct drm_plane *plane,
 	struct drm_rect *src = &state->src;
 	struct drm_rect *dst = &state->dst;
 	const struct drm_rect *clip = &state->clip;
+	struct intel_crtc_scaler_state *scaler_state;
 	int hscale, vscale;
 	int max_scale, min_scale;
 	int pixel_size;
+	int ret;
 
 	intel_crtc = intel_crtc ? intel_crtc : to_intel_crtc(plane->crtc);
+	crtc_state = state->base.state ?
+		intel_atomic_get_crtc_state(state->base.state, intel_crtc) : NULL;
+	scaler_state = crtc_state ? &crtc_state->scaler_state : NULL;
 
 	if (!fb) {
 		state->visible = false;
@@ -1128,6 +1163,11 @@ intel_check_sprite_plane(struct drm_plane *plane,
 	max_scale = intel_plane->max_downscale << 16;
 	min_scale = intel_plane->can_scale ? 1 : (1 << 16);
 
+	if (INTEL_INFO(dev)->gen >= 9 && scaler_state && scaler_state->num_scalers) {
+		min_scale = 1;
+		max_scale = (100 << 16) / scaler_state->min_hsr;
+	}
+
 	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
 			state->base.rotation);
 
@@ -1223,18 +1263,18 @@ intel_check_sprite_plane(struct drm_plane *plane,
 		width_bytes = ((src_x * pixel_size) & 63) +
 					src_w * pixel_size;
 
-		if (src_w > 2048 || src_h > 2048 ||
-		    width_bytes > 4096 || fb->pitches[0] > 4096) {
+		if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 ||
+		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
 			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
 			return -EINVAL;
 		}
 	}
 
 	if (state->visible) {
-		src->x1 = src_x;
-		src->x2 = src_x + src_w;
-		src->y1 = src_y;
-		src->y2 = src_y + src_h;
+		src->x1 = src_x << 16;
+		src->x2 = (src_x + src_w) << 16;
+		src->y1 = src_y << 16;
+		src->y2 = (src_y + src_h) << 16;
 	}
 
 	dst->x1 = crtc_x;
@@ -1271,6 +1311,13 @@ finish:
 			intel_crtc->atomic.update_wm = true;
 	}
 
+	if (INTEL_INFO(dev)->gen >= 9) {
+		ret = skl_update_scaler_users(intel_crtc, crtc_state, intel_plane,
+			state, 0);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -1301,10 +1348,10 @@ intel_commit_sprite_plane(struct drm_plane *plane,
 			crtc_y = state->dst.y1;
 			crtc_w = drm_rect_width(&state->dst);
 			crtc_h = drm_rect_height(&state->dst);
-			src_x = state->src.x1;
-			src_y = state->src.y1;
-			src_w = drm_rect_width(&state->src);
-			src_h = drm_rect_height(&state->src);
+			src_x = state->src.x1 >> 16;
+			src_y = state->src.y1 >> 16;
+			src_w = drm_rect_width(&state->src) >> 16;
+			src_h = drm_rect_height(&state->src) >> 16;
 			intel_plane->update_plane(plane, crtc, fb, obj,
 						  crtc_x, crtc_y, crtc_w, crtc_h,
 						  src_x, src_y, src_w, src_h);
@@ -1493,12 +1540,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
 		}
 		break;
 	case 9:
-		/*
-		 * FIXME: Skylake planes can be scaled (with some restrictions),
-		 * but this is for another time.
-		 */
-		intel_plane->can_scale = false;
-		intel_plane->max_downscale = 1;
+		intel_plane->can_scale = true;
+		intel_plane->max_downscale = 2; /* updated later */
 		intel_plane->update_plane = skl_update_plane;
 		intel_plane->disable_plane = skl_disable_plane;
 		intel_plane->update_colorkey = skl_update_colorkey;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index().
  2015-03-21  0:04 ` [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index() Chandra Konduru
@ 2015-03-23  9:32   ` Daniel Vetter
  2015-03-23 16:32     ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Daniel Vetter @ 2015-03-23  9:32 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: ander.conselvan.de.oliveira, intel-gfx, daniel.vetter

On Fri, Mar 20, 2015 at 05:04:22PM -0700, Chandra Konduru wrote:
> Adding drm helper function to return plane pointer from index where
> index is a returned by drm_plane_index.
> 
> v2:
> -avoided nested loop by adding loop count (Daniel)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>

Sorry forgotten to mention this earlier, but any code touching drm core
must be cc'ed to dri-devel. Best to just add a Cc: line before the sob
line so that git send-email automatically picks it up every time.
-Daniel

> ---
>  drivers/gpu/drm/drm_crtc.c |   22 ++++++++++++++++++++++
>  include/drm/drm_crtc.h     |    1 +
>  2 files changed, 23 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 9f970c2..b6703f4 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1286,6 +1286,28 @@ unsigned int drm_plane_index(struct drm_plane *plane)
>  EXPORT_SYMBOL(drm_plane_index);
>  
>  /**
> + * drm_plane_from_index - find the registered plane at an index
> + * @idx: index of registered plane to find for
> + *
> + * Given a plane index, return the registered plane from DRM device's
> + * list of planes with matching index.
> + */
> +struct drm_plane *
> +drm_plane_from_index(struct drm_device *dev, int idx)
> +{
> +	struct drm_plane *plane;
> +	unsigned int i = 0;
> +
> +	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> +		if (i == idx)
> +			return plane;
> +		i++;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL(drm_plane_from_index);
> +
> +/**
>   * drm_plane_force_disable - Forcibly disable a plane
>   * @plane: plane to disable
>   *
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 7b5c661..6b30036 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1264,6 +1264,7 @@ extern int drm_plane_init(struct drm_device *dev,
>  			  bool is_primary);
>  extern void drm_plane_cleanup(struct drm_plane *plane);
>  extern unsigned int drm_plane_index(struct drm_plane *plane);
> +extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
>  extern void drm_plane_force_disable(struct drm_plane *plane);
>  extern int drm_plane_check_pixel_format(const struct drm_plane *plane,
>  					u32 format);
> -- 
> 1.7.9.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index().
  2015-03-23  9:32   ` Daniel Vetter
@ 2015-03-23 16:32     ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-23 16:32 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Conselvan De Oliveira, Ander, intel-gfx, dri-devel, Vetter, Daniel



> -----Original Message-----
> From: Daniel Vetter [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel Vetter
> Sent: Monday, March 23, 2015 2:33 AM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Conselvan De Oliveira, Ander; Vetter, Daniel
> Subject: Re: [Intel-gfx] [PATCH 01/21 v2] drm/i915: Adding drm helper function
> drm_plane_from_index().
> 
> On Fri, Mar 20, 2015 at 05:04:22PM -0700, Chandra Konduru wrote:
> > Adding drm helper function to return plane pointer from index where
> > index is a returned by drm_plane_index.
> >
> > v2:
> > -avoided nested loop by adding loop count (Daniel)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> 
> Sorry forgotten to mention this earlier, but any code touching drm core must be
> cc'ed to dri-devel. Best to just add a Cc: line before the sob line so that git send-
> email automatically picks it up every time.
> -Daniel

np, sure.
By the way, copied dri-devel.

> 
> > ---
> >  drivers/gpu/drm/drm_crtc.c |   22 ++++++++++++++++++++++
> >  include/drm/drm_crtc.h     |    1 +
> >  2 files changed, 23 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > index 9f970c2..b6703f4 100644
> > --- a/drivers/gpu/drm/drm_crtc.c
> > +++ b/drivers/gpu/drm/drm_crtc.c
> > @@ -1286,6 +1286,28 @@ unsigned int drm_plane_index(struct drm_plane
> > *plane)  EXPORT_SYMBOL(drm_plane_index);
> >
> >  /**
> > + * drm_plane_from_index - find the registered plane at an index
> > + * @idx: index of registered plane to find for
> > + *
> > + * Given a plane index, return the registered plane from DRM device's
> > + * list of planes with matching index.
> > + */
> > +struct drm_plane *
> > +drm_plane_from_index(struct drm_device *dev, int idx) {
> > +	struct drm_plane *plane;
> > +	unsigned int i = 0;
> > +
> > +	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
> > +		if (i == idx)
> > +			return plane;
> > +		i++;
> > +	}
> > +	return NULL;
> > +}
> > +EXPORT_SYMBOL(drm_plane_from_index);
> > +
> > +/**
> >   * drm_plane_force_disable - Forcibly disable a plane
> >   * @plane: plane to disable
> >   *
> > diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index
> > 7b5c661..6b30036 100644
> > --- a/include/drm/drm_crtc.h
> > +++ b/include/drm/drm_crtc.h
> > @@ -1264,6 +1264,7 @@ extern int drm_plane_init(struct drm_device *dev,
> >  			  bool is_primary);
> >  extern void drm_plane_cleanup(struct drm_plane *plane);  extern
> > unsigned int drm_plane_index(struct drm_plane *plane);
> > +extern struct drm_plane * drm_plane_from_index(struct drm_device
> > +*dev, int idx);
> >  extern void drm_plane_force_disable(struct drm_plane *plane);  extern
> > int drm_plane_check_pixel_format(const struct drm_plane *plane,
> >  					u32 format);
> > --
> > 1.7.9.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions
  2015-03-21  0:04 ` [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions Chandra Konduru
@ 2015-03-25  5:13   ` Matt Roper
  2015-03-25 13:22     ` Daniel Vetter
  2015-03-25 16:54     ` Konduru, Chandra
  0 siblings, 2 replies; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:13 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:25PM -0700, Chandra Konduru wrote:
> skylake scaler structure definitions. scalers live in crtc_state as
> they are pipe resources. They can be used either as plane scaler or
> panel fitter.
> 
> scaler assigned to either plane (for plane scaling) or crtc (for panel
> fitting) is saved in scaler_id in plane_state or crtc_state respectively.
> 
> scaler_id is used instead of scaler pointer in plane or crtc state
> to avoid updating scaler pointer everytime a new crtc_state is created.
> 
> v2:
> -made single copy of min/max values for scalers (Matt)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drv.h |   99 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 99 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 3f7d05e..1da5087 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -256,6 +256,35 @@ struct intel_plane_state {
>  	 * enable/disable the primary plane
>  	 */
>  	bool hides_primary;
> +
> +	/*
> +	 * scaler_id
> +	 *    = -1 : not using a scaler
> +	 *    >=  0 : using a scalers
> +	 *
> +	 * plane requiring a scaler:
> +	 *   - During check_plane, its bit is set in
> +	 *     crtc_state->scaler_state.scaler_users by calling helper function
> +	 *     update_scaler_users.
> +	 *   - scaler_id indicates the scaler it got assigned.
> +	 *
> +	 * plane doesn't require a scaler:
> +	 *   - this can happen when scaling is no more required or plane simply
> +	 *     got disabled.
> +	 *   - During check_plane, corresponding bit is reset in
> +	 *     crtc_state->scaler_state.scaler_users by calling helper function
> +	 *     update_scaler_users.
> +	 *
> +	 *   There are two scenarios:
> +	 *   1. the freed up scaler is assigned to crtc or some other plane
> +	 *      In this case, as part of plane programming scaler_id will be set
> +	 *      to -1 using helper function detach_scalers
> +	 *   2. the freed up scaler is not assigned to anyone
> +	 *      In this case, as part of plane programming scaler registers will
> +	 *      be reset and scaler_id will also be reset to -1 using the same
> +	 *      helper function detach_scalers
> +	 */
> +	int scaler_id;
>  };
>  
>  struct intel_initial_plane_config {
> @@ -265,6 +294,74 @@ struct intel_initial_plane_config {
>  	u32 base;
>  };
>  
> +struct intel_scaler {
> +	int id;
> +	int in_use;
> +	uint32_t mode;

If I'm reading later patches correctly, this looks like this is always
PS_SCALER_MODE_HQ if one scaler is needed, or PS_SCALER_MODE_DYN if
multiple scalers are needed.  So the values for each of a CRTC's scalers
doesn't actually vary; should this just be a single value in
intel_crtc_scalar_state rather than being duplicated for each scaler?

> +	uint32_t filter;

Is filter a constant?  Unless I missed something in later patches, it
looks like it's set to PS_FILTER_MEDIUM and then never changed.  Can we
drop the field and just use the constant itself where appropriate?

> +};
> +
> +struct intel_crtc_scaler_state {
> +#define INTEL_MAX_SCALERS 2
> +#define SKL_NUM_SCALERS INTEL_MAX_SCALERS
> +	/* scalers available on this crtc */
> +	int num_scalers;

Maybe stick this in intel_crtc since it never changes (i.e., distinguish
runtime-changeable state from immutable hardware traits)?

> +	struct intel_scaler scalers[INTEL_MAX_SCALERS];
> +
> +	/*
> +	 * scaler_users: keeps track of users requesting scalers on this crtc.
> +	 *
> +	 *     If a bit is set, a user is using a scaler.
> +	 *     Here user can be a plane or crtc as defined below:
> +	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
> +	 *       bit 31    - crtc
> +	 *
> +	 * Instead of creating a new index to cover planes and crtc, using
> +	 * existing drm_plane_index for planes which is well less than 31
> +	 * planes and bit 31 for crtc. This should be fine to cover all
> +	 * our platforms.
> +	 *
> +	 * intel_atomic_setup_scalers will setup available scalers to users
> +	 * requesting scalers. It will gracefully fail if request exceeds
> +	 * avilability.
> +	 */
> +#define SKL_CRTC_INDEX 31
> +	unsigned scaler_users;
> +
> +	/* scaler used by crtc for panel fitting purpose */
> +	int scaler_id;

Calling this something like 'pfit_scaler_id' might make it a little more
intuitive what this is for when it's used in the code.

> +
> +	/*
> +	 * Supported scaling ratio is represented as a range in [min max]
> +	 * variables. This range covers both up and downscaling
> +	 * where scaling ratio = (dst * 100)/src.
> +	 * In above range any value:
> +	 *    < 100 represents downscaling coverage
> +	 *    > 100 represents upscaling coverage
> +	 *    = 100 represents no-scaling (i.e., 1:1)
> +	 * e.g., a min value = 50 means -> supports upto 50% of original image
> +	 *       a max value = 200 means -> supports upto 200% of original image
> +	 *
> +	 * if incoming flip requires scaling in the supported [min max] range
> +	 * then requested scaling will be performed.
> +	 */
> +	uint32_t min_hsr;
> +	uint32_t max_hsr;
> +	uint32_t min_vsr;
> +	uint32_t max_vsr;
> +	uint32_t min_hvsr;
> +	uint32_t max_hvsr;

I'm still not sure I understand why we need these in the state
structure.  The max_* fields here are set once, never changed, and never
even read back, so I think they're completely droppable.  The min_vsr
and min_hvsr fields are updated later, but never actually read back, so
I think they can go too.  The only value we actually make use of here is
min_hsr; I notice that it can get adjusted upward, but never downward,
so I'm not sure if the logic there (patch #7) is quite right, but we may
be able to just replace it with a direct use of crtc_clock instead?


> +
> +	uint32_t min_src_w;
> +	uint32_t max_src_w;
> +	uint32_t min_src_h;
> +	uint32_t max_src_h;
> +	uint32_t min_dst_w;
> +	uint32_t max_dst_w;
> +	uint32_t min_dst_h;
> +	uint32_t max_dst_h;

I think these are set once and never changed, so a simple #define might
be easier.

> +};
> +
>  struct intel_crtc_state {
>  	struct drm_crtc_state base;
>  
> @@ -391,6 +488,8 @@ struct intel_crtc_state {
>  
>  	bool dp_encoder_is_mst;
>  	int pbn;
> +
> +	struct intel_crtc_scaler_state scaler_state;

If we can kill off a bunch of the fields above, then we may be able to
put the remaining few fields directly in intel_crtc_state and eliminate
a level of structure nesting, which might make things a bit simpler.


Matt

>  };
>  
>  struct intel_pipe_wm {
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 05/21 v2] drm/i915: Initialize skylake scalers
  2015-03-21  0:04 ` [PATCH 05/21 v2] drm/i915: Initialize skylake scalers Chandra Konduru
@ 2015-03-25  5:14   ` Matt Roper
  2015-03-25 13:24     ` Daniel Vetter
  2015-03-25 16:56     ` Konduru, Chandra
  2015-03-25 23:21   ` [PATCH 05/21 v3] " Chandra Konduru
  1 sibling, 2 replies; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:14 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:26PM -0700, Chandra Konduru wrote:
> Initializing scalers with supported values during crtc init.
> 
> v2:
> -initialize single copy of min/max values (Matt)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c |   53 ++++++++++++++++++++++++++++++++++
>  1 file changed, 53 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 89299b6..e6ea9e0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -103,6 +103,8 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
>  			    const struct intel_crtc_state *pipe_config);
>  static void intel_begin_crtc_commit(struct drm_crtc *crtc);
>  static void intel_finish_crtc_commit(struct drm_crtc *crtc);
> +static void skl_init_scalers(struct drm_device *dev, int pipe,
> +	struct intel_crtc_state *crtc_state);
>  
>  static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
>  {
> @@ -12750,6 +12752,54 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
>  	return &cursor->base;
>  }
>  
> +static void skl_init_scalers(struct drm_device *dev, int pipe,
> +	struct intel_crtc_state *crtc_state)
> +{
> +	int i;
> +	struct intel_scaler *intel_scaler;
> +	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
> +	if (INTEL_INFO(dev)->gen < 9)
> +		return;

It's probably better to move this guard out to the callsite so that we
can more easily extend this for future platforms.  Unless you plan to
just extend this function in the future, in which case we should
probably drop the 'skl_' prefix.


Matt

> +
> +	scaler_state->num_scalers = SKL_NUM_SCALERS;
> +	for (i = 0; i < SKL_NUM_SCALERS; i++) {
> +		intel_scaler = &scaler_state->scalers[i];
> +		intel_scaler->in_use = 0;
> +		intel_scaler->id = i;
> +
> +		intel_scaler->mode = PS_SCALER_MODE_DYN;
> +		intel_scaler->filter = PS_FILTER_MEDIUM;
> +	}
> +
> +	/* down scaling ratio: 2.99 --> 1, i.e., 34% of original */
> +	scaler_state->min_hsr = 34;
> +	scaler_state->min_vsr = 34;
> +	scaler_state->max_hsr = 500;
> +	scaler_state->max_vsr = 500;
> +
> +	/* down scaling ratio: 2.99x2.99 --> 1x1, i.e., 12% of original */
> +	scaler_state->min_hvsr = 12;
> +	scaler_state->max_hvsr = 2500;
> +
> +	/* src_w & dst_w range 8 - 4096 */
> +	scaler_state->min_src_w = 8;
> +	scaler_state->max_src_w = 4096;
> +	scaler_state->min_dst_w = 8;
> +	scaler_state->max_dst_w = 4096;
> +
> +	/* src_h & dst_h range 8 - 2304 */
> +	scaler_state->min_src_h = 8;
> +	scaler_state->max_src_h = 2304;
> +	scaler_state->min_dst_h = 8;
> +	scaler_state->max_dst_h = 2304;
> +
> +	/* pipe C has one scaler */
> +	if (pipe == PIPE_C) {
> +		scaler_state->num_scalers = 1;
> +	}
> +	scaler_state->scaler_id = -1;
> +}
> +
>  static void intel_crtc_init(struct drm_device *dev, int pipe)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> @@ -12769,6 +12819,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
>  	intel_crtc_set_state(intel_crtc, crtc_state);
>  	crtc_state->base.crtc = &intel_crtc->base;
>  
> +	/* initialize shared scalers */
> +	skl_init_scalers(dev, pipe, crtc_state);
> +
>  	primary = intel_primary_plane_create(dev, pipe);
>  	if (!primary)
>  		goto fail;
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio.
  2015-03-21  0:04 ` [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio Chandra Konduru
@ 2015-03-25  5:14   ` Matt Roper
  2015-03-25 17:37     ` Konduru, Chandra
  2015-03-25 23:21   ` [PATCH 07/21 v3] " Chandra Konduru
  1 sibling, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:14 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:28PM -0700, Chandra Konduru wrote:
> Helper function updates supported scaling ratios based on cdclk and
> crtc clocks.
> 
> v2:
> -update single copy of scaling ratios (Matt)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c |   25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 20f13c8..890d372 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4513,6 +4513,31 @@ static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
>  	intel_wait_for_vblank(dev, other_active_crtc->pipe);
>  }
>  
> +static void skl_update_scaling_ratio(struct drm_device *dev,
> +	struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	uint32_t crtc_clock, cdclk;
> +	struct intel_crtc_scaler_state *scaler_state;
> +
> +	if (!crtc_state)
> +		return;
> +
> +	crtc_clock = (uint32_t) crtc_state->base.adjusted_mode.crtc_clock;
> +	cdclk = (uint32_t) intel_ddi_get_cdclk_freq(dev_priv);
> +
> +	if (!crtc_clock || !cdclk)
> +		return;
> +
> +	scaler_state = &crtc_state->scaler_state;
> +	scaler_state->min_hsr = max(scaler_state->min_hsr, (crtc_clock * 100)/cdclk);
> +	scaler_state->min_vsr = max(scaler_state->min_hsr, (crtc_clock * 100)/cdclk);

I don't have access to the bspec at the moment, but this seems a little
strange...the minimums here can go up when you change mode, but they can
never go back down again, even if you go back to the original mode?
It feels like the first parameter to max() here should have been a
constant for the lowest min the hardware can support.

> +	scaler_state->min_hvsr = max(scaler_state->min_hsr, (crtc_clock * 100)/cdclk);
                                                   ^^^^^^^
                                                   min_hvsr?


> +
> +	DRM_DEBUG_KMS("for crtc_state = %p crtc_clock = %d cdclk = %d\n", crtc_state,
> +		crtc_clock, cdclk);
> +}
> +
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state
  2015-03-21  0:04 ` [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state Chandra Konduru
@ 2015-03-25  5:15   ` Matt Roper
  2015-03-25 19:20     ` Konduru, Chandra
  2015-03-25 23:21   ` [PATCH 08/21 v3] " Chandra Konduru
  1 sibling, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:15 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:29PM -0700, Chandra Konduru wrote:
> This helper function stages a scaler request for a plane/crtc into
> crtc_state->scaler_users (which is a bit field). It also performs
> required checks before staging any change into scaler_state.
> 
> v2:
> -updates to use single copy of scaler limits (Matt)
> -added force detach parameter for pfit disable purpose (me)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c |  143 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |    3 +
>  2 files changed, 146 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 890d372..976bfb1 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12387,6 +12387,149 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
>  	}
>  }
>  
> +/*
> + * Update crtc_state->scaler_users for requested plane or crtc based on state.

I realize you're trying to re-use some logic here, but I find the
overloaded function that works on either planes or crtcs a bit harder to
follow.  Personally I'd prefer if this were just two separate functions,
one focused on planes, one focused on CRTC's, even if it means
duplicating a little bit of the logic.

> + *
> + * plane (in)
> + *     NULL - for crtc
> + *     not NULL - for plane
> + * force_detach (in)
> + *     unconditionally scaler will be staged for detachment from crtc/plane
> + * Return
> + *     0 - scaler_usage updated successfully
> + *    error - requested scaling cannot be supported or other error condition
> + */

Probably want to put this in kerneldoc format.

> +int
> +skl_update_scaler_users(
> +	struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state,
> +	struct intel_plane *intel_plane, struct intel_plane_state *plane_state,

Might be a little easier to drop the intel_crtc and intel_plane
parameters and just pull them out of the state backpointers.

> +	int force_detach)
> +{
> +	int need_scaling;
> +	int idx;
> +	int src_w, src_h, dst_w, dst_h;
> +	int scaler_id;
> +	struct drm_framebuffer *fb;
> +	struct intel_crtc_scaler_state *scaler_state;
> +
> +	if (!intel_crtc || !crtc_state ||
> +		(intel_plane && intel_plane->base.type == DRM_PLANE_TYPE_CURSOR))
> +		return 0;
> +
> +	scaler_state = &crtc_state->scaler_state;
> +
> +	if (!scaler_state->num_scalers) {
> +		DRM_DEBUG_KMS("crtc_state = %p, num_scalers = %d\n", crtc_state,
> +			scaler_state->num_scalers);
> +		return 0;
> +	}
> +
> +	idx = intel_plane ? drm_plane_index(&intel_plane->base) : SKL_CRTC_INDEX;
> +	fb = intel_plane ? plane_state->base.fb : NULL;
> +
> +	if (intel_plane) {
> +		src_w = drm_rect_width(&plane_state->src) >> 16;
> +		src_h = drm_rect_height(&plane_state->src) >> 16;
> +		dst_w = drm_rect_width(&plane_state->dst);
> +		dst_h = drm_rect_height(&plane_state->dst);
> +		scaler_id = plane_state->scaler_id;
> +	} else {
> +		struct drm_display_mode *adjusted_mode =
> +			&crtc_state->base.adjusted_mode;
> +		src_w = crtc_state->pipe_src_w;
> +		src_h = crtc_state->pipe_src_h;
> +		dst_w = adjusted_mode->hdisplay;
> +		dst_h = adjusted_mode->vdisplay;
> +		scaler_id = scaler_state->scaler_id;
> +	}
> +	need_scaling = (src_w != dst_w || src_h != dst_h);

We're already calculating this in the plane check function; we should
probably just store the result in a plane_state field at that point so
we don't have to re-calculate it here.


> +
> +	/*
> +	 * if plane is being disabled or scaler is no more required or force detach

Maybe it will become more clear later in the patch series, but I'm not
sure I understand what 'force_detach' does.  Won't scalers that we don't
end up re-assigning automatically be cleared when we nobody makes use of
them in a new commit?

> +	 *  - free scaler binded to this plane/crtc
> +	 *  - in order to do this, update crtc->scaler_usage
> +	 *
> +	 * Here scaler state in crtc_state is set free so that
> +	 * scaler can be assigned to other user. Actual register
> +	 * update to free the scaler is done in plane/panel-fit programming.
> +	 * For this purpose crtc/plane_state->scaler_id isn't reset here.
> +	 */
> +	if (force_detach || !need_scaling || (intel_plane &&
> +		(!fb || !plane_state->visible))) {
> +		if (scaler_id >= 0) {
> +			scaler_state->scaler_users &= ~(1 << idx);
> +			scaler_state->scalers[scaler_id].in_use = 0;
> +
> +			DRM_DEBUG_KMS("Staged freeing scaler id %u.%u from %s:%d "
> +				"crtc_state = %p scaler_users = 0x%x\n",
> +				intel_crtc->pipe, scaler_id, intel_plane ? "PLANE" : "CRTC",
> +				intel_plane ? intel_plane->base.base.id :
> +				intel_crtc->base.base.id, crtc_state,
> +				scaler_state->scaler_users);
> +		}
> +		return 0;
> +	}
> +
> +	/*
> +	 * check for rect size:
> +	 *     min sizes in case of scaling involved
> +	 *     max sizes in all cases
> +	 */
> +	if ((need_scaling &&

need_scaling is guaranteed to be true now (otherwise we would have
returned above), so we can drop this test.

> +		(src_w < scaler_state->min_src_w || src_h < scaler_state->min_src_h ||
> +		 dst_w < scaler_state->min_dst_w || dst_h < scaler_state->min_dst_h)) ||
> +
> +		 src_w > scaler_state->max_src_w || src_h > scaler_state->max_src_h ||
> +		 dst_w > scaler_state->max_dst_w || dst_h > scaler_state->max_dst_h) {
> +		DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u dst %ux%u "
> +			"size is out of scaler range\n",
> +			intel_plane ? "PLANE" : "CRTC",
> +			intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
> +			intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h);
> +		return -EINVAL;
> +	}
> +
> +	/* check colorkey */
> +	if (intel_plane && need_scaling && intel_colorkey_enabled(intel_plane)) {

Can drop 'need_scaling' test again.

> +		DRM_DEBUG_KMS("PLANE:%d scaling with color key not allowed",
> +			intel_plane->base.base.id);
> +		return -EINVAL;
> +	}
> +
> +	/* Check src format */
> +	if (intel_plane && need_scaling) {

Ditto

> +		switch (fb->pixel_format) {
> +		case DRM_FORMAT_RGB565:
> +		case DRM_FORMAT_XBGR8888:
> +		case DRM_FORMAT_XRGB8888:
> +		case DRM_FORMAT_ABGR8888:
> +		case DRM_FORMAT_ARGB8888:
> +		case DRM_FORMAT_XRGB2101010:
> +		case DRM_FORMAT_ARGB2101010:
> +		case DRM_FORMAT_XBGR2101010:
> +		case DRM_FORMAT_ABGR2101010:
> +		case DRM_FORMAT_YUYV:
> +		case DRM_FORMAT_YVYU:
> +		case DRM_FORMAT_UYVY:
> +		case DRM_FORMAT_VYUY:
> +			break;
> +		default:
> +			DRM_DEBUG_KMS("PLANE:%d FB:%d format 0x%x not supported\n",
> +				intel_plane->base.base.id, fb->base.id, fb->pixel_format);

Might want to add "...while scaling" to this message to avoid confusion.

> +			return -EINVAL;
> +		}
> +	}
> +
> +	/* mark this plane as a scaler user in crtc_state */
> +	scaler_state->scaler_users |= (1 << idx);
> +	DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u "
> +		"crtc_state = %p scaler_users = 0x%x\n",
> +		intel_plane ? "PLANE" : "CRTC",
> +		intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
> +		src_w, src_h, dst_w, dst_h, crtc_state, scaler_state->scaler_users);
> +	return 0;
> +}
> +
>  static int
>  intel_check_primary_plane(struct drm_plane *plane,
>  			  struct intel_plane_state *state)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 1da5087..f5d53c9 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1138,6 +1138,9 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  				 struct intel_crtc_state *pipe_config);
>  void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
>  void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
> +int skl_update_scaler_users(struct intel_crtc *intel_crtc,
> +	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
> +	struct intel_plane_state *plane_state, int force_detach);
>  
>  /* intel_dp.c */
>  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
> -- 
> 1.7.9.5

You should probably just squash this into the later patches where you
actually call it (e.g., patch 18) so it's more clear how/when/where it
is used.


Matt

> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc.
  2015-03-21  0:04 ` [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc Chandra Konduru
@ 2015-03-25  5:15   ` Matt Roper
  2015-03-25 19:46     ` Konduru, Chandra
  2015-03-25 23:21   ` [PATCH 09/21 v3] " Chandra Konduru
  1 sibling, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:15 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:30PM -0700, Chandra Konduru wrote:
> intel_atomic_setup_scalers sets up scalers based on staged scaling
> requests coming from a crtc and its planes. This function should be
> called from crtc level check path.
> 
> If staged requests are supportable, function assigns scalers to
> requested planes and crtc. This function also takes into account
> the current planes using scalers but not being part of this
> atomic state for optimal operation of scalers. Note that the scaler
> assignement itself is staged into crtc_state and respective
> plane_states for later commit after all checks have been done.
> 
> overall high level flow:
>  - scaler requests are staged into crtc_state by planes/crtc
>  - check whether staged scaling requests can be supported
>  - add planes using scalers that aren't in current transaction
>  - assign scalers to requested users
>  - as part of plane commit, scalers will be committed
>    (i.e., either attached or detached) to respective planes in hw
>  - as part of crtc_commit, scaler will be either attached or detached
>    to crtc in hw
> 
> v2:
> -removed a log message (me)
> -changed input parameter to crtc_state (me)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_atomic.c |  138 +++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h    |    3 +
>  2 files changed, 141 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> index 3903b90..407516a 100644
> --- a/drivers/gpu/drm/i915/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/intel_atomic.c
> @@ -241,3 +241,141 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
>  {
>  	drm_atomic_helper_crtc_destroy_state(crtc, state);
>  }
> +
> +/**
> + * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
> + * @dev: DRM device
> + * @crtc: intel crtc
> + * @crtc_state: incoming crtc_state to validate and setup scalers
> + *
> + * This function setups up scalers based on staged scaling requests for

s/setups up/sets up/

> + * a @crtc and its planes. It is called from crtc level check path. If request
> + * is a supportable request, it attaches scalers to requested planes and crtc.
> + *
> + * This function takes into account the current scaler(s) in use by any planes
> + * not being part of this atomic state
> + *
> + *  Returns:
> + *         0 - scalers were setup succesfully
> + *         error code - otherwise
> + */
> +int intel_atomic_setup_scalers(struct drm_device *dev,
> +	struct intel_crtc *intel_crtc,
> +	struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_plane *plane = NULL;
> +	struct intel_plane *intel_plane;
> +	struct intel_plane_state *plane_state = NULL;
> +	struct intel_crtc_scaler_state *scaler_state;
> +	struct drm_atomic_state *drm_state;
> +	int num_scalers_need;
> +	int i, j;
> +
> +	if (INTEL_INFO(dev)->gen < 9 || !intel_crtc || !crtc_state)
> +		return 0;
> +
> +	scaler_state = &crtc_state->scaler_state;
> +	drm_state = crtc_state->base.state;
> +
> +	num_scalers_need = hweight32(scaler_state->scaler_users);
> +	DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n",
> +		crtc_state, num_scalers_need, scaler_state->num_scalers,
> +		scaler_state->scaler_users);
> +
> +	/* if there is no change in scaler configuration, return */
> +	if (scaler_state->scaler_users ==
> +		intel_crtc->config->scaler_state.scaler_users)
> +		return 0;
> +
> +	/*
> +	 * High level flow:
> +	 * - staged scaler requests are already in scaler_state->scaler_users
> +	 * - check whether staged scaling requests can be supported
> +	 * - add planes using scalers that aren't in current transaction
> +	 * - assign scalers to requested users
> +	 * - as part of plane commit, scalers will be committed
> +	 *   (i.e., either attached or detached) to respective planes in hw
> +	 * - as part of crtc_commit, scaler will be either attached or detached
> +	 *   to crtc in hw
> +	 */
> +
> +	/* fail if required scalers > available scalers */
> +	if (num_scalers_need > scaler_state->num_scalers){
> +		DRM_DEBUG_KMS("Too many scaling requests %d > %d\n",
> +			num_scalers_need, scaler_state->num_scalers);
> +		return -EINVAL;
> +	}
> +
> +	/* walkthrough scaler_users bits and start assigning scalers */
> +	for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
> +		int *scaler_id;
> +
> +		/* skip if scaler not required */
> +		if (!(scaler_state->scaler_users & (1 << i)))
> +			continue;
> +
> +		if (i == SKL_CRTC_INDEX) {
> +			/* panel fitter case: assign as a crtc scaler */
> +			scaler_id = &scaler_state->scaler_id;
> +		} else {
> +			if (!drm_state)
> +				continue;

This shouldn't happen, at least not once we're back on the full atomic
helpers, right?  It seems like if it does happen, nothing's going to
work right, so maybe add a WARN_ON() to this test?

> +
> +			/* plane scaler case: assign as a plane scaler */
> +			/* find the plane that set the bit as scaler_user */
> +			plane = drm_state->planes[i];
> +
> +			/*
> +			 * to enable/disable hq mode, add planes that are using scaler
> +			 * into this transaction
> +			 */
> +			if (!plane) {
> +				plane = drm_plane_from_index(dev, i);
> +				drm_state->planes[i] = plane;
> +				drm_state->plane_states[i] =
> +					drm_atomic_get_plane_state(drm_state, plane);

I think you need to test for EDEADLK here in case we have a w/w
collision.  Other errors like ENOMEM might also happen.  Actually,
drm_atomic_get_plane_state() will take care of adding the state to the
plane_states[] array for you, so no need for the assignment; you can
just call the function and check for error returns.

> +			}
> +
> +			intel_plane = to_intel_plane(plane);
> +
> +			/* plane on different crtc cannot be a scaler user of this crtc */
> +			if (WARN_ON(intel_plane->pipe != intel_crtc->pipe)) {
> +				continue;
> +			}
> +
> +			plane_state = to_intel_plane_state(drm_state->plane_states[i]);
> +			scaler_id = &plane_state->scaler_id;
> +		}
> +
> +		if (*scaler_id < 0) {
> +			/* find a free scaler */
> +			for (j = 0; j < scaler_state->num_scalers; j++) {
> +				if (!scaler_state->scalers[j].in_use) {
> +					scaler_state->scalers[j].in_use = 1;
> +					*scaler_id = scaler_state->scalers[j].id;
> +					DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n",
> +						intel_crtc->pipe,
> +						i == SKL_CRTC_INDEX ? scaler_state->scaler_id :
> +							plane_state->scaler_id,
> +						i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
> +						i == SKL_CRTC_INDEX ?  intel_crtc->base.base.id :
> +						plane->base.id);
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (WARN_ON(*scaler_id < 0)) {
> +			DRM_DEBUG_KMS("Cannot find scaler for %s:%d\n",
> +				i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
> +				i == SKL_CRTC_INDEX ? intel_crtc->base.base.id:plane->base.id);
> +			continue;
> +		}
> +
> +		/* set scaler mode */
> +		scaler_state->scalers[*scaler_id].mode = (num_scalers_need == 1) ?
> +			PS_SCALER_MODE_HQ : PS_SCALER_MODE_DYN;
> +	}
> +
> +	return 0;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f5d53c9..a9d787d 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1401,6 +1401,9 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
>  
>  	return to_intel_crtc_state(crtc_state);
>  }
> +int intel_atomic_setup_scalers(struct drm_device *dev,
> +	struct intel_crtc *intel_crtc,
> +	struct intel_crtc_state *crtc_state);
>  
>  /* intel_atomic_plane.c */
>  struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane);
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-21  0:04 ` [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc Chandra Konduru
@ 2015-03-25  5:15   ` Matt Roper
  2015-03-25 20:14     ` Konduru, Chandra
  2015-03-25 23:21   ` [PATCH 10/21 v3] " Chandra Konduru
  1 sibling, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:15 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:31PM -0700, Chandra Konduru wrote:
> This function is called from commit path of a plane or crtc.
> It programs scaler registers to detach (aka. unbinds) scaler
> from requested plane or crtc if it isn't in use. It also resets
> scaler_id in crtc/plane state.
> 
> v2:
> -improved a log message (me)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c |   39 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |    1 +
>  2 files changed, 40 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 976bfb1..7150c33 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
>  	}
>  }
>  
> +/*
> + * This function detaches (aka. unbinds) a scaler from plane or crtc

You might want to clarify that detach/unbind refers to the actual
hardware programming, not the state calculation.  I'm a bit surprised we
need this function; I figured we'd just be looping over all scalers at
the end of the commit step and progamming them to either on or off
depending on what the scaling state contained.

As I mentioned on a previous patch, these overloaded functions that
might operate on a plane or might operate on a CRTC can be a bit
confusing, especially when we have multi-nested ternary operators like
you do below.

> + * if scaler is not in use.
> + * It resets scaler_id in plane or crtc
> + * To request detach a scaler from crtc, call plane as NULL
> + */
> +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc_state *crtc_state;
> +	struct intel_crtc *intel_crtc;
> +	struct intel_plane *intel_plane;
> +	struct intel_plane_state *plane_state;
> +	int *scaler_id;
> +
> +	intel_crtc = to_intel_crtc(crtc);
> +	intel_plane = plane ? to_intel_plane(plane) : NULL;
> +	crtc_state = intel_crtc->config;
> +	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
> +
> +	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
> +		&crtc_state->scaler_state.scaler_id;
> +
> +	if (!scaler_id || (scaler_id && *scaler_id < 0))
> +		return;
> +
> +	/* if scaler is not in use, free */
> +	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
> +		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
> +		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)), 0);
> +		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
> +		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u from %s:%d\n",
> +			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
> +			plane ? plane->base.id : crtc->base.id);
> +		*scaler_id = -1;

This confuses me...why are we updating the state here at the end of the
commit step?  State should be immutable at this point, right?


Matt

> +	}
> +}
> +
>  static void skylake_update_primary_plane(struct drm_crtc *crtc,
>  					 struct drm_framebuffer *fb,
>  					 int x, int y)
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index a9d787d..f25d14d 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1141,6 +1141,7 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
>  int skl_update_scaler_users(struct intel_crtc *intel_crtc,
>  	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
>  	struct intel_plane_state *plane_state, int force_detach);
> +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane);
>  
>  /* intel_dp.c */
>  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 11/21 v2] drm/i915: Ensure planes begin with no scaler.
  2015-03-21  0:04 ` [PATCH 11/21 v2] drm/i915: Ensure planes begin with no scaler Chandra Konduru
@ 2015-03-25  5:17   ` Matt Roper
  0 siblings, 0 replies; 56+ messages in thread
From: Matt Roper @ 2015-03-25  5:17 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:32PM -0700, Chandra Konduru wrote:
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>

I'd squash this into patch 4, when you first added this field.


Matt

> ---
>  drivers/gpu/drm/i915/intel_display.c |    2 ++
>  drivers/gpu/drm/i915/intel_sprite.c  |    1 +
>  2 files changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7150c33..ffaed7b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12819,6 +12819,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
>  
>  	primary->can_scale = false;
>  	primary->max_downscale = 1;
> +	state->scaler_id = -1;
>  	primary->pipe = pipe;
>  	primary->plane = pipe;
>  	primary->check_plane = intel_check_primary_plane;
> @@ -12976,6 +12977,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
>  	cursor->max_downscale = 1;
>  	cursor->pipe = pipe;
>  	cursor->plane = pipe;
> +	state->scaler_id = -1;
>  	cursor->check_plane = intel_check_cursor_plane;
>  	cursor->commit_plane = intel_commit_cursor_plane;
>  
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 9ee12d0..c010528 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -1497,6 +1497,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
>  		intel_plane->disable_plane = skl_disable_plane;
>  		intel_plane->update_colorkey = skl_update_colorkey;
>  		intel_plane->get_colorkey = skl_get_colorkey;
> +		state->scaler_id = -1;
>  
>  		plane_formats = skl_plane_formats;
>  		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions
  2015-03-25  5:13   ` Matt Roper
@ 2015-03-25 13:22     ` Daniel Vetter
  2015-03-25 16:54     ` Konduru, Chandra
  1 sibling, 0 replies; 56+ messages in thread
From: Daniel Vetter @ 2015-03-25 13:22 UTC (permalink / raw)
  To: Matt Roper; +Cc: ander.conselvan.de.oliveira, daniel.vetter, intel-gfx

On Tue, Mar 24, 2015 at 10:13:54PM -0700, Matt Roper wrote:
> On Fri, Mar 20, 2015 at 05:04:25PM -0700, Chandra Konduru wrote:
> > +struct intel_scaler {
> > +	int id;
> > +	int in_use;
> > +	uint32_t mode;
> 
> If I'm reading later patches correctly, this looks like this is always
> PS_SCALER_MODE_HQ if one scaler is needed, or PS_SCALER_MODE_DYN if
> multiple scalers are needed.  So the values for each of a CRTC's scalers
> doesn't actually vary; should this just be a single value in
> intel_crtc_scalar_state rather than being duplicated for each scaler?

Or we can just compute it at runtime with hweight of the inuse scaler
bitmask.

> > +	uint32_t filter;
> 
> Is filter a constant?  Unless I missed something in later patches, it
> looks like it's set to PS_FILTER_MEDIUM and then never changed.  Can we
> drop the field and just use the constant itself where appropriate?

Concured. I prefer that we add struct members only when there's a need -
all that indirection just makes it harder to follow the code logic.

I also agree with all of the other comments from Matt cut out here.

[snip]

> > +	struct intel_crtc_scaler_state scaler_state;
> 
> If we can kill off a bunch of the fields above, then we may be able to
> put the remaining few fields directly in intel_crtc_state and eliminate
> a level of structure nesting, which might make things a bit simpler.

Imo substructures for separate things make sense - otherwise we'll just
have a pile of members with the same prefix, which semantically is exactly
the same thing. But I agree that reducing dynamic state to only the bits
that are indeed dynamic (and not trivially derived from existing dynamic
state) is a good goal.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 05/21 v2] drm/i915: Initialize skylake scalers
  2015-03-25  5:14   ` Matt Roper
@ 2015-03-25 13:24     ` Daniel Vetter
  2015-03-25 16:56     ` Konduru, Chandra
  1 sibling, 0 replies; 56+ messages in thread
From: Daniel Vetter @ 2015-03-25 13:24 UTC (permalink / raw)
  To: Matt Roper; +Cc: ander.conselvan.de.oliveira, daniel.vetter, intel-gfx

On Tue, Mar 24, 2015 at 10:14:01PM -0700, Matt Roper wrote:
> On Fri, Mar 20, 2015 at 05:04:26PM -0700, Chandra Konduru wrote:
> > +static void skl_init_scalers(struct drm_device *dev, int pipe,
> > +	struct intel_crtc_state *crtc_state)
> > +{
> > +	int i;
> > +	struct intel_scaler *intel_scaler;
> > +	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
> > +	if (INTEL_INFO(dev)->gen < 9)
> > +		return;
> 
> It's probably better to move this guard out to the callsite so that we
> can more easily extend this for future platforms.  Unless you plan to
> just extend this function in the future, in which case we should
> probably drop the 'skl_' prefix.

Naming rule is that platform-specific stuff is named with the first
platform codename that uses it. So skl_ is still fine even if we extend
this for bxt or skl+1. intel_ should only be used for truly generic
driver-wide stuff.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions
  2015-03-25  5:13   ` Matt Roper
  2015-03-25 13:22     ` Daniel Vetter
@ 2015-03-25 16:54     ` Konduru, Chandra
  1 sibling, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 16:54 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Tuesday, March 24, 2015 10:14 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions
> 
> On Fri, Mar 20, 2015 at 05:04:25PM -0700, Chandra Konduru wrote:
> > skylake scaler structure definitions. scalers live in crtc_state as
> > they are pipe resources. They can be used either as plane scaler or
> > panel fitter.
> >
> > scaler assigned to either plane (for plane scaling) or crtc (for panel
> > fitting) is saved in scaler_id in plane_state or crtc_state respectively.
> >
> > scaler_id is used instead of scaler pointer in plane or crtc state to
> > avoid updating scaler pointer everytime a new crtc_state is created.
> >
> > v2:
> > -made single copy of min/max values for scalers (Matt)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_drv.h |   99
> ++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 99 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index 3f7d05e..1da5087 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -256,6 +256,35 @@ struct intel_plane_state {
> >  	 * enable/disable the primary plane
> >  	 */
> >  	bool hides_primary;
> > +
> > +	/*
> > +	 * scaler_id
> > +	 *    = -1 : not using a scaler
> > +	 *    >=  0 : using a scalers
> > +	 *
> > +	 * plane requiring a scaler:
> > +	 *   - During check_plane, its bit is set in
> > +	 *     crtc_state->scaler_state.scaler_users by calling helper function
> > +	 *     update_scaler_users.
> > +	 *   - scaler_id indicates the scaler it got assigned.
> > +	 *
> > +	 * plane doesn't require a scaler:
> > +	 *   - this can happen when scaling is no more required or plane simply
> > +	 *     got disabled.
> > +	 *   - During check_plane, corresponding bit is reset in
> > +	 *     crtc_state->scaler_state.scaler_users by calling helper function
> > +	 *     update_scaler_users.
> > +	 *
> > +	 *   There are two scenarios:
> > +	 *   1. the freed up scaler is assigned to crtc or some other plane
> > +	 *      In this case, as part of plane programming scaler_id will be set
> > +	 *      to -1 using helper function detach_scalers
> > +	 *   2. the freed up scaler is not assigned to anyone
> > +	 *      In this case, as part of plane programming scaler registers will
> > +	 *      be reset and scaler_id will also be reset to -1 using the same
> > +	 *      helper function detach_scalers
> > +	 */
> > +	int scaler_id;
> >  };
> >
> >  struct intel_initial_plane_config {
> > @@ -265,6 +294,74 @@ struct intel_initial_plane_config {
> >  	u32 base;
> >  };
> >
> > +struct intel_scaler {
> > +	int id;
> > +	int in_use;
> > +	uint32_t mode;
> 
> If I'm reading later patches correctly, this looks like this is always
> PS_SCALER_MODE_HQ if one scaler is needed, or PS_SCALER_MODE_DYN if
> multiple scalers are needed.  So the values for each of a CRTC's scalers doesn't
> actually vary; should this just be a single value in intel_crtc_scalar_state rather
> than being duplicated for each scaler?

There is another mode required for nv12 which is coming up in next 
series. So it needs per scaler mode.

> 
> > +	uint32_t filter;
> 
> Is filter a constant?  Unless I missed something in later patches, it looks like it's
> set to PS_FILTER_MEDIUM and then never changed.  Can we drop the field and
> just use the constant itself where appropriate?

Hardware has additional filter types. Initial implementation is using only one type.
So kept it as a parameter in scaler than hardcoding. 

> 
> > +};
> > +
> > +struct intel_crtc_scaler_state {
> > +#define INTEL_MAX_SCALERS 2
> > +#define SKL_NUM_SCALERS INTEL_MAX_SCALERS
> > +	/* scalers available on this crtc */
> > +	int num_scalers;
> 
> Maybe stick this in intel_crtc since it never changes (i.e., distinguish runtime-
> changeable state from immutable hardware traits)?

The approach I followed is to keep all scaler related in one place. 
Certainly this can go to crtc, but don't see any issue by keeping it here.

> 
> > +	struct intel_scaler scalers[INTEL_MAX_SCALERS];
> > +
> > +	/*
> > +	 * scaler_users: keeps track of users requesting scalers on this crtc.
> > +	 *
> > +	 *     If a bit is set, a user is using a scaler.
> > +	 *     Here user can be a plane or crtc as defined below:
> > +	 *       bits 0-30 - plane (bit position is index from drm_plane_index)
> > +	 *       bit 31    - crtc
> > +	 *
> > +	 * Instead of creating a new index to cover planes and crtc, using
> > +	 * existing drm_plane_index for planes which is well less than 31
> > +	 * planes and bit 31 for crtc. This should be fine to cover all
> > +	 * our platforms.
> > +	 *
> > +	 * intel_atomic_setup_scalers will setup available scalers to users
> > +	 * requesting scalers. It will gracefully fail if request exceeds
> > +	 * avilability.
> > +	 */
> > +#define SKL_CRTC_INDEX 31
> > +	unsigned scaler_users;
> > +
> > +	/* scaler used by crtc for panel fitting purpose */
> > +	int scaler_id;
> 
> Calling this something like 'pfit_scaler_id' might make it a little more intuitive
> what this is for when it's used in the code.

Sure, but it is obvious that scaler_id here is for crtc, as it is hanging inside crtc_state.

> 
> > +
> > +	/*
> > +	 * Supported scaling ratio is represented as a range in [min max]
> > +	 * variables. This range covers both up and downscaling
> > +	 * where scaling ratio = (dst * 100)/src.
> > +	 * In above range any value:
> > +	 *    < 100 represents downscaling coverage
> > +	 *    > 100 represents upscaling coverage
> > +	 *    = 100 represents no-scaling (i.e., 1:1)
> > +	 * e.g., a min value = 50 means -> supports upto 50% of original image
> > +	 *       a max value = 200 means -> supports upto 200% of original image
> > +	 *
> > +	 * if incoming flip requires scaling in the supported [min max] range
> > +	 * then requested scaling will be performed.
> > +	 */
> > +	uint32_t min_hsr;
> > +	uint32_t max_hsr;
> > +	uint32_t min_vsr;
> > +	uint32_t max_vsr;
> > +	uint32_t min_hvsr;
> > +	uint32_t max_hvsr;
> 
> I'm still not sure I understand why we need these in the state structure.  The
> max_* fields here are set once, never changed, and never even read back, so I
> think they're completely droppable.  The min_vsr and min_hvsr fields are
> updated later, but never actually read back, so I think they can go too.  The only
> value we actually make use of here is min_hsr; I notice that it can get adjusted
> upward, but never downward, so I'm not sure if the logic there (patch #7) is
> quite right, but we may be able to just replace it with a direct use of crtc_clock
> instead?
> 

The approach I took is have state maintain values not only for this platform
but for upcoming platform. This way, check function can be used not only
for skl but also for upcoming platforms by initializing them appropriately
in init function.
Max fields can be dropped for skl, but kept it for above reason.
Also currently there aren't properties to expose scaler limits/ranges to 
userland. One another reason for keeping them is to report as part of
properties once they gets added in drm core. Even if we don't add
for any reason, there is no harm in having all scaler limits in one place.

> 
> > +
> > +	uint32_t min_src_w;
> > +	uint32_t max_src_w;
> > +	uint32_t min_src_h;
> > +	uint32_t max_src_h;
> > +	uint32_t min_dst_w;
> > +	uint32_t max_dst_w;
> > +	uint32_t min_dst_h;
> > +	uint32_t max_dst_h;
> 
> I think these are set once and never changed, so a simple #define might be
> easier.

Again these were also kept here to make functions that use them work for upcoming
platforms.

> 
> > +};
> > +
> >  struct intel_crtc_state {
> >  	struct drm_crtc_state base;
> >
> > @@ -391,6 +488,8 @@ struct intel_crtc_state {
> >
> >  	bool dp_encoder_is_mst;
> >  	int pbn;
> > +
> > +	struct intel_crtc_scaler_state scaler_state;
> 
> If we can kill off a bunch of the fields above, then we may be able to put the
> remaining few fields directly in intel_crtc_state and eliminate a level of structure
> nesting, which might make things a bit simpler.

It is bit tricky than that. Initially I started that way, but in crtc_state computations,
current scaler state needs to be copied over to newer state to make it work
correctly in legacy paths. Instead of copying individual members one by one,
put them in a structure to save some typing and make code cleaner. 

> 
> 
> Matt
> 
> >  };
> >
> >  struct intel_pipe_wm {
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 05/21 v2] drm/i915: Initialize skylake scalers
  2015-03-25  5:14   ` Matt Roper
  2015-03-25 13:24     ` Daniel Vetter
@ 2015-03-25 16:56     ` Konduru, Chandra
  1 sibling, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 16:56 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Tuesday, March 24, 2015 10:14 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 05/21 v2] drm/i915: Initialize skylake scalers
> 
> On Fri, Mar 20, 2015 at 05:04:26PM -0700, Chandra Konduru wrote:
> > Initializing scalers with supported values during crtc init.
> >
> > v2:
> > -initialize single copy of min/max values (Matt)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c |   53
> ++++++++++++++++++++++++++++++++++
> >  1 file changed, 53 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 89299b6..e6ea9e0 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -103,6 +103,8 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
> >  			    const struct intel_crtc_state *pipe_config);  static
> void
> > intel_begin_crtc_commit(struct drm_crtc *crtc);  static void
> > intel_finish_crtc_commit(struct drm_crtc *crtc);
> > +static void skl_init_scalers(struct drm_device *dev, int pipe,
> > +	struct intel_crtc_state *crtc_state);
> >
> >  static struct intel_encoder *intel_find_encoder(struct
> > intel_connector *connector, int pipe)  { @@ -12750,6 +12752,54 @@
> > static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
> >  	return &cursor->base;
> >  }
> >
> > +static void skl_init_scalers(struct drm_device *dev, int pipe,
> > +	struct intel_crtc_state *crtc_state) {
> > +	int i;
> > +	struct intel_scaler *intel_scaler;
> > +	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
> > +	if (INTEL_INFO(dev)->gen < 9)
> > +		return;
> 
> It's probably better to move this guard out to the callsite so that we can more
> easily extend this for future platforms.  Unless you plan to just extend this
> function in the future, in which case we should probably drop the 'skl_' prefix.

That is a slip. Will move the check to callsite and send out update.

> 
> 
> Matt
> 
> > +
> > +	scaler_state->num_scalers = SKL_NUM_SCALERS;
> > +	for (i = 0; i < SKL_NUM_SCALERS; i++) {
> > +		intel_scaler = &scaler_state->scalers[i];
> > +		intel_scaler->in_use = 0;
> > +		intel_scaler->id = i;
> > +
> > +		intel_scaler->mode = PS_SCALER_MODE_DYN;
> > +		intel_scaler->filter = PS_FILTER_MEDIUM;
> > +	}
> > +
> > +	/* down scaling ratio: 2.99 --> 1, i.e., 34% of original */
> > +	scaler_state->min_hsr = 34;
> > +	scaler_state->min_vsr = 34;
> > +	scaler_state->max_hsr = 500;
> > +	scaler_state->max_vsr = 500;
> > +
> > +	/* down scaling ratio: 2.99x2.99 --> 1x1, i.e., 12% of original */
> > +	scaler_state->min_hvsr = 12;
> > +	scaler_state->max_hvsr = 2500;
> > +
> > +	/* src_w & dst_w range 8 - 4096 */
> > +	scaler_state->min_src_w = 8;
> > +	scaler_state->max_src_w = 4096;
> > +	scaler_state->min_dst_w = 8;
> > +	scaler_state->max_dst_w = 4096;
> > +
> > +	/* src_h & dst_h range 8 - 2304 */
> > +	scaler_state->min_src_h = 8;
> > +	scaler_state->max_src_h = 2304;
> > +	scaler_state->min_dst_h = 8;
> > +	scaler_state->max_dst_h = 2304;
> > +
> > +	/* pipe C has one scaler */
> > +	if (pipe == PIPE_C) {
> > +		scaler_state->num_scalers = 1;
> > +	}
> > +	scaler_state->scaler_id = -1;
> > +}
> > +
> >  static void intel_crtc_init(struct drm_device *dev, int pipe)  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -12769,6
> > +12819,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
> >  	intel_crtc_set_state(intel_crtc, crtc_state);
> >  	crtc_state->base.crtc = &intel_crtc->base;
> >
> > +	/* initialize shared scalers */
> > +	skl_init_scalers(dev, pipe, crtc_state);
> > +
> >  	primary = intel_primary_plane_create(dev, pipe);
> >  	if (!primary)
> >  		goto fail;
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time
  2015-03-21  0:04 ` [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time Chandra Konduru
@ 2015-03-25 17:21   ` Matt Roper
  2015-03-25 17:29     ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25 17:21 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:33PM -0700, Chandra Konduru wrote:
> Plane scaling and colorkey are mutually exclusive. Ensure scaling
> isn't active at the time of enabling colorkey.
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>

I guess this is fine for now, but eventually we're going to need to get
colorkey and other blending styles brought over to atomic...do you know
if there's already someone working on that?


Matt

> ---
>  drivers/gpu/drm/i915/intel_sprite.c |    6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index c010528..0194390 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -319,6 +319,12 @@ skl_update_colorkey(struct drm_plane *drm_plane,
>  	const int plane = intel_plane->plane;
>  	u32 plane_ctl;
>  
> +	/* plane scaling and colorkey are mutually exclusive */
> +	if (to_intel_plane_state(drm_plane->state)->scaler_id >= 0) {
> +		DRM_ERROR("colorkey not allowed with scaler\n");
> +		return -EINVAL;
> +	}
> +
>  	I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
>  	I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
>  	I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state
  2015-03-21  0:04 ` [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state Chandra Konduru
@ 2015-03-25 17:21   ` Matt Roper
  2015-03-25 17:26     ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25 17:21 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:37PM -0700, Chandra Konduru wrote:
> From intel_atomic_check, call intel_atomic_setup_scalers() to
> assign scalers based on staged scaling requests. Fail the
> transaction if setup returns error.
> 
> Setting up of scalers should be moved to atomic crtc check  once
> atomic crtc is ready.
> 
> v2:
> -updated parameter passing to setup_scalers (me)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_atomic.c |   11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
> index 407516a..73e94c4 100644
> --- a/drivers/gpu/drm/i915/intel_atomic.c
> +++ b/drivers/gpu/drm/i915/intel_atomic.c
> @@ -48,6 +48,8 @@ int intel_atomic_check(struct drm_device *dev,
>  	int ncrtcs = dev->mode_config.num_crtc;
>  	int nconnectors = dev->mode_config.num_connector;
>  	enum pipe nuclear_pipe = INVALID_PIPE;
> +	struct intel_crtc *nuclear_crtc = NULL;
> +	struct intel_crtc_state *crtc_state = NULL;
>  	int ret;
>  	int i;
>  	bool not_nuclear = false;
> @@ -78,6 +80,10 @@ int intel_atomic_check(struct drm_device *dev,
>  		struct intel_crtc *crtc = to_intel_crtc(state->crtcs[i]);
>  		if (crtc && crtc->pipe != nuclear_pipe)
>  			not_nuclear = true;
> +		if (crtc && crtc->pipe == nuclear_pipe) {
> +			nuclear_crtc = crtc;
> +			crtc_state = to_intel_crtc_state(state->crtc_states[i]);
> +		}
>  	}
>  	for (i = 0; i < nconnectors; i++)
>  		if (state->connectors[i] != NULL)
> @@ -92,6 +98,11 @@ int intel_atomic_check(struct drm_device *dev,
>  	if (ret)
>  		return ret;
>  
> +	/* FIXME: move to crtc atomic check function once it is ready */

We can go ahead and add the crtc's atomic_check now.
drm_atomic_helper_check_planes() will call it if we setup the function
pointer.


Matt

> +	ret = intel_atomic_setup_scalers(dev, nuclear_crtc, crtc_state);
> +	if (ret)
> +		return ret;
> +
>  	return ret;
>  }
>  
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state
  2015-03-25 17:21   ` Matt Roper
@ 2015-03-25 17:26     ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 17:26 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander


> -----Original Message-----
> From: Roper, Matthew D
> Sent: Wednesday, March 25, 2015 10:22 AM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged
> crtc_state
> 
> On Fri, Mar 20, 2015 at 05:04:37PM -0700, Chandra Konduru wrote:
> > From intel_atomic_check, call intel_atomic_setup_scalers() to assign
> > scalers based on staged scaling requests. Fail the transaction if
> > setup returns error.
> >
> > Setting up of scalers should be moved to atomic crtc check  once
> > atomic crtc is ready.
> >
> > v2:
> > -updated parameter passing to setup_scalers (me)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_atomic.c |   11 +++++++++++
> >  1 file changed, 11 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_atomic.c
> > b/drivers/gpu/drm/i915/intel_atomic.c
> > index 407516a..73e94c4 100644
> > --- a/drivers/gpu/drm/i915/intel_atomic.c
> > +++ b/drivers/gpu/drm/i915/intel_atomic.c
> > @@ -48,6 +48,8 @@ int intel_atomic_check(struct drm_device *dev,
> >  	int ncrtcs = dev->mode_config.num_crtc;
> >  	int nconnectors = dev->mode_config.num_connector;
> >  	enum pipe nuclear_pipe = INVALID_PIPE;
> > +	struct intel_crtc *nuclear_crtc = NULL;
> > +	struct intel_crtc_state *crtc_state = NULL;
> >  	int ret;
> >  	int i;
> >  	bool not_nuclear = false;
> > @@ -78,6 +80,10 @@ int intel_atomic_check(struct drm_device *dev,
> >  		struct intel_crtc *crtc = to_intel_crtc(state->crtcs[i]);
> >  		if (crtc && crtc->pipe != nuclear_pipe)
> >  			not_nuclear = true;
> > +		if (crtc && crtc->pipe == nuclear_pipe) {
> > +			nuclear_crtc = crtc;
> > +			crtc_state = to_intel_crtc_state(state->crtc_states[i]);
> > +		}
> >  	}
> >  	for (i = 0; i < nconnectors; i++)
> >  		if (state->connectors[i] != NULL)
> > @@ -92,6 +98,11 @@ int intel_atomic_check(struct drm_device *dev,
> >  	if (ret)
> >  		return ret;
> >
> > +	/* FIXME: move to crtc atomic check function once it is ready */
> 
> We can go ahead and add the crtc's atomic_check now.
> drm_atomic_helper_check_planes() will call it if we setup the function pointer.

My understanding is it is not that straight forward after chat with Ander.
So placed it here to make it work while things are inflight.

> 
> 
> Matt
> 
> > +	ret = intel_atomic_setup_scalers(dev, nuclear_crtc, crtc_state);
> > +	if (ret)
> > +		return ret;
> > +
> >  	return ret;
> >  }
> >
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time
  2015-03-25 17:21   ` Matt Roper
@ 2015-03-25 17:29     ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 17:29 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Wednesday, March 25, 2015 10:22 AM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't
> enabled at same time
> 
> On Fri, Mar 20, 2015 at 05:04:33PM -0700, Chandra Konduru wrote:
> > Plane scaling and colorkey are mutually exclusive. Ensure scaling
> > isn't active at the time of enabling colorkey.
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> 
> I guess this is fine for now, but eventually we're going to need to get colorkey
> and other blending styles brought over to atomic...do you know if there's
> already someone working on that?

I do not know. 

> 
> 
> Matt
> 
> > ---
> >  drivers/gpu/drm/i915/intel_sprite.c |    6 ++++++
> >  1 file changed, 6 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c
> > b/drivers/gpu/drm/i915/intel_sprite.c
> > index c010528..0194390 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -319,6 +319,12 @@ skl_update_colorkey(struct drm_plane *drm_plane,
> >  	const int plane = intel_plane->plane;
> >  	u32 plane_ctl;
> >
> > +	/* plane scaling and colorkey are mutually exclusive */
> > +	if (to_intel_plane_state(drm_plane->state)->scaler_id >= 0) {
> > +		DRM_ERROR("colorkey not allowed with scaler\n");
> > +		return -EINVAL;
> > +	}
> > +
> >  	I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
> >  	I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
> >  	I915_WRITE(PLANE_KEYMSK(pipe, plane), key->channel_mask);
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio.
  2015-03-25  5:14   ` Matt Roper
@ 2015-03-25 17:37     ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 17:37 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Tuesday, March 24, 2015 10:14 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 07/21 v2] drm/i915: Helper function to update skylake
> scaling ratio.
> 
> On Fri, Mar 20, 2015 at 05:04:28PM -0700, Chandra Konduru wrote:
> > Helper function updates supported scaling ratios based on cdclk and
> > crtc clocks.
> >
> > v2:
> > -update single copy of scaling ratios (Matt)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c |   25 +++++++++++++++++++++++++
> >  1 file changed, 25 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 20f13c8..890d372 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -4513,6 +4513,31 @@ static void
> haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
> >  	intel_wait_for_vblank(dev, other_active_crtc->pipe);  }
> >
> > +static void skl_update_scaling_ratio(struct drm_device *dev,
> > +	struct intel_crtc_state *crtc_state) {
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	uint32_t crtc_clock, cdclk;
> > +	struct intel_crtc_scaler_state *scaler_state;
> > +
> > +	if (!crtc_state)
> > +		return;
> > +
> > +	crtc_clock = (uint32_t) crtc_state->base.adjusted_mode.crtc_clock;
> > +	cdclk = (uint32_t) intel_ddi_get_cdclk_freq(dev_priv);
> > +
> > +	if (!crtc_clock || !cdclk)
> > +		return;
> > +
> > +	scaler_state = &crtc_state->scaler_state;
> > +	scaler_state->min_hsr = max(scaler_state->min_hsr, (crtc_clock *
> 100)/cdclk);
> > +	scaler_state->min_vsr = max(scaler_state->min_hsr, (crtc_clock *
> > +100)/cdclk);
> 
> I don't have access to the bspec at the moment, but this seems a little
> strange...the minimums here can go up when you change mode, but they can
> never go back down again, even if you go back to the original mode?
> It feels like the first parameter to max() here should have been a constant for
> the lowest min the hardware can support.

You are right, I also found that while testing nv12 feature that they aren't
going back. Will fix and send revised patch.

> 
> > +	scaler_state->min_hvsr = max(scaler_state->min_hsr, (crtc_clock *
> > +100)/cdclk);
>                                                    ^^^^^^^
>                                                    min_hvsr?

Will fix along with above.

> 
> 
> > +
> > +	DRM_DEBUG_KMS("for crtc_state = %p crtc_clock = %d cdclk = %d\n",
> crtc_state,
> > +		crtc_clock, cdclk);
> > +}
> > +
> >  static void haswell_crtc_enable(struct drm_crtc *crtc)  {
> >  	struct drm_device *dev = crtc->dev;
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state
  2015-03-25  5:15   ` Matt Roper
@ 2015-03-25 19:20     ` Konduru, Chandra
  2015-03-25 20:58       ` Matt Roper
  0 siblings, 1 reply; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 19:20 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Tuesday, March 24, 2015 10:15 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 08/21 v2] drm/i915: Add helper function to update
> scaler_users in crtc_state
> 
> On Fri, Mar 20, 2015 at 05:04:29PM -0700, Chandra Konduru wrote:
> > This helper function stages a scaler request for a plane/crtc into
> > crtc_state->scaler_users (which is a bit field). It also performs
> > required checks before staging any change into scaler_state.
> >
> > v2:
> > -updates to use single copy of scaler limits (Matt) -added force
> > detach parameter for pfit disable purpose (me)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c |  143
> ++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h     |    3 +
> >  2 files changed, 146 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 890d372..976bfb1 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -12387,6 +12387,149 @@ intel_cleanup_plane_fb(struct drm_plane
> *plane,
> >  	}
> >  }
> >
> > +/*
> > + * Update crtc_state->scaler_users for requested plane or crtc based on
> state.
> 
> I realize you're trying to re-use some logic here, but I find the overloaded
> function that works on either planes or crtcs a bit harder to follow.  Personally
> I'd prefer if this were just two separate functions, one focused on planes, one
> focused on CRTC's, even if it means duplicating a little bit of the logic.
> 

Yes, this is written as per one of the earlier feedback comment. 
I know this is bit complex, but I find it is worth to take care of all 
Checks in one place covering both crtc and plane. 
To avoid any confusion, I have put sufficient commentary 
throughout the code. let me know if you think any further
commentary is required.

> > + *
> > + * plane (in)
> > + *     NULL - for crtc
> > + *     not NULL - for plane
> > + * force_detach (in)
> > + *     unconditionally scaler will be staged for detachment from crtc/plane
> > + * Return
> > + *     0 - scaler_usage updated successfully
> > + *    error - requested scaling cannot be supported or other error condition
> > + */
> 
> Probably want to put this in kerneldoc format.

Will update in next rev.

> 
> > +int
> > +skl_update_scaler_users(
> > +	struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state,
> > +	struct intel_plane *intel_plane, struct intel_plane_state
> > +*plane_state,
> 
> Might be a little easier to drop the intel_crtc and intel_plane parameters and just
> pull them out of the state backpointers.

You know there is a check caller is doing to get right crtc pointer in 
case of check_plane:
	crtc = crtc ? crtc : plane->crtc;

If crtc isn't passed, then similar check is required in this function.
As caller is already taking care of this, passing crtc just to avoid
another check. 

> 
> > +	int force_detach)
> > +{
> > +	int need_scaling;
> > +	int idx;
> > +	int src_w, src_h, dst_w, dst_h;
> > +	int scaler_id;
> > +	struct drm_framebuffer *fb;
> > +	struct intel_crtc_scaler_state *scaler_state;
> > +
> > +	if (!intel_crtc || !crtc_state ||
> > +		(intel_plane && intel_plane->base.type ==
> DRM_PLANE_TYPE_CURSOR))
> > +		return 0;
> > +
> > +	scaler_state = &crtc_state->scaler_state;
> > +
> > +	if (!scaler_state->num_scalers) {
> > +		DRM_DEBUG_KMS("crtc_state = %p, num_scalers = %d\n",
> crtc_state,
> > +			scaler_state->num_scalers);
> > +		return 0;
> > +	}
> > +
> > +	idx = intel_plane ? drm_plane_index(&intel_plane->base) :
> SKL_CRTC_INDEX;
> > +	fb = intel_plane ? plane_state->base.fb : NULL;
> > +
> > +	if (intel_plane) {
> > +		src_w = drm_rect_width(&plane_state->src) >> 16;
> > +		src_h = drm_rect_height(&plane_state->src) >> 16;
> > +		dst_w = drm_rect_width(&plane_state->dst);
> > +		dst_h = drm_rect_height(&plane_state->dst);
> > +		scaler_id = plane_state->scaler_id;
> > +	} else {
> > +		struct drm_display_mode *adjusted_mode =
> > +			&crtc_state->base.adjusted_mode;
> > +		src_w = crtc_state->pipe_src_w;
> > +		src_h = crtc_state->pipe_src_h;
> > +		dst_w = adjusted_mode->hdisplay;
> > +		dst_h = adjusted_mode->vdisplay;
> > +		scaler_id = scaler_state->scaler_id;
> > +	}
> > +	need_scaling = (src_w != dst_w || src_h != dst_h);
> 
> We're already calculating this in the plane check function; we should probably
> just store the result in a plane_state field at that point so we don't have to re-
> calculate it here.

I think you are referring to sprite plane check, but this is not there in primary plane
check function.

> 
> 
> > +
> > +	/*
> > +	 * if plane is being disabled or scaler is no more required or force
> > +detach
> 
> Maybe it will become more clear later in the patch series, but I'm not sure I
> understand what 'force_detach' does.  Won't scalers that we don't end up re-
> assigning automatically be cleared when we nobody makes use of them in a new
> commit?

Force detach, as name suggests, it stages force freeing of a scaler if one is 
attached to crtc or plane. This is used when disabling panel fitter which 
is called from crtc disable. 

> 
> > +	 *  - free scaler binded to this plane/crtc
> > +	 *  - in order to do this, update crtc->scaler_usage
> > +	 *
> > +	 * Here scaler state in crtc_state is set free so that
> > +	 * scaler can be assigned to other user. Actual register
> > +	 * update to free the scaler is done in plane/panel-fit programming.
> > +	 * For this purpose crtc/plane_state->scaler_id isn't reset here.
> > +	 */
> > +	if (force_detach || !need_scaling || (intel_plane &&
> > +		(!fb || !plane_state->visible))) {
> > +		if (scaler_id >= 0) {
> > +			scaler_state->scaler_users &= ~(1 << idx);
> > +			scaler_state->scalers[scaler_id].in_use = 0;
> > +
> > +			DRM_DEBUG_KMS("Staged freeing scaler id %u.%u
> from %s:%d "
> > +				"crtc_state = %p scaler_users = 0x%x\n",
> > +				intel_crtc->pipe, scaler_id, intel_plane ?
> "PLANE" : "CRTC",
> > +				intel_plane ? intel_plane->base.base.id :
> > +				intel_crtc->base.base.id, crtc_state,
> > +				scaler_state->scaler_users);
> > +		}
> > +		return 0;
> > +	}
> > +
> > +	/*
> > +	 * check for rect size:
> > +	 *     min sizes in case of scaling involved
> > +	 *     max sizes in all cases
> > +	 */
> > +	if ((need_scaling &&
> 
> need_scaling is guaranteed to be true now (otherwise we would have returned
> above), so we can drop this test.
> 
> > +		(src_w < scaler_state->min_src_w || src_h < scaler_state-
> >min_src_h ||
> > +		 dst_w < scaler_state->min_dst_w || dst_h <
> > +scaler_state->min_dst_h)) ||
> > +
> > +		 src_w > scaler_state->max_src_w || src_h > scaler_state-
> >max_src_h ||
> > +		 dst_w > scaler_state->max_dst_w || dst_h > scaler_state-
> >max_dst_h) {
> > +		DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u
> dst %ux%u "
> > +			"size is out of scaler range\n",
> > +			intel_plane ? "PLANE" : "CRTC",
> > +			intel_plane ? intel_plane->base.base.id : intel_crtc-
> >base.base.id,
> > +			intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* check colorkey */
> > +	if (intel_plane && need_scaling &&
> > +intel_colorkey_enabled(intel_plane)) {
> 
> Can drop 'need_scaling' test again.
> 
> > +		DRM_DEBUG_KMS("PLANE:%d scaling with color key not
> allowed",
> > +			intel_plane->base.base.id);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* Check src format */
> > +	if (intel_plane && need_scaling) {
> 
> Ditto
> 
> > +		switch (fb->pixel_format) {
> > +		case DRM_FORMAT_RGB565:
> > +		case DRM_FORMAT_XBGR8888:
> > +		case DRM_FORMAT_XRGB8888:
> > +		case DRM_FORMAT_ABGR8888:
> > +		case DRM_FORMAT_ARGB8888:
> > +		case DRM_FORMAT_XRGB2101010:
> > +		case DRM_FORMAT_ARGB2101010:
> > +		case DRM_FORMAT_XBGR2101010:
> > +		case DRM_FORMAT_ABGR2101010:
> > +		case DRM_FORMAT_YUYV:
> > +		case DRM_FORMAT_YVYU:
> > +		case DRM_FORMAT_UYVY:
> > +		case DRM_FORMAT_VYUY:
> > +			break;
> > +		default:
> > +			DRM_DEBUG_KMS("PLANE:%d FB:%d format 0x%x not
> supported\n",
> > +				intel_plane->base.base.id, fb->base.id, fb-
> >pixel_format);
> 
> Might want to add "...while scaling" to this message to avoid confusion.
> 
> > +			return -EINVAL;
> > +		}
> > +	}
> > +
> > +	/* mark this plane as a scaler user in crtc_state */
> > +	scaler_state->scaler_users |= (1 << idx);
> > +	DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u "
> > +		"crtc_state = %p scaler_users = 0x%x\n",
> > +		intel_plane ? "PLANE" : "CRTC",
> > +		intel_plane ? intel_plane->base.base.id : intel_crtc-
> >base.base.id,
> > +		src_w, src_h, dst_w, dst_h, crtc_state, scaler_state-
> >scaler_users);
> > +	return 0;
> > +}
> > +
> >  static int
> >  intel_check_primary_plane(struct drm_plane *plane,
> >  			  struct intel_plane_state *state) diff --git
> > a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 1da5087..f5d53c9 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1138,6 +1138,9 @@ void intel_mode_from_pipe_config(struct
> drm_display_mode *mode,
> >  				 struct intel_crtc_state *pipe_config);  void
> > intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);  void
> > intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
> > +int skl_update_scaler_users(struct intel_crtc *intel_crtc,
> > +	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
> > +	struct intel_plane_state *plane_state, int force_detach);
> >
> >  /* intel_dp.c */
> >  void intel_dp_init(struct drm_device *dev, int output_reg, enum port
> > port);
> > --
> > 1.7.9.5
> 
> You should probably just squash this into the later patches where you actually
> call it (e.g., patch 18) so it's more clear how/when/where it is used.

Same point came up during review of previous version, and for now it is agreed 
to keep current split to avoid redo of the whole series. I hope you are ok with this. 

> 
> 
> Matt
> 
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc.
  2015-03-25  5:15   ` Matt Roper
@ 2015-03-25 19:46     ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 19:46 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Tuesday, March 24, 2015 10:15 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers
> scalers for a crtc.
> 
> On Fri, Mar 20, 2015 at 05:04:30PM -0700, Chandra Konduru wrote:
> > intel_atomic_setup_scalers sets up scalers based on staged scaling
> > requests coming from a crtc and its planes. This function should be
> > called from crtc level check path.
> >
> > If staged requests are supportable, function assigns scalers to
> > requested planes and crtc. This function also takes into account the
> > current planes using scalers but not being part of this atomic state
> > for optimal operation of scalers. Note that the scaler assignement
> > itself is staged into crtc_state and respective plane_states for later
> > commit after all checks have been done.
> >
> > overall high level flow:
> >  - scaler requests are staged into crtc_state by planes/crtc
> >  - check whether staged scaling requests can be supported
> >  - add planes using scalers that aren't in current transaction
> >  - assign scalers to requested users
> >  - as part of plane commit, scalers will be committed
> >    (i.e., either attached or detached) to respective planes in hw
> >  - as part of crtc_commit, scaler will be either attached or detached
> >    to crtc in hw
> >
> > v2:
> > -removed a log message (me)
> > -changed input parameter to crtc_state (me)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_atomic.c |  138
> +++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h    |    3 +
> >  2 files changed, 141 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_atomic.c
> > b/drivers/gpu/drm/i915/intel_atomic.c
> > index 3903b90..407516a 100644
> > --- a/drivers/gpu/drm/i915/intel_atomic.c
> > +++ b/drivers/gpu/drm/i915/intel_atomic.c
> > @@ -241,3 +241,141 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
> > {
> >  	drm_atomic_helper_crtc_destroy_state(crtc, state);  }
> > +
> > +/**
> > + * intel_atomic_setup_scalers() - setup scalers for crtc per staged
> > +requests
> > + * @dev: DRM device
> > + * @crtc: intel crtc
> > + * @crtc_state: incoming crtc_state to validate and setup scalers
> > + *
> > + * This function setups up scalers based on staged scaling requests
> > +for
> 
> s/setups up/sets up/

Yes, will update.

> 
> > + * a @crtc and its planes. It is called from crtc level check path.
> > +If request
> > + * is a supportable request, it attaches scalers to requested planes and crtc.
> > + *
> > + * This function takes into account the current scaler(s) in use by
> > +any planes
> > + * not being part of this atomic state
> > + *
> > + *  Returns:
> > + *         0 - scalers were setup succesfully
> > + *         error code - otherwise
> > + */
> > +int intel_atomic_setup_scalers(struct drm_device *dev,
> > +	struct intel_crtc *intel_crtc,
> > +	struct intel_crtc_state *crtc_state) {
> > +	struct drm_plane *plane = NULL;
> > +	struct intel_plane *intel_plane;
> > +	struct intel_plane_state *plane_state = NULL;
> > +	struct intel_crtc_scaler_state *scaler_state;
> > +	struct drm_atomic_state *drm_state;
> > +	int num_scalers_need;
> > +	int i, j;
> > +
> > +	if (INTEL_INFO(dev)->gen < 9 || !intel_crtc || !crtc_state)
> > +		return 0;
> > +
> > +	scaler_state = &crtc_state->scaler_state;
> > +	drm_state = crtc_state->base.state;
> > +
> > +	num_scalers_need = hweight32(scaler_state->scaler_users);
> > +	DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users =
> 0x%x\n",
> > +		crtc_state, num_scalers_need, scaler_state->num_scalers,
> > +		scaler_state->scaler_users);
> > +
> > +	/* if there is no change in scaler configuration, return */
> > +	if (scaler_state->scaler_users ==
> > +		intel_crtc->config->scaler_state.scaler_users)
> > +		return 0;
> > +
> > +	/*
> > +	 * High level flow:
> > +	 * - staged scaler requests are already in scaler_state->scaler_users
> > +	 * - check whether staged scaling requests can be supported
> > +	 * - add planes using scalers that aren't in current transaction
> > +	 * - assign scalers to requested users
> > +	 * - as part of plane commit, scalers will be committed
> > +	 *   (i.e., either attached or detached) to respective planes in hw
> > +	 * - as part of crtc_commit, scaler will be either attached or detached
> > +	 *   to crtc in hw
> > +	 */
> > +
> > +	/* fail if required scalers > available scalers */
> > +	if (num_scalers_need > scaler_state->num_scalers){
> > +		DRM_DEBUG_KMS("Too many scaling requests %d > %d\n",
> > +			num_scalers_need, scaler_state->num_scalers);
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* walkthrough scaler_users bits and start assigning scalers */
> > +	for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
> > +		int *scaler_id;
> > +
> > +		/* skip if scaler not required */
> > +		if (!(scaler_state->scaler_users & (1 << i)))
> > +			continue;
> > +
> > +		if (i == SKL_CRTC_INDEX) {
> > +			/* panel fitter case: assign as a crtc scaler */
> > +			scaler_id = &scaler_state->scaler_id;
> > +		} else {
> > +			if (!drm_state)
> > +				continue;
> 
> This shouldn't happen, at least not once we're back on the full atomic helpers,
> right?  It seems like if it does happen, nothing's going to work right, so maybe
> add a WARN_ON() to this test?

Two reasons for having above check:
1) Yes, that is what expected in case of planes. But because current tree is not 
having full atomic helpers, placed this check.
2) During legacy setmode requiring/freeing panel fitter,  it can be null. 
To cover those cases, placed this check for proper operation of scaler 
for panel fitter. 

> 
> > +
> > +			/* plane scaler case: assign as a plane scaler */
> > +			/* find the plane that set the bit as scaler_user */
> > +			plane = drm_state->planes[i];
> > +
> > +			/*
> > +			 * to enable/disable hq mode, add planes that are using
> scaler
> > +			 * into this transaction
> > +			 */
> > +			if (!plane) {
> > +				plane = drm_plane_from_index(dev, i);
> > +				drm_state->planes[i] = plane;
> > +				drm_state->plane_states[i] =
> > +
> 	drm_atomic_get_plane_state(drm_state, plane);
> 
> I think you need to test for EDEADLK here in case we have a w/w collision.
> Other errors like ENOMEM might also happen.  Actually,
> drm_atomic_get_plane_state() will take care of adding the state to the
> plane_states[] array for you, so no need for the assignment; you can just call the
> function and check for error returns.

Ok, will return in case of error from drm_atomic_get_plane_state().
Will send updated patch shortly.

> 
> > +			}
> > +
> > +			intel_plane = to_intel_plane(plane);
> > +
> > +			/* plane on different crtc cannot be a scaler user of this
> crtc */
> > +			if (WARN_ON(intel_plane->pipe != intel_crtc->pipe)) {
> > +				continue;
> > +			}
> > +
> > +			plane_state = to_intel_plane_state(drm_state-
> >plane_states[i]);
> > +			scaler_id = &plane_state->scaler_id;
> > +		}
> > +
> > +		if (*scaler_id < 0) {
> > +			/* find a free scaler */
> > +			for (j = 0; j < scaler_state->num_scalers; j++) {
> > +				if (!scaler_state->scalers[j].in_use) {
> > +					scaler_state->scalers[j].in_use = 1;
> > +					*scaler_id = scaler_state->scalers[j].id;
> > +					DRM_DEBUG_KMS("Attached scaler id
> %u.%u to %s:%d\n",
> > +						intel_crtc->pipe,
> > +						i == SKL_CRTC_INDEX ?
> scaler_state->scaler_id :
> > +							plane_state-
> >scaler_id,
> > +						i == SKL_CRTC_INDEX ? "CRTC"
> : "PLANE",
> > +						i == SKL_CRTC_INDEX ?
> intel_crtc->base.base.id :
> > +						plane->base.id);
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (WARN_ON(*scaler_id < 0)) {
> > +			DRM_DEBUG_KMS("Cannot find scaler for %s:%d\n",
> > +				i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
> > +				i == SKL_CRTC_INDEX ? intel_crtc-
> >base.base.id:plane->base.id);
> > +			continue;
> > +		}
> > +
> > +		/* set scaler mode */
> > +		scaler_state->scalers[*scaler_id].mode = (num_scalers_need ==
> 1) ?
> > +			PS_SCALER_MODE_HQ : PS_SCALER_MODE_DYN;
> > +	}
> > +
> > +	return 0;
> > +}
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index f5d53c9..a9d787d 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1401,6 +1401,9 @@ intel_atomic_get_crtc_state(struct
> > drm_atomic_state *state,
> >
> >  	return to_intel_crtc_state(crtc_state);  }
> > +int intel_atomic_setup_scalers(struct drm_device *dev,
> > +	struct intel_crtc *intel_crtc,
> > +	struct intel_crtc_state *crtc_state);
> >
> >  /* intel_atomic_plane.c */
> >  struct intel_plane_state *intel_create_plane_state(struct drm_plane
> > *plane);
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-25  5:15   ` Matt Roper
@ 2015-03-25 20:14     ` Konduru, Chandra
  2015-03-25 21:13       ` Matt Roper
  0 siblings, 1 reply; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 20:14 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Tuesday, March 24, 2015 10:16 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from
> a plane or crtc
> 
> On Fri, Mar 20, 2015 at 05:04:31PM -0700, Chandra Konduru wrote:
> > This function is called from commit path of a plane or crtc.
> > It programs scaler registers to detach (aka. unbinds) scaler from
> > requested plane or crtc if it isn't in use. It also resets scaler_id
> > in crtc/plane state.
> >
> > v2:
> > -improved a log message (me)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c |   39
> ++++++++++++++++++++++++++++++++++
> >  drivers/gpu/drm/i915/intel_drv.h     |    1 +
> >  2 files changed, 40 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 976bfb1..7150c33 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct drm_device
> *dev, uint64_t fb_modifier,
> >  	}
> >  }
> >
> > +/*
> > + * This function detaches (aka. unbinds) a scaler from plane or crtc
> 
> You might want to clarify that detach/unbind refers to the actual hardware
> programming, not the state calculation.  I'm a bit surprised we need this
> function; I figured we'd just be looping over all scalers at the end of the commit
> step and programming them to either on or off depending on what the scaling
> state contained.

This is bit tricky and isn't that straight forward.
Staged scaler state can trigger freeing a scaler that can lead to two scenarios:
1) freed scaler is not attached to any other user. In this case, reg programming
needed to update hw. And reset scaler_id to -1 to indicate scaler isn't used.
Once done, both sw and hw states are in sync.

2) freed scaler is allocated to someone. In this case, registers shouldn't be 
programmed by previous owner because scaler may be in use
by new owner. 

I think I explained these details in comments already. But will check and 
update if needed.

> 
> As I mentioned on a previous patch, these overloaded functions that might
> operate on a plane or might operate on a CRTC can be a bit confusing, especially
> when we have multi-nested ternary operators like you do below.

> 
> > + * if scaler is not in use.
> > + * It resets scaler_id in plane or crtc
> > + * To request detach a scaler from crtc, call plane as NULL  */ void
> > +skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane) {
> > +	struct drm_device *dev = crtc->dev;
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	struct intel_crtc_state *crtc_state;
> > +	struct intel_crtc *intel_crtc;
> > +	struct intel_plane *intel_plane;
> > +	struct intel_plane_state *plane_state;
> > +	int *scaler_id;
> > +
> > +	intel_crtc = to_intel_crtc(crtc);
> > +	intel_plane = plane ? to_intel_plane(plane) : NULL;
> > +	crtc_state = intel_crtc->config;
> > +	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
> > +
> > +	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
> > +		&crtc_state->scaler_state.scaler_id;
> > +
> > +	if (!scaler_id || (scaler_id && *scaler_id < 0))
> > +		return;
> > +
> > +	/* if scaler is not in use, free */
> > +	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
> > +		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
> > +		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)),
> 0);
> > +		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
> > +		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u
> from %s:%d\n",
> > +			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
> > +			plane ? plane->base.id : crtc->base.id);
> > +		*scaler_id = -1;
> 
> This confuses me...why are we updating the state here at the end of the commit
> step?  State should be immutable at this point, right?

As I explained above, valid scaler_id is required. Then scaler_id can be set to -1.

> 
> 
> Matt
> 
> > +	}
> > +}
> > +
> >  static void skylake_update_primary_plane(struct drm_crtc *crtc,
> >  					 struct drm_framebuffer *fb,
> >  					 int x, int y)
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index a9d787d..f25d14d 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1141,6 +1141,7 @@ void intel_modeset_preclose(struct drm_device
> > *dev, struct drm_file *file);  int skl_update_scaler_users(struct intel_crtc
> *intel_crtc,
> >  	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
> >  	struct intel_plane_state *plane_state, int force_detach);
> > +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane
> > +*plane);
> >
> >  /* intel_dp.c */
> >  void intel_dp_init(struct drm_device *dev, int output_reg, enum port
> > port);
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state
  2015-03-25 19:20     ` Konduru, Chandra
@ 2015-03-25 20:58       ` Matt Roper
  2015-03-25 22:02         ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25 20:58 UTC (permalink / raw)
  To: Konduru, Chandra; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander

On Wed, Mar 25, 2015 at 12:20:08PM -0700, Konduru, Chandra wrote:
...
> > 
> > We're already calculating this in the plane check function; we should probably
> > just store the result in a plane_state field at that point so we don't have to re-
> > calculate it here.
> 
> I think you are referring to sprite plane check, but this is not there in primary plane
> check function.

Well, it is, but it's hidden inside the drm plane helper function and
isn't directly in our i915 driver code.

I feel like "do these src/dest rectangles imply scaling?" is a question
that is going to be relevant to all drivers, not just i915, so it might
even be worth adding the field to the DRM core's state structure and
have the helper function set it for any drivers using the helper.
Hardware drivers could override this value, or could set it themselves
if they don't use the helper.  Just a thought...


Matt

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-25 20:14     ` Konduru, Chandra
@ 2015-03-25 21:13       ` Matt Roper
  2015-03-25 21:28         ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25 21:13 UTC (permalink / raw)
  To: Konduru, Chandra; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander

On Wed, Mar 25, 2015 at 01:14:40PM -0700, Konduru, Chandra wrote:
> 
> 
> > -----Original Message-----
> > From: Roper, Matthew D
> > Sent: Tuesday, March 24, 2015 10:16 PM
> > To: Konduru, Chandra
> > Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> > Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from
> > a plane or crtc
> > 
> > On Fri, Mar 20, 2015 at 05:04:31PM -0700, Chandra Konduru wrote:
> > > This function is called from commit path of a plane or crtc.
> > > It programs scaler registers to detach (aka. unbinds) scaler from
> > > requested plane or crtc if it isn't in use. It also resets scaler_id
> > > in crtc/plane state.
> > >
> > > v2:
> > > -improved a log message (me)
> > >
> > > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_display.c |   39
> > ++++++++++++++++++++++++++++++++++
> > >  drivers/gpu/drm/i915/intel_drv.h     |    1 +
> > >  2 files changed, 40 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > b/drivers/gpu/drm/i915/intel_display.c
> > > index 976bfb1..7150c33 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct drm_device
> > *dev, uint64_t fb_modifier,
> > >  	}
> > >  }
> > >
> > > +/*
> > > + * This function detaches (aka. unbinds) a scaler from plane or crtc
> > 
> > You might want to clarify that detach/unbind refers to the actual hardware
> > programming, not the state calculation.  I'm a bit surprised we need this
> > function; I figured we'd just be looping over all scalers at the end of the commit
> > step and programming them to either on or off depending on what the scaling
> > state contained.
> 
> This is bit tricky and isn't that straight forward.
> Staged scaler state can trigger freeing a scaler that can lead to two scenarios:
> 1) freed scaler is not attached to any other user. In this case, reg programming
> needed to update hw. And reset scaler_id to -1 to indicate scaler isn't used.
> Once done, both sw and hw states are in sync.
> 
> 2) freed scaler is allocated to someone. In this case, registers shouldn't be 
> programmed by previous owner because scaler may be in use
> by new owner. 
> 
> I think I explained these details in comments already. But will check and 
> update if needed.

I might not have been clear in my earlier email.  What I meant was that
I didn't expect scalers to be programmed as part of their "owner's"
programming at all.  At the moment you seem to be programming them in
the low-level plane programming functions (skl_update_plane and such).
Instead, I had expected a single loop over each scaler at the very end
of the entire commit process, after you're done with the plane
programming functions.  The scaler state would already indicate whether
the scaler is supposed to be associated with a plane/crtc (which may or
may not be the same as the previous frame; we don't care) or whether it
is unused and should be programmed to off.  So basically you would
wind up programming all of the scaler registers on each atomic commit,
even if they didn't change, but you wouldn't have to worry about whether
the scaler's owner is changing or who is responsible for doing the
programming of that scaler this time around --- basically just treat
scalers as an independent resource that have their own programming step
at the end of processing a CRTC.


> 
> > 
> > As I mentioned on a previous patch, these overloaded functions that might
> > operate on a plane or might operate on a CRTC can be a bit confusing, especially
> > when we have multi-nested ternary operators like you do below.
> 
> > 
> > > + * if scaler is not in use.
> > > + * It resets scaler_id in plane or crtc
> > > + * To request detach a scaler from crtc, call plane as NULL  */ void
> > > +skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane) {
> > > +	struct drm_device *dev = crtc->dev;
> > > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > > +	struct intel_crtc_state *crtc_state;
> > > +	struct intel_crtc *intel_crtc;
> > > +	struct intel_plane *intel_plane;
> > > +	struct intel_plane_state *plane_state;
> > > +	int *scaler_id;
> > > +
> > > +	intel_crtc = to_intel_crtc(crtc);
> > > +	intel_plane = plane ? to_intel_plane(plane) : NULL;
> > > +	crtc_state = intel_crtc->config;
> > > +	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
> > > +
> > > +	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
> > > +		&crtc_state->scaler_state.scaler_id;
> > > +
> > > +	if (!scaler_id || (scaler_id && *scaler_id < 0))
> > > +		return;
> > > +
> > > +	/* if scaler is not in use, free */
> > > +	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
> > > +		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
> > > +		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)),
> > 0);
> > > +		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
> > > +		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u
> > from %s:%d\n",
> > > +			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
> > > +			plane ? plane->base.id : crtc->base.id);
> > > +		*scaler_id = -1;
> > 
> > This confuses me...why are we updating the state here at the end of the commit
> > step?  State should be immutable at this point, right?
> 
> As I explained above, valid scaler_id is required. Then scaler_id can be set to -1.

The problem is that we're ultimately updating crtc_state from the
'commit' step here, which violates the atomic design.  State structures
are supposed to be immutable during the commit phase

> 
> > 
> > 
> > Matt
> > 
> > > +	}
> > > +}
> > > +
> > >  static void skylake_update_primary_plane(struct drm_crtc *crtc,
> > >  					 struct drm_framebuffer *fb,
> > >  					 int x, int y)
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > b/drivers/gpu/drm/i915/intel_drv.h
> > > index a9d787d..f25d14d 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -1141,6 +1141,7 @@ void intel_modeset_preclose(struct drm_device
> > > *dev, struct drm_file *file);  int skl_update_scaler_users(struct intel_crtc
> > *intel_crtc,
> > >  	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
> > >  	struct intel_plane_state *plane_state, int force_detach);
> > > +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane
> > > +*plane);
> > >
> > >  /* intel_dp.c */
> > >  void intel_dp_init(struct drm_device *dev, int output_reg, enum port
> > > port);
> > > --
> > > 1.7.9.5
> > >
> > 
> > --
> > Matt Roper
> > Graphics Software Engineer
> > IoTG Platform Enabling & Development
> > Intel Corporation
> > (916) 356-2795

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-25 21:13       ` Matt Roper
@ 2015-03-25 21:28         ` Konduru, Chandra
  2015-03-28  0:21           ` Matt Roper
  0 siblings, 1 reply; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 21:28 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Wednesday, March 25, 2015 2:14 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from
> a plane or crtc
> 
> On Wed, Mar 25, 2015 at 01:14:40PM -0700, Konduru, Chandra wrote:
> >
> >
> > > -----Original Message-----
> > > From: Roper, Matthew D
> > > Sent: Tuesday, March 24, 2015 10:16 PM
> > > To: Konduru, Chandra
> > > Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De
> > > Oliveira, Ander
> > > Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a
> > > scaler from a plane or crtc
> > >
> > > On Fri, Mar 20, 2015 at 05:04:31PM -0700, Chandra Konduru wrote:
> > > > This function is called from commit path of a plane or crtc.
> > > > It programs scaler registers to detach (aka. unbinds) scaler from
> > > > requested plane or crtc if it isn't in use. It also resets
> > > > scaler_id in crtc/plane state.
> > > >
> > > > v2:
> > > > -improved a log message (me)
> > > >
> > > > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_display.c |   39
> > > ++++++++++++++++++++++++++++++++++
> > > >  drivers/gpu/drm/i915/intel_drv.h     |    1 +
> > > >  2 files changed, 40 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > > b/drivers/gpu/drm/i915/intel_display.c
> > > > index 976bfb1..7150c33 100644
> > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > @@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct
> > > > drm_device
> > > *dev, uint64_t fb_modifier,
> > > >  	}
> > > >  }
> > > >
> > > > +/*
> > > > + * This function detaches (aka. unbinds) a scaler from plane or
> > > > +crtc
> > >
> > > You might want to clarify that detach/unbind refers to the actual
> > > hardware programming, not the state calculation.  I'm a bit
> > > surprised we need this function; I figured we'd just be looping over
> > > all scalers at the end of the commit step and programming them to
> > > either on or off depending on what the scaling state contained.
> >
> > This is bit tricky and isn't that straight forward.
> > Staged scaler state can trigger freeing a scaler that can lead to two scenarios:
> > 1) freed scaler is not attached to any other user. In this case, reg
> > programming needed to update hw. And reset scaler_id to -1 to indicate scaler
> isn't used.
> > Once done, both sw and hw states are in sync.
> >
> > 2) freed scaler is allocated to someone. In this case, registers
> > shouldn't be programmed by previous owner because scaler may be in use
> > by new owner.
> >
> > I think I explained these details in comments already. But will check
> > and update if needed.
> 
> I might not have been clear in my earlier email.  What I meant was that I didn't
> expect scalers to be programmed as part of their "owner's"
> programming at all.  At the moment you seem to be programming them in the
> low-level plane programming functions (skl_update_plane and such).
> Instead, I had expected a single loop over each scaler at the very end of the
> entire commit process, after you're done with the plane programming functions.
> The scaler state would already indicate whether the scaler is supposed to be
> associated with a plane/crtc (which may or may not be the same as the previous
> frame; we don't care) or whether it is unused and should be programmed to off.
> So basically you would wind up programming all of the scaler registers on each
> atomic commit, even if they didn't change, but you wouldn't have to worry
> about whether the scaler's owner is changing or who is responsible for doing the
> programming of that scaler this time around --- basically just treat scalers as an
> independent resource that have their own programming step at the end of
> processing a CRTC.

OK. Now I understand what you meant.
In early versions, I tried something similar, but that approach
required back pointers from scaler to its owner to program scaler 
output window coordinates. 
And it also requires managing back pointer assignment and resetting.
It is certainly doable but I didn't see any advantage than current approach.

> 
> 
> >
> > >
> > > As I mentioned on a previous patch, these overloaded functions that
> > > might operate on a plane or might operate on a CRTC can be a bit
> > > confusing, especially when we have multi-nested ternary operators like you
> do below.
> >
> > >
> > > > + * if scaler is not in use.
> > > > + * It resets scaler_id in plane or crtc
> > > > + * To request detach a scaler from crtc, call plane as NULL  */
> > > > +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane) {
> > > > +	struct drm_device *dev = crtc->dev;
> > > > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > > > +	struct intel_crtc_state *crtc_state;
> > > > +	struct intel_crtc *intel_crtc;
> > > > +	struct intel_plane *intel_plane;
> > > > +	struct intel_plane_state *plane_state;
> > > > +	int *scaler_id;
> > > > +
> > > > +	intel_crtc = to_intel_crtc(crtc);
> > > > +	intel_plane = plane ? to_intel_plane(plane) : NULL;
> > > > +	crtc_state = intel_crtc->config;
> > > > +	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
> > > > +
> > > > +	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
> > > > +		&crtc_state->scaler_state.scaler_id;
> > > > +
> > > > +	if (!scaler_id || (scaler_id && *scaler_id < 0))
> > > > +		return;
> > > > +
> > > > +	/* if scaler is not in use, free */
> > > > +	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
> > > > +		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
> > > > +		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)),
> > > 0);
> > > > +		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
> > > > +		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u
> > > from %s:%d\n",
> > > > +			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
> > > > +			plane ? plane->base.id : crtc->base.id);
> > > > +		*scaler_id = -1;
> > >
> > > This confuses me...why are we updating the state here at the end of
> > > the commit step?  State should be immutable at this point, right?
> >
> > As I explained above, valid scaler_id is required. Then scaler_id can be set to -
> 1.
> 
> The problem is that we're ultimately updating crtc_state from the 'commit' step
> here, which violates the atomic design.  State structures are supposed to be
> immutable during the commit phase
> 
> >
> > >
> > >
> > > Matt
> > >
> > > > +	}
> > > > +}
> > > > +
> > > >  static void skylake_update_primary_plane(struct drm_crtc *crtc,
> > > >  					 struct drm_framebuffer *fb,
> > > >  					 int x, int y)
> > > > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > > > b/drivers/gpu/drm/i915/intel_drv.h
> > > > index a9d787d..f25d14d 100644
> > > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > > @@ -1141,6 +1141,7 @@ void intel_modeset_preclose(struct
> > > > drm_device *dev, struct drm_file *file);  int
> > > > skl_update_scaler_users(struct intel_crtc
> > > *intel_crtc,
> > > >  	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
> > > >  	struct intel_plane_state *plane_state, int force_detach);
> > > > +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane
> > > > +*plane);
> > > >
> > > >  /* intel_dp.c */
> > > >  void intel_dp_init(struct drm_device *dev, int output_reg, enum
> > > > port port);
> > > > --
> > > > 1.7.9.5
> > > >
> > >
> > > --
> > > Matt Roper
> > > Graphics Software Engineer
> > > IoTG Platform Enabling & Development Intel Corporation
> > > (916) 356-2795
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 21/21 v2] drm/i915: Enable skylake sprite plane scaling using shared scalers
  2015-03-21  0:04 ` [PATCH 21/21 v2] drm/i915: Enable skylake sprite " Chandra Konduru
@ 2015-03-25 21:29   ` Matt Roper
  2015-03-25 21:55     ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-25 21:29 UTC (permalink / raw)
  To: Chandra Konduru; +Cc: daniel.vetter, intel-gfx, ander.conselvan.de.oliveira

On Fri, Mar 20, 2015 at 05:04:42PM -0700, Chandra Konduru wrote:
> This patch enables skylake sprite plane display scaling using shared
> scalers atomic desgin.
> 
> v2:
> -use single copy of scaler limits (Matt)
> 
> Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_sprite.c |   79 +++++++++++++++++++++++++++--------
>  1 file changed, 61 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 0194390..b4452bc 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -33,6 +33,7 @@
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_fourcc.h>
>  #include <drm/drm_rect.h>
> +#include <drm/drm_atomic.h>
>  #include <drm/drm_plane_helper.h>
>  #include "intel_drv.h"
>  #include <drm/i915_drm.h>
> @@ -191,6 +192,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	const int plane = intel_plane->plane + 1;
>  	u32 plane_ctl, stride_div;
>  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> +	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
> +	int scaler_id;
>  
>  	plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
>  
> @@ -274,16 +277,39 @@ skl_update_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc,
>  	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
>  					       fb->pixel_format);
>  
> +	skl_detach_scaler(crtc, drm_plane);
> +	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> +
>  	/* Sizes are 0 based */
>  	src_w--;
>  	src_h--;
>  	crtc_w--;
>  	crtc_h--;
>  
> +	/* program plane scaler */
> +	if (scaler_id >= 0) {
> +		uint32_t ps_ctrl = 0;
> +
> +		DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) = 0x%x\n", plane,
> +			PS_PLANE_SEL(plane));
> +		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) |
> +			crtc_state->scaler_state.scalers[scaler_id].mode |
> +			crtc_state->scaler_state.scalers[scaler_id].filter;
> +		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
> +		I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
> +		I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
> +		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id),
> +			((crtc_w + 1) << 16)|(crtc_h + 1));
> +
> +		I915_WRITE(PLANE_POS(pipe, plane), 0);
> +		I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
> +	} else {
> +		I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
> +		I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
> +	}

These parts of the last few patches are what I was referring to earlier;
I think rather than programming scaler registers inside the plane update
(which means you have to keep track of who new/old owners are so that
the right plane takes responsibility), it would be easier to just have a
separate step, after planes are done being programmed, that writes the
proper values for each scaler, based on the CRTC scaling state.

> +
>  	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
>  	I915_WRITE(PLANE_STRIDE(pipe, plane), fb->pitches[0] / stride_div);
> -	I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
> -	I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
>  	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
>  	I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
>  	POSTING_READ(PLANE_SURF(pipe, plane));
> @@ -305,6 +331,8 @@ skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
>  	I915_WRITE(PLANE_CTL(pipe, plane), 0);
>  	POSTING_READ(PLANE_CTL(pipe, plane));
>  
> +	skl_detach_scaler(crtc, drm_plane);
> +
>  	intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false, false);
>  }
>  
> @@ -1088,7 +1116,9 @@ static int
>  intel_check_sprite_plane(struct drm_plane *plane,
>  			 struct intel_plane_state *state)
>  {
> +	struct drm_device *dev = plane->dev;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
> +	struct intel_crtc_state *crtc_state;
>  	struct intel_plane *intel_plane = to_intel_plane(plane);
>  	struct drm_framebuffer *fb = state->base.fb;
>  	int crtc_x, crtc_y;
> @@ -1097,11 +1127,16 @@ intel_check_sprite_plane(struct drm_plane *plane,
>  	struct drm_rect *src = &state->src;
>  	struct drm_rect *dst = &state->dst;
>  	const struct drm_rect *clip = &state->clip;
> +	struct intel_crtc_scaler_state *scaler_state;
>  	int hscale, vscale;
>  	int max_scale, min_scale;
>  	int pixel_size;
> +	int ret;
>  
>  	intel_crtc = intel_crtc ? intel_crtc : to_intel_crtc(plane->crtc);
> +	crtc_state = state->base.state ?
> +		intel_atomic_get_crtc_state(state->base.state, intel_crtc) : NULL;
> +	scaler_state = crtc_state ? &crtc_state->scaler_state : NULL;
>  
>  	if (!fb) {
>  		state->visible = false;
> @@ -1128,6 +1163,11 @@ intel_check_sprite_plane(struct drm_plane *plane,
>  	max_scale = intel_plane->max_downscale << 16;
>  	min_scale = intel_plane->can_scale ? 1 : (1 << 16);
>  
> +	if (INTEL_INFO(dev)->gen >= 9 && scaler_state && scaler_state->num_scalers) {
> +		min_scale = 1;
> +		max_scale = (100 << 16) / scaler_state->min_hsr;
> +	}
> +
>  	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
>  			state->base.rotation);
>  
> @@ -1223,18 +1263,18 @@ intel_check_sprite_plane(struct drm_plane *plane,
>  		width_bytes = ((src_x * pixel_size) & 63) +
>  					src_w * pixel_size;
>  
> -		if (src_w > 2048 || src_h > 2048 ||
> -		    width_bytes > 4096 || fb->pitches[0] > 4096) {
> +		if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 ||
> +		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
>  			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
>  			return -EINVAL;
>  		}
>  	}
>  
>  	if (state->visible) {
> -		src->x1 = src_x;
> -		src->x2 = src_x + src_w;
> -		src->y1 = src_y;
> -		src->y2 = src_y + src_h;
> +		src->x1 = src_x << 16;
> +		src->x2 = (src_x + src_w) << 16;
> +		src->y1 = src_y << 16;
> +		src->y2 = (src_y + src_h) << 16;

This feels unrelated...if we're changing our i915 subclass to use 16.16
format, that should probably be a standalone patch, independent of your
hardware enabling here, with an explanation of why we want to switch.

>  	}
>  
>  	dst->x1 = crtc_x;
> @@ -1271,6 +1311,13 @@ finish:
>  			intel_crtc->atomic.update_wm = true;
>  	}
>  
> +	if (INTEL_INFO(dev)->gen >= 9) {
> +		ret = skl_update_scaler_users(intel_crtc, crtc_state, intel_plane,
> +			state, 0);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	return 0;
>  }
>  
> @@ -1301,10 +1348,10 @@ intel_commit_sprite_plane(struct drm_plane *plane,
>  			crtc_y = state->dst.y1;
>  			crtc_w = drm_rect_width(&state->dst);
>  			crtc_h = drm_rect_height(&state->dst);
> -			src_x = state->src.x1;
> -			src_y = state->src.y1;
> -			src_w = drm_rect_width(&state->src);
> -			src_h = drm_rect_height(&state->src);
> +			src_x = state->src.x1 >> 16;
> +			src_y = state->src.y1 >> 16;
> +			src_w = drm_rect_width(&state->src) >> 16;
> +			src_h = drm_rect_height(&state->src) >> 16;
>  			intel_plane->update_plane(plane, crtc, fb, obj,
>  						  crtc_x, crtc_y, crtc_w, crtc_h,
>  						  src_x, src_y, src_w, src_h);
> @@ -1493,12 +1540,8 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
>  		}
>  		break;
>  	case 9:
> -		/*
> -		 * FIXME: Skylake planes can be scaled (with some restrictions),
> -		 * but this is for another time.
> -		 */
> -		intel_plane->can_scale = false;
> -		intel_plane->max_downscale = 1;
> +		intel_plane->can_scale = true;
> +		intel_plane->max_downscale = 2; /* updated later */
>  		intel_plane->update_plane = skl_update_plane;
>  		intel_plane->disable_plane = skl_disable_plane;
>  		intel_plane->update_colorkey = skl_update_colorkey;
> -- 
> 1.7.9.5
> 

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 21/21 v2] drm/i915: Enable skylake sprite plane scaling using shared scalers
  2015-03-25 21:29   ` Matt Roper
@ 2015-03-25 21:55     ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 21:55 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Wednesday, March 25, 2015 2:30 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 21/21 v2] drm/i915: Enable skylake sprite plane scaling
> using shared scalers
> 
> On Fri, Mar 20, 2015 at 05:04:42PM -0700, Chandra Konduru wrote:
> > This patch enables skylake sprite plane display scaling using shared
> > scalers atomic desgin.
> >
> > v2:
> > -use single copy of scaler limits (Matt)
> >
> > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_sprite.c |   79 +++++++++++++++++++++++++++---
> -----
> >  1 file changed, 61 insertions(+), 18 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c
> > b/drivers/gpu/drm/i915/intel_sprite.c
> > index 0194390..b4452bc 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -33,6 +33,7 @@
> >  #include <drm/drm_crtc.h>
> >  #include <drm/drm_fourcc.h>
> >  #include <drm/drm_rect.h>
> > +#include <drm/drm_atomic.h>
> >  #include <drm/drm_plane_helper.h>
> >  #include "intel_drv.h"
> >  #include <drm/i915_drm.h>
> > @@ -191,6 +192,8 @@ skl_update_plane(struct drm_plane *drm_plane,
> struct drm_crtc *crtc,
> >  	const int plane = intel_plane->plane + 1;
> >  	u32 plane_ctl, stride_div;
> >  	int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> > +	struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
> > +	int scaler_id;
> >
> >  	plane_ctl = I915_READ(PLANE_CTL(pipe, plane));
> >
> > @@ -274,16 +277,39 @@ skl_update_plane(struct drm_plane *drm_plane,
> struct drm_crtc *crtc,
> >  	stride_div = intel_fb_stride_alignment(dev, fb->modifier[0],
> >  					       fb->pixel_format);
> >
> > +	skl_detach_scaler(crtc, drm_plane);
> > +	scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> > +
> >  	/* Sizes are 0 based */
> >  	src_w--;
> >  	src_h--;
> >  	crtc_w--;
> >  	crtc_h--;
> >
> > +	/* program plane scaler */
> > +	if (scaler_id >= 0) {
> > +		uint32_t ps_ctrl = 0;
> > +
> > +		DRM_DEBUG_KMS("plane = %d PS_PLANE_SEL(plane) =
> 0x%x\n", plane,
> > +			PS_PLANE_SEL(plane));
> > +		ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane) |
> > +			crtc_state->scaler_state.scalers[scaler_id].mode |
> > +			crtc_state->scaler_state.scalers[scaler_id].filter;
> > +		I915_WRITE(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl);
> > +		I915_WRITE(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
> > +		I915_WRITE(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) |
> crtc_y);
> > +		I915_WRITE(SKL_PS_WIN_SZ(pipe, scaler_id),
> > +			((crtc_w + 1) << 16)|(crtc_h + 1));
> > +
> > +		I915_WRITE(PLANE_POS(pipe, plane), 0);
> > +		I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
> > +	} else {
> > +		I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
> > +		I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
> > +	}
> 
> These parts of the last few patches are what I was referring to earlier; I think
> rather than programming scaler registers inside the plane update (which means
> you have to keep track of who new/old owners are so that the right plane takes
> responsibility), it would be easier to just have a separate step, after planes are
> done being programmed, that writes the proper values for each scaler, based on
> the CRTC scaling state.

I got your point, but that approach has its own complexities and challenges.
I responded to your previous email regarding this one.

> 
> > +
> >  	I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
> >  	I915_WRITE(PLANE_STRIDE(pipe, plane), fb->pitches[0] / stride_div);
> > -	I915_WRITE(PLANE_POS(pipe, plane), (crtc_y << 16) | crtc_x);
> > -	I915_WRITE(PLANE_SIZE(pipe, plane), (crtc_h << 16) | crtc_w);
> >  	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
> >  	I915_WRITE(PLANE_SURF(pipe, plane), i915_gem_obj_ggtt_offset(obj));
> >  	POSTING_READ(PLANE_SURF(pipe, plane)); @@ -305,6 +331,8 @@
> > skl_disable_plane(struct drm_plane *drm_plane, struct drm_crtc *crtc)
> >  	I915_WRITE(PLANE_CTL(pipe, plane), 0);
> >  	POSTING_READ(PLANE_CTL(pipe, plane));
> >
> > +	skl_detach_scaler(crtc, drm_plane);
> > +
> >  	intel_update_sprite_watermarks(drm_plane, crtc, 0, 0, 0, false,
> > false);  }
> >
> > @@ -1088,7 +1116,9 @@ static int
> >  intel_check_sprite_plane(struct drm_plane *plane,
> >  			 struct intel_plane_state *state)
> >  {
> > +	struct drm_device *dev = plane->dev;
> >  	struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
> > +	struct intel_crtc_state *crtc_state;
> >  	struct intel_plane *intel_plane = to_intel_plane(plane);
> >  	struct drm_framebuffer *fb = state->base.fb;
> >  	int crtc_x, crtc_y;
> > @@ -1097,11 +1127,16 @@ intel_check_sprite_plane(struct drm_plane
> *plane,
> >  	struct drm_rect *src = &state->src;
> >  	struct drm_rect *dst = &state->dst;
> >  	const struct drm_rect *clip = &state->clip;
> > +	struct intel_crtc_scaler_state *scaler_state;
> >  	int hscale, vscale;
> >  	int max_scale, min_scale;
> >  	int pixel_size;
> > +	int ret;
> >
> >  	intel_crtc = intel_crtc ? intel_crtc : to_intel_crtc(plane->crtc);
> > +	crtc_state = state->base.state ?
> > +		intel_atomic_get_crtc_state(state->base.state, intel_crtc) :
> NULL;
> > +	scaler_state = crtc_state ? &crtc_state->scaler_state : NULL;
> >
> >  	if (!fb) {
> >  		state->visible = false;
> > @@ -1128,6 +1163,11 @@ intel_check_sprite_plane(struct drm_plane *plane,
> >  	max_scale = intel_plane->max_downscale << 16;
> >  	min_scale = intel_plane->can_scale ? 1 : (1 << 16);
> >
> > +	if (INTEL_INFO(dev)->gen >= 9 && scaler_state && scaler_state-
> >num_scalers) {
> > +		min_scale = 1;
> > +		max_scale = (100 << 16) / scaler_state->min_hsr;
> > +	}
> > +
> >  	drm_rect_rotate(src, fb->width << 16, fb->height << 16,
> >  			state->base.rotation);
> >
> > @@ -1223,18 +1263,18 @@ intel_check_sprite_plane(struct drm_plane
> *plane,
> >  		width_bytes = ((src_x * pixel_size) & 63) +
> >  					src_w * pixel_size;
> >
> > -		if (src_w > 2048 || src_h > 2048 ||
> > -		    width_bytes > 4096 || fb->pitches[0] > 4096) {
> > +		if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048
> ||
> > +		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
> >  			DRM_DEBUG_KMS("Source dimensions exceed
> hardware limits\n");
> >  			return -EINVAL;
> >  		}
> >  	}
> >
> >  	if (state->visible) {
> > -		src->x1 = src_x;
> > -		src->x2 = src_x + src_w;
> > -		src->y1 = src_y;
> > -		src->y2 = src_y + src_h;
> > +		src->x1 = src_x << 16;
> > +		src->x2 = (src_x + src_w) << 16;
> > +		src->y1 = src_y << 16;
> > +		src->y2 = (src_y + src_h) << 16;
> 
> This feels unrelated...if we're changing our i915 subclass to use 16.16 format,
> that should probably be a standalone patch, independent of your hardware
> enabling here, with an explanation of why we want to switch.

I touched this code because intel_commit_sprite_plane() 
is converting to regular integer (by doing >> 16) before calling
low level update_plane. For scalers to function properly
this change is required. So I made the change as part of this series. 

Code snippet from intel_commit_sprite_plane():
        if (state->visible) {
            crtc_x = state->dst.x1;
            crtc_y = state->dst.y1;
            crtc_w = drm_rect_width(&state->dst);
            crtc_h = drm_rect_height(&state->dst);
            src_x = state->src.x1 >> 16;
            src_y = state->src.y1 >> 16;
            src_w = drm_rect_width(&state->src) >> 16;
            src_h = drm_rect_height(&state->src) >> 16;
            intel_plane->update_plane(plane, crtc, fb, obj,
                          crtc_x, crtc_y, crtc_w, crtc_h,
                          src_x, src_y, src_w, src_h);
        } else {
            intel_plane->disable_plane(plane, crtc);
        }

> 
> >  	}
> >
> >  	dst->x1 = crtc_x;
> > @@ -1271,6 +1311,13 @@ finish:
> >  			intel_crtc->atomic.update_wm = true;
> >  	}
> >
> > +	if (INTEL_INFO(dev)->gen >= 9) {
> > +		ret = skl_update_scaler_users(intel_crtc, crtc_state, intel_plane,
> > +			state, 0);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	return 0;
> >  }
> >
> > @@ -1301,10 +1348,10 @@ intel_commit_sprite_plane(struct drm_plane
> *plane,
> >  			crtc_y = state->dst.y1;
> >  			crtc_w = drm_rect_width(&state->dst);
> >  			crtc_h = drm_rect_height(&state->dst);
> > -			src_x = state->src.x1;
> > -			src_y = state->src.y1;
> > -			src_w = drm_rect_width(&state->src);
> > -			src_h = drm_rect_height(&state->src);
> > +			src_x = state->src.x1 >> 16;
> > +			src_y = state->src.y1 >> 16;
> > +			src_w = drm_rect_width(&state->src) >> 16;
> > +			src_h = drm_rect_height(&state->src) >> 16;
> >  			intel_plane->update_plane(plane, crtc, fb, obj,
> >  						  crtc_x, crtc_y, crtc_w, crtc_h,
> >  						  src_x, src_y, src_w, src_h);
> > @@ -1493,12 +1540,8 @@ intel_plane_init(struct drm_device *dev, enum
> pipe pipe, int plane)
> >  		}
> >  		break;
> >  	case 9:
> > -		/*
> > -		 * FIXME: Skylake planes can be scaled (with some restrictions),
> > -		 * but this is for another time.
> > -		 */
> > -		intel_plane->can_scale = false;
> > -		intel_plane->max_downscale = 1;
> > +		intel_plane->can_scale = true;
> > +		intel_plane->max_downscale = 2; /* updated later */
> >  		intel_plane->update_plane = skl_update_plane;
> >  		intel_plane->disable_plane = skl_disable_plane;
> >  		intel_plane->update_colorkey = skl_update_colorkey;
> > --
> > 1.7.9.5
> >
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state
  2015-03-25 20:58       ` Matt Roper
@ 2015-03-25 22:02         ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-25 22:02 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Wednesday, March 25, 2015 1:59 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 08/21 v2] drm/i915: Add helper function to update
> scaler_users in crtc_state
> 
> On Wed, Mar 25, 2015 at 12:20:08PM -0700, Konduru, Chandra wrote:
> ...
> > >
> > > We're already calculating this in the plane check function; we
> > > should probably just store the result in a plane_state field at that
> > > point so we don't have to re- calculate it here.
> >
> > I think you are referring to sprite plane check, but this is not there
> > in primary plane check function.
> 
> Well, it is, but it's hidden inside the drm plane helper function and isn't directly in
> our i915 driver code.
> 
> I feel like "do these src/dest rectangles imply scaling?" is a question that is going
> to be relevant to all drivers, not just i915, so it might even be worth adding the
> field to the DRM core's state structure and have the helper function set it for any
> drivers using the helper.
> Hardware drivers could override this value, or could set it themselves if they
> don't use the helper.  Just a thought...

I think that makes sense, but not planning in this patch series.

> 
> 
> Matt
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH 05/21 v3] drm/i915: Initialize skylake scalers
  2015-03-21  0:04 ` [PATCH 05/21 v2] drm/i915: Initialize skylake scalers Chandra Konduru
  2015-03-25  5:14   ` Matt Roper
@ 2015-03-25 23:21   ` Chandra Konduru
  1 sibling, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-25 23:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Initializing scalers with supported values during crtc init.

v2:
-initialize single copy of min/max values (Matt)

v3:
-moved gen check to callsite (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   52 ++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 89299b6..90f12e8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -103,6 +103,8 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
 			    const struct intel_crtc_state *pipe_config);
 static void intel_begin_crtc_commit(struct drm_crtc *crtc);
 static void intel_finish_crtc_commit(struct drm_crtc *crtc);
+static void skl_init_scalers(struct drm_device *dev, int pipe,
+	struct intel_crtc_state *crtc_state);
 
 static struct intel_encoder *intel_find_encoder(struct intel_connector *connector, int pipe)
 {
@@ -12750,6 +12752,52 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
 	return &cursor->base;
 }
 
+static void skl_init_scalers(struct drm_device *dev, int pipe,
+	struct intel_crtc_state *crtc_state)
+{
+	int i;
+	struct intel_scaler *intel_scaler;
+	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
+
+	scaler_state->num_scalers = SKL_NUM_SCALERS;
+	for (i = 0; i < SKL_NUM_SCALERS; i++) {
+		intel_scaler = &scaler_state->scalers[i];
+		intel_scaler->in_use = 0;
+		intel_scaler->id = i;
+
+		intel_scaler->mode = PS_SCALER_MODE_DYN;
+		intel_scaler->filter = PS_FILTER_MEDIUM;
+	}
+
+	/* down scaling ratio: 2.99 --> 1, i.e., 34% of original */
+	scaler_state->min_hsr = 34;
+	scaler_state->min_vsr = 34;
+	scaler_state->max_hsr = 500;
+	scaler_state->max_vsr = 500;
+
+	/* down scaling ratio: 2.99x2.99 --> 1x1, i.e., 12% of original */
+	scaler_state->min_hvsr = 12;
+	scaler_state->max_hvsr = 2500;
+
+	/* src_w & dst_w range 8 - 4096 */
+	scaler_state->min_src_w = 8;
+	scaler_state->max_src_w = 4096;
+	scaler_state->min_dst_w = 8;
+	scaler_state->max_dst_w = 4096;
+
+	/* src_h & dst_h range 8 - 2304 */
+	scaler_state->min_src_h = 8;
+	scaler_state->max_src_h = 2304;
+	scaler_state->min_dst_h = 8;
+	scaler_state->max_dst_h = 2304;
+
+	/* pipe C has one scaler */
+	if (pipe == PIPE_C) {
+		scaler_state->num_scalers = 1;
+	}
+	scaler_state->scaler_id = -1;
+}
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -12769,6 +12817,10 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 	intel_crtc_set_state(intel_crtc, crtc_state);
 	crtc_state->base.crtc = &intel_crtc->base;
 
+	/* initialize shared scalers */
+	if (INTEL_INFO(dev)->gen >= 9)
+		skl_init_scalers(dev, pipe, crtc_state);
+
 	primary = intel_primary_plane_create(dev, pipe);
 	if (!primary)
 		goto fail;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 07/21 v3] drm/i915: Helper function to update skylake scaling ratio.
  2015-03-21  0:04 ` [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio Chandra Konduru
  2015-03-25  5:14   ` Matt Roper
@ 2015-03-25 23:21   ` Chandra Konduru
  1 sibling, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-25 23:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

Helper function updates supported scaling ratios based on cdclk and
crtc clocks.

v2:
-update single copy of scaling ratios (Matt)

v3:
-min scaling ratio is limited by either display engine limit or clocks,
 it is not related to previous ratio (Matt, me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ec58f1d..29d46fc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4513,6 +4513,31 @@ static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
 	intel_wait_for_vblank(dev, other_active_crtc->pipe);
 }
 
+static void skl_update_scaling_ratio(struct drm_device *dev,
+	struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	uint32_t crtc_clock, cdclk;
+	struct intel_crtc_scaler_state *scaler_state;
+
+	if (!crtc_state)
+		return;
+
+	crtc_clock = (uint32_t) crtc_state->base.adjusted_mode.crtc_clock;
+	cdclk = (uint32_t) intel_ddi_get_cdclk_freq(dev_priv);
+
+	if (!crtc_clock || !cdclk)
+		return;
+
+	scaler_state = &crtc_state->scaler_state;
+	scaler_state->min_hsr = max((uint32_t)34, (crtc_clock * 100)/cdclk);
+	scaler_state->min_vsr = max((uint32_t)34, (crtc_clock * 100)/cdclk);
+	scaler_state->min_hvsr = max((uint32_t)12, (crtc_clock * 100)/cdclk);
+
+	DRM_DEBUG_KMS("for crtc_state = %p crtc_clock = %d cdclk = %d\n", crtc_state,
+		crtc_clock, cdclk);
+}
+
 static void haswell_crtc_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 08/21 v3] drm/i915: Add helper function to update scaler_users in crtc_state
  2015-03-21  0:04 ` [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state Chandra Konduru
  2015-03-25  5:15   ` Matt Roper
@ 2015-03-25 23:21   ` Chandra Konduru
  1 sibling, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-25 23:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This helper function stages a scaler request for a plane/crtc into
crtc_state->scaler_users (which is a bit field). It also performs
required checks before staging any change into scaler_state.

v2:
-updates to use single copy of scaler limits (Matt)
-added force detach parameter for pfit disable purpose (me)

v3:
-updated function header to kerneldoc format (Matt)
-dropped need_scaling checks (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |  143 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    3 +
 2 files changed, 146 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 29d46fc..5c365f3 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12387,6 +12387,149 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
 	}
 }
 
+/**
+ * skl_update_scaler_users - Stages update to crtc's scaler state
+ * @intel_crtc: crtc
+ * @crtc_state: crtc_state
+ * @plane: plane (NULL indicates crtc is requesting update)
+ * @plane_state: plane's state
+ * @force_detach: request unconditional detachment of scaler
+ *
+ * This function updates scaler state for requested plane or crtc.
+ * To request scaler usage update for a plane, caller shall pass plane pointer.
+ * To request scaler usage update for crtc, caller shall pass plane pointer
+ * as NULL.
+ *
+ * Return
+ *     0 - scaler_usage updated successfully
+ *    error - requested scaling cannot be supported or other error condition
+ */
+int
+skl_update_scaler_users(
+	struct intel_crtc *intel_crtc, struct intel_crtc_state *crtc_state,
+	struct intel_plane *intel_plane, struct intel_plane_state *plane_state,
+	int force_detach)
+{
+	int need_scaling;
+	int idx;
+	int src_w, src_h, dst_w, dst_h;
+	int scaler_id;
+	struct drm_framebuffer *fb;
+	struct intel_crtc_scaler_state *scaler_state;
+
+	if (!intel_crtc || !crtc_state ||
+		(intel_plane && intel_plane->base.type == DRM_PLANE_TYPE_CURSOR))
+		return 0;
+
+	scaler_state = &crtc_state->scaler_state;
+
+	if (!scaler_state->num_scalers) {
+		DRM_DEBUG_KMS("crtc_state = %p, num_scalers = %d\n", crtc_state,
+			scaler_state->num_scalers);
+		return 0;
+	}
+
+	idx = intel_plane ? drm_plane_index(&intel_plane->base) : SKL_CRTC_INDEX;
+	fb = intel_plane ? plane_state->base.fb : NULL;
+
+	if (intel_plane) {
+		src_w = drm_rect_width(&plane_state->src) >> 16;
+		src_h = drm_rect_height(&plane_state->src) >> 16;
+		dst_w = drm_rect_width(&plane_state->dst);
+		dst_h = drm_rect_height(&plane_state->dst);
+		scaler_id = plane_state->scaler_id;
+	} else {
+		struct drm_display_mode *adjusted_mode =
+			&crtc_state->base.adjusted_mode;
+		src_w = crtc_state->pipe_src_w;
+		src_h = crtc_state->pipe_src_h;
+		dst_w = adjusted_mode->hdisplay;
+		dst_h = adjusted_mode->vdisplay;
+		scaler_id = scaler_state->scaler_id;
+	}
+	need_scaling = (src_w != dst_w || src_h != dst_h);
+
+	/*
+	 * if plane is being disabled or scaler is no more required or force detach
+	 *  - free scaler binded to this plane/crtc
+	 *  - in order to do this, update crtc->scaler_usage
+	 *
+	 * Here scaler state in crtc_state is set free so that
+	 * scaler can be assigned to other user. Actual register
+	 * update to free the scaler is done in plane/panel-fit programming.
+	 * For this purpose crtc/plane_state->scaler_id isn't reset here.
+	 */
+	if (force_detach || !need_scaling || (intel_plane &&
+		(!fb || !plane_state->visible))) {
+		if (scaler_id >= 0) {
+			scaler_state->scaler_users &= ~(1 << idx);
+			scaler_state->scalers[scaler_id].in_use = 0;
+
+			DRM_DEBUG_KMS("Staged freeing scaler id %u.%u from %s:%d "
+				"crtc_state = %p scaler_users = 0x%x\n",
+				intel_crtc->pipe, scaler_id, intel_plane ? "PLANE" : "CRTC",
+				intel_plane ? intel_plane->base.base.id :
+				intel_crtc->base.base.id, crtc_state,
+				scaler_state->scaler_users);
+		}
+		return 0;
+	}
+
+	/* range checks */
+	if (src_w < scaler_state->min_src_w || src_h < scaler_state->min_src_h ||
+		dst_w < scaler_state->min_dst_w || dst_h < scaler_state->min_dst_h ||
+
+		src_w > scaler_state->max_src_w || src_h > scaler_state->max_src_h ||
+		dst_w > scaler_state->max_dst_w || dst_h > scaler_state->max_dst_h) {
+		DRM_DEBUG_KMS("%s:%d scaler_user index %u.%u: src %ux%u dst %ux%u "
+			"size is out of scaler range\n",
+			intel_plane ? "PLANE" : "CRTC",
+			intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
+			intel_crtc->pipe, idx, src_w, src_h, dst_w, dst_h);
+		return -EINVAL;
+	}
+
+	/* check colorkey */
+	if (intel_plane && intel_colorkey_enabled(intel_plane)) {
+		DRM_DEBUG_KMS("PLANE:%d scaling with color key not allowed",
+			intel_plane->base.base.id);
+		return -EINVAL;
+	}
+
+	/* Check src format */
+	if (intel_plane) {
+		switch (fb->pixel_format) {
+		case DRM_FORMAT_RGB565:
+		case DRM_FORMAT_XBGR8888:
+		case DRM_FORMAT_XRGB8888:
+		case DRM_FORMAT_ABGR8888:
+		case DRM_FORMAT_ARGB8888:
+		case DRM_FORMAT_XRGB2101010:
+		case DRM_FORMAT_ARGB2101010:
+		case DRM_FORMAT_XBGR2101010:
+		case DRM_FORMAT_ABGR2101010:
+		case DRM_FORMAT_YUYV:
+		case DRM_FORMAT_YVYU:
+		case DRM_FORMAT_UYVY:
+		case DRM_FORMAT_VYUY:
+			break;
+		default:
+			DRM_DEBUG_KMS("PLANE:%d FB:%d unsupported scaling format 0x%x\n",
+				intel_plane->base.base.id, fb->base.id, fb->pixel_format);
+			return -EINVAL;
+		}
+	}
+
+	/* mark this plane as a scaler user in crtc_state */
+	scaler_state->scaler_users |= (1 << idx);
+	DRM_DEBUG_KMS("%s:%d staged scaling request for %ux%u->%ux%u "
+		"crtc_state = %p scaler_users = 0x%x\n",
+		intel_plane ? "PLANE" : "CRTC",
+		intel_plane ? intel_plane->base.base.id : intel_crtc->base.base.id,
+		src_w, src_h, dst_w, dst_h, crtc_state, scaler_state->scaler_users);
+	return 0;
+}
+
 static int
 intel_check_primary_plane(struct drm_plane *plane,
 			  struct intel_plane_state *state)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1da5087..f5d53c9 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1138,6 +1138,9 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_state *pipe_config);
 void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc);
 void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
+int skl_update_scaler_users(struct intel_crtc *intel_crtc,
+	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
+	struct intel_plane_state *plane_state, int force_detach);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 09/21 v3] drm/i915: Add atomic function to setup scalers scalers for a crtc.
  2015-03-21  0:04 ` [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc Chandra Konduru
  2015-03-25  5:15   ` Matt Roper
@ 2015-03-25 23:21   ` Chandra Konduru
  1 sibling, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-25 23:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

intel_atomic_setup_scalers sets up scalers based on staged scaling
requests coming from a crtc and its planes. This function should be
called from crtc level check path.

If staged requests are supportable, function assigns scalers to
requested planes and crtc. This function also takes into account
the current planes using scalers but not being part of this
atomic state for optimal operation of scalers. Note that the scaler
assignement itself is staged into crtc_state and respective
plane_states for later commit after all checks have been done.

overall high level flow:
 - scaler requests are staged into crtc_state by planes/crtc
 - check whether staged scaling requests can be supported
 - add planes using scalers that aren't in current transaction
 - assign scalers to requested users
 - as part of plane commit, scalers will be committed
   (i.e., either attached or detached) to respective planes in hw
 - as part of crtc_commit, scaler will be either attached or detached
   to crtc in hw

v2:
-removed a log message (me)
-changed input parameter to crtc_state (me)

v3:
-remove assigning plane_state returned by drm_atomic_get_plane_state (Matt)
-fail if there is an error from drm_atomic_get_plane_state (Matt)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c |  142 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h    |    3 +
 2 files changed, 145 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 3903b90..fab1f13 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -241,3 +241,145 @@ intel_crtc_destroy_state(struct drm_crtc *crtc,
 {
 	drm_atomic_helper_crtc_destroy_state(crtc, state);
 }
+
+/**
+ * intel_atomic_setup_scalers() - setup scalers for crtc per staged requests
+ * @dev: DRM device
+ * @crtc: intel crtc
+ * @crtc_state: incoming crtc_state to validate and setup scalers
+ *
+ * This function sets up scalers based on staged scaling requests for
+ * a @crtc and its planes. It is called from crtc level check path. If request
+ * is a supportable request, it attaches scalers to requested planes and crtc.
+ *
+ * This function takes into account the current scaler(s) in use by any planes
+ * not being part of this atomic state
+ *
+ *  Returns:
+ *         0 - scalers were setup succesfully
+ *         error code - otherwise
+ */
+int intel_atomic_setup_scalers(struct drm_device *dev,
+	struct intel_crtc *intel_crtc,
+	struct intel_crtc_state *crtc_state)
+{
+	struct drm_plane *plane = NULL;
+	struct intel_plane *intel_plane;
+	struct intel_plane_state *plane_state = NULL;
+	struct intel_crtc_scaler_state *scaler_state;
+	struct drm_atomic_state *drm_state;
+	int num_scalers_need;
+	int i, j;
+
+	if (INTEL_INFO(dev)->gen < 9 || !intel_crtc || !crtc_state)
+		return 0;
+
+	scaler_state = &crtc_state->scaler_state;
+	drm_state = crtc_state->base.state;
+
+	num_scalers_need = hweight32(scaler_state->scaler_users);
+	DRM_DEBUG_KMS("crtc_state = %p need = %d avail = %d scaler_users = 0x%x\n",
+		crtc_state, num_scalers_need, scaler_state->num_scalers,
+		scaler_state->scaler_users);
+
+	/* if there is no change in scaler configuration, return */
+	if (scaler_state->scaler_users ==
+		intel_crtc->config->scaler_state.scaler_users)
+		return 0;
+
+	/*
+	 * High level flow:
+	 * - staged scaler requests are already in scaler_state->scaler_users
+	 * - check whether staged scaling requests can be supported
+	 * - add planes using scalers that aren't in current transaction
+	 * - assign scalers to requested users
+	 * - as part of plane commit, scalers will be committed
+	 *   (i.e., either attached or detached) to respective planes in hw
+	 * - as part of crtc_commit, scaler will be either attached or detached
+	 *   to crtc in hw
+	 */
+
+	/* fail if required scalers > available scalers */
+	if (num_scalers_need > scaler_state->num_scalers){
+		DRM_DEBUG_KMS("Too many scaling requests %d > %d\n",
+			num_scalers_need, scaler_state->num_scalers);
+		return -EINVAL;
+	}
+
+	/* walkthrough scaler_users bits and start assigning scalers */
+	for (i = 0; i < sizeof(scaler_state->scaler_users) * 8; i++) {
+		int *scaler_id;
+
+		/* skip if scaler not required */
+		if (!(scaler_state->scaler_users & (1 << i)))
+			continue;
+
+		if (i == SKL_CRTC_INDEX) {
+			/* panel fitter case: assign as a crtc scaler */
+			scaler_id = &scaler_state->scaler_id;
+		} else {
+			if (!drm_state)
+				continue;
+
+			/* plane scaler case: assign as a plane scaler */
+			/* find the plane that set the bit as scaler_user */
+			plane = drm_state->planes[i];
+
+			/*
+			 * to enable/disable hq mode, add planes that are using scaler
+			 * into this transaction
+			 */
+			if (!plane) {
+				struct drm_plane_state *state;
+				plane = drm_plane_from_index(dev, i);
+				state = drm_atomic_get_plane_state(drm_state, plane);
+				if (IS_ERR(state)) {
+					DRM_DEBUG_KMS("Failed to add [PLANE:%d] to drm_state\n",
+						plane->base.id);
+					return PTR_ERR(state);
+				}
+			}
+
+			intel_plane = to_intel_plane(plane);
+
+			/* plane on different crtc cannot be a scaler user of this crtc */
+			if (WARN_ON(intel_plane->pipe != intel_crtc->pipe)) {
+				continue;
+			}
+
+			plane_state = to_intel_plane_state(drm_state->plane_states[i]);
+			scaler_id = &plane_state->scaler_id;
+		}
+
+		if (*scaler_id < 0) {
+			/* find a free scaler */
+			for (j = 0; j < scaler_state->num_scalers; j++) {
+				if (!scaler_state->scalers[j].in_use) {
+					scaler_state->scalers[j].in_use = 1;
+					*scaler_id = scaler_state->scalers[j].id;
+					DRM_DEBUG_KMS("Attached scaler id %u.%u to %s:%d\n",
+						intel_crtc->pipe,
+						i == SKL_CRTC_INDEX ? scaler_state->scaler_id :
+							plane_state->scaler_id,
+						i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
+						i == SKL_CRTC_INDEX ?  intel_crtc->base.base.id :
+						plane->base.id);
+					break;
+				}
+			}
+		}
+
+		if (WARN_ON(*scaler_id < 0)) {
+			DRM_DEBUG_KMS("Cannot find scaler for %s:%d\n",
+				i == SKL_CRTC_INDEX ? "CRTC" : "PLANE",
+				i == SKL_CRTC_INDEX ? intel_crtc->base.base.id:plane->base.id);
+			continue;
+		}
+
+		/* set scaler mode */
+		scaler_state->scalers[*scaler_id].mode = (num_scalers_need == 1) ?
+			PS_SCALER_MODE_HQ : PS_SCALER_MODE_DYN;
+	}
+
+	return 0;
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f5d53c9..a9d787d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1401,6 +1401,9 @@ intel_atomic_get_crtc_state(struct drm_atomic_state *state,
 
 	return to_intel_crtc_state(crtc_state);
 }
+int intel_atomic_setup_scalers(struct drm_device *dev,
+	struct intel_crtc *intel_crtc,
+	struct intel_crtc_state *crtc_state);
 
 /* intel_atomic_plane.c */
 struct intel_plane_state *intel_create_plane_state(struct drm_plane *plane);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH 10/21 v3] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-21  0:04 ` [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc Chandra Konduru
  2015-03-25  5:15   ` Matt Roper
@ 2015-03-25 23:21   ` Chandra Konduru
  1 sibling, 0 replies; 56+ messages in thread
From: Chandra Konduru @ 2015-03-25 23:21 UTC (permalink / raw)
  To: intel-gfx; +Cc: ander.conselvan.de.oliveira, daniel.vetter

This function is called from commit path of a plane or crtc.
It programs scaler registers to detach (aka. unbinds) scaler
from requested plane or crtc if it isn't in use. It also resets
scaler_id in crtc/plane state.

v2:
-improved a log message (me)

v3:
-improved commentary (Matt)
-added a case where scaler id needs to be reset (me)

Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   57 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    1 +
 2 files changed, 58 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5c365f3..8290c7d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2836,6 +2836,63 @@ u32 intel_fb_stride_alignment(struct drm_device *dev, uint64_t fb_modifier,
 	}
 }
 
+/*
+ * This function detaches (aka. unbinds) a scaler from plane or crtc
+ * if scaler is not in use.
+ * It resets scaler_id in plane or crtc
+ * To request detach a scaler from crtc, call plane as NULL
+ */
+void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc_state *crtc_state;
+	struct intel_crtc *intel_crtc;
+	struct intel_plane *intel_plane;
+	struct intel_plane_state *plane_state;
+	int *scaler_id;
+	int idx;
+
+	intel_crtc = to_intel_crtc(crtc);
+	intel_plane = plane ? to_intel_plane(plane) : NULL;
+	crtc_state = intel_crtc->config;
+	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
+
+	idx = plane ? drm_plane_index(plane) : SKL_CRTC_INDEX;
+	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
+		&crtc_state->scaler_state.scaler_id;
+
+	if (!scaler_id || (scaler_id && *scaler_id < 0))
+		return;
+
+	/*
+	 * staged scaler state can trigger below:
+	 *
+	 * 1) scaler is freed and not attached to any other user. In this case,
+	 *    reg programming needed to update hw. And reset scaler_id to -1
+	 *    to indicate scaler isn't used. Once done, both sw and hw states
+	 *    are in sync.
+	 * 2) scaler is freed and attached to other user. In this case, registers
+	 *    shouldn't be touched here because scaler is used by new owner.
+	 *    Just reset scaler_id to -1.
+	 * 3) scaler is with same user as before. In this case, registers
+	 *    shouldn't be touched. No action needed.
+	 */
+	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
+		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
+		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)), 0);
+		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
+		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u from %s:%d\n",
+			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
+			plane ? plane->base.id : crtc->base.id);
+		*scaler_id = -1;
+	}
+
+	if (!(crtc_state->scaler_state.scaler_users & (1 << idx))) {
+		*scaler_id = -1;
+	}
+}
+
 static void skylake_update_primary_plane(struct drm_crtc *crtc,
 					 struct drm_framebuffer *fb,
 					 int x, int y)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a9d787d..f25d14d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1141,6 +1141,7 @@ void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file);
 int skl_update_scaler_users(struct intel_crtc *intel_crtc,
 	struct intel_crtc_state *crtc_state, struct intel_plane *intel_plane,
 	struct intel_plane_state *plane_state, int force_detach);
+void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
-- 
1.7.9.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-25 21:28         ` Konduru, Chandra
@ 2015-03-28  0:21           ` Matt Roper
  2015-03-30 19:06             ` Konduru, Chandra
  0 siblings, 1 reply; 56+ messages in thread
From: Matt Roper @ 2015-03-28  0:21 UTC (permalink / raw)
  To: Konduru, Chandra; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander

On Wed, Mar 25, 2015 at 02:28:16PM -0700, Konduru, Chandra wrote:
> 
> 
> > -----Original Message-----
> > From: Roper, Matthew D
> > Sent: Wednesday, March 25, 2015 2:14 PM
> > To: Konduru, Chandra
> > Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> > Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from
> > a plane or crtc
> > 
> > On Wed, Mar 25, 2015 at 01:14:40PM -0700, Konduru, Chandra wrote:
> > >
> > >
> > > > -----Original Message-----
> > > > From: Roper, Matthew D
> > > > Sent: Tuesday, March 24, 2015 10:16 PM
> > > > To: Konduru, Chandra
> > > > Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De
> > > > Oliveira, Ander
> > > > Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a
> > > > scaler from a plane or crtc
> > > >
> > > > On Fri, Mar 20, 2015 at 05:04:31PM -0700, Chandra Konduru wrote:
> > > > > This function is called from commit path of a plane or crtc.
> > > > > It programs scaler registers to detach (aka. unbinds) scaler from
> > > > > requested plane or crtc if it isn't in use. It also resets
> > > > > scaler_id in crtc/plane state.
> > > > >
> > > > > v2:
> > > > > -improved a log message (me)
> > > > >
> > > > > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_display.c |   39
> > > > ++++++++++++++++++++++++++++++++++
> > > > >  drivers/gpu/drm/i915/intel_drv.h     |    1 +
> > > > >  2 files changed, 40 insertions(+)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > > > b/drivers/gpu/drm/i915/intel_display.c
> > > > > index 976bfb1..7150c33 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > > @@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct
> > > > > drm_device
> > > > *dev, uint64_t fb_modifier,
> > > > >  	}
> > > > >  }
> > > > >
> > > > > +/*
> > > > > + * This function detaches (aka. unbinds) a scaler from plane or
> > > > > +crtc
> > > >
> > > > You might want to clarify that detach/unbind refers to the actual
> > > > hardware programming, not the state calculation.  I'm a bit
> > > > surprised we need this function; I figured we'd just be looping over
> > > > all scalers at the end of the commit step and programming them to
> > > > either on or off depending on what the scaling state contained.
> > >
> > > This is bit tricky and isn't that straight forward.
> > > Staged scaler state can trigger freeing a scaler that can lead to two scenarios:
> > > 1) freed scaler is not attached to any other user. In this case, reg
> > > programming needed to update hw. And reset scaler_id to -1 to indicate scaler
> > isn't used.
> > > Once done, both sw and hw states are in sync.
> > >
> > > 2) freed scaler is allocated to someone. In this case, registers
> > > shouldn't be programmed by previous owner because scaler may be in use
> > > by new owner.
> > >
> > > I think I explained these details in comments already. But will check
> > > and update if needed.
> > 
> > I might not have been clear in my earlier email.  What I meant was that I didn't
> > expect scalers to be programmed as part of their "owner's"
> > programming at all.  At the moment you seem to be programming them in the
> > low-level plane programming functions (skl_update_plane and such).
> > Instead, I had expected a single loop over each scaler at the very end of the
> > entire commit process, after you're done with the plane programming functions.
> > The scaler state would already indicate whether the scaler is supposed to be
> > associated with a plane/crtc (which may or may not be the same as the previous
> > frame; we don't care) or whether it is unused and should be programmed to off.
> > So basically you would wind up programming all of the scaler registers on each
> > atomic commit, even if they didn't change, but you wouldn't have to worry
> > about whether the scaler's owner is changing or who is responsible for doing the
> > programming of that scaler this time around --- basically just treat scalers as an
> > independent resource that have their own programming step at the end of
> > processing a CRTC.
> 
> OK. Now I understand what you meant.
> In early versions, I tried something similar, but that approach
> required back pointers from scaler to its owner to program scaler 
> output window coordinates. 
> And it also requires managing back pointer assignment and resetting.
> It is certainly doable but I didn't see any advantage than current approach.
> 
> > 
> > 
> > >
> > > >
> > > > As I mentioned on a previous patch, these overloaded functions that
> > > > might operate on a plane or might operate on a CRTC can be a bit
> > > > confusing, especially when we have multi-nested ternary operators like you
> > do below.
> > >
> > > >
> > > > > + * if scaler is not in use.
> > > > > + * It resets scaler_id in plane or crtc
> > > > > + * To request detach a scaler from crtc, call plane as NULL  */
> > > > > +void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane *plane) {
> > > > > +	struct drm_device *dev = crtc->dev;
> > > > > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > > > > +	struct intel_crtc_state *crtc_state;
> > > > > +	struct intel_crtc *intel_crtc;
> > > > > +	struct intel_plane *intel_plane;
> > > > > +	struct intel_plane_state *plane_state;
> > > > > +	int *scaler_id;
> > > > > +
> > > > > +	intel_crtc = to_intel_crtc(crtc);
> > > > > +	intel_plane = plane ? to_intel_plane(plane) : NULL;
> > > > > +	crtc_state = intel_crtc->config;
> > > > > +	plane_state = plane ? to_intel_plane_state(plane->state) : NULL;
> > > > > +
> > > > > +	scaler_id = plane ? (plane_state ? &plane_state->scaler_id : NULL) :
> > > > > +		&crtc_state->scaler_state.scaler_id;
> > > > > +
> > > > > +	if (!scaler_id || (scaler_id && *scaler_id < 0))
> > > > > +		return;
> > > > > +
> > > > > +	/* if scaler is not in use, free */
> > > > > +	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
> > > > > +		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe, (*scaler_id)), 0);
> > > > > +		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe, (*scaler_id)),
> > > > 0);
> > > > > +		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe, (*scaler_id)), 0);
> > > > > +		DRM_DEBUG_KMS("Detached and disabled scaler id %u.%u
> > > > from %s:%d\n",
> > > > > +			intel_crtc->pipe, *scaler_id, plane ? "PLANE" : "CRTC",
> > > > > +			plane ? plane->base.id : crtc->base.id);
> > > > > +		*scaler_id = -1;
> > > >
> > > > This confuses me...why are we updating the state here at the end of
> > > > the commit step?  State should be immutable at this point, right?
> > >
> > > As I explained above, valid scaler_id is required. Then scaler_id can be set to -
> > 1.
> > 
> > The problem is that we're ultimately updating crtc_state from the 'commit' step
> > here, which violates the atomic design.  State structures are supposed to be
> > immutable during the commit phase

This is still a problem; we really can't go back and update the state
structure in a function that is ultimately called as part of the
'commit' phase.  Also keep in mind that locks may have already been dropped
before we start the commit phase (for non-blocking flips that run in a
wq thread).

I'm still unconvinced on the need for the whole "program scaler
registers with their current owner" design.  Above you said:

> OK. Now I understand what you meant.
> In early versions, I tried something similar, but that approach
> required back pointers from scaler to its owner to program scaler 
> output window coordinates. 
> And it also requires managing back pointer assignment and resetting.
> It is certainly doable but I didn't see any advantage than current approach.

When we assign a scaler to a plane or a CRTC in the check phase, why
can't we just pre-calculate the actual register values like

        crtc_state->scaler_state.scalers[i].ctrl
        crtc_state->scaler_state.scalers[i].win_pos
        crtc_state->scaler_state.scalers[i].win_sz

at that point rather than trying to maintain backpointers to planes or
crtcs?  Then at the end of your CRTC commit you could just do the
equivalent of:

        for each scaler {
                I915_WRITE(SKL_PS_CTRL[i], state->ctrl);
                I915_WRITE(SKL_PS_WIN_POS[i], state->win_pos);
                I915_WRITE(SKL_PS_WIN_SZ[i], state->win_sz);
        }

This eliminates the need for the whole 'detach' concept, avoids the need
for backpointers to the actual plane/crtc which you were worried about,
and brings all the programming into one place rather than spreading it
across a bunch of different planes/crtc functions, which is a lot more
complicated logic-wise.

Feel free to tell me I'm stupid if I'm overlooking some obvious
stumbling block with this approach.  :-)


Matt


-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc
  2015-03-28  0:21           ` Matt Roper
@ 2015-03-30 19:06             ` Konduru, Chandra
  0 siblings, 0 replies; 56+ messages in thread
From: Konduru, Chandra @ 2015-03-30 19:06 UTC (permalink / raw)
  To: Roper, Matthew D; +Cc: Vetter, Daniel, intel-gfx, Conselvan De Oliveira, Ander



> -----Original Message-----
> From: Roper, Matthew D
> Sent: Friday, March 27, 2015 5:22 PM
> To: Konduru, Chandra
> Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De Oliveira, Ander
> Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from
> a plane or crtc
> 
> On Wed, Mar 25, 2015 at 02:28:16PM -0700, Konduru, Chandra wrote:
> >
> >
> > > -----Original Message-----
> > > From: Roper, Matthew D
> > > Sent: Wednesday, March 25, 2015 2:14 PM
> > > To: Konduru, Chandra
> > > Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan De
> > > Oliveira, Ander
> > > Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to detach a
> > > scaler from a plane or crtc
> > >
> > > On Wed, Mar 25, 2015 at 01:14:40PM -0700, Konduru, Chandra wrote:
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Roper, Matthew D
> > > > > Sent: Tuesday, March 24, 2015 10:16 PM
> > > > > To: Konduru, Chandra
> > > > > Cc: intel-gfx@lists.freedesktop.org; Vetter, Daniel; Conselvan
> > > > > De Oliveira, Ander
> > > > > Subject: Re: [PATCH 10/21 v2] drm/i915: Helper function to
> > > > > detach a scaler from a plane or crtc
> > > > >
> > > > > On Fri, Mar 20, 2015 at 05:04:31PM -0700, Chandra Konduru wrote:
> > > > > > This function is called from commit path of a plane or crtc.
> > > > > > It programs scaler registers to detach (aka. unbinds) scaler
> > > > > > from requested plane or crtc if it isn't in use. It also
> > > > > > resets scaler_id in crtc/plane state.
> > > > > >
> > > > > > v2:
> > > > > > -improved a log message (me)
> > > > > >
> > > > > > Signed-off-by: Chandra Konduru <chandra.konduru@intel.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/i915/intel_display.c |   39
> > > > > ++++++++++++++++++++++++++++++++++
> > > > > >  drivers/gpu/drm/i915/intel_drv.h     |    1 +
> > > > > >  2 files changed, 40 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > > > > > b/drivers/gpu/drm/i915/intel_display.c
> > > > > > index 976bfb1..7150c33 100644
> > > > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > > > @@ -2836,6 +2836,45 @@ u32 intel_fb_stride_alignment(struct
> > > > > > drm_device
> > > > > *dev, uint64_t fb_modifier,
> > > > > >  	}
> > > > > >  }
> > > > > >
> > > > > > +/*
> > > > > > + * This function detaches (aka. unbinds) a scaler from plane
> > > > > > +or crtc
> > > > >
> > > > > You might want to clarify that detach/unbind refers to the
> > > > > actual hardware programming, not the state calculation.  I'm a
> > > > > bit surprised we need this function; I figured we'd just be
> > > > > looping over all scalers at the end of the commit step and
> > > > > programming them to either on or off depending on what the scaling
> state contained.
> > > >
> > > > This is bit tricky and isn't that straight forward.
> > > > Staged scaler state can trigger freeing a scaler that can lead to two
> scenarios:
> > > > 1) freed scaler is not attached to any other user. In this case,
> > > > reg programming needed to update hw. And reset scaler_id to -1 to
> > > > indicate scaler
> > > isn't used.
> > > > Once done, both sw and hw states are in sync.
> > > >
> > > > 2) freed scaler is allocated to someone. In this case, registers
> > > > shouldn't be programmed by previous owner because scaler may be in
> > > > use by new owner.
> > > >
> > > > I think I explained these details in comments already. But will
> > > > check and update if needed.
> > >
> > > I might not have been clear in my earlier email.  What I meant was
> > > that I didn't expect scalers to be programmed as part of their "owner's"
> > > programming at all.  At the moment you seem to be programming them
> > > in the low-level plane programming functions (skl_update_plane and such).
> > > Instead, I had expected a single loop over each scaler at the very
> > > end of the entire commit process, after you're done with the plane
> programming functions.
> > > The scaler state would already indicate whether the scaler is
> > > supposed to be associated with a plane/crtc (which may or may not be
> > > the same as the previous frame; we don't care) or whether it is unused and
> should be programmed to off.
> > > So basically you would wind up programming all of the scaler
> > > registers on each atomic commit, even if they didn't change, but you
> > > wouldn't have to worry about whether the scaler's owner is changing
> > > or who is responsible for doing the programming of that scaler this
> > > time around --- basically just treat scalers as an independent
> > > resource that have their own programming step at the end of processing a
> CRTC.
> >
> > OK. Now I understand what you meant.
> > In early versions, I tried something similar, but that approach
> > required back pointers from scaler to its owner to program scaler
> > output window coordinates.
> > And it also requires managing back pointer assignment and resetting.
> > It is certainly doable but I didn't see any advantage than current approach.
> >
> > >
> > >
> > > >
> > > > >
> > > > > As I mentioned on a previous patch, these overloaded functions
> > > > > that might operate on a plane or might operate on a CRTC can be
> > > > > a bit confusing, especially when we have multi-nested ternary
> > > > > operators like you
> > > do below.
> > > >
> > > > >
> > > > > > + * if scaler is not in use.
> > > > > > + * It resets scaler_id in plane or crtc
> > > > > > + * To request detach a scaler from crtc, call plane as NULL
> > > > > > +*/ void skl_detach_scaler(struct drm_crtc *crtc, struct drm_plane
> *plane) {
> > > > > > +	struct drm_device *dev = crtc->dev;
> > > > > > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > > > > > +	struct intel_crtc_state *crtc_state;
> > > > > > +	struct intel_crtc *intel_crtc;
> > > > > > +	struct intel_plane *intel_plane;
> > > > > > +	struct intel_plane_state *plane_state;
> > > > > > +	int *scaler_id;
> > > > > > +
> > > > > > +	intel_crtc = to_intel_crtc(crtc);
> > > > > > +	intel_plane = plane ? to_intel_plane(plane) : NULL;
> > > > > > +	crtc_state = intel_crtc->config;
> > > > > > +	plane_state = plane ? to_intel_plane_state(plane->state) :
> > > > > > +NULL;
> > > > > > +
> > > > > > +	scaler_id = plane ? (plane_state ? &plane_state->scaler_id :
> NULL) :
> > > > > > +		&crtc_state->scaler_state.scaler_id;
> > > > > > +
> > > > > > +	if (!scaler_id || (scaler_id && *scaler_id < 0))
> > > > > > +		return;
> > > > > > +
> > > > > > +	/* if scaler is not in use, free */
> > > > > > +	if (!crtc_state->scaler_state.scalers[*scaler_id].in_use) {
> > > > > > +		I915_WRITE(SKL_PS_CTRL(intel_crtc->pipe,
> (*scaler_id)), 0);
> > > > > > +		I915_WRITE(SKL_PS_WIN_POS(intel_crtc->pipe,
> (*scaler_id)),
> > > > > 0);
> > > > > > +		I915_WRITE(SKL_PS_WIN_SZ(intel_crtc->pipe,
> (*scaler_id)), 0);
> > > > > > +		DRM_DEBUG_KMS("Detached and disabled scaler id
> %u.%u
> > > > > from %s:%d\n",
> > > > > > +			intel_crtc->pipe, *scaler_id, plane ? "PLANE" :
> "CRTC",
> > > > > > +			plane ? plane->base.id : crtc->base.id);
> > > > > > +		*scaler_id = -1;
> > > > >
> > > > > This confuses me...why are we updating the state here at the end
> > > > > of the commit step?  State should be immutable at this point, right?
> > > >
> > > > As I explained above, valid scaler_id is required. Then scaler_id
> > > > can be set to -
> > > 1.
> > >
> > > The problem is that we're ultimately updating crtc_state from the
> > > 'commit' step here, which violates the atomic design.  State
> > > structures are supposed to be immutable during the commit phase
> 
> This is still a problem; we really can't go back and update the state structure in a
> function that is ultimately called as part of the 'commit' phase.  Also keep in
> mind that locks may have already been dropped before we start the commit
> phase (for non-blocking flips that run in a wq thread).
> 
> I'm still unconvinced on the need for the whole "program scaler registers with
> their current owner" design.  Above you said:
> 
> > OK. Now I understand what you meant.
> > In early versions, I tried something similar, but that approach
> > required back pointers from scaler to its owner to program scaler
> > output window coordinates.
> > And it also requires managing back pointer assignment and resetting.
> > It is certainly doable but I didn't see any advantage than current approach.
> 
> When we assign a scaler to a plane or a CRTC in the check phase, why can't we
> just pre-calculate the actual register values like
> 
>         crtc_state->scaler_state.scalers[i].ctrl
>         crtc_state->scaler_state.scalers[i].win_pos
>         crtc_state->scaler_state.scalers[i].win_sz
> 
> at that point rather than trying to maintain backpointers to planes or crtcs?
> Then at the end of your CRTC commit you could just do the equivalent of:
> 
>         for each scaler {
>                 I915_WRITE(SKL_PS_CTRL[i], state->ctrl);
>                 I915_WRITE(SKL_PS_WIN_POS[i], state->win_pos);
>                 I915_WRITE(SKL_PS_WIN_SZ[i], state->win_sz);
>         }
> 
> This eliminates the need for the whole 'detach' concept, avoids the need for
> backpointers to the actual plane/crtc which you were worried about, and brings
> all the programming into one place rather than spreading it across a bunch of
> different planes/crtc functions, which is a lot more complicated logic-wise.
> 
> Feel free to tell me I'm stupid if I'm overlooking some obvious stumbling block
> with this approach.  :-)

I had a chat with Matt and his concern is when state is duplicated for a 
subsequent flip while a non-blocking flip is staged but not committed.
This isn't an issue because the state in crtc is still whatever previously 
committed state and not uncommitted but staged state.

Anyway, once full atomic crtc check/commit is in place I can revisit 
and make any mods if above update is an issue. For now I think it is fine.

> 
> 
> Matt
> 
> 
> --
> Matt Roper
> Graphics Software Engineer
> IoTG Platform Enabling & Development
> Intel Corporation
> (916) 356-2795
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2015-03-30 19:06 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-21  0:04 [PATCH 00/21 v2] Adding support for skylake shared scalers Chandra Konduru
2015-03-21  0:04 ` [PATCH 01/21 v2] drm/i915: Adding drm helper function drm_plane_from_index() Chandra Konduru
2015-03-23  9:32   ` Daniel Vetter
2015-03-23 16:32     ` Konduru, Chandra
2015-03-21  0:04 ` [PATCH 02/21 v2] drm/i915: Register definitions for skylake scalers Chandra Konduru
2015-03-21  0:04 ` [PATCH 03/21 v2] drm/i915: Enable get_colorkey functions for primary plane Chandra Konduru
2015-03-21  0:04 ` [PATCH 04/21 v2] drm/i915: skylake scaler structure definitions Chandra Konduru
2015-03-25  5:13   ` Matt Roper
2015-03-25 13:22     ` Daniel Vetter
2015-03-25 16:54     ` Konduru, Chandra
2015-03-21  0:04 ` [PATCH 05/21 v2] drm/i915: Initialize skylake scalers Chandra Konduru
2015-03-25  5:14   ` Matt Roper
2015-03-25 13:24     ` Daniel Vetter
2015-03-25 16:56     ` Konduru, Chandra
2015-03-25 23:21   ` [PATCH 05/21 v3] " Chandra Konduru
2015-03-21  0:04 ` [PATCH 06/21 v2] drm/i915: Dump scaler_state too as part of dumping crtc_state Chandra Konduru
2015-03-21  0:04 ` [PATCH 07/21 v2] drm/i915: Helper function to update skylake scaling ratio Chandra Konduru
2015-03-25  5:14   ` Matt Roper
2015-03-25 17:37     ` Konduru, Chandra
2015-03-25 23:21   ` [PATCH 07/21 v3] " Chandra Konduru
2015-03-21  0:04 ` [PATCH 08/21 v2] drm/i915: Add helper function to update scaler_users in crtc_state Chandra Konduru
2015-03-25  5:15   ` Matt Roper
2015-03-25 19:20     ` Konduru, Chandra
2015-03-25 20:58       ` Matt Roper
2015-03-25 22:02         ` Konduru, Chandra
2015-03-25 23:21   ` [PATCH 08/21 v3] " Chandra Konduru
2015-03-21  0:04 ` [PATCH 09/21 v2] drm/i915: Add atomic function to setup scalers scalers for a crtc Chandra Konduru
2015-03-25  5:15   ` Matt Roper
2015-03-25 19:46     ` Konduru, Chandra
2015-03-25 23:21   ` [PATCH 09/21 v3] " Chandra Konduru
2015-03-21  0:04 ` [PATCH 10/21 v2] drm/i915: Helper function to detach a scaler from a plane or crtc Chandra Konduru
2015-03-25  5:15   ` Matt Roper
2015-03-25 20:14     ` Konduru, Chandra
2015-03-25 21:13       ` Matt Roper
2015-03-25 21:28         ` Konduru, Chandra
2015-03-28  0:21           ` Matt Roper
2015-03-30 19:06             ` Konduru, Chandra
2015-03-25 23:21   ` [PATCH 10/21 v3] " Chandra Konduru
2015-03-21  0:04 ` [PATCH 11/21 v2] drm/i915: Ensure planes begin with no scaler Chandra Konduru
2015-03-25  5:17   ` Matt Roper
2015-03-21  0:04 ` [PATCH 12/21 v2] drm/i915: Ensure colorkey and scaling aren't enabled at same time Chandra Konduru
2015-03-25 17:21   ` Matt Roper
2015-03-25 17:29     ` Konduru, Chandra
2015-03-21  0:04 ` [PATCH 13/21 v2] drm/i915: Preserve scaler state when clearing crtc_state Chandra Konduru
2015-03-21  0:04 ` [PATCH 14/21 v2] drm/i915: use current scaler state during readout_hw_state Chandra Konduru
2015-03-21  0:04 ` [PATCH 15/21 v2] drm/i915: Update scaling ratio as part of crtc_compute_config Chandra Konduru
2015-03-21  0:04 ` [PATCH 16/21 v2] drm/i915: Ensure setting up scalers into staged crtc_state Chandra Konduru
2015-03-25 17:21   ` Matt Roper
2015-03-25 17:26     ` Konduru, Chandra
2015-03-21  0:04 ` [PATCH 17/21 v2] drm/i915: copy staged scaler state from drm state to crtc->config Chandra Konduru
2015-03-21  0:04 ` [PATCH 18/21 v2] drm/i915: stage panel fitting scaler request for fixed mode panel Chandra Konduru
2015-03-21  0:04 ` [PATCH 19/21 v2] drm/i915: Enable skylake panel fitting using skylake shared scalers Chandra Konduru
2015-03-21  0:04 ` [PATCH 20/21 v2] drm/i915: Enable skylake primary plane scaling using " Chandra Konduru
2015-03-21  0:04 ` [PATCH 21/21 v2] drm/i915: Enable skylake sprite " Chandra Konduru
2015-03-25 21:29   ` Matt Roper
2015-03-25 21:55     ` Konduru, Chandra

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.