xref: /linux/drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c (revision 58f6259b7a08f8d47d4629609703d358b042f0fd)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2022 MediaTek Inc.
4  * Author: Ping-Hsun Wu <ping-hsun.wu@mediatek.com>
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/of_platform.h>
9 #include <linux/of_address.h>
10 #include <linux/pm_runtime.h>
11 #include "mtk-mdp3-cfg.h"
12 #include "mtk-mdp3-comp.h"
13 #include "mtk-mdp3-core.h"
14 #include "mtk-mdp3-regs.h"
15 
16 #include "mdp_reg_rdma.h"
17 #include "mdp_reg_ccorr.h"
18 #include "mdp_reg_rsz.h"
19 #include "mdp_reg_wrot.h"
20 #include "mdp_reg_wdma.h"
21 
22 static u32 mdp_comp_alias_id[MDP_COMP_TYPE_COUNT];
23 static int p_id;
24 
25 static inline const struct mdp_platform_config *
26 __get_plat_cfg(const struct mdp_comp_ctx *ctx)
27 {
28 	if (!ctx)
29 		return NULL;
30 
31 	return ctx->comp->mdp_dev->mdp_data->mdp_cfg;
32 }
33 
34 static s64 get_comp_flag(const struct mdp_comp_ctx *ctx)
35 {
36 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
37 	u32 rdma0, rsz1;
38 
39 	rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0);
40 	rsz1 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RSZ1);
41 	if (!rdma0 || !rsz1)
42 		return MDP_COMP_NONE;
43 
44 	if (mdp_cfg && mdp_cfg->rdma_rsz1_sram_sharing)
45 		if (ctx->comp->inner_id == rdma0)
46 			return BIT(rdma0) | BIT(rsz1);
47 
48 	return BIT(ctx->comp->inner_id);
49 }
50 
51 static int init_rdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
52 {
53 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
54 	phys_addr_t base = ctx->comp->reg_base;
55 	u8 subsys_id = ctx->comp->subsys_id;
56 	s32 rdma0;
57 
58 	rdma0 = mdp_cfg_get_id_inner(ctx->comp->mdp_dev, MDP_COMP_RDMA0);
59 	if (!rdma0)
60 		return -EINVAL;
61 
62 	if (mdp_cfg && mdp_cfg->rdma_support_10bit) {
63 		struct mdp_comp *prz1 = ctx->comp->mdp_dev->comp[MDP_COMP_RSZ1];
64 
65 		/* Disable RSZ1 */
66 		if (ctx->comp->inner_id == rdma0 && prz1)
67 			MM_REG_WRITE(cmd, subsys_id, prz1->reg_base, PRZ_ENABLE,
68 				     0x0, BIT(0));
69 	}
70 
71 	/* Reset RDMA */
72 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESET, BIT(0), BIT(0));
73 	MM_REG_POLL(cmd, subsys_id, base, MDP_RDMA_MON_STA_1, BIT(8), BIT(8));
74 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_RESET, 0x0, BIT(0));
75 	return 0;
76 }
77 
78 static int config_rdma_frame(struct mdp_comp_ctx *ctx,
79 			     struct mdp_cmdq_cmd *cmd,
80 			     const struct v4l2_rect *compose)
81 {
82 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
83 	u32 colorformat = ctx->input->buffer.format.colorformat;
84 	bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat);
85 	bool en_ufo = MDP_COLOR_IS_UFP(colorformat);
86 	phys_addr_t base = ctx->comp->reg_base;
87 	u8 subsys_id = ctx->comp->subsys_id;
88 	u32 reg = 0;
89 
90 	if (mdp_cfg && mdp_cfg->rdma_support_10bit) {
91 		if (block10bit)
92 			MM_REG_WRITE(cmd, subsys_id, base,
93 				     MDP_RDMA_RESV_DUMMY_0, 0x7, 0x7);
94 		else
95 			MM_REG_WRITE(cmd, subsys_id, base,
96 				     MDP_RDMA_RESV_DUMMY_0, 0x0, 0x7);
97 	}
98 
99 	/* Setup smi control */
100 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_GMCIF_CON,
101 		     (7 <<  4) + //burst type to 8
102 		     (1 << 16),  //enable pre-ultra
103 		     0x00030071);
104 
105 	/* Setup source frame info */
106 	if (CFG_CHECK(MT8183, p_id))
107 		reg = CFG_COMP(MT8183, ctx->param, rdma.src_ctrl);
108 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_CON, reg,
109 		     0x03C8FE0F);
110 
111 	if (mdp_cfg)
112 		if (mdp_cfg->rdma_support_10bit && en_ufo) {
113 			/* Setup source buffer base */
114 			if (CFG_CHECK(MT8183, p_id))
115 				reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_y);
116 			MM_REG_WRITE(cmd, subsys_id,
117 				     base, MDP_RDMA_UFO_DEC_LENGTH_BASE_Y,
118 				     reg, 0xFFFFFFFF);
119 			if (CFG_CHECK(MT8183, p_id))
120 				reg = CFG_COMP(MT8183, ctx->param, rdma.ufo_dec_c);
121 			MM_REG_WRITE(cmd, subsys_id,
122 				     base, MDP_RDMA_UFO_DEC_LENGTH_BASE_C,
123 				     reg, 0xFFFFFFFF);
124 			/* Set 10bit source frame pitch */
125 			if (block10bit) {
126 				if (CFG_CHECK(MT8183, p_id))
127 					reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd_in_pxl);
128 				MM_REG_WRITE(cmd, subsys_id,
129 					     base, MDP_RDMA_MF_BKGD_SIZE_IN_PXL,
130 					     reg, 0x001FFFFF);
131 			}
132 		}
133 
134 	if (CFG_CHECK(MT8183, p_id))
135 		reg = CFG_COMP(MT8183, ctx->param, rdma.control);
136 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_CON, reg,
137 		     0x1110);
138 	/* Setup source buffer base */
139 	if (CFG_CHECK(MT8183, p_id))
140 		reg = CFG_COMP(MT8183, ctx->param, rdma.iova[0]);
141 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_0, reg,
142 		     0xFFFFFFFF);
143 	if (CFG_CHECK(MT8183, p_id))
144 		reg = CFG_COMP(MT8183, ctx->param, rdma.iova[1]);
145 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_1, reg,
146 		     0xFFFFFFFF);
147 	if (CFG_CHECK(MT8183, p_id))
148 		reg = CFG_COMP(MT8183, ctx->param, rdma.iova[2]);
149 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_BASE_2, reg,
150 		     0xFFFFFFFF);
151 	/* Setup source buffer end */
152 	if (CFG_CHECK(MT8183, p_id))
153 		reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[0]);
154 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_0,
155 		     reg, 0xFFFFFFFF);
156 	if (CFG_CHECK(MT8183, p_id))
157 		reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[1]);
158 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_1,
159 		     reg, 0xFFFFFFFF);
160 	if (CFG_CHECK(MT8183, p_id))
161 		reg = CFG_COMP(MT8183, ctx->param, rdma.iova_end[2]);
162 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_END_2,
163 		     reg, 0xFFFFFFFF);
164 	/* Setup source frame pitch */
165 	if (CFG_CHECK(MT8183, p_id))
166 		reg = CFG_COMP(MT8183, ctx->param, rdma.mf_bkgd);
167 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_BKGD_SIZE_IN_BYTE,
168 		     reg, 0x001FFFFF);
169 	if (CFG_CHECK(MT8183, p_id))
170 		reg = CFG_COMP(MT8183, ctx->param, rdma.sf_bkgd);
171 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SF_BKGD_SIZE_IN_BYTE,
172 		     reg, 0x001FFFFF);
173 	/* Setup color transform */
174 	if (CFG_CHECK(MT8183, p_id))
175 		reg = CFG_COMP(MT8183, ctx->param, rdma.transform);
176 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_TRANSFORM_0,
177 		     reg, 0x0F110000);
178 
179 	return 0;
180 }
181 
182 static int config_rdma_subfrm(struct mdp_comp_ctx *ctx,
183 			      struct mdp_cmdq_cmd *cmd, u32 index)
184 {
185 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
186 	u32 colorformat = ctx->input->buffer.format.colorformat;
187 	bool block10bit = MDP_COLOR_IS_10BIT_PACKED(colorformat);
188 	bool en_ufo = MDP_COLOR_IS_UFP(colorformat);
189 	phys_addr_t base = ctx->comp->reg_base;
190 	u8 subsys_id = ctx->comp->subsys_id;
191 	u32 csf_l = 0, csf_r = 0;
192 	u32 reg = 0;
193 
194 	/* Enable RDMA */
195 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, BIT(0), BIT(0));
196 
197 	/* Set Y pixel offset */
198 	if (CFG_CHECK(MT8183, p_id))
199 		reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[0]);
200 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_0,
201 		     reg, 0xFFFFFFFF);
202 
203 	/* Set 10bit UFO mode */
204 	if (mdp_cfg) {
205 		if (mdp_cfg->rdma_support_10bit && block10bit && en_ufo) {
206 			if (CFG_CHECK(MT8183, p_id))
207 				reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset_0_p);
208 			MM_REG_WRITE(cmd, subsys_id, base,
209 				     MDP_RDMA_SRC_OFFSET_0_P,
210 				     reg, 0xFFFFFFFF);
211 		}
212 	}
213 
214 	/* Set U pixel offset */
215 	if (CFG_CHECK(MT8183, p_id))
216 		reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[1]);
217 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_1,
218 		     reg, 0xFFFFFFFF);
219 	/* Set V pixel offset */
220 	if (CFG_CHECK(MT8183, p_id))
221 		reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].offset[2]);
222 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_SRC_OFFSET_2,
223 		     reg, 0xFFFFFFFF);
224 	/* Set source size */
225 	if (CFG_CHECK(MT8183, p_id))
226 		reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].src);
227 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_SRC_SIZE, reg,
228 		     0x1FFF1FFF);
229 	/* Set target size */
230 	if (CFG_CHECK(MT8183, p_id))
231 		reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip);
232 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_CLIP_SIZE,
233 		     reg, 0x1FFF1FFF);
234 	/* Set crop offset */
235 	if (CFG_CHECK(MT8183, p_id))
236 		reg = CFG_COMP(MT8183, ctx->param, rdma.subfrms[index].clip_ofst);
237 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_MF_OFFSET_1,
238 		     reg, 0x003F001F);
239 
240 	if (CFG_CHECK(MT8183, p_id)) {
241 		csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
242 		csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
243 	}
244 	if (mdp_cfg && mdp_cfg->rdma_upsample_repeat_only)
245 		if ((csf_r - csf_l + 1) > 320)
246 			MM_REG_WRITE(cmd, subsys_id, base,
247 				     MDP_RDMA_RESV_DUMMY_0, BIT(2), BIT(2));
248 
249 	return 0;
250 }
251 
252 static int wait_rdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
253 {
254 	struct device *dev = &ctx->comp->mdp_dev->pdev->dev;
255 	phys_addr_t base = ctx->comp->reg_base;
256 	u8 subsys_id = ctx->comp->subsys_id;
257 
258 	if (ctx->comp->alias_id == 0)
259 		MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]);
260 	else
261 		dev_err(dev, "Do not support RDMA1_DONE event\n");
262 
263 	/* Disable RDMA */
264 	MM_REG_WRITE(cmd, subsys_id, base, MDP_RDMA_EN, 0x0, BIT(0));
265 	return 0;
266 }
267 
268 static const struct mdp_comp_ops rdma_ops = {
269 	.get_comp_flag = get_comp_flag,
270 	.init_comp = init_rdma,
271 	.config_frame = config_rdma_frame,
272 	.config_subfrm = config_rdma_subfrm,
273 	.wait_comp_event = wait_rdma_event,
274 };
275 
276 static int init_rsz(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
277 {
278 	phys_addr_t base = ctx->comp->reg_base;
279 	u8 subsys_id = ctx->comp->subsys_id;
280 
281 	/* Reset RSZ */
282 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x10000, BIT(16));
283 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(16));
284 	/* Enable RSZ */
285 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, BIT(0), BIT(0));
286 	return 0;
287 }
288 
289 static int config_rsz_frame(struct mdp_comp_ctx *ctx,
290 			    struct mdp_cmdq_cmd *cmd,
291 			    const struct v4l2_rect *compose)
292 {
293 	phys_addr_t base = ctx->comp->reg_base;
294 	u8 subsys_id = ctx->comp->subsys_id;
295 	bool bypass = FALSE;
296 	u32 reg = 0;
297 
298 	if (CFG_CHECK(MT8183, p_id))
299 		bypass = CFG_COMP(MT8183, ctx->param, frame.bypass);
300 
301 	if (bypass) {
302 		/* Disable RSZ */
303 		MM_REG_WRITE(cmd, subsys_id, base, PRZ_ENABLE, 0x0, BIT(0));
304 		return 0;
305 	}
306 
307 	if (CFG_CHECK(MT8183, p_id))
308 		reg = CFG_COMP(MT8183, ctx->param, rsz.control1);
309 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, reg,
310 		     0x03FFFDF3);
311 	if (CFG_CHECK(MT8183, p_id))
312 		reg = CFG_COMP(MT8183, ctx->param, rsz.control2);
313 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, reg,
314 		     0x0FFFC290);
315 	if (CFG_CHECK(MT8183, p_id))
316 		reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_x);
317 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_HORIZONTAL_COEFF_STEP,
318 		     reg, 0x007FFFFF);
319 	if (CFG_CHECK(MT8183, p_id))
320 		reg = CFG_COMP(MT8183, ctx->param, rsz.coeff_step_y);
321 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_VERTICAL_COEFF_STEP,
322 		     reg, 0x007FFFFF);
323 	return 0;
324 }
325 
326 static int config_rsz_subfrm(struct mdp_comp_ctx *ctx,
327 			     struct mdp_cmdq_cmd *cmd, u32 index)
328 {
329 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
330 	phys_addr_t base = ctx->comp->reg_base;
331 	u8 subsys_id = ctx->comp->subsys_id;
332 	u32 csf_l = 0, csf_r = 0;
333 	u32 reg = 0;
334 
335 	if (CFG_CHECK(MT8183, p_id))
336 		reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].control2);
337 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_2, reg,
338 		     0x00003800);
339 	if (CFG_CHECK(MT8183, p_id))
340 		reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].src);
341 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_INPUT_IMAGE, reg,
342 		     0xFFFFFFFF);
343 
344 	if (CFG_CHECK(MT8183, p_id)) {
345 		csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
346 		csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
347 	}
348 	if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample)
349 		if ((csf_r - csf_l + 1) <= 16)
350 			MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1,
351 				     BIT(27), BIT(27));
352 
353 	if (CFG_CHECK(MT8183, p_id))
354 		reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left);
355 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_HORIZONTAL_INTEGER_OFFSET,
356 		     reg, 0xFFFF);
357 	if (CFG_CHECK(MT8183, p_id))
358 		reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.left_subpix);
359 	MM_REG_WRITE(cmd, subsys_id,
360 		     base, PRZ_LUMA_HORIZONTAL_SUBPIXEL_OFFSET,
361 		     reg, 0x1FFFFF);
362 	if (CFG_CHECK(MT8183, p_id))
363 		reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top);
364 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_INTEGER_OFFSET,
365 		     reg, 0xFFFF);
366 	if (CFG_CHECK(MT8183, p_id))
367 		reg = CFG_COMP(MT8183, ctx->param, subfrms[index].luma.top_subpix);
368 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_LUMA_VERTICAL_SUBPIXEL_OFFSET,
369 		     reg, 0x1FFFFF);
370 	if (CFG_CHECK(MT8183, p_id))
371 		reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left);
372 	MM_REG_WRITE(cmd, subsys_id,
373 		     base, PRZ_CHROMA_HORIZONTAL_INTEGER_OFFSET,
374 		     reg, 0xFFFF);
375 	if (CFG_CHECK(MT8183, p_id))
376 		reg = CFG_COMP(MT8183, ctx->param, subfrms[index].chroma.left_subpix);
377 	MM_REG_WRITE(cmd, subsys_id,
378 		     base, PRZ_CHROMA_HORIZONTAL_SUBPIXEL_OFFSET,
379 		     reg, 0x1FFFFF);
380 
381 	if (CFG_CHECK(MT8183, p_id))
382 		reg = CFG_COMP(MT8183, ctx->param, rsz.subfrms[index].clip);
383 	MM_REG_WRITE(cmd, subsys_id, base, PRZ_OUTPUT_IMAGE, reg,
384 		     0xFFFFFFFF);
385 
386 	return 0;
387 }
388 
389 static int advance_rsz_subfrm(struct mdp_comp_ctx *ctx,
390 			      struct mdp_cmdq_cmd *cmd, u32 index)
391 {
392 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
393 
394 	if (mdp_cfg && mdp_cfg->rsz_disable_dcm_small_sample) {
395 		phys_addr_t base = ctx->comp->reg_base;
396 		u8 subsys_id = ctx->comp->subsys_id;
397 		u32 csf_l = 0, csf_r = 0;
398 
399 		if (CFG_CHECK(MT8183, p_id)) {
400 			csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
401 			csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
402 		}
403 
404 		if ((csf_r - csf_l + 1) <= 16)
405 			MM_REG_WRITE(cmd, subsys_id, base, PRZ_CONTROL_1, 0x0,
406 				     BIT(27));
407 	}
408 
409 	return 0;
410 }
411 
412 static const struct mdp_comp_ops rsz_ops = {
413 	.get_comp_flag = get_comp_flag,
414 	.init_comp = init_rsz,
415 	.config_frame = config_rsz_frame,
416 	.config_subfrm = config_rsz_subfrm,
417 	.advance_subfrm = advance_rsz_subfrm,
418 };
419 
420 static int init_wrot(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
421 {
422 	phys_addr_t base = ctx->comp->reg_base;
423 	u8 subsys_id = ctx->comp->subsys_id;
424 
425 	/* Reset WROT */
426 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_SOFT_RST, BIT(0), BIT(0));
427 	MM_REG_POLL(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, BIT(0), BIT(0));
428 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_SOFT_RST, 0x0, BIT(0));
429 	MM_REG_POLL(cmd, subsys_id, base, VIDO_SOFT_RST_STAT, 0x0, BIT(0));
430 	return 0;
431 }
432 
433 static int config_wrot_frame(struct mdp_comp_ctx *ctx,
434 			     struct mdp_cmdq_cmd *cmd,
435 			     const struct v4l2_rect *compose)
436 {
437 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
438 	phys_addr_t base = ctx->comp->reg_base;
439 	u8 subsys_id = ctx->comp->subsys_id;
440 	u32 reg = 0;
441 
442 	/* Write frame base address */
443 	if (CFG_CHECK(MT8183, p_id))
444 		reg = CFG_COMP(MT8183, ctx->param, wrot.iova[0]);
445 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR, reg,
446 		     0xFFFFFFFF);
447 	if (CFG_CHECK(MT8183, p_id))
448 		reg = CFG_COMP(MT8183, ctx->param, wrot.iova[1]);
449 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_C, reg,
450 		     0xFFFFFFFF);
451 	if (CFG_CHECK(MT8183, p_id))
452 		reg = CFG_COMP(MT8183, ctx->param, wrot.iova[2]);
453 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_BASE_ADDR_V, reg,
454 		     0xFFFFFFFF);
455 	/* Write frame related registers */
456 	if (CFG_CHECK(MT8183, p_id))
457 		reg = CFG_COMP(MT8183, ctx->param, wrot.control);
458 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_CTRL, reg,
459 		     0xF131510F);
460 	/* Write frame Y pitch */
461 	if (CFG_CHECK(MT8183, p_id))
462 		reg = CFG_COMP(MT8183, ctx->param, wrot.stride[0]);
463 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE, reg,
464 		     0x0000FFFF);
465 	/* Write frame UV pitch */
466 	if (CFG_CHECK(MT8183, p_id))
467 		reg = CFG_COMP(MT8183, ctx->param, wrot.stride[1]);
468 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_C, reg,
469 		     0xFFFF);
470 	if (CFG_CHECK(MT8183, p_id))
471 		reg = CFG_COMP(MT8183, ctx->param, wrot.stride[2]);
472 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_STRIDE_V, reg,
473 		     0xFFFF);
474 	/* Write matrix control */
475 	if (CFG_CHECK(MT8183, p_id))
476 		reg = CFG_COMP(MT8183, ctx->param, wrot.mat_ctrl);
477 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAT_CTRL, reg, 0xF3);
478 
479 	/* Set the fixed ALPHA as 0xFF */
480 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_DITHER, 0xFF000000,
481 		     0xFF000000);
482 	/* Set VIDO_EOL_SEL */
483 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_RSV_1, BIT(31), BIT(31));
484 	/* Set VIDO_FIFO_TEST */
485 	if (CFG_CHECK(MT8183, p_id))
486 		reg = CFG_COMP(MT8183, ctx->param, wrot.fifo_test);
487 	if (reg != 0)
488 		MM_REG_WRITE(cmd, subsys_id, base, VIDO_FIFO_TEST,
489 			     reg, 0xFFF);
490 	/* Filter enable */
491 	if (mdp_cfg && mdp_cfg->wrot_filter_constraint) {
492 		if (CFG_CHECK(MT8183, p_id))
493 			reg = CFG_COMP(MT8183, ctx->param, wrot.filter);
494 		MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE,
495 			     reg, 0x77);
496 	}
497 
498 	return 0;
499 }
500 
501 static int config_wrot_subfrm(struct mdp_comp_ctx *ctx,
502 			      struct mdp_cmdq_cmd *cmd, u32 index)
503 {
504 	phys_addr_t base = ctx->comp->reg_base;
505 	u8 subsys_id = ctx->comp->subsys_id;
506 	u32 reg = 0;
507 
508 	/* Write Y pixel offset */
509 	if (CFG_CHECK(MT8183, p_id))
510 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[0]);
511 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR,
512 		     reg, 0x0FFFFFFF);
513 	/* Write U pixel offset */
514 	if (CFG_CHECK(MT8183, p_id))
515 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[1]);
516 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_C,
517 		     reg, 0x0FFFFFFF);
518 	/* Write V pixel offset */
519 	if (CFG_CHECK(MT8183, p_id))
520 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].offset[2]);
521 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_OFST_ADDR_V,
522 		     reg, 0x0FFFFFFF);
523 	/* Write source size */
524 	if (CFG_CHECK(MT8183, p_id))
525 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].src);
526 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_IN_SIZE, reg,
527 		     0x1FFF1FFF);
528 	/* Write target size */
529 	if (CFG_CHECK(MT8183, p_id))
530 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip);
531 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_TAR_SIZE, reg,
532 		     0x1FFF1FFF);
533 	if (CFG_CHECK(MT8183, p_id))
534 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].clip_ofst);
535 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_CROP_OFST, reg,
536 		     0x1FFF1FFF);
537 
538 	if (CFG_CHECK(MT8183, p_id))
539 		reg = CFG_COMP(MT8183, ctx->param, wrot.subfrms[index].main_buf);
540 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE,
541 		     reg, 0x1FFF7F00);
542 
543 	/* Enable WROT */
544 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, BIT(0), BIT(0));
545 
546 	return 0;
547 }
548 
549 static int wait_wrot_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
550 {
551 	const struct mdp_platform_config *mdp_cfg = __get_plat_cfg(ctx);
552 	struct device *dev = &ctx->comp->mdp_dev->pdev->dev;
553 	phys_addr_t base = ctx->comp->reg_base;
554 	u8 subsys_id = ctx->comp->subsys_id;
555 
556 	if (ctx->comp->alias_id == 0)
557 		MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]);
558 	else
559 		dev_err(dev, "Do not support WROT1_DONE event\n");
560 
561 	if (mdp_cfg && mdp_cfg->wrot_filter_constraint)
562 		MM_REG_WRITE(cmd, subsys_id, base, VIDO_MAIN_BUF_SIZE, 0x0,
563 			     0x77);
564 
565 	/* Disable WROT */
566 	MM_REG_WRITE(cmd, subsys_id, base, VIDO_ROT_EN, 0x0, BIT(0));
567 
568 	return 0;
569 }
570 
571 static const struct mdp_comp_ops wrot_ops = {
572 	.get_comp_flag = get_comp_flag,
573 	.init_comp = init_wrot,
574 	.config_frame = config_wrot_frame,
575 	.config_subfrm = config_wrot_subfrm,
576 	.wait_comp_event = wait_wrot_event,
577 };
578 
579 static int init_wdma(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
580 {
581 	phys_addr_t base = ctx->comp->reg_base;
582 	u8 subsys_id = ctx->comp->subsys_id;
583 
584 	/* Reset WDMA */
585 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_RST, BIT(0), BIT(0));
586 	MM_REG_POLL(cmd, subsys_id, base, WDMA_FLOW_CTRL_DBG, BIT(0), BIT(0));
587 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_RST, 0x0, BIT(0));
588 	return 0;
589 }
590 
591 static int config_wdma_frame(struct mdp_comp_ctx *ctx,
592 			     struct mdp_cmdq_cmd *cmd,
593 			     const struct v4l2_rect *compose)
594 {
595 	phys_addr_t base = ctx->comp->reg_base;
596 	u8 subsys_id = ctx->comp->subsys_id;
597 	u32 reg = 0;
598 
599 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_BUF_CON2, 0x10101050,
600 		     0xFFFFFFFF);
601 
602 	/* Setup frame information */
603 	if (CFG_CHECK(MT8183, p_id))
604 		reg = CFG_COMP(MT8183, ctx->param, wdma.wdma_cfg);
605 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_CFG, reg,
606 		     0x0F01B8F0);
607 	/* Setup frame base address */
608 	if (CFG_CHECK(MT8183, p_id))
609 		reg = CFG_COMP(MT8183, ctx->param, wdma.iova[0]);
610 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR, reg,
611 		     0xFFFFFFFF);
612 	if (CFG_CHECK(MT8183, p_id))
613 		reg = CFG_COMP(MT8183, ctx->param, wdma.iova[1]);
614 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR, reg,
615 		     0xFFFFFFFF);
616 	if (CFG_CHECK(MT8183, p_id))
617 		reg = CFG_COMP(MT8183, ctx->param, wdma.iova[2]);
618 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR, reg,
619 		     0xFFFFFFFF);
620 	/* Setup Y pitch */
621 	if (CFG_CHECK(MT8183, p_id))
622 		reg = CFG_COMP(MT8183, ctx->param, wdma.w_in_byte);
623 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_W_IN_BYTE,
624 		     reg, 0x0000FFFF);
625 	/* Setup UV pitch */
626 	if (CFG_CHECK(MT8183, p_id))
627 		reg = CFG_COMP(MT8183, ctx->param, wdma.uv_stride);
628 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_UV_PITCH,
629 		     reg, 0x0000FFFF);
630 	/* Set the fixed ALPHA as 0xFF */
631 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_ALPHA, 0x800000FF,
632 		     0x800000FF);
633 
634 	return 0;
635 }
636 
637 static int config_wdma_subfrm(struct mdp_comp_ctx *ctx,
638 			      struct mdp_cmdq_cmd *cmd, u32 index)
639 {
640 	phys_addr_t base = ctx->comp->reg_base;
641 	u8 subsys_id = ctx->comp->subsys_id;
642 	u32 reg = 0;
643 
644 	/* Write Y pixel offset */
645 	if (CFG_CHECK(MT8183, p_id))
646 		reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[0]);
647 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_ADDR_OFFSET,
648 		     reg, 0x0FFFFFFF);
649 	/* Write U pixel offset */
650 	if (CFG_CHECK(MT8183, p_id))
651 		reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[1]);
652 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_U_ADDR_OFFSET,
653 		     reg, 0x0FFFFFFF);
654 	/* Write V pixel offset */
655 	if (CFG_CHECK(MT8183, p_id))
656 		reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].offset[2]);
657 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_DST_V_ADDR_OFFSET,
658 		     reg, 0x0FFFFFFF);
659 	/* Write source size */
660 	if (CFG_CHECK(MT8183, p_id))
661 		reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].src);
662 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_SRC_SIZE, reg,
663 		     0x3FFF3FFF);
664 	/* Write target size */
665 	if (CFG_CHECK(MT8183, p_id))
666 		reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip);
667 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_SIZE, reg,
668 		     0x3FFF3FFF);
669 	/* Write clip offset */
670 	if (CFG_CHECK(MT8183, p_id))
671 		reg = CFG_COMP(MT8183, ctx->param, wdma.subfrms[index].clip_ofst);
672 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_CLIP_COORD, reg,
673 		     0x3FFF3FFF);
674 
675 	/* Enable WDMA */
676 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_EN, BIT(0), BIT(0));
677 
678 	return 0;
679 }
680 
681 static int wait_wdma_event(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
682 {
683 	phys_addr_t base = ctx->comp->reg_base;
684 	u8 subsys_id = ctx->comp->subsys_id;
685 
686 	MM_REG_WAIT(cmd, ctx->comp->gce_event[MDP_GCE_EVENT_EOF]);
687 	/* Disable WDMA */
688 	MM_REG_WRITE(cmd, subsys_id, base, WDMA_EN, 0x0, BIT(0));
689 	return 0;
690 }
691 
692 static const struct mdp_comp_ops wdma_ops = {
693 	.get_comp_flag = get_comp_flag,
694 	.init_comp = init_wdma,
695 	.config_frame = config_wdma_frame,
696 	.config_subfrm = config_wdma_subfrm,
697 	.wait_comp_event = wait_wdma_event,
698 };
699 
700 static int init_ccorr(struct mdp_comp_ctx *ctx, struct mdp_cmdq_cmd *cmd)
701 {
702 	phys_addr_t base = ctx->comp->reg_base;
703 	u8 subsys_id = ctx->comp->subsys_id;
704 
705 	/* CCORR enable */
706 	MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_EN, BIT(0), BIT(0));
707 	/* Relay mode */
708 	MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_CFG, BIT(0), BIT(0));
709 	return 0;
710 }
711 
712 static int config_ccorr_subfrm(struct mdp_comp_ctx *ctx,
713 			       struct mdp_cmdq_cmd *cmd, u32 index)
714 {
715 	phys_addr_t base = ctx->comp->reg_base;
716 	u8 subsys_id = ctx->comp->subsys_id;
717 	u32 csf_l = 0, csf_r = 0;
718 	u32 csf_t = 0, csf_b = 0;
719 	u32 hsize, vsize;
720 
721 	if (CFG_CHECK(MT8183, p_id)) {
722 		csf_l = CFG_COMP(MT8183, ctx->param, subfrms[index].in.left);
723 		csf_r = CFG_COMP(MT8183, ctx->param, subfrms[index].in.right);
724 		csf_t = CFG_COMP(MT8183, ctx->param, subfrms[index].in.top);
725 		csf_b = CFG_COMP(MT8183, ctx->param, subfrms[index].in.bottom);
726 	}
727 
728 	hsize = csf_r - csf_l + 1;
729 	vsize = csf_b - csf_t + 1;
730 	MM_REG_WRITE(cmd, subsys_id, base, MDP_CCORR_SIZE,
731 		     (hsize << 16) + (vsize <<  0), 0x1FFF1FFF);
732 	return 0;
733 }
734 
735 static const struct mdp_comp_ops ccorr_ops = {
736 	.get_comp_flag = get_comp_flag,
737 	.init_comp = init_ccorr,
738 	.config_subfrm = config_ccorr_subfrm,
739 };
740 
741 static const struct mdp_comp_ops *mdp_comp_ops[MDP_COMP_TYPE_COUNT] = {
742 	[MDP_COMP_TYPE_RDMA] =		&rdma_ops,
743 	[MDP_COMP_TYPE_RSZ] =		&rsz_ops,
744 	[MDP_COMP_TYPE_WROT] =		&wrot_ops,
745 	[MDP_COMP_TYPE_WDMA] =		&wdma_ops,
746 	[MDP_COMP_TYPE_CCORR] =		&ccorr_ops,
747 };
748 
749 static const struct of_device_id mdp_comp_dt_ids[] = {
750 	{
751 		.compatible = "mediatek,mt8183-mdp3-rdma",
752 		.data = (void *)MDP_COMP_TYPE_RDMA,
753 	}, {
754 		.compatible = "mediatek,mt8183-mdp3-ccorr",
755 		.data = (void *)MDP_COMP_TYPE_CCORR,
756 	}, {
757 		.compatible = "mediatek,mt8183-mdp3-rsz",
758 		.data = (void *)MDP_COMP_TYPE_RSZ,
759 	}, {
760 		.compatible = "mediatek,mt8183-mdp3-wrot",
761 		.data = (void *)MDP_COMP_TYPE_WROT,
762 	}, {
763 		.compatible = "mediatek,mt8183-mdp3-wdma",
764 		.data = (void *)MDP_COMP_TYPE_WDMA,
765 	},
766 	{}
767 };
768 
769 static inline bool is_dma_capable(const enum mdp_comp_type type)
770 {
771 	return (type == MDP_COMP_TYPE_RDMA ||
772 		type == MDP_COMP_TYPE_WROT ||
773 		type == MDP_COMP_TYPE_WDMA);
774 }
775 
776 static inline bool is_bypass_gce_event(const enum mdp_comp_type type)
777 {
778 	/*
779 	 * Subcomponent PATH is only used for the direction of data flow and
780 	 * dose not need to wait for GCE event.
781 	 */
782 	return (type == MDP_COMP_TYPE_PATH);
783 }
784 
785 static int mdp_comp_get_id(struct mdp_dev *mdp, enum mdp_comp_type type, u32 alias_id)
786 {
787 	int i;
788 
789 	for (i = 0; i < mdp->mdp_data->comp_data_len; i++)
790 		if (mdp->mdp_data->comp_data[i].match.type == type &&
791 		    mdp->mdp_data->comp_data[i].match.alias_id == alias_id)
792 			return i;
793 	return -ENODEV;
794 }
795 
796 int mdp_comp_clock_on(struct device *dev, struct mdp_comp *comp)
797 {
798 	int i, ret;
799 
800 	/* Only DMA capable components need the pm control */
801 	if (comp->comp_dev && is_dma_capable(comp->type)) {
802 		ret = pm_runtime_resume_and_get(comp->comp_dev);
803 		if (ret < 0) {
804 			dev_err(dev,
805 				"Failed to get power, err %d. type:%d id:%d\n",
806 				ret, comp->type, comp->inner_id);
807 			return ret;
808 		}
809 	}
810 
811 	for (i = 0; i < comp->clk_num; i++) {
812 		if (IS_ERR_OR_NULL(comp->clks[i]))
813 			continue;
814 		ret = clk_prepare_enable(comp->clks[i]);
815 		if (ret) {
816 			dev_err(dev,
817 				"Failed to enable clk %d. type:%d id:%d\n",
818 				i, comp->type, comp->inner_id);
819 			goto err_revert;
820 		}
821 	}
822 
823 	return 0;
824 
825 err_revert:
826 	while (--i >= 0) {
827 		if (IS_ERR_OR_NULL(comp->clks[i]))
828 			continue;
829 		clk_disable_unprepare(comp->clks[i]);
830 	}
831 	if (comp->comp_dev && is_dma_capable(comp->type))
832 		pm_runtime_put_sync(comp->comp_dev);
833 
834 	return ret;
835 }
836 
837 void mdp_comp_clock_off(struct device *dev, struct mdp_comp *comp)
838 {
839 	int i;
840 
841 	for (i = 0; i < comp->clk_num; i++) {
842 		if (IS_ERR_OR_NULL(comp->clks[i]))
843 			continue;
844 		clk_disable_unprepare(comp->clks[i]);
845 	}
846 
847 	if (comp->comp_dev && is_dma_capable(comp->type))
848 		pm_runtime_put(comp->comp_dev);
849 }
850 
851 int mdp_comp_clocks_on(struct device *dev, struct mdp_comp *comps, int num)
852 {
853 	int i, ret;
854 
855 	for (i = 0; i < num; i++) {
856 		ret = mdp_comp_clock_on(dev, &comps[i]);
857 		if (ret)
858 			return ret;
859 	}
860 
861 	return 0;
862 }
863 
864 void mdp_comp_clocks_off(struct device *dev, struct mdp_comp *comps, int num)
865 {
866 	int i;
867 
868 	for (i = 0; i < num; i++)
869 		mdp_comp_clock_off(dev, &comps[i]);
870 }
871 
872 static int mdp_get_subsys_id(struct mdp_dev *mdp, struct device *dev,
873 			     struct device_node *node, struct mdp_comp *comp)
874 {
875 	struct platform_device *comp_pdev;
876 	struct cmdq_client_reg  cmdq_reg;
877 	int ret = 0;
878 	int index = 0;
879 
880 	if (!dev || !node || !comp)
881 		return -EINVAL;
882 
883 	comp_pdev = of_find_device_by_node(node);
884 
885 	if (!comp_pdev) {
886 		dev_err(dev, "get comp_pdev fail! comp public id=%d, inner id=%d, type=%d\n",
887 			comp->public_id, comp->inner_id, comp->type);
888 		return -ENODEV;
889 	}
890 
891 	index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst;
892 	ret = cmdq_dev_get_client_reg(&comp_pdev->dev, &cmdq_reg, index);
893 	if (ret != 0) {
894 		dev_err(&comp_pdev->dev, "cmdq_dev_get_subsys fail!\n");
895 		return -EINVAL;
896 	}
897 
898 	comp->subsys_id = cmdq_reg.subsys;
899 	dev_dbg(&comp_pdev->dev, "subsys id=%d\n", cmdq_reg.subsys);
900 
901 	return 0;
902 }
903 
904 static void __mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
905 			    struct mdp_comp *comp)
906 {
907 	struct resource res;
908 	phys_addr_t base;
909 	int index;
910 
911 	index = mdp->mdp_data->comp_data[comp->public_id].info.dts_reg_ofst;
912 	if (of_address_to_resource(node, index, &res) < 0)
913 		base = 0L;
914 	else
915 		base = res.start;
916 
917 	comp->mdp_dev = mdp;
918 	comp->regs = of_iomap(node, 0);
919 	comp->reg_base = base;
920 }
921 
922 static int mdp_comp_init(struct mdp_dev *mdp, struct device_node *node,
923 			 struct mdp_comp *comp, enum mtk_mdp_comp_id id)
924 {
925 	struct device *dev = &mdp->pdev->dev;
926 	struct platform_device *pdev_c;
927 	int clk_ofst;
928 	int i;
929 	s32 event;
930 
931 	if (id < 0 || id >= MDP_MAX_COMP_COUNT) {
932 		dev_err(dev, "Invalid component id %d\n", id);
933 		return -EINVAL;
934 	}
935 
936 	pdev_c = of_find_device_by_node(node);
937 	if (!pdev_c) {
938 		dev_warn(dev, "can't find platform device of node:%s\n",
939 			 node->name);
940 		return -ENODEV;
941 	}
942 
943 	comp->comp_dev = &pdev_c->dev;
944 	comp->public_id = id;
945 	comp->type = mdp->mdp_data->comp_data[id].match.type;
946 	comp->inner_id = mdp->mdp_data->comp_data[id].match.inner_id;
947 	comp->alias_id = mdp->mdp_data->comp_data[id].match.alias_id;
948 	comp->ops = mdp_comp_ops[comp->type];
949 	__mdp_comp_init(mdp, node, comp);
950 
951 	comp->clk_num = mdp->mdp_data->comp_data[id].info.clk_num;
952 	comp->clks = devm_kzalloc(dev, sizeof(struct clk *) * comp->clk_num,
953 				  GFP_KERNEL);
954 	if (!comp->clks)
955 		return -ENOMEM;
956 
957 	clk_ofst = mdp->mdp_data->comp_data[id].info.clk_ofst;
958 
959 	for (i = 0; i < comp->clk_num; i++) {
960 		comp->clks[i] = of_clk_get(node, i + clk_ofst);
961 		if (IS_ERR(comp->clks[i]))
962 			break;
963 	}
964 
965 	mdp_get_subsys_id(mdp, dev, node, comp);
966 
967 	/* Set GCE SOF event */
968 	if (is_bypass_gce_event(comp->type) ||
969 	    of_property_read_u32_index(node, "mediatek,gce-events",
970 				       MDP_GCE_EVENT_SOF, &event))
971 		event = MDP_GCE_NO_EVENT;
972 
973 	comp->gce_event[MDP_GCE_EVENT_SOF] = event;
974 
975 	/* Set GCE EOF event */
976 	if (is_dma_capable(comp->type)) {
977 		if (of_property_read_u32_index(node, "mediatek,gce-events",
978 					       MDP_GCE_EVENT_EOF, &event)) {
979 			dev_err(dev, "Component id %d has no EOF\n", id);
980 			return -EINVAL;
981 		}
982 	} else {
983 		event = MDP_GCE_NO_EVENT;
984 	}
985 
986 	comp->gce_event[MDP_GCE_EVENT_EOF] = event;
987 
988 	return 0;
989 }
990 
991 static void mdp_comp_deinit(struct mdp_comp *comp)
992 {
993 	if (!comp)
994 		return;
995 
996 	if (comp->comp_dev && comp->clks) {
997 		devm_kfree(&comp->mdp_dev->pdev->dev, comp->clks);
998 		comp->clks = NULL;
999 	}
1000 
1001 	if (comp->regs)
1002 		iounmap(comp->regs);
1003 }
1004 
1005 static struct mdp_comp *mdp_comp_create(struct mdp_dev *mdp,
1006 					struct device_node *node,
1007 					enum mtk_mdp_comp_id id)
1008 {
1009 	struct device *dev = &mdp->pdev->dev;
1010 	struct mdp_comp *comp;
1011 	int ret;
1012 
1013 	if (mdp->comp[id])
1014 		return ERR_PTR(-EEXIST);
1015 
1016 	comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
1017 	if (!comp)
1018 		return ERR_PTR(-ENOMEM);
1019 
1020 	ret = mdp_comp_init(mdp, node, comp, id);
1021 	if (ret) {
1022 		devm_kfree(dev, comp);
1023 		return ERR_PTR(ret);
1024 	}
1025 	mdp->comp[id] = comp;
1026 	mdp->comp[id]->mdp_dev = mdp;
1027 
1028 	dev_dbg(dev, "%s type:%d alias:%d public id:%d inner id:%d base:%#x regs:%p\n",
1029 		dev->of_node->name, comp->type, comp->alias_id, id, comp->inner_id,
1030 		(u32)comp->reg_base, comp->regs);
1031 	return comp;
1032 }
1033 
1034 static int mdp_comp_sub_create(struct mdp_dev *mdp)
1035 {
1036 	struct device *dev = &mdp->pdev->dev;
1037 	struct device_node *node, *parent;
1038 	int ret = 0;
1039 
1040 	parent = dev->of_node->parent;
1041 
1042 	for_each_child_of_node(parent, node) {
1043 		const struct of_device_id *of_id;
1044 		enum mdp_comp_type type;
1045 		int id, alias_id;
1046 		struct mdp_comp *comp;
1047 
1048 		of_id = of_match_node(mdp->mdp_data->mdp_sub_comp_dt_ids, node);
1049 		if (!of_id)
1050 			continue;
1051 		if (!of_device_is_available(node)) {
1052 			dev_dbg(dev, "Skipping disabled sub comp. %pOF\n",
1053 				node);
1054 			continue;
1055 		}
1056 
1057 		type = (enum mdp_comp_type)(uintptr_t)of_id->data;
1058 		alias_id = mdp_comp_alias_id[type];
1059 		id = mdp_comp_get_id(mdp, type, alias_id);
1060 		if (id < 0) {
1061 			dev_err(dev,
1062 				"Fail to get sub comp. id: type %d alias %d\n",
1063 				type, alias_id);
1064 			ret = -EINVAL;
1065 			goto err_free_node;
1066 		}
1067 		mdp_comp_alias_id[type]++;
1068 
1069 		comp = mdp_comp_create(mdp, node, id);
1070 		if (IS_ERR(comp)) {
1071 			ret = PTR_ERR(comp);
1072 			goto err_free_node;
1073 		}
1074 	}
1075 	return ret;
1076 
1077 err_free_node:
1078 	of_node_put(node);
1079 	return ret;
1080 }
1081 
1082 void mdp_comp_destroy(struct mdp_dev *mdp)
1083 {
1084 	int i;
1085 
1086 	for (i = 0; i < ARRAY_SIZE(mdp->comp); i++) {
1087 		if (mdp->comp[i]) {
1088 			if (is_dma_capable(mdp->comp[i]->type))
1089 				pm_runtime_disable(mdp->comp[i]->comp_dev);
1090 			mdp_comp_deinit(mdp->comp[i]);
1091 			devm_kfree(mdp->comp[i]->comp_dev, mdp->comp[i]);
1092 			mdp->comp[i] = NULL;
1093 		}
1094 	}
1095 }
1096 
1097 int mdp_comp_config(struct mdp_dev *mdp)
1098 {
1099 	struct device *dev = &mdp->pdev->dev;
1100 	struct device_node *node, *parent;
1101 	int ret;
1102 
1103 	memset(mdp_comp_alias_id, 0, sizeof(mdp_comp_alias_id));
1104 	p_id = mdp->mdp_data->mdp_plat_id;
1105 
1106 	parent = dev->of_node->parent;
1107 	/* Iterate over sibling MDP function blocks */
1108 	for_each_child_of_node(parent, node) {
1109 		const struct of_device_id *of_id;
1110 		enum mdp_comp_type type;
1111 		int id, alias_id;
1112 		struct mdp_comp *comp;
1113 
1114 		of_id = of_match_node(mdp_comp_dt_ids, node);
1115 		if (!of_id)
1116 			continue;
1117 
1118 		if (!of_device_is_available(node)) {
1119 			dev_dbg(dev, "Skipping disabled component %pOF\n",
1120 				node);
1121 			continue;
1122 		}
1123 
1124 		type = (enum mdp_comp_type)(uintptr_t)of_id->data;
1125 		alias_id = mdp_comp_alias_id[type];
1126 		id = mdp_comp_get_id(mdp, type, alias_id);
1127 		if (id < 0) {
1128 			dev_err(dev,
1129 				"Fail to get component id: type %d alias %d\n",
1130 				type, alias_id);
1131 			continue;
1132 		}
1133 		mdp_comp_alias_id[type]++;
1134 
1135 		comp = mdp_comp_create(mdp, node, id);
1136 		if (IS_ERR(comp)) {
1137 			ret = PTR_ERR(comp);
1138 			goto err_init_comps;
1139 		}
1140 
1141 		/* Only DMA capable components need the pm control */
1142 		if (!is_dma_capable(comp->type))
1143 			continue;
1144 		pm_runtime_enable(comp->comp_dev);
1145 	}
1146 
1147 	ret = mdp_comp_sub_create(mdp);
1148 	if (ret)
1149 		goto err_init_comps;
1150 
1151 	return 0;
1152 
1153 err_init_comps:
1154 	mdp_comp_destroy(mdp);
1155 	return ret;
1156 }
1157 
1158 int mdp_comp_ctx_config(struct mdp_dev *mdp, struct mdp_comp_ctx *ctx,
1159 			const struct img_compparam *param,
1160 			const struct img_ipi_frameparam *frame)
1161 {
1162 	struct device *dev = &mdp->pdev->dev;
1163 	enum mtk_mdp_comp_id public_id = MDP_COMP_NONE;
1164 	u32 arg;
1165 	int i, idx;
1166 
1167 	if (!param) {
1168 		dev_err(dev, "Invalid component param");
1169 		return -EINVAL;
1170 	}
1171 
1172 	if (CFG_CHECK(MT8183, p_id))
1173 		arg = CFG_COMP(MT8183, param, type);
1174 	else
1175 		return -EINVAL;
1176 	public_id = mdp_cfg_get_id_public(mdp, arg);
1177 	if (public_id < 0) {
1178 		dev_err(dev, "Invalid component id %d", public_id);
1179 		return -EINVAL;
1180 	}
1181 
1182 	ctx->comp = mdp->comp[public_id];
1183 	if (!ctx->comp) {
1184 		dev_err(dev, "Uninit component inner id %d", arg);
1185 		return -EINVAL;
1186 	}
1187 
1188 	ctx->param = param;
1189 	if (CFG_CHECK(MT8183, p_id))
1190 		arg = CFG_COMP(MT8183, param, input);
1191 	else
1192 		return -EINVAL;
1193 	ctx->input = &frame->inputs[arg];
1194 	if (CFG_CHECK(MT8183, p_id))
1195 		idx = CFG_COMP(MT8183, param, num_outputs);
1196 	else
1197 		return -EINVAL;
1198 	for (i = 0; i < idx; i++) {
1199 		if (CFG_CHECK(MT8183, p_id))
1200 			arg = CFG_COMP(MT8183, param, outputs[i]);
1201 		else
1202 			return -EINVAL;
1203 		ctx->outputs[i] = &frame->outputs[arg];
1204 	}
1205 	return 0;
1206 }
1207