linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/6] Added scaler support for komeda
@ 2019-05-23 11:09 james qian wang (Arm Technology China)
  2019-05-23 11:09 ` [PATCH v2 1/6] drm/komeda: Attach scaler to drm as private object james qian wang (Arm Technology China)
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:09 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

This patch series added scaling and image enhancement support for komeda
driver.
Enabled two different scaling usage:
- layer scaling: scaling a input image before composite it with others
- write-back scaling: scaling the composition result and write it to memory

This patchset depends on:
- https://patchwork.freedesktop.org/series/59915/
- https://patchwork.freedesktop.org/series/59000/
- https://patchwork.freedesktop.org/series/59000/

v2:
- Rebase and correct typos
- Rename "needs_scaling" to "en_scaling"
- Rename "needs_img_enhancement" to "en_img_enhancement"

james qian wang (Arm Technology China) (6):
  drm/komeda: Attach scaler to drm as private object
  drm/komeda: Add the initial scaler support for CORE
  drm/komeda: Implement D71 scaler support
  drm/komeda: Add writeback scaling support
  drm/komeda: Add engine clock requirement check for the downscaling
  drm/komeda: Add image enhancement support

 .../arm/display/komeda/d71/d71_component.c    | 177 +++++++++++++++++-
 .../gpu/drm/arm/display/komeda/d71/d71_dev.c  |   2 +-
 .../gpu/drm/arm/display/komeda/d71/d71_dev.h  |   2 +
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  |  66 ++++++-
 .../gpu/drm/arm/display/komeda/komeda_kms.h   |  14 +-
 .../drm/arm/display/komeda/komeda_pipeline.c  |  14 ++
 .../drm/arm/display/komeda/komeda_pipeline.h  |  32 +++-
 .../display/komeda/komeda_pipeline_state.c    | 165 +++++++++++++++-
 .../gpu/drm/arm/display/komeda/komeda_plane.c |  75 +++++++-
 .../arm/display/komeda/komeda_private_obj.c   |  49 +++++
 .../arm/display/komeda/komeda_wb_connector.c  |   2 +
 11 files changed, 583 insertions(+), 15 deletions(-)

-- 
2.17.1


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

* [PATCH v2 1/6] drm/komeda: Attach scaler to drm as private object
  2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
@ 2019-05-23 11:09 ` james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 2/6] drm/komeda: Add the initial scaler support for CORE james qian wang (Arm Technology China)
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:09 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

According to the komeda pipeline configuration, attach scaler to drm as
private object.

v2: Rebase

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../arm/display/komeda/komeda_private_obj.c   | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
index d53bd6c23c5d..bac90ab8fdc9 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_private_obj.c
@@ -60,6 +60,49 @@ static int komeda_layer_obj_add(struct komeda_kms_dev *kms,
 	return 0;
 }
 
+static struct drm_private_state *
+komeda_scaler_atomic_duplicate_state(struct drm_private_obj *obj)
+{
+	struct komeda_scaler_state *st;
+
+	st = kmemdup(obj->state, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return NULL;
+
+	komeda_component_state_reset(&st->base);
+	__drm_atomic_helper_private_obj_duplicate_state(obj, &st->base.obj);
+
+	return &st->base.obj;
+}
+
+static void
+komeda_scaler_atomic_destroy_state(struct drm_private_obj *obj,
+				   struct drm_private_state *state)
+{
+	kfree(to_scaler_st(priv_to_comp_st(state)));
+}
+
+static const struct drm_private_state_funcs komeda_scaler_obj_funcs = {
+	.atomic_duplicate_state	= komeda_scaler_atomic_duplicate_state,
+	.atomic_destroy_state	= komeda_scaler_atomic_destroy_state,
+};
+
+static int komeda_scaler_obj_add(struct komeda_kms_dev *kms,
+				 struct komeda_scaler *scaler)
+{
+	struct komeda_scaler_state *st;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->base.component = &scaler->base;
+	drm_atomic_private_obj_init(&kms->base,
+				    &scaler->base.obj, &st->base.obj,
+				    &komeda_scaler_obj_funcs);
+	return 0;
+}
+
 static struct drm_private_state *
 komeda_compiz_atomic_duplicate_state(struct drm_private_obj *obj)
 {
@@ -258,6 +301,12 @@ int komeda_kms_add_private_objs(struct komeda_kms_dev *kms,
 				return err;
 		}
 
+		for (j = 0; j < pipe->n_scalers; j++) {
+			err = komeda_scaler_obj_add(kms, pipe->scalers[j]);
+			if (err)
+				return err;
+		}
+
 		err = komeda_compiz_obj_add(kms, pipe->compiz);
 		if (err)
 			return err;
-- 
2.17.1


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

* [PATCH v2 2/6] drm/komeda: Add the initial scaler support for CORE
  2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
  2019-05-23 11:09 ` [PATCH v2 1/6] drm/komeda: Attach scaler to drm as private object james qian wang (Arm Technology China)
@ 2019-05-23 11:10 ` james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 3/6] drm/komeda: Implement D71 scaler support james qian wang (Arm Technology China)
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:10 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

This patch add the initial and necessary logic for CORE to support scaler:
- Complete the struct komeda_scaler and komeda_scaler_state for adding
  the scaler specific features and capablities.
- Implement komeda_scaler_validate to check the scaler with the data flow
  configurations.
- Enable scaling support for plane input path (layer input data flow).

v2: Fix a typo, and rename "needs_scaling" to "en_scaling"

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../drm/arm/display/komeda/komeda_pipeline.c  |  14 +++
 .../drm/arm/display/komeda/komeda_pipeline.h  |  20 ++-
 .../display/komeda/komeda_pipeline_state.c    | 116 ++++++++++++++++++
 .../gpu/drm/arm/display/komeda/komeda_plane.c |   8 ++
 4 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
index a130b62fa6d1..96248586b4e8 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c
@@ -126,6 +126,20 @@ komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id)
 	return c;
 }
 
