cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

komeda_pipeline_state.c (39413B)


      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
     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/* Assign pipeline for crtc */
     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	/* 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
     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 * 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 */
    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	/* 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
    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	/* 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
    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/* Get current available scaler from the component->supported_outputs */
    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	/* update the data flow for the next stage */
    387	komeda_component_set_output(&dflow->input, &layer->base, 0);
    388
    389	/*
    390	 * The rotation has been handled by layer, so adjusted the data flow for
    391	 * the next stage.
    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	/* If input comes from compiz that means the scaling is for writeback
    468	 * and scaler can not do upscaling for writeback
    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	/* Enable alpha processing if the next stage needs the pixel alpha */
    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	/* check display rect */
    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
    708	/* compare with old to check if this input has been changed */
    709	if (WARN_ON(!old_st) ||
    710	    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	/* compiz output dflow will be fed to the next pipeline stage, prepare
    739	 * the data flow configuration for the next stage
    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		/* the output data of compiz doesn't have alpha, it only can be
    747		 * used as bottom layer when blend it with master layers
    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	/* if format doesn't have alpha, fix blend mode to PIXEL_NONE */
    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	/* try to enable image enhancer if data flow is a 2x+ upscaling */
    862	dflow->en_img_enhancement = dflow->out_w >= 2 * w ||
    863				    dflow->out_h >= 2 * h;
    864
    865	/* try to enable split if scaling exceed the scaler's acceptable
    866	 * input/output range.
    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	/* if split, check if can put the data flow into merger */
    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 * Split is introduced for workaround scaler's input/output size limitation.
    915 * The idea is simple, if one scaler can not fit the requirement, use two.
    916 * So split splits the big source image to two half parts (left/right) and do
    917 * the scaling by two scaler separately and independently.
    918 * But split also imports an edge problem in the middle of the image when
    919 * scaling, to avoid it, split isn't a simple half-and-half, but add an extra
    920 * pixels (overlap) to both side, after split the left/right will be:
    921 * - left: [0, src_length/2 + overlap]
    922 * - right: [src_length/2 - overlap, src_length]
    923 * The extra overlap do eliminate the edge problem, but which may also generates
    924 * unnecessary pixels when scaling, we need to crop them before scaler output
    925 * the result to the next stage. and for the how to crop, it depends on the
    926 * unneeded pixels, another words the position where overlay has been added.
    927 * - left: crop the right
    928 * - right: crop the left
    929 *
    930 * The diagram for how to do the split
    931 *
    932 *  <---------------------left->out_w ---------------->
    933 * |--------------------------------|---right_crop-----| <- left after split
    934 *  \                                \                /
    935 *   \                                \<--overlap--->/
    936 *   |-----------------|-------------|(Middle)------|-----------------| <- src
    937 *                     /<---overlap--->\                               \
    938 *                    /                 \                               \
    939 * right after split->|-----left_crop---|--------------------------------|
    940 *                    ^<------------------- right->out_w --------------->^
    941 *
    942 * NOTE: To consistent with HW the output_w always contains the crop size.
    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	/* original dflow may fed into splitter, and which doesn't need
    966	 * enhancement overlap
    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	/* split the origin content */
    977	/* left/right here always means the left/right part of display image,
    978	 * not the source Image
    979	 */
    980	/* DRM rotation is anti-clockwise */
    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			/* enhancer only */
    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			/* split without scaler, no overlap */
    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		/* Consider YUV format, after split, the split source w/h
    996		 * may not aligned to 2. we have two choices for such case.
    997		 * 1. scaler is enabled (overlap != 0), we can do a alignment
    998		 *    both left/right and crop the extra data by scaler.
    999		 * 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 */
   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	/* 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 */
   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/* writeback scaling split data path:
   1150 *                   /-> scaler ->\
   1151 * compiz -> splitter              merger -> wb_layer -> memory
   1152 *                   \-> scaler ->/
   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/* build display output data flow, the data path is:
   1185 * compiz -> improc -> timing_ctrlr
   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; /* 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
   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 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 */
   1251int 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 */
   1284bool 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
   1329void 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}