For side by side, the slave pipeline merges to master via image processor

 slave-layers -> slave-compiz-> slave-improc-
                                             \
 master-layers -> master-compiz -------------> master-improc ->

v3: Rebase.

Signed-off-by: James Qian Wang (Arm Technology China) <james.qian.w...@arm.com>
---
 .../arm/display/komeda/d71/d71_component.c    |  4 ++
 .../gpu/drm/arm/display/komeda/komeda_crtc.c  | 18 +++++--
 .../drm/arm/display/komeda/komeda_pipeline.h  |  1 +
 .../display/komeda/komeda_pipeline_state.c    | 51 ++++++++++++++-----
 .../arm/display/komeda/komeda_wb_connector.c  |  2 +-
 5 files changed, 56 insertions(+), 20 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 b6517c46e670..6dadf4413ef3 100644
--- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
+++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c
@@ -1085,6 +1085,10 @@ static void d71_improc_update(struct komeda_component *c,
        else if (st->color_format == DRM_COLOR_FORMAT_YCRCB444)
                ctrl |= IPS_CTRL_YUV;
 
+       /* slave input has been enabled, means side by side */
+       if (has_bit(1, state->active_inputs))
+               ctrl |= IPS_CTRL_SBS;
+
        malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
 }
 
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c 
b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index cee9a1692e71..24928b922fbd 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -385,15 +385,23 @@ komeda_crtc_atomic_flush(struct drm_crtc *crtc,
        komeda_crtc_do_flush(crtc, old);
 }
 
-/* Returns the minimum frequency of the aclk rate (main engine clock) in Hz */
+/*
+ * Returns the minimum frequency of the aclk rate (main engine clock) in Hz.
+ *
+ * The DPU output can be split into two halves, to stay within the bandwidth
+ * capabilities of the external link (dual-link mode).
+ * In these cases, each output link runs at half the pixel clock rate of the
+ * combined display, and has half the number of pixels.
+ * Beside split the output, the DPU internal pixel processing also can be split
+ * into two halves (LEFT/RIGHT) and handles by two pipelines simultaneously.
+ * So if side by side, the pipeline (main engine clock) also can run at half
+ * the clock rate of the combined display.
+ */
 static unsigned long
 komeda_calc_min_aclk_rate(struct komeda_crtc *kcrtc,
                          unsigned long pxlclk)
 {
-       /* Once dual-link one display pipeline drives two display outputs,
-        * the aclk needs run on the double rate of pxlclk
-        */
-       if (kcrtc->master->dual_link)
+       if (kcrtc->master->dual_link && !kcrtc->side_by_side)
                return pxlclk * 2;
        else
                return pxlclk;
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h 
b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
index 4c0946fbaac1..59a81b4476df 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h
@@ -540,6 +540,7 @@ struct komeda_crtc_state;
 struct komeda_crtc;
 
 void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
+                              bool side_by_side,
                               u16 *hsize, u16 *vsize);
 
 int komeda_build_layer_data_flow(struct komeda_layer *layer,
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 10a0dc9291b8..b1e90feb5c55 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -654,12 +654,13 @@ komeda_merger_validate(struct komeda_merger *merger,
 }
 
 void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
+                              bool side_by_side,
                               u16 *hsize, u16 *vsize)
 {
        struct drm_display_mode *m = &kcrtc_st->base.adjusted_mode;
 
        if (hsize)
-               *hsize = m->hdisplay;
+               *hsize = side_by_side ? m->hdisplay / 2 : m->hdisplay;
        if (vsize)
                *vsize = m->vdisplay;
 }