+struct komeda_component *
+komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
+				    u32 comp_mask)
+{
+	struct komeda_component *c = NULL;
+	int id;
+
+	id = find_first_bit((unsigned long *)&comp_mask, 32);
+	if (id < 32)
+		c = komeda_pipeline_get_component(pipe, id);
+
+	return c;
+}
+
 /** komeda_component_add - Add a component to &komeda_pipeline */
 struct komeda_component *
 komeda_component_add(struct komeda_pipeline *pipe,
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index fdde93bad8de..400af217ed86 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -244,11 +244,17 @@ struct komeda_layer_state {
 
 struct komeda_scaler {
 	struct komeda_component base;
-	/* scaler features and caps */
+	struct malidp_range hsize, vsize;
+	u32 max_upscaling;
+	u32 max_downscaling;
 };
 
 struct komeda_scaler_state {
 	struct komeda_component_state base;
+	u16 hsize_in, vsize_in;
+	u16 hsize_out, vsize_out;
+	u8 en_scaling : 1,
+	   en_alpha : 1; /* enable alpha processing */
 };
 
 struct komeda_compiz {
@@ -307,6 +313,7 @@ struct komeda_data_flow_cfg {
 	u32 rot;
 	int blending_zorder;
 	u8 pixel_blend_mode, layer_alpha;
+	u8 en_scaling : 1;
 };
 
 /** struct komeda_pipeline_funcs */
@@ -407,6 +414,9 @@ void komeda_pipeline_destroy(struct komeda_dev *mdev,
 int komeda_assemble_pipelines(struct komeda_dev *mdev);
 struct komeda_component *
 komeda_pipeline_get_component(struct komeda_pipeline *pipe, int id);
+struct komeda_component *
+komeda_pipeline_get_first_component(struct komeda_pipeline *pipe,
+				    u32 comp_mask);
 
 void komeda_pipeline_dump_register(struct komeda_pipeline *pipe,
 				   struct seq_file *sf);
@@ -423,6 +433,14 @@ komeda_component_add(struct komeda_pipeline *pipe,
 void komeda_component_destroy(struct komeda_dev *mdev,
 			      struct komeda_component *c);
 
+static inline struct komeda_component *
+komeda_component_pickup_output(struct komeda_component *c, u32 avail_comps)
+{
+	u32 avail_inputs = c->supported_outputs & (avail_comps);
+
+	return komeda_pipeline_get_first_component(c->pipeline, avail_inputs);
+}
+
 struct komeda_plane_state;
 struct komeda_crtc_state;
 struct komeda_crtc;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
index db2c3d6d2a8a..a5300ef92eb7 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -249,6 +249,26 @@ komeda_component_validate_private(struct komeda_component *c,
 	return err;
 }
 
+/* Get current available scaler from the component->supported_outputs */
+static struct komeda_scaler *
+komeda_component_get_avail_scaler(struct komeda_component *c,
+				  struct drm_atomic_state *state)
+{
+	struct komeda_pipeline_state *pipe_st;
+	u32 avail_scalers;
+
+	pipe_st = komeda_pipeline_get_state(c->pipeline, state);
+	if (!pipe_st)
+		return NULL;
+
+	avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
+			KOMEDA_PIPELINE_SCALERS;
+
+	c = komeda_component_pickup_output(c, avail_scalers);
+
+	return to_scaler(c);
+}
+
 static int
 komeda_layer_check_cfg(struct komeda_layer *layer,
 		       struct komeda_plane_state *kplane_st,
@@ -355,6 +375,98 @@ komeda_wb_layer_validate(struct komeda_layer *wb_layer,
 	return 0;
 }
 
+static bool scaling_ratio_valid(u32 size_in, u32 size_out,
+				u32 max_upscaling, u32 max_downscaling)
+{
+	if (size_out > size_in * max_upscaling)
+		return false;
+	else if (size_in > size_out * max_downscaling)
+		return false;
+	return true;
+}
+
+static int
+komeda_scaler_check_cfg(struct komeda_scaler *scaler,
+			struct komeda_data_flow_cfg *dflow)
+{
+	u32 hsize_in, vsize_in, hsize_out, vsize_out;
+
+	hsize_in = dflow->in_w;
+	vsize_in = dflow->in_h;
+	hsize_out = dflow->out_w;
+	vsize_out = dflow->out_h;
+
+	if (!in_range(&scaler->hsize, hsize_in) ||
+	    !in_range(&scaler->hsize, hsize_out)) {
+		DRM_DEBUG_ATOMIC("Invalid horizontal sizes");
+		return -EINVAL;
+	}
+
+	if (!in_range(&scaler->vsize, vsize_in) ||
+	    !in_range(&scaler->vsize, vsize_out)) {
+		DRM_DEBUG_ATOMIC("Invalid vertical sizes");
+		return -EINVAL;
+	}
+
+	if (!scaling_ratio_valid(hsize_in, hsize_out, scaler->max_upscaling,
+				 scaler->max_downscaling)) {
+		DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
+		return -EINVAL;
+	}
+
+	if (!scaling_ratio_valid(vsize_in, vsize_out, scaler->max_upscaling,
+				 scaler->max_downscaling)) {
+		DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int
+komeda_scaler_validate(void *user,
+		       struct komeda_crtc_state *kcrtc_st,
+		       struct komeda_data_flow_cfg *dflow)
+{
+	struct drm_atomic_state *drm_st = kcrtc_st->base.state;
+	struct komeda_component_state *c_st;
+	struct komeda_scaler_state *st;
+	struct komeda_scaler *scaler;
+	int err = 0;
+
+	if (!dflow->en_scaling)
+		return 0;
+
+	scaler = komeda_component_get_avail_scaler(dflow->input.component,
+						   drm_st);
+	if (!scaler) {
+		DRM_DEBUG_ATOMIC("No scaler available");
+		return -EINVAL;
+	}
+
+	err = komeda_scaler_check_cfg(scaler, dflow);
+	if (err)
+		return err;
+
+	c_st = komeda_component_get_state_and_set_user(&scaler->base,
+			drm_st, user, kcrtc_st->base.crtc);
+	if (IS_ERR(c_st))
+		return PTR_ERR(c_st);
+
+	st = to_scaler_st(c_st);
+
+	st->hsize_in = dflow->in_w;
+	st->vsize_in = dflow->in_h;
+	st->hsize_out = dflow->out_w;
+	st->vsize_out = dflow->out_h;
+	st->en_scaling = dflow->en_scaling;
+	/* Enable alpha processing if the next stage needs the pixel alpha */
+	st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
+
+	komeda_component_add_input(&st->base, &dflow->input, 0);
+	komeda_component_set_output(&dflow->input, &scaler->base, 0);
+	return err;
+}
+
 void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
 			       u16 *hsize, u16 *vsize)
 {
@@ -520,6 +632,10 @@ int komeda_build_layer_data_flow(struct komeda_layer *layer,
 	if (err)
 		return err;
 
+	err = komeda_scaler_validate(plane, kcrtc_st, dflow);
+	if (err)
+		return err;
+
 	err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
 
 	return err;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index 6462c0206942..cd3a7172a756 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -16,6 +16,7 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 			    struct komeda_data_flow_cfg *dflow)
 {
 	struct drm_framebuffer *fb = st->fb;
+	u32 w, h;
 
 	memset(dflow, 0, sizeof(*dflow));
 
@@ -36,6 +37,13 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 	dflow->in_w = st->src_w >> 16;
 	dflow->in_h = st->src_h >> 16;
 
+	w = dflow->in_w;
+	h = dflow->in_h;
+	if (drm_rotation_90_or_270(dflow->rot))
+		swap(w, h);
+
+	dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
+
 	return 0;
 }
 
-- 
2.17.1


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

* [PATCH v2 3/6] drm/komeda: Implement D71 scaler support
  2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
  2019-05-23 11:09 ` [PATCH v2 1/6] drm/komeda: Attach scaler to drm as private object james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 2/6] drm/komeda: Add the initial scaler support for CORE james qian wang (Arm Technology China)
@ 2019-05-23 11:10 ` james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 4/6] drm/komeda: Add writeback scaling support james qian wang (Arm Technology China)
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:10 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

1. Add scaler component and initialize it according to D71 HW.
2. Implement d71_scaler_update/disable/dump

v2:
- Correct a typo
- Constify component_funcs: d71_scaler_funcs

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    | 131 +++++++++++++++++-
 1 file changed, 130 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 5c9bc859f886..0bf5c7baedb5 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -551,6 +551,132 @@ static int d71_compiz_init(struct d71_dev *d71,
 	return 0;
 }
 
+static void d71_scaler_update_filter_lut(u32 __iomem *reg, u32 hsize_in,
+					 u32 vsize_in, u32 hsize_out,
+					 u32 vsize_out)
+{
+	u32 val = 0;
+
+	if (hsize_in <= hsize_out)
+		val  |= 0x62;
+	else if (hsize_in <= (hsize_out + hsize_out / 2))
+		val |= 0x63;
+	else if (hsize_in <= hsize_out * 2)
+		val |= 0x64;
+	else if (hsize_in <= hsize_out * 2 + (hsize_out * 3) / 4)
+		val |= 0x65;
+	else
+		val |= 0x66;
+
+	if (vsize_in <= vsize_out)
+		val  |= SC_VTSEL(0x6A);
+	else if (vsize_in <= (vsize_out + vsize_out / 2))
+		val |= SC_VTSEL(0x6B);
+	else if (vsize_in <= vsize_out * 2)
+		val |= SC_VTSEL(0x6C);
+	else if (vsize_in <= vsize_out * 2 + vsize_out * 3 / 4)
+		val |= SC_VTSEL(0x6D);
+	else
+		val |= SC_VTSEL(0x6E);
+
+	malidp_write32(reg, SC_COEFFTAB, val);
+}
+
+static void d71_scaler_update(struct komeda_component *c,
+			      struct komeda_component_state *state)
+{
+	struct komeda_scaler_state *st = to_scaler_st(state);
+	u32 __iomem *reg = c->reg;
+	u32 init_ph, delta_ph, ctrl;
+
+	d71_scaler_update_filter_lut(reg, st->hsize_in, st->vsize_in,
+				     st->hsize_out, st->vsize_out);
+
+	malidp_write32(reg, BLK_IN_SIZE, HV_SIZE(st->hsize_in, st->vsize_in));
+	malidp_write32(reg, SC_OUT_SIZE, HV_SIZE(st->hsize_out, st->vsize_out));
+
+	init_ph = (st->hsize_in << 15) / st->hsize_out;
+	malidp_write32(reg, SC_H_INIT_PH, init_ph);
+
+	delta_ph = (st->hsize_in << 16) / st->hsize_out;
+	malidp_write32(reg, SC_H_DELTA_PH, delta_ph);
+
+	init_ph = (st->vsize_in << 15) / st->vsize_out;
+	malidp_write32(reg, SC_V_INIT_PH, init_ph);
+
+	delta_ph = (st->vsize_in << 16) / st->vsize_out;
+	malidp_write32(reg, SC_V_DELTA_PH, delta_ph);
+
+	ctrl = 0;
+	ctrl |= st->en_scaling ? SC_CTRL_SCL : 0;
+	ctrl |= st->en_alpha ? SC_CTRL_AP : 0;
+
+	malidp_write32(reg, BLK_CONTROL, ctrl);
+	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0]));
+}
+
+static void d71_scaler_dump(struct komeda_component *c, struct seq_file *sf)
+{
+	u32 v[9];
+
+	dump_block_header(sf, c->reg);
+
+	get_values_from_reg(c->reg, 0x80, 1, v);
+	seq_printf(sf, "SC_INPUT_ID0:\t\t0x%X\n", v[0]);
+
+	get_values_from_reg(c->reg, 0xD0, 1, v);
+	seq_printf(sf, "SC_CONTROL:\t\t0x%X\n", v[0]);
+
+	get_values_from_reg(c->reg, 0xDC, 9, v);
+	seq_printf(sf, "SC_COEFFTAB:\t\t0x%X\n", v[0]);
+	seq_printf(sf, "SC_IN_SIZE:\t\t0x%X\n", v[1]);
+	seq_printf(sf, "SC_OUT_SIZE:\t\t0x%X\n", v[2]);
+	seq_printf(sf, "SC_H_CROP:\t\t0x%X\n", v[3]);
+	seq_printf(sf, "SC_V_CROP:\t\t0x%X\n", v[4]);
+	seq_printf(sf, "SC_H_INIT_PH:\t\t0x%X\n", v[5]);
+	seq_printf(sf, "SC_H_DELTA_PH:\t\t0x%X\n", v[6]);
+	seq_printf(sf, "SC_V_INIT_PH:\t\t0x%X\n", v[7]);
+	seq_printf(sf, "SC_V_DELTA_PH:\t\t0x%X\n", v[8]);
+}
+
+static const struct komeda_component_funcs d71_scaler_funcs = {
+	.update		= d71_scaler_update,
+	.disable	= d71_component_disable,
+	.dump_register	= d71_scaler_dump,
+};
+
+static int d71_scaler_init(struct d71_dev *d71,
+			   struct block_header *blk, u32 __iomem *reg)
+{
+	struct komeda_component *c;
+	struct komeda_scaler *scaler;
+	u32 pipe_id, comp_id;
+
+	get_resources_id(blk->block_info, &pipe_id, &comp_id);
+
+	c = komeda_component_add(&d71->pipes[pipe_id]->base, sizeof(*scaler),
+				 comp_id, BLOCK_INFO_INPUT_ID(blk->block_info),
+				 &d71_scaler_funcs,
+				 1, get_valid_inputs(blk), 1, reg,
+				 "CU%d_SCALER%d",
+				 pipe_id, BLOCK_INFO_BLK_ID(blk->block_info));
+
+	if (IS_ERR(c)) {
+		DRM_ERROR("Failed to initialize scaler");
+		return PTR_ERR(c);
+	}
+
+	scaler = to_scaler(c);
+	set_range(&scaler->hsize, 4, d71->max_line_size);
+	set_range(&scaler->vsize, 4, 4096);
+	scaler->max_downscaling = 6;
+	scaler->max_upscaling = 64;
+
+	malidp_write32(c->reg, BLK_CONTROL, 0);
+
+	return 0;
+}
+
 static void d71_improc_update(struct komeda_component *c,
 			      struct komeda_component_state *state)
 {
@@ -771,8 +897,11 @@ int d71_probe_block(struct d71_dev *d71,
 		err = d71_compiz_init(d71, blk, reg);
 		break;
 
-	case D71_BLK_TYPE_CU_SPLITTER:
 	case D71_BLK_TYPE_CU_SCALER:
+		err = d71_scaler_init(d71, blk, reg);
+		break;
+
+	case D71_BLK_TYPE_CU_SPLITTER:
 	case D71_BLK_TYPE_CU_MERGER:
 		break;
 
-- 
2.17.1


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

* [PATCH v2 4/6] drm/komeda: Add writeback scaling support
  2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
                   ` (2 preceding siblings ...)
  2019-05-23 11:10 ` [PATCH v2 3/6] drm/komeda: Implement D71 scaler support james qian wang (Arm Technology China)
@ 2019-05-23 11:10 ` james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 5/6] drm/komeda: Add engine clock requirement check for the downscaling james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 6/6] drm/komeda: Add image enhancement support james qian wang (Arm Technology China)
  5 siblings, 0 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:10 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

1. Add scaler to writeback pipeline to enable the writeback scaling support
2. Display HW can not do upscaling for writeback, check it when validate.

v2: Rebase

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../drm/arm/display/komeda/komeda_pipeline.h  |  2 ++
 .../display/komeda/komeda_pipeline_state.c    | 36 +++++++++++++++----
 .../gpu/drm/arm/display/komeda/komeda_plane.c |  8 +----
 .../arm/display/komeda/komeda_wb_connector.c  |  2 ++
 4 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 400af217ed86..9ffe11c9f386 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -470,4 +470,6 @@ void komeda_pipeline_disable(struct komeda_pipeline *pipe,
 void komeda_pipeline_update(struct komeda_pipeline *pipe,
 			    struct drm_atomic_state *old_state);
 
+void komeda_complete_data_flow_cfg(struct komeda_data_flow_cfg *dflow);
+
 #endif /* _KOMEDA_PIPELINE_H_*/
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
index a5300ef92eb7..9f07ef65008f 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -390,6 +390,7 @@ komeda_scaler_check_cfg(struct komeda_scaler *scaler,
 			struct komeda_data_flow_cfg *dflow)
 {
 	u32 hsize_in, vsize_in, hsize_out, vsize_out;
+	u32 max_upscaling;
 
 	hsize_in = dflow->in_w;
 	vsize_in = dflow->in_h;
@@ -408,13 +409,21 @@ komeda_scaler_check_cfg(struct komeda_scaler *scaler,
 		return -EINVAL;
 	}
 
-	if (!scaling_ratio_valid(hsize_in, hsize_out, scaler->max_upscaling,
+	/* If input comes from compiz that means the scaling is for writeback
+	 * and scaler can not do upscaling for writeback
+	 */
+	if (has_bit(dflow->input.component->id, KOMEDA_PIPELINE_COMPIZS))
+		max_upscaling = 1;
+	else
+		max_upscaling = scaler->max_upscaling;
+
+	if (!scaling_ratio_valid(hsize_in, hsize_out, max_upscaling,
 				 scaler->max_downscaling)) {
 		DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
 		return -EINVAL;
 	}
 
-	if (!scaling_ratio_valid(vsize_in, vsize_out, scaler->max_upscaling,
+	if (!scaling_ratio_valid(vsize_in, vsize_out, max_upscaling,
 				 scaler->max_downscaling)) {
 		DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
 		return -EINVAL;
@@ -614,6 +623,17 @@ komeda_timing_ctrlr_validate(struct komeda_timing_ctrlr *ctrlr,
 	return 0;
 }
 
+void komeda_complete_data_flow_cfg(struct komeda_data_flow_cfg *dflow)
+{
+	u32 w = dflow->in_w;
+	u32 h = dflow->in_h;
+
+	if (drm_rotation_90_or_270(dflow->rot))
+		swap(w, h);
+
+	dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
+}
+
 int komeda_build_layer_data_flow(struct komeda_layer *layer,
 				 struct komeda_plane_state *kplane_st,
 				 struct komeda_crtc_state *kcrtc_st,
@@ -641,16 +661,18 @@ int komeda_build_layer_data_flow(struct komeda_layer *layer,
 	return err;
 }
 
+/* writeback data path: compiz -> scaler -> wb_layer -> memory */
 int komeda_build_wb_data_flow(struct komeda_layer *wb_layer,
 			      struct drm_connector_state *conn_st,
 			      struct komeda_crtc_state *kcrtc_st,
 			      struct komeda_data_flow_cfg *dflow)
 {
-	if ((dflow->in_w != dflow->out_w) ||
-	    (dflow->in_h != dflow->out_h)) {
-		DRM_DEBUG_ATOMIC("current do not support scaling writeback.\n");
-		return -EINVAL;
-	}
+	struct drm_connector *conn = conn_st->connector;
+	int err;
+
+	err = komeda_scaler_validate(conn, kcrtc_st, dflow);
+	if (err)
+		return err;
 
 	return komeda_wb_layer_validate(wb_layer, conn_st, dflow);
 }
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index cd3a7172a756..97d8adb6cd2b 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -16,7 +16,6 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 			    struct komeda_data_flow_cfg *dflow)
 {
 	struct drm_framebuffer *fb = st->fb;
-	u32 w, h;
 
 	memset(dflow, 0, sizeof(*dflow));
 
@@ -37,12 +36,7 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 	dflow->in_w = st->src_w >> 16;
 	dflow->in_h = st->src_h >> 16;
 
-	w = dflow->in_w;
-	h = dflow->in_h;
-	if (drm_rotation_90_or_270(dflow->rot))
-		swap(w, h);
-
-	dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
+	komeda_complete_data_flow_cfg(dflow);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
index 0c1a4220c280..eed521218ef3 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -31,6 +31,8 @@ komeda_wb_init_data_flow(struct komeda_layer *wb_layer,
 	dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
 	dflow->rot = DRM_MODE_ROTATE_0;
 
+	komeda_complete_data_flow_cfg(dflow);
+
 	return 0;
 }
 
-- 
2.17.1


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

* [PATCH v2 5/6] drm/komeda: Add engine clock requirement check for the downscaling
  2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
                   ` (3 preceding siblings ...)
  2019-05-23 11:10 ` [PATCH v2 4/6] drm/komeda: Add writeback scaling support james qian wang (Arm Technology China)
@ 2019-05-23 11:10 ` james qian wang (Arm Technology China)
  2019-05-23 11:10 ` [PATCH v2 6/6] drm/komeda: Add image enhancement support james qian wang (Arm Technology China)
  5 siblings, 0 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:10 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

For downscaling there is a restriction, the downscaling needed engine
clock can not acceed the real engine clock, and the clock requirement
mostly depend on the specific HW, to solve this problem:
1. Add a pipeline func - downscaling_clk_check for CORE to query the real
   HW if downscaling can be supported.
2. Add new property clock ratio which is the ratio of:
     (mclk << 32) / pxlclk
   then User driver can use this ratio to do the clock check to avoid post
   an invalid downscaling to kernel.

v2: Rebase and Delete debug print

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    | 45 +++++++++++++
 .../gpu/drm/arm/display/komeda/d71/d71_dev.c  |  2 +-
 .../gpu/drm/arm/display/komeda/d71/d71_dev.h  |  2 +
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  | 66 ++++++++++++++++++-
 .../gpu/drm/arm/display/komeda/komeda_kms.h   |  8 +++
 .../drm/arm/display/komeda/komeda_pipeline.h  |  8 ++-
 .../display/komeda/komeda_pipeline_state.c    | 17 ++++-
 7 files changed, 142 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 0bf5c7baedb5..2ea282c6a156 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -677,6 +677,47 @@ static int d71_scaler_init(struct d71_dev *d71,
 	return 0;
 }
 
+static int d71_downscaling_clk_check(struct komeda_pipeline *pipe,
+				     struct drm_display_mode *mode,
+				     unsigned long mclk_rate,
+				     struct komeda_data_flow_cfg *dflow)
+{
+	u32 h_in = dflow->in_w;
+	u32 v_in = dflow->in_h;
+	u32 v_out = dflow->out_h;
+	u64 fraction, denominator;
+
+	/* D71 downscaling must satisfy the following equation
+	 *
+	 *   MCLK                   h_in * v_in
+	 * ------- >= ---------------------------------------------
+	 *  PXLCLK     (h_total - (1 + 2 * v_in / v_out)) * v_out
+	 *
+	 * In only horizontal downscaling situation, the right side should be
+	 * multiplied by (h_total - 3) / (h_active - 3), then equation becomes
+	 *
+	 *   MCLK          h_in
+	 * ------- >= ----------------
+	 *  PXLCLK     (h_active - 3)
+	 *
+	 * To avoid precision lost the equation 1 will be convert to:
+	 *
+	 *   MCLK             h_in * v_in
+	 * ------- >= -----------------------------------
+	 *  PXLCLK     (h_total -1 ) * v_out -  2 * v_in
+	 */
+	if (v_in == v_out) {
+		fraction = h_in;
+		denominator = mode->hdisplay - 3;
+	} else {
+		fraction = h_in * v_in;
+		denominator = (mode->htotal - 1) * v_out -  2 * v_in;
+	}
+
+	return mclk_rate * denominator >= mode->clock * 1000 * fraction ?
+	       0 : -EINVAL;
+}
+
 static void d71_improc_update(struct komeda_component *c,
 			      struct komeda_component_state *state)
 {
@@ -939,3 +980,7 @@ int d71_probe_block(struct d71_dev *d71,
 
 	return err;
 }
+
+const struct komeda_pipeline_funcs d71_pipeline_funcs = {
+	.downscaling_clk_check = d71_downscaling_clk_check,
+};
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
index 3a7248d42376..1c914f8ca016 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.c
@@ -390,7 +390,7 @@ static int d71_enum_resources(struct komeda_dev *mdev)
 
 	for (i = 0; i < d71->num_pipelines; i++) {
 		pipe = komeda_pipeline_add(mdev, sizeof(struct d71_pipeline),
-					   NULL);
+					   &d71_pipeline_funcs);
 		if (IS_ERR(pipe)) {
 			err = PTR_ERR(pipe);
 			goto err_cleanup;
diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.h b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.h
index 7465c57d9774..84f1878b647d 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.h
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_dev.h
@@ -43,6 +43,8 @@ struct d71_dev {
 
 #define to_d71_pipeline(x)	container_of(x, struct d71_pipeline, base)
 
+extern const struct komeda_pipeline_funcs d71_pipeline_funcs;
+
 int d71_probe_block(struct d71_dev *d71,
 		    struct block_header *blk, u32 __iomem *reg);
 void d71_read_block_header(u32 __iomem *reg, struct block_header *blk);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index 6712603b8c7a..24a961356cb3 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -18,6 +18,22 @@
 #include "komeda_dev.h"
 #include "komeda_kms.h"
 
+static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st)
+{
+	u64 pxlclk, mclk;
+
+	if (!kcrtc_st->base.active) {
+		kcrtc_st->clock_ratio = 0;
+		return;
+	}
+
+	pxlclk = kcrtc_st->base.adjusted_mode.clock * 1000;
+	mclk = komeda_calc_mclk(kcrtc_st) << 32;
+
+	do_div(mclk, pxlclk);
+	kcrtc_st->clock_ratio = mclk;
+}
+
 /**
  * komeda_crtc_atomic_check - build display output data flow
  * @crtc: DRM crtc
@@ -38,6 +54,9 @@ komeda_crtc_atomic_check(struct drm_crtc *crtc,
 	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(state);
 	int err;
 
+	if (drm_atomic_crtc_needs_modeset(state))
+		komeda_crtc_update_clock_ratio(kcrtc_st);
+
 	if (state->active) {
 		err = komeda_build_display_data_flow(kcrtc, kcrtc_st);
 		if (err)
@@ -52,11 +71,12 @@ komeda_crtc_atomic_check(struct drm_crtc *crtc,
 	return 0;
 }
 
-static u32 komeda_calc_mclk(struct komeda_crtc_state *kcrtc_st)
+unsigned long komeda_calc_mclk(struct komeda_crtc_state *kcrtc_st)
 {
-	unsigned long mclk = kcrtc_st->base.adjusted_mode.clock * 1000;
+	struct komeda_dev *mdev = kcrtc_st->base.crtc->dev->dev_private;
+	unsigned long pxlclk = kcrtc_st->base.adjusted_mode.clock;
 
-	return mclk;
+	return clk_round_rate(mdev->mclk, pxlclk * 1000);
 }
 
 /* For active a crtc, mainly need two parts of preparation
@@ -404,6 +424,7 @@ komeda_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
 	__drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
 
 	new->affected_pipes = old->active_pipes;
+	new->clock_ratio = old->clock_ratio;
 
 	return &new->base;
 }
@@ -432,6 +453,24 @@ static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
 	mdev->funcs->on_off_vblank(mdev, kcrtc->master->id, false);
 }
 
+static int
+komeda_crtc_atomic_get_property(struct drm_crtc *crtc,
+				const struct drm_crtc_state *state,
+				struct drm_property *property, uint64_t *val)
+{
+	struct komeda_crtc *kcrtc = to_kcrtc(crtc);
+	struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(state);
+
+	if (property == kcrtc->clock_ratio_property) {
+		*val = kcrtc_st->clock_ratio;
+	} else {
+		DRM_DEBUG_DRIVER("Unknown property %s\n", property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static const struct drm_crtc_funcs komeda_crtc_funcs = {
 	.gamma_set		= drm_atomic_helper_legacy_gamma_set,
 	.destroy		= drm_crtc_cleanup,
@@ -442,6 +481,7 @@ static const struct drm_crtc_funcs komeda_crtc_funcs = {
 	.atomic_destroy_state	= komeda_crtc_atomic_destroy_state,
 	.enable_vblank		= komeda_crtc_vblank_enable,
 	.disable_vblank		= komeda_crtc_vblank_disable,
+	.atomic_get_property	= komeda_crtc_atomic_get_property,
 };
 
 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
@@ -477,6 +517,22 @@ int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms,
 	return 0;
 }
 
+static int komeda_crtc_create_clock_ratio_property(struct komeda_crtc *kcrtc)
+{
+	struct drm_crtc *crtc = &kcrtc->base;
+	struct drm_property *prop;
+
+	prop = drm_property_create_range(crtc->dev, DRM_MODE_PROP_ATOMIC,
+					 "CLOCK_RATIO", 0, U64_MAX);
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&crtc->base, prop, 0);
+	kcrtc->clock_ratio_property = prop;
+
+	return 0;
+}
+
 static struct drm_plane *
 get_crtc_primary(struct komeda_kms_dev *kms, struct komeda_crtc *crtc)
 {
@@ -513,6 +569,10 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
 
 	crtc->port = kcrtc->master->of_output_port;
 
+	err = komeda_crtc_create_clock_ratio_property(kcrtc);
+	if (err)
+		return err;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index f16e9e577593..db59a9042beb 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -79,6 +79,9 @@ struct komeda_crtc {
 
 	/** @disable_done: this flip_done is for tracing the disable */
 	struct completion *disable_done;
+
+	/** @clock_ratio_property: property for ratio of (mclk << 32)/pxlclk */
+	struct drm_property *clock_ratio_property;
 };
 
 /**
@@ -101,6 +104,9 @@ struct komeda_crtc_state {
 	 * the active pipelines in once display instance
 	 */
 	u32 active_pipes;
+
+	/** @clock_ratio: ratio of (mclk << 32)/pxlclk */
+	u64 clock_ratio;
 };
 
 /** struct komeda_kms_dev - for gather KMS related things */
@@ -142,6 +148,8 @@ is_only_changed_connector(struct drm_crtc_state *st, struct drm_connector *conn)
 	return BIT(drm_connector_index(conn)) == changed_connectors;
 }
 
+unsigned long komeda_calc_mclk(struct komeda_crtc_state *kcrtc_st);
+
 int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
 
 int komeda_kms_add_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 9ffe11c9f386..d0bf7d5b39a7 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -316,8 +316,14 @@ struct komeda_data_flow_cfg {
 	u8 en_scaling : 1;
 };
 
-/** struct komeda_pipeline_funcs */
 struct komeda_pipeline_funcs {
+	/* check if the mclk (main engine clock) can satisfy the clock
+	 * requirements of the downscaling that specified by dflow
+	 */
+	int (*downscaling_clk_check)(struct komeda_pipeline *pipe,
+				     struct drm_display_mode *mode,
+				     unsigned long mclk_rate,
+				     struct komeda_data_flow_cfg *dflow);
 	/* dump_register: Optional, dump registers to seq_file */
 	void (*dump_register)(struct komeda_pipeline *pipe,
 			      struct seq_file *sf);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
index 9f07ef65008f..01544c274848 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -387,6 +387,7 @@ static bool scaling_ratio_valid(u32 size_in, u32 size_out,
 
 static int
 komeda_scaler_check_cfg(struct komeda_scaler *scaler,
+			struct komeda_crtc_state *kcrtc_st,
 			struct komeda_data_flow_cfg *dflow)
 {
 	u32 hsize_in, vsize_in, hsize_out, vsize_out;
@@ -428,6 +429,20 @@ komeda_scaler_check_cfg(struct komeda_scaler *scaler,
 		DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
 		return -EINVAL;
 	}
+
+	if (hsize_in > hsize_out || vsize_in > vsize_out) {
+		struct komeda_pipeline *pipe = scaler->base.pipeline;
+		int err;
+
+		err = pipe->funcs->downscaling_clk_check(pipe,
+					&kcrtc_st->base.adjusted_mode,
+					komeda_calc_mclk(kcrtc_st), dflow);
+		if (err) {
+			DRM_DEBUG_ATOMIC("mclk can't satisfy the clock requirement of the downscaling\n");
+			return err;
+		}
+	}
+
 	return 0;
 }
 
@@ -452,7 +467,7 @@ komeda_scaler_validate(void *user,
 		return -EINVAL;
 	}
 
-	err = komeda_scaler_check_cfg(scaler, dflow);
+	err = komeda_scaler_check_cfg(scaler, kcrtc_st, dflow);
 	if (err)
 		return err;
 
-- 
2.17.1


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

* [PATCH v2 6/6] drm/komeda: Add image enhancement support
  2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
                   ` (4 preceding siblings ...)
  2019-05-23 11:10 ` [PATCH v2 5/6] drm/komeda: Add engine clock requirement check for the downscaling james qian wang (Arm Technology China)
@ 2019-05-23 11:10 ` james qian wang (Arm Technology China)
  5 siblings, 0 replies; 7+ messages in thread
From: james qian wang (Arm Technology China) @ 2019-05-23 11:10 UTC (permalink / raw)
  To: Liviu Dudau, airlied, Brian Starkey, maarten.lankhorst, sean
  Cc: Jonathan Chai (Arm Technology China),
	Julien Yin (Arm Technology China),
	thomas Sun (Arm Technology China),
	Lowry Li (Arm Technology China),
	Ayan Halder, Tiannan Zhu (Arm Technology China),
	Yiqi Kang (Arm Technology China),
	nd, linux-kernel, dri-devel, Ben Davis,
	Oscar Zhang (Arm Technology China),
	Channing Chen (Arm Technology China),
	james qian wang (Arm Technology China)

Besides scaling, Arm display scaler also can support image enhancement.
For support it, Add a new property "img_enhancement" to plane, then user
can turn on/off it by this property, and kernel follow user's requirement
to maitain the state and enable/disable the real HW image enhancement.

v2: Rebase and rename "needs_img_enhancement" to "en_img_enhancement"

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.wang@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    |  1 +
 .../gpu/drm/arm/display/komeda/komeda_kms.h   |  6 +-
 .../drm/arm/display/komeda/komeda_pipeline.h  |  6 +-
 .../display/komeda/komeda_pipeline_state.c    |  6 +-
 .../gpu/drm/arm/display/komeda/komeda_plane.c | 73 ++++++++++++++++++-
 5 files changed, 85 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
index 2ea282c6a156..1f7a5d572b1a 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -610,6 +610,7 @@ static void d71_scaler_update(struct komeda_component *c,
 	ctrl = 0;
 	ctrl |= st->en_scaling ? SC_CTRL_SCL : 0;
 	ctrl |= st->en_alpha ? SC_CTRL_AP : 0;
+	ctrl |= st->en_img_enhancement ? SC_CTRL_IENH : 0;
 
 	malidp_write32(reg, BLK_CONTROL, ctrl);
 	malidp_write32(reg, BLK_INPUT_ID0, to_d71_input_id(&state->inputs[0]));
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
index db59a9042beb..e6e059f2af52 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h
@@ -32,6 +32,9 @@ struct komeda_plane {
 	 * Layers with same capabilities.
 	 */
 	struct komeda_layer *layer;
+
+	/** @prop_img_enhancement: for on/off image enhancement */
+	struct drm_property *prop_img_enhancement;
 };
 
 /**
@@ -44,7 +47,8 @@ struct komeda_plane_state {
 	/** @base: &drm_plane_state */
 	struct drm_plane_state base;
 
-	/* private properties */
+	/* @img_enhancement: on/off image enhancement */
+	u8 img_enhancement : 1;
 };
 
 /**
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index d0bf7d5b39a7..0e334f1cf18b 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -254,7 +254,8 @@ struct komeda_scaler_state {
 	u16 hsize_in, vsize_in;
 	u16 hsize_out, vsize_out;
 	u8 en_scaling : 1,
-	   en_alpha : 1; /* enable alpha processing */
+	   en_alpha : 1, /* enable alpha processing */
+	   en_img_enhancement : 1;
 };
 
 struct komeda_compiz {
@@ -313,7 +314,8 @@ struct komeda_data_flow_cfg {
 	u32 rot;
 	int blending_zorder;
 	u8 pixel_blend_mode, layer_alpha;
-	u8 en_scaling : 1;
+	u8 en_scaling : 1,
+	   en_img_enhancement : 1;
 };
 
 struct komeda_pipeline_funcs {
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
index 01544c274848..db34ea26760c 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -457,7 +457,7 @@ komeda_scaler_validate(void *user,
 	struct komeda_scaler *scaler;
 	int err = 0;
 
-	if (!dflow->en_scaling)
+	if (!(dflow->en_scaling || dflow->en_img_enhancement))
 		return 0;
 
 	scaler = komeda_component_get_avail_scaler(dflow->input.component,
@@ -482,9 +482,11 @@ komeda_scaler_validate(void *user,
 	st->vsize_in = dflow->in_h;
 	st->hsize_out = dflow->out_w;
 	st->vsize_out = dflow->out_h;
-	st->en_scaling = dflow->en_scaling;
+
 	/* Enable alpha processing if the next stage needs the pixel alpha */
 	st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
+	st->en_scaling = dflow->en_scaling;
+	st->en_img_enhancement = dflow->en_img_enhancement;
 
 	komeda_component_add_input(&st->base, &dflow->input, 0);
 	komeda_component_set_output(&dflow->input, &scaler->base, 0);
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
index 97d8adb6cd2b..e7cd690d933d 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -15,6 +15,7 @@ static int
 komeda_plane_init_data_flow(struct drm_plane_state *st,
 			    struct komeda_data_flow_cfg *dflow)
 {
+	struct komeda_plane_state *kplane_st = to_kplane_st(st);
 	struct drm_framebuffer *fb = st->fb;
 
 	memset(dflow, 0, sizeof(*dflow));
@@ -23,7 +24,7 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 
 	/* if format doesn't have alpha, fix blend mode to PIXEL_NONE */
 	dflow->pixel_blend_mode = fb->format->has_alpha ?
-		st->pixel_blend_mode : DRM_MODE_BLEND_PIXEL_NONE;
+			st->pixel_blend_mode : DRM_MODE_BLEND_PIXEL_NONE;
 	dflow->layer_alpha = st->alpha >> 8;
 
 	dflow->out_x = st->crtc_x;
@@ -36,6 +37,8 @@ komeda_plane_init_data_flow(struct drm_plane_state *st,
 	dflow->in_w = st->src_w >> 16;
 	dflow->in_h = st->src_h >> 16;
 
+	dflow->en_img_enhancement = kplane_st->img_enhancement;
+
 	komeda_complete_data_flow_cfg(dflow);
 
 	return 0;
@@ -133,7 +136,7 @@ static void komeda_plane_reset(struct drm_plane *plane)
 static struct drm_plane_state *
 komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
 {
-	struct komeda_plane_state *new;
+	struct komeda_plane_state *new, *old;
 
 	if (WARN_ON(!plane->state))
 		return NULL;
@@ -144,6 +147,10 @@ komeda_plane_atomic_duplicate_state(struct drm_plane *plane)
 
 	__drm_atomic_helper_plane_duplicate_state(plane, &new->base);
 
+	old = to_kplane_st(plane->state);
+
+	new->img_enhancement = old->img_enhancement;
+
 	return &new->base;
 }
 
@@ -155,6 +162,40 @@ komeda_plane_atomic_destroy_state(struct drm_plane *plane,
 	kfree(to_kplane_st(state));
 }
 
+static int
+komeda_plane_atomic_get_property(struct drm_plane *plane,
+				 const struct drm_plane_state *state,
+				 struct drm_property *property,
+				 uint64_t *val)
+{
+	struct komeda_plane *kplane = to_kplane(plane);
+	struct komeda_plane_state *st = to_kplane_st(state);
+
+	if (property == kplane->prop_img_enhancement)
+		*val = st->img_enhancement;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+komeda_plane_atomic_set_property(struct drm_plane *plane,
+				 struct drm_plane_state *state,
+				 struct drm_property *property,
+				 uint64_t val)
+{
+	struct komeda_plane *kplane = to_kplane(plane);
+	struct komeda_plane_state *st = to_kplane_st(state);
+
+	if (property == kplane->prop_img_enhancement)
+		st->img_enhancement = !!val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
 static bool
 komeda_plane_format_mod_supported(struct drm_plane *plane,
 				  u32 format, u64 modifier)
@@ -174,9 +215,33 @@ static const struct drm_plane_funcs komeda_plane_funcs = {
 	.reset			= komeda_plane_reset,
 	.atomic_duplicate_state	= komeda_plane_atomic_duplicate_state,
 	.atomic_destroy_state	= komeda_plane_atomic_destroy_state,
+	.atomic_get_property	= komeda_plane_atomic_get_property,
+	.atomic_set_property	= komeda_plane_atomic_set_property,
 	.format_mod_supported	= komeda_plane_format_mod_supported,
 };
 
+static int
+komeda_plane_create_layer_properties(struct komeda_plane *kplane,
+				     struct komeda_layer *layer)
+{
+	struct drm_device *drm = kplane->base.dev;
+	struct drm_plane *plane = &kplane->base;
+	struct drm_property *prop = NULL;
+
+	/* property: layer image_enhancement */
+	if (layer->base.supported_outputs & KOMEDA_PIPELINE_SCALERS) {
+		prop = drm_property_create_bool(drm, DRM_MODE_PROP_ATOMIC,
+						"img_enhancement");
+		if (!prop)
+			return -ENOMEM;
+
+		drm_object_attach_property(&plane->base, prop, 0);
+		kplane->prop_img_enhancement = prop;
+	}
+
+	return 0;
+}
+
 /* for komeda, which is pipeline can be share between crtcs */
 static u32 get_possible_crtcs(struct komeda_kms_dev *kms,
 			      struct komeda_pipeline *pipe)
@@ -238,6 +303,10 @@ static int komeda_plane_add(struct komeda_kms_dev *kms,
 
 	drm_plane_helper_add(plane, &komeda_plane_helper_funcs);
 
+	err = komeda_plane_create_layer_properties(kplane, layer);
+	if (err)
+		goto cleanup;
+
 	return 0;
 cleanup:
 	komeda_plane_destroy(plane);
-- 
2.17.1


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

end of thread, other threads:[~2019-05-23 11:10 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-23 11:09 [PATCH v2 0/6] Added scaler support for komeda james qian wang (Arm Technology China)
2019-05-23 11:09 ` [PATCH v2 1/6] drm/komeda: Attach scaler to drm as private object james qian wang (Arm Technology China)
2019-05-23 11:10 ` [PATCH v2 2/6] drm/komeda: Add the initial scaler support for CORE james qian wang (Arm Technology China)
2019-05-23 11:10 ` [PATCH v2 3/6] drm/komeda: Implement D71 scaler support james qian wang (Arm Technology China)
2019-05-23 11:10 ` [PATCH v2 4/6] drm/komeda: Add writeback scaling support james qian wang (Arm Technology China)
2019-05-23 11:10 ` [PATCH v2 5/6] drm/komeda: Add engine clock requirement check for the downscaling james qian wang (Arm Technology China)
2019-05-23 11:10 ` [PATCH v2 6/6] drm/komeda: Add image enhancement support james qian wang (Arm Technology China)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).