]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
drm/komeda: Rename main engine clk name "mclk" to "aclk"
[linux.git] / drivers / gpu / drm / arm / display / komeda / komeda_pipeline_state.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) COPYRIGHT 2018 ARM Limited. All rights reserved.
4  * Author: James.Qian.Wang <james.qian.wang@arm.com>
5  *
6  */
7
8 #include <drm/drm_print.h>
9 #include <linux/clk.h>
10 #include "komeda_dev.h"
11 #include "komeda_kms.h"
12 #include "komeda_pipeline.h"
13 #include "komeda_framebuffer.h"
14
15 static inline bool is_switching_user(void *old, void *new)
16 {
17         if (!old || !new)
18                 return false;
19
20         return old != new;
21 }
22
23 static struct komeda_pipeline_state *
24 komeda_pipeline_get_state(struct komeda_pipeline *pipe,
25                           struct drm_atomic_state *state)
26 {
27         struct drm_private_state *priv_st;
28
29         priv_st = drm_atomic_get_private_obj_state(state, &pipe->obj);
30         if (IS_ERR(priv_st))
31                 return ERR_CAST(priv_st);
32
33         return priv_to_pipe_st(priv_st);
34 }
35
36 struct komeda_pipeline_state *
37 komeda_pipeline_get_old_state(struct komeda_pipeline *pipe,
38                               struct drm_atomic_state *state)
39 {
40         struct drm_private_state *priv_st;
41
42         priv_st = drm_atomic_get_old_private_obj_state(state, &pipe->obj);
43         if (priv_st)
44                 return priv_to_pipe_st(priv_st);
45         return NULL;
46 }
47
48 static struct komeda_pipeline_state *
49 komeda_pipeline_get_new_state(struct komeda_pipeline *pipe,
50                               struct drm_atomic_state *state)
51 {
52         struct drm_private_state *priv_st;
53
54         priv_st = drm_atomic_get_new_private_obj_state(state, &pipe->obj);
55         if (priv_st)
56                 return priv_to_pipe_st(priv_st);
57         return NULL;
58 }
59
60 /* Assign pipeline for crtc */
61 static struct komeda_pipeline_state *
62 komeda_pipeline_get_state_and_set_crtc(struct komeda_pipeline *pipe,
63                                        struct drm_atomic_state *state,
64                                        struct drm_crtc *crtc)
65 {
66         struct komeda_pipeline_state *st;
67
68         st = komeda_pipeline_get_state(pipe, state);
69         if (IS_ERR(st))
70                 return st;
71
72         if (is_switching_user(crtc, st->crtc)) {
73                 DRM_DEBUG_ATOMIC("CRTC%d required pipeline%d is busy.\n",
74                                  drm_crtc_index(crtc), pipe->id);
75                 return ERR_PTR(-EBUSY);
76         }
77
78         /* pipeline only can be disabled when the it is free or unused */
79         if (!crtc && st->active_comps) {
80                 DRM_DEBUG_ATOMIC("Disabling a busy pipeline:%d.\n", pipe->id);
81                 return ERR_PTR(-EBUSY);
82         }
83
84         st->crtc = crtc;
85
86         if (crtc) {
87                 struct komeda_crtc_state *kcrtc_st;
88
89                 kcrtc_st = to_kcrtc_st(drm_atomic_get_new_crtc_state(state,
90                                                                      crtc));
91
92                 kcrtc_st->active_pipes |= BIT(pipe->id);
93                 kcrtc_st->affected_pipes |= BIT(pipe->id);
94         }
95         return st;
96 }
97
98 static struct komeda_component_state *
99 komeda_component_get_state(struct komeda_component *c,
100                            struct drm_atomic_state *state)
101 {
102         struct drm_private_state *priv_st;
103
104         WARN_ON(!drm_modeset_is_locked(&c->pipeline->obj.lock));
105
106         priv_st = drm_atomic_get_private_obj_state(state, &c->obj);
107         if (IS_ERR(priv_st))
108                 return ERR_CAST(priv_st);
109
110         return priv_to_comp_st(priv_st);
111 }
112
113 static struct komeda_component_state *
114 komeda_component_get_old_state(struct komeda_component *c,
115                                struct drm_atomic_state *state)
116 {
117         struct drm_private_state *priv_st;
118
119         priv_st = drm_atomic_get_old_private_obj_state(state, &c->obj);
120         if (priv_st)
121                 return priv_to_comp_st(priv_st);
122         return NULL;
123 }
124
125 /**
126  * komeda_component_get_state_and_set_user()
127  *
128  * @c: component to get state and set user
129  * @state: global atomic state
130  * @user: direct user, the binding user
131  * @crtc: the CRTC user, the big boss :)
132  *
133  * This function accepts two users:
134  * -   The direct user: can be plane/crtc/wb_connector depends on component
135  * -   The big boss (CRTC)
136  * CRTC is the big boss (the final user), because all component resources
137  * eventually will be assigned to CRTC, like the layer will be binding to
138  * kms_plane, but kms plane will be binding to a CRTC eventually.
139  *
140  * The big boss (CRTC) is for pipeline assignment, since &komeda_component isn't
141  * independent and can be assigned to CRTC freely, but belongs to a specific
142  * pipeline, only pipeline can be shared between crtc, and pipeline as a whole
143  * (include all the internal components) assigned to a specific CRTC.
144  *
145  * So when set a user to komeda_component, need first to check the status of
146  * component->pipeline to see if the pipeline is available on this specific
147  * CRTC. if the pipeline is busy (assigned to another CRTC), even the required
148  * component is free, the component still cannot be assigned to the direct user.
149  */
150 static struct komeda_component_state *
151 komeda_component_get_state_and_set_user(struct komeda_component *c,
152                                         struct drm_atomic_state *state,
153                                         void *user,
154                                         struct drm_crtc *crtc)
155 {
156         struct komeda_pipeline_state *pipe_st;
157         struct komeda_component_state *st;
158
159         /* First check if the pipeline is available */
160         pipe_st = komeda_pipeline_get_state_and_set_crtc(c->pipeline,
161                                                          state, crtc);
162         if (IS_ERR(pipe_st))
163                 return ERR_CAST(pipe_st);
164
165         st = komeda_component_get_state(c, state);
166         if (IS_ERR(st))
167                 return st;
168
169         /* check if the component has been occupied */
170         if (is_switching_user(user, st->binding_user)) {
171                 DRM_DEBUG_ATOMIC("required %s is busy.\n", c->name);
172                 return ERR_PTR(-EBUSY);
173         }
174
175         st->binding_user = user;
176         /* mark the component as active if user is valid */
177         if (st->binding_user)
178                 pipe_st->active_comps |= BIT(c->id);
179
180         return st;
181 }
182
183 static void
184 komeda_component_add_input(struct komeda_component_state *state,
185                            struct komeda_component_output *input,
186                            int idx)
187 {
188         struct komeda_component *c = state->component;
189
190         WARN_ON((idx < 0 || idx >= c->max_active_inputs));
191
192         /* since the inputs[i] is only valid when it is active. So if a input[i]
193          * is a newly enabled input which switches from disable to enable, then
194          * the old inputs[i] is undefined (NOT zeroed), we can not rely on
195          * memcmp, but directly mark it changed
196          */
197         if (!has_bit(idx, state->affected_inputs) ||
198             memcmp(&state->inputs[idx], input, sizeof(*input))) {
199                 memcpy(&state->inputs[idx], input, sizeof(*input));
200                 state->changed_active_inputs |= BIT(idx);
201         }
202         state->active_inputs |= BIT(idx);
203         state->affected_inputs |= BIT(idx);
204 }
205
206 static int
207 komeda_component_check_input(struct komeda_component_state *state,
208                              struct komeda_component_output *input,
209                              int idx)
210 {
211         struct komeda_component *c = state->component;
212
213         if ((idx < 0) || (idx >= c->max_active_inputs)) {
214                 DRM_DEBUG_ATOMIC("%s invalid input id: %d.\n", c->name, idx);
215                 return -EINVAL;
216         }
217
218         if (has_bit(idx, state->active_inputs)) {
219                 DRM_DEBUG_ATOMIC("%s required input_id: %d has been occupied already.\n",
220                                  c->name, idx);
221                 return -EINVAL;
222         }
223
224         return 0;
225 }
226
227 static void
228 komeda_component_set_output(struct komeda_component_output *output,
229                             struct komeda_component *comp,
230                             u8 output_port)
231 {
232         output->component = comp;
233         output->output_port = output_port;
234 }
235
236 static int
237 komeda_component_validate_private(struct komeda_component *c,
238                                   struct komeda_component_state *st)
239 {
240         int err;
241
242         if (!c->funcs->validate)
243                 return 0;
244
245         err = c->funcs->validate(c, st);
246         if (err)
247                 DRM_DEBUG_ATOMIC("%s validate private failed.\n", c->name);
248
249         return err;
250 }
251
252 /* Get current available scaler from the component->supported_outputs */
253 static struct komeda_scaler *
254 komeda_component_get_avail_scaler(struct komeda_component *c,
255                                   struct drm_atomic_state *state)
256 {
257         struct komeda_pipeline_state *pipe_st;
258         u32 avail_scalers;
259
260         pipe_st = komeda_pipeline_get_state(c->pipeline, state);
261         if (!pipe_st)
262                 return NULL;
263
264         avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
265                         KOMEDA_PIPELINE_SCALERS;
266
267         c = komeda_component_pickup_output(c, avail_scalers);
268
269         return to_scaler(c);
270 }
271
272 static int
273 komeda_layer_check_cfg(struct komeda_layer *layer,
274                        struct komeda_fb *kfb,
275                        struct komeda_data_flow_cfg *dflow)
276 {
277         u32 hsize_in, vsize_in;
278
279         if (!komeda_fb_is_layer_supported(kfb, layer->layer_type, dflow->rot))
280                 return -EINVAL;
281
282         if (komeda_fb_check_src_coords(kfb, dflow->in_x, dflow->in_y,
283                                        dflow->in_w, dflow->in_h))
284                 return -EINVAL;
285
286         if (layer->base.id == KOMEDA_COMPONENT_WB_LAYER) {
287                 hsize_in = dflow->out_w;
288                 vsize_in = dflow->out_h;
289         } else {
290                 hsize_in = dflow->in_w;
291                 vsize_in = dflow->in_h;
292         }
293
294         if (!in_range(&layer->hsize_in, hsize_in)) {
295                 DRM_DEBUG_ATOMIC("invalidate src_w %d.\n", hsize_in);
296                 return -EINVAL;
297         }
298
299         if (!in_range(&layer->vsize_in, vsize_in)) {
300                 DRM_DEBUG_ATOMIC("invalidate src_h %d.\n", vsize_in);
301                 return -EINVAL;
302         }
303
304         return 0;
305 }
306
307 static int
308 komeda_layer_validate(struct komeda_layer *layer,
309                       struct komeda_plane_state *kplane_st,
310                       struct komeda_data_flow_cfg *dflow)
311 {
312         struct drm_plane_state *plane_st = &kplane_st->base;
313         struct drm_framebuffer *fb = plane_st->fb;
314         struct komeda_fb *kfb = to_kfb(fb);
315         struct komeda_component_state *c_st;
316         struct komeda_layer_state *st;
317         int i, err;
318
319         err = komeda_layer_check_cfg(layer, kfb, dflow);
320         if (err)
321                 return err;
322
323         c_st = komeda_component_get_state_and_set_user(&layer->base,
324                         plane_st->state, plane_st->plane, plane_st->crtc);
325         if (IS_ERR(c_st))
326                 return PTR_ERR(c_st);
327
328         st = to_layer_st(c_st);
329
330         st->rot = dflow->rot;
331
332         if (fb->modifier) {
333                 st->hsize = kfb->aligned_w;
334                 st->vsize = kfb->aligned_h;
335                 st->afbc_crop_l = dflow->in_x;
336                 st->afbc_crop_r = kfb->aligned_w - dflow->in_x - dflow->in_w;
337                 st->afbc_crop_t = dflow->in_y;
338                 st->afbc_crop_b = kfb->aligned_h - dflow->in_y - dflow->in_h;
339         } else {
340                 st->hsize = dflow->in_w;
341                 st->vsize = dflow->in_h;
342                 st->afbc_crop_l = 0;
343                 st->afbc_crop_r = 0;
344                 st->afbc_crop_t = 0;
345                 st->afbc_crop_b = 0;
346         }
347
348         for (i = 0; i < fb->format->num_planes; i++)
349                 st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->in_x,
350                                                        dflow->in_y, i);
351
352         err = komeda_component_validate_private(&layer->base, c_st);
353         if (err)
354                 return err;
355
356         /* update the data flow for the next stage */
357         komeda_component_set_output(&dflow->input, &layer->base, 0);
358
359         /*
360          * The rotation has been handled by layer, so adjusted the data flow for
361          * the next stage.
362          */
363         if (drm_rotation_90_or_270(st->rot))
364                 swap(dflow->in_h, dflow->in_w);
365
366         return 0;
367 }
368
369 static int
370 komeda_wb_layer_validate(struct komeda_layer *wb_layer,
371                          struct drm_connector_state *conn_st,
372                          struct komeda_data_flow_cfg *dflow)
373 {
374         struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
375         struct komeda_component_state *c_st;
376         struct komeda_layer_state *st;
377         int i, err;
378
379         err = komeda_layer_check_cfg(wb_layer, kfb, dflow);
380         if (err)
381                 return err;
382
383         c_st = komeda_component_get_state_and_set_user(&wb_layer->base,
384                         conn_st->state, conn_st->connector, conn_st->crtc);
385         if (IS_ERR(c_st))
386                 return PTR_ERR(c_st);
387
388         st = to_layer_st(c_st);
389
390         st->hsize = dflow->out_w;
391         st->vsize = dflow->out_h;
392
393         for (i = 0; i < kfb->base.format->num_planes; i++)
394                 st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->out_x,
395                                                        dflow->out_y, i);
396
397         komeda_component_add_input(&st->base, &dflow->input, 0);
398         komeda_component_set_output(&dflow->input, &wb_layer->base, 0);
399
400         return 0;
401 }
402
403 static bool scaling_ratio_valid(u32 size_in, u32 size_out,
404                                 u32 max_upscaling, u32 max_downscaling)
405 {
406         if (size_out > size_in * max_upscaling)
407                 return false;
408         else if (size_in > size_out * max_downscaling)
409                 return false;
410         return true;
411 }
412
413 static int
414 komeda_scaler_check_cfg(struct komeda_scaler *scaler,
415                         struct komeda_crtc_state *kcrtc_st,
416                         struct komeda_data_flow_cfg *dflow)
417 {
418         u32 hsize_in, vsize_in, hsize_out, vsize_out;
419         u32 max_upscaling;
420
421         hsize_in = dflow->in_w;
422         vsize_in = dflow->in_h;
423         hsize_out = dflow->out_w;
424         vsize_out = dflow->out_h;
425
426         if (!in_range(&scaler->hsize, hsize_in) ||
427             !in_range(&scaler->hsize, hsize_out)) {
428                 DRM_DEBUG_ATOMIC("Invalid horizontal sizes");
429                 return -EINVAL;
430         }
431
432         if (!in_range(&scaler->vsize, vsize_in) ||
433             !in_range(&scaler->vsize, vsize_out)) {
434                 DRM_DEBUG_ATOMIC("Invalid vertical sizes");
435                 return -EINVAL;
436         }
437
438         /* If input comes from compiz that means the scaling is for writeback
439          * and scaler can not do upscaling for writeback
440          */
441         if (has_bit(dflow->input.component->id, KOMEDA_PIPELINE_COMPIZS))
442                 max_upscaling = 1;
443         else
444                 max_upscaling = scaler->max_upscaling;
445
446         if (!scaling_ratio_valid(hsize_in, hsize_out, max_upscaling,
447                                  scaler->max_downscaling)) {
448                 DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
449                 return -EINVAL;
450         }
451
452         if (!scaling_ratio_valid(vsize_in, vsize_out, max_upscaling,
453                                  scaler->max_downscaling)) {
454                 DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
455                 return -EINVAL;
456         }
457
458         if (hsize_in > hsize_out || vsize_in > vsize_out) {
459                 struct komeda_pipeline *pipe = scaler->base.pipeline;
460                 int err;
461
462                 err = pipe->funcs->downscaling_clk_check(pipe,
463                                         &kcrtc_st->base.adjusted_mode,
464                                         komeda_calc_aclk(kcrtc_st), dflow);
465                 if (err) {
466                         DRM_DEBUG_ATOMIC("aclk can't satisfy the clock requirement of the downscaling\n");
467                         return err;
468                 }
469         }
470
471         return 0;
472 }
473
474 static int
475 komeda_scaler_validate(void *user,
476                        struct komeda_crtc_state *kcrtc_st,
477                        struct komeda_data_flow_cfg *dflow)
478 {
479         struct drm_atomic_state *drm_st = kcrtc_st->base.state;
480         struct komeda_component_state *c_st;
481         struct komeda_scaler_state *st;
482         struct komeda_scaler *scaler;
483         int err = 0;
484
485         if (!(dflow->en_scaling || dflow->en_img_enhancement))
486                 return 0;
487
488         scaler = komeda_component_get_avail_scaler(dflow->input.component,
489                                                    drm_st);
490         if (!scaler) {
491                 DRM_DEBUG_ATOMIC("No scaler available");
492                 return -EINVAL;
493         }
494
495         err = komeda_scaler_check_cfg(scaler, kcrtc_st, dflow);
496         if (err)
497                 return err;
498
499         c_st = komeda_component_get_state_and_set_user(&scaler->base,
500                         drm_st, user, kcrtc_st->base.crtc);
501         if (IS_ERR(c_st))
502                 return PTR_ERR(c_st);
503
504         st = to_scaler_st(c_st);
505
506         st->hsize_in = dflow->in_w;
507         st->vsize_in = dflow->in_h;
508         st->hsize_out = dflow->out_w;
509         st->vsize_out = dflow->out_h;
510
511         /* Enable alpha processing if the next stage needs the pixel alpha */
512         st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
513         st->en_scaling = dflow->en_scaling;
514         st->en_img_enhancement = dflow->en_img_enhancement;
515
516         komeda_component_add_input(&st->base, &dflow->input, 0);
517         komeda_component_set_output(&dflow->input, &scaler->base, 0);
518         return err;
519 }
520
521 void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
522                                u16 *hsize, u16 *vsize)
523 {
524         struct drm_display_mode *m = &kcrtc_st->base.adjusted_mode;
525
526         if (hsize)
527                 *hsize = m->hdisplay;
528         if (vsize)
529                 *vsize = m->vdisplay;
530 }
531
532 static int
533 komeda_compiz_set_input(struct komeda_compiz *compiz,
534                         struct komeda_crtc_state *kcrtc_st,
535                         struct komeda_data_flow_cfg *dflow)
536 {
537         struct drm_atomic_state *drm_st = kcrtc_st->base.state;
538         struct komeda_component_state *c_st, *old_st;
539         struct komeda_compiz_input_cfg *cin;
540         u16 compiz_w, compiz_h;
541         int idx = dflow->blending_zorder;
542
543         pipeline_composition_size(kcrtc_st, &compiz_w, &compiz_h);
544         /* check display rect */
545         if ((dflow->out_x + dflow->out_w > compiz_w) ||
546             (dflow->out_y + dflow->out_h > compiz_h) ||
547              dflow->out_w == 0 || dflow->out_h == 0) {
548                 DRM_DEBUG_ATOMIC("invalid disp rect [x=%d, y=%d, w=%d, h=%d]\n",
549                                  dflow->out_x, dflow->out_y,
550                                  dflow->out_w, dflow->out_h);
551                 return -EINVAL;
552         }
553
554         c_st = komeda_component_get_state_and_set_user(&compiz->base, drm_st,
555                         kcrtc_st->base.crtc, kcrtc_st->base.crtc);
556         if (IS_ERR(c_st))
557                 return PTR_ERR(c_st);
558
559         if (komeda_component_check_input(c_st, &dflow->input, idx))
560                 return -EINVAL;
561
562         cin = &(to_compiz_st(c_st)->cins[idx]);
563
564         cin->hsize   = dflow->out_w;
565         cin->vsize   = dflow->out_h;
566         cin->hoffset = dflow->out_x;
567         cin->voffset = dflow->out_y;
568         cin->pixel_blend_mode = dflow->pixel_blend_mode;
569         cin->layer_alpha = dflow->layer_alpha;
570
571         old_st = komeda_component_get_old_state(&compiz->base, drm_st);
572         WARN_ON(!old_st);
573
574         /* compare with old to check if this input has been changed */
575         if (memcmp(&(to_compiz_st(old_st)->cins[idx]), cin, sizeof(*cin)))
576                 c_st->changed_active_inputs |= BIT(idx);
577
578         komeda_component_add_input(c_st, &dflow->input, idx);
579
580         return 0;
581 }
582
583 static int
584 komeda_compiz_validate(struct komeda_compiz *compiz,
585                        struct komeda_crtc_state *state,
586                        struct komeda_data_flow_cfg *dflow)
587 {
588         struct komeda_component_state *c_st;
589         struct komeda_compiz_state *st;
590
591         c_st = komeda_component_get_state_and_set_user(&compiz->base,
592                         state->base.state, state->base.crtc, state->base.crtc);
593         if (IS_ERR(c_st))
594                 return PTR_ERR(c_st);
595
596         st = to_compiz_st(c_st);
597
598         pipeline_composition_size(state, &st->hsize, &st->vsize);
599
600         komeda_component_set_output(&dflow->input, &compiz->base, 0);
601
602         /* compiz output dflow will be fed to the next pipeline stage, prepare
603          * the data flow configuration for the next stage
604          */
605         if (dflow) {
606                 dflow->in_w = st->hsize;
607                 dflow->in_h = st->vsize;
608                 dflow->out_w = dflow->in_w;
609                 dflow->out_h = dflow->in_h;
610                 /* the output data of compiz doesn't have alpha, it only can be
611                  * used as bottom layer when blend it with master layers
612                  */
613                 dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
614                 dflow->layer_alpha = 0xFF;
615                 dflow->blending_zorder = 0;
616         }
617
618         return 0;
619 }
620
621 static int
622 komeda_improc_validate(struct komeda_improc *improc,
623                        struct komeda_crtc_state *kcrtc_st,
624                        struct komeda_data_flow_cfg *dflow)
625 {
626         struct drm_crtc *crtc = kcrtc_st->base.crtc;
627         struct komeda_component_state *c_st;
628         struct komeda_improc_state *st;
629
630         c_st = komeda_component_get_state_and_set_user(&improc->base,
631                         kcrtc_st->base.state, crtc, crtc);
632         if (IS_ERR(c_st))
633                 return PTR_ERR(c_st);
634
635         st = to_improc_st(c_st);
636
637         st->hsize = dflow->in_w;
638         st->vsize = dflow->in_h;
639
640         komeda_component_add_input(&st->base, &dflow->input, 0);
641         komeda_component_set_output(&dflow->input, &improc->base, 0);
642
643         return 0;
644 }
645
646 static int
647 komeda_timing_ctrlr_validate(struct komeda_timing_ctrlr *ctrlr,
648                              struct komeda_crtc_state *kcrtc_st,
649                              struct komeda_data_flow_cfg *dflow)
650 {
651         struct drm_crtc *crtc = kcrtc_st->base.crtc;
652         struct komeda_timing_ctrlr_state *st;
653         struct komeda_component_state *c_st;
654
655         c_st = komeda_component_get_state_and_set_user(&ctrlr->base,
656                         kcrtc_st->base.state, crtc, crtc);
657         if (IS_ERR(c_st))
658                 return PTR_ERR(c_st);
659
660         st = to_ctrlr_st(c_st);
661
662         komeda_component_add_input(&st->base, &dflow->input, 0);
663         komeda_component_set_output(&dflow->input, &ctrlr->base, 0);
664
665         return 0;
666 }
667
668 void komeda_complete_data_flow_cfg(struct komeda_data_flow_cfg *dflow)
669 {
670         u32 w = dflow->in_w;
671         u32 h = dflow->in_h;
672
673         if (drm_rotation_90_or_270(dflow->rot))
674                 swap(w, h);
675
676         dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
677 }
678
679 int komeda_build_layer_data_flow(struct komeda_layer *layer,
680                                  struct komeda_plane_state *kplane_st,
681                                  struct komeda_crtc_state *kcrtc_st,
682                                  struct komeda_data_flow_cfg *dflow)
683 {
684         struct drm_plane *plane = kplane_st->base.plane;
685         struct komeda_pipeline *pipe = layer->base.pipeline;
686         int err;
687
688         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]",
689                          layer->base.name, plane->base.id, plane->name,
690                          dflow->in_x, dflow->in_y, dflow->in_w, dflow->in_h,
691                          dflow->out_x, dflow->out_y, dflow->out_w, dflow->out_h);
692
693         err = komeda_layer_validate(layer, kplane_st, dflow);
694         if (err)
695                 return err;
696
697         err = komeda_scaler_validate(plane, kcrtc_st, dflow);
698         if (err)
699                 return err;
700
701         err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
702
703         return err;
704 }
705
706 /* writeback data path: compiz -> scaler -> wb_layer -> memory */
707 int komeda_build_wb_data_flow(struct komeda_layer *wb_layer,
708                               struct drm_connector_state *conn_st,
709                               struct komeda_crtc_state *kcrtc_st,
710                               struct komeda_data_flow_cfg *dflow)
711 {
712         struct drm_connector *conn = conn_st->connector;
713         int err;
714
715         err = komeda_scaler_validate(conn, kcrtc_st, dflow);
716         if (err)
717                 return err;
718
719         return komeda_wb_layer_validate(wb_layer, conn_st, dflow);
720 }
721
722 /* build display output data flow, the data path is:
723  * compiz -> improc -> timing_ctrlr
724  */
725 int komeda_build_display_data_flow(struct komeda_crtc *kcrtc,
726                                    struct komeda_crtc_state *kcrtc_st)
727 {
728         struct komeda_pipeline *master = kcrtc->master;
729         struct komeda_data_flow_cfg m_dflow; /* master data flow */
730         int err;
731
732         memset(&m_dflow, 0, sizeof(m_dflow));
733
734         err = komeda_compiz_validate(master->compiz, kcrtc_st, &m_dflow);
735         if (err)
736                 return err;
737
738         err = komeda_improc_validate(master->improc, kcrtc_st, &m_dflow);
739         if (err)
740                 return err;
741
742         err = komeda_timing_ctrlr_validate(master->ctrlr, kcrtc_st, &m_dflow);
743         if (err)
744                 return err;
745
746         return 0;
747 }
748
749 static void
750 komeda_pipeline_unbound_components(struct komeda_pipeline *pipe,
751                                    struct komeda_pipeline_state *new)
752 {
753         struct drm_atomic_state *drm_st = new->obj.state;
754         struct komeda_pipeline_state *old = priv_to_pipe_st(pipe->obj.state);
755         struct komeda_component_state *c_st;
756         struct komeda_component *c;
757         u32 disabling_comps, id;
758
759         WARN_ON(!old);
760
761         disabling_comps = (~new->active_comps) & old->active_comps;
762
763         /* unbound all disabling component */
764         dp_for_each_set_bit(id, disabling_comps) {
765                 c = komeda_pipeline_get_component(pipe, id);
766                 c_st = komeda_component_get_state_and_set_user(c,
767                                 drm_st, NULL, new->crtc);
768                 WARN_ON(IS_ERR(c_st));
769         }
770 }
771
772 /* release unclaimed pipeline resource */
773 int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
774                                        struct komeda_crtc_state *kcrtc_st)
775 {
776         struct drm_atomic_state *drm_st = kcrtc_st->base.state;
777         struct komeda_pipeline_state *st;
778
779         /* ignore the pipeline which is not affected */
780         if (!pipe || !has_bit(pipe->id, kcrtc_st->affected_pipes))
781                 return 0;
782
783         if (has_bit(pipe->id, kcrtc_st->active_pipes))
784                 st = komeda_pipeline_get_new_state(pipe, drm_st);
785         else
786                 st = komeda_pipeline_get_state_and_set_crtc(pipe, drm_st, NULL);
787
788         if (WARN_ON(IS_ERR_OR_NULL(st)))
789                 return -EINVAL;
790
791         komeda_pipeline_unbound_components(pipe, st);
792
793         return 0;
794 }
795
796 void komeda_pipeline_disable(struct komeda_pipeline *pipe,
797                              struct drm_atomic_state *old_state)
798 {
799         struct komeda_pipeline_state *old;
800         struct komeda_component *c;
801         struct komeda_component_state *c_st;
802         u32 id, disabling_comps = 0;
803
804         old = komeda_pipeline_get_old_state(pipe, old_state);
805
806         disabling_comps = old->active_comps;
807         DRM_DEBUG_ATOMIC("PIPE%d: disabling_comps: 0x%x.\n",
808                          pipe->id, disabling_comps);
809
810         dp_for_each_set_bit(id, disabling_comps) {
811                 c = komeda_pipeline_get_component(pipe, id);
812                 c_st = priv_to_comp_st(c->obj.state);
813
814                 /*
815                  * If we disabled a component then all active_inputs should be
816                  * put in the list of changed_active_inputs, so they get
817                  * re-enabled.
818                  * This usually happens during a modeset when the pipeline is
819                  * first disabled and then the actual state gets committed
820                  * again.
821                  */
822                 c_st->changed_active_inputs |= c_st->active_inputs;
823
824                 c->funcs->disable(c);
825         }
826 }
827
828 void komeda_pipeline_update(struct komeda_pipeline *pipe,
829                             struct drm_atomic_state *old_state)
830 {
831         struct komeda_pipeline_state *new = priv_to_pipe_st(pipe->obj.state);
832         struct komeda_pipeline_state *old;
833         struct komeda_component *c;
834         u32 id, changed_comps = 0;
835
836         old = komeda_pipeline_get_old_state(pipe, old_state);
837
838         changed_comps = new->active_comps | old->active_comps;
839
840         DRM_DEBUG_ATOMIC("PIPE%d: active_comps: 0x%x, changed: 0x%x.\n",
841                          pipe->id, new->active_comps, changed_comps);
842
843         dp_for_each_set_bit(id, changed_comps) {
844                 c = komeda_pipeline_get_component(pipe, id);
845
846                 if (new->active_comps & BIT(c->id))
847                         c->funcs->update(c, priv_to_comp_st(c->obj.state));
848                 else
849                         c->funcs->disable(c);
850         }
851 }