@@ -670,12 +671,14 @@ komeda_compiz_set_input(struct komeda_compiz *compiz,
                        struct komeda_data_flow_cfg *dflow)
 {
        struct drm_atomic_state *drm_st = kcrtc_st->base.state;
+       struct drm_crtc *crtc = kcrtc_st->base.crtc;
        struct komeda_component_state *c_st, *old_st;
        struct komeda_compiz_input_cfg *cin;
        u16 compiz_w, compiz_h;
        int idx = dflow->blending_zorder;
 
-       pipeline_composition_size(kcrtc_st, &compiz_w, &compiz_h);
+       pipeline_composition_size(kcrtc_st, to_kcrtc(crtc)->side_by_side,
+                                 &compiz_w, &compiz_h);
        /* check display rect */
        if ((dflow->out_x + dflow->out_w > compiz_w) ||
            (dflow->out_y + dflow->out_h > compiz_h) ||
@@ -687,7 +690,7 @@ komeda_compiz_set_input(struct komeda_compiz *compiz,
        }
 
        c_st = komeda_component_get_state_and_set_user(&compiz->base, drm_st,
-                       kcrtc_st->base.crtc, kcrtc_st->base.crtc);
+                       crtc, crtc);
        if (IS_ERR(c_st))
                return PTR_ERR(c_st);
 
@@ -721,17 +724,19 @@ komeda_compiz_validate(struct komeda_compiz *compiz,
                       struct komeda_crtc_state *state,
                       struct komeda_data_flow_cfg *dflow)
 {
+       struct drm_crtc *crtc = state->base.crtc;
        struct komeda_component_state *c_st;
        struct komeda_compiz_state *st;
 
        c_st = komeda_component_get_state_and_set_user(&compiz->base,
-                       state->base.state, state->base.crtc, state->base.crtc);
+                       state->base.state, crtc, crtc);
        if (IS_ERR(c_st))
                return PTR_ERR(c_st);
 
        st = to_compiz_st(c_st);
 
-       pipeline_composition_size(state, &st->hsize, &st->vsize);
+       pipeline_composition_size(state, to_kcrtc(crtc)->side_by_side,
+                                 &st->hsize, &st->vsize);
 
        komeda_component_set_output(&dflow->input, &compiz->base, 0);
 
@@ -757,7 +762,8 @@ komeda_compiz_validate(struct komeda_compiz *compiz,
 static int
 komeda_improc_validate(struct komeda_improc *improc,
                       struct komeda_crtc_state *kcrtc_st,
-                      struct komeda_data_flow_cfg *dflow)
+                      struct komeda_data_flow_cfg *m_dflow,
+                      struct komeda_data_flow_cfg *s_dflow)
 {
        struct drm_crtc *crtc = kcrtc_st->base.crtc;
        struct drm_crtc_state *crtc_st = &kcrtc_st->base;
@@ -771,8 +777,8 @@ komeda_improc_validate(struct komeda_improc *improc,
 
        st = to_improc_st(c_st);
 
-       st->hsize = dflow->in_w;
-       st->vsize = dflow->in_h;
+       st->hsize = m_dflow->in_w;
+       st->vsize = m_dflow->in_h;
 
        if (drm_atomic_crtc_needs_modeset(crtc_st)) {
                u32 output_depths, output_formats;
@@ -808,8 +814,10 @@ komeda_improc_validate(struct komeda_improc *improc,
                drm_ctm_to_coeffs(kcrtc_st->base.ctm, st->ctm_coeffs);
        }
 
-       komeda_component_add_input(&st->base, &dflow->input, 0);
-       komeda_component_set_output(&dflow->input, &improc->base, 0);
+       komeda_component_add_input(&st->base, &m_dflow->input, 0);
+       if (s_dflow)
+               komeda_component_add_input(&st->base, &s_dflow->input, 1);
+       komeda_component_set_output(&m_dflow->input, &improc->base, 0);
 
        return 0;
 }
@@ -1146,7 +1154,7 @@ komeda_split_sbs_master_data_flow(struct 
komeda_crtc_state *kcrtc_st,
        u32 disp_end = master->out_x + master->out_w;
        u16 boundary;
 
-       pipeline_composition_size(kcrtc_st, &boundary, NULL);
+       pipeline_composition_size(kcrtc_st, true, &boundary, NULL);
 
        if (disp_end <= boundary) {
                /* the master viewport only located in master side, no need
@@ -1209,7 +1217,7 @@ komeda_split_sbs_slave_data_flow(struct komeda_crtc_state 
*kcrtc_st,
 {
        u16 boundary;
 
-       pipeline_composition_size(kcrtc_st, &boundary, NULL);
+       pipeline_composition_size(kcrtc_st, true, &boundary, NULL);
 
        if (slave->out_x < boundary) {
                DRM_DEBUG_ATOMIC("SBS Slave plane is only allowed to configure 
the right part frame.\n");
@@ -1384,7 +1392,20 @@ int komeda_build_display_data_flow(struct komeda_crtc 
*kcrtc,
        memset(&m_dflow, 0, sizeof(m_dflow));
        memset(&s_dflow, 0, sizeof(s_dflow));
 
-       if (slave && has_bit(slave->id, kcrtc_st->active_pipes)) {
+       /* build slave output data flow */
+       if (kcrtc->side_by_side) {
+               /* on side by side, the slave data flows into the improc of
+                * itself first, and then merge it into master's image processor
+                */
+               err = komeda_compiz_validate(slave->compiz, kcrtc_st, &s_dflow);
+               if (err)
+                       return err;
+
+               err = komeda_improc_validate(slave->improc, kcrtc_st,
+                                            &s_dflow, NULL);
+               if (err)
+                       return err;
+       } else if (slave && has_bit(slave->id, kcrtc_st->active_pipes)) {
                err = komeda_compiz_validate(slave->compiz, kcrtc_st, &s_dflow);
                if (err)
                        return err;
@@ -1400,7 +1421,9 @@ int komeda_build_display_data_flow(struct komeda_crtc 
*kcrtc,
        if (err)
                return err;
 
-       err = komeda_improc_validate(master->improc, kcrtc_st, &m_dflow);
+       /* on side by side, merge the slave dflow into master */
+       err = komeda_improc_validate(master->improc, kcrtc_st, &m_dflow,
+                                    kcrtc->side_by_side ? &s_dflow : NULL);
        if (err)
                return err;
 
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 e465cc4879c9..17ea021488aa 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -21,7 +21,7 @@ komeda_wb_init_data_flow(struct komeda_layer *wb_layer,
        dflow->out_h = fb->height;
 
        /* the write back data comes from the compiz */
-       pipeline_composition_size(kcrtc_st, &dflow->in_w, &dflow->in_h);
+       pipeline_composition_size(kcrtc_st, false, &dflow->in_w, &dflow->in_h);
        dflow->input.component = &wb_layer->base.pipeline->compiz->base;
        /* compiz doesn't output alpha */
        dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
-- 
2.20.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to