Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
0004  * Author: James.Qian.Wang <james.qian.wang@arm.com>
0005  *
0006  */
0007 
0008 #include <drm/drm_print.h>
0009 #include <linux/clk.h>
0010 #include "komeda_dev.h"
0011 #include "komeda_kms.h"
0012 #include "komeda_pipeline.h"
0013 #include "komeda_framebuffer.h"
0014 
0015 static inline bool is_switching_user(void *old, void *new)
0016 {
0017     if (!old || !new)
0018         return false;
0019 
0020     return old != new;
0021 }
0022 
0023 static struct komeda_pipeline_state *
0024 komeda_pipeline_get_state(struct komeda_pipeline *pipe,
0025               struct drm_atomic_state *state)
0026 {
0027     struct drm_private_state *priv_st;
0028 
0029     priv_st = drm_atomic_get_private_obj_state(state, &pipe->obj);
0030     if (IS_ERR(priv_st))
0031         return ERR_CAST(priv_st);
0032 
0033     return priv_to_pipe_st(priv_st);
0034 }
0035 
0036 struct komeda_pipeline_state *
0037 komeda_pipeline_get_old_state(struct komeda_pipeline *pipe,
0038                   struct drm_atomic_state *state)
0039 {
0040     struct drm_private_state *priv_st;
0041 
0042     priv_st = drm_atomic_get_old_private_obj_state(state, &pipe->obj);
0043     if (priv_st)
0044         return priv_to_pipe_st(priv_st);
0045     return NULL;
0046 }
0047 
0048 static struct komeda_pipeline_state *
0049 komeda_pipeline_get_new_state(struct komeda_pipeline *pipe,
0050                   struct drm_atomic_state *state)
0051 {
0052     struct drm_private_state *priv_st;
0053 
0054     priv_st = drm_atomic_get_new_private_obj_state(state, &pipe->obj);
0055     if (priv_st)
0056         return priv_to_pipe_st(priv_st);
0057     return NULL;
0058 }
0059 
0060 /* Assign pipeline for crtc */
0061 static struct komeda_pipeline_state *
0062 komeda_pipeline_get_state_and_set_crtc(struct komeda_pipeline *pipe,
0063                        struct drm_atomic_state *state,
0064                        struct drm_crtc *crtc)
0065 {
0066     struct komeda_pipeline_state *st;
0067 
0068     st = komeda_pipeline_get_state(pipe, state);
0069     if (IS_ERR(st))
0070         return st;
0071 
0072     if (is_switching_user(crtc, st->crtc)) {
0073         DRM_DEBUG_ATOMIC("CRTC%d required pipeline%d is busy.\n",
0074                  drm_crtc_index(crtc), pipe->id);
0075         return ERR_PTR(-EBUSY);
0076     }
0077 
0078     /* pipeline only can be disabled when the it is free or unused */
0079     if (!crtc && st->active_comps) {
0080         DRM_DEBUG_ATOMIC("Disabling a busy pipeline:%d.\n", pipe->id);
0081         return ERR_PTR(-EBUSY);
0082     }
0083 
0084     st->crtc = crtc;
0085 
0086     if (crtc) {
0087         struct komeda_crtc_state *kcrtc_st;
0088 
0089         kcrtc_st = to_kcrtc_st(drm_atomic_get_new_crtc_state(state,
0090                                      crtc));
0091 
0092         kcrtc_st->active_pipes |= BIT(pipe->id);
0093         kcrtc_st->affected_pipes |= BIT(pipe->id);
0094     }
0095     return st;
0096 }
0097 
0098 static struct komeda_component_state *
0099 komeda_component_get_state(struct komeda_component *c,
0100                struct drm_atomic_state *state)
0101 {
0102     struct drm_private_state *priv_st;
0103 
0104     WARN_ON(!drm_modeset_is_locked(&c->pipeline->obj.lock));
0105 
0106     priv_st = drm_atomic_get_private_obj_state(state, &c->obj);
0107     if (IS_ERR(priv_st))
0108         return ERR_CAST(priv_st);
0109 
0110     return priv_to_comp_st(priv_st);
0111 }
0112 
0113 static struct komeda_component_state *
0114 komeda_component_get_old_state(struct komeda_component *c,
0115                    struct drm_atomic_state *state)
0116 {
0117     struct drm_private_state *priv_st;
0118 
0119     priv_st = drm_atomic_get_old_private_obj_state(state, &c->obj);
0120     if (priv_st)
0121         return priv_to_comp_st(priv_st);
0122     return NULL;
0123 }
0124 
0125 /**
0126  * komeda_component_get_state_and_set_user()
0127  *
0128  * @c: component to get state and set user
0129  * @state: global atomic state
0130  * @user: direct user, the binding user
0131  * @crtc: the CRTC user, the big boss :)
0132  *
0133  * This function accepts two users:
0134  * -   The direct user: can be plane/crtc/wb_connector depends on component
0135  * -   The big boss (CRTC)
0136  * CRTC is the big boss (the final user), because all component resources
0137  * eventually will be assigned to CRTC, like the layer will be binding to
0138  * kms_plane, but kms plane will be binding to a CRTC eventually.
0139  *
0140  * The big boss (CRTC) is for pipeline assignment, since &komeda_component isn't
0141  * independent and can be assigned to CRTC freely, but belongs to a specific
0142  * pipeline, only pipeline can be shared between crtc, and pipeline as a whole
0143  * (include all the internal components) assigned to a specific CRTC.
0144  *
0145  * So when set a user to komeda_component, need first to check the status of
0146  * component->pipeline to see if the pipeline is available on this specific
0147  * CRTC. if the pipeline is busy (assigned to another CRTC), even the required
0148  * component is free, the component still cannot be assigned to the direct user.
0149  */
0150 static struct komeda_component_state *
0151 komeda_component_get_state_and_set_user(struct komeda_component *c,
0152                     struct drm_atomic_state *state,
0153                     void *user,
0154                     struct drm_crtc *crtc)
0155 {
0156     struct komeda_pipeline_state *pipe_st;
0157     struct komeda_component_state *st;
0158 
0159     /* First check if the pipeline is available */
0160     pipe_st = komeda_pipeline_get_state_and_set_crtc(c->pipeline,
0161                              state, crtc);
0162     if (IS_ERR(pipe_st))
0163         return ERR_CAST(pipe_st);
0164 
0165     st = komeda_component_get_state(c, state);
0166     if (IS_ERR(st))
0167         return st;
0168 
0169     /* check if the component has been occupied */
0170     if (is_switching_user(user, st->binding_user)) {
0171         DRM_DEBUG_ATOMIC("required %s is busy.\n", c->name);
0172         return ERR_PTR(-EBUSY);
0173     }
0174 
0175     st->binding_user = user;
0176     /* mark the component as active if user is valid */
0177     if (st->binding_user)
0178         pipe_st->active_comps |= BIT(c->id);
0179 
0180     return st;
0181 }
0182 
0183 static void
0184 komeda_component_add_input(struct komeda_component_state *state,
0185                struct komeda_component_output *input,
0186                int idx)
0187 {
0188     struct komeda_component *c = state->component;
0189 
0190     WARN_ON((idx < 0 || idx >= c->max_active_inputs));
0191 
0192     /* since the inputs[i] is only valid when it is active. So if a input[i]
0193      * is a newly enabled input which switches from disable to enable, then
0194      * the old inputs[i] is undefined (NOT zeroed), we can not rely on
0195      * memcmp, but directly mark it changed
0196      */
0197     if (!has_bit(idx, state->affected_inputs) ||
0198         memcmp(&state->inputs[idx], input, sizeof(*input))) {
0199         memcpy(&state->inputs[idx], input, sizeof(*input));
0200         state->changed_active_inputs |= BIT(idx);
0201     }
0202     state->active_inputs |= BIT(idx);
0203     state->affected_inputs |= BIT(idx);
0204 }
0205 
0206 static int
0207 komeda_component_check_input(struct komeda_component_state *state,
0208                  struct komeda_component_output *input,
0209                  int idx)
0210 {
0211     struct komeda_component *c = state->component;
0212 
0213     if ((idx < 0) || (idx >= c->max_active_inputs)) {
0214         DRM_DEBUG_ATOMIC("%s required an invalid %s-input[%d].\n",
0215                  input->component->name, c->name, idx);
0216         return -EINVAL;
0217     }
0218 
0219     if (has_bit(idx, state->active_inputs)) {
0220         DRM_DEBUG_ATOMIC("%s required %s-input[%d] has been occupied already.\n",
0221                  input->component->name, c->name, idx);
0222         return -EINVAL;
0223     }
0224 
0225     return 0;
0226 }
0227 
0228 static void
0229 komeda_component_set_output(struct komeda_component_output *output,
0230                 struct komeda_component *comp,
0231                 u8 output_port)
0232 {
0233     output->component = comp;
0234     output->output_port = output_port;
0235 }
0236 
0237 static int
0238 komeda_component_validate_private(struct komeda_component *c,
0239                   struct komeda_component_state *st)
0240 {
0241     int err;
0242 
0243     if (!c->funcs->validate)
0244         return 0;
0245 
0246     err = c->funcs->validate(c, st);
0247     if (err)
0248         DRM_DEBUG_ATOMIC("%s validate private failed.\n", c->name);
0249 
0250     return err;
0251 }
0252 
0253 /* Get current available scaler from the component->supported_outputs */
0254 static struct komeda_scaler *
0255 komeda_component_get_avail_scaler(struct komeda_component *c,
0256                   struct drm_atomic_state *state)
0257 {
0258     struct komeda_pipeline_state *pipe_st;
0259     u32 avail_scalers;
0260 
0261     pipe_st = komeda_pipeline_get_state(c->pipeline, state);
0262     if (!pipe_st)
0263         return NULL;
0264 
0265     avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
0266             KOMEDA_PIPELINE_SCALERS;
0267 
0268     c = komeda_component_pickup_output(c, avail_scalers);
0269 
0270     return to_scaler(c);
0271 }
0272 
0273 static void
0274 komeda_rotate_data_flow(struct komeda_data_flow_cfg *dflow, u32 rot)
0275 {
0276     if (drm_rotation_90_or_270(rot)) {
0277         swap(dflow->in_h, dflow->in_w);
0278         swap(dflow->total_in_h, dflow->total_in_w);
0279     }
0280 }
0281 
0282 static int
0283 komeda_layer_check_cfg(struct komeda_layer *layer,
0284                struct komeda_fb *kfb,
0285                struct komeda_data_flow_cfg *dflow)
0286 {
0287     u32 src_x, src_y, src_w, src_h;
0288     u32 line_sz, max_line_sz;
0289 
0290     if (!komeda_fb_is_layer_supported(kfb, layer->layer_type, dflow->rot))
0291         return -EINVAL;
0292 
0293     if (layer->base.id == KOMEDA_COMPONENT_WB_LAYER) {
0294         src_x = dflow->out_x;
0295         src_y = dflow->out_y;
0296         src_w = dflow->out_w;
0297         src_h = dflow->out_h;
0298     } else {
0299         src_x = dflow->in_x;
0300         src_y = dflow->in_y;
0301         src_w = dflow->in_w;
0302         src_h = dflow->in_h;
0303     }
0304 
0305     if (komeda_fb_check_src_coords(kfb, src_x, src_y, src_w, src_h))
0306         return -EINVAL;
0307 
0308     if (!in_range(&layer->hsize_in, src_w)) {
0309         DRM_DEBUG_ATOMIC("invalidate src_w %d.\n", src_w);
0310         return -EINVAL;
0311     }
0312 
0313     if (!in_range(&layer->vsize_in, src_h)) {
0314         DRM_DEBUG_ATOMIC("invalidate src_h %d.\n", src_h);
0315         return -EINVAL;
0316     }
0317 
0318     if (drm_rotation_90_or_270(dflow->rot))
0319         line_sz = dflow->in_h;
0320     else
0321         line_sz = dflow->in_w;
0322 
0323     if (kfb->base.format->hsub > 1)
0324         max_line_sz = layer->yuv_line_sz;
0325     else
0326         max_line_sz = layer->line_sz;
0327 
0328     if (line_sz > max_line_sz) {
0329         DRM_DEBUG_ATOMIC("Required line_sz: %d exceeds the max size %d\n",
0330                  line_sz, max_line_sz);
0331         return -EINVAL;
0332     }
0333 
0334     return 0;
0335 }
0336 
0337 static int
0338 komeda_layer_validate(struct komeda_layer *layer,
0339               struct komeda_plane_state *kplane_st,
0340               struct komeda_data_flow_cfg *dflow)
0341 {
0342     struct drm_plane_state *plane_st = &kplane_st->base;
0343     struct drm_framebuffer *fb = plane_st->fb;
0344     struct komeda_fb *kfb = to_kfb(fb);
0345     struct komeda_component_state *c_st;
0346     struct komeda_layer_state *st;
0347     int i, err;
0348 
0349     err = komeda_layer_check_cfg(layer, kfb, dflow);
0350     if (err)
0351         return err;
0352 
0353     c_st = komeda_component_get_state_and_set_user(&layer->base,
0354             plane_st->state, plane_st->plane, plane_st->crtc);
0355     if (IS_ERR(c_st))
0356         return PTR_ERR(c_st);
0357 
0358     st = to_layer_st(c_st);
0359 
0360     st->rot = dflow->rot;
0361 
0362     if (fb->modifier) {
0363         st->hsize = kfb->aligned_w;
0364         st->vsize = kfb->aligned_h;
0365         st->afbc_crop_l = dflow->in_x;
0366         st->afbc_crop_r = kfb->aligned_w - dflow->in_x - dflow->in_w;
0367         st->afbc_crop_t = dflow->in_y;
0368         st->afbc_crop_b = kfb->aligned_h - dflow->in_y - dflow->in_h;
0369     } else {
0370         st->hsize = dflow->in_w;
0371         st->vsize = dflow->in_h;
0372         st->afbc_crop_l = 0;
0373         st->afbc_crop_r = 0;
0374         st->afbc_crop_t = 0;
0375         st->afbc_crop_b = 0;
0376     }
0377 
0378     for (i = 0; i < fb->format->num_planes; i++)
0379         st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->in_x,
0380                                dflow->in_y, i);
0381 
0382     err = komeda_component_validate_private(&layer->base, c_st);
0383     if (err)
0384         return err;
0385 
0386     /* update the data flow for the next stage */
0387     komeda_component_set_output(&dflow->input, &layer->base, 0);
0388 
0389     /*
0390      * The rotation has been handled by layer, so adjusted the data flow for
0391      * the next stage.
0392      */
0393     komeda_rotate_data_flow(dflow, st->rot);
0394 
0395     return 0;
0396 }
0397 
0398 static int
0399 komeda_wb_layer_validate(struct komeda_layer *wb_layer,
0400              struct drm_connector_state *conn_st,
0401              struct komeda_data_flow_cfg *dflow)
0402 {
0403     struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
0404     struct komeda_component_state *c_st;
0405     struct komeda_layer_state *st;
0406     int i, err;
0407 
0408     err = komeda_layer_check_cfg(wb_layer, kfb, dflow);
0409     if (err)
0410         return err;
0411 
0412     c_st = komeda_component_get_state_and_set_user(&wb_layer->base,
0413             conn_st->state, conn_st->connector, conn_st->crtc);
0414     if (IS_ERR(c_st))
0415         return PTR_ERR(c_st);
0416 
0417     st = to_layer_st(c_st);
0418 
0419     st->hsize = dflow->out_w;
0420     st->vsize = dflow->out_h;
0421 
0422     for (i = 0; i < kfb->base.format->num_planes; i++)
0423         st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->out_x,
0424                                dflow->out_y, i);
0425 
0426     komeda_component_add_input(&st->base, &dflow->input, 0);
0427     komeda_component_set_output(&dflow->input, &wb_layer->base, 0);
0428 
0429     return 0;
0430 }
0431 
0432 static bool scaling_ratio_valid(u32 size_in, u32 size_out,
0433                 u32 max_upscaling, u32 max_downscaling)
0434 {
0435     if (size_out > size_in * max_upscaling)
0436         return false;
0437     else if (size_in > size_out * max_downscaling)
0438         return false;
0439     return true;
0440 }
0441 
0442 static int
0443 komeda_scaler_check_cfg(struct komeda_scaler *scaler,
0444             struct komeda_crtc_state *kcrtc_st,
0445             struct komeda_data_flow_cfg *dflow)
0446 {
0447     u32 hsize_in, vsize_in, hsize_out, vsize_out;
0448     u32 max_upscaling;
0449 
0450     hsize_in = dflow->in_w;
0451     vsize_in = dflow->in_h;
0452     hsize_out = dflow->out_w;
0453     vsize_out = dflow->out_h;
0454 
0455     if (!in_range(&scaler->hsize, hsize_in) ||
0456         !in_range(&scaler->hsize, hsize_out)) {
0457         DRM_DEBUG_ATOMIC("Invalid horizontal sizes");
0458         return -EINVAL;
0459     }
0460 
0461     if (!in_range(&scaler->vsize, vsize_in) ||
0462         !in_range(&scaler->vsize, vsize_out)) {
0463         DRM_DEBUG_ATOMIC("Invalid vertical sizes");
0464         return -EINVAL;
0465     }
0466 
0467     /* If input comes from compiz that means the scaling is for writeback
0468      * and scaler can not do upscaling for writeback
0469      */
0470     if (has_bit(dflow->input.component->id, KOMEDA_PIPELINE_COMPIZS))
0471         max_upscaling = 1;
0472     else
0473         max_upscaling = scaler->max_upscaling;
0474 
0475     if (!scaling_ratio_valid(hsize_in, hsize_out, max_upscaling,
0476                  scaler->max_downscaling)) {
0477         DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
0478         return -EINVAL;
0479     }
0480 
0481     if (!scaling_ratio_valid(vsize_in, vsize_out, max_upscaling,
0482                  scaler->max_downscaling)) {
0483         DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
0484         return -EINVAL;
0485     }
0486 
0487     if (hsize_in > hsize_out || vsize_in > vsize_out) {
0488         struct komeda_pipeline *pipe = scaler->base.pipeline;
0489         int err;
0490 
0491         err = pipe->funcs->downscaling_clk_check(pipe,
0492                     &kcrtc_st->base.adjusted_mode,
0493                     komeda_crtc_get_aclk(kcrtc_st), dflow);
0494         if (err) {
0495             DRM_DEBUG_ATOMIC("aclk can't satisfy the clock requirement of the downscaling\n");
0496             return err;
0497         }
0498     }
0499 
0500     return 0;
0501 }
0502 
0503 static int
0504 komeda_scaler_validate(void *user,
0505                struct komeda_crtc_state *kcrtc_st,
0506                struct komeda_data_flow_cfg *dflow)
0507 {
0508     struct drm_atomic_state *drm_st = kcrtc_st->base.state;
0509     struct komeda_component_state *c_st;
0510     struct komeda_scaler_state *st;
0511     struct komeda_scaler *scaler;
0512     int err = 0;
0513 
0514     if (!(dflow->en_scaling || dflow->en_img_enhancement))
0515         return 0;
0516 
0517     scaler = komeda_component_get_avail_scaler(dflow->input.component,
0518                            drm_st);
0519     if (!scaler) {
0520         DRM_DEBUG_ATOMIC("No scaler available");
0521         return -EINVAL;
0522     }
0523 
0524     err = komeda_scaler_check_cfg(scaler, kcrtc_st, dflow);
0525     if (err)
0526         return err;
0527 
0528     c_st = komeda_component_get_state_and_set_user(&scaler->base,
0529             drm_st, user, kcrtc_st->base.crtc);
0530     if (IS_ERR(c_st))
0531         return PTR_ERR(c_st);
0532 
0533     st = to_scaler_st(c_st);
0534 
0535     st->hsize_in = dflow->in_w;
0536     st->vsize_in = dflow->in_h;
0537     st->hsize_out = dflow->out_w;
0538     st->vsize_out = dflow->out_h;
0539     st->right_crop = dflow->right_crop;
0540     st->left_crop = dflow->left_crop;
0541     st->total_vsize_in = dflow->total_in_h;
0542     st->total_hsize_in = dflow->total_in_w;
0543     st->total_hsize_out = dflow->total_out_w;
0544 
0545     /* Enable alpha processing if the next stage needs the pixel alpha */
0546     st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
0547     st->en_scaling = dflow->en_scaling;
0548     st->en_img_enhancement = dflow->en_img_enhancement;
0549     st->en_split = dflow->en_split;
0550     st->right_part = dflow->right_part;
0551 
0552     komeda_component_add_input(&st->base, &dflow->input, 0);
0553     komeda_component_set_output(&dflow->input, &scaler->base, 0);
0554     return err;
0555 }
0556 
0557 static void komeda_split_data_flow(struct komeda_scaler *scaler,
0558                    struct komeda_data_flow_cfg *dflow,
0559                    struct komeda_data_flow_cfg *l_dflow,
0560                    struct komeda_data_flow_cfg *r_dflow);
0561 
0562 static int
0563 komeda_splitter_validate(struct komeda_splitter *splitter,
0564              struct drm_connector_state *conn_st,
0565              struct komeda_data_flow_cfg *dflow,
0566              struct komeda_data_flow_cfg *l_output,
0567              struct komeda_data_flow_cfg *r_output)
0568 {
0569     struct komeda_component_state *c_st;
0570     struct komeda_splitter_state *st;
0571 
0572     if (!splitter) {
0573         DRM_DEBUG_ATOMIC("Current HW doesn't support splitter.\n");
0574         return -EINVAL;
0575     }
0576 
0577     if (!in_range(&splitter->hsize, dflow->in_w)) {
0578         DRM_DEBUG_ATOMIC("split in_w:%d is out of the acceptable range.\n",
0579                  dflow->in_w);
0580         return -EINVAL;
0581     }
0582 
0583     if (!in_range(&splitter->vsize, dflow->in_h)) {
0584         DRM_DEBUG_ATOMIC("split in_h: %d exceeds the acceptable range.\n",
0585                  dflow->in_h);
0586         return -EINVAL;
0587     }
0588 
0589     c_st = komeda_component_get_state_and_set_user(&splitter->base,
0590             conn_st->state, conn_st->connector, conn_st->crtc);
0591 
0592     if (IS_ERR(c_st))
0593         return PTR_ERR(c_st);
0594 
0595     komeda_split_data_flow(splitter->base.pipeline->scalers[0],
0596                    dflow, l_output, r_output);
0597 
0598     st = to_splitter_st(c_st);
0599     st->hsize = dflow->in_w;
0600     st->vsize = dflow->in_h;
0601     st->overlap = dflow->overlap;
0602 
0603     komeda_component_add_input(&st->base, &dflow->input, 0);
0604     komeda_component_set_output(&l_output->input, &splitter->base, 0);
0605     komeda_component_set_output(&r_output->input, &splitter->base, 1);
0606 
0607     return 0;
0608 }
0609 
0610 static int
0611 komeda_merger_validate(struct komeda_merger *merger,
0612                void *user,
0613                struct komeda_crtc_state *kcrtc_st,
0614                struct komeda_data_flow_cfg *left_input,
0615                struct komeda_data_flow_cfg *right_input,
0616                struct komeda_data_flow_cfg *output)
0617 {
0618     struct komeda_component_state *c_st;
0619     struct komeda_merger_state *st;
0620     int err = 0;
0621 
0622     if (!merger) {
0623         DRM_DEBUG_ATOMIC("No merger is available");
0624         return -EINVAL;
0625     }
0626 
0627     if (!in_range(&merger->hsize_merged, output->out_w)) {
0628         DRM_DEBUG_ATOMIC("merged_w: %d is out of the accepted range.\n",
0629                  output->out_w);
0630         return -EINVAL;
0631     }
0632 
0633     if (!in_range(&merger->vsize_merged, output->out_h)) {
0634         DRM_DEBUG_ATOMIC("merged_h: %d is out of the accepted range.\n",
0635                  output->out_h);
0636         return -EINVAL;
0637     }
0638 
0639     c_st = komeda_component_get_state_and_set_user(&merger->base,
0640             kcrtc_st->base.state, kcrtc_st->base.crtc, kcrtc_st->base.crtc);
0641 
0642     if (IS_ERR(c_st))
0643         return PTR_ERR(c_st);
0644 
0645     st = to_merger_st(c_st);
0646     st->hsize_merged = output->out_w;
0647     st->vsize_merged = output->out_h;
0648 
0649     komeda_component_add_input(c_st, &left_input->input, 0);
0650     komeda_component_add_input(c_st, &right_input->input, 1);
0651     komeda_component_set_output(&output->input, &merger->base, 0);
0652 
0653     return err;
0654 }
0655 
0656 void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
0657                    u16 *hsize, u16 *vsize)
0658 {
0659     struct drm_display_mode *m = &kcrtc_st->base.adjusted_mode;
0660 
0661     if (hsize)
0662         *hsize = m->hdisplay;
0663     if (vsize)
0664         *vsize = m->vdisplay;
0665 }
0666 
0667 static int
0668 komeda_compiz_set_input(struct komeda_compiz *compiz,
0669             struct komeda_crtc_state *kcrtc_st,
0670             struct komeda_data_flow_cfg *dflow)
0671 {
0672     struct drm_atomic_state *drm_st = kcrtc_st->base.state;
0673     struct komeda_component_state *c_st, *old_st;
0674     struct komeda_compiz_input_cfg *cin;
0675     u16 compiz_w, compiz_h;
0676     int idx = dflow->blending_zorder;
0677 
0678     pipeline_composition_size(kcrtc_st, &compiz_w, &compiz_h);
0679     /* check display rect */
0680     if ((dflow->out_x + dflow->out_w > compiz_w) ||
0681         (dflow->out_y + dflow->out_h > compiz_h) ||
0682          dflow->out_w == 0 || dflow->out_h == 0) {
0683         DRM_DEBUG_ATOMIC("invalid disp rect [x=%d, y=%d, w=%d, h=%d]\n",
0684                  dflow->out_x, dflow->out_y,
0685                  dflow->out_w, dflow->out_h);
0686         return -EINVAL;
0687     }
0688 
0689     c_st = komeda_component_get_state_and_set_user(&compiz->base, drm_st,
0690             kcrtc_st->base.crtc, kcrtc_st->base.crtc);
0691     if (IS_ERR(c_st))
0692         return PTR_ERR(c_st);
0693 
0694     if (komeda_component_check_input(c_st, &dflow->input, idx))
0695         return -EINVAL;
0696 
0697     cin = &(to_compiz_st(c_st)->cins[idx]);
0698 
0699     cin->hsize   = dflow->out_w;
0700     cin->vsize   = dflow->out_h;
0701     cin->hoffset = dflow->out_x;
0702     cin->voffset = dflow->out_y;
0703     cin->pixel_blend_mode = dflow->pixel_blend_mode;
0704     cin->layer_alpha = dflow->layer_alpha;
0705 
0706     old_st = komeda_component_get_old_state(&compiz->base, drm_st);
0707 
0708     /* compare with old to check if this input has been changed */
0709     if (WARN_ON(!old_st) ||
0710         memcmp(&(to_compiz_st(old_st)->cins[idx]), cin, sizeof(*cin)))
0711         c_st->changed_active_inputs |= BIT(idx);
0712 
0713     komeda_component_add_input(c_st, &dflow->input, idx);
0714     komeda_component_set_output(&dflow->input, &compiz->base, 0);
0715 
0716     return 0;
0717 }
0718 
0719 static int
0720 komeda_compiz_validate(struct komeda_compiz *compiz,
0721                struct komeda_crtc_state *state,
0722                struct komeda_data_flow_cfg *dflow)
0723 {
0724     struct komeda_component_state *c_st;
0725     struct komeda_compiz_state *st;
0726 
0727     c_st = komeda_component_get_state_and_set_user(&compiz->base,
0728             state->base.state, state->base.crtc, state->base.crtc);
0729     if (IS_ERR(c_st))
0730         return PTR_ERR(c_st);
0731 
0732     st = to_compiz_st(c_st);
0733 
0734     pipeline_composition_size(state, &st->hsize, &st->vsize);
0735 
0736     komeda_component_set_output(&dflow->input, &compiz->base, 0);
0737 
0738     /* compiz output dflow will be fed to the next pipeline stage, prepare
0739      * the data flow configuration for the next stage
0740      */
0741     if (dflow) {
0742         dflow->in_w = st->hsize;
0743         dflow->in_h = st->vsize;
0744         dflow->out_w = dflow->in_w;
0745         dflow->out_h = dflow->in_h;
0746         /* the output data of compiz doesn't have alpha, it only can be
0747          * used as bottom layer when blend it with master layers
0748          */
0749         dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
0750         dflow->layer_alpha = 0xFF;
0751         dflow->blending_zorder = 0;
0752     }
0753 
0754     return 0;
0755 }
0756 
0757 static int
0758 komeda_improc_validate(struct komeda_improc *improc,
0759                struct komeda_crtc_state *kcrtc_st,
0760                struct komeda_data_flow_cfg *dflow)
0761 {
0762     struct drm_crtc *crtc = kcrtc_st->base.crtc;
0763     struct drm_crtc_state *crtc_st = &kcrtc_st->base;
0764     struct komeda_component_state *c_st;
0765     struct komeda_improc_state *st;
0766 
0767     c_st = komeda_component_get_state_and_set_user(&improc->base,
0768             kcrtc_st->base.state, crtc, crtc);
0769     if (IS_ERR(c_st))
0770         return PTR_ERR(c_st);
0771 
0772     st = to_improc_st(c_st);
0773 
0774     st->hsize = dflow->in_w;
0775     st->vsize = dflow->in_h;
0776 
0777     if (drm_atomic_crtc_needs_modeset(crtc_st)) {
0778         u32 output_depths, output_formats;
0779         u32 avail_depths, avail_formats;
0780 
0781         komeda_crtc_get_color_config(crtc_st, &output_depths,
0782                          &output_formats);
0783 
0784         avail_depths = output_depths & improc->supported_color_depths;
0785         if (avail_depths == 0) {
0786             DRM_DEBUG_ATOMIC("No available color depths, conn depths: 0x%x & display: 0x%x\n",
0787                      output_depths,
0788                      improc->supported_color_depths);
0789             return -EINVAL;
0790         }
0791 
0792         avail_formats = output_formats &
0793                 improc->supported_color_formats;
0794         if (!avail_formats) {
0795             DRM_DEBUG_ATOMIC("No available color_formats, conn formats 0x%x & display: 0x%x\n",
0796                      output_formats,
0797                      improc->supported_color_formats);
0798             return -EINVAL;
0799         }
0800 
0801         st->color_depth = __fls(avail_depths);
0802         st->color_format = BIT(__ffs(avail_formats));
0803     }
0804 
0805     if (kcrtc_st->base.color_mgmt_changed) {
0806         drm_lut_to_fgamma_coeffs(kcrtc_st->base.gamma_lut,
0807                      st->fgamma_coeffs);
0808         drm_ctm_to_coeffs(kcrtc_st->base.ctm, st->ctm_coeffs);
0809     }
0810 
0811     komeda_component_add_input(&st->base, &dflow->input, 0);
0812     komeda_component_set_output(&dflow->input, &improc->base, 0);
0813 
0814     return 0;
0815 }
0816 
0817 static int
0818 komeda_timing_ctrlr_validate(struct komeda_timing_ctrlr *ctrlr,
0819                  struct komeda_crtc_state *kcrtc_st,
0820                  struct komeda_data_flow_cfg *dflow)
0821 {
0822     struct drm_crtc *crtc = kcrtc_st->base.crtc;
0823     struct komeda_timing_ctrlr_state *st;
0824     struct komeda_component_state *c_st;
0825 
0826     c_st = komeda_component_get_state_and_set_user(&ctrlr->base,
0827             kcrtc_st->base.state, crtc, crtc);
0828     if (IS_ERR(c_st))
0829         return PTR_ERR(c_st);
0830 
0831     st = to_ctrlr_st(c_st);
0832 
0833     komeda_component_add_input(&st->base, &dflow->input, 0);
0834     komeda_component_set_output(&dflow->input, &ctrlr->base, 0);
0835 
0836     return 0;
0837 }
0838 
0839 void komeda_complete_data_flow_cfg(struct komeda_layer *layer,
0840                    struct komeda_data_flow_cfg *dflow,
0841                    struct drm_framebuffer *fb)
0842 {
0843     struct komeda_scaler *scaler = layer->base.pipeline->scalers[0];
0844     u32 w = dflow->in_w;
0845     u32 h = dflow->in_h;
0846 
0847     dflow->total_in_w = dflow->in_w;
0848     dflow->total_in_h = dflow->in_h;
0849     dflow->total_out_w = dflow->out_w;
0850 
0851     /* if format doesn't have alpha, fix blend mode to PIXEL_NONE */
0852     if (!fb->format->has_alpha)
0853         dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
0854 
0855     if (drm_rotation_90_or_270(dflow->rot))
0856         swap(w, h);
0857 
0858     dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
0859     dflow->is_yuv = fb->format->is_yuv;
0860 
0861     /* try to enable image enhancer if data flow is a 2x+ upscaling */
0862     dflow->en_img_enhancement = dflow->out_w >= 2 * w ||
0863                     dflow->out_h >= 2 * h;
0864 
0865     /* try to enable split if scaling exceed the scaler's acceptable
0866      * input/output range.
0867      */
0868     if (dflow->en_scaling && scaler)
0869         dflow->en_split = !in_range(&scaler->hsize, dflow->in_w) ||
0870                   !in_range(&scaler->hsize, dflow->out_w);
0871 }
0872 
0873 static bool merger_is_available(struct komeda_pipeline *pipe,
0874                 struct komeda_data_flow_cfg *dflow)
0875 {
0876     u32 avail_inputs = pipe->merger ?
0877                pipe->merger->base.supported_inputs : 0;
0878 
0879     return has_bit(dflow->input.component->id, avail_inputs);
0880 }
0881 
0882 int komeda_build_layer_data_flow(struct komeda_layer *layer,
0883                  struct komeda_plane_state *kplane_st,
0884                  struct komeda_crtc_state *kcrtc_st,
0885                  struct komeda_data_flow_cfg *dflow)
0886 {
0887     struct drm_plane *plane = kplane_st->base.plane;
0888     struct komeda_pipeline *pipe = layer->base.pipeline;
0889     int err;
0890 
0891     DRM_DEBUG_ATOMIC("%s handling [PLANE:%d:%s]: src[x/y:%d/%d, w/h:%d/%d] disp[x/y:%d/%d, w/h:%d/%d]",
0892              layer->base.name, plane->base.id, plane->name,
0893              dflow->in_x, dflow->in_y, dflow->in_w, dflow->in_h,
0894              dflow->out_x, dflow->out_y, dflow->out_w, dflow->out_h);
0895 
0896     err = komeda_layer_validate(layer, kplane_st, dflow);
0897     if (err)
0898         return err;
0899 
0900     err = komeda_scaler_validate(plane, kcrtc_st, dflow);
0901     if (err)
0902         return err;
0903 
0904     /* if split, check if can put the data flow into merger */
0905     if (dflow->en_split && merger_is_available(pipe, dflow))
0906         return 0;
0907 
0908     err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
0909 
0910     return err;
0911 }
0912 
0913 /*
0914  * Split is introduced for workaround scaler's input/output size limitation.
0915  * The idea is simple, if one scaler can not fit the requirement, use two.
0916  * So split splits the big source image to two half parts (left/right) and do
0917  * the scaling by two scaler separately and independently.
0918  * But split also imports an edge problem in the middle of the image when
0919  * scaling, to avoid it, split isn't a simple half-and-half, but add an extra
0920  * pixels (overlap) to both side, after split the left/right will be:
0921  * - left: [0, src_length/2 + overlap]
0922  * - right: [src_length/2 - overlap, src_length]
0923  * The extra overlap do eliminate the edge problem, but which may also generates
0924  * unnecessary pixels when scaling, we need to crop them before scaler output
0925  * the result to the next stage. and for the how to crop, it depends on the
0926  * unneeded pixels, another words the position where overlay has been added.
0927  * - left: crop the right
0928  * - right: crop the left
0929  *
0930  * The diagram for how to do the split
0931  *
0932  *  <---------------------left->out_w ---------------->
0933  * |--------------------------------|---right_crop-----| <- left after split
0934  *  \                                \                /
0935  *   \                                \<--overlap--->/
0936  *   |-----------------|-------------|(Middle)------|-----------------| <- src
0937  *                     /<---overlap--->\                               \
0938  *                    /                 \                               \
0939  * right after split->|-----left_crop---|--------------------------------|
0940  *                    ^<------------------- right->out_w --------------->^
0941  *
0942  * NOTE: To consistent with HW the output_w always contains the crop size.
0943  */
0944 
0945 static void komeda_split_data_flow(struct komeda_scaler *scaler,
0946                    struct komeda_data_flow_cfg *dflow,
0947                    struct komeda_data_flow_cfg *l_dflow,
0948                    struct komeda_data_flow_cfg *r_dflow)
0949 {
0950     bool r90 = drm_rotation_90_or_270(dflow->rot);
0951     bool flip_h = has_flip_h(dflow->rot);
0952     u32 l_out, r_out, overlap;
0953 
0954     memcpy(l_dflow, dflow, sizeof(*dflow));
0955     memcpy(r_dflow, dflow, sizeof(*dflow));
0956 
0957     l_dflow->right_part = false;
0958     r_dflow->right_part = true;
0959     r_dflow->blending_zorder = dflow->blending_zorder + 1;
0960 
0961     overlap = 0;
0962     if (dflow->en_scaling && scaler)
0963         overlap += scaler->scaling_split_overlap;
0964 
0965     /* original dflow may fed into splitter, and which doesn't need
0966      * enhancement overlap
0967      */
0968     dflow->overlap = overlap;
0969 
0970     if (dflow->en_img_enhancement && scaler)
0971         overlap += scaler->enh_split_overlap;
0972 
0973     l_dflow->overlap = overlap;
0974     r_dflow->overlap = overlap;
0975 
0976     /* split the origin content */
0977     /* left/right here always means the left/right part of display image,
0978      * not the source Image
0979      */
0980     /* DRM rotation is anti-clockwise */
0981     if (r90) {
0982         if (dflow->en_scaling) {
0983             l_dflow->in_h = ALIGN(dflow->in_h, 2) / 2 + l_dflow->overlap;
0984             r_dflow->in_h = l_dflow->in_h;
0985         } else if (dflow->en_img_enhancement) {
0986             /* enhancer only */
0987             l_dflow->in_h = ALIGN(dflow->in_h, 2) / 2 + l_dflow->overlap;
0988             r_dflow->in_h = dflow->in_h / 2 + r_dflow->overlap;
0989         } else {
0990             /* split without scaler, no overlap */
0991             l_dflow->in_h = ALIGN(((dflow->in_h + 1) >> 1), 2);
0992             r_dflow->in_h = dflow->in_h - l_dflow->in_h;
0993         }
0994 
0995         /* Consider YUV format, after split, the split source w/h
0996          * may not aligned to 2. we have two choices for such case.
0997          * 1. scaler is enabled (overlap != 0), we can do a alignment
0998          *    both left/right and crop the extra data by scaler.
0999          * 2. scaler is not enabled, only align the split left
1000          *    src/disp, and the rest part assign to right
1001          */
1002         if ((overlap != 0) && dflow->is_yuv) {
1003             l_dflow->in_h = ALIGN(l_dflow->in_h, 2);
1004             r_dflow->in_h = ALIGN(r_dflow->in_h, 2);
1005         }
1006 
1007         if (flip_h)
1008             l_dflow->in_y = dflow->in_y + dflow->in_h - l_dflow->in_h;
1009         else
1010             r_dflow->in_y = dflow->in_y + dflow->in_h - r_dflow->in_h;
1011     } else {
1012         if (dflow->en_scaling) {
1013             l_dflow->in_w = ALIGN(dflow->in_w, 2) / 2 + l_dflow->overlap;
1014             r_dflow->in_w = l_dflow->in_w;
1015         } else if (dflow->en_img_enhancement) {
1016             l_dflow->in_w = ALIGN(dflow->in_w, 2) / 2 + l_dflow->overlap;
1017             r_dflow->in_w = dflow->in_w / 2 + r_dflow->overlap;
1018         } else {
1019             l_dflow->in_w = ALIGN(((dflow->in_w + 1) >> 1), 2);
1020             r_dflow->in_w = dflow->in_w - l_dflow->in_w;
1021         }
1022 
1023         /* do YUV alignment when scaler enabled */
1024         if ((overlap != 0) && dflow->is_yuv) {
1025             l_dflow->in_w = ALIGN(l_dflow->in_w, 2);
1026             r_dflow->in_w = ALIGN(r_dflow->in_w, 2);
1027         }
1028 
1029         /* on flip_h, the left display content from the right-source */
1030         if (flip_h)
1031             l_dflow->in_x = dflow->in_w + dflow->in_x - l_dflow->in_w;
1032         else
1033             r_dflow->in_x = dflow->in_w + dflow->in_x - r_dflow->in_w;
1034     }
1035 
1036     /* split the disp_rect */
1037     if (dflow->en_scaling || dflow->en_img_enhancement)
1038         l_dflow->out_w = ((dflow->out_w + 1) >> 1);
1039     else
1040         l_dflow->out_w = ALIGN(((dflow->out_w + 1) >> 1), 2);
1041 
1042     r_dflow->out_w = dflow->out_w - l_dflow->out_w;
1043 
1044     l_dflow->out_x = dflow->out_x;
1045     r_dflow->out_x = l_dflow->out_w + l_dflow->out_x;
1046 
1047     /* calculate the scaling crop */
1048     /* left scaler output more data and do crop */
1049     if (r90) {
1050         l_out = (dflow->out_w * l_dflow->in_h) / dflow->in_h;
1051         r_out = (dflow->out_w * r_dflow->in_h) / dflow->in_h;
1052     } else {
1053         l_out = (dflow->out_w * l_dflow->in_w) / dflow->in_w;
1054         r_out = (dflow->out_w * r_dflow->in_w) / dflow->in_w;
1055     }
1056 
1057     l_dflow->left_crop  = 0;
1058     l_dflow->right_crop = l_out - l_dflow->out_w;
1059     r_dflow->left_crop  = r_out - r_dflow->out_w;
1060     r_dflow->right_crop = 0;
1061 
1062     /* out_w includes the crop length */
1063     l_dflow->out_w += l_dflow->right_crop + l_dflow->left_crop;
1064     r_dflow->out_w += r_dflow->right_crop + r_dflow->left_crop;
1065 }
1066 
1067 /* For layer split, a plane state will be split to two data flows and handled
1068  * by two separated komeda layer input pipelines. komeda supports two types of
1069  * layer split:
1070  * - none-scaling split:
1071  *             / layer-left -> \
1072  * plane_state                  compiz-> ...
1073  *             \ layer-right-> /
1074  *
1075  * - scaling split:
1076  *             / layer-left -> scaler->\
1077  * plane_state                          merger -> compiz-> ...
1078  *             \ layer-right-> scaler->/
1079  *
1080  * Since merger only supports scaler as input, so for none-scaling split, two
1081  * layer data flows will be output to compiz directly. for scaling_split, two
1082  * data flow will be merged by merger firstly, then merger outputs one merged
1083  * data flow to compiz.
1084  */
1085 int komeda_build_layer_split_data_flow(struct komeda_layer *left,
1086                        struct komeda_plane_state *kplane_st,
1087                        struct komeda_crtc_state *kcrtc_st,
1088                        struct komeda_data_flow_cfg *dflow)
1089 {
1090     struct drm_plane *plane = kplane_st->base.plane;
1091     struct komeda_pipeline *pipe = left->base.pipeline;
1092     struct komeda_layer *right = left->right;
1093     struct komeda_data_flow_cfg l_dflow, r_dflow;
1094     int err;
1095 
1096     komeda_split_data_flow(pipe->scalers[0], dflow, &l_dflow, &r_dflow);
1097 
1098     DRM_DEBUG_ATOMIC("Assign %s + %s to [PLANE:%d:%s]: "
1099              "src[x/y:%d/%d, w/h:%d/%d] disp[x/y:%d/%d, w/h:%d/%d]",
1100              left->base.name, right->base.name,
1101              plane->base.id, plane->name,
1102              dflow->in_x, dflow->in_y, dflow->in_w, dflow->in_h,
1103              dflow->out_x, dflow->out_y, dflow->out_w, dflow->out_h);
1104 
1105     err = komeda_build_layer_data_flow(left, kplane_st, kcrtc_st, &l_dflow);
1106     if (err)
1107         return err;
1108 
1109     err = komeda_build_layer_data_flow(right, kplane_st, kcrtc_st, &r_dflow);
1110     if (err)
1111         return err;
1112 
1113     /* The rotation has been handled by layer, so adjusted the data flow */
1114     komeda_rotate_data_flow(dflow, dflow->rot);
1115 
1116     /* left and right dflow has been merged to compiz already,
1117      * no need merger to merge them anymore.
1118      */
1119     if (r_dflow.input.component == l_dflow.input.component)
1120         return 0;
1121 
1122     /* line merger path */
1123     err = komeda_merger_validate(pipe->merger, plane, kcrtc_st,
1124                      &l_dflow, &r_dflow, dflow);
1125     if (err)
1126         return err;
1127 
1128     err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
1129 
1130     return err;
1131 }
1132 
1133 /* writeback data path: compiz -> scaler -> wb_layer -> memory */
1134 int komeda_build_wb_data_flow(struct komeda_layer *wb_layer,
1135                   struct drm_connector_state *conn_st,
1136                   struct komeda_crtc_state *kcrtc_st,
1137                   struct komeda_data_flow_cfg *dflow)
1138 {
1139     struct drm_connector *conn = conn_st->connector;
1140     int err;
1141 
1142     err = komeda_scaler_validate(conn, kcrtc_st, dflow);
1143     if (err)
1144         return err;
1145 
1146     return komeda_wb_layer_validate(wb_layer, conn_st, dflow);
1147 }
1148 
1149 /* writeback scaling split data path:
1150  *                   /-> scaler ->\
1151  * compiz -> splitter              merger -> wb_layer -> memory
1152  *                   \-> scaler ->/
1153  */
1154 int komeda_build_wb_split_data_flow(struct komeda_layer *wb_layer,
1155                     struct drm_connector_state *conn_st,
1156                     struct komeda_crtc_state *kcrtc_st,
1157                     struct komeda_data_flow_cfg *dflow)
1158 {
1159     struct komeda_pipeline *pipe = wb_layer->base.pipeline;
1160     struct drm_connector *conn = conn_st->connector;
1161     struct komeda_data_flow_cfg l_dflow, r_dflow;
1162     int err;
1163 
1164     err = komeda_splitter_validate(pipe->splitter, conn_st,
1165                        dflow, &l_dflow, &r_dflow);
1166     if (err)
1167         return err;
1168     err = komeda_scaler_validate(conn, kcrtc_st, &l_dflow);
1169     if (err)
1170         return err;
1171 
1172     err = komeda_scaler_validate(conn, kcrtc_st, &r_dflow);
1173     if (err)
1174         return err;
1175 
1176     err = komeda_merger_validate(pipe->merger, conn_st, kcrtc_st,
1177                      &l_dflow, &r_dflow, dflow);
1178     if (err)
1179         return err;
1180 
1181     return komeda_wb_layer_validate(wb_layer, conn_st, dflow);
1182 }
1183 
1184 /* build display output data flow, the data path is:
1185  * compiz -> improc -> timing_ctrlr
1186  */
1187 int komeda_build_display_data_flow(struct komeda_crtc *kcrtc,
1188                    struct komeda_crtc_state *kcrtc_st)
1189 {
1190     struct komeda_pipeline *master = kcrtc->master;
1191     struct komeda_pipeline *slave  = kcrtc->slave;
1192     struct komeda_data_flow_cfg m_dflow; /* master data flow */
1193     struct komeda_data_flow_cfg s_dflow; /* slave data flow */
1194     int err;
1195 
1196     memset(&m_dflow, 0, sizeof(m_dflow));
1197     memset(&s_dflow, 0, sizeof(s_dflow));
1198 
1199     if (slave && has_bit(slave->id, kcrtc_st->active_pipes)) {
1200         err = komeda_compiz_validate(slave->compiz, kcrtc_st, &s_dflow);
1201         if (err)
1202             return err;
1203 
1204         /* merge the slave dflow into master pipeline */
1205         err = komeda_compiz_set_input(master->compiz, kcrtc_st,
1206                           &s_dflow);
1207         if (err)
1208             return err;
1209     }
1210 
1211     err = komeda_compiz_validate(master->compiz, kcrtc_st, &m_dflow);
1212     if (err)
1213         return err;
1214 
1215     err = komeda_improc_validate(master->improc, kcrtc_st, &m_dflow);
1216     if (err)
1217         return err;
1218 
1219     err = komeda_timing_ctrlr_validate(master->ctrlr, kcrtc_st, &m_dflow);
1220     if (err)
1221         return err;
1222 
1223     return 0;
1224 }
1225 
1226 static void
1227 komeda_pipeline_unbound_components(struct komeda_pipeline *pipe,
1228                    struct komeda_pipeline_state *new)
1229 {
1230     struct drm_atomic_state *drm_st = new->obj.state;
1231     struct komeda_pipeline_state *old = priv_to_pipe_st(pipe->obj.state);
1232     struct komeda_component_state *c_st;
1233     struct komeda_component *c;
1234     u32 id;
1235     unsigned long disabling_comps;
1236 
1237     WARN_ON(!old);
1238 
1239     disabling_comps = (~new->active_comps) & old->active_comps;
1240 
1241     /* unbound all disabling component */
1242     for_each_set_bit(id, &disabling_comps, 32) {
1243         c = komeda_pipeline_get_component(pipe, id);
1244         c_st = komeda_component_get_state_and_set_user(c,
1245                 drm_st, NULL, new->crtc);
1246         WARN_ON(IS_ERR(c_st));
1247     }
1248 }
1249 
1250 /* release unclaimed pipeline resource */
1251 int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
1252                        struct komeda_crtc_state *kcrtc_st)
1253 {
1254     struct drm_atomic_state *drm_st = kcrtc_st->base.state;
1255     struct komeda_pipeline_state *st;
1256 
1257     /* ignore the pipeline which is not affected */
1258     if (!pipe || !has_bit(pipe->id, kcrtc_st->affected_pipes))
1259         return 0;
1260 
1261     if (has_bit(pipe->id, kcrtc_st->active_pipes))
1262         st = komeda_pipeline_get_new_state(pipe, drm_st);
1263     else
1264         st = komeda_pipeline_get_state_and_set_crtc(pipe, drm_st, NULL);
1265 
1266     if (WARN_ON(IS_ERR_OR_NULL(st)))
1267         return -EINVAL;
1268 
1269     komeda_pipeline_unbound_components(pipe, st);
1270 
1271     return 0;
1272 }
1273 
1274 /* Since standalong disabled components must be disabled separately and in the
1275  * last, So a complete disable operation may needs to call pipeline_disable
1276  * twice (two phase disabling).
1277  * Phase 1: disable the common components, flush it.
1278  * Phase 2: disable the standalone disabled components, flush it.
1279  *
1280  * RETURNS:
1281  * true: disable is not complete, needs a phase 2 disable.
1282  * false: disable is complete.
1283  */
1284 bool komeda_pipeline_disable(struct komeda_pipeline *pipe,
1285                  struct drm_atomic_state *old_state)
1286 {
1287     struct komeda_pipeline_state *old;
1288     struct komeda_component *c;
1289     struct komeda_component_state *c_st;
1290     u32 id;
1291     unsigned long disabling_comps;
1292 
1293     old = komeda_pipeline_get_old_state(pipe, old_state);
1294 
1295     disabling_comps = old->active_comps &
1296               (~pipe->standalone_disabled_comps);
1297     if (!disabling_comps)
1298         disabling_comps = old->active_comps &
1299                   pipe->standalone_disabled_comps;
1300 
1301     DRM_DEBUG_ATOMIC("PIPE%d: active_comps: 0x%x, disabling_comps: 0x%lx.\n",
1302              pipe->id, old->active_comps, disabling_comps);
1303 
1304     for_each_set_bit(id, &disabling_comps, 32) {
1305         c = komeda_pipeline_get_component(pipe, id);
1306         c_st = priv_to_comp_st(c->obj.state);
1307 
1308         /*
1309          * If we disabled a component then all active_inputs should be
1310          * put in the list of changed_active_inputs, so they get
1311          * re-enabled.
1312          * This usually happens during a modeset when the pipeline is
1313          * first disabled and then the actual state gets committed
1314          * again.
1315          */
1316         c_st->changed_active_inputs |= c_st->active_inputs;
1317 
1318         c->funcs->disable(c);
1319     }
1320 
1321     /* Update the pipeline state, if there are components that are still
1322      * active, return true for calling the phase 2 disable.
1323      */
1324     old->active_comps &= ~disabling_comps;
1325 
1326     return old->active_comps ? true : false;
1327 }
1328 
1329 void komeda_pipeline_update(struct komeda_pipeline *pipe,
1330                 struct drm_atomic_state *old_state)
1331 {
1332     struct komeda_pipeline_state *new = priv_to_pipe_st(pipe->obj.state);
1333     struct komeda_pipeline_state *old;
1334     struct komeda_component *c;
1335     u32 id;
1336     unsigned long changed_comps;
1337 
1338     old = komeda_pipeline_get_old_state(pipe, old_state);
1339 
1340     changed_comps = new->active_comps | old->active_comps;
1341 
1342     DRM_DEBUG_ATOMIC("PIPE%d: active_comps: 0x%x, changed: 0x%lx.\n",
1343              pipe->id, new->active_comps, changed_comps);
1344 
1345     for_each_set_bit(id, &changed_comps, 32) {
1346         c = komeda_pipeline_get_component(pipe, id);
1347 
1348         if (new->active_comps & BIT(c->id))
1349             c->funcs->update(c, priv_to_comp_st(c->obj.state));
1350         else
1351             c->funcs->disable(c);
1352     }
1353 }