1
2
3
4
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
15static inline bool is_switching_user(void *old, void *new)
16{
17 if (!old || !new)
18 return false;
19
20 return old != new;
21}
22
23static struct komeda_pipeline_state *
24komeda_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
36struct komeda_pipeline_state *
37komeda_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
48static struct komeda_pipeline_state *
49komeda_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
61static struct komeda_pipeline_state *
62komeda_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
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
98static struct komeda_component_state *
99komeda_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
113static struct komeda_component_state *
114komeda_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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150static struct komeda_component_state *
151komeda_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
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
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
177 if (st->binding_user)
178 pipe_st->active_comps |= BIT(c->id);
179
180 return st;
181}
182
183static void
184komeda_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
193
194
195
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
206static int
207komeda_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 required an invalid %s-input[%d].\n",
215 input->component->name, c->name, idx);
216 return -EINVAL;
217 }
218
219 if (has_bit(idx, state->active_inputs)) {
220 DRM_DEBUG_ATOMIC("%s required %s-input[%d] has been occupied already.\n",
221 input->component->name, c->name, idx);
222 return -EINVAL;
223 }
224
225 return 0;
226}
227
228static void
229komeda_component_set_output(struct komeda_component_output *output,
230 struct komeda_component *comp,
231 u8 output_port)
232{
233 output->component = comp;
234 output->output_port = output_port;
235}
236
237static int
238komeda_component_validate_private(struct komeda_component *c,
239 struct komeda_component_state *st)
240{
241 int err;
242
243 if (!c->funcs->validate)
244 return 0;
245
246 err = c->funcs->validate(c, st);
247 if (err)
248 DRM_DEBUG_ATOMIC("%s validate private failed.\n", c->name);
249
250 return err;
251}
252
253
254static struct komeda_scaler *
255komeda_component_get_avail_scaler(struct komeda_component *c,
256 struct drm_atomic_state *state)
257{
258 struct komeda_pipeline_state *pipe_st;
259 u32 avail_scalers;
260
261 pipe_st = komeda_pipeline_get_state(c->pipeline, state);
262 if (!pipe_st)
263 return NULL;
264
265 avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
266 KOMEDA_PIPELINE_SCALERS;
267
268 c = komeda_component_pickup_output(c, avail_scalers);
269
270 return to_scaler(c);
271}
272
273static void
274komeda_rotate_data_flow(struct komeda_data_flow_cfg *dflow, u32 rot)
275{
276 if (drm_rotation_90_or_270(rot)) {
277 swap(dflow->in_h, dflow->in_w);
278 swap(dflow->total_in_h, dflow->total_in_w);
279 }
280}
281
282static int
283komeda_layer_check_cfg(struct komeda_layer *layer,
284 struct komeda_fb *kfb,
285 struct komeda_data_flow_cfg *dflow)
286{
287 u32 src_x, src_y, src_w, src_h;
288 u32 line_sz, max_line_sz;
289
290 if (!komeda_fb_is_layer_supported(kfb, layer->layer_type, dflow->rot))
291 return -EINVAL;
292
293 if (layer->base.id == KOMEDA_COMPONENT_WB_LAYER) {
294 src_x = dflow->out_x;
295 src_y = dflow->out_y;
296 src_w = dflow->out_w;
297 src_h = dflow->out_h;
298 } else {
299 src_x = dflow->in_x;
300 src_y = dflow->in_y;
301 src_w = dflow->in_w;
302 src_h = dflow->in_h;
303 }
304
305 if (komeda_fb_check_src_coords(kfb, src_x, src_y, src_w, src_h))
306 return -EINVAL;
307
308 if (!in_range(&layer->hsize_in, src_w)) {
309 DRM_DEBUG_ATOMIC("invalidate src_w %d.\n", src_w);
310 return -EINVAL;
311 }
312
313 if (!in_range(&layer->vsize_in, src_h)) {
314 DRM_DEBUG_ATOMIC("invalidate src_h %d.\n", src_h);
315 return -EINVAL;
316 }
317
318 if (drm_rotation_90_or_270(dflow->rot))
319 line_sz = dflow->in_h;
320 else
321 line_sz = dflow->in_w;
322
323 if (kfb->base.format->hsub > 1)
324 max_line_sz = layer->yuv_line_sz;
325 else
326 max_line_sz = layer->line_sz;
327
328 if (line_sz > max_line_sz) {
329 DRM_DEBUG_ATOMIC("Required line_sz: %d exceeds the max size %d\n",
330 line_sz, max_line_sz);
331 return -EINVAL;
332 }
333
334 return 0;
335}
336
337static int
338komeda_layer_validate(struct komeda_layer *layer,
339 struct komeda_plane_state *kplane_st,
340 struct komeda_data_flow_cfg *dflow)
341{
342 struct drm_plane_state *plane_st = &kplane_st->base;
343 struct drm_framebuffer *fb = plane_st->fb;
344 struct komeda_fb *kfb = to_kfb(fb);
345 struct komeda_component_state *c_st;
346 struct komeda_layer_state *st;
347 int i, err;
348
349 err = komeda_layer_check_cfg(layer, kfb, dflow);
350 if (err)
351 return err;
352
353 c_st = komeda_component_get_state_and_set_user(&layer->base,
354 plane_st->state, plane_st->plane, plane_st->crtc);
355 if (IS_ERR(c_st))
356 return PTR_ERR(c_st);
357
358 st = to_layer_st(c_st);
359
360 st->rot = dflow->rot;
361
362 if (fb->modifier) {
363 st->hsize = kfb->aligned_w;
364 st->vsize = kfb->aligned_h;
365 st->afbc_crop_l = dflow->in_x;
366 st->afbc_crop_r = kfb->aligned_w - dflow->in_x - dflow->in_w;
367 st->afbc_crop_t = dflow->in_y;
368 st->afbc_crop_b = kfb->aligned_h - dflow->in_y - dflow->in_h;
369 } else {
370 st->hsize = dflow->in_w;
371 st->vsize = dflow->in_h;
372 st->afbc_crop_l = 0;
373 st->afbc_crop_r = 0;
374 st->afbc_crop_t = 0;
375 st->afbc_crop_b = 0;
376 }
377
378 for (i = 0; i < fb->format->num_planes; i++)
379 st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->in_x,
380 dflow->in_y, i);
381
382 err = komeda_component_validate_private(&layer->base, c_st);
383 if (err)
384 return err;
385
386
387 komeda_component_set_output(&dflow->input, &layer->base, 0);
388
389
390
391
392
393 komeda_rotate_data_flow(dflow, st->rot);
394
395 return 0;
396}
397
398static int
399komeda_wb_layer_validate(struct komeda_layer *wb_layer,
400 struct drm_connector_state *conn_st,
401 struct komeda_data_flow_cfg *dflow)
402{
403 struct komeda_fb *kfb = to_kfb(conn_st->writeback_job->fb);
404 struct komeda_component_state *c_st;
405 struct komeda_layer_state *st;
406 int i, err;
407
408 err = komeda_layer_check_cfg(wb_layer, kfb, dflow);
409 if (err)
410 return err;
411
412 c_st = komeda_component_get_state_and_set_user(&wb_layer->base,
413 conn_st->state, conn_st->connector, conn_st->crtc);
414 if (IS_ERR(c_st))
415 return PTR_ERR(c_st);
416
417 st = to_layer_st(c_st);
418
419 st->hsize = dflow->out_w;
420 st->vsize = dflow->out_h;
421
422 for (i = 0; i < kfb->base.format->num_planes; i++)
423 st->addr[i] = komeda_fb_get_pixel_addr(kfb, dflow->out_x,
424 dflow->out_y, i);
425
426 komeda_component_add_input(&st->base, &dflow->input, 0);
427 komeda_component_set_output(&dflow->input, &wb_layer->base, 0);
428
429 return 0;
430}
431
432static bool scaling_ratio_valid(u32 size_in, u32 size_out,
433 u32 max_upscaling, u32 max_downscaling)
434{
435 if (size_out > size_in * max_upscaling)
436 return false;
437 else if (size_in > size_out * max_downscaling)
438 return false;
439 return true;
440}
441
442static int
443komeda_scaler_check_cfg(struct komeda_scaler *scaler,
444 struct komeda_crtc_state *kcrtc_st,
445 struct komeda_data_flow_cfg *dflow)
446{
447 u32 hsize_in, vsize_in, hsize_out, vsize_out;
448 u32 max_upscaling;
449
450 hsize_in = dflow->in_w;
451 vsize_in = dflow->in_h;
452 hsize_out = dflow->out_w;
453 vsize_out = dflow->out_h;
454
455 if (!in_range(&scaler->hsize, hsize_in) ||
456 !in_range(&scaler->hsize, hsize_out)) {
457 DRM_DEBUG_ATOMIC("Invalid horizontal sizes");
458 return -EINVAL;
459 }
460
461 if (!in_range(&scaler->vsize, vsize_in) ||
462 !in_range(&scaler->vsize, vsize_out)) {
463 DRM_DEBUG_ATOMIC("Invalid vertical sizes");
464 return -EINVAL;
465 }
466
467
468
469
470 if (has_bit(dflow->input.component->id, KOMEDA_PIPELINE_COMPIZS))
471 max_upscaling = 1;
472 else
473 max_upscaling = scaler->max_upscaling;
474
475 if (!scaling_ratio_valid(hsize_in, hsize_out, max_upscaling,
476 scaler->max_downscaling)) {
477 DRM_DEBUG_ATOMIC("Invalid horizontal scaling ratio");
478 return -EINVAL;
479 }
480
481 if (!scaling_ratio_valid(vsize_in, vsize_out, max_upscaling,
482 scaler->max_downscaling)) {
483 DRM_DEBUG_ATOMIC("Invalid vertical scaling ratio");
484 return -EINVAL;
485 }
486
487 if (hsize_in > hsize_out || vsize_in > vsize_out) {
488 struct komeda_pipeline *pipe = scaler->base.pipeline;
489 int err;
490
491 err = pipe->funcs->downscaling_clk_check(pipe,
492 &kcrtc_st->base.adjusted_mode,
493 komeda_crtc_get_aclk(kcrtc_st), dflow);
494 if (err) {
495 DRM_DEBUG_ATOMIC("aclk can't satisfy the clock requirement of the downscaling\n");
496 return err;
497 }
498 }
499
500 return 0;
501}
502
503static int
504komeda_scaler_validate(void *user,
505 struct komeda_crtc_state *kcrtc_st,
506 struct komeda_data_flow_cfg *dflow)
507{
508 struct drm_atomic_state *drm_st = kcrtc_st->base.state;
509 struct komeda_component_state *c_st;
510 struct komeda_scaler_state *st;
511 struct komeda_scaler *scaler;
512 int err = 0;
513
514 if (!(dflow->en_scaling || dflow->en_img_enhancement))
515 return 0;
516
517 scaler = komeda_component_get_avail_scaler(dflow->input.component,
518 drm_st);
519 if (!scaler) {
520 DRM_DEBUG_ATOMIC("No scaler available");
521 return -EINVAL;
522 }
523
524 err = komeda_scaler_check_cfg(scaler, kcrtc_st, dflow);
525 if (err)
526 return err;
527
528 c_st = komeda_component_get_state_and_set_user(&scaler->base,
529 drm_st, user, kcrtc_st->base.crtc);
530 if (IS_ERR(c_st))
531 return PTR_ERR(c_st);
532
533 st = to_scaler_st(c_st);
534
535 st->hsize_in = dflow->in_w;
536 st->vsize_in = dflow->in_h;
537 st->hsize_out = dflow->out_w;
538 st->vsize_out = dflow->out_h;
539 st->right_crop = dflow->right_crop;
540 st->left_crop = dflow->left_crop;
541 st->total_vsize_in = dflow->total_in_h;
542 st->total_hsize_in = dflow->total_in_w;
543 st->total_hsize_out = dflow->total_out_w;
544
545
546 st->en_alpha = dflow->pixel_blend_mode != DRM_MODE_BLEND_PIXEL_NONE;
547 st->en_scaling = dflow->en_scaling;
548 st->en_img_enhancement = dflow->en_img_enhancement;
549 st->en_split = dflow->en_split;
550 st->right_part = dflow->right_part;
551
552 komeda_component_add_input(&st->base, &dflow->input, 0);
553 komeda_component_set_output(&dflow->input, &scaler->base, 0);
554 return err;
555}
556
557static void komeda_split_data_flow(struct komeda_scaler *scaler,
558 struct komeda_data_flow_cfg *dflow,
559 struct komeda_data_flow_cfg *l_dflow,
560 struct komeda_data_flow_cfg *r_dflow);
561
562static int
563komeda_splitter_validate(struct komeda_splitter *splitter,
564 struct drm_connector_state *conn_st,
565 struct komeda_data_flow_cfg *dflow,
566 struct komeda_data_flow_cfg *l_output,
567 struct komeda_data_flow_cfg *r_output)
568{
569 struct komeda_component_state *c_st;
570 struct komeda_splitter_state *st;
571
572 if (!splitter) {
573 DRM_DEBUG_ATOMIC("Current HW doesn't support splitter.\n");
574 return -EINVAL;
575 }
576
577 if (!in_range(&splitter->hsize, dflow->in_w)) {
578 DRM_DEBUG_ATOMIC("split in_w:%d is out of the acceptable range.\n",
579 dflow->in_w);
580 return -EINVAL;
581 }
582
583 if (!in_range(&splitter->vsize, dflow->in_h)) {
584 DRM_DEBUG_ATOMIC("split in_h: %d exceeds the acceptable range.\n",
585 dflow->in_h);
586 return -EINVAL;
587 }
588
589 c_st = komeda_component_get_state_and_set_user(&splitter->base,
590 conn_st->state, conn_st->connector, conn_st->crtc);
591
592 if (IS_ERR(c_st))
593 return PTR_ERR(c_st);
594
595 komeda_split_data_flow(splitter->base.pipeline->scalers[0],
596 dflow, l_output, r_output);
597
598 st = to_splitter_st(c_st);
599 st->hsize = dflow->in_w;
600 st->vsize = dflow->in_h;
601 st->overlap = dflow->overlap;
602
603 komeda_component_add_input(&st->base, &dflow->input, 0);
604 komeda_component_set_output(&l_output->input, &splitter->base, 0);
605 komeda_component_set_output(&r_output->input, &splitter->base, 1);
606
607 return 0;
608}
609
610static int
611komeda_merger_validate(struct komeda_merger *merger,
612 void *user,
613 struct komeda_crtc_state *kcrtc_st,
614 struct komeda_data_flow_cfg *left_input,
615 struct komeda_data_flow_cfg *right_input,
616 struct komeda_data_flow_cfg *output)
617{
618 struct komeda_component_state *c_st;
619 struct komeda_merger_state *st;
620 int err = 0;
621
622 if (!merger) {
623 DRM_DEBUG_ATOMIC("No merger is available");
624 return -EINVAL;
625 }
626
627 if (!in_range(&merger->hsize_merged, output->out_w)) {
628 DRM_DEBUG_ATOMIC("merged_w: %d is out of the accepted range.\n",
629 output->out_w);
630 return -EINVAL;
631 }
632
633 if (!in_range(&merger->vsize_merged, output->out_h)) {
634 DRM_DEBUG_ATOMIC("merged_h: %d is out of the accepted range.\n",
635 output->out_h);
636 return -EINVAL;
637 }
638
639 c_st = komeda_component_get_state_and_set_user(&merger->base,
640 kcrtc_st->base.state, kcrtc_st->base.crtc, kcrtc_st->base.crtc);
641
642 if (IS_ERR(c_st))
643 return PTR_ERR(c_st);
644
645 st = to_merger_st(c_st);
646 st->hsize_merged = output->out_w;
647 st->vsize_merged = output->out_h;
648
649 komeda_component_add_input(c_st, &left_input->input, 0);
650 komeda_component_add_input(c_st, &right_input->input, 1);
651 komeda_component_set_output(&output->input, &merger->base, 0);
652
653 return err;
654}
655
656void pipeline_composition_size(struct komeda_crtc_state *kcrtc_st,
657 u16 *hsize, u16 *vsize)
658{
659 struct drm_display_mode *m = &kcrtc_st->base.adjusted_mode;
660
661 if (hsize)
662 *hsize = m->hdisplay;
663 if (vsize)
664 *vsize = m->vdisplay;
665}
666
667static int
668komeda_compiz_set_input(struct komeda_compiz *compiz,
669 struct komeda_crtc_state *kcrtc_st,
670 struct komeda_data_flow_cfg *dflow)
671{
672 struct drm_atomic_state *drm_st = kcrtc_st->base.state;
673 struct komeda_component_state *c_st, *old_st;
674 struct komeda_compiz_input_cfg *cin;
675 u16 compiz_w, compiz_h;
676 int idx = dflow->blending_zorder;
677
678 pipeline_composition_size(kcrtc_st, &compiz_w, &compiz_h);
679
680 if ((dflow->out_x + dflow->out_w > compiz_w) ||
681 (dflow->out_y + dflow->out_h > compiz_h) ||
682 dflow->out_w == 0 || dflow->out_h == 0) {
683 DRM_DEBUG_ATOMIC("invalid disp rect [x=%d, y=%d, w=%d, h=%d]\n",
684 dflow->out_x, dflow->out_y,
685 dflow->out_w, dflow->out_h);
686 return -EINVAL;
687 }
688
689 c_st = komeda_component_get_state_and_set_user(&compiz->base, drm_st,
690 kcrtc_st->base.crtc, kcrtc_st->base.crtc);
691 if (IS_ERR(c_st))
692 return PTR_ERR(c_st);
693
694 if (komeda_component_check_input(c_st, &dflow->input, idx))
695 return -EINVAL;
696
697 cin = &(to_compiz_st(c_st)->cins[idx]);
698
699 cin->hsize = dflow->out_w;
700 cin->vsize = dflow->out_h;
701 cin->hoffset = dflow->out_x;
702 cin->voffset = dflow->out_y;
703 cin->pixel_blend_mode = dflow->pixel_blend_mode;
704 cin->layer_alpha = dflow->layer_alpha;
705
706 old_st = komeda_component_get_old_state(&compiz->base, drm_st);
707 WARN_ON(!old_st);
708
709
710 if (memcmp(&(to_compiz_st(old_st)->cins[idx]), cin, sizeof(*cin)))
711 c_st->changed_active_inputs |= BIT(idx);
712
713 komeda_component_add_input(c_st, &dflow->input, idx);
714 komeda_component_set_output(&dflow->input, &compiz->base, 0);
715
716 return 0;
717}
718
719static int
720komeda_compiz_validate(struct komeda_compiz *compiz,
721 struct komeda_crtc_state *state,
722 struct komeda_data_flow_cfg *dflow)
723{
724 struct komeda_component_state *c_st;
725 struct komeda_compiz_state *st;
726
727 c_st = komeda_component_get_state_and_set_user(&compiz->base,
728 state->base.state, state->base.crtc, state->base.crtc);
729 if (IS_ERR(c_st))
730 return PTR_ERR(c_st);
731
732 st = to_compiz_st(c_st);
733
734 pipeline_composition_size(state, &st->hsize, &st->vsize);
735
736 komeda_component_set_output(&dflow->input, &compiz->base, 0);
737
738
739
740
741 if (dflow) {
742 dflow->in_w = st->hsize;
743 dflow->in_h = st->vsize;
744 dflow->out_w = dflow->in_w;
745 dflow->out_h = dflow->in_h;
746
747
748
749 dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
750 dflow->layer_alpha = 0xFF;
751 dflow->blending_zorder = 0;
752 }
753
754 return 0;
755}
756
757static int
758komeda_improc_validate(struct komeda_improc *improc,
759 struct komeda_crtc_state *kcrtc_st,
760 struct komeda_data_flow_cfg *dflow)
761{
762 struct drm_crtc *crtc = kcrtc_st->base.crtc;
763 struct drm_crtc_state *crtc_st = &kcrtc_st->base;
764 struct komeda_component_state *c_st;
765 struct komeda_improc_state *st;
766
767 c_st = komeda_component_get_state_and_set_user(&improc->base,
768 kcrtc_st->base.state, crtc, crtc);
769 if (IS_ERR(c_st))
770 return PTR_ERR(c_st);
771
772 st = to_improc_st(c_st);
773
774 st->hsize = dflow->in_w;
775 st->vsize = dflow->in_h;
776
777 if (drm_atomic_crtc_needs_modeset(crtc_st)) {
778 u32 output_depths, output_formats;
779 u32 avail_depths, avail_formats;
780
781 komeda_crtc_get_color_config(crtc_st, &output_depths,
782 &output_formats);
783
784 avail_depths = output_depths & improc->supported_color_depths;
785 if (avail_depths == 0) {
786 DRM_DEBUG_ATOMIC("No available color depths, conn depths: 0x%x & display: 0x%x\n",
787 output_depths,
788 improc->supported_color_depths);
789 return -EINVAL;
790 }
791
792 avail_formats = output_formats &
793 improc->supported_color_formats;
794 if (!avail_formats) {
795 DRM_DEBUG_ATOMIC("No available color_formats, conn formats 0x%x & display: 0x%x\n",
796 output_formats,
797 improc->supported_color_formats);
798 return -EINVAL;
799 }
800
801 st->color_depth = __fls(avail_depths);
802 st->color_format = BIT(__ffs(avail_formats));
803 }
804
805 if (kcrtc_st->base.color_mgmt_changed) {
806 drm_lut_to_fgamma_coeffs(kcrtc_st->base.gamma_lut,
807 st->fgamma_coeffs);
808 drm_ctm_to_coeffs(kcrtc_st->base.ctm, st->ctm_coeffs);
809 }
810
811 komeda_component_add_input(&st->base, &dflow->input, 0);
812 komeda_component_set_output(&dflow->input, &improc->base, 0);
813
814 return 0;
815}
816
817static int
818komeda_timing_ctrlr_validate(struct komeda_timing_ctrlr *ctrlr,
819 struct komeda_crtc_state *kcrtc_st,
820 struct komeda_data_flow_cfg *dflow)
821{
822 struct drm_crtc *crtc = kcrtc_st->base.crtc;
823 struct komeda_timing_ctrlr_state *st;
824 struct komeda_component_state *c_st;
825
826 c_st = komeda_component_get_state_and_set_user(&ctrlr->base,
827 kcrtc_st->base.state, crtc, crtc);
828 if (IS_ERR(c_st))
829 return PTR_ERR(c_st);
830
831 st = to_ctrlr_st(c_st);
832
833 komeda_component_add_input(&st->base, &dflow->input, 0);
834 komeda_component_set_output(&dflow->input, &ctrlr->base, 0);
835
836 return 0;
837}
838
839void komeda_complete_data_flow_cfg(struct komeda_layer *layer,
840 struct komeda_data_flow_cfg *dflow,
841 struct drm_framebuffer *fb)
842{
843 struct komeda_scaler *scaler = layer->base.pipeline->scalers[0];
844 u32 w = dflow->in_w;
845 u32 h = dflow->in_h;
846
847 dflow->total_in_w = dflow->in_w;
848 dflow->total_in_h = dflow->in_h;
849 dflow->total_out_w = dflow->out_w;
850
851
852 if (!fb->format->has_alpha)
853 dflow->pixel_blend_mode = DRM_MODE_BLEND_PIXEL_NONE;
854
855 if (drm_rotation_90_or_270(dflow->rot))
856 swap(w, h);
857
858 dflow->en_scaling = (w != dflow->out_w) || (h != dflow->out_h);
859 dflow->is_yuv = fb->format->is_yuv;
860
861
862 dflow->en_img_enhancement = dflow->out_w >= 2 * w ||
863 dflow->out_h >= 2 * h;
864
865
866
867
868 if (dflow->en_scaling && scaler)
869 dflow->en_split = !in_range(&scaler->hsize, dflow->in_w) ||
870 !in_range(&scaler->hsize, dflow->out_w);
871}
872
873static bool merger_is_available(struct komeda_pipeline *pipe,
874 struct komeda_data_flow_cfg *dflow)
875{
876 u32 avail_inputs = pipe->merger ?
877 pipe->merger->base.supported_inputs : 0;
878
879 return has_bit(dflow->input.component->id, avail_inputs);
880}
881
882int komeda_build_layer_data_flow(struct komeda_layer *layer,
883 struct komeda_plane_state *kplane_st,
884 struct komeda_crtc_state *kcrtc_st,
885 struct komeda_data_flow_cfg *dflow)
886{
887 struct drm_plane *plane = kplane_st->base.plane;
888 struct komeda_pipeline *pipe = layer->base.pipeline;
889 int err;
890
891 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]",
892 layer->base.name, plane->base.id, plane->name,
893 dflow->in_x, dflow->in_y, dflow->in_w, dflow->in_h,
894 dflow->out_x, dflow->out_y, dflow->out_w, dflow->out_h);
895
896 err = komeda_layer_validate(layer, kplane_st, dflow);
897 if (err)
898 return err;
899
900 err = komeda_scaler_validate(plane, kcrtc_st, dflow);
901 if (err)
902 return err;
903
904
905 if (dflow->en_split && merger_is_available(pipe, dflow))
906 return 0;
907
908 err = komeda_compiz_set_input(pipe->compiz, kcrtc_st, dflow);
909
910 return err;
911}
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945static void komeda_split_data_flow(struct komeda_scaler *scaler,
946 struct komeda_data_flow_cfg *dflow,
947 struct komeda_data_flow_cfg *l_dflow,
948 struct komeda_data_flow_cfg *r_dflow)
949{
950 bool r90 = drm_rotation_90_or_270(dflow->rot);
951 bool flip_h = has_flip_h(dflow->rot);
952 u32 l_out, r_out, overlap;
953
954 memcpy(l_dflow, dflow, sizeof(*dflow));
955 memcpy(r_dflow, dflow, sizeof(*dflow));
956
957 l_dflow->right_part = false;
958 r_dflow->right_part = true;
959 r_dflow->blending_zorder = dflow->blending_zorder + 1;
960
961 overlap = 0;
962 if (dflow->en_scaling && scaler)
963 overlap += scaler->scaling_split_overlap;
964
965
966
967
968 dflow->overlap = overlap;
969
970 if (dflow->en_img_enhancement && scaler)
971 overlap += scaler->enh_split_overlap;
972
973 l_dflow->overlap = overlap;
974 r_dflow->overlap = overlap;
975
976
977
978
979
980
981 if (r90) {
982 if (dflow->en_scaling) {
983 l_dflow->in_h = ALIGN(dflow->in_h, 2) / 2 + l_dflow->overlap;
984 r_dflow->in_h = l_dflow->in_h;
985 } else if (dflow->en_img_enhancement) {
986
987 l_dflow->in_h = ALIGN(dflow->in_h, 2) / 2 + l_dflow->overlap;
988 r_dflow->in_h = dflow->in_h / 2 + r_dflow->overlap;
989 } else {
990
991 l_dflow->in_h = ALIGN(((dflow->in_h + 1) >> 1), 2);
992 r_dflow->in_h = dflow->in_h - l_dflow->in_h;
993 }
994
995
996
997
998
999
1000
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
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
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
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
1048
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
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
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085int 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
1114 komeda_rotate_data_flow(dflow, dflow->rot);
1115
1116
1117
1118
1119 if (r_dflow.input.component == l_dflow.input.component)
1120 return 0;
1121
1122
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
1134int 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
1150
1151
1152
1153
1154int 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
1185
1186
1187int 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;
1193 struct komeda_data_flow_cfg s_dflow;
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
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
1226static void
1227komeda_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 disabling_comps, id;
1235
1236 WARN_ON(!old);
1237
1238 disabling_comps = (~new->active_comps) & old->active_comps;
1239
1240
1241 dp_for_each_set_bit(id, disabling_comps) {
1242 c = komeda_pipeline_get_component(pipe, id);
1243 c_st = komeda_component_get_state_and_set_user(c,
1244 drm_st, NULL, new->crtc);
1245 WARN_ON(IS_ERR(c_st));
1246 }
1247}
1248
1249
1250int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
1251 struct komeda_crtc_state *kcrtc_st)
1252{
1253 struct drm_atomic_state *drm_st = kcrtc_st->base.state;
1254 struct komeda_pipeline_state *st;
1255
1256
1257 if (!pipe || !has_bit(pipe->id, kcrtc_st->affected_pipes))
1258 return 0;
1259
1260 if (has_bit(pipe->id, kcrtc_st->active_pipes))
1261 st = komeda_pipeline_get_new_state(pipe, drm_st);
1262 else
1263 st = komeda_pipeline_get_state_and_set_crtc(pipe, drm_st, NULL);
1264
1265 if (WARN_ON(IS_ERR_OR_NULL(st)))
1266 return -EINVAL;
1267
1268 komeda_pipeline_unbound_components(pipe, st);
1269
1270 return 0;
1271}
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283bool komeda_pipeline_disable(struct komeda_pipeline *pipe,
1284 struct drm_atomic_state *old_state)
1285{
1286 struct komeda_pipeline_state *old;
1287 struct komeda_component *c;
1288 struct komeda_component_state *c_st;
1289 u32 id, disabling_comps = 0;
1290
1291 old = komeda_pipeline_get_old_state(pipe, old_state);
1292
1293 disabling_comps = old->active_comps &
1294 (~pipe->standalone_disabled_comps);
1295 if (!disabling_comps)
1296 disabling_comps = old->active_comps &
1297 pipe->standalone_disabled_comps;
1298
1299 DRM_DEBUG_ATOMIC("PIPE%d: active_comps: 0x%x, disabling_comps: 0x%x.\n",
1300 pipe->id, old->active_comps, disabling_comps);
1301
1302 dp_for_each_set_bit(id, disabling_comps) {
1303 c = komeda_pipeline_get_component(pipe, id);
1304 c_st = priv_to_comp_st(c->obj.state);
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314 c_st->changed_active_inputs |= c_st->active_inputs;
1315
1316 c->funcs->disable(c);
1317 }
1318
1319
1320
1321
1322 old->active_comps &= ~disabling_comps;
1323
1324 return old->active_comps ? true : false;
1325}
1326
1327void komeda_pipeline_update(struct komeda_pipeline *pipe,
1328 struct drm_atomic_state *old_state)
1329{
1330 struct komeda_pipeline_state *new = priv_to_pipe_st(pipe->obj.state);
1331 struct komeda_pipeline_state *old;
1332 struct komeda_component *c;
1333 u32 id, changed_comps = 0;
1334
1335 old = komeda_pipeline_get_old_state(pipe, old_state);
1336
1337 changed_comps = new->active_comps | old->active_comps;
1338
1339 DRM_DEBUG_ATOMIC("PIPE%d: active_comps: 0x%x, changed: 0x%x.\n",
1340 pipe->id, new->active_comps, changed_comps);
1341
1342 dp_for_each_set_bit(id, changed_comps) {
1343 c = komeda_pipeline_get_component(pipe, id);
1344
1345 if (new->active_comps & BIT(c->id))
1346 c->funcs->update(c, priv_to_comp_st(c->obj.state));
1347 else
1348 c->funcs->disable(c);
1349 }
1350}
1351